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

Cooldown fix and minor changes #74139

Merged
merged 2 commits into from
Jun 1, 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
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
15 changes: 10 additions & 5 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 @@ -1463,8 +1463,6 @@ mtype_special_attack MonsterGenerator::create_actor( const JsonObject &obj,

void mattack_actor::load( const JsonObject &jo, const std::string &src )
{
bool strict = src == "dda";

// Legacy support
if( !jo.has_string( "id" ) ) {
id = jo.get_string( "type" );
Expand All @@ -1473,7 +1471,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 +1525,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
Loading