From 8af1284654a4a5d454a559eca371bf0ac3c79786 Mon Sep 17 00:00:00 2001 From: jacopograndi Date: Tue, 31 Aug 2021 23:53:53 +0200 Subject: tech done, building sprites, upgrade on age up, gui --- game/constants.h | 13 ++++ game/entity.h | 7 +- game/ground.cpp | 6 +- game/gst.cpp | 188 +++++++++++++++++++++++++++++++++++++++++++++---- game/gst.h | 13 +++- game/load.cpp | 39 ++++++++++ game/menu.h | 15 +++- game/player.h | 31 +++++++- game/playercontrol.cpp | 147 ++++++++++++++++++++++++++++++++------ game/playercontrol.h | 2 + game/tech.h | 53 +++++++++++++- game/view.cpp | 24 +++++++ game/view.h | 2 + 13 files changed, 494 insertions(+), 46 deletions(-) create mode 100644 game/constants.h (limited to 'game') diff --git a/game/constants.h b/game/constants.h new file mode 100644 index 0000000..7ea34e0 --- /dev/null +++ b/game/constants.h @@ -0,0 +1,13 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +namespace constants { + const int col_gud_r = 40; + const int col_gud_g = 120; + const int col_gud_b = 0; + const int col_bad_r = 255; + const int col_bad_g = 120; + const int col_bad_b = 0; +} + +#endif \ No newline at end of file diff --git a/game/entity.h b/game/entity.h index eeab110..50c7acc 100644 --- a/game/entity.h +++ b/game/entity.h @@ -16,6 +16,7 @@ class EntityInfo { std::string name; int id; + int level; float hp; float attack; @@ -28,11 +29,13 @@ class EntityInfo { std::vector build; std::vector train; - std::vector prod { 0, 0 }; - std::vector cost { 0, 0 }; + std::vector prod { 0, 0 }; + std::vector cost { 0, 0 }; std::vector adjacent; + int upgrade { -1 }; + enum Class { inf, cav, ran, sie, bld }; Class ent_class; diff --git a/game/ground.cpp b/game/ground.cpp index e6055bf..4308047 100644 --- a/game/ground.cpp +++ b/game/ground.cpp @@ -38,9 +38,13 @@ class step { public: }; std::vector Ground::move_area (Gst &gst, Entity &ent) { + Player &player = gst.players[ent.owner]; + int move_num = ent.info->move; + move_num += player.tech_lookup.id(ent.info->id).move; + std::vector moves; std::vector visited { at(ent.x, ent.y) }; - std::vector frontier { step { at(ent.x, ent.y), ent.info->move } }; + std::vector frontier { step { at(ent.x, ent.y), move_num } }; int maxcost = 99; if (gst.info_has_ability(ent.info, "Scout")) maxcost = 2; diff --git a/game/gst.cpp b/game/gst.cpp index 0a524fc..5c7485b 100644 --- a/game/gst.cpp +++ b/game/gst.cpp @@ -1,7 +1,20 @@ #include "gst.h" +#include #include +Player& Gst::get_player (int id) { + for (auto &player : players) { + if (id == player.id) return player; + } +} + +Tech* Gst::get_tech (int id) { + for (auto &tech : techs) { + if (id == tech.id) return &tech; + } +} + EntityInfo* Gst::get_info (std::string name) { for (EntityInfo &info : infos) { if (name == info.name) return &info; @@ -27,6 +40,21 @@ Entity& Gst::get_at (int x, int y) { } } +std::vector Gst::get_cost (EntityInfo *info, Player &player) { + std::vector cost = info->cost; + for (int i=0; icost.size(); i++) { + cost[i] *= 1+player.tech_lookup.id(info->id).cost[i]; + cost[i] += player.tech_lookup.id(info->id).cost_abs[i]; + } + return cost; +} + +float Gst::get_trade_rate (Player &player) { + float rate = 250; + rate -= player.tech_lookup.id(0).trade * 25; + return rate; +} + float Gst::get_type_bonus (Entity &atk, Entity &def) { float b = 0; switch(atk.info->ent_class) { @@ -104,6 +132,16 @@ std::vector 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; + if (tech_attack != 0) + bs.emplace_back(tech_attack, Bonus::Id::tech, true); + float tech_defence = player_def.tech_lookup.id(def.info->id).defence; + if (tech_defence != 0) + bs.emplace_back(tech_defence, Bonus::Id::tech, false); + return bs; } @@ -133,7 +171,7 @@ bool Gst::get_first_strike (Entity &atk, Entity &def) { return fs; } -float clamp (float hp) { +float clamp_hp (float hp) { if (hp > 100) hp = 100; if (hp < 0) hp = 0; return hp; @@ -163,36 +201,36 @@ BattleResult Gst::battle_res (Entity &atk, Entity &def) { if (first_strike_def && !first_strike_atk) swap = true; if (swap) { if (def_inrange) { - result.atk_hp = clamp( + result.atk_hp = clamp_hp( result.atk_hp - get_damage(def, atk, result.def_hp)); } if (!info_has_ability(atk.info, "No Counter")) if (result.atk_hp > 0) - result.def_hp = clamp( + result.def_hp = clamp_hp( result.def_hp - get_damage(atk, def, result.atk_hp)); } else { - result.def_hp = clamp( + result.def_hp = clamp_hp( result.def_hp - get_damage(atk, def, result.atk_hp)); if (!info_has_ability(def.info, "No Counter") && def_inrange) if (result.def_hp > 0) - result.atk_hp = clamp( + result.atk_hp = clamp_hp( result.atk_hp - get_damage(def, atk, result.def_hp)); } if (info_has_ability(atk.info, "Rapid Fire")) if (result.def_hp > 0) - result.def_hp = clamp( + result.def_hp = clamp_hp( result.def_hp - get_damage(atk, def, result.def_hp)); if (info_has_ability(def.info, "Rapid Fire") && def_inrange) if (result.atk_hp > 0) - result.atk_hp = clamp( + result.atk_hp = clamp_hp( result.atk_hp - get_damage(def, atk, result.def_hp)); if (result.atk_hp > 0 && info_has_ability(atk.info, "Zeal")) - result.atk_hp = clamp(result.atk_hp + 20); + result.atk_hp = clamp_hp(result.atk_hp + 20); if (result.def_hp > 0 && info_has_ability(def.info, "Zeal")) - result.def_hp = clamp(result.def_hp + 20); + result.def_hp = clamp_hp(result.def_hp + 20); return result; } @@ -239,7 +277,10 @@ std::vector Gst::get_possible_builds (Entity &ent) { return builds; } + bool Gst::check_req_build(Entity &ent, EntityInfo *info) { + Player &player = players[ent.owner]; + if (player.level < info->level) return false; for (int id : info->adjacent) { bool adj = false; for (Entity &e : entities) { @@ -294,6 +335,63 @@ 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; + if (tech->level > player.level) { + return false; + } + if (tech->cost[0] > player.res[0] + || tech->cost[1] > player.res[1] ) + { + return false; + } + if (player.has_tech(tech->id)) { + return false; + } + bool req_id = false; + for (auto &ent : entities) { + if (ent.owner == turn // WARNING: turn is not player.id + && ent.info->id == tech->req_id + && ent.building == 0) + { + req_id = true; + break; + } + } + if (!req_id) { + return false; + } + return true; +} + +bool Gst::check_req_level (Player &player) { + if (player.leveling_up == 1) return false; + + for (float v : player.res) { + if (v <= (player.level+1)*500) return false; + } + + std::map lv_techs; + for (int id : player.techs) lv_techs[get_tech(id)->level] ++; + if (player.level == 0) { + if (lv_techs[0] >= 3) return true; + } + if (player.level == 1) { + if (lv_techs[1] >= 7) return true; + } + if (player.level == 2) { + if (lv_techs[2] >= 11) return true; + } + return false; +} + bool Gst::check_obstructed (Entity &ent) { for (Entity &e : entities) { if (&ent != &e && e.x == ent.x && ent.y == e.y) return true; @@ -307,21 +405,83 @@ void Gst::end_day () { turn = 0; day++; } + Player &player = players[turn]; + if (player.leveling_up != -1) { + level_upgrade(player); + player.level ++; + player.leveling_up = -1; + } for (Entity &e : entities) { e.done = false; e.moved = 0; - if (e.owner == turn) { - Player &player = players[e.owner]; + if (get_player(e.owner) == player) { for (int i=0; iprod[i]; + player.res[i] += e.info->prod[i] * + (1+player.tech_lookup.id(e.info->id).prod[i]); } - // todo heal when on top of building if (e.building < 0) { e.building++; if (e.building == 0) { - e.hp += 50; if (e.hp > 100) e.hp = 100; + e.hp = clamp_hp(e.hp + 50); + } + } + if (e.info->unit == 1 && check_obstructed(e)) { + e.hp = clamp_hp(e.hp + 20); + } + } + } + if (player.researching != -1) { + player.techs.push_back(player.researching); + update_tech_lookup(player); + player.researching = -1; + } +} + +void Gst::level_upgrade (Player &player) { + for (Entity &e : entities) { + if (get_player(e.owner) == player) { + if (e.info->upgrade != -1 && e.info->level == player.level) { + e.info = get_info(e.info->upgrade); + } + } + } +} + + +void Gst::update_tech_lookup (Player &player) { + player.tech_lookup.map_id.clear(); + for (int i : player.techs) { + Tech *tech = get_tech(i); + std::vector ids { }; + if (tech->bonus.aff_id.size() > 0) { + ids = tech->bonus.aff_id; + } else { + if (tech->bonus.aff_level != -1) { + for (EntityInfo info : infos) { + if (info.level == tech->bonus.aff_level) { + ids.push_back(info.id); + } + } + } + if (tech->bonus.aff_class.size() > 0) { + for (EntityInfo info : infos) { + auto &cls = tech->bonus.aff_class; + if (std::find(cls.begin(), cls.end(), + info.ent_class) != cls.end()) + { + ids.push_back(info.id); + } } } + if (tech->bonus.aff_all == 1) { + for (EntityInfo 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; } } } \ No newline at end of file diff --git a/game/gst.h b/game/gst.h index 906b372..c9c5d3c 100644 --- a/game/gst.h +++ b/game/gst.h @@ -54,10 +54,14 @@ class Gst { std::vector players; + Player& get_player (int id); + Tech* get_tech (int id); EntityInfo* get_info (std::string name); EntityInfo* get_info (int id); bool info_has_ability (EntityInfo* info, std::string name); Entity& get_at (int x, int y); + std::vector get_cost (EntityInfo *info, Player &player); + float get_trade_rate (Player &player); float get_type_bonus (Entity &atk, Entity &def); std::vector get_bonuses (Entity &atk, Entity &def); @@ -71,14 +75,19 @@ class Gst { std::vector get_possible_builds (Entity &ent); - bool check_req_build(Entity &ent, EntityInfo *info); - + 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); int turn { 0 }; int day { 0 }; void end_day (); + void level_upgrade (Player &player); + + void update_tech_lookup (Player &player); }; #endif \ No newline at end of file diff --git a/game/load.cpp b/game/load.cpp index 5baae6c..c9c9132 100644 --- a/game/load.cpp +++ b/game/load.cpp @@ -53,6 +53,7 @@ void load_json (Gst &gst) { EntityInfo ent; ent.id = it["id"]; ent.name = it["name"]; + ent.level = it["level"]; ent.range = it["range"]; ent.move = it["move"]; ent.attack = it["attack"]; @@ -88,6 +89,7 @@ void load_json (Gst &gst) { ent.abilities.push_back(index); } ent.spritebounds = vec2 { it["spritebounds"][0], it["spritebounds"][1] }; + if (it.contains("upgrade")) { ent.upgrade = it["upgrade"]; } gst.infos.push_back(ent); } @@ -102,6 +104,43 @@ void load_json (Gst &gst) { for (int i=0; i cost; + std::vector cost; }; @@ -56,7 +56,18 @@ class Menu_train : public Menu { public: Menu_train () {} }; - +class Menu_trade : public Menu { + public: + Menu_trade () {} + + enum Opts { + food, gold + }; +}; +class Menu_age_up : public Menu { + public: + Menu_age_up () {} +}; class OptionTech { public: diff --git a/game/player.h b/game/player.h index 01d8ee9..cf4146f 100644 --- a/game/player.h +++ b/game/player.h @@ -3,14 +3,41 @@ #include +#include "tech.h" + class Player { public: - Player (int r, int g, int b) : r(r), g(g), b(b) { } + Player (int r, int g, int b, int id) : r(r), g(g), b(b), id(id) { } + + void pay (std::vector cost) { + for (int i=0; i gain) { + for (int i=0; i res { 0, 0 }; + bool operator== (Player &oth) { return id == oth.id; } + + int id; + + std::vector res { 0, 0 }; std::vector techs; + TechLookup tech_lookup; + + int researching { -1 }; + int leveling_up { -1 }; int level { 0 }; int r, g, b; diff --git a/game/playercontrol.cpp b/game/playercontrol.cpp index 90e063e..284c6ff 100644 --- a/game/playercontrol.cpp +++ b/game/playercontrol.cpp @@ -6,37 +6,48 @@ void open_unit_menu (Gst &gst, View &view, Fsm &fsm, int p) { Entity &ent = gst.entities[view.selected_entity]; + Player &player = gst.players[ent.owner]; view.menu_unit.options.clear(); if (ent.info->unit == 1) { if (gst.ground.move_area(gst, ent).size() > 0 && ent.moved == 0) { - view.menu_unit.options.emplace_back("Move", Menu_unit::Opts::move); + view.menu_unit.options.emplace_back("Move", + Menu_unit::Opts::move); } if (gst.ground.attack_targets(gst, ent).size() > 0 && (!gst.info_has_ability(ent.info, "No Move & Attack") || ent.moved == 0)) { - view.menu_unit.options.emplace_back("Attack", Menu_unit::Opts::attack); + view.menu_unit.options.emplace_back("Attack", + Menu_unit::Opts::attack); } if (ent.info->build.size() > 0 && !gst.check_obstructed(ent) && gst.get_possible_builds(ent).size() > 0) { - view.menu_unit.options.emplace_back("Build", Menu_unit::Opts::build); + view.menu_unit.options.emplace_back("Build", + Menu_unit::Opts::build); } - view.menu_unit.options.emplace_back("Done", Menu_unit::Opts::done); + view.menu_unit.options.emplace_back("Done", + Menu_unit::Opts::done); } else { if (ent.info->train.size() && !gst.check_obstructed(ent)) { - view.menu_unit.options.emplace_back("Train", Menu_unit::Opts::train); + view.menu_unit.options.emplace_back("Train", + Menu_unit::Opts::train); } if (ent.info->id == 100 || ent.info->id == 101) { - view.menu_unit.options.emplace_back("Trade", Menu_unit::Opts::trade); + int rate = (int)gst.get_trade_rate(player); + if (player.res[0] >= rate || player.res[1] >= rate) { + view.menu_unit.options.emplace_back("Trade", + Menu_unit::Opts::trade); + } } if (ent.info->id == 100) { - view.menu_unit.options.emplace_back("Age Up", Menu_unit::Opts::age_up); + view.menu_unit.options.emplace_back("Age Up", + Menu_unit::Opts::age_up); } } view.menu_unit.open(view.res); @@ -49,10 +60,14 @@ Player_control::Player_control () { view.selected_ground = p; std::cout << "selected ground " << p << "\n"; view.menu_day.options.clear(); - view.menu_day.options.emplace_back("End Day", Menu_day::Opts::end_day); - view.menu_day.options.emplace_back("Research", Menu_day::Opts::tech); - view.menu_day.options.emplace_back("Empire Review", Menu_day::Opts::empire_review); - view.menu_day.options.emplace_back("Scoring", Menu_day::Opts::scoring); + view.menu_day.options.emplace_back("End Day", + Menu_day::Opts::end_day); + view.menu_day.options.emplace_back("Research", + Menu_day::Opts::tech); + view.menu_day.options.emplace_back("Empire Review", + Menu_day::Opts::empire_review); + view.menu_day.options.emplace_back("Scoring", + Menu_day::Opts::scoring); view.menu_day.open(view.res); return menu_day; } @@ -91,6 +106,18 @@ Player_control::Player_control () { fsm.arcs.emplace_back( menu_tech, opt, -1, [](Gst &gst, View &view, Fsm &fsm, int p) { + if (p == -1) + return menu_tech; + Player &player = gst.players[gst.turn]; + Tech *tech = gst.get_tech(p); + if (!gst.check_req_tech(tech, player)) { + return menu_tech; + } + if (player.researching != -1) { + player.gain(tech->cost); + } + player.researching = p; + player.pay(tech->cost); view.menu_tech.close(); view.selected_ground = -1; std::cout << "selected tech " << p << "\n"; @@ -128,13 +155,16 @@ Player_control::Player_control () { view.menu_unit.close(); std::cout << "train " << p << "\n"; Entity &ent = gst.entities[view.selected_entity]; + Player &player = gst.players[ent.owner]; view.menu_train.options.clear(); for (int id : ent.info->train) { - std::cout << id << " " << gst.get_info(id)->name << "\n"; EntityInfo *info = gst.get_info(id); - Option opt { info->name, id }; - opt.cost = info->cost; - view.menu_train.options.push_back(opt); + 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); + } } view.menu_train.open(view.res); return menu_train; @@ -152,9 +182,7 @@ Player_control::Player_control () { entb.hp = 50; gst.entities.push_back(entb); Player &player = gst.players[gst.turn]; - for (int i=0; icost[i]; - } + player.pay(gst.get_cost(entb.info, player)); view.selected_entity = -1; return select; } @@ -165,13 +193,14 @@ Player_control::Player_control () { view.menu_unit.close(); std::cout << "build " << p << "\n"; Entity &ent = gst.entities[view.selected_entity]; + Player &player = gst.players[ent.owner]; view.menu_build.options.clear(); for (int id : ent.info->build) { EntityInfo *info = gst.get_info(id); if(!gst.check_req_build(ent, info)) continue; std::cout << id << " " << gst.get_info(id)->name << "\n"; Option opt { info->name, id }; - opt.cost = info->cost; + opt.cost = gst.get_cost(info, player); view.menu_build.options.push_back(opt); } view.menu_build.open(view.res); @@ -191,9 +220,7 @@ Player_control::Player_control () { entb.hp = 50; gst.entities.push_back(entb); Player &player = gst.players[gst.turn]; - for (int i=0; icost[i]; - } + player.pay(gst.get_cost(entb.info, player)); view.selected_entity = -1; return select; } @@ -247,6 +274,82 @@ Player_control::Player_control () { return select; } ); + fsm.arcs.emplace_back( + menu_unit, opt, Menu_unit::Opts::trade, + [](Gst &gst, View &view, Fsm &fsm, int p) { + Player &player = gst.players[gst.turn]; + view.menu_unit.close(); + view.menu_trade.options.clear(); + int rate = (int)gst.get_trade_rate(player); + if (player.res[0] >= rate) { + view.menu_trade.options.emplace_back( + std::to_string(rate) + " Food for 100 Gold", + Menu_trade::Opts::food); + } + if (player.res[1] >= rate) { + view.menu_trade.options.emplace_back( + std::to_string(rate) + " Gold for 100 Food", + Menu_trade::Opts::gold); + } + view.menu_trade.open(view.res); + std::cout << "trade open " << p << "\n"; + return menu_trade; + } + ); + fsm.arcs.emplace_back( + menu_trade, opt, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + Player &player = gst.players[gst.turn]; + view.menu_trade.close(); + int rate = (int)gst.get_trade_rate(player); + int sel = p; + player.pay(std::vector + { (float)rate*(1-sel), (float)rate*sel }); + player.gain(std::vector + { 100.0f*sel, 100.0f*(1-sel) }); + gst.entities[view.selected_entity].done = true; + view.selected_entity = -1; + std::cout << "done trading " << p << "\n"; + return select; + } + ); + fsm.arcs.emplace_back( + menu_unit, opt, Menu_unit::Opts::age_up, + [](Gst &gst, View &view, Fsm &fsm, int p) { + Player &player = gst.players[gst.turn]; + view.menu_unit.close(); + view.menu_age_up.options.clear(); + if (gst.check_req_level(player)) { + view.menu_age_up.options.emplace_back("Age Up", 0); + } + view.menu_age_up.open(view.res); + std::cout << "age up open " << p << "\n"; + return menu_age_up; + } + ); + fsm.arcs.emplace_back( + menu_age_up, opt, 0, + [](Gst &gst, View &view, Fsm &fsm, int p) { + Player &player = gst.players[gst.turn]; + player.leveling_up = 1; + float cost = (player.level+1)*500; + player.pay(std::vector{ cost, cost }); + view.menu_age_up.close(); + gst.entities[view.selected_entity].done = true; + view.selected_entity = -1; + std::cout << "aged up " << p << "\n"; + return select; + } + ); + fsm.arcs.emplace_back( + menu_age_up, back, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.menu_age_up.close(); + view.selected_entity = -1; + std::cout << "closed ageup " << p << "\n"; + return select; + } + ); fsm.arcs.emplace_back( menu_unit, opt, Menu_unit::Opts::done, [](Gst &gst, View &view, Fsm &fsm, int p) { diff --git a/game/playercontrol.h b/game/playercontrol.h index 3096ada..6d12026 100644 --- a/game/playercontrol.h +++ b/game/playercontrol.h @@ -32,6 +32,8 @@ enum pc_state { menu_unit, menu_day, menu_tech, + menu_trade, + menu_age_up, end }; diff --git a/game/tech.h b/game/tech.h index 84ef05c..cb5e769 100644 --- a/game/tech.h +++ b/game/tech.h @@ -2,10 +2,59 @@ #define TECH_H #include +#include #include #include "../umath/vec2.h" +class TechBonus { + public: + float attack { 0 }; + float defence { 0 }; + int sight { 0 }; + int range { 0 }; + int move { 0 }; + std::vector cost { 0, 0 }; + std::vector cost_abs { 0, 0 }; + std::vector prod { 0, 0 }; + int trade; + int improved_heal; + int improved_convert; + int req_range { 999 }; + + std::vector aff_id; + std::vector aff_class; + int aff_level; + int aff_all { 0 }; + + TechBonus operator+(const TechBonus &rhs) { + TechBonus b; + b.attack = attack + rhs.attack; + b.defence = defence + rhs.defence; + b.sight = sight + rhs.sight; + b.move = move + rhs.move; + for (int i=0; i map_id; +}; + class Tech { public: Tech() {} @@ -14,7 +63,9 @@ class Tech { int id; int level; int req_id; - std::vector cost { 0, 0 }; + std::vector cost { 0, 0 }; + + TechBonus bonus; vec2 spritebounds { 0, 0 }; }; diff --git a/game/view.cpp b/game/view.cpp index 095a99a..7fddcd5 100644 --- a/game/view.cpp +++ b/game/view.cpp @@ -41,6 +41,12 @@ void View::process (Gst &gst, vec2 cam, vec2 mouse, int *mheld) { if (menu_tech.active) { menu_tech.over = menu_tech.mouse_option(mouse); } + if (menu_trade.active) { + menu_trade.over = menu_trade.mouse_option(mouse); + } + if (menu_age_up.active) { + menu_age_up.over = menu_age_up.mouse_option(mouse); + } if (mheld[0] == 1) { bool found = false; @@ -124,6 +130,24 @@ void View::process (Gst &gst, vec2 cam, vec2 mouse, int *mheld) { back = 1; found = 1; } } + + if (menu_trade.active && !found) { + int selected = menu_trade.mouse_option(mouse); + if (selected != -1) { + opt = selected; found = true; + } else { + back = 1; found = 1; + } + } + + if (menu_age_up.active && !found) { + int selected = menu_age_up.mouse_option(mouse); + if (selected != -1) { + opt = selected; found = true; + } else { + back = 1; found = 1; + } + } for (int i=0; i