Skip to content

Commit

Permalink
Cooldown changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramza13 committed May 27, 2024
1 parent 2c68074 commit 7bd1b9a
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
"id": "ratatosks_curse",
"cooldown": 10,
"move_cost": 100,
"attack_chance": 50,
"hitsize_min": 4,
"attack_upper": false,
"damage_max_instance": [ { "damage_type": "bash", "amount": 0 } ],
Expand Down
6 changes: 3 additions & 3 deletions doc/MONSTER_SPECIAL_ATTACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Generally [hardcoded special attacks](#hardcoded-special-attacks) are declared t

It contains either:
* An `id` of a [hardcoded special attack](#hardcoded-special-attacks), or a [JSON-declared attacks](/data/json/monster_special_attacks).
* A `type` member (string) plus a `cooldown` member (integer) pair, for [partially hardcoded special attacks](#partially-hardcoded-special-attacks).
* A `type` member (string) plus a `cooldown` member (integer or this can be a Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info.) pair, for [partially hardcoded special attacks](#partially-hardcoded-special-attacks).
* A spell (see [MAGIC.md](MAGIC.md)).

Depending on the kind of attack, it may contain additional required members. Example:
Expand Down Expand Up @@ -178,7 +178,7 @@ These special attacks are defined in [JSON](/data/json/monster_special_attacks),

| field | description
| --- | ---
| `cooldown` | Integer, amount of turns between uses.
| `cooldown` | Integer or Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info, amount of turns between uses.
| `damage_max_instance` | Array of objects. See also [MONSTERS.md#melee_damage](MONSTERS.md#melee_damage).
| `min_mul`, `max_mul` | Sets the bounds on the range of damage done. For each attack, the above defined amount of damage will be multiplied by a
| | randomly rolled multiplier between the values `min_mul` and `max_mul`. Default 0.5 and 1.0, meaning each attack will do at least half of the defined damage.
Expand Down Expand Up @@ -284,7 +284,7 @@ Casts a separately-defined spell at the monster's target. Spells with `target_s
| --- | ------------------------------------------------------------------------------------------------------- |
| `spell_data` | List of spell properties for the attack. |
| `min_level` | The level at which the spell is cast. Spells cast by monsters do not gain levels like player spells. |
| `cooldown ` | How often the monster can cast this spell.
| `cooldown ` | Integer or a Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info. How often the monster can cast this spell.
| `monster_message` | Message to print when the spell is cast, replacing the `message` in the spell definition. Dynamic fields correspond to `<Monster Display Name> / <Spell Name> / <Target name>`. |
| `condition` | Object, dialogue conditions enabling the attack. See `NPCs.md` for the possible conditions, `u` refers to the casting monster and `npc` to the target unless the spell allows no target (in which case only self-conditions can be defined).
| `allow_no_target` | Bool, default `false`. If `true` the monster will cast it even without a hostile target. |
Expand Down
17 changes: 6 additions & 11 deletions src/mattack_actors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ void leap_actor::load_internal( const JsonObject &obj, const std::string & )
// Optional:
min_range = obj.get_float( "min_range", 1.0f );
allow_no_target = obj.get_bool( "allow_no_target", false );
optional( obj, was_loaded, "attack_chance", attack_chance, 100 );
optional( obj, was_loaded, "prefer_leap", prefer_leap, false );
optional( obj, was_loaded, "random_leap", random_leap, false );
optional( obj, was_loaded, "ignore_dest_terrain", ignore_dest_terrain, false );
Expand Down Expand Up @@ -256,7 +255,6 @@ void mon_spellcasting_actor::load_internal( const JsonObject &obj, const std::st
//~ "<Monster Display name> cast <Spell Name> on <Target name>!"
to_translation( "%1$s casts %2$s at %3$s!" ) );
spell_data.trigger_message = monster_message;
optional( obj, was_loaded, "attack_chance", attack_chance, 100 );
optional( obj, was_loaded, "allow_no_target", allow_no_target, false );

if( obj.has_member( "condition" ) ) {
Expand Down Expand Up @@ -353,7 +351,6 @@ void melee_actor::load_internal( const JsonObject &obj, const std::string & )
damage_max_instance = load_damage_instance( obj );
}

optional( obj, was_loaded, "attack_chance", attack_chance, 100 );
optional( obj, was_loaded, "accuracy", accuracy, INT_MIN );
optional( obj, was_loaded, "min_mul", min_mul, 0.5f );
optional( obj, was_loaded, "max_mul", max_mul, 1.0f );
Expand Down Expand Up @@ -1160,9 +1157,8 @@ bool gun_actor::call( monster &z ) const
for( const auto &e : ranges ) {
if( dist >= e.first.first && dist <= e.first.second ) {
if( untargeted || try_target( z, *target ) ) {
shoot( z, aim_at, e.second );
return shoot( z, aim_at, e.second );
}
return true;
}
}
return false;
Expand Down Expand Up @@ -1216,11 +1212,9 @@ bool gun_actor::try_target( monster &z, Creature &target ) const
return true;
}

void gun_actor::shoot( monster &z, const tripoint &target, const gun_mode_id &mode,
bool gun_actor::shoot( monster &z, const tripoint &target, const gun_mode_id &mode,
int inital_recoil ) const
{
z.mod_moves( -move_cost );

itype_id mig_gun_type = item_controller->migrate_id( gun_type );
item gun( mig_gun_type );
gun.gun_set_mode( mode );
Expand All @@ -1246,7 +1240,7 @@ void gun_actor::shoot( monster &z, const tripoint &target, const gun_mode_id &mo

if( z.has_effect( effect_stunned ) || z.has_effect( effect_psi_stunned ) ||
z.has_effect( effect_sensor_stun ) ) {
return;
return false;
}

add_msg_debug( debugmode::DF_MATTACK, "%d ammo (%s) remaining", z.ammo[ammo_type],
Expand All @@ -1256,9 +1250,9 @@ void gun_actor::shoot( monster &z, const tripoint &target, const gun_mode_id &mo
if( !no_ammo_sound.empty() ) {
sounds::sound( z.pos(), 10, sounds::sound_t::combat, no_ammo_sound );
}
return;
return false;
}

z.mod_moves( -move_cost );
standard_npc tmp( _( "The " ) + z.name(), z.pos(), {}, 8,
fake_str, fake_dex, fake_int, fake_per );
tmp.worn.wear_item( tmp, item( "backpack" ), false, false, true, true );
Expand Down Expand Up @@ -1289,4 +1283,5 @@ void gun_actor::shoot( monster &z, const tripoint &target, const gun_mode_id &mo
} else {
z.ammo[ammo_type] -= tmp.fire_gun( target, gun.gun_current_mode().qty );
}
return true;
}
2 changes: 1 addition & 1 deletion src/mattack_actors.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ class gun_actor : public mattack_actor
bool require_sunlight = false;

bool try_target( monster &z, Creature &target ) const;
void shoot( monster &z, const tripoint &target, const gun_mode_id &mode,
bool shoot( monster &z, const tripoint &target, const gun_mode_id &mode,
int inital_recoil = 0 ) const;
int get_max_range() const;

Expand Down
4 changes: 1 addition & 3 deletions src/mattack_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ class mattack_actor
mattack_id id;
bool was_loaded = false;

int cooldown = 0;
// Percent chance for the attack to happen if the mob tries it
int attack_chance = 100;
dbl_or_var cooldown;

// Dialogue conditions of the attack
std::function<bool( dialogue & )> condition;
Expand Down
8 changes: 4 additions & 4 deletions src/mondefense.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ void mdefense::return_fire( monster &m, Creature *source, const dealt_projectile
continue;
}

gunactor->shoot( m, fire_point, gun_mode_DEFAULT, dispersion );

// We only return fire once with one gun.
return;
if( gunactor->shoot( m, fire_point, gun_mode_DEFAULT, dispersion ) ) {
// We only return fire once with one gun.
return;
}
}
}
}
13 changes: 9 additions & 4 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,10 @@ monster::monster( const mtype_id &id ) : monster()
moves = type->speed;
Creature::set_speed_base( type->speed );
hp = type->hp;
dialogue d( get_talker_for( this ), get_talker_for( get_avatar() ) );
for( const auto &sa : type->special_attacks ) {
mon_special_attack &entry = special_attacks[sa.first];
entry.cooldown = rng( 0, sa.second->cooldown );
entry.cooldown = rng( 0, sa.second->cooldown.evaluate( d ) );
}
anger = type->agro;
morale = type->morale;
Expand Down Expand Up @@ -385,9 +386,10 @@ void monster::poly( const mtype_id &id )
morale = type->morale;
hp = static_cast<int>( hp_percentage * type->hp );
special_attacks.clear();
dialogue d( get_talker_for( this ), get_talker_for( get_avatar() ) );
for( const auto &sa : type->special_attacks ) {
mon_special_attack &entry = special_attacks[sa.first];
entry.cooldown = sa.second->cooldown;
entry.cooldown = sa.second->cooldown.evaluate( d );
}
faction = type->default_faction;
upgrades = type->upgrades;
Expand Down Expand Up @@ -2585,12 +2587,15 @@ void monster::reset_stats()

void monster::reset_special( const std::string &special_name )
{
set_special( special_name, type->special_attacks.at( special_name )->cooldown );
dialogue d( get_talker_for( this ), get_talker_for( get_avatar() ) );
set_special( special_name, type->special_attacks.at( special_name )->cooldown.evaluate( d ) );
}

void monster::reset_special_rng( const std::string &special_name )
{
set_special( special_name, rng( 0, type->special_attacks.at( special_name )->cooldown ) );
dialogue d( get_talker_for( this ), get_talker_for( get_avatar() ) );
set_special( special_name, rng( 0,
type->special_attacks.at( special_name )->cooldown.evaluate( d ) ) );
}

void monster::set_special( const std::string &special_name, int time )
Expand Down
13 changes: 10 additions & 3 deletions src/monstergenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ mtype MonsterGenerator::generate_fake_pseudo_dormant_monster( const mtype &mon )
// first make a new mon_spellcasting_actor actor
std::unique_ptr<mon_spellcasting_actor> new_actor( new mon_spellcasting_actor() );
new_actor->allow_no_target = true;
new_actor->cooldown = 1;
new_actor->cooldown.min.dbl_val = 1;
new_actor->spell_data.id = spell_pseudo_dormant_trap_setup;
new_actor->spell_data.self = true;

Expand Down Expand Up @@ -1473,7 +1473,7 @@ void mattack_actor::load( const JsonObject &jo, const std::string &src )
assign( jo, "id", id, false );
}

assign( jo, "cooldown", cooldown, strict );
cooldown = get_dbl_or_var( jo, "cooldown", false, 0.0 );

load_internal( jo, src );
// Set was_loaded manually because we don't have generic_factory to do it for us
Expand Down Expand Up @@ -1527,7 +1527,14 @@ void mtype::add_special_attack( const JsonArray &inner, const std::string_view )
}
}
mtype_special_attack new_attack = mtype_special_attack( iter->second );
new_attack.actor->cooldown = inner.get_int( 1 );
if( inner.has_array( 1 ) ) {
new_attack.actor->cooldown.min = get_dbl_or_var_part( inner.get_array( 1 )[0],
"special attack cooldown", 0.0 );
new_attack.actor->cooldown.max = get_dbl_or_var_part( inner.get_array( 1 )[1],
"special attack cooldown", 0.0 );
} else {
new_attack.actor->cooldown.min = get_dbl_or_var_part( inner[1], "special attack cooldown", 0.0 );
}
special_attacks.emplace( name, new_attack );
special_attacks_names.push_back( name );
}
Expand Down
6 changes: 4 additions & 2 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2500,7 +2500,8 @@ void monster::load( const JsonObject &data )
if( ptimeout >= 0 ) {
entry.cooldown = ptimeout;
} else { // -1 means disabled, unclear what <-1 values mean in old saves
entry.cooldown = type->special_attacks.at( aname )->cooldown;
dialogue d( get_talker_for( this ), get_talker_for( get_avatar() ) );
entry.cooldown = type->special_attacks.at( aname )->cooldown.evaluate( d );
entry.enabled = false;
}
}
Expand All @@ -2523,7 +2524,8 @@ void monster::load( const JsonObject &data )
const std::string &aname = sa.first;
if( special_attacks.find( aname ) == special_attacks.end() ) {
auto &entry = special_attacks[aname];
entry.cooldown = rng( 0, sa.second->cooldown );
dialogue d( get_talker_for( this ), get_talker_for( get_avatar() ) );
entry.cooldown = rng( 0, sa.second->cooldown.evaluate( d ) );
}
}

Expand Down

0 comments on commit 7bd1b9a

Please sign in to comment.