Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make ammo effect able to run EoC #75291

Merged
merged 2 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions doc/EFFECT_ON_CONDITION.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,40 @@ For example, `{ "npc_has_effect": "Shadow_Reveal" }`, used by shadow lieutenant,

### Typical Alpha and Beta Talkers by cases

| EOC | Alpha (possible types) | Beta (possible types) |
| ------------------------------------------------ | ---------------------- | --------------------------- |
| Talk with NPC | player (Avatar) | NPC (NPC) |
| EOC | Alpha (possible types) | Beta (possible types) | variables sent |
| ------------------------------------------------ | ---------------------- | --------------------------- | --------------------------- |
| Talk with NPC | player (Avatar) | NPC (NPC) | |
| Talk with monster | player (Avatar) | monster (monster) |
| Use computer | player (Avatar) | computer (Furniture) |
| furniture: "examine_action" | player (Avatar) | NONE |
| SPELL: "effect": "effect_on_condition" | target (Character, Monster) | spell caster (Character, Monster) |
| use_action: "type": "effect_on_conditions" | user (Character) | item (item) |
| use_action: "type": "effect_on_conditions" | user (Character) | item (item) | `id`, string, stores item id
| tick_action: "type": "effect_on_conditions" | carrier (Character) | item (item) |
| countdown_action: "type": "effect_on_conditions" | carrier (Character) | item (item) |
| COMESTIBLE: "consumption_effect_on_conditions" | user (Character) | item (item) |
| activity_type: "completion_eoc" | character (Character) | NONE |
| activity_type: "do_turn_eoc" | character (Character) | NONE |
| addiction_type: "effect_on_condition" | character (Character) | NONE |
| bionics: "activated_eocs" | character (Character) | NONE |
| bionics: "activated_eocs" | character (Character) | NONE | `act_cost`, int, cost of activation of item
| bionics: "deactivated_eocs" | character (Character) | NONE |
| bionics: "processed_eocs" | character (Character) | NONE |
| mutation: "activated_eocs" | character (Character) | NONE |
| mutation: "deactivated_eocs" | character (Character) | NONE |
| mutation: "processed_eocs" | character (Character) | NONE |
| recipe: "result_eocs" | crafter (Character) | NONE |
| monster death: "death_function" | killed monster (monster) | you (avatar) |
| monster death: "death_function" | victim (Creature) | NONE |
| ammo_effect: "eoc" | shooter (Creature) | victim (if exist, otherwise NONE) (Creature) | `proj_damage`, int, amount of damage projectile dealt. Detonation via SPECIAL_COOKOFF ammo effect return `proj_damage` as 1. Note that if projectile miss the target, EoC would be built without beta talker, so using EoC referencing `npc_` or `n_` would result in error. Use `has_beta` condition before manipulating with npc

Some actions sent additional context variables, that can be used in EoC, in format:

```json
{ "compare_string": [ "bio_uncanny_dodge", { "context_val": "id" } ] }
```

```json
{ "math": [ "_act_cost", "==", "2000" ] }
```

Using `use_action: "type": "effect_on_conditions"` automatically passes the context variable `id`, that stores the id of an item that was activated
Using `bionics: "activated_eocs"` automatically passes the context variable `act_cost` that stores the value of `act_cost` field
## Value types

Effect on Condition uses a huge variety of different values for effects or for conditions to check against, so to standardize it, most of them are explained here
Expand Down Expand Up @@ -278,6 +287,22 @@ Checks there is portal storm **and** you have `MAKAYLA_MUTATOR` mutation **and**

## Possible conditions

### `has_alpha`, `has_beta`
- type: simple string
- return true if alpha or beta talker exist

#### Valid talkers:

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

#### Examples
return true if beta talker exists
```json
"condition": "has_beta",
```

### `u_male`, `u_female`, `npc_male`, `npc_female`
- type: simple string
- return true if alpha or beta talker is male or female
Expand Down
1 change: 1 addition & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3588,6 +3588,7 @@ ammo_effects define what effect the projectile, that you shoot, would have. List
"do_flashbang": false, // Creates a one tile radius EMP explosion at the hit location; default false
"do_emp_blast": false // Creates a hardcoded flashbang explosion; default false
"foamcrete_build": false // Creates foamcrete fields and walls on the hit location, used in aftershock; default false
"eoc": [ "EOC_CAUSE_PAIN", "EOC_CAUSE_VOMIT" ], // Runs EoC when hit the target. See EFFECT_ON_CONDITION.md#typical-alpha-and-beta-talkers-by-cases for more information
"spell_data": { "id": "bear_trap" } // Spell, that would be casted when projectile hits an enemy
"spell_data": { "id": "release_the_deltas", "hit_self": true, "min_level": 10 }, //another example
"always_cast_spell ": false // if spell_data is used, and this is true, spell would be casted even if projectile did not deal any damage. Default false.
Expand Down
1 change: 1 addition & 0 deletions src/ammo_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ void ammo_effect::load( const JsonObject &jo, const std::string_view )
optional( jo, was_loaded, "do_flashbang", do_flashbang, false );
optional( jo, was_loaded, "do_emp_blast", do_emp_blast, false );
optional( jo, was_loaded, "foamcrete_build", foamcrete_build, false );
optional( jo, was_loaded, "eoc", eoc );
optional( jo, was_loaded, "spell_data", spell_data );
optional( jo, was_loaded, "always_cast_spell", always_cast_spell, false );

Expand Down
1 change: 1 addition & 0 deletions src/ammo_effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct ammo_effect {
bool do_flashbang = false;
bool do_emp_blast = false;
bool foamcrete_build = false;
std::vector<effect_on_condition_id> eoc;
bool always_cast_spell = false;

field_type_id trail_field_type = fd_null.id_or( INVALID_FIELD_TYPE_ID );
Expand Down
2 changes: 1 addition & 1 deletion src/ballistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ dealt_projectile_attack projectile_attack( const projectile &proj_arg, const tri

drop_or_embed_projectile( attack );

bool dealt_damage = attack.dealt_dam.total_damage() > 0;
int dealt_damage = attack.dealt_dam.total_damage();
apply_ammo_effects( null_source ? nullptr : origin, tp, proj.proj_effects, dealt_damage );
const explosion_data &expl = proj.get_custom_explosion();
if( expl.power > 0.0f ) {
Expand Down
16 changes: 16 additions & 0 deletions src/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,20 @@ conditional_t::func f_player_see( bool is_npc )
};
}

conditional_t::func f_has_alpha()
{
return []( dialogue const & d ) {
return d.has_alpha;
};
}

conditional_t::func f_has_beta()
{
return []( dialogue const & d ) {
return d.has_beta;
};
}

conditional_t::func f_no_assigned_mission()
{
return []( dialogue const & d ) {
Expand Down Expand Up @@ -2554,6 +2568,8 @@ parsers_simple = {
{"u_is_furniture", "npc_is_furniture", &conditional_fun::f_is_furniture },
{"has_ammo", &conditional_fun::f_has_ammo },
{"player_see_u", "player_see_npc", &conditional_fun::f_player_see },
{"has_alpha", &conditional_fun::f_has_alpha },
{"has_beta", &conditional_fun::f_has_beta },
};

conditional_t::conditional_t( const JsonObject &jo )
Expand Down
2 changes: 1 addition & 1 deletion src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12561,7 +12561,7 @@ bool item::detonate( const tripoint &p, std::vector<item> &drops )
const int rounds_exploded = rng( 1, charges_remaining / 2 );
if( type->ammo->special_cookoff ) {
// If it has a special effect just trigger it.
apply_ammo_effects( nullptr, p, type->ammo->ammo_effects, true );
apply_ammo_effects( nullptr, p, type->ammo->ammo_effects, 1 );
}
if( type->ammo->cookoff ) {
// If ammo type can burn, then create an explosion proportional to quantity.
Expand Down
4 changes: 2 additions & 2 deletions src/npctalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4330,11 +4330,11 @@ talk_effect_fun_t::func f_message( const JsonObject &jo, std::string_view member
return [snip_id, message, outdoor_only, sound, snippet, same_snippet, type_string,
popup_msg, popup_w_interrupt_query_msg, interrupt_type, global, is_npc]
( dialogue const & d ) {
Character *target;
Character const *target;
if( global ) {
target = &get_player_character();
} else {
target = d.actor( is_npc )->get_character();
target = static_cast<talker const *>( d.actor( is_npc ) )->get_character();
}
if( !target || target->is_npc() ) {
return;
Expand Down
18 changes: 16 additions & 2 deletions src/projectile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

#include "ammo_effect.h"
#include "character.h"
#include "condition.h"
#include "creature_tracker.h"
#include "debug.h"
#include "effect_on_condition.h"
#include "enums.h"
#include "explosion.h"
#include "field.h"
Expand Down Expand Up @@ -142,7 +145,7 @@ static void foamcrete_build( const tripoint &p )
}

void apply_ammo_effects( const Creature *source, const tripoint &p,
const std::set<ammo_effect_str_id> &effects, const bool dealt_damage )
const std::set<ammo_effect_str_id> &effects, const int dealt_damage )
{
map &here = get_map();
Character &player_character = get_player_character();
Expand Down Expand Up @@ -186,10 +189,21 @@ void apply_ammo_effects( const Creature *source, const tripoint &p,
if( ae.foamcrete_build ) {
foamcrete_build( p );
}

//run EoCs
for( const effect_on_condition_id &eoc : ae.eoc ) {
Creature *critter = get_creature_tracker().creature_at( p );
dialogue d( get_talker_for( *source ), critter == nullptr ? nullptr : get_talker_for( critter ) );
// `p` is tripoint relative to the upper left corner of currently loaded overmap
// not very useful for player's purposes methinks, but much appreciated
// write_var_value( var_type::context, "npctalk_var_proj_target_tripoint", &d, p.abs().to_string());
write_var_value( var_type::context, "npctalk_var_proj_damage", &d, dealt_damage );
eoc->activate( d );
}
//cast ammo effect spells
const spell ammo_spell = ae.spell_data.get_spell();
if( ammo_spell.is_valid() ) {
if( ae.always_cast_spell || dealt_damage ) {
if( ae.always_cast_spell || dealt_damage > 0 ) {
ammo_spell.cast_all_effects( *const_cast<Creature *>( source ), p );
ammo_spell.make_sound( p, *const_cast<Creature *>( source ) );
}
Expand Down
2 changes: 1 addition & 1 deletion src/projectile.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct dealt_projectile_attack {
};

void apply_ammo_effects( const Creature *source, const tripoint &p,
const std::set<ammo_effect_str_id> &effects, bool dealt_damage );
const std::set<ammo_effect_str_id> &effects, int dealt_damage );
int max_aoe_size( const std::set<ammo_effect_str_id> &tags );

void multi_projectile_hit_message( Creature *critter, int hit_count, int damage_taken,
Expand Down
Loading