Skip to content

Commit

Permalink
Adjust effect intensity decay (CleverRaven#51374)
Browse files Browse the repository at this point in the history
* Effect test

* Tested, doc updated

Fungal spores and per venom works

* Have cake, eat it

Martial arts' funcionality is protected from intensity-based removal, docs updated

Co-authored-by: actual-nh <[email protected]>
  • Loading branch information
Venera3 and actual-nh authored Sep 12, 2021
1 parent 30d3cd9 commit ee43beb
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 40 deletions.
11 changes: 11 additions & 0 deletions data/mods/TEST_DATA/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"rating": "good",
"max_duration": "1 h",
"max_intensity": 10,
"int_decay_tick": 2,
"base_mods": {
"str_mod": [ 1 ],
"dex_mod": [ 2 ],
Expand Down Expand Up @@ -76,6 +77,16 @@
"max_intensity": 3,
"chance_kill": [ [ 0, 1 ], [ 1, 10 ], [ 1, 1 ] ]
},
{
"type": "effect_type",
"id": "test_int_remove",
"name": [ "Protected from removal" ],
"desc": [ "Don't worry, you can't run out of steam!" ],
"int_decay_remove": false,
"max_intensity": 4,
"int_decay_step": -2,
"int_decay_tick": 1
},
{
"type": "effect_type",
"id": "max_effected",
Expand Down
18 changes: 10 additions & 8 deletions doc/EFFECTS_JSON.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ in "removes_effects" are automatically added to "blocks_effects", no need for ma

### Effect limiters
```C++
"max_duration": 100,
"dur_add_perc": 150 - Defaults to 100%
"max_duration": 100, - Time duration string, defaults to 365 days
"dur_add_perc": 150 - Defaults to 100(%)
```
These are utilized when adding to currently existing effects. "max_duration" limits the overall duration of the effect.
"dur_add_perc" is the percentage value of the normal duration for adding to an existing. An example:
Expand All @@ -230,11 +230,12 @@ future applications decreasing the overall time left.

### Intensities
Intensities are used to control effect effects, names, and descriptions. They are defined with:
```C++
"int_add_val": 2 - Defaults to 0! This means future applications will not increase intensity unless changed!
and/or
"int_decay_step": -2, - Defaults to -1
"int_decay_tick": 10
```JSON
"int_add_val": 2 - Int, defaults to 0 meaning future applications will not increase intensity

"int_decay_step": -2, - Int, default -1, intensity levels removed every decay tick
"int_decay_tick": 10 - Int, seconds between intensity decay (no decay at the default of 0)
"int_decay_remove": true - Bool, default true, removes the intensity if decay would decrease it to zero
or
"int_dur_factor": 700
```
Expand All @@ -245,7 +246,8 @@ Because "int_add_val" = 2, the second addition will change the effect intensity
NOTE: You must have at least one of the 3 intensity data sets for intensity to do anything!

"int_decay_step" and "int_decay_tick" require one another to do anything. If both exist then the game will automatically
increment the current effect intensities by "int_decay_step" every "int_decay_tick" ticks, capping the result at [1, "max_intensity"].
increment the current effect intensities by "int_decay_step" every "int_decay_tick" ticks, capping the result at [0, "max_intensity"]
and removing effects if the intensity reaches zero and `int_decay_remove` is true.
This can be used to make effects automatically increase or decrease in intensity over time.

"int_dur_factor" overrides the other three intensities fields, and forces the intensity to be a number defined as
Expand Down
4 changes: 2 additions & 2 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,7 @@ void Creature::add_effect( const effect_source &source, const efftype_id &eff_id
// If we do, mod the duration, factoring in the mod value
e.mod_duration( dur * e.get_dur_add_perc() / 100 );
// Limit to max duration
if( e.get_max_duration() > 0_turns && e.get_duration() > e.get_max_duration() ) {
if( e.get_duration() > e.get_max_duration() ) {
e.set_duration( e.get_max_duration() );
}
// Adding a permanent effect makes it permanent
Expand Down Expand Up @@ -1282,7 +1282,7 @@ void Creature::add_effect( const effect_source &source, const efftype_id &eff_id
// Now we can make the new effect for application
effect e( effect_source( source ), &type, dur, bp.id(), permanent, intensity, calendar::turn );
// Bound to max duration
if( e.get_max_duration() > 0_turns && e.get_duration() > e.get_max_duration() ) {
if( e.get_duration() > e.get_max_duration() ) {
e.set_duration( e.get_max_duration() );
}

Expand Down
47 changes: 33 additions & 14 deletions src/effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,12 +818,15 @@ std::string effect::disp_short_desc( bool reduced ) const
void effect::decay( std::vector<efftype_id> &rem_ids, std::vector<bodypart_id> &rem_bps,
const time_point &time, const bool player )
{
// Decay intensity if supposed to do so
// TODO: Remove effects that would decay to 0 intensity?
if( intensity > 1 && eff_type->int_decay_tick != 0 &&
// Decay intensity if supposed to do so, removing effects at zero intensity
if( intensity > 0 && eff_type->int_decay_tick != 0 &&
to_turn<int>( time ) % eff_type->int_decay_tick == 0 &&
get_max_duration() > get_duration() ) {
set_intensity( intensity + eff_type->int_decay_step, player );
if( intensity <= 0 ) {
rem_ids.push_back( get_id() );
rem_bps.push_back( bp.id() );
}
}

// Add to removal list if duration is <= 0
Expand Down Expand Up @@ -852,8 +855,8 @@ time_duration effect::get_max_duration() const
void effect::set_duration( const time_duration &dur, bool alert )
{
duration = dur;
// Cap to max_duration if it exists
if( eff_type->max_duration > 0_turns && duration > eff_type->max_duration ) {
// Cap to max_duration
if( duration > eff_type->max_duration ) {
duration = eff_type->max_duration;
}

Expand Down Expand Up @@ -989,17 +992,23 @@ int effect::set_intensity( int val, bool alert )
intensity = 1;
}

val = std::max( std::min( val, eff_type->max_intensity ), 1 );
val = std::max( std::min( val, eff_type->max_intensity ), 0 );
if( val == intensity ) {
// Nothing to change
return intensity;
}

if( alert && val < intensity && val - 1 < static_cast<int>( eff_type->decay_msgs.size() ) ) {
// Filter out intensity falling to zero (the effect will be removed later)
if( alert && val < intensity && val != 0 &&
val - 1 < static_cast<int>( eff_type->decay_msgs.size() ) ) {
add_msg( eff_type->decay_msgs[ val - 1 ].second,
eff_type->decay_msgs[ val - 1 ].first.translated() );
}

if( val == 0 && !eff_type->int_decay_remove ) {
val = 1;
}

intensity = val;

return intensity;
Expand Down Expand Up @@ -1333,6 +1342,21 @@ int effect::get_int_add_val() const
return eff_type->int_add_val;
}

int effect::get_int_decay_step() const
{
return eff_type->int_decay_step;
}

int effect::get_int_decay_tick() const
{
return eff_type->int_decay_tick;
}

bool effect::get_int_decay_remove() const
{
return eff_type->int_decay_remove;
}

const std::vector<std::pair<translation, int>> &effect::get_miss_msgs() const
{
return eff_type->miss_msgs;
Expand Down Expand Up @@ -1449,13 +1473,7 @@ void load_effect_type( const JsonObject &jo )
for( auto &&f : jo.get_string_array( "blocks_effects" ) ) { // *NOPAD*
new_etype.blocks_effects.emplace_back( f );
}

if( jo.has_string( "max_duration" ) ) {
new_etype.max_duration = read_from_json_string<time_duration>( jo.get_member( "max_duration" ),
time_duration::units );
} else {
new_etype.max_duration = time_duration::from_turns( jo.get_int( "max_duration", 0 ) );
}
optional( jo, false, "max_duration", new_etype.max_duration, 365_days );

if( jo.has_string( "int_dur_factor" ) ) {
new_etype.int_dur_factor = read_from_json_string<time_duration>( jo.get_member( "int_dur_factor" ),
Expand All @@ -1476,6 +1494,7 @@ void load_effect_type( const JsonObject &jo )
new_etype.int_add_val = jo.get_int( "int_add_val", 0 );
new_etype.int_decay_step = jo.get_int( "int_decay_step", -1 );
new_etype.int_decay_tick = jo.get_int( "int_decay_tick", 0 );
optional( jo, false, "int_decay_remove", new_etype.int_decay_remove, true );

new_etype.load_miss_msgs( jo, "miss_messages" );
new_etype.load_decay_msgs( jo, "decay_messages" );
Expand Down
16 changes: 12 additions & 4 deletions src/effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,15 @@ class effect_type
protected:
int max_intensity = 0;
int max_effective_intensity = 0;
time_duration max_duration = 0_turns;
time_duration max_duration = 365_days;

int dur_add_perc = 0;
int int_add_val = 0;

int int_decay_step = 0;
int int_decay_tick = 0 ;
time_duration int_dur_factor = 0_turns;
bool int_decay_remove = true;

std::set<flag_id> flags;

Expand Down Expand Up @@ -244,11 +245,11 @@ class effect
time_duration get_duration() const;
/** Returns the maximum duration of an effect. */
time_duration get_max_duration() const;
/** Sets the duration, capping at max_duration if it exists. */
/** Sets the duration, capping at max duration. */
void set_duration( const time_duration &dur, bool alert = false );
/** Mods the duration, capping at max_duration if it exists. */
/** Mods the duration, capping at max_duration. */
void mod_duration( const time_duration &dur, bool alert = false );
/** Multiplies the duration, capping at max_duration if it exists. */
/** Multiplies the duration, capping at max_duration. */
void mult_duration( double dur, bool alert = false );

std::vector<vitamin_applied_effect> vit_effects( bool reduced ) const;
Expand Down Expand Up @@ -338,6 +339,12 @@ class effect
time_duration get_int_dur_factor() const;
/** Returns the amount an already existing effect intensity is modified by further applications of the same effect. */
int get_int_add_val() const;
/** Returns the step of intensity decay */
int get_int_decay_step() const;
/** Returns the number of ticks between intensity changes */
int get_int_decay_tick() const;
/** Returns if the effect is not protected from intensity decay-based removal */
bool get_int_decay_remove() const;

/** Returns a vector of the miss message messages and chances for use in add_miss_reason() while the effect is in effect. */
const std::vector<std::pair<translation, int>> &get_miss_msgs() const;
Expand All @@ -348,6 +355,7 @@ class effect
/** Returns if the effect is supposed to be handed in Creature::movement */
bool impairs_movement() const;


/** Returns the effect's matching effect_type id. */
const efftype_id &get_id() const {
return eff_type->id;
Expand Down
1 change: 1 addition & 0 deletions src/martialarts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ class ma_buff_effect_type : public effect_type
int_decay_step = -1;
int_decay_tick = 1;
int_dur_factor = 0_turns;
int_decay_remove = false;
name.push_back( buff.name );
desc.push_back( buff.description );
rating = e_good;
Expand Down
Loading

0 comments on commit ee43beb

Please sign in to comment.