diff options
Diffstat (limited to 'game')
-rw-r--r-- | game/entity.h | 1 | ||||
-rw-r--r-- | game/ground.cpp | 30 | ||||
-rw-r--r-- | game/ground.h | 2 | ||||
-rw-r--r-- | game/gst.cpp | 63 | ||||
-rw-r--r-- | game/gst.h | 31 | ||||
-rw-r--r-- | game/load.cpp | 12 | ||||
-rw-r--r-- | game/menu.h | 2 | ||||
-rw-r--r-- | game/playercontrol.cpp | 66 | ||||
-rw-r--r-- | game/playercontrol.h | 1 | ||||
-rw-r--r-- | game/tech.cpp | 2 | ||||
-rw-r--r-- | game/tech.h | 71 | ||||
-rw-r--r-- | game/view.cpp | 28 | ||||
-rw-r--r-- | game/view.h | 2 |
13 files changed, 279 insertions, 32 deletions
diff --git a/game/entity.h b/game/entity.h index 8f61cee..62e352e 100644 --- a/game/entity.h +++ b/game/entity.h @@ -37,6 +37,7 @@ class EntityInfo { std::vector<float> cost { 0, 0 }; std::vector<int> adjacent; + std::vector<int> diagonal; float defence_bonus { 0 }; int upgrade { -1 }; diff --git a/game/ground.cpp b/game/ground.cpp index 4308047..1cadd9b 100644 --- a/game/ground.cpp +++ b/game/ground.cpp @@ -98,9 +98,37 @@ std::vector<int> Ground::attack_targets (Gst &gst, Entity &ent) { for (Entity &e : gst.entities) { if (!units && e.info->unit == 1) continue; if (!builds && e.info->unit == 0) continue; - if (e.owner != ent.owner && abs(e.x-ent.x)+abs(e.y-ent.y) <= range) { + int dist = abs(e.x-ent.x)+abs(e.y-ent.y); + if (dist > 0 && e.owner != ent.owner && dist <= range) { attacks.push_back(at(e.x, e.y)); } } return attacks; +} + +std::vector<int> Ground::heal_targets (Gst &gst, Entity &ent) { + std::vector<int> heals; + int range = gst.get_range(ent); + for (Entity &e : gst.entities) { + if (e.info->unit == 0) continue; + if (e.info->ent_class == EntityInfo::Class::sie) continue; + int dist = abs(e.x-ent.x)+abs(e.y-ent.y); + if (dist > 0 && e.owner == ent.owner && dist <= range) { + heals.push_back(at(e.x, e.y)); + } + } + return heals; +} + +std::vector<int> Ground::convert_targets (Gst &gst, Entity &ent) { + std::vector<int> converts; + int range = gst.get_range(ent); + for (Entity &e : gst.entities) { + if (e.info->unit == 0) continue; + int dist = abs(e.x-ent.x)+abs(e.y-ent.y); + if (dist > 0 && e.owner != ent.owner && dist <= range) { + converts.push_back(at(e.x, e.y)); + } + } + return converts; }
\ No newline at end of file diff --git a/game/ground.h b/game/ground.h index c9f997b..ab8f0e8 100644 --- a/game/ground.h +++ b/game/ground.h @@ -29,6 +29,8 @@ class Ground { std::vector<int> star (int pos); std::vector<int> move_area (Gst &gst, Entity &ent); std::vector<int> attack_targets (Gst &gst, Entity &ent); + std::vector<int> heal_targets (Gst &gst, Entity &ent); + std::vector<int> convert_targets (Gst &gst, Entity &ent); }; #endif
\ No newline at end of file diff --git a/game/gst.cpp b/game/gst.cpp index 3c0c1de..886dcc7 100644 --- a/game/gst.cpp +++ b/game/gst.cpp @@ -43,6 +43,8 @@ Entity& Gst::get_at (int x, int y) { std::vector<float> Gst::get_cost (EntityInfo *info, Player &player) { std::vector<float> cost = info->cost; + + std::cout << "cost : " << player.tech_lookup.id(info->id).cost[0] << " " << player.tech_lookup.id(info->id).cost[1] << "\n"; for (int i=0; i<info->cost.size(); i++) { cost[i] *= 1+player.tech_lookup.id(info->id).cost[i]; cost[i] += player.tech_lookup.id(info->id).cost_abs[i]; @@ -289,6 +291,29 @@ int Gst::get_range (Entity &ent) { return range; } + +void Gst::heal (Entity &atk, Entity &def) { + Player &player = get_player(atk.owner); + float amt = 20; + if (atk.info->level == 3) { amt += 10; } // improved heal + if (player.has_tech(52)) { amt += 10; } // tech illumination + def.hp = clamp_hp(def.hp + amt); +} + +void Gst::convert (Entity &atk, Entity &def) { + Player &player = get_player(atk.owner); + float amt = 0.20f; + if (player.has_tech(53)) { amt += 0.10f; } // tech faith + // caution, randomness + std::uniform_real_distribution<float> odds(0, 1); + float value = odds(engine); + std::cout << value << " / " << amt << " odds\n"; + if (value < amt) { + def.owner = atk.owner; + } +} + + std::vector<int> Gst::get_possible_trains (Entity &ent) { Player &player = get_player(ent.owner); auto &cls = ent.info->train_class; @@ -309,13 +334,14 @@ std::vector<int> Gst::get_possible_trains (Entity &ent) { 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); - } + auto info = get_info(id); + if (info->level > player.level) continue; + if (info->level < player.level && info->upgrade != -1) continue; + 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 @@ -323,12 +349,12 @@ std::vector<int> Gst::get_possible_trains (Entity &ent) { 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.end()) { trains.push_back(info.id); } } - } + }*/ return trains; } @@ -358,6 +384,19 @@ bool Gst::check_req_build(Entity &ent, EntityInfo *info) { } if (!adj) return false; } + for (int id : info->diagonal) { + bool diag = false; + for (Entity &e : entities) { + if (e.info->id == id && ent.owner == e.owner) { + int dx = abs(e.x-ent.x), dy = abs(e.y-ent.y); + int dist = dx + dy; + if (dx == 1 && dy == 1) { + diag = true; + } + } + } + if (!diag) return false; + } if (info->id == 100) { for (Resource &r : ground.resources) { if (r.pos == ground.at(ent.x, ent.y)) { @@ -511,8 +550,10 @@ void Gst::update_tech_lookup (Player &player) { for (int i : player.techs) { Tech *tech = get_tech(i); std::vector<int> ids { }; + bool noaff = true; if (tech->bonus.aff_id.size() > 0) { ids = tech->bonus.aff_id; + noaff = false; } else { if (tech->bonus.aff_level != -1) { for (EntityInfo info : infos) { @@ -520,6 +561,7 @@ void Gst::update_tech_lookup (Player &player) { ids.push_back(info.id); } } + noaff = false; } if (tech->bonus.aff_class.size() > 0) { for (EntityInfo info : infos) { @@ -530,13 +572,10 @@ void Gst::update_tech_lookup (Player &player) { ids.push_back(info.id); } } - } - if (tech->bonus.aff_all == 1) { - for (EntityInfo info : infos) { - ids.push_back(info.id); - } + noaff = false; } } + if (noaff) { for (auto info : infos) ids.push_back(info.id); } for (int id : ids) { player.tech_lookup.map_id[id] = player.tech_lookup.map_id[id] + tech->bonus; @@ -46,20 +46,32 @@ class BattleResult { float atk_hp, def_hp; }; -class Gst { - private: std::default_random_engine engine = std::default_random_engine{}; +class Inv { public: - Gst(int sx, int sy) : ground(sx, sy) { } + Inv () {} std::vector<Tech> techs; std::vector<Ability> abilities; std::vector<EntityInfo> infos; std::vector<Tile> tiles; - std::vector<Entity> entities; Ground ground; + private: + std::default_random_engine engine = std::default_random_engine{}; +} + +class Gst { + public: + Gst() { } + + Inv *inv; + + std::vector<Entity> entities; std::vector<Player> players; + int turn { 0 }; + int day { 0 }; + Player& get_player (int id); Tech* get_tech (int id); EntityInfo* get_info (std::string name); @@ -76,11 +88,15 @@ class Gst { float get_damage (Entity &atk, Entity &def, float atk_hp); bool get_first_strike (Entity &atk, Entity &def); BattleResult battle_res (Entity &atk, Entity &def); - void battle (Entity &atk, Entity &def); void clear_dead(); int get_range(Entity &ent); - std::vector<int> get_possible_trains (Entity &ent); + void battle (Entity &atk, Entity &def); + + void heal (Entity &atk, Entity &def); + void convert (Entity &atk, Entity &def); + + std::vector<int> get_possible_trains (Entity &ent); std::vector<int> get_possible_builds (Entity &ent); bool check_req_build (Entity &ent, EntityInfo *info); @@ -88,9 +104,6 @@ class Gst { bool check_req_level (Player &player); bool check_obstructed (Entity &ent); - int turn { 0 }; - int day { 0 }; - void end_day (); void level_upgrade (Player &player); diff --git a/game/load.cpp b/game/load.cpp index 16f0911..4b58ff0 100644 --- a/game/load.cpp +++ b/game/load.cpp @@ -79,6 +79,9 @@ void load_json (Gst &gst) { for (auto ad : it["adjacent"]) { ent.adjacent.push_back(ad); } + for (auto ad : it["diagonal"]) { + ent.diagonal.push_back(ad); + } ent.ent_class = (EntityInfo::Class) EntityClass::from_string( it["class"].get<std::string>()); for (auto ab : it["abilities"]) { @@ -118,13 +121,16 @@ void load_json (Gst &gst) { tech.bonus.req_range = b["req_range"]; } if (b.contains("improved_heal")) { - tech.bonus.attack = b["improved_heal"]; + tech.bonus.improved_heal = b["improved_heal"]; } if (b.contains("improved_convert")) { - tech.bonus.attack = b["improved_convert"]; + tech.bonus.improved_convert = b["improved_convert"]; } + if (b.contains("cost")) tech.bonus.cost.clear(); for (auto v : b["cost"]) { tech.bonus.cost.push_back(v); } + if (b.contains("cost_abs")) tech.bonus.cost_abs.clear(); for (auto v : b["cost_abs"]) { tech.bonus.cost_abs.push_back(v); } + if (b.contains("prod")) tech.bonus.prod.clear(); for (auto v : b["prod"]) { tech.bonus.prod.push_back(v); } for (auto v : b["aff_id"]) { tech.bonus.aff_id.push_back(v); } @@ -139,6 +145,8 @@ void load_json (Gst &gst) { tech.bonus.aff_all = b["aff_all"]; } } + + std::cout << tech.id << tech.bonus.to_string() << std::endl; gst.techs.push_back(tech); } }
\ No newline at end of file diff --git a/game/menu.h b/game/menu.h index 3da0c46..41348a7 100644 --- a/game/menu.h +++ b/game/menu.h @@ -35,7 +35,7 @@ class Menu_unit : public Menu { Menu_unit () {} enum Opts { - move, attack, done, build, train, trade, age_up + move, attack, done, build, train, trade, age_up, heal, convert }; }; diff --git a/game/playercontrol.cpp b/game/playercontrol.cpp index 23c9f3e..2aa9264 100644 --- a/game/playercontrol.cpp +++ b/game/playercontrol.cpp @@ -28,6 +28,18 @@ void open_unit_menu (Gst &gst, View &view, Fsm &fsm, int p) { view.menu_unit.options.emplace_back("Build", Menu_unit::Opts::build); } + if (gst.ground.heal_targets(gst, ent).size() > 0 + && (gst.info_has_ability(ent.info, "Heal"))) + { + view.menu_unit.options.emplace_back("Heal", + Menu_unit::Opts::heal); + } + if (gst.ground.convert_targets(gst, ent).size() > 0 + && (gst.info_has_ability(ent.info, "Convert"))) + { + view.menu_unit.options.emplace_back("Convert", + Menu_unit::Opts::convert); + } view.menu_unit.options.emplace_back("Done", Menu_unit::Opts::done); } else { @@ -358,6 +370,60 @@ Player_control::Player_control () { } ); fsm.arcs.emplace_back( + menu_unit, opt, Menu_unit::Opts::heal, + [](Gst &gst, View &view, Fsm &fsm, int p) { + Player &player = gst.players[gst.turn]; + view.menu_unit.close(); + Entity &ent = gst.entities[view.selected_entity]; + view.heals = gst.ground.heal_targets(gst, ent); + std::cout << "heal targeting " << p << "\n"; + return target_heal; + } + ); + fsm.arcs.emplace_back( + target_heal, sel_ground, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + std::cout << "healed " << p << "\n"; + Entity &atk = gst.entities[view.selected_entity]; + int x = view.cursor_ground % gst.ground.sizex; + int y = view.cursor_ground / gst.ground.sizex; + std::cout << "selg " << x << " " << y << "\n"; + Entity &def = gst.get_at(x, y); + atk.done = true; + gst.heal(atk, def); + view.heals.clear(); + view.selected_entity = -1; + return select; + } + ); + fsm.arcs.emplace_back( + menu_unit, opt, Menu_unit::Opts::convert, + [](Gst &gst, View &view, Fsm &fsm, int p) { + Player &player = gst.players[gst.turn]; + view.menu_unit.close(); + Entity &ent = gst.entities[view.selected_entity]; + view.converts = gst.ground.convert_targets(gst, ent); + std::cout << "convert targeting " << p << "\n"; + return target_convert; + } + ); + fsm.arcs.emplace_back( + target_convert, sel_ground, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + std::cout << "converted " << p << "\n"; + Entity &atk = gst.entities[view.selected_entity]; + int x = view.cursor_ground % gst.ground.sizex; + int y = view.cursor_ground / gst.ground.sizex; + std::cout << "selg " << x << " " << y << "\n"; + Entity &def = gst.get_at(x, y); + atk.done = true; + gst.convert(atk, def); + view.converts.clear(); + view.selected_entity = -1; + return select; + } + ); + fsm.arcs.emplace_back( menu_unit, opt, Menu_unit::Opts::done, [](Gst &gst, View &view, Fsm &fsm, int p) { view.menu_unit.close(); diff --git a/game/playercontrol.h b/game/playercontrol.h index 6d12026..c0075d4 100644 --- a/game/playercontrol.h +++ b/game/playercontrol.h @@ -27,6 +27,7 @@ enum pc_state { target_build, merge_target, target_heal, + target_convert, menu_power, target_power, menu_unit, diff --git a/game/tech.cpp b/game/tech.cpp index c556dfe..848b211 100644 --- a/game/tech.cpp +++ b/game/tech.cpp @@ -1 +1 @@ -#include "tech.h"
\ No newline at end of file +#include "tech.h" diff --git a/game/tech.h b/game/tech.h index cb5e769..b22b173 100644 --- a/game/tech.h +++ b/game/tech.h @@ -5,6 +5,10 @@ #include <unordered_map> #include <string> +#include <math.h> + +#include <iostream> + #include "../umath/vec2.h" class TechBonus { @@ -17,14 +21,14 @@ class TechBonus { std::vector<float> cost { 0, 0 }; std::vector<float> cost_abs { 0, 0 }; std::vector<float> prod { 0, 0 }; - int trade; - int improved_heal; - int improved_convert; + int trade { 0 } ; + int improved_heal { 0 }; + int improved_convert { 0 }; int req_range { 999 }; std::vector<int> aff_id; std::vector<int> aff_class; - int aff_level; + int aff_level { -1 }; int aff_all { 0 }; TechBonus operator+(const TechBonus &rhs) { @@ -33,7 +37,7 @@ class TechBonus { b.defence = defence + rhs.defence; b.sight = sight + rhs.sight; b.move = move + rhs.move; - for (int i=0; i<b.cost.size(); i++) { + for (int i=0; i<cost.size(); i++) { b.cost[i] = cost[i] + rhs.cost[i]; b.cost_abs[i] = cost_abs[i] + rhs.cost_abs[i]; b.prod[i] = prod[i] + rhs.prod[i]; @@ -42,8 +46,63 @@ class TechBonus { b.improved_heal = improved_heal + rhs.improved_heal; b.improved_convert = improved_convert + rhs.improved_convert; return b; - } + } + std::string to_string () { + std::string str = ""; + if (attack != 0) { + int value = (int)roundf(attack*100); + str += "Attack: " + std::to_string(value) + "%\n"; + } + if (defence != 0) { + int value = (int)roundf(defence*100); + str += "Defence: " + std::to_string(value) + "%\n"; + } + if (sight != 0) { + str += "Sight: " + std::to_string(sight) + "\n"; + } + if (range != 0) { + str += "Range: " + std::to_string(range) + "\n"; + } + if (move != 0) { + str += "Range: " + std::to_string(range) + "\n"; + } + if (cost[0] != 0 || cost[1] != 0) { + int vf = (int)roundf(cost[0]*100); + int vg = (int)roundf(cost[1]*100); + str += "Cost f: " + std::to_string(vf); + str += "%, g: " + std::to_string(vg) + "%\n"; + } + if (cost_abs[0] != 0 || cost_abs[1] != 0) { + int vf = (int)roundf(cost_abs[0]); + int vg = (int)roundf(cost_abs[1]); + str += "Cost f: " + std::to_string(vf); + str += ", g: " + std::to_string(vg) + "\n"; + } + if (prod[0] != 0 || prod[1] != 0) { + int vf = (int)roundf(prod[0]*100); + int vg = (int)roundf(prod[1]*100); + str += "Production f: " + std::to_string(vf); + str += "%, g: " + std::to_string(vg) + "%\n"; + } + if (trade != 0) { str += "Improves Trade Rate\n"; } + if (improved_heal != 0) { str += "Improves Heal Ability\n"; } + if (improved_convert != 0) { str += "Improves Convert Ability\n"; } + if (aff_id.size() > 0) { + str += "of entitiy "; + for (int id : aff_id) str += std::to_string(id) + " "; + str += "\n"; + } + if (aff_class.size() > 0) { + str += "of class "; + for (int c : aff_class) str += std::to_string(c) + " "; + str += "\n"; + } + if (aff_level != -1) { + str += "of level " + std::to_string(aff_level) + "\n"; + } + return str; + } }; class TechLookup { diff --git a/game/view.cpp b/game/view.cpp index 7fddcd5..78a9932 100644 --- a/game/view.cpp +++ b/game/view.cpp @@ -85,6 +85,34 @@ void View::process (Gst &gst, vec2 cam, vec2 mouse, int *mheld) { } found = true; } + + if (heals.size() > 0 && !found) { + for (int i=0; i<heals.size() && !found; i++) { + int x = heals[i] % gr.sizex; + int y = heals[i] / gr.sizex; + vec2 pos { (float)x*32, (float)y*32 }; + if (pos.x < absmouse.x && absmouse.x <= pos.x+32 + && pos.y < absmouse.y && absmouse.y <= pos.y+32) + { + cursor_ground = heals[i]; + } + } + found = true; + } + + if (converts.size() > 0 && !found) { + for (int i=0; i<converts.size() && !found; i++) { + int x = converts[i] % gr.sizex; + int y = converts[i] / gr.sizex; + vec2 pos { (float)x*32, (float)y*32 }; + if (pos.x < absmouse.x && absmouse.x <= pos.x+32 + && pos.y < absmouse.y && absmouse.y <= pos.y+32) + { + cursor_ground = converts[i]; + } + } + found = true; + } if (menu_train.active && !found) { int selected = menu_train.mouse_option(mouse); diff --git a/game/view.h b/game/view.h index 61301ac..6a316de 100644 --- a/game/view.h +++ b/game/view.h @@ -23,6 +23,8 @@ class View { std::vector<int> moves; std::vector<int> attacks; std::vector<int> builds; + std::vector<int> heals; + std::vector<int> converts; Menu_unit menu_unit; Menu_day menu_day; |