You now receive damage to multiple body parts and can heal them all too.
This commit is contained in:
parent
1777a6bbf2
commit
360402cb3c
6 changed files with 61 additions and 23 deletions
|
|
@ -6,7 +6,17 @@
|
||||||
"foreground": "enemies/fg:player",
|
"foreground": "enemies/fg:player",
|
||||||
"background": "color:transparent"
|
"background": "color:transparent"
|
||||||
},
|
},
|
||||||
{"_type": "Combat", "ap": 0, "max_ap": 12, "ap_delta": 6, "damage": 50, "dead": false},
|
{"_type": "Combat", "max_hp": 50, "max_ap": 12, "ap_delta": 6, "damage": 100, "dead": false,
|
||||||
|
"body_parts": {
|
||||||
|
"head": 200,
|
||||||
|
"chest": 200,
|
||||||
|
"stomach": 200,
|
||||||
|
"right_arm": 200,
|
||||||
|
"left_arm": 200,
|
||||||
|
"right_leg": 200,
|
||||||
|
"left_leg": 200
|
||||||
|
}
|
||||||
|
},
|
||||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||||
{"_type": "Collision", "has": true},
|
{"_type": "Collision", "has": true},
|
||||||
{"_type": "EnemyConfig", "ai_script": "Host::actions", "ai_start_name": "Host::initial_state", "ai_goal_name": "Host::final_state"},
|
{"_type": "EnemyConfig", "ai_script": "Host::actions", "ai_start_name": "Host::initial_state", "ai_goal_name": "Host::final_state"},
|
||||||
|
|
@ -20,7 +30,17 @@
|
||||||
"foreground": "enemies/fg:rat_giant",
|
"foreground": "enemies/fg:rat_giant",
|
||||||
"background": "color:transparent"
|
"background": "color:transparent"
|
||||||
},
|
},
|
||||||
{"_type": "Combat", "ap": 0, "max_ap": 12, "ap_delta": 6,"damage": 2, "dead": false},
|
{"_type": "Combat", "max_hp": 50, "max_ap": 12, "ap_delta": 6,"damage": 10, "dead": false,
|
||||||
|
"body_parts": {
|
||||||
|
"head": 50,
|
||||||
|
"chest": 50,
|
||||||
|
"stomach": 50,
|
||||||
|
"right_arm": 50,
|
||||||
|
"left_arm": 50,
|
||||||
|
"right_leg": 50,
|
||||||
|
"left_leg": 50
|
||||||
|
}
|
||||||
|
},
|
||||||
{"_type": "Collision", "has": true},
|
{"_type": "Collision", "has": true},
|
||||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||||
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||||
|
|
|
||||||
|
|
@ -8,30 +8,39 @@ namespace components {
|
||||||
|
|
||||||
if(attack) {
|
if(attack) {
|
||||||
my_dmg = Random::uniform<int>(1, damage);
|
my_dmg = Random::uniform<int>(1, damage);
|
||||||
target.hit_limb(my_dmg);
|
target.take_damage(my_dmg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return my_dmg;
|
return my_dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Combat::hit_limb(int my_dmg) {
|
void Combat::take_damage(int my_dmg) {
|
||||||
body_parts["head"] -= my_dmg;
|
for(auto& [key, hp] : body_parts) {
|
||||||
|
if(Random::uniform(0, 1) == 0) {
|
||||||
|
body_parts[key] = hp - my_dmg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Combat::less_than(int level) {
|
||||||
|
return body_parts["head"] < level || body_parts["stomach"] < level || body_parts["chest"] < level;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Combat::is_dead() {
|
bool Combat::is_dead() {
|
||||||
return body_parts["head"] < 0;
|
return less_than(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Combat::almost_dead() {
|
bool Combat::almost_dead() {
|
||||||
return body_parts["head"] < 20;
|
return less_than(max_hp / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Combat::can_heal() {
|
bool Combat::can_heal() {
|
||||||
return body_parts["head"] < 50;
|
return less_than(max_hp / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Combat::apply_healing(Curative& cure) {
|
void Combat::apply_healing(Curative& cure) {
|
||||||
int new_hp = body_parts["head"] + cure.hp;
|
for(auto& [key, hp] : body_parts) {
|
||||||
body_parts["head"] = std::min(new_hp, 50);
|
body_parts[key] = std::min(hp + cure.hp, max_hp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,11 +107,18 @@ namespace components {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Combat {
|
struct Combat {
|
||||||
int ap_delta;
|
int max_hp=1;
|
||||||
int max_ap;
|
int ap_delta=1;
|
||||||
int damage;
|
int max_ap=1;
|
||||||
|
int damage=1;
|
||||||
std::unordered_map<std::string, int> body_parts{
|
std::unordered_map<std::string, int> body_parts{
|
||||||
{"head", 50},
|
{"head", 10},
|
||||||
|
{"chest", 10},
|
||||||
|
{"stomach", 10},
|
||||||
|
{"right_arm", 10},
|
||||||
|
{"left_arm", 10},
|
||||||
|
{"right_leg", 10},
|
||||||
|
{"left_leg", 10},
|
||||||
};
|
};
|
||||||
|
|
||||||
// everyone starts at 0 but ap_delta is added each round
|
// everyone starts at 0 but ap_delta is added each round
|
||||||
|
|
@ -120,8 +127,9 @@ namespace components {
|
||||||
/* NOTE: This is used to _mark_ entities as dead, to detect ones that have just died. Don't make attack automatically set it.*/
|
/* NOTE: This is used to _mark_ entities as dead, to detect ones that have just died. Don't make attack automatically set it.*/
|
||||||
bool dead = false;
|
bool dead = false;
|
||||||
|
|
||||||
|
bool less_than(int level);
|
||||||
int attack(Combat &target);
|
int attack(Combat &target);
|
||||||
void hit_limb(int my_dmg);
|
void take_damage(int my_dmg);
|
||||||
bool is_dead();
|
bool is_dead();
|
||||||
bool almost_dead();
|
bool almost_dead();
|
||||||
bool can_heal();
|
bool can_heal();
|
||||||
|
|
@ -162,7 +170,7 @@ namespace components {
|
||||||
ENROLL_COMPONENT(EnemyConfig, ai_script, ai_start_name, ai_goal_name);
|
ENROLL_COMPONENT(EnemyConfig, ai_script, ai_start_name, ai_goal_name);
|
||||||
ENROLL_COMPONENT(Personality, hearing_distance, tough);
|
ENROLL_COMPONENT(Personality, hearing_distance, tough);
|
||||||
ENROLL_COMPONENT(Motion, dx, dy, random);
|
ENROLL_COMPONENT(Motion, dx, dy, random);
|
||||||
ENROLL_COMPONENT(Combat, ap_delta, max_ap, damage, dead);
|
ENROLL_COMPONENT(Combat, max_hp, ap_delta, max_ap, damage, body_parts);
|
||||||
ENROLL_COMPONENT(Device, config, events);
|
ENROLL_COMPONENT(Device, config, events);
|
||||||
ENROLL_COMPONENT(Storyboard, image, audio, layout, beats);
|
ENROLL_COMPONENT(Storyboard, image, audio, layout, beats);
|
||||||
ENROLL_COMPONENT(Sound, attack, death);
|
ENROLL_COMPONENT(Sound, attack, death);
|
||||||
|
|
@ -186,7 +194,7 @@ namespace components {
|
||||||
|
|
||||||
template <typename COMPONENT> void enroll(ComponentMap &m) {
|
template <typename COMPONENT> void enroll(ComponentMap &m) {
|
||||||
m[NameOf<COMPONENT>::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) {
|
m[NameOf<COMPONENT>::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) {
|
||||||
COMPONENT c;
|
COMPONENT c{};
|
||||||
from_json(j, c);
|
from_json(j, c);
|
||||||
world.set<COMPONENT>(ent, c);
|
world.set<COMPONENT>(ent, c);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ namespace gui {
|
||||||
$gui.layout(
|
$gui.layout(
|
||||||
"[head]"
|
"[head]"
|
||||||
"[chest]"
|
"[chest]"
|
||||||
|
"[stomach]"
|
||||||
"[right_arm]"
|
"[right_arm]"
|
||||||
"[left_arm]"
|
"[left_arm]"
|
||||||
"[stomach]"
|
"[right_leg]"
|
||||||
"[left_leg]"
|
"[left_leg]");
|
||||||
"[right_leg]");
|
|
||||||
|
|
||||||
$gui.set<Background>($gui.MAIN, {$gui.$parser, });
|
$gui.set<Background>($gui.MAIN, {$gui.$parser, });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,7 @@ namespace gui {
|
||||||
$main_ui.play_hands();
|
$main_ui.play_hands();
|
||||||
$main_ui.dirty();
|
$main_ui.dirty();
|
||||||
sound::play("Sword_Hit_1");
|
sound::play("Sword_Hit_1");
|
||||||
|
$status_ui.update();
|
||||||
state(State::ATTACKING);
|
state(State::ATTACKING);
|
||||||
break;
|
break;
|
||||||
case ROTATE_LEFT:
|
case ROTATE_LEFT:
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,17 @@ TEST_CASE("battle operations fantasy", "[combat-battle]") {
|
||||||
|
|
||||||
DinkyECS::Entity host = 0;
|
DinkyECS::Entity host = 0;
|
||||||
ai::EntityAI host_ai("Host::actions", host_start, host_goal);
|
ai::EntityAI host_ai("Host::actions", host_start, host_goal);
|
||||||
components::Combat host_combat{.ap_delta=6, .max_ap=12, .damage=20};
|
components::Combat host_combat{.max_hp=50, .ap_delta=6, .max_ap=12, .damage=20};
|
||||||
battle.add_enemy({host, &host_ai, &host_combat, true});
|
battle.add_enemy({host, &host_ai, &host_combat, true});
|
||||||
|
|
||||||
DinkyECS::Entity axe_ranger = 1;
|
DinkyECS::Entity axe_ranger = 1;
|
||||||
ai::EntityAI axe_ai("Enemy::actions", ai_start, ai_goal);
|
ai::EntityAI axe_ai("Enemy::actions", ai_start, ai_goal);
|
||||||
components::Combat axe_combat{.ap_delta=8, .max_ap=12, .damage=20};
|
components::Combat axe_combat{.max_hp=50, .ap_delta=8, .max_ap=12, .damage=20};
|
||||||
battle.add_enemy({axe_ranger, &axe_ai, &axe_combat});
|
battle.add_enemy({axe_ranger, &axe_ai, &axe_combat});
|
||||||
|
|
||||||
DinkyECS::Entity rat = 2;
|
DinkyECS::Entity rat = 2;
|
||||||
ai::EntityAI rat_ai("Enemy::actions", ai_start, ai_goal);
|
ai::EntityAI rat_ai("Enemy::actions", ai_start, ai_goal);
|
||||||
components::Combat rat_combat{.ap_delta=2, .max_ap=10, .damage=10};
|
components::Combat rat_combat{.max_hp=50, .ap_delta=2, .max_ap=10, .damage=10};
|
||||||
battle.add_enemy({rat, &rat_ai, &rat_combat});
|
battle.add_enemy({rat, &rat_ai, &rat_combat});
|
||||||
|
|
||||||
battle.set_all("enemy_found", true);
|
battle.set_all("enemy_found", true);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue