Now the body_ui handles the toughness and attack rating, and applies colors to show your body part status.
This commit is contained in:
parent
009c5c1cd2
commit
831b46fa3f
11 changed files with 92 additions and 20 deletions
|
|
@ -6,7 +6,8 @@
|
||||||
"foreground": "enemies/fg:player",
|
"foreground": "enemies/fg:player",
|
||||||
"background": "color:transparent"
|
"background": "color:transparent"
|
||||||
},
|
},
|
||||||
{"_type": "Combat", "max_hp": 200, "max_ap": 12, "ap_delta": 6, "damage": 20,
|
{"_type": "Combat", "max_hp": 200, "max_ap": 12,
|
||||||
|
"ap_delta": 6, "damage": 20, "attack_rating": 0.5, "toughness_rating": 0.1,
|
||||||
"body_parts": {
|
"body_parts": {
|
||||||
"head": 200,
|
"head": 200,
|
||||||
"chest": 200,
|
"chest": 200,
|
||||||
|
|
@ -21,7 +22,8 @@
|
||||||
{"_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"},
|
||||||
{"_type": "Personality", "hearing_distance": 5, "tough": false},
|
{"_type": "Personality", "hearing_distance": 5, "tough": false},
|
||||||
{"_type": "LightSource", "strength": 35, "radius": 2.0}
|
{"_type": "LightSource", "strength": 35, "radius": 2.0},
|
||||||
|
{"_type": "LearnByDoing", "attacks": 0, "hits": 0, "next_attack_level": 10, "next_toughness_level": 10}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"SPIDER_BOT": {
|
"SPIDER_BOT": {
|
||||||
|
|
@ -30,7 +32,8 @@
|
||||||
"foreground": "enemies/fg:rat_giant",
|
"foreground": "enemies/fg:rat_giant",
|
||||||
"background": "color:transparent"
|
"background": "color:transparent"
|
||||||
},
|
},
|
||||||
{"_type": "Combat", "max_hp": 50, "max_ap": 12, "ap_delta": 6,"damage": 30,
|
{"_type": "Combat", "max_hp": 50, "max_ap": 12,
|
||||||
|
"ap_delta": 6,"damage": 20, "attack_rating": 0.6, "toughness_rating": 0.2,
|
||||||
"body_parts": {
|
"body_parts": {
|
||||||
"head": 50,
|
"head": 50,
|
||||||
"chest": 50,
|
"chest": 50,
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,14 @@
|
||||||
|
|
||||||
namespace components {
|
namespace components {
|
||||||
int Combat::attack(Combat &target) {
|
int Combat::attack(Combat &target) {
|
||||||
int attack = 1;
|
float hit_prob = Random::uniform_real(0.0f, 1.0f);
|
||||||
|
|
||||||
int my_dmg = 0;
|
int my_dmg = 0;
|
||||||
|
|
||||||
my_dmg = Random::uniform<int>(1, damage);
|
if(hit_prob < attack_rating) {
|
||||||
|
my_dmg = std::ceil(Random::uniform_real(1.0f, float(damage)) * (1.0f - toughness_rating));
|
||||||
target.take_damage(my_dmg);
|
target.take_damage(my_dmg);
|
||||||
|
}
|
||||||
|
|
||||||
return my_dmg;
|
return my_dmg;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,5 +45,6 @@ namespace game {
|
||||||
TRAP=__LINE__,
|
TRAP=__LINE__,
|
||||||
UPDATE_SPRITE=__LINE__,
|
UPDATE_SPRITE=__LINE__,
|
||||||
USE_ITEM=__LINE__,
|
USE_ITEM=__LINE__,
|
||||||
|
LEVEL_UP=__LINE__,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ namespace components {
|
||||||
components::enroll<Sprite>(MAP);
|
components::enroll<Sprite>(MAP);
|
||||||
components::enroll<Sound>(MAP);
|
components::enroll<Sound>(MAP);
|
||||||
components::enroll<Collision>(MAP);
|
components::enroll<Collision>(MAP);
|
||||||
|
components::enroll<LearnByDoing>(MAP);
|
||||||
MAP_configured = true;
|
MAP_configured = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,11 +108,21 @@ namespace components {
|
||||||
int hp = 10;
|
int hp = 10;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LearnByDoing {
|
||||||
|
int attacks=0;
|
||||||
|
int hits=0;
|
||||||
|
int next_attack_level=10;
|
||||||
|
int next_toughness_level=10;
|
||||||
|
};
|
||||||
|
|
||||||
struct Combat {
|
struct Combat {
|
||||||
int max_hp=1;
|
int max_hp=1;
|
||||||
int ap_delta=1;
|
int ap_delta=1;
|
||||||
int max_ap=1;
|
int max_ap=1;
|
||||||
int damage=1;
|
int damage=1;
|
||||||
|
float attack_rating=0.01;
|
||||||
|
float toughness_rating=0.01;
|
||||||
|
|
||||||
std::unordered_map<std::string, int> body_parts{
|
std::unordered_map<std::string, int> body_parts{
|
||||||
{"head", 10},
|
{"head", 10},
|
||||||
{"chest", 10},
|
{"chest", 10},
|
||||||
|
|
@ -177,11 +187,12 @@ 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, max_hp, ap_delta, max_ap, damage, body_parts);
|
ENROLL_COMPONENT(Combat, max_hp, ap_delta, max_ap, damage, attack_rating, toughness_rating, 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);
|
||||||
ENROLL_COMPONENT(Collision, has);
|
ENROLL_COMPONENT(Collision, has);
|
||||||
|
ENROLL_COMPONENT(LearnByDoing, attacks, hits, next_attack_level, next_toughness_level);
|
||||||
|
|
||||||
template<typename COMPONENT> COMPONENT convert(nlohmann::json &data) {
|
template<typename COMPONENT> COMPONENT convert(nlohmann::json &data) {
|
||||||
COMPONENT result;
|
COMPONENT result;
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,7 @@ void System::combat(int attack_id) {
|
||||||
// player shouldn't hit theirself
|
// player shouldn't hit theirself
|
||||||
if(host_state != BattleHostState::not_host) continue;
|
if(host_state != BattleHostState::not_host) continue;
|
||||||
|
|
||||||
|
// BUG: really this should be attacker and receiver so I don't need the above line
|
||||||
components::CombatResult result {
|
components::CombatResult result {
|
||||||
.attacker=enemy.entity,
|
.attacker=enemy.entity,
|
||||||
.host_state=host_state,
|
.host_state=host_state,
|
||||||
|
|
@ -286,10 +287,38 @@ void System::combat(int attack_id) {
|
||||||
animation::animate_entity(world, enemy.entity);
|
animation::animate_entity(world, enemy.entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System::learn_by_doing(result);
|
||||||
world.send<game::Event>(game::Event::COMBAT, enemy.entity, result);
|
world.send<game::Event>(game::Event::COMBAT, enemy.entity, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void System::learn_by_doing(components::CombatResult& result) {
|
||||||
|
auto& level = GameDB::current_level();
|
||||||
|
auto& world = *level.world;
|
||||||
|
auto& combat = world.get<components::Combat>(level.player);
|
||||||
|
auto& lbd = world.get<components::LearnByDoing>(level.player);
|
||||||
|
|
||||||
|
if(result.player_did > 0) {
|
||||||
|
lbd.attacks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result.enemy_did > 0) {
|
||||||
|
lbd.hits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lbd.attacks > lbd.next_attack_level) {
|
||||||
|
// they leveled up
|
||||||
|
combat.attack_rating += 0.01;
|
||||||
|
lbd.next_attack_level = lbd.next_attack_level * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lbd.hits > lbd.next_toughness_level) {
|
||||||
|
// they leveled up
|
||||||
|
combat.toughness_rating += 0.01;
|
||||||
|
lbd.next_toughness_level = lbd.next_toughness_level * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void System::collision() {
|
void System::collision() {
|
||||||
auto& level = GameDB::current_level();
|
auto& level = GameDB::current_level();
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ namespace System {
|
||||||
|
|
||||||
void enemy_ai();
|
void enemy_ai();
|
||||||
void combat(int attack_id);
|
void combat(int attack_id);
|
||||||
|
void learn_by_doing(components::CombatResult& result);
|
||||||
|
|
||||||
std::shared_ptr<sf::Shader> sprite_effect(Entity entity);
|
std::shared_ptr<sf::Shader> sprite_effect(Entity entity);
|
||||||
void distribute_loot(Position target_pos);
|
void distribute_loot(Position target_pos);
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,7 @@ void WorldBuilder::configure_starting_items(DinkyECS::World &world) {
|
||||||
world.make_constant(healing);
|
world.make_constant(healing);
|
||||||
|
|
||||||
auto sword = System::spawn_item(world, "SWORD_1");
|
auto sword = System::spawn_item(world, "SWORD_1");
|
||||||
inventory.add("hand_main", sword);
|
inventory.add("weapon", sword);
|
||||||
world.make_constant(sword);
|
world.make_constant(sword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,26 @@ namespace gui {
|
||||||
"[right_arm]"
|
"[right_arm]"
|
||||||
"[left_arm]"
|
"[left_arm]"
|
||||||
"[right_leg]"
|
"[right_leg]"
|
||||||
"[left_leg]");
|
"[left_leg]"
|
||||||
|
"[=*%(200,100)attack|_|attack_rating]"
|
||||||
|
"[=*%(200,100)toughness|_|toughness_rating]");
|
||||||
|
|
||||||
$gui.set<Background>($gui.MAIN, {$gui.$parser, });
|
$gui.set<Background>($gui.MAIN, {$gui.$parser, });
|
||||||
|
|
||||||
for(auto& [name, cell] : $gui.cells()) {
|
for(auto& [name, cell] : $gui.cells()) {
|
||||||
auto gui_id = $gui.entity(name);
|
auto gui_id = $gui.entity(name);
|
||||||
|
|
||||||
|
if(name.starts_with("attack")) {
|
||||||
|
$gui.set<Rectangle>(gui_id, {});
|
||||||
|
$gui.set<Text>(gui_id, {L"Attack"});
|
||||||
|
} else if(name.starts_with("toughness")) {
|
||||||
|
$gui.set<Rectangle>(gui_id, {});
|
||||||
|
$gui.set<Text>(gui_id, {L"Toughness"});
|
||||||
|
} else {
|
||||||
$gui.set<Text>(gui_id, {guecs::to_wstring(name)});
|
$gui.set<Text>(gui_id, {guecs::to_wstring(name)});
|
||||||
$gui.set<Meter>(gui_id, {1.0f, THEME.DARK_MID, {}});
|
$gui.set<Meter>(gui_id, {1.0f, THEME.DARK_MID, {}});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$gui.init();
|
$gui.init();
|
||||||
update();
|
update();
|
||||||
|
|
@ -50,10 +60,23 @@ namespace gui {
|
||||||
|
|
||||||
if(auto meter = $gui.get_if<Meter>(gui_id)) {
|
if(auto meter = $gui.get_if<Meter>(gui_id)) {
|
||||||
meter->percent = float(value) / float(player_combat.max_hp);
|
meter->percent = float(value) / float(player_combat.max_hp);
|
||||||
|
|
||||||
|
if(meter->percent < 0.2) {
|
||||||
|
meter->color = sf::Color(220, 10, 10, 255);
|
||||||
|
} else {
|
||||||
|
meter->color = THEME.DARK_MID;
|
||||||
}
|
}
|
||||||
|
|
||||||
$gui.show_text(key, fmt::format(L"{}: {}", guecs::to_wstring(key), value));
|
// BUG: gross, make it stop
|
||||||
|
meter->bar.shape->setFillColor(meter->color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$gui.show_text(key, fmt::format(L"{}", guecs::to_wstring(key), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// update learn by doing
|
||||||
|
$gui.show_text("attack_rating", fmt::format(L"{}", int(player_combat.attack_rating * 100.0f)));
|
||||||
|
$gui.show_text("toughness_rating", fmt::format(L"{}", int(player_combat.toughness_rating * 100.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BodyUI::render(sf::RenderWindow &window) {
|
void BodyUI::render(sf::RenderWindow &window) {
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,11 @@ namespace gui {
|
||||||
void FSM::INTRO(Event ev) {
|
void FSM::INTRO(Event ev) {
|
||||||
dbc::check($story != nullptr, "you forgot the stroy");
|
dbc::check($story != nullptr, "you forgot the stroy");
|
||||||
|
|
||||||
if($story->playing()) {
|
|
||||||
if(ev == game::Event::MOUSE_CLICK) {
|
if(ev == game::Event::MOUSE_CLICK) {
|
||||||
$story->stop();
|
$story->stop();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
if(!$story->playing()) {
|
||||||
$story = nullptr;
|
$story = nullptr;
|
||||||
state(State::IDLE);
|
state(State::IDLE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,14 @@ namespace gui {
|
||||||
{
|
{
|
||||||
$gui.position(x, y, width, height);
|
$gui.position(x, y, width, height);
|
||||||
$gui.layout(
|
$gui.layout(
|
||||||
"[*%(100, 300)body_ui]"
|
"[*%(100, 400)body_ui]"
|
||||||
|
"[_]"
|
||||||
"[_]"
|
"[_]"
|
||||||
"[_]"
|
"[_]"
|
||||||
"[=inv0|=inv1|=inv2]"
|
"[=inv0|=inv1|=inv2]"
|
||||||
"[=inv3|=inv4|=inv5]"
|
"[=inv3|=inv4|=inv5]"
|
||||||
"[=inv6|=inv7|=inv8]"
|
"[=inv6|=inv7|=inv8]"
|
||||||
"[=hand_main]"
|
"[=weapon]");
|
||||||
"[=hand_off]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusUI::init() {
|
void StatusUI::init() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue