Skip to content

Commit

Permalink
[Xedra Evolved] Add Time Related Monsters (#78579)
Browse files Browse the repository at this point in the history
* Xedra: Add time zombies, distribute STABILIZED_TIME, and allow monster him_me, hit_you, and ignore impassable fields

* fixes highest tier zombies upgrading out of their path

* Update data/mods/Xedra_Evolved/monsters/zombies.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Lint and code review

* clang fixes

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
b3brodie and github-actions[bot] authored Dec 15, 2024
1 parent f54a05e commit 5fa6a6c
Show file tree
Hide file tree
Showing 21 changed files with 271 additions and 35 deletions.
10 changes: 10 additions & 0 deletions data/mods/Xedra_Evolved/effects/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -2882,5 +2882,15 @@
"max_intensity": 1,
"show_in_info": true,
"enchantments": [ { "hit_you_effect": [ { "id": "xedra_eater_erosion_attack" } ] } ]
},
{
"type": "effect_type",
"id": "effect_xedra_monster_erosion",
"name": [ "Eroding Time" ],
"desc": [ "This creature destabilizes time around it, eroding everything it touches." ],
"rating": "good",
"max_intensity": 1,
"show_in_info": true,
"enchantments": [ { "hit_you_effect": [ { "id": "xedra_monster_erosion_attack" } ] } ]
}
]
4 changes: 4 additions & 0 deletions data/mods/Xedra_Evolved/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@
"id": "STABILIZED_TIMELINE",
"type": "json_flag",
"info": "You are immune to adverse affects on your timeline."
},
{
"id": "STABILIZED_TIMELINE",
"type": "monster_flag"
}
]
3 changes: 2 additions & 1 deletion data/mods/Xedra_Evolved/monsters/changeling.json
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,8 @@
"PET_MOUNTABLE",
"PATH_AVOID_DANGER",
"WARM",
"HIT_AND_RUN"
"HIT_AND_RUN",
"STABILIZED_TIMELINE"
],
"armor": {
"bash": 8,
Expand Down
18 changes: 18 additions & 0 deletions data/mods/Xedra_Evolved/monsters/monster_overrides.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
[
{
"type": "MONSTER",
"id": "mon_tindalos",
"copy-from": "mon_tindalos",
"extend": { "flags": [ "STABILIZED_TIMELINE" ] }
},
{
"type": "MONSTER",
"id": "mon_hound_tindalos",
"copy-from": "mon_hound_tindalos",
"extend": { "flags": [ "STABILIZED_TIMELINE" ] }
},
{
"type": "MONSTER",
"id": "mon_lieutenant_shadow",
"copy-from": "mon_lieutenant_shadow",
"extend": { "flags": [ "STABILIZED_TIMELINE" ] }
},
{
"id": "mon_bear_cub",
"type": "MONSTER",
Expand Down
49 changes: 49 additions & 0 deletions data/mods/Xedra_Evolved/monsters/monsterattacks.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,5 +294,54 @@
"flags": [ "SILENT", "RANDOM_DAMAGE", "RANDOM_AOE" ],
"min_aoe": 7,
"max_aoe": 10
},
{
"id": "zombie_monochrome_reset_hp",
"type": "SPELL",
"name": { "str": "Reset HP", "//~": "NO_I18N" },
"description": { "str": "Heals 100% of health. Players should not have this spell.", "//~": "NO_I18N" },
"message": "",
"effect": "attack",
"shape": "blast",
"valid_targets": [ "ally", "self" ],
"flags": [ "SILENT", "IGNORE_WALLS", "PERCENTAGE_DAMAGE", "NO_EXPLOSION_SFX" ],
"min_damage": -200,
"max_damage": -200,
"min_range": 0,
"max_range": 0,
"damage_type": "pure"
},
{
"id": "xedra_monster_erosion_attack",
"type": "SPELL",
"name": { "str": "Monster Erosion - Attack", "//~": "NO_I18N" },
"description": "This causes the dot when attacking targets with the erosion buff. Having the spell is a bug. Monster version",
"valid_targets": [ "hostile", "ground", "none" ],
"flags": [ "SILENT", "NO_PROJECTILE", "NO_EXPLOSION_SFX", "RANDOM_DAMAGE", "RANDOM_DURATION", "SPLIT_DAMAGE" ],
"message": "monster erosion attack",
"effect": "attack",
"shape": "blast",
"min_dot": 5,
"max_dot": 5,
"min_range": 10,
"max_range": 10,
"min_duration": 1000,
"max_duration": 1000,
"damage_type": "pure"
},
{
"id": "xedra_monster_erosion_buff",
"type": "SPELL",
"name": { "str": "Monster Erosion - Buff", "//~": "NO_I18N" },
"description": "This gives the monster the erosion buff. Having the spell is a bug. Monster version",
"valid_targets": [ "self" ],
"flags": [ "SILENT", "NO_PROJECTILE", "NO_EXPLOSION_SFX" ],
"effect": "attack",
"effect_str": "effect_xedra_monster_erosion",
"shape": "blast",
"min_duration": 100000,
"max_duration": 100000,
"min_range": 0,
"max_range": 0
}
]
15 changes: 15 additions & 0 deletions data/mods/Xedra_Evolved/monsters/monstergroup.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,5 +366,20 @@
{ "monster": "mon_samhain_ghost_axe", "weight": 333 },
{ "monster": "mon_samhain_ghost_spear", "weight": 333 }
]
},
{
"type": "monstergroup",
"name": "GROUP_ZOMBIE_UPGRADE",
"monsters": [ { "monster": "mon_zombie_monochrome", "weight": 30 } ]
},
{
"type": "monstergroup",
"name": "GROUP_ZOMBIE_MONOCHROME_UPGRADE",
"default": "mon_zombie_monochrome",
"monsters": [
{ "monster": "mon_zombie_monochrome", "weight": 450 },
{ "monster": "mon_zombie_monochrome_2", "weight": 225 },
{ "monster": "mon_zombie_monochrome_3", "weight": 100 }
]
}
]
83 changes: 83 additions & 0 deletions data/mods/Xedra_Evolved/monsters/zombies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[
{
"id": "mon_zombie_monochrome",
"copy-from": "mon_zombie_base",
"type": "MONSTER",
"name": { "str": "monochrome zombie" },
"description": "What stands in front of you is one of the healthiest zombies you've ever seen. If not for the black muck oozing from its orifices and shambling gait, you might even think it human. Every part of this zombie, even its clothes, is colored some shade of gray, and every couple of seconds it flickers.",
"symbol": "Z",
"color": "light_gray",
"special_attacks": [
{ "id": "grab", "cooldown": 1 },
{ "id": "bite_humanoid", "cooldown": 5 },
{
"id": "zombie_monochrome_reset_hp_attack",
"type": "spell",
"condition": { "math": [ "u_hp('ALL') < u_hp_max('bp_null')" ] },
"spell_data": { "id": "zombie_monochrome_reset_hp" },
"allow_no_target": true,
"cooldown": 10,
"monster_message": "%1$s flickers and all of its injuries disappear!"
}
],
"upgrades": { "half_life": 25, "into_group": "GROUP_ZOMBIE_MONOCHROME_UPGRADE" }
},
{
"id": "mon_zombie_monochrome_2",
"copy-from": "mon_zombie_base",
"type": "MONSTER",
"name": { "str": "distorted zombie" },
"description": "This zombie is partially obscured by the gray, distorted air around it. From what you can see it doesn't have a single wound on its body, and it moves much quicker than a zombie should. Every few seconds the distortions surge.",
"symbol": "Z",
"color": "light_gray",
"proportional": { "speed": 1.5, "hp": 1.5 },
"special_attacks": [
{ "id": "grab", "cooldown": 1 },
{ "id": "bite_humanoid", "cooldown": 5 },
{
"id": "zombie_monochrome_reset_hp_attack",
"type": "spell",
"condition": { "math": [ "u_hp('ALL') < u_hp_max('bp_null')" ] },
"spell_data": { "id": "zombie_monochrome_reset_hp" },
"allow_no_target": true,
"cooldown": 5,
"monster_message": "%1$s flickers and all of its injuries disappear!"
}
],
"upgrades": { "half_life": 25, "into": "mon_zombie_monochrome_3" },
"extend": { "flags": [ "STABILIZED_TIMELINE" ] }
},
{
"id": "mon_zombie_monochrome_3",
"copy-from": "mon_zombie_base",
"type": "MONSTER",
"name": { "str": "zombie timewound" },
"description": "Every bit of color around this zombie has been sapped a distorted gray. In contrast with its healthy appearance, the surrounding environment seems to slowly erode, even after it swiftly moves away. It sharply flickers every few seconds.",
"symbol": "Z",
"color": "dark_gray",
"proportional": { "speed": 2, "hp": 2 },
"special_attacks": [
{ "id": "grab", "cooldown": 1 },
{ "id": "bite_humanoid", "cooldown": 5 },
{
"id": "zombie_monochrome_reset_hp_special",
"type": "spell",
"condition": { "math": [ "u_hp('ALL') < u_hp_max('bp_null')" ] },
"spell_data": { "id": "zombie_monochrome_reset_hp" },
"allow_no_target": true,
"cooldown": 2,
"monster_message": "%1$s flickers and all of its injuries disappear!"
},
{
"id": "xedra_monster_erosion_buff_special",
"type": "spell",
"condition": { "not": { "u_has_effect": "effect_xedra_monster_erosion" } },
"spell_data": { "id": "xedra_monster_erosion_buff" },
"allow_no_target": true,
"monster_message": "The ground around %1$s starts eroding into nothingness."
}
],
"extend": { "flags": [ "STABILIZED_TIMELINE" ] },
"upgrades": false
}
]
2 changes: 1 addition & 1 deletion src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10585,7 +10585,7 @@ void Character::echo_pulse()
}
// It's not moving. Must be an obstacle
if( critter->has_flag( mon_flag_IMMOBILE ) ||
critter->has_effect_with_flag( json_flag_CANNOT_MOVE ) ) {
critter->has_flag( json_flag_CANNOT_MOVE ) ) {
echo_string = _( "click." );
}
sounds::sound( origin, echo_volume, sounds::sound_t::sensory, _( echo_string ), false,
Expand Down
2 changes: 1 addition & 1 deletion src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,7 @@ class Character : public Creature, public visitable
/** This is to prevent clang complaining about overloading a virtual function, the creature version uses monster flags so confusion is unlikely. */
using Creature::has_flag;
/** Returns true if player has a trait, bionic, effect, bodypart, or martial arts buff with a flag */
bool has_flag( const json_character_flag &flag ) const;
bool has_flag( const json_character_flag &flag ) const override;
/** Returns the count of traits, bionics, effects, bodyparts, and martial arts buffs with a flag */
int count_flag( const json_character_flag &flag ) const;

Expand Down
6 changes: 3 additions & 3 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ int Creature::deal_melee_attack( Creature *source, int hitroll )
add_msg_debug( debugmode::DF_CREATURE, "Dodge roll %.1f",
dodge );

if( has_flag( mon_flag_IMMOBILE ) || has_effect_with_flag( json_flag_CANNOT_MOVE ) ) {
if( has_flag( mon_flag_IMMOBILE ) || has_flag( json_flag_CANNOT_MOVE ) ) {
// Under normal circumstances, even a clumsy person would
// not miss a turret. It should, however, be possible to
// miss a smaller target, especially when wielding a
Expand Down Expand Up @@ -1366,7 +1366,7 @@ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack
dealt_damage_instance Creature::deal_damage( Creature *source, bodypart_id bp,
const damage_instance &dam, const weakpoint_attack &attack )
{
if( is_dead_state() || has_effect_with_flag( json_flag_CANNOT_TAKE_DAMAGE ) ) {
if( is_dead_state() || has_flag( json_flag_CANNOT_TAKE_DAMAGE ) ) {
return dealt_damage_instance();
}
int total_damage = 0;
Expand Down Expand Up @@ -2035,7 +2035,7 @@ void Creature::process_effects()
for( auto &elem : *effects ) {
for( auto &_it : elem.second ) {
// Do not freeze the effect with the FREEZE_EFFECTS flag.
if( has_effect_with_flag( json_flag_FREEZE_EFFECTS ) &&
if( has_flag( json_flag_FREEZE_EFFECTS ) &&
!_it.second.has_flag( json_flag_FREEZE_EFFECTS ) ) {
continue;
}
Expand Down
3 changes: 3 additions & 0 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,9 @@ class Creature : public viewer
virtual bool has_flag( const mon_flag_id & ) const {
return false;
}
virtual bool has_flag( const flag_id & ) const {
return false;
}
virtual bool uncanny_dodge() {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11892,7 +11892,7 @@ bool game::fling_creature( Creature *c, const units::angle &dir, float flvel, bo
return false;
}

if( c->has_effect_with_flag( json_flag_CANNOT_MOVE ) ) {
if( c->has_flag( json_flag_CANNOT_MOVE ) ) {
// cannot fling creatures that cannot move.
return false;
}
Expand Down
21 changes: 20 additions & 1 deletion src/magic_enchantment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ bool enchantment::is_monster_relevant() const
}
}

// check for hit you / me effects
if( !hit_you_effect.empty() || !hit_me_effect.empty() ) {
return true;
}

if( !damage_values_add.empty() || !damage_values_multiply.empty() ||
!armor_values_add.empty() || !armor_values_multiply.empty() ) {
return true;
Expand Down Expand Up @@ -1384,6 +1389,20 @@ void enchant_cache::activate_passive( Character &guy ) const
}
}

void enchant_cache::cast_hit_you( Creature &caster, const Creature &target ) const
{
for( const fake_spell &sp : hit_you_effect ) {
cast_enchantment_spell( caster, &target, sp );
}
}

void enchant_cache::cast_hit_me( Creature &caster, const Creature *target ) const
{
for( const fake_spell &sp : hit_me_effect ) {
cast_enchantment_spell( caster, target, sp );
}
}

void enchant_cache::cast_hit_you( Character &caster, const Creature &target ) const
{
for( const fake_spell &sp : hit_you_effect ) {
Expand All @@ -1398,7 +1417,7 @@ void enchant_cache::cast_hit_me( Character &caster, const Creature *target ) con
}
}

void enchant_cache::cast_enchantment_spell( Character &caster, const Creature *target,
void enchant_cache::cast_enchantment_spell( Creature &caster, const Creature *target,
const fake_spell &sp ) const
{
// check the chances
Expand Down
4 changes: 3 additions & 1 deletion src/magic_enchantment.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,15 +326,17 @@ class enchant_cache : public enchantment
// checks if the enchantments have the same active_conditions
bool stacks_with( const enchantment &rhs ) const;
// performs cooldown and distance checks before casting enchantment spells
void cast_enchantment_spell( Character &caster, const Creature *target,
void cast_enchantment_spell( Creature &caster, const Creature *target,
const fake_spell &sp ) const;
//Clears all the maps and vectors in the cache.
void clear();

// casts all the hit_you_effects on the target
void cast_hit_you( Character &caster, const Creature &target ) const;
void cast_hit_you( Creature &caster, const Creature &target ) const;
// casts all the hit_me_effects on self or a target depending on the enchantment definition
void cast_hit_me( Character &caster, const Creature *target ) const;
void cast_hit_me( Creature &caster, const Creature *target ) const;
void serialize( JsonOut &jsout ) const;
void add_value_add( enchant_vals::mod value, int add_value );

Expand Down
2 changes: 1 addition & 1 deletion src/mattack_actors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ bool melee_actor::call( monster &z ) const
}
}
if( throw_strength > 0 && !( target->has_flag( mon_flag_IMMOBILE ) ||
target->has_effect_with_flag( json_flag_CANNOT_MOVE ) ) ) {
target->has_flag( json_flag_CANNOT_MOVE ) ) ) {
if( g->fling_creature( target, coord_to_angle( z.pos(), target->pos() ),
throw_strength ) ) {
target->add_msg_player_or_npc( msg_type, throw_msg_u,
Expand Down
12 changes: 6 additions & 6 deletions src/melee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,8 +697,8 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special,

// Practice melee and relevant weapon skill (if any) except when using CQB bionic, if the creature is a hallucination, or if the creature cannot move and take damage.
if( !has_active_bionic( bio_cqb ) && !t.is_hallucination() &&
!( t.has_effect_with_flag( json_flag_CANNOT_MOVE ) &&
t.has_effect_with_flag( json_flag_CANNOT_TAKE_DAMAGE ) ) ) {
!( t.has_flag( json_flag_CANNOT_MOVE ) &&
t.has_flag( json_flag_CANNOT_TAKE_DAMAGE ) ) ) {
melee_train( *this, 2, std::min( 5, skill_training_cap ), cur_weap, attack_vector_vector_null );
}

Expand Down Expand Up @@ -879,8 +879,8 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special,

// Practice melee and relevant weapon skill (if any) except when using CQB bionic, if the creature is a hallucination, or if the creature cannot move and take damage.
if( !has_active_bionic( bio_cqb ) && !t.is_hallucination() &&
!( t.has_effect_with_flag( json_flag_CANNOT_MOVE ) &&
t.has_effect_with_flag( json_flag_CANNOT_TAKE_DAMAGE ) ) ) {
!( t.has_flag( json_flag_CANNOT_MOVE ) &&
t.has_flag( json_flag_CANNOT_TAKE_DAMAGE ) ) ) {
melee_train( *this, 5, std::min( 10, skill_training_cap ), cur_weap, vector_id );
}

Expand Down Expand Up @@ -1786,7 +1786,7 @@ void Character::perform_technique( const ma_technique &technique, Creature &t,
}

if( technique.side_switch && !( t.has_flag( mon_flag_IMMOBILE ) ||
t.has_effect_with_flag( json_flag_CANNOT_MOVE ) ) ) {
t.has_flag( json_flag_CANNOT_MOVE ) ) ) {
const tripoint b = t.pos();
point new_;

Expand All @@ -1813,7 +1813,7 @@ void Character::perform_technique( const ma_technique &technique, Creature &t,
}
map &here = get_map();
if( technique.knockback_dist && !( t.has_flag( mon_flag_IMMOBILE ) ||
t.has_effect_with_flag( json_flag_CANNOT_MOVE ) ) ) {
t.has_flag( json_flag_CANNOT_MOVE ) ) ) {
const tripoint_bub_ms prev_pos = t.pos_bub(); // track target startpoint for knockback_follow
const point kb_offset( rng( -technique.knockback_spread, technique.knockback_spread ),
rng( -technique.knockback_spread, technique.knockback_spread ) );
Expand Down
Loading

0 comments on commit 5fa6a6c

Please sign in to comment.