aboutsummaryrefslogtreecommitdiff
path: root/game
diff options
context:
space:
mode:
authorjacopograndi <jak.sk8@hotmail.it>2021-08-31 23:53:53 +0200
committerjacopograndi <jak.sk8@hotmail.it>2021-08-31 23:53:53 +0200
commit8af1284654a4a5d454a559eca371bf0ac3c79786 (patch)
tree70e9cf9d3d11a205175bdad394b6201870cf7f07 /game
parentfb5a98b72ab79949d1da7f75a3d6150c2906ef40 (diff)
tech done, building sprites, upgrade on age up, gui
Diffstat (limited to 'game')
-rw-r--r--game/constants.h13
-rw-r--r--game/entity.h7
-rw-r--r--game/ground.cpp6
-rw-r--r--game/gst.cpp188
-rw-r--r--game/gst.h13
-rw-r--r--game/load.cpp39
-rw-r--r--game/menu.h15
-rw-r--r--game/player.h31
-rw-r--r--game/playercontrol.cpp147
-rw-r--r--game/playercontrol.h2
-rw-r--r--game/tech.h53
-rw-r--r--game/view.cpp24
-rw-r--r--game/view.h2
13 files changed, 494 insertions, 46 deletions
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<int> build;
std::vector<int> train;
- std::vector<int> prod { 0, 0 };
- std::vector<int> cost { 0, 0 };
+ std::vector<float> prod { 0, 0 };
+ std::vector<float> cost { 0, 0 };
std::vector<int> 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<int> 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<int> moves;
std::vector<int> visited { at(ent.x, ent.y) };
- std::vector<step> frontier { step { at(ent.x, ent.y), ent.info->move } };
+ std::vector<step> 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 <map>
#include <iostream>
+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<float> Gst::get_cost (EntityInfo *info, Player &player) {
+ std::vector<float> cost = info->cost;
+ 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];
+ }
+ 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<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;
+ 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<int> 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<int, int> 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; i<player.res.size(); i++) {
- player.res[i] += e.info->prod[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<int> 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<Player> 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<float> get_cost (EntityInfo *info, Player &player);
+ float get_trade_rate (Player &player);
float get_type_bonus (Entity &atk, Entity &def);
std::vector<Bonus> get_bonuses (Entity &atk, Entity &def);
@@ -71,14 +75,19 @@ class Gst {
std::vector<int> 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<it["cost"].size(); i++) {
tech.cost[i] = it["cost"][i];
}
+ auto b = it["bonus"];
+ if (b != nullptr) {
+ if (b.contains("attack")) { tech.bonus.attack = b["attack"]; }
+ if (b.contains("defence")) { tech.bonus.defence = b["defence"]; }
+ if (b.contains("sight")) { tech.bonus.sight = b["sight"]; }
+ if (b.contains("move")) { tech.bonus.move = b["move"]; }
+ if (b.contains("trade")) { tech.bonus.trade = b["trade"]; }
+ if (b.contains("req_range")) {
+ tech.bonus.req_range = b["req_range"];
+ }
+ if (b.contains("improved_heal")) {
+ tech.bonus.attack = b["improved_heal"];
+ }
+ if (b.contains("improved_convert")) {
+ tech.bonus.attack = b["improved_convert"];
+ }
+ for (auto v : b["cost"]) { tech.bonus.cost.push_back(v); }
+ for (auto v : b["cost_abs"]) { tech.bonus.cost_abs.push_back(v); }
+ for (auto v : b["prod"]) { tech.bonus.prod.push_back(v); }
+
+ 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);
+ }
+ if (b.contains("aff_level")) {
+ tech.bonus.aff_level = b["aff_level"];
+ }
+ if (b.contains("aff_all")) {
+ tech.bonus.aff_all = b["aff_all"];
+ }
+ }
gst.techs.push_back(tech);
}
} \ No newline at end of file
diff --git a/game/menu.h b/game/menu.h
index 462d893..3da0c46 100644
--- a/game/menu.h
+++ b/game/menu.h
@@ -14,7 +14,7 @@ class Option {
std::string name;
int id;
- std::vector<int> cost;
+ std::vector<float> 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 <vector>
+#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<float> cost) {
+ for (int i=0; i<res.size(); i++) {
+ res[i] -= cost[i];
+ }
+ }
+ void gain (std::vector<float> gain) {
+ for (int i=0; i<res.size(); i++) {
+ res[i] += gain[i];
+ }
+ }
+
+ bool has_tech (int id) {
+ if (std::find(techs.begin(), techs.end(), id) != techs.end())
+ return true;
+ return false;
+ }
- std::vector<int> res { 0, 0 };
+ bool operator== (Player &oth) { return id == oth.id; }
+
+ int id;
+
+ std::vector<float> res { 0, 0 };
std::vector<int> 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; i<player.res.size(); i++) {
- player.res[i] -= entb.info->cost[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; i<player.res.size(); i++) {
- player.res[i] -= entb.info->cost[i];
- }
+ player.pay(gst.get_cost(entb.info, player));
view.selected_entity = -1;
return select;
}
@@ -248,6 +275,82 @@ Player_control::Player_control () {
}
);
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>
+ { (float)rate*(1-sel), (float)rate*sel });
+ player.gain(std::vector<float>
+ { 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<float>{ 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) {
view.menu_unit.close();
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 <vector>
+#include <unordered_map>
#include <string>
#include "../umath/vec2.h"
+class TechBonus {
+ public:
+ float attack { 0 };
+ float defence { 0 };
+ int sight { 0 };
+ int range { 0 };
+ int move { 0 };
+ 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 req_range { 999 };
+
+ std::vector<int> aff_id;
+ std::vector<int> 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<b.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];
+ }
+ b.trade = trade + rhs.trade;
+ b.improved_heal = improved_heal + rhs.improved_heal;
+ b.improved_convert = improved_convert + rhs.improved_convert;
+ return b;
+ }
+
+};
+
+class TechLookup {
+ public:
+ TechLookup() {}
+
+ TechBonus id (int i) { return map_id[i]; }
+
+ std::unordered_map<int, TechBonus> map_id;
+};
+
class Tech {
public:
Tech() {}
@@ -14,7 +63,9 @@ class Tech {
int id;
int level;
int req_id;
- std::vector<int> cost { 0, 0 };
+ std::vector<float> 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<entities.size() && !found; i++) {
if (entities[i].done) continue;
diff --git a/game/view.h b/game/view.h
index 5aab193..61301ac 100644
--- a/game/view.h
+++ b/game/view.h
@@ -29,6 +29,8 @@ class View {
Menu_build menu_build;
Menu_train menu_train;
Menu_tech menu_tech;
+ Menu_trade menu_trade;
+ Menu_age_up menu_age_up;
void process (Gst &gst, vec2 cam, vec2 mouse, int *mheld);
};