Skip to content

Commit

Permalink
Jsonify monster flags (#66722)
Browse files Browse the repository at this point in the history
* jsonify monster flags: code and flag conversion

* jsonify monster flags: docs and lang parser

* jsonify monster flags: optimizations

* jsonify monster flags: remove expensive debug stats tracker for mflags
  • Loading branch information
dseguin authored Jul 10, 2023
1 parent 1f5aaac commit 12e1986
Show file tree
Hide file tree
Showing 54 changed files with 1,291 additions and 572 deletions.
557 changes: 557 additions & 0 deletions data/json/monsters/monster_flags.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ Here's a quick summary of what each of the JSON files contain, broken down by fo
| `monster_attacks.json` | monster attacks
| `monster_drops.json` | monster item drops on death
| `monster_factions.json` | monster factions
| `monster_flags.json` | monster flags and their descriptions
| `monstergroups.json` | monster spawn groups
| `monstergroups_egg.json` | monster spawn groups from eggs
| `monsters.json` | monster descriptions, mostly zombies
Expand Down
2 changes: 1 addition & 1 deletion doc/MONSTERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ Will stop fleeing if at max hp, and regen anger and morale.
## "flags"
(array of strings, optional)

Monster flags. See [JSON_FLAGS.md](JSON_FLAGS.md) for a full list.
Monster flags. See [JSON_FLAGS.md](JSON_FLAGS.md) for a full list. These are IDs that point to a `"monster_flag"` object, which usually can be found in `data/json/monsters/monster_flags.json`.

## "fear_triggers", "anger_triggers", "placate_triggers"
(array of strings, optional)
Expand Down
1 change: 1 addition & 0 deletions lang/string_extractor/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ def dummy_parser(json, origin):
"monster_attack": parse_monster_attack,
"monster_blacklist": dummy_parser,
"monster_faction": dummy_parser,
"monster_flag": dummy_parser,
"monster_whitelist": dummy_parser,
"monstergroup": dummy_parser,
"mood_face": dummy_parser,
Expand Down
10 changes: 7 additions & 3 deletions src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ static const itype_id itype_water_clean( "water_clean" );

static const json_character_flag json_flag_SUPER_HEARING( "SUPER_HEARING" );

static const mon_flag_str_id mon_flag_INTERIOR_AMMO( "INTERIOR_AMMO" );
static const mon_flag_str_id mon_flag_PAY_BOT( "PAY_BOT" );
static const mon_flag_str_id mon_flag_RIDEABLE_MECH( "RIDEABLE_MECH" );

static const move_mode_id move_mode_prone( "prone" );
static const move_mode_id move_mode_walk( "walk" );

Expand Down Expand Up @@ -4034,7 +4038,7 @@ void disable_activity_actor::finish( player_activity &act, Character &/*who*/ )
}
} else {
get_map().add_item_or_charges( target, critter.to_item() );
if( !critter.has_flag( MF_INTERIOR_AMMO ) ) {
if( !critter.has_flag( mon_flag_INTERIOR_AMMO ) ) {
for( std::pair<const itype_id, int> &ammodef : critter.ammo ) {
if( ammodef.second > 0 ) {
get_map().spawn_item( target.xy(), ammodef.first, 1, ammodef.second, calendar::turn );
Expand All @@ -4055,8 +4059,8 @@ bool disable_activity_actor::can_disable_or_reprogram( const monster &monster )
}

return ( ( monster.friendly != 0 || monster.has_effect( effect_sensor_stun ) ) &&
!monster.has_flag( MF_RIDEABLE_MECH ) &&
!( monster.has_flag( MF_PAY_BOT ) && monster.has_effect( effect_paid ) ) ) &&
!monster.has_flag( mon_flag_RIDEABLE_MECH ) &&
!( monster.has_flag( mon_flag_PAY_BOT ) && monster.has_effect( effect_paid ) ) ) &&
( !monster.type->revert_to_itype.is_empty() || monster.type->id == mon_manhack );
}

Expand Down
6 changes: 4 additions & 2 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ static const json_character_flag json_flag_PSYCHOPATH( "PSYCHOPATH" );
static const json_character_flag json_flag_SAPIOVORE( "SAPIOVORE" );
static const json_character_flag json_flag_SILENT_SPELL( "SILENT_SPELL" );

static const mon_flag_str_id mon_flag_RIDEABLE_MECH( "RIDEABLE_MECH" );

static const mongroup_id GROUP_FISH( "GROUP_FISH" );

static const proficiency_id proficiency_prof_dissect_humans( "prof_dissect_humans" );
Expand Down Expand Up @@ -3512,15 +3514,15 @@ void activity_handlers::robot_control_finish( player_activity *act, Character *y
const float computer_skill = you->get_skill_level( skill_computer );
const float randomized_skill = rng( 2, you->int_cur ) + computer_skill;
float success = computer_skill - 3 * z->type->difficulty / randomized_skill;
if( z->has_flag( MF_RIDEABLE_MECH ) ) {
if( z->has_flag( mon_flag_RIDEABLE_MECH ) ) {
success = randomized_skill - rng( 1, 11 );
}
// rideable mechs are not hostile, they have no AI, they do not resist control as much.
if( success >= 0 ) {
you->add_msg_if_player( _( "You successfully override the %s's IFF protocols!" ),
z->name() );
z->friendly = -1;
if( z->has_flag( MF_RIDEABLE_MECH ) ) {
if( z->has_flag( mon_flag_RIDEABLE_MECH ) ) {
z->add_effect( effect_pet, 1_turns, true );
}
} else if( success >= -2 ) {
Expand Down
7 changes: 5 additions & 2 deletions src/avatar_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ static const efftype_id effect_winded( "winded" );

static const itype_id itype_swim_fins( "swim_fins" );

static const mon_flag_str_id mon_flag_IMMOBILE( "IMMOBILE" );
static const mon_flag_str_id mon_flag_RIDEABLE_MECH( "RIDEABLE_MECH" );

static const move_mode_id move_mode_prone( "prone" );

static const skill_id skill_swimming( "swimming" );
Expand Down Expand Up @@ -368,7 +371,7 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d )
}
g->draw_hit_mon( dest_loc, critter, critter.is_dead() );
return false;
} else if( critter.has_flag( MF_IMMOBILE ) || critter.has_effect( effect_harnessed ) ||
} else if( critter.has_flag( mon_flag_IMMOBILE ) || critter.has_effect( effect_harnessed ) ||
critter.has_effect( effect_ridden ) ) {
add_msg( m_info, _( "You can't displace your %s." ), critter.name() );
return false;
Expand Down Expand Up @@ -958,7 +961,7 @@ void avatar_action::plthrow( avatar &you, item_location loc,
}
if( you.is_mounted() ) {
monster *mons = get_player_character().mounted_creature.get();
if( mons->has_flag( MF_RIDEABLE_MECH ) ) {
if( mons->has_flag( mon_flag_RIDEABLE_MECH ) ) {
if( !mons->check_mech_powered() ) {
add_msg( m_bad, _( "Your %s refuses to move as its batteries have been drained." ),
mons->get_name() );
Expand Down
5 changes: 3 additions & 2 deletions src/cata_tiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
static const efftype_id effect_ridden( "ridden" );

static const itype_id itype_corpse( "corpse" );
static const mon_flag_str_id mon_flag_ALWAYS_VISIBLE( "ALWAYS_VISIBLE" );
static const trait_id trait_INATTENTIVE( "INATTENTIVE" );
static const trap_str_id tr_unfinished_construction( "tr_unfinished_construction" );

Expand Down Expand Up @@ -1644,7 +1645,7 @@ void cata_tiles::draw( const point &dest, const tripoint &center, int width, int
const Creature *critter = creatures.creature_at( pos, true );
if( has_draw_override( pos ) || has_memory_at( pos ) ||
( critter &&
( critter->has_flag( MF_ALWAYS_VISIBLE )
( critter->has_flag( mon_flag_ALWAYS_VISIBLE )
|| you.sees_with_infrared( *critter )
|| you.sees_with_specials( *critter ) ) ) ) {
invisible[0] = true;
Expand Down Expand Up @@ -3943,7 +3944,7 @@ bool cata_tiles::draw_critter_at( const tripoint &p, lit_level ll, int &height_3
Creature::Attitude attitude;
Character &you = get_player_character();
const Creature *pcritter = get_creature_tracker().creature_at( p, true );
const bool always_visible = pcritter && pcritter->has_flag( MF_ALWAYS_VISIBLE );
const bool always_visible = pcritter && pcritter->has_flag( mon_flag_ALWAYS_VISIBLE );
const auto override = monster_override.find( p );
if( override != monster_override.end() ) {
const mtype_id id = std::get<0>( override->second );
Expand Down
37 changes: 21 additions & 16 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,11 @@ static const material_id material_mc_steel( "mc_steel" );
static const material_id material_qt_steel( "qt_steel" );
static const material_id material_steel( "steel" );

static const mon_flag_str_id mon_flag_COMBAT_MOUNT( "COMBAT_MOUNT" );
static const mon_flag_str_id mon_flag_LOUDMOVES( "LOUDMOVES" );
static const mon_flag_str_id mon_flag_MECH_RECON_VISION( "MECH_RECON_VISION" );
static const mon_flag_str_id mon_flag_RIDEABLE_MECH( "RIDEABLE_MECH" );

static const morale_type morale_nightmare( "morale_nightmare" );

static const move_mode_id move_mode_prone( "prone" );
Expand Down Expand Up @@ -1220,7 +1225,7 @@ int Character::overmap_sight_range( float light_level ) const
// When adding checks here, also call game::update_overmap_seen at the place they first become true
const bool has_optic = has_item_with_flag( flag_ZOOM ) ||
has_flag( json_flag_ENHANCED_VISION ) ||
( is_mounted() && mounted_creature->has_flag( MF_MECH_RECON_VISION ) ) ||
( is_mounted() && mounted_creature->has_flag( mon_flag_MECH_RECON_VISION ) ) ||
get_map().veh_at( pos() ).avail_part_with_feature( "ENHANCED_VISION" ).has_value();

if( has_optic ) {
Expand Down Expand Up @@ -1503,7 +1508,7 @@ void Character::mount_creature( monster &z )
player_avatar.grab( object_type::NONE );
}
add_msg_if_player( m_good, _( "You climb on the %s." ), z.get_name() );
if( z.has_flag( MF_RIDEABLE_MECH ) ) {
if( z.has_flag( mon_flag_RIDEABLE_MECH ) ) {
if( !z.type->mech_weapon.is_empty() ) {
item mechwep = item( z.type->mech_weapon );
set_wielded_item( mechwep );
Expand All @@ -1522,7 +1527,7 @@ void Character::mount_creature( monster &z )
z.facing = facing;
// some rideable mechs have night-vision
recalc_sight_limits();
if( is_avatar() && z.has_flag( MF_MECH_RECON_VISION ) ) {
if( is_avatar() && z.has_flag( mon_flag_MECH_RECON_VISION ) ) {
// mech night-vision counts as optics for overmap sight range.
g->update_overmap_seen();
}
Expand All @@ -1531,7 +1536,7 @@ void Character::mount_creature( monster &z )

bool Character::check_mount_will_move( const tripoint &dest_loc )
{
if( !is_mounted() || mounted_creature->has_flag( MF_COMBAT_MOUNT ) ) {
if( !is_mounted() || mounted_creature->has_flag( mon_flag_COMBAT_MOUNT ) ) {
return true;
}
if( mounted_creature && mounted_creature->type->has_fear_trigger( mon_trigger::HOSTILE_CLOSE ) ) {
Expand Down Expand Up @@ -1567,7 +1572,7 @@ bool Character::check_mount_is_spooked()
if( mounted_creature && mounted_creature->type->has_fear_trigger( mon_trigger::HOSTILE_CLOSE ) ) {
const creature_size mount_size = mounted_creature->get_size();
const bool saddled = mounted_creature->has_effect( effect_monster_saddled );
const bool combat_mount = mounted_creature->has_flag( MF_COMBAT_MOUNT );
const bool combat_mount = mounted_creature->has_flag( mon_flag_COMBAT_MOUNT );
for( const monster &critter : g->all_monsters() ) {
if( critter.is_hallucination() ) {
continue;
Expand Down Expand Up @@ -1623,7 +1628,7 @@ void Character::forced_dismount()
bool mech = false;
if( mounted_creature ) {
auto *mon = mounted_creature.get();
if( mon->has_flag( MF_RIDEABLE_MECH ) && !mon->type->mech_weapon.is_empty() ) {
if( mon->has_flag( mon_flag_RIDEABLE_MECH ) && !mon->type->mech_weapon.is_empty() ) {
mech = true;
remove_item( weapon );
}
Expand Down Expand Up @@ -1735,7 +1740,7 @@ void Character::dismount()
remove_effect( effect_riding );
monster *critter = mounted_creature.get();
critter->mounted_player_id = character_id();
if( critter->has_flag( MF_RIDEABLE_MECH ) && !critter->type->mech_weapon.is_empty() &&
if( critter->has_flag( mon_flag_RIDEABLE_MECH ) && !critter->type->mech_weapon.is_empty() &&
weapon.typeId() == critter->type->mech_weapon ) {
remove_item( weapon );
}
Expand Down Expand Up @@ -2072,7 +2077,7 @@ int Character::footstep_sound() const
default:
break;
}
if( mons->has_flag( MF_LOUDMOVES ) ) {
if( mons->has_flag( mon_flag_LOUDMOVES ) ) {
volume += 6;
}
} else {
Expand Down Expand Up @@ -2123,7 +2128,7 @@ steed_type Character::get_steed_type() const
{
steed_type steed;
if( is_mounted() ) {
if( mounted_creature->has_flag( MF_RIDEABLE_MECH ) ) {
if( mounted_creature->has_flag( mon_flag_RIDEABLE_MECH ) ) {
steed = steed_type::MECH;
} else {
steed = steed_type::ANIMAL;
Expand Down Expand Up @@ -2401,7 +2406,7 @@ void Character::recalc_sight_limits()
vision_mode_cache.set( NV_GOGGLES );
}
if( has_active_mutation( trait_NIGHTVISION3 ) || is_wearing( itype_rm13_armor_on ) ||
( is_mounted() && mounted_creature->has_flag( MF_MECH_RECON_VISION ) ) ) {
( is_mounted() && mounted_creature->has_flag( mon_flag_MECH_RECON_VISION ) ) ) {
vision_mode_cache.set( NIGHTVISION_3 );
}
if( has_active_mutation( trait_ELFA_FNV ) ) {
Expand Down Expand Up @@ -2432,7 +2437,7 @@ void Character::recalc_sight_limits()
// Not exactly a sight limit thing, but related enough
if( has_flag( json_flag_INFRARED ) ||
worn_with_flag( flag_IR_EFFECT ) || ( is_mounted() &&
mounted_creature->has_flag( MF_MECH_RECON_VISION ) ) ) {
mounted_creature->has_flag( mon_flag_MECH_RECON_VISION ) ) ) {
vision_mode_cache.set( IR_VISION );
}

Expand Down Expand Up @@ -2887,7 +2892,7 @@ units::mass Character::best_nearby_lifting_assist( const tripoint &world_pos ) c
int mech_lift = 0;
if( is_mounted() ) {
auto *mons = mounted_creature.get();
if( mons->has_flag( MF_RIDEABLE_MECH ) ) {
if( mons->has_flag( mon_flag_RIDEABLE_MECH ) ) {
mech_lift = mons->mech_str_addition() + 10;
}
}
Expand Down Expand Up @@ -7486,7 +7491,7 @@ ret_val<void> Character::can_wield( const item &it ) const
monster *mount = mounted_creature.get();
if( it.is_two_handed( *this ) && ( !has_two_arms_lifting() ||
worn_with_flag( flag_RESTRICT_HANDS ) ) &&
!( is_mounted() && mount->has_flag( MF_RIDEABLE_MECH ) &&
!( is_mounted() && mount->has_flag( mon_flag_RIDEABLE_MECH ) &&
mount->type->mech_weapon && it.typeId() == mount->type->mech_weapon ) ) {
if( worn_with_flag( flag_RESTRICT_HANDS ) ) {
return ret_val<void>::make_failure(
Expand All @@ -7499,7 +7504,7 @@ ret_val<void> Character::can_wield( const item &it ) const
it.tname() );
}
}
if( is_mounted() && mount->has_flag( MF_RIDEABLE_MECH ) &&
if( is_mounted() && mount->has_flag( mon_flag_RIDEABLE_MECH ) &&
mount->type->mech_weapon && it.typeId() != mount->type->mech_weapon ) {
return ret_val<void>::make_failure( _( "You cannot wield anything while piloting a mech." ) );
}
Expand Down Expand Up @@ -8886,7 +8891,7 @@ bool Character::use_charges_if_avail( const itype_id &it, int quantity )
units::energy Character::available_ups() const
{
units::energy available_charges = 0_kJ;
if( is_mounted() && mounted_creature.get()->has_flag( MF_RIDEABLE_MECH ) ) {
if( is_mounted() && mounted_creature.get()->has_flag( mon_flag_RIDEABLE_MECH ) ) {
auto *mons = mounted_creature.get();
available_charges += units::from_kilojoule( mons->battery_item->ammo_remaining() );
}
Expand All @@ -8906,7 +8911,7 @@ units::energy Character::consume_ups( units::energy qty, const int radius )
const units::energy wanted_qty = qty;

// UPS from mounted mech
if( qty != 0_kJ && is_mounted() && mounted_creature.get()->has_flag( MF_RIDEABLE_MECH ) &&
if( qty != 0_kJ && is_mounted() && mounted_creature.get()->has_flag( mon_flag_RIDEABLE_MECH ) &&
mounted_creature.get()->battery_item ) {
auto *mons = mounted_creature.get();
qty -= mons->use_mech_power( qty );
Expand Down
4 changes: 3 additions & 1 deletion src/computer_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ static const mission_type_id
mission_MISSION_OLD_GUARD_NEC_COMMO_4( "MISSION_OLD_GUARD_NEC_COMMO_4" );
static const mission_type_id mission_MISSION_REACH_REFUGEE_CENTER( "MISSION_REACH_REFUGEE_CENTER" );

static const mon_flag_str_id mon_flag_CONSOLE_DESPAWN( "CONSOLE_DESPAWN" );

static const mtype_id mon_manhack( "mon_manhack" );
static const mtype_id mon_secubot( "mon_secubot" );

Expand Down Expand Up @@ -273,7 +275,7 @@ static void remove_submap_turrets()
// Check 1) same overmap coords, 2) turret, 3) hostile
if( ms_to_omt_copy( here.getabs( critter.pos() ) ) == ms_to_omt_copy( here.getabs(
player_character.pos() ) ) &&
critter.has_flag( MF_CONSOLE_DESPAWN ) &&
critter.has_flag( mon_flag_CONSOLE_DESPAWN ) &&
critter.attitude_to( player_character ) == Creature::Attitude::HOSTILE ) {
g->remove_zombie( critter );
}
Expand Down
4 changes: 3 additions & 1 deletion src/construction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ static const itype_id itype_sheet( "sheet" );
static const itype_id itype_stick( "stick" );
static const itype_id itype_string_36( "string_36" );

static const mon_flag_str_id mon_flag_HUMAN( "HUMAN" );

static const mtype_id mon_skeleton( "mon_skeleton" );
static const mtype_id mon_zombie( "mon_zombie" );
static const mtype_id mon_zombie_crawler( "mon_zombie_crawler" );
Expand Down Expand Up @@ -1302,7 +1304,7 @@ void construct::done_grave( const tripoint_bub_ms &p, Character &player_characte
for( const item &it : its ) {
if( it.is_corpse() ) {
if( it.get_corpse_name().empty() ) {
if( it.get_mtype()->has_flag( MF_HUMAN ) ) {
if( it.get_mtype()->has_flag( mon_flag_HUMAN ) ) {
if( player_character.has_trait( trait_SPIRITUAL ) ) {
player_character.add_morale( MORALE_FUNERAL, 50, 75, 1_days, 1_hours );
add_msg( m_good,
Expand Down
Loading

0 comments on commit 12e1986

Please sign in to comment.