Skip to content

Commit

Permalink
Add support for damage overtime and move super healing from panacea t…
Browse files Browse the repository at this point in the history
…o Aftershock (#40082)

* Damage over time initial implementation

* Unhardcode healing from panacea and move it to Aftershock

* Update src/creature.cpp

Co-authored-by: Curtis Merrill <curtis.r.merrill@gmail.com>

* DoT class

* Save and load DoT

* doc

* Apply suggestions from code review

Co-authored-by: Curtis Merrill <curtis.r.merrill@gmail.com>

* serialize, deserialize and load in proper cdda fashion

Co-authored-by: Curtis Merrill <curtis.r.merrill@gmail.com>
  • Loading branch information
Fris0uman and KorGgenT authored May 4, 2020
1 parent 7780822 commit 11714a3
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 7 deletions.
23 changes: 23 additions & 0 deletions data/mods/Aftershock/items/comestibles.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,28 @@
{ "id": "downed", "duration": 1 }
]
}
},
{
"id": "panacea",
"type": "COMESTIBLE",
"comestible_type": "MED",
"name": { "str": "Panaceus", "str_pl": "Panaceii" },
"symbol": "!",
"color": "red",
"copy-from": "panacea",
"use_action": {
"type": "consume_drug",
"activation_message": "You feel AMAZING!",
"effects": [ { "id": "panacea", "duration": "1 m" }, { "id": "cureall" } ],
"damage_over_time": [
{
"damage_type": "true",
"duration": "1 m",
"amount": -10,
"bodyparts": [ "torso", "head", "arm_l", "leg_l", "arm_r", "leg_r" ]
}
]
},
"flags": [ "NPC_SAFE", "IRREPLACEABLE_CONSUMABLE" ]
}
]
8 changes: 8 additions & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2292,6 +2292,14 @@ The contents of use_action fields can either be a string indicating a built-in f
"type" : "consume_drug", // A drug the player can consume.
"activation_message" : "You smoke your crack rocks. Mother would be proud.", // Message, ayup.
"effects" : { "high": 15 }, // Effects and their duration.
"damage_over_time": [
{
"damage_type": "true", // Type of damage
"duration": "1 m", // For how long this damage will be applied
"amount": -10, // Amount of damage applied every turn, negative damage heals
"bodyparts": [ "torso", "head", "arm_l", "leg_l", "arm_r", "leg_r" ] // Body parts hit by the damage
}
]
"stat_adjustments": {"hunger" : -10}, // Adjustment to make to player stats.
"fields_produced" : {"cracksmoke" : 2}, // Fields to produce, mostly used for smoke.
"charges_needed" : { "fire" : 1 }, // Charges to use in the process of consuming the drug.
Expand Down
5 changes: 5 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8691,6 +8691,11 @@ int Character::reduce_healing_effect( const efftype_id &eff_id, int remove_med,
return intensity;
}

void Character::heal_bp( bodypart_id bp, int dam )
{
heal( bp->token, dam );
}

void Character::heal( body_part healed, int dam )
{
hp_part healpart;
Expand Down
1 change: 1 addition & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ class Character : public Creature, public visitable<Character>
/** Handles effects that happen when the player is damaged and aware of the fact. */
void on_hurt( Creature *source, bool disturb = true );
/** Heals a body_part for dam */
void heal_bp( bodypart_id bp, int dam ) override;
void heal( body_part healed, int dam );
/** Heals an hp_part for dam */
void heal( hp_part healed, int dam );
Expand Down
31 changes: 31 additions & 0 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ void Creature::process_turn()

process_effects();

process_damage_over_time();

// Call this in case any effects have changed our stats
reset_stats();

Expand Down Expand Up @@ -898,6 +900,10 @@ void Creature::deal_damage_handle_type( const damage_unit &du, bodypart_id bp, i
pain += roll_remainder( adjusted_damage / div );
}

void Creature::heal_bp( bodypart_id /* bp */, int /* dam */ )
{
}

/*
* State check functions
*/
Expand Down Expand Up @@ -1684,6 +1690,31 @@ body_part Creature::select_body_part( Creature *source, int hit_roll ) const
return human_anatomy->select_body_part( szdif, hit_roll )->token;
}

void Creature::add_damage_over_time( const damage_over_time_data &DoT )
{
damage_over_time_map.emplace_back( DoT );
}

void Creature::process_damage_over_time()
{
for( auto DoT = damage_over_time_map.begin(); DoT != damage_over_time_map.end(); ) {
if( DoT->duration > 0_turns ) {
for( const bodypart_str_id &bp : DoT->bps ) {
const int dmg_amount = DoT->amount;
if( dmg_amount < 0 ) {
heal_bp( bp.id(), -dmg_amount );
} else {
deal_damage( nullptr, bp.id(), damage_instance( DoT->type, dmg_amount ) );
}
}
DoT->duration -= 1_turns;
++DoT;
} else {
damage_over_time_map.erase( DoT );
}
}
}

void Creature::check_dead_state()
{
if( is_dead_state() ) {
Expand Down
9 changes: 9 additions & 0 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "anatomy.h"
#include "bodypart.h"
#include "damage.h"
#include "pimpl.h"
#include "string_formatter.h"
#include "translations.h"
Expand Down Expand Up @@ -265,6 +266,8 @@ class Creature
virtual void apply_damage( Creature *source, bodypart_id bp, int amount,
bool bypass_med = false ) = 0;

virtual void heal_bp( bodypart_id bp, int dam );

/**
* This creature just dodged an attack - possibly special/ranged attack - from source.
* Players should train dodge, monsters may use some special defenses.
Expand Down Expand Up @@ -754,6 +757,9 @@ class Creature
virtual void process_one_effect( effect &e, bool is_new ) = 0;

pimpl<effects_map> effects;

std::vector<damage_over_time_data> damage_over_time_map;

// Miscellaneous key/value pairs.
std::unordered_map<std::string, std::string> values;

Expand Down Expand Up @@ -800,6 +806,9 @@ class Creature
public:
body_part select_body_part( Creature *source, int hit_roll ) const;

void add_damage_over_time( const damage_over_time_data &DoT );
void process_damage_over_time();

static void load_hit_range( const JsonObject & );
// Empirically determined by "synthetic_range_test" in tests/ranged_balance.cpp.
static std::vector <int> dispersion_for_even_chance_of_good_hit;
Expand Down
35 changes: 35 additions & 0 deletions src/damage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <utility>

#include "debug.h"
#include "generic_factory.h"
#include "item.h"
#include "json.h"
#include "monster.h"
Expand Down Expand Up @@ -426,3 +427,37 @@ resistances load_resistances_instance( const JsonObject &jo )
ret.resist_vals = load_damage_array( jo );
return ret;
}

void damage_over_time_data::load( const JsonObject &obj )
{
std::string tmp_string;
mandatory( obj, was_loaded, "damage_type", tmp_string );
type = dt_by_name( tmp_string );
mandatory( obj, was_loaded, "amount", amount );
mandatory( obj, was_loaded, "bodyparts", bps );

if( obj.has_string( "duration" ) ) {
duration = read_from_json_string<time_duration>( *obj.get_raw( "duration" ), time_duration::units );
} else {
duration = time_duration::from_turns( obj.get_int( "duration", 0 ) );
}
}

void damage_over_time_data::serialize( JsonOut &jsout ) const
{
jsout.start_object();
jsout.member( "damage_type", name_by_dt( type ) );
jsout.member( "duration", duration );
jsout.member( "amount", amount );
jsout.member( "bodyparts", bps );
jsout.end_object();
}

void damage_over_time_data::deserialize( JsonIn &jsin )
{
const JsonObject &jo = jsin.get_object();
type = dt_by_name( jo.get_string( "damage_type" ) );
jo.read( "amount", amount );
jo.read( "duration", duration );
jo.read( "bodyparts", bps );
}
17 changes: 17 additions & 0 deletions src/damage.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <string>

#include "type_id.h"
#include "calendar.h"

class item;
class monster;
Expand Down Expand Up @@ -86,6 +87,22 @@ struct damage_instance {
void deserialize( JsonIn & );
};

class damage_over_time_data
{
public:
damage_type type;
time_duration duration;
std::vector<bodypart_str_id> bps;
int amount;

bool was_loaded;

void load( const JsonObject &obj );

void serialize( JsonOut &jsout ) const;
void deserialize( JsonIn &jsin );
};

struct dealt_damage_instance {
std::array<int, NUM_DT> dealt_dams;
body_part bp_hit;
Expand Down
7 changes: 7 additions & 0 deletions src/iuse_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "clothing_mod.h"
#include "crafting.h"
#include "creature.h"
#include "damage.h"
#include "debug.h"
#include "effect.h"
#include "enum_conversions.h"
Expand All @@ -34,6 +35,7 @@
#include "flat_set.h"
#include "game.h"
#include "game_inventory.h"
#include "generic_factory.h"
#include "int_id.h"
#include "inventory.h"
#include "item.h"
Expand Down Expand Up @@ -702,6 +704,7 @@ void consume_drug_iuse::load( const JsonObject &obj )
effects.push_back( load_effect_data( e ) );
}
}
optional( obj, false, "damage_over_time", damage_over_time );
obj.read( "stat_adjustments", stat_adjustments );
obj.read( "fields_produced", fields_produced );
obj.read( "moves", moves );
Expand Down Expand Up @@ -778,6 +781,10 @@ int consume_drug_iuse::use( player &p, item &it, bool, const tripoint & ) const
}
p.add_effect( eff.id, dur, eff.bp, eff.permanent );
}
//Apply the various damage_over_time
for( const damage_over_time_data &Dot : damage_over_time ) {
p.add_damage_over_time( Dot );
}
for( const auto &stat_adjustment : stat_adjustments ) {
p.mod_stat( stat_adjustment.first, stat_adjustment.second );
}
Expand Down
5 changes: 4 additions & 1 deletion src/iuse_actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include <utility>
#include <vector>

#include "calendar.h"
#include "color.h"
#include "damage.h"
#include "enums.h"
#include "explosion.h"
#include "game_constants.h"
Expand Down Expand Up @@ -261,6 +261,9 @@ class consume_drug_iuse : public iuse_actor
/** Modify player vitamin_levels by random amount between min (first) and max (second) */
std::map<vitamin_id, std::pair<int, int>> vitamins;

/**List of damage over time applyed by this drug, negative damage heals*/
std::vector<damage_over_time_data> damage_over_time;

/** How many move points this action takes. */
int moves = 100;

Expand Down
5 changes: 5 additions & 0 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,11 @@ void monster::die_in_explosion( Creature *source )
die( source );
}

void monster::heal_bp( bodypart_id, int dam )
{
heal( dam );
}

bool monster::movement_impaired()
{
return effect_cache[MOVEMENT_IMPAIRED];
Expand Down
2 changes: 2 additions & 0 deletions src/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ class monster : public Creature
void explode();
// Let the monster die and let its body explode into gibs
void die_in_explosion( Creature *source );

void heal_bp( bodypart_id bp, int dam ) override;
/**
* Flat addition to the monsters @ref hp. If `overheal` is true, this is not capped by max hp.
* Returns actually healed hp.
Expand Down
6 changes: 0 additions & 6 deletions src/player_hardcoded_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1307,12 +1307,6 @@ void player::hardcoded_effects( effect &it )
// Just unpause, in case someone added it as a temporary effect (numbing poison etc.)
it.unpause_effect();
}
} else if( id == effect_panacea ) {
// restore health all body parts, dramatically reduce pain
for( int i = 0; i < num_hp_parts; i++ ) {
hp_cur[i] += 10;
}
mod_pain( -10 );
} else if( id == effect_toxin_buildup ) {
// Loosely based on toxic man-made compounds (mostly pesticides) which don't degrade
// easily, leading to build-up in muscle and fat tissue through bioaccumulation.
Expand Down
4 changes: 4 additions & 0 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "craft_command.h"
#include "creature.h"
#include "creature_tracker.h"
#include "damage.h"
#include "debug.h"
#include "effect.h"
#include "enum_conversions.h"
Expand Down Expand Up @@ -3042,6 +3043,7 @@ void Creature::store( JsonOut &jsout ) const
}
jsout.member( "effects", tmp_map );

jsout.member( "damage_over_time_map", damage_over_time_map );
jsout.member( "values", values );

jsout.member( "blocks_left", num_blocks );
Expand Down Expand Up @@ -3108,6 +3110,8 @@ void Creature::load( const JsonObject &jsin )
}
jsin.read( "values", values );

jsin.read( "damage_over_time_map", damage_over_time_map );

jsin.read( "blocks_left", num_blocks );
jsin.read( "dodges_left", num_dodges );
jsin.read( "num_blocks_bonus", num_blocks_bonus );
Expand Down

0 comments on commit 11714a3

Please sign in to comment.