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
|
|
@ -4,11 +4,14 @@
|
|||
|
||||
namespace components {
|
||||
int Combat::attack(Combat &target) {
|
||||
int attack = 1;
|
||||
float hit_prob = Random::uniform_real(0.0f, 1.0f);
|
||||
|
||||
int my_dmg = 0;
|
||||
|
||||
my_dmg = Random::uniform<int>(1, damage);
|
||||
target.take_damage(my_dmg);
|
||||
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);
|
||||
}
|
||||
|
||||
return my_dmg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,5 +45,6 @@ namespace game {
|
|||
TRAP=__LINE__,
|
||||
UPDATE_SPRITE=__LINE__,
|
||||
USE_ITEM=__LINE__,
|
||||
LEVEL_UP=__LINE__,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace components {
|
|||
components::enroll<Sprite>(MAP);
|
||||
components::enroll<Sound>(MAP);
|
||||
components::enroll<Collision>(MAP);
|
||||
components::enroll<LearnByDoing>(MAP);
|
||||
MAP_configured = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,11 +108,21 @@ namespace components {
|
|||
int hp = 10;
|
||||
};
|
||||
|
||||
struct LearnByDoing {
|
||||
int attacks=0;
|
||||
int hits=0;
|
||||
int next_attack_level=10;
|
||||
int next_toughness_level=10;
|
||||
};
|
||||
|
||||
struct Combat {
|
||||
int max_hp=1;
|
||||
int ap_delta=1;
|
||||
int max_ap=1;
|
||||
int damage=1;
|
||||
float attack_rating=0.01;
|
||||
float toughness_rating=0.01;
|
||||
|
||||
std::unordered_map<std::string, int> body_parts{
|
||||
{"head", 10},
|
||||
{"chest", 10},
|
||||
|
|
@ -177,11 +187,12 @@ namespace components {
|
|||
ENROLL_COMPONENT(EnemyConfig, ai_script, ai_start_name, ai_goal_name);
|
||||
ENROLL_COMPONENT(Personality, hearing_distance, tough);
|
||||
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(Storyboard, image, audio, layout, beats);
|
||||
ENROLL_COMPONENT(Sound, attack, death);
|
||||
ENROLL_COMPONENT(Collision, has);
|
||||
ENROLL_COMPONENT(LearnByDoing, attacks, hits, next_attack_level, next_toughness_level);
|
||||
|
||||
template<typename COMPONENT> COMPONENT convert(nlohmann::json &data) {
|
||||
COMPONENT result;
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ void System::combat(int attack_id) {
|
|||
// player shouldn't hit theirself
|
||||
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 {
|
||||
.attacker=enemy.entity,
|
||||
.host_state=host_state,
|
||||
|
|
@ -286,10 +287,38 @@ void System::combat(int attack_id) {
|
|||
animation::animate_entity(world, enemy.entity);
|
||||
}
|
||||
|
||||
System::learn_by_doing(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() {
|
||||
auto& level = GameDB::current_level();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ namespace System {
|
|||
|
||||
void enemy_ai();
|
||||
void combat(int attack_id);
|
||||
void learn_by_doing(components::CombatResult& result);
|
||||
|
||||
std::shared_ptr<sf::Shader> sprite_effect(Entity entity);
|
||||
void distribute_loot(Position target_pos);
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ void WorldBuilder::configure_starting_items(DinkyECS::World &world) {
|
|||
world.make_constant(healing);
|
||||
|
||||
auto sword = System::spawn_item(world, "SWORD_1");
|
||||
inventory.add("hand_main", sword);
|
||||
inventory.add("weapon", sword);
|
||||
world.make_constant(sword);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,15 +21,25 @@ namespace gui {
|
|||
"[right_arm]"
|
||||
"[left_arm]"
|
||||
"[right_leg]"
|
||||
"[left_leg]");
|
||||
"[left_leg]"
|
||||
"[=*%(200,100)attack|_|attack_rating]"
|
||||
"[=*%(200,100)toughness|_|toughness_rating]");
|
||||
|
||||
$gui.set<Background>($gui.MAIN, {$gui.$parser, });
|
||||
|
||||
for(auto& [name, cell] : $gui.cells()) {
|
||||
auto gui_id = $gui.entity(name);
|
||||
|
||||
$gui.set<Text>(gui_id, {guecs::to_wstring(name)});
|
||||
$gui.set<Meter>(gui_id, {1.0f, THEME.DARK_MID, {}});
|
||||
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<Meter>(gui_id, {1.0f, THEME.DARK_MID, {}});
|
||||
}
|
||||
}
|
||||
|
||||
$gui.init();
|
||||
|
|
@ -50,10 +60,23 @@ namespace gui {
|
|||
|
||||
if(auto meter = $gui.get_if<Meter>(gui_id)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// BUG: gross, make it stop
|
||||
meter->bar.shape->setFillColor(meter->color);
|
||||
}
|
||||
|
||||
$gui.show_text(key, fmt::format(L"{}: {}", guecs::to_wstring(key), value));
|
||||
$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) {
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ namespace gui {
|
|||
void FSM::INTRO(Event ev) {
|
||||
dbc::check($story != nullptr, "you forgot the stroy");
|
||||
|
||||
if($story->playing()) {
|
||||
if(ev == game::Event::MOUSE_CLICK) {
|
||||
$story->stop();
|
||||
}
|
||||
} else {
|
||||
if(ev == game::Event::MOUSE_CLICK) {
|
||||
$story->stop();
|
||||
}
|
||||
|
||||
if(!$story->playing()) {
|
||||
$story = nullptr;
|
||||
state(State::IDLE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ namespace gui {
|
|||
{
|
||||
$gui.position(x, y, width, height);
|
||||
$gui.layout(
|
||||
"[*%(100, 300)body_ui]"
|
||||
"[*%(100, 400)body_ui]"
|
||||
"[_]"
|
||||
"[_]"
|
||||
"[_]"
|
||||
"[=inv0|=inv1|=inv2]"
|
||||
"[=inv3|=inv4|=inv5]"
|
||||
"[=inv6|=inv7|=inv8]"
|
||||
"[=hand_main]"
|
||||
"[=hand_off]");
|
||||
"[=weapon]");
|
||||
}
|
||||
|
||||
void StatusUI::init() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue