aboutsummaryrefslogtreecommitdiff
path: root/game
diff options
context:
space:
mode:
Diffstat (limited to 'game')
-rw-r--r--game/constants.h4
-rw-r--r--game/entity.cpp10
-rw-r--r--game/entity.h16
-rw-r--r--game/gst.cpp76
-rw-r--r--game/gst.h13
-rw-r--r--game/load.cpp28
-rw-r--r--game/playercontrol.cpp23
7 files changed, 129 insertions, 41 deletions
diff --git a/game/constants.h b/game/constants.h
index 7ea34e0..2ba343a 100644
--- a/game/constants.h
+++ b/game/constants.h
@@ -8,6 +8,10 @@ namespace constants {
const int col_bad_r = 255;
const int col_bad_g = 120;
const int col_bad_b = 0;
+
+ const float menu_attack_margin_amt = 60;
+ const float menu_attack_margin_arrow = 80;
+ const float menu_attack_margin_mod = 93;
}
#endif \ No newline at end of file
diff --git a/game/entity.cpp b/game/entity.cpp
index 8362c40..f127150 100644
--- a/game/entity.cpp
+++ b/game/entity.cpp
@@ -1,3 +1,11 @@
#include "entity.h"
#include <iostream>
-; \ No newline at end of file
+
+
+int EntityClass::from_string (std::string str) {
+ if (str == "inf") return EntityInfo::Class::inf;
+ if (str == "cav") return EntityInfo::Class::cav;
+ if (str == "ran") return EntityInfo::Class::ran;
+ if (str == "sie") return EntityInfo::Class::sie;
+ if (str == "bld") return EntityInfo::Class::bld;
+} \ No newline at end of file
diff --git a/game/entity.h b/game/entity.h
index 50c7acc..8f61cee 100644
--- a/game/entity.h
+++ b/game/entity.h
@@ -13,6 +13,9 @@ class EntityInfo {
public:
EntityInfo() { spritebounds = vec2 { 16*6, 16 }; }
+ enum Class { inf, cav, ran, sie, bld };
+ Class ent_class;
+
std::string name;
int id;
@@ -27,21 +30,23 @@ class EntityInfo {
int unit;
std::vector<int> abilities;
std::vector<int> build;
- std::vector<int> train;
+ std::vector<int> train_id;
+ std::vector<Class> train_class;
std::vector<float> prod { 0, 0 };
std::vector<float> cost { 0, 0 };
std::vector<int> adjacent;
-
+ float defence_bonus { 0 };
int upgrade { -1 };
- enum Class { inf, cav, ran, sie, bld };
- Class ent_class;
-
vec2 spritebounds;
};
+namespace EntityClass {
+ int from_string(std::string str);
+}
+
class Entity {
public:
Entity(int x, int y, EntityInfo *info, int owner)
@@ -58,6 +63,7 @@ class Entity {
bool done = false;
int moved;
EntityInfo *info;
+ int fights { 0 };
int owner;
};
diff --git a/game/gst.cpp b/game/gst.cpp
index 5c7485b..3c0c1de 100644
--- a/game/gst.cpp
+++ b/game/gst.cpp
@@ -3,6 +3,7 @@
#include <map>
#include <iostream>
+
Player& Gst::get_player (int id) {
for (auto &player : players) {
if (id == player.id) return player;
@@ -80,6 +81,8 @@ float Gst::get_type_bonus (Entity &atk, Entity &def) {
return b;
}
+int Gst::get_vet_level (Entity &ent) { return std::min(3, ent.fights/3); }
+
std::vector<Bonus> Gst::get_bonuses (Entity &atk, Entity &def) {
std::vector<Bonus> bs;
if (tiles[ground.tiles[ground.at(atk.x, atk.y)]].attack_bonus != 0) {
@@ -93,13 +96,23 @@ std::vector<Bonus> Gst::get_bonuses (Entity &atk, Entity &def) {
tiles[ground.tiles[ground.at(def.x, def.y)]].defence_bonus,
Bonus::Id::ground, false);
}
+
+ if (check_obstructed(def)) {
+ for (Entity &e : entities) {
+ if (&def != &e && e.x == def.x && def.y == e.y) {
+ bs.emplace_back(e.info->defence_bonus,
+ Bonus::Id::on_bld, false);
+ }
+ }
+ }
if (get_type_bonus(atk, def) != 0) {
bs.emplace_back(get_type_bonus(atk, def), Bonus::Id::type, true);
}
+ /* only attack bonuses
if (get_type_bonus(def, atk) != 0) {
bs.emplace_back(get_type_bonus(def, atk), Bonus::Id::type, false);
- }
+ }*/
if (info_has_ability(atk.info, "Causes Fear"))
bs.emplace_back(-1.0f/3, Bonus::Id::ability, false);
@@ -132,7 +145,6 @@ std::vector<Bonus> Gst::get_bonuses (Entity &atk, Entity &def) {
if (info_has_ability(atk.info, "Frenzy"))
bs.emplace_back(1/atk.hp, Bonus::Id::ability, true);
-
Player &player_atk = players[atk.owner];
Player &player_def = players[def.owner];
float tech_attack = player_atk.tech_lookup.id(atk.info->id).attack;
@@ -142,6 +154,13 @@ std::vector<Bonus> Gst::get_bonuses (Entity &atk, Entity &def) {
if (tech_defence != 0)
bs.emplace_back(tech_defence, Bonus::Id::tech, false);
+ float atk_vet = get_vet_level(atk) * 0.15f;
+ if (atk_vet > 0)
+ bs.emplace_back(atk_vet, Bonus::Id::veteran, true);
+ float def_vet = get_vet_level(def) * 0.15f;
+ if (def_vet > 0)
+ bs.emplace_back(def_vet, Bonus::Id::veteran, false);
+
return bs;
}
@@ -243,6 +262,9 @@ void Gst::battle (Entity &atk, Entity &def) {
atk.hp = result.atk_hp;
def.hp = result.def_hp;
+ if (atk.info->unit == 1) atk.fights += 1;
+ if (def.info->unit == 1) def.fights += 1;
+
std::cout << "! result " << atk.info->name << "(hp:" << atk.hp << "), "
<< def.info->name << "(hp:" << def.hp << ") \n";
clear_dead();
@@ -267,6 +289,49 @@ int Gst::get_range (Entity &ent) {
return range;
}
+std::vector<int> Gst::get_possible_trains (Entity &ent) {
+ Player &player = get_player(ent.owner);
+ auto &cls = ent.info->train_class;
+ std::vector<int> trains;
+ if (ent.info->id == 107) { // market special case
+ std::vector<int> candidates;
+ for (EntityInfo &info : infos) {
+ if (info.id == 0) continue; // villager only in train_id
+ if (info.level > player.level) continue;
+ if (info.level < player.level && info.upgrade != -1) continue;
+ if (std::find(cls.begin(), cls.end(), info.ent_class) != cls.end())
+ {
+ candidates.push_back(info.id);
+ }
+ }
+ std::shuffle(candidates.begin(), candidates.end(), engine);
+ // pick 3 cands at random
+ for (int i=0; i<3; i++) trains.push_back(candidates[i]);
+ return trains;
+ }
+
+ for (int id : ent.info->train_id) {
+ if (get_info(id)->level > player.level) {
+ trains.push_back(id);
+ }
+ }
+
+ // get all train class ids, highest upgrade level
+ for (EntityInfo &info : infos) {
+ if (info.id == 0) continue; // villager only in train_id
+ if (info.level > player.level) continue;
+ if (info.level < player.level && info.upgrade != -1) continue;
+ if (std::find(cls.begin(), cls.end(), info.ent_class) != cls.end()) {
+ if (std::find(trains.begin(), trains.end(), info.id)
+ == trains.end())
+ {
+ trains.push_back(info.id);
+ }
+ }
+ }
+ return trains;
+}
+
std::vector<int> Gst::get_possible_builds (Entity &ent) {
std::vector<int> builds;
for (int id : ent.info->build) {
@@ -308,7 +373,6 @@ bool Gst::check_req_build(Entity &ent, EntityInfo *info) {
}
}
}
- std::cout << " " << mindist;
if (mindist < 5) {
return false;
}
@@ -335,12 +399,6 @@ bool Gst::check_req_build(Entity &ent, EntityInfo *info) {
return true;
}
-bool Gst::check_req_train (Entity &ent, EntityInfo *info) {
- Player &player = players[ent.owner];
- if (player.level < info->level) return false;
- return true;
-}
-
bool Gst::check_req_tech (Tech *tech, Player &player) {
if (player.leveling_up == 1) return false;
diff --git a/game/gst.h b/game/gst.h
index c9c5d3c..82f4b07 100644
--- a/game/gst.h
+++ b/game/gst.h
@@ -7,6 +7,8 @@
#include <vector>
#include <functional>
+#include <random> // just for picking market trains
+
#include "ground.h"
#include "entity.h"
#include "tile.h"
@@ -23,13 +25,16 @@ class Bonus {
public:
Bonus(float amt, int id, bool atk) : amt(amt), id(id), atk(atk) {}
float amt; int id; bool atk;
- enum Id { ground, type, ability, tech };
+ enum Id { ground, type, ability, tech, veteran, on_bld, adjacency };
std::string id_string () {
switch (id) {
case ground: return "Ground";
case type: return "Class";
case ability: return "Ability";
case tech: return "Tech";
+ case veteran: return "Veteran";
+ case on_bld: return "On Building";
+ case adjacency: return "Adjacency";
}
}
};
@@ -42,8 +47,9 @@ class BattleResult {
};
class Gst {
+ private: std::default_random_engine engine = std::default_random_engine{};
public:
- Gst(int sx, int sy) : ground(sx, sy) {}
+ Gst(int sx, int sy) : ground(sx, sy) { }
std::vector<Tech> techs;
std::vector<Ability> abilities;
@@ -63,6 +69,7 @@ class Gst {
std::vector<float> get_cost (EntityInfo *info, Player &player);
float get_trade_rate (Player &player);
+ int get_vet_level (Entity &ent);
float get_type_bonus (Entity &atk, Entity &def);
std::vector<Bonus> get_bonuses (Entity &atk, Entity &def);
float get_damage (Entity &atk, Entity &def);
@@ -73,10 +80,10 @@ class Gst {
void clear_dead();
int get_range(Entity &ent);
+ std::vector<int> get_possible_trains (Entity &ent);
std::vector<int> get_possible_builds (Entity &ent);
bool check_req_build (Entity &ent, EntityInfo *info);
- bool check_req_train (Entity &ent, EntityInfo *info);
bool check_req_tech (Tech *tech, Player &player);
bool check_req_level (Player &player);
bool check_obstructed (Entity &ent);
diff --git a/game/load.cpp b/game/load.cpp
index c9c9132..16f0911 100644
--- a/game/load.cpp
+++ b/game/load.cpp
@@ -69,18 +69,18 @@ void load_json (Gst &gst) {
for (auto blds : it["build"]) {
ent.build.push_back(blds);
}
- for (auto train : it["train"]) {
- ent.train.push_back(train);
+ for (auto train : it["train_id"]) {
+ ent.train_id.push_back(train);
+ }
+ for (auto train : it["train_class"]) {
+ ent.train_class.push_back((EntityInfo::Class)
+ EntityClass::from_string(train.get<std::string>()));
}
for (auto ad : it["adjacent"]) {
ent.adjacent.push_back(ad);
}
- std::string cl = it["class"];
- if (cl == "inf") ent.ent_class = EntityInfo::Class::inf;
- if (cl == "cav") ent.ent_class = EntityInfo::Class::cav;
- if (cl == "ran") ent.ent_class = EntityInfo::Class::ran;
- if (cl == "sie") ent.ent_class = EntityInfo::Class::sie;
- if (cl == "bld") ent.ent_class = EntityInfo::Class::bld;
+ ent.ent_class = (EntityInfo::Class) EntityClass::from_string(
+ it["class"].get<std::string>());
for (auto ab : it["abilities"]) {
int index = 0;
for (int i=0; i<gst.abilities.size(); i++) {
@@ -90,6 +90,9 @@ void load_json (Gst &gst) {
}
ent.spritebounds = vec2 { it["spritebounds"][0], it["spritebounds"][1] };
if (it.contains("upgrade")) { ent.upgrade = it["upgrade"]; }
+ if (it.contains("defence_bonus")) {
+ ent.defence_bonus = it["defence_bonus"];
+ }
gst.infos.push_back(ent);
}
@@ -126,13 +129,8 @@ void load_json (Gst &gst) {
for (auto v : b["aff_id"]) { tech.bonus.aff_id.push_back(v); }
for (auto v : b["aff_class"]) {
- int w = -1;
- if (v == "inf") w = EntityInfo::Class::inf;
- if (v == "cav") w = EntityInfo::Class::cav;
- if (v == "ran") w = EntityInfo::Class::ran;
- if (v == "sie") w = EntityInfo::Class::sie;
- if (v == "bld") w = EntityInfo::Class::bld;
- tech.bonus.aff_class.push_back(w);
+ tech.bonus.aff_class.push_back(EntityClass::from_string(
+ v.get<std::string>()));
}
if (b.contains("aff_level")) {
tech.bonus.aff_level = b["aff_level"];
diff --git a/game/playercontrol.cpp b/game/playercontrol.cpp
index 284c6ff..23c9f3e 100644
--- a/game/playercontrol.cpp
+++ b/game/playercontrol.cpp
@@ -31,7 +31,7 @@ void open_unit_menu (Gst &gst, View &view, Fsm &fsm, int p) {
view.menu_unit.options.emplace_back("Done",
Menu_unit::Opts::done);
} else {
- if (ent.info->train.size()
+ if (gst.get_possible_trains(ent).size()
&& !gst.check_obstructed(ent))
{
view.menu_unit.options.emplace_back("Train",
@@ -157,14 +157,17 @@ Player_control::Player_control () {
Entity &ent = gst.entities[view.selected_entity];
Player &player = gst.players[ent.owner];
view.menu_train.options.clear();
- for (int id : ent.info->train) {
+ auto trains = gst.get_possible_trains(ent);
+ for (int id : trains) {
EntityInfo *info = gst.get_info(id);
- if (gst.check_req_train(ent, info)) {
- std::cout << id << " " << gst.get_info(id)->name << "\n";
- Option opt { info->name, id };
- opt.cost = gst.get_cost(info, player);
- view.menu_train.options.push_back(opt);
+ std::cout << id << " " << gst.get_info(id)->name << "\n";
+ Option opt { info->name, id };
+ opt.cost = gst.get_cost(info, player);
+ if (ent.info->id == 107) { // market
+ // tech.id = 31 -> merc network
+ opt.cost[1] += 50 - (int)player.has_tech(31)*25;
}
+ view.menu_train.options.push_back(opt);
}
view.menu_train.open(view.res);
return menu_train;
@@ -173,6 +176,10 @@ Player_control::Player_control () {
fsm.arcs.emplace_back(
menu_train, opt, -1,
[](Gst &gst, View &view, Fsm &fsm, int p) {
+ std::vector<float> cost { -1, -1 };
+ for (auto o : view.menu_train.options) {
+ if (o.id == p) {cost = o.cost; break; }
+ }
view.menu_train.close();
Entity &ent = gst.entities[view.selected_entity];
ent.done = true;
@@ -182,7 +189,7 @@ Player_control::Player_control () {
entb.hp = 50;
gst.entities.push_back(entb);
Player &player = gst.players[gst.turn];
- player.pay(gst.get_cost(entb.info, player));
+ player.pay(cost);
view.selected_entity = -1;
return select;
}