diff options
Diffstat (limited to 'game')
-rw-r--r-- | game/constants.h | 4 | ||||
-rw-r--r-- | game/entity.cpp | 10 | ||||
-rw-r--r-- | game/entity.h | 16 | ||||
-rw-r--r-- | game/gst.cpp | 76 | ||||
-rw-r--r-- | game/gst.h | 13 | ||||
-rw-r--r-- | game/load.cpp | 28 | ||||
-rw-r--r-- | game/playercontrol.cpp | 23 |
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; @@ -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; } |