aboutsummaryrefslogtreecommitdiff
path: root/game
diff options
context:
space:
mode:
Diffstat (limited to 'game')
-rw-r--r--game/entity.h1
-rw-r--r--game/ground.cpp30
-rw-r--r--game/ground.h2
-rw-r--r--game/gst.cpp63
-rw-r--r--game/gst.h31
-rw-r--r--game/load.cpp12
-rw-r--r--game/menu.h2
-rw-r--r--game/playercontrol.cpp66
-rw-r--r--game/playercontrol.h1
-rw-r--r--game/tech.cpp2
-rw-r--r--game/tech.h71
-rw-r--r--game/view.cpp28
-rw-r--r--game/view.h2
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;
diff --git a/game/gst.h b/game/gst.h
index 82f4b07..dc68b31 100644
--- a/game/gst.h
+++ b/game/gst.h
@@ -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;