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

Add effect add/remove scheduling #51952

Merged
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
26 changes: 26 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9000,6 +9000,32 @@ void Character::process_effects()
}
}

// Apply new effects from effect->effect chains
while( !scheduled_effects.empty() ) {
const auto &effect = scheduled_effects.front();

add_effect( effect_source::empty(),
effect.eff_id,
effect.dur,
effect.bp,
effect.permanent,
effect.intensity,
effect.force,
effect.deferred );

scheduled_effects.pop();
}

// Perform immediate effect removals
while( !terminating_effects.empty() ) {

const auto &effect = terminating_effects.front();

remove_effect( effect.eff_id, effect.bp );

terminating_effects.pop();
}

Creature::process_effects();
}

Expand Down
35 changes: 35 additions & 0 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ Creature &Creature::operator=( Creature && ) noexcept = default;

Creature::~Creature() = default;


std::queue<scheduled_effect> Creature::scheduled_effects = std::queue<scheduled_effect> {};
std::queue<terminating_effect> Creature::terminating_effects = std::queue<terminating_effect> {};

tripoint Creature::pos() const
{
return get_map().getlocal( location );
Expand Down Expand Up @@ -1340,6 +1344,28 @@ void Creature::add_effect( const effect_source &source, const efftype_id &eff_id
add_effect( source, eff_id, dur, bodypart_str_id::NULL_ID(), permanent, intensity, force,
deferred );
}

void Creature::schedule_effect( const effect &eff, bool force, bool deferred )
{
scheduled_effects.push( scheduled_effect{eff.get_id(), eff.get_duration(), eff.get_bp(),
eff.is_permanent(), eff.get_intensity(), force,
deferred} );
}
void Creature::schedule_effect( const efftype_id &eff_id, const time_duration &dur, bodypart_id bp,
bool permanent, int intensity, bool force, bool deferred )
{
scheduled_effects.push( scheduled_effect{eff_id, dur, bp,
permanent, intensity, force,
deferred} );
}
void Creature::schedule_effect( const efftype_id &eff_id,
const time_duration &dur, bool permanent, int intensity, bool force,
bool deferred )
{
scheduled_effects.push( scheduled_effect{eff_id, dur, bodypart_str_id::NULL_ID(),
permanent, intensity, force, deferred} );
}

bool Creature::add_env_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength,
const time_duration &dur, const bodypart_id &bp, bool permanent, int intensity, bool force )
{
Expand Down Expand Up @@ -1410,6 +1436,15 @@ bool Creature::remove_effect( const efftype_id &eff_id )
return remove_effect( eff_id, bodypart_str_id::NULL_ID() );
}

void Creature::schedule_effect_removal( const efftype_id &eff_id, const bodypart_id &bp )
{
terminating_effects.push( terminating_effect{eff_id, bp} );
}
void Creature::schedule_effect_removal( const efftype_id &eff_id )
{
return schedule_effect_removal( eff_id, bodypart_str_id::NULL_ID() );
}

bool Creature::has_effect( const efftype_id &eff_id, const bodypart_id &bp ) const
{
// bp_null means anything targeted or not
Expand Down
30 changes: 30 additions & 0 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <unordered_map>
#include <utility>
#include <vector>
#include <queue>

#include "bodypart.h"
#include "compatibility.h"
Expand Down Expand Up @@ -220,6 +221,21 @@ struct enum_traits<get_body_part_flags> {
static constexpr bool is_flag_enum = true;
};

using scheduled_effect = struct scheduled_effect_t {
efftype_id eff_id;
time_duration dur;
bodypart_id bp;
bool permanent = false;
int intensity = 0;
bool force = false;
bool deferred = false;
};

using terminating_effect = struct terminating_effect_t {
efftype_id eff_id;
bodypart_id bp;
};

class Creature : public viewer
{
public:
Expand Down Expand Up @@ -546,6 +562,15 @@ class Creature : public viewer
bool deferred = false );
void add_effect( const effect_source &source, const efftype_id &eff_id, const time_duration &dur,
bool permanent = false, int intensity = 0, bool force = false, bool deferred = false );
/** Schedules a new effect to be applied. Used during effect processing to avoid invalidating
current effects map. */
void schedule_effect( const effect &eff, bool force = false,
bool deferred = false );
void schedule_effect( const efftype_id &eff_id, const time_duration &dur,
bodypart_id bp, bool permanent = false, int intensity = 0, bool force = false,
bool deferred = false );
void schedule_effect( const efftype_id &eff_id, const time_duration &dur,
bool permanent = false, int intensity = 0, bool force = false, bool deferred = false );
/** Gives chance to save via environmental resist, returns false if resistance was successful. */
bool add_env_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength,
const time_duration &dur, const bodypart_id &bp, bool permanent = false, int intensity = 1,
Expand All @@ -557,6 +582,9 @@ class Creature : public viewer
* removed. */
bool remove_effect( const efftype_id &eff_id, const bodypart_id &bp );
bool remove_effect( const efftype_id &eff_id );
/** Schedule effect removal */
void schedule_effect_removal( const efftype_id &eff_id, const bodypart_id &bp );
void schedule_effect_removal( const efftype_id &eff_id );
/** Remove all effects. */
void clear_effects();
/** Check if creature has the matching effect. If the bodypart is not specified check if the Creature has any effect
Expand Down Expand Up @@ -1139,6 +1167,8 @@ class Creature : public viewer
virtual void process_one_effect( effect &e, bool is_new ) = 0;

pimpl<effects_map> effects;
static std::queue<scheduled_effect> scheduled_effects;
static std::queue<terminating_effect> terminating_effects;

std::vector<damage_over_time_data> damage_over_time_map;

Expand Down
37 changes: 19 additions & 18 deletions src/player_hardcoded_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ void Character::hardcoded_effects( effect &it )
formication_chance += 14400 - to_turns<int>( dur );
}
if( one_in( formication_chance ) ) {
add_effect( effect_formication, 60_minutes, bp );
schedule_effect( effect_formication, 60_minutes, bp );
}
if( dur < 1_days && one_in( 14400 ) ) {
vomit();
Expand All @@ -1190,7 +1190,7 @@ void Character::hardcoded_effects( effect &it )
}
}
get_event_bus().send<event_type::dermatik_eggs_hatch>( getID() );
remove_effect( effect_formication, bp );
schedule_effect_removal( effect_formication, bp );
moves -= 600;
triggered = true;
}
Expand Down Expand Up @@ -1264,7 +1264,7 @@ void Character::hardcoded_effects( effect &it )
} else if( one_in( 3000 ) ) {
add_msg_if_player( m_bad, _( "You notice a large abscess. You pick at it." ) );
const bodypart_id &itch = random_body_part( true );
add_effect( effect_formication, 60_minutes, itch );
schedule_effect( effect_formication, 60_minutes, itch );
mod_pain( 1 );
} else if( one_in( 3000 ) ) {
add_msg_if_player( m_bad,
Expand Down Expand Up @@ -1305,15 +1305,15 @@ void Character::hardcoded_effects( effect &it )
apply_damage( nullptr, bodypart_id( "head" ), rng( 0, 1 ) );
if( !has_effect( effect_visuals ) ) {
add_msg_if_player( m_bad, _( "Your vision is getting fuzzy." ) );
add_effect( effect_visuals, rng( 1_minutes, 60_minutes ) );
schedule_effect( effect_visuals, rng( 1_minutes, 60_minutes ) );
}
}
if( one_in( 24576 ) ) {
mod_healthy_mod( -10, -100 );
apply_damage( nullptr, bodypart_id( "head" ), rng( 1, 2 ) );
if( !is_blind() && !sleeping ) {
add_msg_if_player( m_bad, _( "Your vision goes black!" ) );
add_effect( effect_blind, rng( 5_turns, 20_turns ) );
schedule_effect( effect_blind, rng( 5_turns, 20_turns ) );
}
}
} else if( id == effect_tapeworm ) {
Expand All @@ -1336,8 +1336,8 @@ void Character::hardcoded_effects( effect &it )
add_miss_reason( _( "Your muscles are locking up and you can't fight effectively." ), 4 );
if( one_in( 3072 ) ) {
add_msg_if_player( m_bad, _( "Your muscles spasm." ) );
add_effect( effect_downed, rng( 1_turns, 4_turns ), false, 0, true );
add_effect( effect_stunned, rng( 1_turns, 4_turns ) );
schedule_effect( effect_downed, rng( 1_turns, 4_turns ), false, 0, true );
schedule_effect( effect_stunned, rng( 1_turns, 4_turns ) );
if( one_in( 10 ) ) {
mod_pain( rng( 1, 10 ) );
}
Expand All @@ -1359,7 +1359,8 @@ void Character::hardcoded_effects( effect &it )
}
if( zed_number > 0 ) {
//If intensity isn't pass the cap, average it with # of zeds
add_effect( effect_grabbed, 2_turns, bodypart_id( "torso" ), false, ( intense + zed_number ) / 2 );
schedule_effect( effect_grabbed, 2_turns, bodypart_id( "torso" ), false,
( intense + zed_number ) / 2 );
}
} else if( id == effect_bite ) {
bool recovered = false;
Expand Down Expand Up @@ -1417,7 +1418,7 @@ void Character::hardcoded_effects( effect &it )
if( !recovered ) {
// Move up to infection
if( dur > 6_hours ) {
add_effect( effect_infected, 1_turns, bp, true );
schedule_effect( effect_infected, 1_turns, bp, true );
// Set ourselves up for removal
it.set_duration( 0_turns );
} else if( has_effect( effect_strong_antibiotic ) ) {
Expand Down Expand Up @@ -1461,7 +1462,7 @@ void Character::hardcoded_effects( effect &it )
//~ %s is bodypart name.
add_msg_if_player( m_good, _( "Your %s wound begins to feel better!" ),
body_part_name( bp ) );
add_effect( effect_recover, 4 * dur );
schedule_effect( effect_recover, 4 * dur );
// Set ourselves up for removal
it.set_duration( 0_turns );
recovered = true;
Expand Down Expand Up @@ -1526,7 +1527,7 @@ void Character::hardcoded_effects( effect &it )
}
} else {
if( !has_effect( effect_slept_through_alarm ) ) {
add_effect( effect_slept_through_alarm, 1_turns, true );
schedule_effect( effect_slept_through_alarm, 1_turns, true );
}
// 10 minute cyber-snooze
it.mod_duration( 10_minutes );
Expand All @@ -1535,7 +1536,7 @@ void Character::hardcoded_effects( effect &it )
} else {
if( asleep && dur == 1_turns ) {
if( !has_effect( effect_slept_through_alarm ) ) {
add_effect( effect_slept_through_alarm, 1_turns, true );
schedule_effect( effect_slept_through_alarm, 1_turns, true );
}
// 10 minute automatic snooze
it.mod_duration( 10_minutes );
Expand Down Expand Up @@ -1583,9 +1584,9 @@ void Character::hardcoded_effects( effect &it )
if( one_turn_in( 3_days ) && !has_effect( effect_valium ) ) {
add_msg_if_player( m_bad, _( "You lose control of your body as it begins to convulse!" ) );
time_duration td = rng( 30_seconds, 4_minutes );
add_effect( effect_motor_seizure, td );
add_effect( effect_downed, td );
add_effect( effect_stunned, td );
schedule_effect( effect_motor_seizure, td );
schedule_effect( effect_downed, td );
schedule_effect( effect_stunned, td );
if( one_in( 3 ) ) {
add_msg_if_player( m_bad, _( "You lose consciousness!" ) );
fall_asleep( td );
Expand Down Expand Up @@ -1615,7 +1616,7 @@ void Character::hardcoded_effects( effect &it )
}
} else if( limb == "leg" ) {
if( dice( 4, 4 ) > get_dex() ) {
add_effect( effect_downed, rng( 5_seconds, 10_seconds ) );
schedule_effect( effect_downed, rng( 5_seconds, 10_seconds ) );
} else {
add_msg_if_player( m_neutral, _( "However, you manage to keep your footing." ) );
}
Expand All @@ -1625,8 +1626,8 @@ void Character::hardcoded_effects( effect &it )
if( one_turn_in( 2_days / mod ) && !has_effect( effect_valium ) ) {
add_msg_if_player( m_bad,
_( "You suddenly lose all muscle tone, and can't support your own weight!" ) );
add_effect( effect_motor_seizure, rng( 1_seconds, 2_seconds ) );
add_effect( effect_downed, rng( 5_seconds, 10_seconds ) );
schedule_effect( effect_motor_seizure, rng( 1_seconds, 2_seconds ) );
schedule_effect( effect_downed, rng( 5_seconds, 10_seconds ) );
}
mod *= 2;
/* fallthrough */
Expand Down