Skip to content

Commit

Permalink
Add EoC effect that deal damage (#77009)
Browse files Browse the repository at this point in the history
* deal damage eoc effect

* add proper talker_charactere override

* it was a test EoC, it should not be here

* add handling for monsters, document thing

* Update src/talker.h

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update src/npctalk.cpp

* Update doc/EFFECT_ON_CONDITION.md

Co-authored-by: Anton Burmistrov <[email protected]>

* remove unc, they can't be used with this EoC effect

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Anton Burmistrov <[email protected]>
  • Loading branch information
3 people authored Oct 18, 2024
1 parent ba026ac commit 54b5684
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 0 deletions.
34 changes: 34 additions & 0 deletions doc/EFFECT_ON_CONDITION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2607,6 +2607,40 @@ A loop of 10 iterations.

## Character effects

#### `u_deal_damage``npc_deal_damage`

Deal damage, the same way melee attack deals damage; it can't be dodged, but it can be mitigated by armor

| Syntax | Optionality | Value | Info |
| --- | --- | --- | --- |
| "u_deal_damage" / "npc_deal_damage" | **mandatory** | string or [variable object](#variable-object) | Damage type that would be dealt |
| "amount" | optional | int or [variable object](#variable-object) | Amount of damage that would be dealt; Default 0 |
| "bodypart" | optional | string or [variable object](#variable-object) | Bodypart that take the damage. Reminder that only characters can have limbs. Default is RANDOM |
| "arpen" | optional | int or [variable object](#variable-object) | Armor penetration of attack; Default 0 |
| "arpen_mult" | optional | int or [variable object](#variable-object) | Multiplier for armor penetration; Default 1 |
| "dmg_mult" | optional | int or [variable object](#variable-object) | Multiplier for damage amount. Default 1 |
| "min_hit" | optional | int or [variable object](#variable-object) | If bodypart is RANDOM, limit body part only to bodyparts that has `hit_size` bigger than this; default -1 |
| "max_hit" | optional | int or [variable object](#variable-object) | If bodypart is RANDOM, limit body part only to bodyparts that has `hit_size` smaller than this; default the size of your biggest body part |
| "can_attack_high" | optional | bool | If true, can attack limbs with flag LIMB_UPPER, if false, such limbs are discarded; Default true |
| "hit_roll" | optional | int or [variable object](#variable-object) | hit_roll |

##### Valid talkers:

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
| ✔️ | ✔️ | ✔️ | ✔️ |||

##### Examples

Deal 20 biological damage to your torso
```json
{
"type": "effect_on_condition",
"id": "TEST",
"effect": [ { "u_deal_damage": "biological", "amount": 20, "bodypart": "torso" } ]
},
```

#### `u_mutate``npc_mutate`

Your character or the NPC will attempt to mutate; used in mutation system, for other purposes it's better to use [`u_add_trait`](#`u_add_trait`, `npc_add_trait`)
Expand Down
57 changes: 57 additions & 0 deletions src/npctalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6436,6 +6436,62 @@ talk_effect_fun_t::func f_give_equipment( const JsonObject &jo, std::string_view
};
}


talk_effect_fun_t::func f_deal_damage( const JsonObject &jo, std::string_view member,
const std::string_view, bool is_npc )
{
str_or_var dmg_type = get_str_or_var( jo.get_member( member ), member );
dbl_or_var dmg_amount = get_dbl_or_var( jo, "amount", false, 0 );
dbl_or_var arpen = get_dbl_or_var( jo, "arpen", false, 0 );
dbl_or_var arpen_mult = get_dbl_or_var( jo, "arpen_mult", false, 1 );
dbl_or_var dmg_mult = get_dbl_or_var( jo, "dmg_mult", false, 1 );

dbl_or_var dbl_min_hit = get_dbl_or_var( jo, "min_hit", false, -1 );
dbl_or_var dbl_max_hit = get_dbl_or_var( jo, "max_hit", false, -1 );
dbl_or_var dbl_hit_roll = get_dbl_or_var( jo, "hit_roll", false, 0 );
bool can_attack_high = jo.get_bool( "can_attack_high", true );


str_or_var bodypart;

if( jo.has_member( "bodypart" ) ) {
bodypart = get_str_or_var( jo.get_member( "bodypart" ), "bodypart", false, "RANDOM" );
} else {
bodypart.str_val = "RANDOM";
}

return [is_npc, dmg_type, dmg_amount, bodypart, arpen, arpen_mult, dmg_mult, dbl_min_hit,
dbl_max_hit, dbl_hit_roll, can_attack_high]( dialogue & d ) {

damage_instance dmg_inst;
damage_type_id damage_type = damage_type_id( dmg_type.evaluate( d ) );
std::string const bp_str = bodypart.evaluate( d );
bodypart_id bp;

if( d.actor( is_npc )->get_character() ) {
if( bp_str == "RANDOM" ) {
Character &guy = *d.actor( is_npc )->get_character();
int min_hit = dbl_min_hit.evaluate( d );
int max_hit = dbl_max_hit.evaluate( d );
int hit_roll = dbl_hit_roll.evaluate( d );

if( max_hit == -1 ) {
max_hit = guy.get_max_hitsize_bodypart()->hit_size;
}
bp = guy.select_body_part( min_hit, max_hit, can_attack_high, hit_roll );
}
}

if( d.actor( is_npc )->get_monster() ) {
bp = bodypart_id( "bp_null" );
}

dmg_inst.add_damage( damage_type, dmg_amount.evaluate( d ), arpen.evaluate( d ),
arpen_mult.evaluate( d ), dmg_mult.evaluate( d ), 1, 1 );
d.actor( is_npc )->deal_damage( d.actor( is_npc )->get_creature(), bp, dmg_inst );
};
}

talk_effect_fun_t::func f_spawn_monster( const JsonObject &jo, std::string_view member,
const std::string_view src, bool is_npc )
{
Expand Down Expand Up @@ -7078,6 +7134,7 @@ parsers = {
{ "u_consume_item_sum", "npc_consume_item_sum", jarg::array, &talk_effect_fun::f_consume_item_sum },
{ "u_remove_item_with", "npc_remove_item_with", jarg::member, &talk_effect_fun::f_remove_item_with },
{ "u_bulk_trade_accept", "npc_bulk_trade_accept", jarg::member, &talk_effect_fun::f_bulk_trade_accept },
{ "u_deal_damage", "npc_deal_damage", jarg::member, &talk_effect_fun::f_deal_damage },
{ "u_bulk_donate", "npc_bulk_donate", jarg::member, &talk_effect_fun::f_bulk_trade_accept },
{ "u_cast_spell", "npc_cast_spell", jarg::member, &talk_effect_fun::f_cast_spell },
{ "u_map_run_item_eocs", "npc_map_run_item_eocs", jarg::member, &talk_effect_fun::f_map_run_item_eocs },
Expand Down
4 changes: 4 additions & 0 deletions src/talker.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,10 @@ class talker
virtual int attack_speed() const {
return 0;
}
virtual dealt_damage_instance deal_damage( Creature *, bodypart_id,
const damage_instance & ) const {
return dealt_damage_instance();
};
virtual double armor_at( damage_type_id &, bodypart_id & ) const {
return 0;
}
Expand Down
6 changes: 6 additions & 0 deletions src/talker_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ int talker_character_const::attack_speed() const
return me_chr_const->attack_speed( cur_weap );
}

dealt_damage_instance talker_character_const::deal_damage( Creature *source, bodypart_id bp,
const damage_instance &dam ) const
{
return source->deal_damage( source, bp, dam );
}

void talker_character::set_str_max( int value )
{
me_chr->str_max = value;
Expand Down
2 changes: 2 additions & 0 deletions src/talker_character.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class talker_character_const: public talker_cloner<talker_character_const>
int int_cur() const override;
int per_cur() const override;
int attack_speed() const override;
dealt_damage_instance deal_damage( Creature *source, bodypart_id bp,
const damage_instance &dam ) const override;
int pain_cur() const override;
int perceived_pain_cur() const override;
double armor_at( damage_type_id &dt, bodypart_id &bp ) const override;
Expand Down
6 changes: 6 additions & 0 deletions src/talker_monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ void talker_monster::set_all_parts_hp_cur( int set ) const
me_mon->set_hp( set );
}

dealt_damage_instance talker_monster::deal_damage( Creature *source, bodypart_id bp,
const damage_instance &dam ) const
{
return source->deal_damage( source, bp, dam );
}

std::vector<std::string> talker_monster_const::get_topics( bool )
{
return me_mon_const->type->chat_topics;
Expand Down
2 changes: 2 additions & 0 deletions src/talker_monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ class talker_monster: public talker_cloner<talker_monster, talker_monster_const>
void die() override;

void set_all_parts_hp_cur( int ) const override;
dealt_damage_instance deal_damage( Creature *source, bodypart_id bp,
const damage_instance &dam ) const override;
protected:
talker_monster() = default;
monster *me_mon;
Expand Down

0 comments on commit 54b5684

Please sign in to comment.