From 42f83145165d13e6caa5afd9be07176b2bdb4ec7 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 04:44:53 +0000 Subject: [PATCH 01/81] Cleanse (cont.) Continuation of #2789 --- config/fxdata/creature.cfg | 19 +++++++++++++++++++ config/fxdata/magic.cfg | 13 +++++++++++++ src/config_magic.c | 2 ++ src/config_magic.h | 2 ++ src/creature_instances.h | 2 ++ src/creature_states_combt.c | 19 +++++++++++++++++++ src/creature_states_combt.h | 1 + src/creature_states_prisn.c | 3 +++ src/gui_boxmenu.c | 1 + src/room_jobs.c | 4 ++++ src/thing_creature.c | 37 +++++++++++++++++++++++++++++++++++- src/thing_creature.h | 2 ++ src/thing_effects.c | 38 +++++++++++++++++++++++++++++++++++++ src/thing_effects.h | 1 + 14 files changed, 143 insertions(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 8481b40a6e..2d36067acb 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1114,6 +1114,25 @@ PrimaryTarget = 3 Properties = DESTRUCTIVE MELEE_ATTACK DISPLAY_SWIPE Function = creature_fire_shot SHOT_CRIPPLE 0 +[instance55] +Name = CLEANSE +Time = 10 +ActionTime = 6 +ResetTime = 375 +FPTime = 5 +FPActionTime = 3 +FPResetTime = 300 +FPInstantCast = 1 +ForceVisibility = 10 +TooltipTextID = 1067 +SymbolSprites = 701 +Graphics = CASTSPELL +Properties = SELF_BUFF +PrimaryTarget = 3 +Function = creature_cast_spell SPELL_CLEANSE 0 +ValidateSourceFunc = validate_source_generic 0 0 +ValidateTargetFunc = validate_target_non_idle 0 0 + [job0] ; Empty job, indicates no job assigned. Name = NULL diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 9195bb227e..82981c9166 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -46,6 +46,7 @@ SpellPower = NOPOWER ; 32768: TELEPORT - If self-cast, jumps to its next objective or place to fulfill its needs. If cast on a target, jumps it to its lair or flee point. ; 65536: TIMEBOMB - Sets a countdown on the target, making it move toward enemies to explode on impact, dealing damage from the linked shot. ; 131072: WIND - Not functional on spells, exists only for immunity. +; 262144: SPELL_BLOCKS - Prevents effects from affecting the creature. Must be combined with 'CleanseFlags' to function, has no effect on its own. SpellFlags = 0 ; Spell effects to remove from the target. Use the same list as 'SpellFlags'. Accepts both names and numbers. CleanseFlags = 0 @@ -357,6 +358,18 @@ Duration = 160 SelfCasted = 1 978 1 SymbolSprites = 768 770 +[spell32] +; Cures all negative effect and blocks them for a short duration. +Name = SPELL_CLEANSE +CastAtThing = 0 +ShotModel = NOSHOT +SpellPower = NOPOWER +SpellFlags = SPELL_BLOCKS +CleanseFlags = SLOW DISEASE CHICKEN FREEZE MAD_KILLING FEAR TIMEBOMB +Duration = 100 +SelfCasted = 1 161 1 +SymbolSprites = 699 701 + ; Shots types. [shot0] diff --git a/src/config_magic.c b/src/config_magic.c index 4129025a13..ee974053ab 100644 --- a/src/config_magic.c +++ b/src/config_magic.c @@ -98,6 +98,8 @@ const struct NamedCommand spell_effect_flags[] = { {"TELEPORT", CSAfF_Teleport}, {"TIMEBOMB", CSAfF_Timebomb}, {"WIND", CSAfF_Wind}, + {"CLEANSE", CSAfF_Cleanse}, + {"SPELL_BLOCKS", CSAfF_SpellBlocks}, {NULL, 0}, }; diff --git a/src/config_magic.h b/src/config_magic.h index 4092812bc9..8e7a62f816 100644 --- a/src/config_magic.h +++ b/src/config_magic.h @@ -55,6 +55,8 @@ enum CreatureSpellAffectedFlags { CSAfF_Teleport = 0x008000, CSAfF_Timebomb = 0x010000, CSAfF_Wind = 0x020000, + CSAfF_Cleanse = 0x040000, + CSAfF_SpellBlocks = 0x080000, }; enum SpellPropertiesFlags { diff --git a/src/creature_instances.h b/src/creature_instances.h index f7b6f9ab56..597d1adad8 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -84,6 +84,8 @@ enum CreatureInstances { CrInst_RANGED_SPEED, CrInst_RANGED_ARMOUR, CrInst_RANGED_REBOUND, + CrInst_CRIPPLE, + CrInst_CLEANSE, CrInst_LISTEND, }; diff --git a/src/creature_states_combt.c b/src/creature_states_combt.c index 1581e8fc96..888ee6d9a8 100644 --- a/src/creature_states_combt.c +++ b/src/creature_states_combt.c @@ -3494,4 +3494,23 @@ short creature_damage_walls(struct Thing *creatng) } +TbBool creature_requires_cleansing(const struct Thing* thing) +{ + struct CreatureControl* cctrl = creature_control_get_from_thing(thing); + struct SpellConfig* spconf = get_spell_config(32); + for (long i = 0; i < CREATURE_MAX_SPELLS_CASTED_AT; i++) + { + struct CastedSpellData *cspell = &cctrl->casted_spells[i]; + struct SpellConfig* spconf2 = get_spell_config(cspell->spkind); + if (flag_is_set(spconf->cleanse_flags, spconf2->spell_flags)) + { + if (creature_under_spell_effect(thing, spconf2->spell_flags)) + { + return true; + } + } + } + return false; +} + /******************************************************************************/ diff --git a/src/creature_states_combt.h b/src/creature_states_combt.h index 8bf88bbead..d0c0b486af 100644 --- a/src/creature_states_combt.h +++ b/src/creature_states_combt.h @@ -71,6 +71,7 @@ TbBool creature_has_creature_in_combat(const struct Thing *thing, const struct T TbBool set_creature_combat_state(struct Thing *fighter, struct Thing *enemy, CrAttackType attack_type); TbBool battle_with_creature_of_player(PlayerNumber plyr_idx, BattleIndex battle_id); TbBool creature_would_benefit_from_healing(const struct Thing* thing); +TbBool creature_requires_cleansing(const struct Thing* thing); void reset_postal_instance_cache(); CrInstance get_postal_instance_to_use(const struct Thing *thing, unsigned long dist); diff --git a/src/creature_states_prisn.c b/src/creature_states_prisn.c index 98362c92d9..ab5dc602bf 100644 --- a/src/creature_states_prisn.c +++ b/src/creature_states_prisn.c @@ -126,6 +126,9 @@ short creature_arrived_at_prison(struct Thing *creatng) { clean_spell_effect(creatng, CSAfF_Invisibility); } + if (creature_under_spell_effect(creatng, CSAfF_Cleanse)) { + clean_spell_effect(creatng, CSAfF_Cleanse); + } if (creatng->light_id != 0) { light_delete_light(creatng->light_id); creatng->light_id = 0; diff --git a/src/gui_boxmenu.c b/src/gui_boxmenu.c index 5363bcc412..e8bec6e14e 100644 --- a/src/gui_boxmenu.c +++ b/src/gui_boxmenu.c @@ -148,6 +148,7 @@ struct GuiBoxOption gui_instance_option_list[] = { {"Disease",1,NULL, gf_change_creature_instance,CrInst_CAST_SPELL_DISEASE, 0, 0, CrInst_CAST_SPELL_DISEASE, 0, 0, 0, true}, {"Chicken",1,NULL, gf_change_creature_instance,CrInst_CAST_SPELL_CHICKEN, 0, 0, CrInst_CAST_SPELL_CHICKEN, 0, 0, 0, true}, {"Time Bomb",1,NULL, gf_change_creature_instance,CrInst_CAST_SPELL_TIME_BOMB, 0, 0, CrInst_CAST_SPELL_TIME_BOMB, 0, 0, 0, true}, + {"Cleanse", 1, NULL, gf_change_creature_instance, CrInst_CLEANSE, 0, 0, CrInst_CLEANSE, 0, 0, 0, true}, {"!", 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, false}, }; diff --git a/src/room_jobs.c b/src/room_jobs.c index 90c1a3d8b4..7441efeddc 100644 --- a/src/room_jobs.c +++ b/src/room_jobs.c @@ -101,6 +101,10 @@ TbBool add_creature_to_torture_room(struct Thing *creatng, const struct Room *ro { clean_spell_effect(creatng, CSAfF_Invisibility); } + if (creature_under_spell_effect(creatng, CSAfF_SpellBlocks)) + { + clean_spell_effect(creatng, CSAfF_SpellBlocks); + } if (room->owner != game.neutral_player_num) { struct Dungeon* dungeon = get_dungeon(room->owner); diff --git a/src/thing_creature.c b/src/thing_creature.c index 0ec0e978af..93d3a69f40 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1176,6 +1176,13 @@ TbBool set_thing_spell_flags_f(struct Thing *thing, SpellKind spell_idx, GameTur } affected = true; } + // CLEANSE. + if (flag_is_set(spconf->spell_flags, CSAfF_Cleanse) + && (!creature_is_immune_to_spell_effect(thing, CSAfF_Cleanse))) + { + cleanse_creature(thing); + affected = true; + } if (!affected) { SYNCDBG(7, "%s: No spell flags %d to set on %s index %d", func_name, (uint)spconf->spell_flags, thing_model_name(thing), (int)thing->index); @@ -1357,6 +1364,12 @@ TbBool clear_thing_spell_flags_f(struct Thing *thing, unsigned long spell_flags, // 'CSAfF_Heal' is never set but we still want to mark it cleared to free the spell slot. cleared = true; } + // CLEANSE. + if (flag_is_set(spell_flags, CSAfF_Cleanse)) + { + clear_flag(cctrl->spell_flags, CSAfF_Cleanse); + cleared = true; + } if (!cleared) { SYNCDBG(7, "%s: No spell flags %d to clear on %s index %d", func_name, (uint)spell_flags, thing_model_name(thing), (int)thing->index); @@ -6326,7 +6339,13 @@ TngUpdateRet update_creature(struct Thing *thing) } } else { - if ((cctrl->stateblock_flags == 0) || creature_state_cannot_be_blocked(thing)) + if (creature_under_spell_effect(thing, CSAfF_Freeze)) + { + if (creature_instance_is_available(thing, CrInst_CLEANSE) && creature_instance_has_reset(thing, CrInst_CLEANSE)) { + cctrl->stopped_for_hand_turns = 0; + } + } + else if ((cctrl->stateblock_flags == 0) || creature_state_cannot_be_blocked(thing)) { if (cctrl->stopped_for_hand_turns > 0) { @@ -7844,6 +7863,22 @@ TbBool script_change_creatures_annoyance(PlayerNumber plyr_idx, ThingModel crmod return true; } +void cleanse_creature(struct Thing* creatng) +{ + struct CreatureControl* cctrl = creature_control_get_from_thing(creatng); + struct SpellConfig* spconf = get_spell_config(32); + clean_spell_effect(creatng, spconf->cleanse_flags); + for (long i = 0; i < CREATURE_MAX_SPELLS_CASTED_AT; i++) + { + struct CastedSpellData *cspell = &cctrl->casted_spells[i]; + struct SpellConfig* spconf2 = get_spell_config(cspell->spkind); + if (flag_is_set(spconf->cleanse_flags, spconf2->spell_flags)) + { + cspell->duration = 0; + } + } +} + /******************************************************************************/ #ifdef __cplusplus } diff --git a/src/thing_creature.h b/src/thing_creature.h index 657d912461..355e43d269 100644 --- a/src/thing_creature.h +++ b/src/thing_creature.h @@ -205,6 +205,8 @@ TbBool creature_stats_debug_dump(void); void create_light_for_possession(struct Thing *creatng); void illuminate_creature(struct Thing *creatng); +void cleanse_creature(struct Thing* creatng); + long get_spell_slot(const struct Thing *thing, SpellKind spkind); TbBool free_spell_slot(struct Thing *thing, int slot_idx); diff --git a/src/thing_effects.c b/src/thing_effects.c index eb8a464f4a..729b8b6707 100644 --- a/src/thing_effects.c +++ b/src/thing_effects.c @@ -1753,6 +1753,44 @@ void create_effects_line(TbMapLocation from, TbMapLocation to, char curvature, u fx_line->partial_steps = FX_LINE_TIME_PARTS; } +// Initial state from the side view of the sphere: +// 'r' is the radius of the circle +// The equation of the circle is x^2 + y^2 = r^2 +// Solving for x, we get x = sqrt(r^2 - y^2) +// As 'y' varies, we recompute 'x', which is the new radius for the lower and upper parts of the sphere +// The point of origin would be the center of the creature +// Starting at y = -r, then x = 0 (a single dot) +// In 3D space, 'y' corresponds to 'z', representing the height +void process_cleanse_effect(struct Thing* thing) { + struct CreatureControl* cctrl = creature_control_get_from_thing(thing); + + int height = thing->clipbox_size_z + thing->floor_height + (5 * game.conf.crtr_conf.exp.size_increase_on_exp * cctrl->exp_level); + int z_min = thing->mappos.z.val; + int z_max = z_min + height; + int z_mid = (z_min + z_max) >> 1; + + int r_max = z_max - z_mid; + int r_max_s = r_max * r_max; + + struct Coord3d pos; + pos.z.val = z_min; + while (true) { + pos.z.val += 64; + if (pos.z.val >= z_max) { + break; + } + int y = pos.z.val - z_mid; + int r = LbSqrL(r_max_s - (y * y)); + for (int j = 0; j < 32; ++j) + { + int angle = j << 6; // 11.25 degrees + pos.x.val = thing->mappos.x.val + (r * LbSinL(angle) >> 16); + pos.y.val = thing->mappos.y.val + (r * LbCosL(angle) >> 16); + create_thing(&pos, TCls_EffectElem, TngEffElm_TinyFlash1, thing->owner, -1); + } + } +} + /******************************************************************************/ #ifdef __cplusplus } diff --git a/src/thing_effects.h b/src/thing_effects.h index 357bcd981e..7ddbfc0e90 100644 --- a/src/thing_effects.h +++ b/src/thing_effects.h @@ -281,6 +281,7 @@ TngUpdateRet update_effect_element(struct Thing *thing); TngUpdateRet update_effect(struct Thing *thing); TngUpdateRet process_effect_generator(struct Thing *thing); void process_spells_affected_by_effect_elements(struct Thing *thing); +void process_cleanse_effect(struct Thing* thing); TbBool destroy_effect_thing(struct Thing *thing); struct Thing *create_price_effect(const struct Coord3d *pos, long plyr_idx, long price); void process_fx_lines(); From 62c4d3df8e402b96638f804fad7cf7fca2360e0d Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 04:45:29 +0000 Subject: [PATCH 02/81] Update magic.cfg --- config/fxdata/magic.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 82981c9166..28ca3403f5 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -364,7 +364,7 @@ Name = SPELL_CLEANSE CastAtThing = 0 ShotModel = NOSHOT SpellPower = NOPOWER -SpellFlags = SPELL_BLOCKS +SpellFlags = CLEANSE SPELL_BLOCKS CleanseFlags = SLOW DISEASE CHICKEN FREEZE MAD_KILLING FEAR TIMEBOMB Duration = 100 SelfCasted = 1 161 1 From d6fdf20c03f9558d9142c27c57404188c1a054e8 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 04:55:55 +0000 Subject: [PATCH 03/81] Update creature.cfg --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 2d36067acb..2eabb00e12 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1125,7 +1125,7 @@ FPResetTime = 300 FPInstantCast = 1 ForceVisibility = 10 TooltipTextID = 1067 -SymbolSprites = 701 +SymbolSprites = 796 Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 3 From 7e69b915ed2d8f338ab959c2b4efb0105095b0ea Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:00:08 +0000 Subject: [PATCH 04/81] Update creature.cfg --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 2eabb00e12..4ebff301c6 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1125,7 +1125,7 @@ FPResetTime = 300 FPInstantCast = 1 ForceVisibility = 10 TooltipTextID = 1067 -SymbolSprites = 796 +SymbolSprites = 794 Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 3 From dc526e5b1fe2ea02bfd94f9da3b857beb8470e66 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:02:14 +0000 Subject: [PATCH 05/81] Update creature.cfg --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 4ebff301c6..bff4ff5a67 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1125,7 +1125,7 @@ FPResetTime = 300 FPInstantCast = 1 ForceVisibility = 10 TooltipTextID = 1067 -SymbolSprites = 794 +SymbolSprites = 798 Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 3 From 63452bf12870c3bdfb6dd4506f99521739409d60 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:05:02 +0000 Subject: [PATCH 06/81] Update thing_creature.c --- src/thing_creature.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/thing_creature.c b/src/thing_creature.c index 93d3a69f40..dad11a1b77 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -7865,6 +7865,7 @@ TbBool script_change_creatures_annoyance(PlayerNumber plyr_idx, ThingModel crmod void cleanse_creature(struct Thing* creatng) { + process_cleanse_effect(creatng); struct CreatureControl* cctrl = creature_control_get_from_thing(creatng); struct SpellConfig* spconf = get_spell_config(32); clean_spell_effect(creatng, spconf->cleanse_flags); From a8f1f8be3f5d8663f1d6273d9894fc61261331e6 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:19:29 +0000 Subject: [PATCH 07/81] Update magic.cfg --- config/fxdata/magic.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 28ca3403f5..3e57941f0b 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -368,7 +368,7 @@ SpellFlags = CLEANSE SPELL_BLOCKS CleanseFlags = SLOW DISEASE CHICKEN FREEZE MAD_KILLING FEAR TIMEBOMB Duration = 100 SelfCasted = 1 161 1 -SymbolSprites = 699 701 +SymbolSprites = 798 800 ; Shots types. From bfb8e0b77e561529051339a675a770ea6bcab68f Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:21:43 +0000 Subject: [PATCH 08/81] Update magic.cfg --- config/fxdata/magic.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 3e57941f0b..f181307f95 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -368,7 +368,7 @@ SpellFlags = CLEANSE SPELL_BLOCKS CleanseFlags = SLOW DISEASE CHICKEN FREEZE MAD_KILLING FEAR TIMEBOMB Duration = 100 SelfCasted = 1 161 1 -SymbolSprites = 798 800 +SymbolSprites = 796 798 ; Shots types. From f738dafd7e54de8381cd2ee0ded0295395d537a8 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:39:01 +0000 Subject: [PATCH 09/81] Not needed. --- src/thing_creature.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/thing_creature.c b/src/thing_creature.c index dad11a1b77..77d407eef9 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1367,7 +1367,7 @@ TbBool clear_thing_spell_flags_f(struct Thing *thing, unsigned long spell_flags, // CLEANSE. if (flag_is_set(spell_flags, CSAfF_Cleanse)) { - clear_flag(cctrl->spell_flags, CSAfF_Cleanse); + // 'CSAfF_Cleanse' is never set but we still want to mark it cleared to free the spell slot. cleared = true; } if (!cleared) @@ -7868,7 +7868,6 @@ void cleanse_creature(struct Thing* creatng) process_cleanse_effect(creatng); struct CreatureControl* cctrl = creature_control_get_from_thing(creatng); struct SpellConfig* spconf = get_spell_config(32); - clean_spell_effect(creatng, spconf->cleanse_flags); for (long i = 0; i < CREATURE_MAX_SPELLS_CASTED_AT; i++) { struct CastedSpellData *cspell = &cctrl->casted_spells[i]; From 84a9213ea7cc073708984b1d0dfb83f7d4f36b86 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 05:50:08 +0000 Subject: [PATCH 10/81] Update magic.cfg --- config/fxdata/magic.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index f181307f95..8e4f6b3a6a 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -46,7 +46,8 @@ SpellPower = NOPOWER ; 32768: TELEPORT - If self-cast, jumps to its next objective or place to fulfill its needs. If cast on a target, jumps it to its lair or flee point. ; 65536: TIMEBOMB - Sets a countdown on the target, making it move toward enemies to explode on impact, dealing damage from the linked shot. ; 131072: WIND - Not functional on spells, exists only for immunity. -; 262144: SPELL_BLOCKS - Prevents effects from affecting the creature. Must be combined with 'CleanseFlags' to function, has no effect on its own. +; 262144: CLEANSE - Cures effects specified in 'CleanseFlags'. +; 524288: SPELL_BLOCKS - Prevents effects from affecting the creature. Must be combined with 'CleanseFlags' to function, has no effect on its own. SpellFlags = 0 ; Spell effects to remove from the target. Use the same list as 'SpellFlags'. Accepts both names and numbers. CleanseFlags = 0 From b3a1e09910aa9e161441b69a3f89282ee07afb80 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 06:26:10 +0000 Subject: [PATCH 11/81] Does this help? --- config/fxdata/creature.cfg | 2 +- src/creature_instances.c | 33 +++++++++++++++++++++++++++++++++ src/creature_instances.h | 1 + 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index bff4ff5a67..aff944cfff 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1131,7 +1131,7 @@ Properties = SELF_BUFF PrimaryTarget = 3 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_generic 0 0 -ValidateTargetFunc = validate_target_non_idle 0 0 +ValidateTargetFunc = validate_target_requires_cleansing 0 0 [job0] ; Empty job, indicates no job assigned. diff --git a/src/creature_instances.c b/src/creature_instances.c index af595bc9c9..feb86ce506 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1826,4 +1826,37 @@ void script_set_creature_instance(ThingModel crmodel, short slot, int instance, } } +TbBool validate_target_requires_cleansing + ( + struct Thing *source, + struct Thing *target, + CrInstance inst_idx, + int32_t param1, + int32_t param2 + ) +{ + if (!validate_target_basic(source, target, inst_idx, param1, param2) || creature_is_being_unconscious(target) || + !creature_requires_cleansing(target)) + { + return false; + } + + if (source->index == target->index) + { + // Special case. The creature is always allowed to cleanse itself even if + // it's being tortured or imprisoned. + return true; + } + else + { + if (creature_is_being_tortured(target) || creature_is_kept_in_prison(target) || + creature_is_being_tortured(source) || creature_is_kept_in_prison(source)) + { + return false; + } + } + + return true; +} + /******************************************************************************/ diff --git a/src/creature_instances.h b/src/creature_instances.h index 597d1adad8..9f5537ee8f 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -181,6 +181,7 @@ TbBool validate_target_benefits_from_wind(struct Thing *source, struct Thing *ta TbBool validate_target_benefits_from_healing(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_non_idle(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_takes_gas_damage(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); +TbBool validate_target_requires_cleansing(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool search_target_generic(struct Thing *source, CrInstance inst_idx, ThingIndex **targets, uint16_t *found_count, int32_t param1, int32_t param2); TbBool search_target_ranged_heal(struct Thing *source, CrInstance inst_idx, ThingIndex **targets, uint16_t *found_count, int32_t param1, int32_t param2); From e4b1ce8d0b6411cf1ed4e1842d75fc409d064d62 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 06:34:33 +0000 Subject: [PATCH 12/81] Update creature.cfg --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index aff944cfff..446024ee23 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1130,7 +1130,7 @@ Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 3 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_generic 0 0 +ValidateSourceFunc = validate_source_even_in_prison 0 0 ValidateTargetFunc = validate_target_requires_cleansing 0 0 [job0] From 7f2d06eddeb30658b76ce621d235de00aac5f7ae Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 06:48:19 +0000 Subject: [PATCH 13/81] Now it works! --- src/creature_instances.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/creature_instances.c b/src/creature_instances.c index feb86ce506..aee8165925 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -126,6 +126,7 @@ const struct NamedCommand creature_instances_validate_func_type[] = { {"validate_target_benefits_from_wind", 10}, {"validate_target_non_idle", 11}, {"validate_target_takes_gas_damage", 12}, + {"validate_target_requires_cleansing", 13}, {NULL, 0}, }; @@ -143,6 +144,7 @@ Creature_Validate_Func creature_instances_validate_func_list[] = { validate_target_benefits_from_wind, validate_target_non_idle, validate_target_takes_gas_damage, + validate_target_requires_cleansing, NULL, }; From b5de5da8f5a02e2b3043228db9ef8e46d2d53919 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 07:25:49 +0000 Subject: [PATCH 14/81] Set Spell Block flags. --- src/thing_creature.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/thing_creature.c b/src/thing_creature.c index 77d407eef9..c6d2ac7c6c 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1183,6 +1183,13 @@ TbBool set_thing_spell_flags_f(struct Thing *thing, SpellKind spell_idx, GameTur cleanse_creature(thing); affected = true; } + // Spell Blocks. + if (flag_is_set(spconf->spell_flags, CSAfF_SpellBlocks) + && (!creature_is_immune_to_spell_effect(thing, CSAfF_SpellBlocks))) + { + set_flag(cctrl->spell_flags, CSAfF_SpellBlocks); + affected = true; + } if (!affected) { SYNCDBG(7, "%s: No spell flags %d to set on %s index %d", func_name, (uint)spconf->spell_flags, thing_model_name(thing), (int)thing->index); @@ -1370,6 +1377,13 @@ TbBool clear_thing_spell_flags_f(struct Thing *thing, unsigned long spell_flags, // 'CSAfF_Cleanse' is never set but we still want to mark it cleared to free the spell slot. cleared = true; } + // Spell Blocks. + if (flag_is_set(spell_flags, CSAfF_SpellBlocks) + && (creature_under_spell_effect(thing, CSAfF_SpellBlocks))) + { + clear_flag(cctrl->spell_flags, CSAfF_SpellBlocks); + cleared = true; + } if (!cleared) { SYNCDBG(7, "%s: No spell flags %d to clear on %s index %d", func_name, (uint)spell_flags, thing_model_name(thing), (int)thing->index); From a066fc9c252a782f79ce677392c903c8c9120eab Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 08:17:34 +0000 Subject: [PATCH 15/81] Not needed. --- src/thing_creature.c | 18 +----------------- src/thing_creature.h | 2 -- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/thing_creature.c b/src/thing_creature.c index c6d2ac7c6c..6b09e52b1b 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1180,7 +1180,7 @@ TbBool set_thing_spell_flags_f(struct Thing *thing, SpellKind spell_idx, GameTur if (flag_is_set(spconf->spell_flags, CSAfF_Cleanse) && (!creature_is_immune_to_spell_effect(thing, CSAfF_Cleanse))) { - cleanse_creature(thing); + process_cleanse_effect(thing); affected = true; } // Spell Blocks. @@ -7877,22 +7877,6 @@ TbBool script_change_creatures_annoyance(PlayerNumber plyr_idx, ThingModel crmod return true; } -void cleanse_creature(struct Thing* creatng) -{ - process_cleanse_effect(creatng); - struct CreatureControl* cctrl = creature_control_get_from_thing(creatng); - struct SpellConfig* spconf = get_spell_config(32); - for (long i = 0; i < CREATURE_MAX_SPELLS_CASTED_AT; i++) - { - struct CastedSpellData *cspell = &cctrl->casted_spells[i]; - struct SpellConfig* spconf2 = get_spell_config(cspell->spkind); - if (flag_is_set(spconf->cleanse_flags, spconf2->spell_flags)) - { - cspell->duration = 0; - } - } -} - /******************************************************************************/ #ifdef __cplusplus } diff --git a/src/thing_creature.h b/src/thing_creature.h index 355e43d269..657d912461 100644 --- a/src/thing_creature.h +++ b/src/thing_creature.h @@ -205,8 +205,6 @@ TbBool creature_stats_debug_dump(void); void create_light_for_possession(struct Thing *creatng); void illuminate_creature(struct Thing *creatng); -void cleanse_creature(struct Thing* creatng); - long get_spell_slot(const struct Thing *thing, SpellKind spkind); TbBool free_spell_slot(struct Thing *thing, int slot_idx); From 76e70e9efb6700047eaca36b2655b80222f77cd4 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 08:39:03 +0000 Subject: [PATCH 16/81] Update thing_creature.c --- src/thing_creature.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/thing_creature.c b/src/thing_creature.c index 6b09e52b1b..701f2b6f16 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1508,12 +1508,15 @@ void apply_spell_effect_to_thing(struct Thing *thing, SpellKind spell_idx, CrtrE } GameTurnDelta duration = get_spell_full_duration(spell_idx, spell_level); // Check for cleansing one-time effect. - if (spconf->cleanse_flags > 0 - && any_flag_is_set(spconf->cleanse_flags, cctrl->spell_flags)) + if ((spconf->cleanse_flags > 0) + && (any_flag_is_set(spconf->cleanse_flags, cctrl->spell_flags))) { - clean_spell_effect(thing, spconf->cleanse_flags); - if (spconf->spell_flags == 0 - && !spell_is_continuous(spell_idx, duration)) + if (!creature_is_immune_to_spell_effect(thing, CSAfF_Cleanse)) + { + clean_spell_effect(thing, spconf->cleanse_flags); + } + if ((spconf->spell_flags == 0) + && (!spell_is_continuous(spell_idx, duration))) { update_aura_effect_to_thing(thing, spell_idx); return; // Exit the function, no continuous effect to apply. From e306d8912cb27c8952e36fadcf81f4a54c725220 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 08:59:54 +0000 Subject: [PATCH 17/81] Fixed immediate termination --- src/thing_creature.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thing_creature.c b/src/thing_creature.c index 701f2b6f16..b7f9f21bdc 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1903,7 +1903,7 @@ void process_thing_spell_effects(struct Thing *thing) struct SpellConfig *spconf = get_spell_config(cspell->spkind); // Terminate the spell if its duration expires, or if the spell flags are cleared and no other continuous effects are active. if ((cspell->duration <= 0) - || ((spconf->spell_flags > 0) && !flag_is_set(cctrl->spell_flags, spconf->spell_flags) && !spell_is_continuous(cspell->spkind, cspell->duration))) + || ((spconf->spell_flags > 0) && !any_flag_is_set(cctrl->spell_flags, spconf->spell_flags) && !spell_is_continuous(cspell->spkind, cspell->duration))) { terminate_thing_spell_effect(thing, cspell->spkind); continue; From d5bb9a0378c535bf3e34968019e60e7894e98a4d Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 20:31:15 +0000 Subject: [PATCH 18/81] Block spells --- src/thing_creature.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/thing_creature.c b/src/thing_creature.c index b7f9f21bdc..6b83c79163 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -716,6 +716,14 @@ TbBool creature_is_immune_to_spell_effect_f(const struct Thing *thing, unsigned { return false; } + if (creature_under_spell_effect(thing, CSAfF_SpellBlocks)) + { + struct SpellConfig* spconf = get_spell_config(32); + if (flag_is_set(spconf->cleanse_flags, spell_flags)) + { + return true; + } + } return flag_is_set(crconf->immunity_flags, spell_flags); } From d214e829c7c2e20e3ca078c7b2ab8f93475014c9 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:33:54 +0000 Subject: [PATCH 19/81] Take spell from instance info --- src/creature_states_combt.c | 3 ++- src/thing_creature.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/creature_states_combt.c b/src/creature_states_combt.c index 2f7d99f681..2f011b018c 100644 --- a/src/creature_states_combt.c +++ b/src/creature_states_combt.c @@ -3497,7 +3497,8 @@ short creature_damage_walls(struct Thing *creatng) TbBool creature_requires_cleansing(const struct Thing* thing) { struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - struct SpellConfig* spconf = get_spell_config(32); + struct InstanceInfo* inst_inf = creature_instance_info_get(CrInst_CLEANSE); + struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); for (long i = 0; i < CREATURE_MAX_SPELLS_CASTED_AT; i++) { struct CastedSpellData *cspell = &cctrl->casted_spells[i]; diff --git a/src/thing_creature.c b/src/thing_creature.c index b902a93535..87b7cd893f 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -718,7 +718,8 @@ TbBool creature_is_immune_to_spell_effect_f(const struct Thing *thing, unsigned } if (creature_under_spell_effect(thing, CSAfF_SpellBlocks)) { - struct SpellConfig* spconf = get_spell_config(32); + struct InstanceInfo* inst_inf = creature_instance_info_get(CrInst_CLEANSE); + struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); if (flag_is_set(spconf->cleanse_flags, spell_flags)) { return true; From c76fa1de2441e1a8e97e82d9d4d2c076e46430fa Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:58:48 +0000 Subject: [PATCH 20/81] User param1 for validation spell id --- config/fxdata/creature.cfg | 2 +- src/creature_instances.c | 2 +- src/creature_states_combt.c | 5 ++--- src/creature_states_combt.h | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 446024ee23..8d0905858a 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1131,7 +1131,7 @@ Properties = SELF_BUFF PrimaryTarget = 3 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_even_in_prison 0 0 -ValidateTargetFunc = validate_target_requires_cleansing 0 0 +ValidateTargetFunc = validate_target_requires_cleansing 32 0 [job0] ; Empty job, indicates no job assigned. diff --git a/src/creature_instances.c b/src/creature_instances.c index aae3e4438a..8587e2890d 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1838,7 +1838,7 @@ TbBool validate_target_requires_cleansing ) { if (!validate_target_basic(source, target, inst_idx, param1, param2) || creature_is_being_unconscious(target) || - !creature_requires_cleansing(target)) + !creature_requires_cleansing(target, param1)) { return false; } diff --git a/src/creature_states_combt.c b/src/creature_states_combt.c index 2f011b018c..bfff4b7149 100644 --- a/src/creature_states_combt.c +++ b/src/creature_states_combt.c @@ -3494,11 +3494,10 @@ short creature_damage_walls(struct Thing *creatng) } -TbBool creature_requires_cleansing(const struct Thing* thing) +TbBool creature_requires_cleansing(const struct Thing* thing, SpellKind spell_idx) { struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - struct InstanceInfo* inst_inf = creature_instance_info_get(CrInst_CLEANSE); - struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); + struct SpellConfig* spconf = get_spell_config(spell_idx); for (long i = 0; i < CREATURE_MAX_SPELLS_CASTED_AT; i++) { struct CastedSpellData *cspell = &cctrl->casted_spells[i]; diff --git a/src/creature_states_combt.h b/src/creature_states_combt.h index d16e5298a4..61e8af0980 100644 --- a/src/creature_states_combt.h +++ b/src/creature_states_combt.h @@ -71,7 +71,7 @@ TbBool creature_has_creature_in_combat(const struct Thing *thing, const struct T TbBool set_creature_combat_state(struct Thing *fighter, struct Thing *enemy, CrAttackType attack_type); TbBool battle_with_creature_of_player(PlayerNumber plyr_idx, BattleIndex battle_id); TbBool creature_would_benefit_from_healing(const struct Thing* thing); -TbBool creature_requires_cleansing(const struct Thing* thing); +TbBool creature_requires_cleansing(const struct Thing* thing, SpellKind spell_idx); void reset_postal_instance_cache(); CrInstance get_postal_instance_to_use(const struct Thing *thing, unsigned long dist); From 2491866be3b67d8d1fe63a808767da746071049f Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Mon, 1 Dec 2025 02:24:54 +0000 Subject: [PATCH 21/81] cleanse_flags creature control field --- src/creature_control.h | 1 + src/thing_creature.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/creature_control.h b/src/creature_control.h index f22957adc1..183e206b69 100644 --- a/src/creature_control.h +++ b/src/creature_control.h @@ -194,6 +194,7 @@ struct CreatureControl { long turns_at_job; short blocking_door_id; unsigned char move_flags; + unsigned long cleanse_flags; union // Union on diggers, heroes and normal creatures { diff --git a/src/thing_creature.c b/src/thing_creature.c index 87b7cd893f..8607037fe5 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -718,11 +718,13 @@ TbBool creature_is_immune_to_spell_effect_f(const struct Thing *thing, unsigned } if (creature_under_spell_effect(thing, CSAfF_SpellBlocks)) { - struct InstanceInfo* inst_inf = creature_instance_info_get(CrInst_CLEANSE); - struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); - if (flag_is_set(spconf->cleanse_flags, spell_flags)) + struct CreatureControl *cctrl = creature_control_get_from_thing(thing); + if (!creature_control_invalid(cctrl)) { - return true; + if (flag_is_set(cctrl->cleanse_flags, spell_flags)) + { + return true; + } } } return flag_is_set(crconf->immunity_flags, spell_flags); @@ -1197,6 +1199,7 @@ TbBool set_thing_spell_flags_f(struct Thing *thing, SpellKind spell_idx, GameTur && (!creature_is_immune_to_spell_effect(thing, CSAfF_SpellBlocks))) { set_flag(cctrl->spell_flags, CSAfF_SpellBlocks); + cctrl->cleanse_flags = spconf->cleanse_flags; affected = true; } if (!affected) @@ -1391,6 +1394,7 @@ TbBool clear_thing_spell_flags_f(struct Thing *thing, unsigned long spell_flags, && (creature_under_spell_effect(thing, CSAfF_SpellBlocks))) { clear_flag(cctrl->spell_flags, CSAfF_SpellBlocks); + cctrl->cleanse_flags = 0; cleared = true; } if (!cleared) From c555929cac377c71661645cc8ea158cea94a1eae Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Mon, 1 Dec 2025 23:19:28 +0000 Subject: [PATCH 22/81] Don't cure or block MAD_KILLING or TIMEBOMB --- config/fxdata/magic.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index ffbb9658b0..df6629c4dd 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -366,7 +366,7 @@ CastAtThing = 0 ShotModel = NOSHOT SpellPower = NOPOWER SpellFlags = CLEANSE SPELL_BLOCKS -CleanseFlags = SLOW DISEASE CHICKEN FREEZE MAD_KILLING FEAR TIMEBOMB +CleanseFlags = SLOW DISEASE CHICKEN FREEZE FEAR Duration = 100 SelfCasted = 1 161 1 SymbolSprites = 796 798 From 101420603d81791bf4cc6af9ca1e3f68dee1ec59 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Tue, 2 Dec 2025 01:59:19 +0000 Subject: [PATCH 23/81] Fixed icon positioning. --- src/engine_redraw.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/engine_redraw.c b/src/engine_redraw.c index c8a755d026..cc29a5a05e 100644 --- a/src/engine_redraw.c +++ b/src/engine_redraw.c @@ -99,10 +99,14 @@ static void draw_creature_view_icons(struct Thing* creatng) y = MyScreenHeight - scale_ui_value_lofi(spr->SHeight * 2); } struct CreatureControl *cctrl = creature_control_get_from_thing(creatng); - struct SpellConfig *spconf; for (SpellKind spell_idx = 0; spell_idx < CREATURE_MAX_SPELLS_CASTED_AT; spell_idx++) { - spconf = get_spell_config(cctrl->casted_spells[spell_idx].spkind); + struct CastedSpellData* cspell = &cctrl->casted_spells[spell_idx]; + if (cspell->spkind == 0) + { + continue; + } + struct SpellConfig *spconf = get_spell_config(cspell->spkind); long spridx = spconf->medsym_sprite_idx; if (flag_is_set(spconf->spell_flags, CSAfF_Invisibility)) { From 068483911ee732dd6482e742aa3ac897454b981e Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:34:08 +0000 Subject: [PATCH 24/81] Creatures self-Cleanse for Freeze --- src/creature_instances.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index 8587e2890d..eaeb38fbc9 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1149,7 +1149,6 @@ TbBool validate_source_basic if (!creature_instance_is_available(source, inst_idx) || !creature_instance_has_reset(source, inst_idx) || - creature_under_spell_effect(source, CSAfF_Freeze) || creature_is_fleeing_combat(source) || creature_under_spell_effect(source, CSAfF_Chicken) || creature_is_being_unconscious(source) || creature_is_dying(source) || thing_is_picked_up(source) || creature_is_being_dropped(source) || @@ -1157,6 +1156,10 @@ TbBool validate_source_basic { return false; } + if (creature_under_spell_effect(source, CSAfF_Freeze)) + { + return (inst_idx == CrInst_CLEANSE); + } return true; } From 3ef74aab0dc6fa5c8608bb829af70b4edc87f577 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:52:28 +0000 Subject: [PATCH 25/81] Make it configurable --- config/fxdata/creature.cfg | 2 +- src/config_creature.c | 1 + src/config_creature.h | 1 + src/creature_instances.c | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 8d0905858a..f8a83ab61a 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1127,7 +1127,7 @@ ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 Graphics = CASTSPELL -Properties = SELF_BUFF +Properties = SELF_BUFF WHILE_FROZEN PrimaryTarget = 3 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_even_in_prison 0 0 diff --git a/src/config_creature.c b/src/config_creature.c index b0e41e3c6e..fd7f3e09d1 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -121,6 +121,7 @@ const struct NamedCommand creaturetype_instance_properties[] = { {"DISPLAY_SWIPE", InstPF_UsesSwipe}, {"RANGED_BUFF", InstPF_RangedBuff}, {"NEEDS_TARGET", InstPF_NeedsTarget}, + {"WHILE_FROZEN", InstPF_AllowWhileFrozen}, {NULL, 0}, }; diff --git a/src/config_creature.h b/src/config_creature.h index 6d01b2f958..34a484c6dc 100644 --- a/src/config_creature.h +++ b/src/config_creature.h @@ -155,6 +155,7 @@ enum InstancePropertiesFlags { InstPF_UsesSwipe = 0x0200, InstPF_RangedBuff = 0x0400, InstPF_NeedsTarget = 0x0800, + InstPF_AllowWhileFrozen = 0x1000, }; enum CreatureDeathKind { diff --git a/src/creature_instances.c b/src/creature_instances.c index eaeb38fbc9..f590d855a3 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1158,7 +1158,8 @@ TbBool validate_source_basic } if (creature_under_spell_effect(source, CSAfF_Freeze)) { - return (inst_idx == CrInst_CLEANSE); + struct InstanceInfo* inst_inf = creature_instance_info_get(inst_idx); + return flag_is_set(inst_inf->instance_property_flags, InstPF_AllowWhileFrozen); } return true; From 09dae087d83fceabc8df4987748e7c5d72b7b4eb Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:54:25 +0000 Subject: [PATCH 26/81] Update creature.cfg --- config/fxdata/creature.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index f8a83ab61a..fa2f9d2c30 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -87,6 +87,7 @@ PostalPriority = 0 ; RANGED_BUFF can be applied to another friendly creature. ; NEEDS_TARGET Cannot be used in possession without a target to cast it on. ; DISARMING allows the instance to be used against traps. +; WHILE_FROZEN allows the instance to be used while the creature is frozen (under the Freeze spell) Properties = ; Function used as the instance action, and its parameters. Function = none 0 0 From 6c259929964ba530f7197231dccc6f0a38d8a6b3 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:56:44 +0000 Subject: [PATCH 27/81] Update creature.cfg --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index fa2f9d2c30..a75ea886c6 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -87,7 +87,7 @@ PostalPriority = 0 ; RANGED_BUFF can be applied to another friendly creature. ; NEEDS_TARGET Cannot be used in possession without a target to cast it on. ; DISARMING allows the instance to be used against traps. -; WHILE_FROZEN allows the instance to be used while the creature is frozen (under the Freeze spell) +; WHILE_FROZEN allows the instance to be used while the creature is frozen (under the Freeze spell). Properties = ; Function used as the instance action, and its parameters. Function = none 0 0 From 038ee65cb38f69cce19445a637e5437846d728ee Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 13 Dec 2025 21:09:25 +0000 Subject: [PATCH 28/81] Configurable effect --- config/fxdata/effects.toml | 30 ++++++++++++++++++++++++++++- config/fxdata/magic.cfg | 4 +++- src/config_magic.c | 1 - src/config_magic.h | 3 +-- src/creature_states_prisn.c | 4 ++-- src/thing_creature.c | 18 +----------------- src/thing_effects.c | 38 ------------------------------------- src/thing_effects.h | 1 - 8 files changed, 36 insertions(+), 63 deletions(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index 19ab542694..731cedd141 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -5301,4 +5301,32 @@ TransformModel = 0 LightRadius = 1 LightIntensity = 0 LightFlags = 0 -AffectedByWind = 1 \ No newline at end of file +AffectedByWind = 1 + +[effectElement124] +Name = "EFFECTELEMENT_CLEANSE" +DrawClass = 2 +MoveType = 5 +Unanimated = 0 +Lifespan = [-1,-1] +AnimationId = 116 +SpriteSize = [96,150] +AnimateOnce = 0 +SpriteSpeed = [256,256] +AnimateOnFloor = true +Unshaded = true +Transparent = 3 +ThroughWalls = 0 +SizeChange = 0 +FallAcceleration = 0 +InertiaFloor = 0 +InertiaAir = 0 +SubeffectModel = 0 +SubeffectDelay = 0 +Movable = false +Impacts = false +TransformModel = 0 +LightRadius = 0 +LightIntensity = 0 +LightFlags = 0 +AffectedByWind = 0 \ No newline at end of file diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index df6629c4dd..adb6b138ff 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -365,7 +365,9 @@ Name = SPELL_CLEANSE CastAtThing = 0 ShotModel = NOSHOT SpellPower = NOPOWER -SpellFlags = CLEANSE SPELL_BLOCKS +SpellFlags = SPELL_BLOCKS +AuraEffect = EFFECTELEMENT_CLEANSE +AuraDuration = 20 CleanseFlags = SLOW DISEASE CHICKEN FREEZE FEAR Duration = 100 SelfCasted = 1 161 1 diff --git a/src/config_magic.c b/src/config_magic.c index 06c81c2ba6..9ad2733ec6 100644 --- a/src/config_magic.c +++ b/src/config_magic.c @@ -98,7 +98,6 @@ const struct NamedCommand spell_effect_flags[] = { {"TELEPORT", CSAfF_Teleport}, {"TIMEBOMB", CSAfF_Timebomb}, {"WIND", CSAfF_Wind}, - {"CLEANSE", CSAfF_Cleanse}, {"SPELL_BLOCKS", CSAfF_SpellBlocks}, {NULL, 0}, }; diff --git a/src/config_magic.h b/src/config_magic.h index 8c6a4f15c8..1572d75909 100644 --- a/src/config_magic.h +++ b/src/config_magic.h @@ -55,8 +55,7 @@ enum CreatureSpellAffectedFlags { CSAfF_Teleport = 0x008000, CSAfF_Timebomb = 0x010000, CSAfF_Wind = 0x020000, - CSAfF_Cleanse = 0x040000, - CSAfF_SpellBlocks = 0x080000, + CSAfF_SpellBlocks = 0x040000, }; enum SpellPropertiesFlags { diff --git a/src/creature_states_prisn.c b/src/creature_states_prisn.c index dfadd51574..4f7bcbf311 100644 --- a/src/creature_states_prisn.c +++ b/src/creature_states_prisn.c @@ -126,8 +126,8 @@ short creature_arrived_at_prison(struct Thing *creatng) { clean_spell_effect(creatng, CSAfF_Invisibility); } - if (creature_under_spell_effect(creatng, CSAfF_Cleanse)) { - clean_spell_effect(creatng, CSAfF_Cleanse); + if (creature_under_spell_effect(creatng, CSAfF_SpellBlocks)) { + clean_spell_effect(creatng, CSAfF_SpellBlocks); } if (creatng->light_id != 0) { light_delete_light(creatng->light_id); diff --git a/src/thing_creature.c b/src/thing_creature.c index 5eedb8411d..b19a7a8233 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -1188,13 +1188,6 @@ TbBool set_thing_spell_flags_f(struct Thing *thing, SpellKind spell_idx, GameTur } affected = true; } - // CLEANSE. - if (flag_is_set(spconf->spell_flags, CSAfF_Cleanse) - && (!creature_is_immune_to_spell_effect(thing, CSAfF_Cleanse))) - { - process_cleanse_effect(thing); - affected = true; - } // Spell Blocks. if (flag_is_set(spconf->spell_flags, CSAfF_SpellBlocks) && (!creature_is_immune_to_spell_effect(thing, CSAfF_SpellBlocks))) @@ -1384,12 +1377,6 @@ TbBool clear_thing_spell_flags_f(struct Thing *thing, unsigned long spell_flags, // 'CSAfF_Heal' is never set but we still want to mark it cleared to free the spell slot. cleared = true; } - // CLEANSE. - if (flag_is_set(spell_flags, CSAfF_Cleanse)) - { - // 'CSAfF_Cleanse' is never set but we still want to mark it cleared to free the spell slot. - cleared = true; - } // Spell Blocks. if (flag_is_set(spell_flags, CSAfF_SpellBlocks) && (creature_under_spell_effect(thing, CSAfF_SpellBlocks))) @@ -1525,10 +1512,7 @@ void apply_spell_effect_to_thing(struct Thing *thing, SpellKind spell_idx, CrtrE if ((spconf->cleanse_flags > 0) && (any_flag_is_set(spconf->cleanse_flags, cctrl->spell_flags))) { - if (!creature_is_immune_to_spell_effect(thing, CSAfF_Cleanse)) - { - clean_spell_effect(thing, spconf->cleanse_flags); - } + clean_spell_effect(thing, spconf->cleanse_flags); if ((spconf->spell_flags == 0) && (!spell_is_continuous(spell_idx, duration))) { diff --git a/src/thing_effects.c b/src/thing_effects.c index 09ac5f55a3..ece76e2d13 100644 --- a/src/thing_effects.c +++ b/src/thing_effects.c @@ -1753,44 +1753,6 @@ void create_effects_line(TbMapLocation from, TbMapLocation to, char curvature, u fx_line->partial_steps = FX_LINE_TIME_PARTS; } -// Initial state from the side view of the sphere: -// 'r' is the radius of the circle -// The equation of the circle is x^2 + y^2 = r^2 -// Solving for x, we get x = sqrt(r^2 - y^2) -// As 'y' varies, we recompute 'x', which is the new radius for the lower and upper parts of the sphere -// The point of origin would be the center of the creature -// Starting at y = -r, then x = 0 (a single dot) -// In 3D space, 'y' corresponds to 'z', representing the height -void process_cleanse_effect(struct Thing* thing) { - struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - - int height = thing->clipbox_size_z + thing->floor_height + (5 * game.conf.crtr_conf.exp.size_increase_on_exp * cctrl->exp_level); - int z_min = thing->mappos.z.val; - int z_max = z_min + height; - int z_mid = (z_min + z_max) >> 1; - - int r_max = z_max - z_mid; - int r_max_s = r_max * r_max; - - struct Coord3d pos; - pos.z.val = z_min; - while (true) { - pos.z.val += 64; - if (pos.z.val >= z_max) { - break; - } - int y = pos.z.val - z_mid; - int r = LbSqrL(r_max_s - (y * y)); - for (int j = 0; j < 32; ++j) - { - int angle = j << 6; // 11.25 degrees - pos.x.val = thing->mappos.x.val + (r * LbSinL(angle) >> 16); - pos.y.val = thing->mappos.y.val + (r * LbCosL(angle) >> 16); - create_thing(&pos, TCls_EffectElem, TngEffElm_TinyFlash1, thing->owner, -1); - } - } -} - /******************************************************************************/ #ifdef __cplusplus } diff --git a/src/thing_effects.h b/src/thing_effects.h index 7ddbfc0e90..357bcd981e 100644 --- a/src/thing_effects.h +++ b/src/thing_effects.h @@ -281,7 +281,6 @@ TngUpdateRet update_effect_element(struct Thing *thing); TngUpdateRet update_effect(struct Thing *thing); TngUpdateRet process_effect_generator(struct Thing *thing); void process_spells_affected_by_effect_elements(struct Thing *thing); -void process_cleanse_effect(struct Thing* thing); TbBool destroy_effect_thing(struct Thing *thing); struct Thing *create_price_effect(const struct Coord3d *pos, long plyr_idx, long price); void process_fx_lines(); From ad60ec1972d44c7caff661f5e2053f699b08b363 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 13 Dec 2025 21:34:54 +0000 Subject: [PATCH 29/81] Purple stars effect --- config/fxdata/effects.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index 731cedd141..02ac294c51 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -5309,13 +5309,13 @@ DrawClass = 2 MoveType = 5 Unanimated = 0 Lifespan = [-1,-1] -AnimationId = 116 -SpriteSize = [96,150] +AnimationId = 907 +SpriteSize = [172,196] AnimateOnce = 0 SpriteSpeed = [256,256] AnimateOnFloor = true Unshaded = true -Transparent = 3 +Transparent = 0 ThroughWalls = 0 SizeChange = 0 FallAcceleration = 0 From 0ebae481a456f734c948c927f20504228d9aa885 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 13 Dec 2025 21:40:02 +0000 Subject: [PATCH 30/81] Update effects.toml --- config/fxdata/effects.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index 02ac294c51..163f91efa0 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -5315,7 +5315,7 @@ AnimateOnce = 0 SpriteSpeed = [256,256] AnimateOnFloor = true Unshaded = true -Transparent = 0 +Transparent = 1 ThroughWalls = 0 SizeChange = 0 FallAcceleration = 0 From 803e7e4ea24cbede871e31550331e5886cfa943f Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 13 Dec 2025 21:42:19 +0000 Subject: [PATCH 31/81] Update magic.cfg --- config/fxdata/magic.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index adb6b138ff..c5581ec196 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -367,7 +367,7 @@ ShotModel = NOSHOT SpellPower = NOPOWER SpellFlags = SPELL_BLOCKS AuraEffect = EFFECTELEMENT_CLEANSE -AuraDuration = 20 +AuraDuration = 10 CleanseFlags = SLOW DISEASE CHICKEN FREEZE FEAR Duration = 100 SelfCasted = 1 161 1 From 81ebe35c85a868d062a057abc0e065695651d4fb Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 13 Dec 2025 22:08:45 +0000 Subject: [PATCH 32/81] Update effects.toml --- config/fxdata/effects.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index 163f91efa0..bac76a4d0b 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -5310,7 +5310,7 @@ MoveType = 5 Unanimated = 0 Lifespan = [-1,-1] AnimationId = 907 -SpriteSize = [172,196] +SpriteSize = [96,150] AnimateOnce = 0 SpriteSpeed = [256,256] AnimateOnFloor = true From f23407708bd0d7b940de8e8a039b3cbe77ac19e6 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 3 Jan 2026 20:02:59 +0000 Subject: [PATCH 33/81] Blue sparkles --- config/fxdata/effects.toml | 8 ++++---- config/fxdata/magic.cfg | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index bac76a4d0b..83c26b902f 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -5306,16 +5306,16 @@ AffectedByWind = 1 [effectElement124] Name = "EFFECTELEMENT_CLEANSE" DrawClass = 2 -MoveType = 5 +MoveType = 2 Unanimated = 0 Lifespan = [-1,-1] -AnimationId = 907 +AnimationId = 119 SpriteSize = [96,150] AnimateOnce = 0 -SpriteSpeed = [256,256] +SpriteSpeed = [384,512] AnimateOnFloor = true Unshaded = true -Transparent = 1 +Transparent = 3 ThroughWalls = 0 SizeChange = 0 FallAcceleration = 0 diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index c5581ec196..8e8d21224c 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -367,6 +367,7 @@ ShotModel = NOSHOT SpellPower = NOPOWER SpellFlags = SPELL_BLOCKS AuraEffect = EFFECTELEMENT_CLEANSE +AuraFrequency = 0 AuraDuration = 10 CleanseFlags = SLOW DISEASE CHICKEN FREEZE FEAR Duration = 100 From 288a4b1035d0b8666375d1fcbd2dddbdc48e254c Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 11 Jan 2026 19:54:55 +0000 Subject: [PATCH 34/81] Update configs --- config/fxdata/effects.toml | 18 ++++++++++++++++++ config/fxdata/magic.cfg | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index 83c26b902f..eda36aed55 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -1514,6 +1514,24 @@ LightFlags = 1 ElementsCount = 3 AlwaysGenerate = 0 +[effect83] +Name = "EFFECT_CLEANSE" +Health = 8 +GenerationType = 1 +GenerationAccelXYRange = [16,16] +GenerationAccelZRange = [64,256] +GenerationKindRange = [124,124] +AreaAffectType = 0 +HitType = 0 +SpellEffect = 0 +Sound = 0 +AffectedByWind = 0 +LightRadius = 0 +LightIntensity = 0 +LightFlags = 0 +ElementsCount = 1 +AlwaysGenerate = 0 + # EffectGenerators. [effectGenerator0] diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 8e8d21224c..ed7bc991fe 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -366,12 +366,12 @@ CastAtThing = 0 ShotModel = NOSHOT SpellPower = NOPOWER SpellFlags = SPELL_BLOCKS -AuraEffect = EFFECTELEMENT_CLEANSE +AuraEffect = EFFECT_CLEANSE AuraFrequency = 0 AuraDuration = 10 CleanseFlags = SLOW DISEASE CHICKEN FREEZE FEAR Duration = 100 -SelfCasted = 1 161 1 +SelfCasted = 1 162 1 SymbolSprites = 796 798 ; Shots types. From a97b7c478f976c59ac1a9315a4076109500eaca0 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Tue, 3 Feb 2026 20:42:25 +0000 Subject: [PATCH 35/81] Use own validation function instead --- config/fxdata/creature.cfg | 5 ++-- src/config_creature.c | 1 - src/config_creature.h | 1 - src/creature_instances.c | 53 ++++++++++++++++++++++++++++++++++---- src/creature_instances.h | 1 + 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index a75ea886c6..965fb4e6fd 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -87,7 +87,6 @@ PostalPriority = 0 ; RANGED_BUFF can be applied to another friendly creature. ; NEEDS_TARGET Cannot be used in possession without a target to cast it on. ; DISARMING allows the instance to be used against traps. -; WHILE_FROZEN allows the instance to be used while the creature is frozen (under the Freeze spell). Properties = ; Function used as the instance action, and its parameters. Function = none 0 0 @@ -1128,10 +1127,10 @@ ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 Graphics = CASTSPELL -Properties = SELF_BUFF WHILE_FROZEN +Properties = SELF_BUFF PrimaryTarget = 3 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_even_in_prison 0 0 +ValidateSourceFunc = validate_source_even_while_frozen 0 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 [job0] diff --git a/src/config_creature.c b/src/config_creature.c index fd7f3e09d1..b0e41e3c6e 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -121,7 +121,6 @@ const struct NamedCommand creaturetype_instance_properties[] = { {"DISPLAY_SWIPE", InstPF_UsesSwipe}, {"RANGED_BUFF", InstPF_RangedBuff}, {"NEEDS_TARGET", InstPF_NeedsTarget}, - {"WHILE_FROZEN", InstPF_AllowWhileFrozen}, {NULL, 0}, }; diff --git a/src/config_creature.h b/src/config_creature.h index 2b67215ded..71280c4f3a 100644 --- a/src/config_creature.h +++ b/src/config_creature.h @@ -155,7 +155,6 @@ enum InstancePropertiesFlags { InstPF_UsesSwipe = 0x0200, InstPF_RangedBuff = 0x0400, InstPF_NeedsTarget = 0x0800, - InstPF_AllowWhileFrozen = 0x1000, }; enum CreatureDeathKind { diff --git a/src/creature_instances.c b/src/creature_instances.c index 87e5d6cc46..86594a51b9 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -127,6 +127,7 @@ const struct NamedCommand creature_instances_validate_func_type[] = { {"validate_target_non_idle", 11}, {"validate_target_takes_gas_damage", 12}, {"validate_target_requires_cleansing", 13}, + {"validate_source_even_while_frozen", 14}, {NULL, 0}, }; @@ -145,6 +146,7 @@ Creature_Validate_Func creature_instances_validate_func_list[] = { validate_target_non_idle, validate_target_takes_gas_damage, validate_target_requires_cleansing, + validate_source_even_while_frozen, NULL, }; @@ -1148,6 +1150,7 @@ TbBool validate_source_basic if (!creature_instance_is_available(source, inst_idx) || !creature_instance_has_reset(source, inst_idx) || + creature_under_spell_effect(source, CSAfF_Freeze) || creature_is_fleeing_combat(source) || creature_under_spell_effect(source, CSAfF_Chicken) || creature_is_being_unconscious(source) || creature_is_dying(source) || thing_is_picked_up(source) || creature_is_being_dropped(source) || @@ -1155,11 +1158,6 @@ TbBool validate_source_basic { return false; } - if (creature_under_spell_effect(source, CSAfF_Freeze)) - { - struct InstanceInfo* inst_inf = creature_instance_info_get(inst_idx); - return flag_is_set(inst_inf->instance_property_flags, InstPF_AllowWhileFrozen); - } return true; } @@ -1864,4 +1862,49 @@ TbBool validate_target_requires_cleansing return true; } +/** + * @brief Check if the given creature can cast spell when frozen. + * + * @param source The source creature + * @param target The target creature + * @param inst_idx The spell instance index + * @param param1 Optional 1st parameter. + * @param param2 Optional 2nd parameter. + * @return TbBool True if the creature can, false if otherwise. + */ +TbBool validate_source_even_while_frozen + ( + struct Thing *source, + struct Thing *target, + CrInstance inst_idx, + int32_t param1, + int32_t param2 + ) +{ + if ((source->alloc_flags & TAlF_IsControlled) != 0) + { + // If this creature is under player's control (Possession). + return false; + } + // We assume we usually don't want to overwrite the original instance. + struct CreatureControl* cctrl = creature_control_get_from_thing(source); + if (cctrl->instance_id != CrInst_NULL) { + SYNCDBG(15, "%s(%d) already has an instance %s.", thing_model_name(source), source->index, + creature_instance_code_name(cctrl->instance_id)); + return false; + } + + if (!creature_instance_is_available(source, inst_idx) || + !creature_instance_has_reset(source, inst_idx) || + creature_is_fleeing_combat(source) || creature_under_spell_effect(source, CSAfF_Chicken) || + creature_is_being_unconscious(source) || creature_is_dying(source) || + thing_is_picked_up(source) || creature_is_being_dropped(source) || + creature_is_being_sacrificed(source) || creature_is_being_summoned(source)) + { + return false; + } + + return true; +} + /******************************************************************************/ diff --git a/src/creature_instances.h b/src/creature_instances.h index 3181115013..43bbd84bc4 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -169,6 +169,7 @@ void script_set_creature_instance(ThingModel crmodel, short slot, int instance, TbBool validate_source_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_even_in_prison(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); +TbBool validate_source_even_while_frozen(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); From 93ab4f7f3e25eafdf8ebb9975ddca0bbb17c30e0 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Wed, 4 Feb 2026 01:00:10 +0100 Subject: [PATCH 36/81] Ranged Cleanse instance and shot --- config/fxdata/creature.cfg | 24 +++++++++++++++++++++++- config/fxdata/magic.cfg | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 965fb4e6fd..5f7b694029 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1128,11 +1128,33 @@ TooltipTextID = 1067 SymbolSprites = 798 Graphics = CASTSPELL Properties = SELF_BUFF -PrimaryTarget = 3 +PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_even_while_frozen 0 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 +[instance56] +Name = RANGED_CLEANSE +Time = 10 +ActionTime = 6 +ResetTime = 375 +FPTime = 5 +FPActionTime = 3 +FPResetTime = 300 +FPInstantCast = 0 +ForceVisibility = 30 +TooltipTextID = 1068 +SymbolSprites = 794 +Graphics = CASTSPELL +RangeMin = MIN +RangeMax = 3072 +Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET +PrimaryTarget = 6 +Function = creature_cast_spell SPELL_CLEANSE 0 +ValidateSourceFunc = validate_source_even_while_frozen 0 0 +ValidateTargetFunc = validate_target_requires_cleansing 32 0 +SearchTargetsFunc = search_target_generic 0 0 + [job0] ; Empty job, indicates no job assigned. Name = NULL diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index ed7bc991fe..def05937e7 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -362,8 +362,8 @@ SymbolSprites = 768 770 [spell32] ; Cures all negative effect and blocks them for a short duration. Name = SPELL_CLEANSE -CastAtThing = 0 -ShotModel = NOSHOT +CastAtThing = 1 +ShotModel = SHOT_RANGED_CLEANSE SpellPower = NOPOWER SpellFlags = SPELL_BLOCKS AuraEffect = EFFECT_CLEANSE @@ -1604,6 +1604,36 @@ FrozenEffect = EFFECT_HIT_FROZEN_UNIT Properties = CAN_COLLIDE NEVER_BLOCK WIND_IMMUNE UpdateLogic = SmokeWhenFired +[shot41] +Name = SHOT_RANGED_CLEANSE +Animation = 119 +AnimationSize = 50 +AnimationTransparency = 3 +Size_XY = 16 +Size_Z = 16 +Health = 30 +Damage = 0 +HitType = 11 +SpellEffect = SPELL_CLEANSE +Speed = 128 +BaseExperienceGain = 256 +DestroyOnHit = 1 +TargetHitstopTurns = 6 +FiringSound = 161 +ShotSound = 0 +ShotSoundPriority = 1 +VisualEffect = EFFECTELEMENT_CLEANSE +VisualEffectAmount = 1 +VisualEffectSpread = 1 +HitCreatureSound = 0 0 +HitWaterEffect = EFFECT_DRIP_1 +HitWaterSound = 21 1 +Properties = NAVIGABLE REBOUND_IMMUNE +FireLogic = 3 +EffectAmount = 4 +Spread_XY = 50 +Spread_Z = 50 + ; Powers types. [power0] From 4e048ef28d586bdd54334887ad424a1f0b409e90 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:46:55 +0000 Subject: [PATCH 37/81] Instead use param1 in validate_source_generic --- config/fxdata/creature.cfg | 4 ++-- src/creature_instances.c | 49 +------------------------------------- src/creature_instances.h | 1 - 3 files changed, 3 insertions(+), 51 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 5f7b694029..e57a37810f 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1130,7 +1130,7 @@ Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_even_while_frozen 0 0 +ValidateSourceFunc = validate_source_even_in_prison 1 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 [instance56] @@ -1151,7 +1151,7 @@ RangeMax = 3072 Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_even_while_frozen 0 0 +ValidateSourceFunc = validate_source_generic 0 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 SearchTargetsFunc = search_target_generic 0 0 diff --git a/src/creature_instances.c b/src/creature_instances.c index 86594a51b9..f340ba0e25 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -127,7 +127,6 @@ const struct NamedCommand creature_instances_validate_func_type[] = { {"validate_target_non_idle", 11}, {"validate_target_takes_gas_damage", 12}, {"validate_target_requires_cleansing", 13}, - {"validate_source_even_while_frozen", 14}, {NULL, 0}, }; @@ -146,7 +145,6 @@ Creature_Validate_Func creature_instances_validate_func_list[] = { validate_target_non_idle, validate_target_takes_gas_damage, validate_target_requires_cleansing, - validate_source_even_while_frozen, NULL, }; @@ -1150,7 +1148,7 @@ TbBool validate_source_basic if (!creature_instance_is_available(source, inst_idx) || !creature_instance_has_reset(source, inst_idx) || - creature_under_spell_effect(source, CSAfF_Freeze) || + (creature_under_spell_effect(source, CSAfF_Freeze) && (param1 == 0)) || creature_is_fleeing_combat(source) || creature_under_spell_effect(source, CSAfF_Chicken) || creature_is_being_unconscious(source) || creature_is_dying(source) || thing_is_picked_up(source) || creature_is_being_dropped(source) || @@ -1862,49 +1860,4 @@ TbBool validate_target_requires_cleansing return true; } -/** - * @brief Check if the given creature can cast spell when frozen. - * - * @param source The source creature - * @param target The target creature - * @param inst_idx The spell instance index - * @param param1 Optional 1st parameter. - * @param param2 Optional 2nd parameter. - * @return TbBool True if the creature can, false if otherwise. - */ -TbBool validate_source_even_while_frozen - ( - struct Thing *source, - struct Thing *target, - CrInstance inst_idx, - int32_t param1, - int32_t param2 - ) -{ - if ((source->alloc_flags & TAlF_IsControlled) != 0) - { - // If this creature is under player's control (Possession). - return false; - } - // We assume we usually don't want to overwrite the original instance. - struct CreatureControl* cctrl = creature_control_get_from_thing(source); - if (cctrl->instance_id != CrInst_NULL) { - SYNCDBG(15, "%s(%d) already has an instance %s.", thing_model_name(source), source->index, - creature_instance_code_name(cctrl->instance_id)); - return false; - } - - if (!creature_instance_is_available(source, inst_idx) || - !creature_instance_has_reset(source, inst_idx) || - creature_is_fleeing_combat(source) || creature_under_spell_effect(source, CSAfF_Chicken) || - creature_is_being_unconscious(source) || creature_is_dying(source) || - thing_is_picked_up(source) || creature_is_being_dropped(source) || - creature_is_being_sacrificed(source) || creature_is_being_summoned(source)) - { - return false; - } - - return true; -} - /******************************************************************************/ diff --git a/src/creature_instances.h b/src/creature_instances.h index 43bbd84bc4..3181115013 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -169,7 +169,6 @@ void script_set_creature_instance(ThingModel crmodel, short slot, int instance, TbBool validate_source_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_even_in_prison(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); -TbBool validate_source_even_while_frozen(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); From 8bd93ae1b5fb106b18d91ddfadc3ea38b8dbcd32 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:14:06 +0000 Subject: [PATCH 38/81] No casting animation for frozen creatures --- src/creature_graphics.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/creature_graphics.c b/src/creature_graphics.c index 239e6d717e..ec4b485890 100644 --- a/src/creature_graphics.c +++ b/src/creature_graphics.c @@ -466,8 +466,11 @@ void update_creature_graphic_anim(struct Thing *thing) { thing->rendering_flags &= ~(TRF_Transpar_Flags); } - struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); - update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); + if (!creature_under_spell_effect(thing, CSAfF_Freeze)) + { + struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); + update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); + } } else if ((cctrl->frozen_on_hit != 0) || creature_is_dying(thing) || creature_under_spell_effect(thing, CSAfF_Freeze)) { From 3caf84e7c6dece5943f1292fee4787e1f9d1b11f Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Thu, 5 Feb 2026 18:23:01 +0000 Subject: [PATCH 39/81] Is this better? --- config/fxdata/creature.cfg | 4 ++-- src/creature_instances.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index e57a37810f..390113e048 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1131,7 +1131,7 @@ Properties = SELF_BUFF PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_even_in_prison 1 0 -ValidateTargetFunc = validate_target_requires_cleansing 32 0 +ValidateTargetFunc = validate_target_requires_cleansing 1 32 [instance56] Name = RANGED_CLEANSE @@ -1152,7 +1152,7 @@ Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_generic 0 0 -ValidateTargetFunc = validate_target_requires_cleansing 32 0 +ValidateTargetFunc = validate_target_requires_cleansing 1 32 SearchTargetsFunc = search_target_generic 0 0 [job0] diff --git a/src/creature_instances.c b/src/creature_instances.c index f340ba0e25..334232ba9e 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1837,7 +1837,7 @@ TbBool validate_target_requires_cleansing ) { if (!validate_target_basic(source, target, inst_idx, param1, param2) || creature_is_being_unconscious(target) || - !creature_requires_cleansing(target, param1)) + !creature_requires_cleansing(target, param2)) { return false; } From ba4c08b9303b94c7e64c7194093998838fc8cc48 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Thu, 5 Feb 2026 18:31:06 +0000 Subject: [PATCH 40/81] No cleansing others when frozen --- src/creature_instances.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index 334232ba9e..b3f4c34d93 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1844,14 +1844,14 @@ TbBool validate_target_requires_cleansing if (source->index == target->index) { - // Special case. The creature is always allowed to cleanse itself even if - // it's being tortured or imprisoned. + // Special case. The creature is always allowed to cleanse itself. return true; } else { if (creature_is_being_tortured(target) || creature_is_kept_in_prison(target) || - creature_is_being_tortured(source) || creature_is_kept_in_prison(source)) + creature_is_being_tortured(source) || creature_is_kept_in_prison(source) || + creature_under_spell_effect(source, CSAfF_Freeze)) // not allowed to cleanse others (only itself) even if param1 is set { return false; } From bd5d4ee416782aa5458762c4482596e99dae6b6a Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Thu, 5 Feb 2026 18:38:28 +0000 Subject: [PATCH 41/81] Revert "Is this better?" This reverts commit 3caf84e7c6dece5943f1292fee4787e1f9d1b11f. --- config/fxdata/creature.cfg | 4 ++-- src/creature_instances.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 390113e048..e57a37810f 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1131,7 +1131,7 @@ Properties = SELF_BUFF PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_even_in_prison 1 0 -ValidateTargetFunc = validate_target_requires_cleansing 1 32 +ValidateTargetFunc = validate_target_requires_cleansing 32 0 [instance56] Name = RANGED_CLEANSE @@ -1152,7 +1152,7 @@ Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 ValidateSourceFunc = validate_source_generic 0 0 -ValidateTargetFunc = validate_target_requires_cleansing 1 32 +ValidateTargetFunc = validate_target_requires_cleansing 32 0 SearchTargetsFunc = search_target_generic 0 0 [job0] diff --git a/src/creature_instances.c b/src/creature_instances.c index b3f4c34d93..2a19dd5ff7 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1837,7 +1837,7 @@ TbBool validate_target_requires_cleansing ) { if (!validate_target_basic(source, target, inst_idx, param1, param2) || creature_is_being_unconscious(target) || - !creature_requires_cleansing(target, param2)) + !creature_requires_cleansing(target, param1)) { return false; } From 105a3eaf75702282d64792a0342428b4babdf783 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Thu, 5 Feb 2026 18:41:31 +0000 Subject: [PATCH 42/81] Update comment --- src/creature_instances.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index 2a19dd5ff7..70b0d71546 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1851,7 +1851,7 @@ TbBool validate_target_requires_cleansing { if (creature_is_being_tortured(target) || creature_is_kept_in_prison(target) || creature_is_being_tortured(source) || creature_is_kept_in_prison(source) || - creature_under_spell_effect(source, CSAfF_Freeze)) // not allowed to cleanse others (only itself) even if param1 is set + creature_under_spell_effect(source, CSAfF_Freeze)) // not allowed to cleanse others (only itself) even if source param1 is set { return false; } From c79cf9ccb74d8ae654437e35b9a511bbd9dda71e Mon Sep 17 00:00:00 2001 From: Loobinex Date: Fri, 6 Feb 2026 02:43:28 +0100 Subject: [PATCH 43/81] Be able to self-cleanse in possession --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index e57a37810f..395f1a7115 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1141,7 +1141,7 @@ ResetTime = 375 FPTime = 5 FPActionTime = 3 FPResetTime = 300 -FPInstantCast = 0 +FPInstantCast = 1 ForceVisibility = 30 TooltipTextID = 1068 SymbolSprites = 794 From 62b5237e2511ffc52cbbfe01e38e22e596920cee Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 04:00:45 +0000 Subject: [PATCH 44/81] Allow non-instant-cast self-cleansing while frozen in possession --- config/fxdata/creature.cfg | 60 ++++++++++- src/config_creature.c | 14 +++ src/creature_instances.h | 1 + src/frontmenu_ingame_tabs.c | 2 +- src/local_camera.c | 2 +- src/packets.c | 194 ++++++++++++++++++++---------------- src/packets.h | 2 +- 7 files changed, 183 insertions(+), 92 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 395f1a7115..9d7b6faad3 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -50,6 +50,8 @@ FPActionTime = 0 FPResetTime = 0 ; Instance is activated as soon as it's selected. FPInstantCast = 0 +; Instance can be used when frozen in possession. +FPAllowWhileFrozen = 0 ; How many game turns after using the instance creature can be spotted even if invisible. ForceVisibility = 0 ; Tooltip string ID, explaining what the instance does. @@ -124,6 +126,7 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 252 SymbolSprites = 450 @@ -143,6 +146,7 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 252 SymbolSprites = 400 @@ -161,6 +165,7 @@ ResetTime = 0 FPTime = 0 FPActionTime = 0 FPResetTime = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -178,6 +183,7 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 8 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 226 SymbolSprites = 454 @@ -198,6 +204,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 150 TooltipTextID = 251 SymbolSprites = 402 @@ -218,6 +225,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 16 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 150 TooltipTextID = 250 SymbolSprites = 404 @@ -237,6 +245,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 150 TooltipTextID = 227 SymbolSprites = 406 @@ -256,6 +265,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -275,6 +285,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 8 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 150 TooltipTextID = 229 SymbolSprites = 410 @@ -295,6 +306,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -314,6 +326,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -333,6 +346,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 20 TooltipTextID = 237 SymbolSprites = 416 @@ -353,6 +367,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -372,6 +387,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -389,6 +405,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -408,6 +425,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 600 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 245 SymbolSprites = 424 @@ -427,6 +445,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 246 SymbolSprites = 513 @@ -446,6 +465,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 450 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 20 TooltipTextID = 231 SymbolSprites = 819 @@ -465,6 +485,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 233 SymbolSprites = 426 @@ -485,6 +506,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 5 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 150 TooltipTextID = 235 SymbolSprites = 428 @@ -505,6 +527,7 @@ FPTime = 3 FPActionTime = 3 FPResetTime = 1 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 241 SymbolSprites = 430 @@ -524,6 +547,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 800 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 30 TooltipTextID = 249 SymbolSprites = 432 @@ -544,6 +568,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -561,6 +586,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -580,6 +606,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -599,6 +626,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 100 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 80 TooltipTextID = 234 SymbolSprites = 440 @@ -617,6 +645,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 80 TooltipTextID = 244 SymbolSprites = 442 @@ -637,6 +666,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 247 SymbolSprites = 444 @@ -656,6 +686,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 100 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 253 SymbolSprites = 446 @@ -675,6 +706,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 40 TooltipTextID = 254 SymbolSprites = 448 @@ -691,6 +723,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -707,6 +740,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -723,6 +757,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -739,6 +774,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 1 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -754,6 +790,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -770,6 +807,7 @@ ResetTime = 1 FPTime = 8 FPActionTime = 4 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -787,6 +825,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 201 SymbolSprites = 0 @@ -803,6 +842,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 201 SymbolSprites = 0 @@ -820,6 +860,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 3 TooltipTextID = 254 SymbolSprites = 448 @@ -837,6 +878,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 80 TooltipTextID = 234 SymbolSprites = 440 @@ -857,6 +899,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 20 TooltipTextID = 255 SymbolSprites = 319 @@ -876,6 +919,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 20 TooltipTextID = 256 SymbolSprites = 314 @@ -895,6 +939,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 257 SymbolSprites = 548 @@ -913,6 +958,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 1 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -929,6 +975,7 @@ ResetTime = 1 FPTime = 8 FPActionTime = 4 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -945,6 +992,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -961,6 +1009,7 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 +FPAllowWhileFrozen = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -978,6 +1027,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -997,6 +1047,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1016,6 +1067,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 1066 SymbolSprites = 786 @@ -1038,6 +1090,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 654 SymbolSprites = 792 @@ -1060,6 +1113,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 655 SymbolSprites = 780 @@ -1082,6 +1136,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 10 TooltipTextID = 1069 SymbolSprites = 788 @@ -1104,6 +1159,7 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 160 FPInstantCast = 0 +FPAllowWhileFrozen = 0 ForceVisibility = 100 TooltipTextID = 245 SymbolSprites = 827 @@ -1123,6 +1179,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 @@ -1141,7 +1198,8 @@ ResetTime = 375 FPTime = 5 FPActionTime = 3 FPResetTime = 300 -FPInstantCast = 1 +FPInstantCast = 0 +FPAllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1068 SymbolSprites = 794 diff --git a/src/config_creature.c b/src/config_creature.c index b0e41e3c6e..41da285c8f 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -106,6 +106,7 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"SearchTargetsFunc", 20}, {"PostalPriority", 21}, {"NoAnimationLoop", 22}, + {"FPAllowWhileFrozen", 23}, {NULL, 0}, }; @@ -1406,6 +1407,19 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; + case 23: // FPALLOWWHILEFROZEN + if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) + { + k = atoi(word_buf); + inst_inf->fp_allow_while_frozen = (TbBool)k; + n++; + } + if (n < 1) + { + CONFWRNLOG("Couldn't read \"%s\" parameter in [%.*s] block of %s file.", + COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); + } + break; case ccr_comment: break; case ccr_endOfFile: diff --git a/src/creature_instances.h b/src/creature_instances.h index 3181115013..c131db1c37 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -126,6 +126,7 @@ struct InstanceInfo { // Refer to creature_instances_search_targets_func_list uint8_t search_func; int32_t search_func_params[2]; + TbBool fp_allow_while_frozen; }; /******************************************************************************/ diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index 4be8590477..f992370437 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1873,7 +1873,7 @@ void gui_area_instance_button(struct GuiButton *gbtn) LbTextDrawResized(gbtn->scr_pos_x + 52*units_per_px/16, gbtn->scr_pos_y + 9*units_per_px/16, tx_units_per_px, text); spr_idx = gbtn->sprite_idx; // Show disabled icon if instance is on cooldown or creature is frozen. - if ((!creature_instance_has_reset(ctrltng, curbtn_inst_id)) || (creature_under_spell_effect(ctrltng, CSAfF_Freeze) && (!inst_inf->instant))) + if ((!creature_instance_has_reset(ctrltng, curbtn_inst_id)) || (creature_under_spell_effect(ctrltng, CSAfF_Freeze) && (!inst_inf->fp_allow_while_frozen))) { spr_idx++; } diff --git a/src/local_camera.c b/src/local_camera.c index f2eabb3f6f..8031d24696 100644 --- a/src/local_camera.c +++ b/src/local_camera.c @@ -166,7 +166,7 @@ void update_local_first_person_camera(struct Thing *ctrltng) int eye_height = get_creature_eye_height(ctrltng); update_first_person_position(cam, ctrltng, eye_height); - if (!can_process_creature_input(ctrltng)) { + if (!can_process_creature_input(ctrltng, true)) { return; } long current_horizontal = destination_local_cameras[CamIV_FirstPerson].rotation_angle_x; diff --git a/src/packets.c b/src/packets.c index fec82dfca2..e503f86af8 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1301,7 +1301,7 @@ void process_first_person_look(struct Thing *thing, struct Packet *pckt, long cu *out_roll = 170 * horizontalTurnSpeed / maxTurnSpeed; } -TbBool can_process_creature_input(struct Thing *thing) +TbBool can_process_creature_input(struct Thing *thing, TbBool stateblock_flags) { if (thing->class_id != TCls_Creature) { return false; @@ -1309,122 +1309,128 @@ TbBool can_process_creature_input(struct Thing *thing) if (creature_is_dying(thing)) { return false; } - struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - if ((cctrl->stateblock_flags != 0) || (thing->active_state == CrSt_CreatureUnconscious)) { - return false; + if (stateblock_flags) + { + struct CreatureControl* cctrl = creature_control_get_from_thing(thing); + return ((cctrl->stateblock_flags == 0) && (thing->active_state != CrSt_CreatureUnconscious)); + } + else + { + return (thing->active_state != CrSt_CreatureUnconscious); } - return true; } void process_players_creature_control_packet_control(long idx) { - struct InstanceInfo *inst_inf; - long i; - SYNCDBG(6,"Starting"); struct PlayerInfo* player = get_player(idx); - struct Packet* pckt = get_packet_direct(player->packet_num); struct Thing* cctng = thing_get(player->controlled_thing_idx); - if (!can_process_creature_input(cctng)) + if (!can_process_creature_input(cctng, false)) return; + struct InstanceInfo *inst_inf; + long i; + struct Packet* pckt = get_packet_direct(player->packet_num); struct CreatureControl* ccctrl = creature_control_get_from_thing(cctng); long speed_limit = get_creature_speed(cctng); - if ((pckt->control_flags & PCtr_MoveUp) != 0) + if (ccctrl->stateblock_flags == 0) { - if (!creature_control_invalid(ccctrl)) + if ((pckt->control_flags & PCtr_MoveUp) != 0) { - ccctrl->move_speed = compute_controlled_speed_increase(ccctrl->move_speed, speed_limit); - ccctrl->creature_control_flags |= CCFlg_MoveY; - } else - { - ERRORLOG("No creature to increase speed"); - } - } - if ((pckt->control_flags & PCtr_MoveDown) != 0) - { - if (!creature_control_invalid(ccctrl)) - { - ccctrl->move_speed = compute_controlled_speed_decrease(ccctrl->move_speed, speed_limit); - ccctrl->creature_control_flags |= CCFlg_MoveY; - } else - { - ERRORLOG("No creature to decrease speed"); + if (!creature_control_invalid(ccctrl)) + { + ccctrl->move_speed = compute_controlled_speed_increase(ccctrl->move_speed, speed_limit); + ccctrl->creature_control_flags |= CCFlg_MoveY; + } else + { + ERRORLOG("No creature to increase speed"); + } } - } - if ((pckt->control_flags & PCtr_MoveLeft) != 0) - { - if (!creature_control_invalid(ccctrl)) - { - ccctrl->orthogn_speed = compute_controlled_speed_increase(ccctrl->orthogn_speed, speed_limit); - ccctrl->creature_control_flags |= CCFlg_MoveX; - } else + if ((pckt->control_flags & PCtr_MoveDown) != 0) { - ERRORLOG("No creature to increase speed"); + if (!creature_control_invalid(ccctrl)) + { + ccctrl->move_speed = compute_controlled_speed_decrease(ccctrl->move_speed, speed_limit); + ccctrl->creature_control_flags |= CCFlg_MoveY; + } else + { + ERRORLOG("No creature to decrease speed"); + } } - } - if ((pckt->control_flags & PCtr_MoveRight) != 0) - { - if (!creature_control_invalid(ccctrl)) + if ((pckt->control_flags & PCtr_MoveLeft) != 0) { - ccctrl->orthogn_speed = compute_controlled_speed_decrease(ccctrl->orthogn_speed, speed_limit); - ccctrl->creature_control_flags |= CCFlg_MoveX; - } else - { - ERRORLOG("No creature to decrease speed"); + if (!creature_control_invalid(ccctrl)) + { + ccctrl->orthogn_speed = compute_controlled_speed_increase(ccctrl->orthogn_speed, speed_limit); + ccctrl->creature_control_flags |= CCFlg_MoveX; + } else + { + ERRORLOG("No creature to increase speed"); + } } - } - if (flag_is_set(cctng->movement_flags, TMvF_Flying)) - { - MapCoord floor_height, ceiling_height; - if ((pckt->control_flags & PCtr_Ascend) != 0) + if ((pckt->control_flags & PCtr_MoveRight) != 0) { if (!creature_control_invalid(ccctrl)) { - ccctrl->vertical_speed = compute_controlled_speed_increase(ccctrl->vertical_speed, speed_limit); - ccctrl->creature_control_flags |= CCFlg_MoveZ; - if (ccctrl->vertical_speed != 0) - { - get_floor_and_ceiling_height_under_thing_at(cctng, &cctng->mappos, &floor_height, &ceiling_height); - if ( (cctng->mappos.z.val >= floor_height) && (cctng->mappos.z.val <= ceiling_height) ) - { - ccctrl->moveaccel.z.val = distance_with_angle_to_coord_z(ccctrl->vertical_speed, 227); - } - else - { - ccctrl->moveaccel.z.val = 0; - } - } + ccctrl->orthogn_speed = compute_controlled_speed_decrease(ccctrl->orthogn_speed, speed_limit); + ccctrl->creature_control_flags |= CCFlg_MoveX; } else { - ERRORLOG("No creature to ascend"); + ERRORLOG("No creature to decrease speed"); } } - if ((pckt->control_flags & PCtr_Descend) != 0) + if (flag_is_set(cctng->movement_flags, TMvF_Flying)) { - if (!creature_control_invalid(ccctrl)) + MapCoord floor_height, ceiling_height; + if ((pckt->control_flags & PCtr_Ascend) != 0) { - // We want increase here, not decrease, because we don't want it angle-dependent - ccctrl->vertical_speed = compute_controlled_speed_increase(ccctrl->vertical_speed, speed_limit); - ccctrl->creature_control_flags |= CCFlg_MoveZ; - if (ccctrl->vertical_speed != 0) + if (!creature_control_invalid(ccctrl)) { - get_floor_and_ceiling_height_under_thing_at(cctng, &cctng->mappos, &floor_height, &ceiling_height); - if ( (cctng->mappos.z.val >= floor_height) && (cctng->mappos.z.val <= ceiling_height) ) + ccctrl->vertical_speed = compute_controlled_speed_increase(ccctrl->vertical_speed, speed_limit); + ccctrl->creature_control_flags |= CCFlg_MoveZ; + if (ccctrl->vertical_speed != 0) { - ccctrl->moveaccel.z.val = distance_with_angle_to_coord_z(ccctrl->vertical_speed, 1820); + get_floor_and_ceiling_height_under_thing_at(cctng, &cctng->mappos, &floor_height, &ceiling_height); + if ( (cctng->mappos.z.val >= floor_height) && (cctng->mappos.z.val <= ceiling_height) ) + { + ccctrl->moveaccel.z.val = distance_with_angle_to_coord_z(ccctrl->vertical_speed, 227); + } + else + { + ccctrl->moveaccel.z.val = 0; + } } - else + } else + { + ERRORLOG("No creature to ascend"); + } + } + if ((pckt->control_flags & PCtr_Descend) != 0) + { + if (!creature_control_invalid(ccctrl)) + { + // We want increase here, not decrease, because we don't want it angle-dependent + ccctrl->vertical_speed = compute_controlled_speed_increase(ccctrl->vertical_speed, speed_limit); + ccctrl->creature_control_flags |= CCFlg_MoveZ; + if (ccctrl->vertical_speed != 0) { - ccctrl->moveaccel.z.val = 0; + get_floor_and_ceiling_height_under_thing_at(cctng, &cctng->mappos, &floor_height, &ceiling_height); + if ( (cctng->mappos.z.val >= floor_height) && (cctng->mappos.z.val <= ceiling_height) ) + { + ccctrl->moveaccel.z.val = distance_with_angle_to_coord_z(ccctrl->vertical_speed, 1820); + } + else + { + ccctrl->moveaccel.z.val = 0; + } } + } else + { + ERRORLOG("No creature to descend"); } - } else - { - ERRORLOG("No creature to descend"); } } } - + TbBool allowed; if ((pckt->control_flags & PCtr_LBtnRelease) != 0) { i = ccctrl->active_instance_id; @@ -1437,7 +1443,11 @@ void process_players_creature_control_packet_control(long idx) if (!creature_under_spell_effect(cctng, CSAfF_Chicken)) { inst_inf = creature_instance_info_get(i); - process_player_use_instance(cctng, i, pckt); + allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (allowed) + { + process_player_use_instance(cctng, i, pckt); + } } } } @@ -1462,7 +1472,11 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - process_player_use_instance(cctng, i, pckt); + allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (allowed) + { + process_player_use_instance(cctng, i, pckt); + } } } else @@ -1523,11 +1537,15 @@ void process_players_creature_control_packet_action(long plyr_idx) { if (creature_instance_is_available(thing,i) && creature_instance_has_reset(thing, pckt->actn_par1)) { - i = pckt->actn_par1; - process_player_use_instance(thing, i, pckt); - if (plyr_idx == my_player_number) { - instant_instance_selected(i); - } + TbBool allowed = (creature_under_spell_effect(thing, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (allowed) + { + i = pckt->actn_par1; + process_player_use_instance(thing, i, pckt); + if (plyr_idx == my_player_number) { + instant_instance_selected(i); + } + } } } break; diff --git a/src/packets.h b/src/packets.h index ef2ef2b5ff..a7843333c8 100644 --- a/src/packets.h +++ b/src/packets.h @@ -338,7 +338,7 @@ void process_chat_message_end(int player_id, const char *message); TbBool try_starting_level_from_chat(char* message, long player_id); void process_camera_controls(struct Camera* cam, struct Packet* pckt, struct PlayerInfo* player, TbBool is_local_camera); void process_first_person_look(struct Thing *thing, struct Packet *pckt, long current_horizontal, long current_vertical, long *out_horizontal, long *out_vertical, long *out_roll); -TbBool can_process_creature_input(struct Thing *thing); +TbBool can_process_creature_input(struct Thing *thing, TbBool stateblock_flags); void process_packets(void); void set_local_packet_turn(void); void clear_packets(void); From 754683de97f34f75c926e35e9e6214c4ff545368 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 04:23:30 +0000 Subject: [PATCH 45/81] Fixed accidentally-reintroduced first-person camera/movement bug --- src/packets.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/packets.c b/src/packets.c index e503f86af8..a12c55ba71 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1429,6 +1429,11 @@ void process_players_creature_control_packet_control(long idx) } } } + long new_horizontal, new_vertical, new_roll; + process_first_person_look(cctng, pckt, cctng->move_angle_xy, cctng->move_angle_z, &new_horizontal, &new_vertical, &new_roll); + cctng->move_angle_xy = new_horizontal; + cctng->move_angle_z = new_vertical; + ccctrl->roll = new_roll; } TbBool allowed; if ((pckt->control_flags & PCtr_LBtnRelease) != 0) @@ -1487,12 +1492,6 @@ void process_players_creature_control_packet_control(long idx) } } } - - long new_horizontal, new_vertical, new_roll; - process_first_person_look(cctng, pckt, cctng->move_angle_xy, cctng->move_angle_z, &new_horizontal, &new_vertical, &new_roll); - cctng->move_angle_xy = new_horizontal; - cctng->move_angle_z = new_vertical; - ccctrl->roll = new_roll; } void process_players_creature_control_packet_action(long plyr_idx) From 73b03d5a9517970a941981882ff8027c03085460 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 04:45:32 +0000 Subject: [PATCH 46/81] Perhaps this is better? --- src/local_camera.c | 2 +- src/packets.c | 97 ++++++++++++++++++++++------------------------ src/packets.h | 2 +- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/local_camera.c b/src/local_camera.c index 8031d24696..f2eabb3f6f 100644 --- a/src/local_camera.c +++ b/src/local_camera.c @@ -166,7 +166,7 @@ void update_local_first_person_camera(struct Thing *ctrltng) int eye_height = get_creature_eye_height(ctrltng); update_first_person_position(cam, ctrltng, eye_height); - if (!can_process_creature_input(ctrltng, true)) { + if (!can_process_creature_input(ctrltng)) { return; } long current_horizontal = destination_local_cameras[CamIV_FirstPerson].rotation_angle_x; diff --git a/src/packets.c b/src/packets.c index a12c55ba71..b3691cd482 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1301,7 +1301,7 @@ void process_first_person_look(struct Thing *thing, struct Packet *pckt, long cu *out_roll = 170 * horizontalTurnSpeed / maxTurnSpeed; } -TbBool can_process_creature_input(struct Thing *thing, TbBool stateblock_flags) +TbBool can_process_creature_input(struct Thing *thing) { if (thing->class_id != TCls_Creature) { return false; @@ -1309,31 +1309,25 @@ TbBool can_process_creature_input(struct Thing *thing, TbBool stateblock_flags) if (creature_is_dying(thing)) { return false; } - if (stateblock_flags) - { - struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - return ((cctrl->stateblock_flags == 0) && (thing->active_state != CrSt_CreatureUnconscious)); - } - else - { - return (thing->active_state != CrSt_CreatureUnconscious); + struct CreatureControl* cctrl = creature_control_get_from_thing(thing); + if ((cctrl->stateblock_flags != 0) || (thing->active_state == CrSt_CreatureUnconscious)) { + return false; } + return true; } void process_players_creature_control_packet_control(long idx) { SYNCDBG(6,"Starting"); - struct PlayerInfo* player = get_player(idx); - struct Thing* cctng = thing_get(player->controlled_thing_idx); - if (!can_process_creature_input(cctng, false)) - return; struct InstanceInfo *inst_inf; long i; + struct PlayerInfo* player = get_player(idx); + struct Thing* cctng = thing_get(player->controlled_thing_idx); struct Packet* pckt = get_packet_direct(player->packet_num); struct CreatureControl* ccctrl = creature_control_get_from_thing(cctng); - long speed_limit = get_creature_speed(cctng); - if (ccctrl->stateblock_flags == 0) + if (can_process_creature_input(cctng)) { + long speed_limit = get_creature_speed(cctng); if ((pckt->control_flags & PCtr_MoveUp) != 0) { if (!creature_control_invalid(ccctrl)) @@ -1435,59 +1429,62 @@ void process_players_creature_control_packet_control(long idx) cctng->move_angle_z = new_vertical; ccctrl->roll = new_roll; } - TbBool allowed; - if ((pckt->control_flags & PCtr_LBtnRelease) != 0) + if ((!creature_is_dying(cctng)) && (cctng->active_state != CrSt_CreatureUnconscious)) { - i = ccctrl->active_instance_id; - if (ccctrl->instance_id == CrInst_NULL) + TbBool allowed; + if ((pckt->control_flags & PCtr_LBtnRelease) != 0) { - if (creature_instance_is_available(cctng, i)) + i = ccctrl->active_instance_id; + if (ccctrl->instance_id == CrInst_NULL) { - if (creature_instance_has_reset(cctng, i)) + if (creature_instance_is_available(cctng, i)) { - if (!creature_under_spell_effect(cctng, CSAfF_Chicken)) + if (creature_instance_has_reset(cctng, i)) { - inst_inf = creature_instance_info_get(i); - allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; - if (allowed) + if (!creature_under_spell_effect(cctng, CSAfF_Chicken)) { - process_player_use_instance(cctng, i, pckt); + inst_inf = creature_instance_info_get(i); + allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (allowed) + { + process_player_use_instance(cctng, i, pckt); + } } } } - } - else - { - // cheat mode - inst_inf = creature_instance_info_get(i); - process_player_use_instance(cctng, i, pckt); + else + { + // cheat mode + inst_inf = creature_instance_info_get(i); + process_player_use_instance(cctng, i, pckt); + } } } - } - if ((pckt->control_flags & PCtr_LBtnHeld) != 0) - { - // Button is held down - check whether the instance has auto-repeat - i = ccctrl->active_instance_id; - inst_inf = creature_instance_info_get(i); - if ((inst_inf->instance_property_flags & InstPF_RepeatTrigger) != 0) + if ((pckt->control_flags & PCtr_LBtnHeld) != 0) { - if (ccctrl->instance_id == CrInst_NULL) + // Button is held down - check whether the instance has auto-repeat + i = ccctrl->active_instance_id; + inst_inf = creature_instance_info_get(i); + if ((inst_inf->instance_property_flags & InstPF_RepeatTrigger) != 0) { - if (creature_instance_is_available(cctng, i)) + if (ccctrl->instance_id == CrInst_NULL) { - if (creature_instance_has_reset(cctng, i)) + if (creature_instance_is_available(cctng, i)) { - allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; - if (allowed) + if (creature_instance_has_reset(cctng, i)) { - process_player_use_instance(cctng, i, pckt); + allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (allowed) + { + process_player_use_instance(cctng, i, pckt); + } } } - } - else - { - // cheat mode - process_player_use_instance(cctng, i, pckt); + else + { + // cheat mode + process_player_use_instance(cctng, i, pckt); + } } } } diff --git a/src/packets.h b/src/packets.h index a7843333c8..ef2ef2b5ff 100644 --- a/src/packets.h +++ b/src/packets.h @@ -338,7 +338,7 @@ void process_chat_message_end(int player_id, const char *message); TbBool try_starting_level_from_chat(char* message, long player_id); void process_camera_controls(struct Camera* cam, struct Packet* pckt, struct PlayerInfo* player, TbBool is_local_camera); void process_first_person_look(struct Thing *thing, struct Packet *pckt, long current_horizontal, long current_vertical, long *out_horizontal, long *out_vertical, long *out_roll); -TbBool can_process_creature_input(struct Thing *thing, TbBool stateblock_flags); +TbBool can_process_creature_input(struct Thing *thing); void process_packets(void); void set_local_packet_turn(void); void clear_packets(void); From 4ba4f6a45edbc2d88956c439f39019d3805914b5 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:12:12 +0000 Subject: [PATCH 47/81] creature.chicken console command For easy testing --- src/console_cmd.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/console_cmd.c b/src/console_cmd.c index bfd1541d24..e244170ee1 100644 --- a/src/console_cmd.c +++ b/src/console_cmd.c @@ -2182,6 +2182,25 @@ TbBool cmd_cheat_menu(PlayerNumber plyr_idx, char * args) return true; } +TbBool cmd_chicken_creature(PlayerNumber plyr_idx, char * args) +{ + if (game.easter_eggs_enabled == false) { + targeted_message_add(MsgType_Player, plyr_idx, plyr_idx, GUI_MESSAGES_DELAY, "require 'cheat mode'"); + return false; + } + struct PlayerInfo * player = get_player(plyr_idx); + struct Thing * thing = thing_get(player->influenced_thing_idx); + if (!thing_is_creature(thing)) { + targeted_message_add(MsgType_Player, plyr_idx, plyr_idx, GUI_MESSAGES_DELAY, "no thing selected or not creature"); + return false; + } + struct PowerConfigStats *powerst = get_power_model_stats(PwrK_CHICKEN); + thing_play_sample(thing, powerst->select_sound_idx, NORMAL_PITCH, 0, 3, 0, 4, FULL_LOUDNESS); + // Not sure how to handle this yet, for now simply hardcode the intended spell kind with a number. + apply_spell_effect_to_thing(thing, 27, 8, plyr_idx); // 3 was 'SplK_Chicken' in the enum. + return true; +} + struct ConsoleCommand { const char * name; @@ -2293,6 +2312,7 @@ static const struct ConsoleCommand console_commands[] = { { "lua", cmd_lua}, { "luatypedump", cmd_luatypedump}, { "cheat.menu", cmd_cheat_menu}, + { "creature.chicken", cmd_chicken_creature}, }; static const int console_command_count = sizeof(console_commands) / sizeof(*console_commands); From c314911b22543dab6e4234bd112d4f6198be057c Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:17:37 +0000 Subject: [PATCH 48/81] Update console_cmd.c --- src/console_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/console_cmd.c b/src/console_cmd.c index e244170ee1..1585c3e653 100644 --- a/src/console_cmd.c +++ b/src/console_cmd.c @@ -2197,7 +2197,7 @@ TbBool cmd_chicken_creature(PlayerNumber plyr_idx, char * args) struct PowerConfigStats *powerst = get_power_model_stats(PwrK_CHICKEN); thing_play_sample(thing, powerst->select_sound_idx, NORMAL_PITCH, 0, 3, 0, 4, FULL_LOUDNESS); // Not sure how to handle this yet, for now simply hardcode the intended spell kind with a number. - apply_spell_effect_to_thing(thing, 27, 8, plyr_idx); // 3 was 'SplK_Chicken' in the enum. + apply_spell_effect_to_thing(thing, 27, 8, plyr_idx); // 27 was 'SplK_Chicken' in the enum. return true; } From 07b6e829b3fbc20bebc24713472bd76cd3e2a2c9 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:42:39 +0000 Subject: [PATCH 49/81] Allow while Chickened in possession --- src/front_input.c | 55 ++++++++++++++++++++++------------------------- src/packets.c | 6 ++++-- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/front_input.c b/src/front_input.c index fbff577544..0f482f98c4 100644 --- a/src/front_input.c +++ b/src/front_input.c @@ -1863,45 +1863,42 @@ short get_creature_control_action_inputs(void) set_players_packet_action(player, PckA_SelectFPPickup, player->thing_under_hand, 0, 0, 0); } } - if (!creature_under_spell_effect(thing, CSAfF_Chicken)) + if (numkey != -1) { - if (numkey != -1) + int num_avail = 0; + for (int idx = 0; idx < LEARNED_INSTANCES_COUNT; idx++) { - int num_avail = 0; - for (int idx = 0; idx < LEARNED_INSTANCES_COUNT; idx++) + struct Thing* cthing = thing_get(player->controlled_thing_idx); + TRACE_THING(cthing); + struct CreatureModelConfig* crconf = creature_stats_get_from_thing(cthing); + int inst_id = crconf->learned_instance_id[idx]; + if (creature_instance_is_available(cthing, inst_id)) { - struct Thing* cthing = thing_get(player->controlled_thing_idx); - TRACE_THING(cthing); - struct CreatureModelConfig* crconf = creature_stats_get_from_thing(cthing); - int inst_id = crconf->learned_instance_id[idx]; - if (creature_instance_is_available(cthing, inst_id)) + if (numkey == num_avail) { - if (numkey == num_avail) - { - set_players_packet_action(player, PckA_CtrlCrtrSetInstnc, inst_id, 0, 0, 0); - break; - } - num_avail++; + set_players_packet_action(player, PckA_CtrlCrtrSetInstnc, inst_id, 0, 0, 0); + break; } + num_avail++; } } + } + + // Next/Previous instance switching + if (menu_is_active(GMnu_CREATURE_QUERY1) || menu_is_active(GMnu_CREATURE_QUERY2)) + { + struct Thing* cthing = thing_get(player->controlled_thing_idx); - // Next/Previous instance switching - if (menu_is_active(GMnu_CREATURE_QUERY1) || menu_is_active(GMnu_CREATURE_QUERY2)) + if (is_key_pressed(KC_GAMEPAD_RIGHTSHOULDER, KMod_DONTCARE)) { - struct Thing* cthing = thing_get(player->controlled_thing_idx); + clear_key_pressed(KC_GAMEPAD_RIGHTSHOULDER); + set_possession_instance(player, cthing, 1); - if (is_key_pressed(KC_GAMEPAD_RIGHTSHOULDER, KMod_DONTCARE)) - { - clear_key_pressed(KC_GAMEPAD_RIGHTSHOULDER); - set_possession_instance(player, cthing, 1); - - } - else if (is_key_pressed(KC_GAMEPAD_LEFTSHOULDER, KMod_DONTCARE)) - { - clear_key_pressed(KC_GAMEPAD_LEFTSHOULDER); - set_possession_instance(player, cthing, -1); - } + } + else if (is_key_pressed(KC_GAMEPAD_LEFTSHOULDER, KMod_DONTCARE)) + { + clear_key_pressed(KC_GAMEPAD_LEFTSHOULDER); + set_possession_instance(player, cthing, -1); } } return false; diff --git a/src/packets.c b/src/packets.c index b3691cd482..b19fb2edc7 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1441,9 +1441,11 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - if (!creature_under_spell_effect(cctng, CSAfF_Chicken)) + inst_inf = creature_instance_info_get(i); + struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); + allowed = (creature_under_spell_effect(cctng, CSAfF_Chicken)) ? flag_is_set(spconf->cleanse_flags, CSAfF_Chicken) : true; + if (allowed) { - inst_inf = creature_instance_info_get(i); allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; if (allowed) { From 652c8cd92bfed2934e8f685c6f99f03cf229b496 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 21:08:41 +0000 Subject: [PATCH 50/81] Optimise --- src/packets.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/packets.c b/src/packets.c index b19fb2edc7..fe6d9d3509 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1441,12 +1441,27 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - inst_inf = creature_instance_info_get(i); - struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); - allowed = (creature_under_spell_effect(cctng, CSAfF_Chicken)) ? flag_is_set(spconf->cleanse_flags, CSAfF_Chicken) : true; + if (creature_under_spell_effect(cctng, CSAfF_Chicken)) + { + inst_inf = creature_instance_info_get(i); + struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); + allowed = flag_is_set(spconf->cleanse_flags, CSAfF_Chicken); + } + else + { + allowed = true; + } if (allowed) { - allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (creature_under_spell_effect(cctng, CSAfF_Freeze)) + { + inst_inf = creature_instance_info_get(i); + allowed = inst_inf->fp_allow_while_frozen; + } + else + { + allowed = true; + } if (allowed) { process_player_use_instance(cctng, i, pckt); @@ -1475,7 +1490,14 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - allowed = (creature_under_spell_effect(cctng, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + if (creature_under_spell_effect(cctng, CSAfF_Freeze)) + { + allowed = inst_inf->fp_allow_while_frozen; + } + else + { + allowed = true; + } if (allowed) { process_player_use_instance(cctng, i, pckt); From 6bb16b8095a251f3c966e90b0f0f0ae6b7c80a1e Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 7 Feb 2026 21:53:14 +0000 Subject: [PATCH 51/81] Block cleansing others whilst Chickened. --- src/creature_instances.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index 70b0d71546..e14f5eebd1 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1851,7 +1851,7 @@ TbBool validate_target_requires_cleansing { if (creature_is_being_tortured(target) || creature_is_kept_in_prison(target) || creature_is_being_tortured(source) || creature_is_kept_in_prison(source) || - creature_under_spell_effect(source, CSAfF_Freeze)) // not allowed to cleanse others (only itself) even if source param1 is set + creature_under_spell_effect(source, CSAfF_Freeze) || creature_under_spell_effect(source, CSAfF_Chicken)) // not allowed to cleanse others (only itself) even if source param1 is set { return false; } From 58b44cc40ddf037d9a0431e4a945eef2ddd9ba5d Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 8 Feb 2026 01:49:18 +0000 Subject: [PATCH 52/81] Redundant assignment --- src/packets.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/packets.c b/src/packets.c index fe6d9d3509..6a5f6e36d3 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1458,10 +1458,6 @@ void process_players_creature_control_packet_control(long idx) inst_inf = creature_instance_info_get(i); allowed = inst_inf->fp_allow_while_frozen; } - else - { - allowed = true; - } if (allowed) { process_player_use_instance(cctng, i, pckt); From e01f0a7fb492f60d604423f3ed2cc45d9631dcbd Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:22:48 +0000 Subject: [PATCH 53/81] Allow cleansing of own accord whilst Chickened --- config/fxdata/creature.cfg | 2 +- src/creature_instances.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 9d7b6faad3..a2d7af18ae 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1187,7 +1187,7 @@ Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_even_in_prison 1 0 +ValidateSourceFunc = validate_source_even_in_prison 2560 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 [instance56] diff --git a/src/creature_instances.c b/src/creature_instances.c index e14f5eebd1..0f6e809f5e 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -1148,8 +1148,9 @@ TbBool validate_source_basic if (!creature_instance_is_available(source, inst_idx) || !creature_instance_has_reset(source, inst_idx) || - (creature_under_spell_effect(source, CSAfF_Freeze) && (param1 == 0)) || - creature_is_fleeing_combat(source) || creature_under_spell_effect(source, CSAfF_Chicken) || + ((creature_under_spell_effect(source, CSAfF_Freeze)) && (!flag_is_set(param1, CSAfF_Freeze))) || + creature_is_fleeing_combat(source) || + ((creature_under_spell_effect(source, CSAfF_Chicken)) && (!flag_is_set(param1, CSAfF_Chicken))) || creature_is_being_unconscious(source) || creature_is_dying(source) || thing_is_picked_up(source) || creature_is_being_dropped(source) || creature_is_being_sacrificed(source) || creature_is_being_summoned(source)) From 895368a7013f9aec0965e80a08dc3b90450c4988 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:26:01 +0000 Subject: [PATCH 54/81] Ranged too --- config/fxdata/creature.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index a2d7af18ae..80515dbdb3 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1209,7 +1209,7 @@ RangeMax = 3072 Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_generic 0 0 +ValidateSourceFunc = validate_source_generic 2560 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 SearchTargetsFunc = search_target_generic 0 0 From 941a64ddb09fb81b515dcf135ab8379069a50107 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:54:49 +0000 Subject: [PATCH 55/81] Added FPAllowWhenChicken config field --- config/fxdata/creature.cfg | 56 +++++++++++++++++++++++++++++++++++++ src/config_creature.c | 14 ++++++++++ src/creature_instances.h | 1 + src/frontmenu_ingame_tabs.c | 19 ++++++++++++- src/packets.c | 23 +++++++++++++-- 5 files changed, 109 insertions(+), 4 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 80515dbdb3..8a379348f1 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -127,6 +127,7 @@ FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 252 SymbolSprites = 450 @@ -147,6 +148,7 @@ FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 252 SymbolSprites = 400 @@ -166,6 +168,7 @@ FPTime = 0 FPActionTime = 0 FPResetTime = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -184,6 +187,7 @@ FPActionTime = 2 FPResetTime = 8 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 226 SymbolSprites = 454 @@ -205,6 +209,7 @@ FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 251 SymbolSprites = 402 @@ -226,6 +231,7 @@ FPActionTime = 3 FPResetTime = 16 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 250 SymbolSprites = 404 @@ -246,6 +252,7 @@ FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 227 SymbolSprites = 406 @@ -266,6 +273,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -286,6 +294,7 @@ FPActionTime = 3 FPResetTime = 8 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 229 SymbolSprites = 410 @@ -307,6 +316,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -327,6 +337,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -347,6 +358,7 @@ FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 237 SymbolSprites = 416 @@ -368,6 +380,7 @@ FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -388,6 +401,7 @@ FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -406,6 +420,7 @@ FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -426,6 +441,7 @@ FPActionTime = 3 FPResetTime = 600 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 245 SymbolSprites = 424 @@ -446,6 +462,7 @@ FPActionTime = 3 FPResetTime = 3 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 246 SymbolSprites = 513 @@ -466,6 +483,7 @@ FPActionTime = 3 FPResetTime = 450 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 231 SymbolSprites = 819 @@ -486,6 +504,7 @@ FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 233 SymbolSprites = 426 @@ -507,6 +526,7 @@ FPActionTime = 2 FPResetTime = 5 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 235 SymbolSprites = 428 @@ -528,6 +548,7 @@ FPActionTime = 3 FPResetTime = 1 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 241 SymbolSprites = 430 @@ -548,6 +569,7 @@ FPActionTime = 3 FPResetTime = 800 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 30 TooltipTextID = 249 SymbolSprites = 432 @@ -569,6 +591,7 @@ FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -587,6 +610,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -607,6 +631,7 @@ FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -627,6 +652,7 @@ FPActionTime = 3 FPResetTime = 100 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 80 TooltipTextID = 234 SymbolSprites = 440 @@ -646,6 +672,7 @@ FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 80 TooltipTextID = 244 SymbolSprites = 442 @@ -667,6 +694,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 247 SymbolSprites = 444 @@ -687,6 +715,7 @@ FPActionTime = 2 FPResetTime = 100 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 253 SymbolSprites = 446 @@ -707,6 +736,7 @@ FPActionTime = 2 FPResetTime = 1 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 40 TooltipTextID = 254 SymbolSprites = 448 @@ -724,6 +754,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -741,6 +772,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -758,6 +790,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -775,6 +808,7 @@ FPTime = 4 FPActionTime = 1 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -791,6 +825,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -808,6 +843,7 @@ FPTime = 8 FPActionTime = 4 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -826,6 +862,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 201 SymbolSprites = 0 @@ -843,6 +880,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 201 SymbolSprites = 0 @@ -861,6 +899,7 @@ FPActionTime = 2 FPResetTime = 1 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 3 TooltipTextID = 254 SymbolSprites = 448 @@ -879,6 +918,7 @@ FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 80 TooltipTextID = 234 SymbolSprites = 440 @@ -900,6 +940,7 @@ FPActionTime = 3 FPResetTime = 150 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 255 SymbolSprites = 319 @@ -920,6 +961,7 @@ FPActionTime = 3 FPResetTime = 150 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 256 SymbolSprites = 314 @@ -940,6 +982,7 @@ FPActionTime = 3 FPResetTime = 3 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 257 SymbolSprites = 548 @@ -959,6 +1002,7 @@ FPTime = 4 FPActionTime = 1 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -976,6 +1020,7 @@ FPTime = 8 FPActionTime = 4 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -993,6 +1038,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -1010,6 +1056,7 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -1028,6 +1075,7 @@ FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -1048,6 +1096,7 @@ FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 0 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1068,6 +1117,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 1066 SymbolSprites = 786 @@ -1091,6 +1141,7 @@ FPActionTime = 3 FPResetTime = 500 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 654 SymbolSprites = 792 @@ -1114,6 +1165,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 655 SymbolSprites = 780 @@ -1137,6 +1189,7 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 1069 SymbolSprites = 788 @@ -1160,6 +1213,7 @@ FPActionTime = 2 FPResetTime = 160 FPInstantCast = 0 FPAllowWhileFrozen = 0 +FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 245 SymbolSprites = 827 @@ -1180,6 +1234,7 @@ FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 1 ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 @@ -1200,6 +1255,7 @@ FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 FPAllowWhileFrozen = 1 +FPAllowWhenChicken = 1 ForceVisibility = 30 TooltipTextID = 1068 SymbolSprites = 794 diff --git a/src/config_creature.c b/src/config_creature.c index 41da285c8f..6cee1f4534 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -107,6 +107,7 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"PostalPriority", 21}, {"NoAnimationLoop", 22}, {"FPAllowWhileFrozen", 23}, + {"FPAllowWhenChicken", 24}, {NULL, 0}, }; @@ -1420,6 +1421,19 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; + case 24: // FPALLOWWHENCHICKEN + if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) + { + k = atoi(word_buf); + inst_inf->fp_allow_when_chicken = (TbBool)k; + n++; + } + if (n < 1) + { + CONFWRNLOG("Couldn't read \"%s\" parameter in [%.*s] block of %s file.", + COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); + } + break; case ccr_comment: break; case ccr_endOfFile: diff --git a/src/creature_instances.h b/src/creature_instances.h index c131db1c37..14b35480b0 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -127,6 +127,7 @@ struct InstanceInfo { uint8_t search_func; int32_t search_func_params[2]; TbBool fp_allow_while_frozen; + TbBool fp_allow_when_chicken; }; /******************************************************************************/ diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index f992370437..12afd6116c 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1873,7 +1873,24 @@ void gui_area_instance_button(struct GuiButton *gbtn) LbTextDrawResized(gbtn->scr_pos_x + 52*units_per_px/16, gbtn->scr_pos_y + 9*units_per_px/16, tx_units_per_px, text); spr_idx = gbtn->sprite_idx; // Show disabled icon if instance is on cooldown or creature is frozen. - if ((!creature_instance_has_reset(ctrltng, curbtn_inst_id)) || (creature_under_spell_effect(ctrltng, CSAfF_Freeze) && (!inst_inf->fp_allow_while_frozen))) + TbBool disabled; + if (!creature_instance_has_reset(ctrltng, curbtn_inst_id)) + { + disabled = true; + } + else if (creature_under_spell_effect(ctrltng, CSAfF_Freeze)) + { + disabled = !inst_inf->fp_allow_while_frozen; + } + else if (creature_under_spell_effect(ctrltng, CSAfF_Chicken)) + { + disabled = !inst_inf->fp_allow_when_chicken; + } + else + { + disabled = false; + } + if (disabled) { spr_idx++; } diff --git a/src/packets.c b/src/packets.c index 6a5f6e36d3..cdcb1672f4 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1444,8 +1444,7 @@ void process_players_creature_control_packet_control(long idx) if (creature_under_spell_effect(cctng, CSAfF_Chicken)) { inst_inf = creature_instance_info_get(i); - struct SpellConfig* spconf = get_spell_config(inst_inf->func_params[0]); - allowed = flag_is_set(spconf->cleanse_flags, CSAfF_Chicken); + allowed = inst_inf->fp_allow_when_chicken; } else { @@ -1553,7 +1552,25 @@ void process_players_creature_control_packet_action(long plyr_idx) { if (creature_instance_is_available(thing,i) && creature_instance_has_reset(thing, pckt->actn_par1)) { - TbBool allowed = (creature_under_spell_effect(thing, CSAfF_Freeze)) ? inst_inf->fp_allow_while_frozen : true; + TbBool allowed; + TbBool frozen = creature_under_spell_effect(thing, CSAfF_Freeze); + TbBool chicken = creature_under_spell_effect(thing, CSAfF_Chicken); + if (frozen && chicken) + { + allowed = (inst_inf->fp_allow_while_frozen && inst_inf->fp_allow_when_chicken); + } + else if (frozen) + { + allowed = inst_inf->fp_allow_while_frozen; + } + else if (chicken) + { + allowed = inst_inf->fp_allow_when_chicken; + } + else + { + allowed = true; + } if (allowed) { i = pckt->actn_par1; From 47b60b6ce422e4038a32efd3d54b39dce01ad481 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:11:05 +0000 Subject: [PATCH 56/81] Update creature.cfg --- config/fxdata/creature.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 8a379348f1..1bec44c236 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -52,6 +52,8 @@ FPResetTime = 0 FPInstantCast = 0 ; Instance can be used when frozen in possession. FPAllowWhileFrozen = 0 +; Instance can be used when under the Chicken spell in possession. +FPAllowWhenChicken = 0 ; How many game turns after using the instance creature can be spotted even if invisible. ForceVisibility = 0 ; Tooltip string ID, explaining what the instance does. From 63660e53d0f3ab1a5a9fa278f117ab031c0ce521 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:16:19 +0000 Subject: [PATCH 57/81] Update creature_instances.h --- src/creature_instances.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/creature_instances.h b/src/creature_instances.h index 14b35480b0..5b260d47c1 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -86,6 +86,7 @@ enum CreatureInstances { CrInst_RANGED_REBOUND, CrInst_CRIPPLE, CrInst_CLEANSE, + CrInst_RANGED_CLEANSE, CrInst_LISTEND, }; From 420a9cda8256de2a51568b79f7065f283221df19 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 15 Feb 2026 20:00:30 +0000 Subject: [PATCH 58/81] Workaround for Cleanse resetting when de-Chickening in possession --- src/creature_control.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/creature_control.c b/src/creature_control.c index e1f3b2183b..0e3e559e31 100644 --- a/src/creature_control.c +++ b/src/creature_control.c @@ -189,7 +189,10 @@ struct Thing *create_and_control_creature_as_controller(struct PlayerInfo *playe void clear_creature_instance(struct Thing *thing) { struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - cctrl->instance_id = CrInst_NULL; + if ((thing->alloc_flags & TAlF_IsControlled) == 0) + { + cctrl->instance_id = CrInst_NULL; + } cctrl->inst_turn = 0; } From 30ca7384b7fd8d44b35021a7b42100bd820b88b3 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sun, 15 Feb 2026 21:19:19 +0100 Subject: [PATCH 59/81] Revert "Workaround for Cleanse resetting when de-Chickening in possession" This reverts commit 420a9cda8256de2a51568b79f7065f283221df19. --- src/creature_control.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/creature_control.c b/src/creature_control.c index 0e3e559e31..e1f3b2183b 100644 --- a/src/creature_control.c +++ b/src/creature_control.c @@ -189,10 +189,7 @@ struct Thing *create_and_control_creature_as_controller(struct PlayerInfo *playe void clear_creature_instance(struct Thing *thing) { struct CreatureControl* cctrl = creature_control_get_from_thing(thing); - if ((thing->alloc_flags & TAlF_IsControlled) == 0) - { - cctrl->instance_id = CrInst_NULL; - } + cctrl->instance_id = CrInst_NULL; cctrl->inst_turn = 0; } From 03715473c025150a27cfa2318b1cb06079188157 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sun, 15 Feb 2026 21:19:42 +0100 Subject: [PATCH 60/81] Alternative approach --- src/creature_instances.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index 0f6e809f5e..c84c799da9 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -514,7 +514,8 @@ long instf_creature_cast_spell(struct Thing *creatng, int32_t *param) // instead of creature_cast_spell_at_thing. target = thing_get(cctrl->targtng_idx); } - + // Start cooldown after spell effect activates + cctrl->instance_use_turn[cctrl->instance_id] = game.play_gameturn; if (!thing_is_invalid(target)) { creature_cast_spell_at_thing(creatng, target, spl_idx, cctrl->exp_level); @@ -523,9 +524,6 @@ long instf_creature_cast_spell(struct Thing *creatng, int32_t *param) { creature_cast_spell(creatng, spl_idx, cctrl->exp_level, cctrl->targtstl_x, cctrl->targtstl_y); } - - // Start cooldown after spell effect activates - cctrl->instance_use_turn[cctrl->instance_id] = game.play_gameturn; return 0; } From c6855b5b945db199ff433ff61bd379355dd227f4 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Thu, 19 Feb 2026 01:36:19 +0000 Subject: [PATCH 61/81] Explanatory comments --- config/fxdata/creature.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 1bec44c236..6502c243a5 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -1244,7 +1244,9 @@ Graphics = CASTSPELL Properties = SELF_BUFF PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 +;param 1 - spell flags under which the instance is allowed ValidateSourceFunc = validate_source_even_in_prison 2560 0 +;param 1 - spell kind from which to take CleanseFlags ValidateTargetFunc = validate_target_requires_cleansing 32 0 [instance56] From a973dbfc7b0e87c875bab5426b20b9de7a342e90 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Tue, 24 Feb 2026 02:17:31 +0100 Subject: [PATCH 62/81] Reduce cleanse duration --- config/fxdata/effects.toml | 28 ++++++++++++++++++++++++++++ config/fxdata/magic.cfg | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/config/fxdata/effects.toml b/config/fxdata/effects.toml index eda36aed55..5b7c0b4f4b 100644 --- a/config/fxdata/effects.toml +++ b/config/fxdata/effects.toml @@ -5343,6 +5343,34 @@ SubeffectModel = 0 SubeffectDelay = 0 Movable = false Impacts = false +TransformModel = 125 +LightRadius = 0 +LightIntensity = 0 +LightFlags = 0 +AffectedByWind = 0 + +[effectElement125] +Name = "EFFECTELEMENT_CLEANSE_DURATION" +DrawClass = 2 +MoveType = 2 +Unanimated = 0 +Lifespan = [10,15] +AnimationId = 850 +SpriteSize = [12,24] +AnimateOnce = 0 +SpriteSpeed = [384,512] +AnimateOnFloor = true +Unshaded = true +Transparent = 3 +ThroughWalls = 0 +SizeChange = 0 +FallAcceleration = 0 +InertiaFloor = 0 +InertiaAir = 0 +SubeffectModel = 0 +SubeffectDelay = 0 +Movable = false +Impacts = false TransformModel = 0 LightRadius = 0 LightIntensity = 0 diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 16cb9aa5c7..c18ac02dd2 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -370,7 +370,7 @@ AuraEffect = EFFECT_CLEANSE AuraFrequency = 0 AuraDuration = 10 CleanseFlags = SLOW DISEASE CHICKEN FREEZE FEAR -Duration = 100 +Duration = 30 SelfCasted = 1 162 1 SymbolSprites = 796 798 From d621a2a40acc4c69e8f47a08cd9aac4520680522 Mon Sep 17 00:00:00 2001 From: Spatulade <100633508+Spatulade@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:43:01 +0000 Subject: [PATCH 63/81] initial setup for keeper power version Need to confirm nametext vs tooltiptext, sound and how to limit casting only to creatures with debuffs. --- config/fxdata/magic.cfg | 25 +++++++++++++++++++++++++ config/fxdata/objects.cfg | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index c18ac02dd2..7527ff2a56 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -2299,6 +2299,31 @@ ParentPower = POWER_HAND CastExpandFunc = do_not_expand UseFunction = magic_use_power_hand +[power30] +Name = POWER_CLEANSE +;check this +NameTextID = 1068 +TooltipTextID = 1068 +SymbolSprites = 796 798 +PointerSprites = 336 +PanelTabIndex = 30 +SoundSamples = 0 +;check this +SoundPlayed = 161 +;Made it cost slightly more than the most expensive debuff it can cure. +Power = 750 750 750 750 750 750 750 750 750 750 +Cost = 1400 1400 1400 1400 1400 1400 1400 1400 1400 +;Needs to only be castable on these creatures with a debuff! +Castability = ALL_GROUND OWNED_CRTRS ALLIED_CRTRS BOUND_CRTRS +Artifact = SPELLBOOK_CLNS +Properties = +PlayerState = PLAYER_STATE_CAST_ON_TARGET +ParentPower = NOPOWER +; To have this power chargeable like other replace 'do_not_expand' with 'general_expand'. +CastExpandFunc = do_not_expand +Spell = SPELL_CLEANSE +UseFunction = magic_use_power_apply_spell + ; Specials types. [special0] diff --git a/config/fxdata/objects.cfg b/config/fxdata/objects.cfg index f626ea7484..6784fec9e7 100644 --- a/config/fxdata/objects.cfg +++ b/config/fxdata/objects.cfg @@ -4557,4 +4557,29 @@ DrawClass = 2 Persistence = 1 Immobile = 1 Properties = CHOWNED_ON_ROOM_CLAIM +UpdateFunction = NULL + +[object185] +Name = SPELLBOOK_CLNS +Genre = SPELLBOOK +AnimationID = 777 +AnimationSpeed = 256 +Size_XY = 0 +Size_Z = 0 +MaximumSize = 300 +DestroyOnLava = 1 +DestroyOnLiquid = 0 +Health = 0 +FallAcceleration = 10 +LightUnaffected = 0 +MapIcon = -1 +TooltipTextID = -1 0 +LightIntensity = 62 +LightRadius = 4 +LightIsDynamic = 0 +RandomStartFrame = 0 +DrawClass = 2 +Persistence = 1 +Immobile = 1 +Properties = CHOWNED_ON_ROOM_CLAIM UpdateFunction = NULL \ No newline at end of file From 671046b79b83c062e724a1f5bbfe64ab9169d841 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sat, 14 Mar 2026 12:38:40 +0100 Subject: [PATCH 64/81] Also do tingle when creature gets hit with cleanse --- config/fxdata/magic.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 7527ff2a56..7364cbddf5 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -1624,7 +1624,7 @@ ShotSoundPriority = 1 VisualEffect = EFFECTELEMENT_CLEANSE VisualEffectAmount = 1 VisualEffectSpread = 1 -HitCreatureSound = 0 0 +HitCreatureSound = 162 1 HitWaterEffect = EFFECT_DRIP_1 HitWaterSound = 21 1 Properties = NAVIGABLE REBOUND_IMMUNE From 970d16fbd5ff538e36b203b4e27bc5812b002d0f Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sat, 14 Mar 2026 17:26:18 +0100 Subject: [PATCH 65/81] Revert "initial setup for keeper power version" This reverts commit d621a2a40acc4c69e8f47a08cd9aac4520680522. --- config/fxdata/magic.cfg | 25 ------------------------- config/fxdata/objects.cfg | 25 ------------------------- 2 files changed, 50 deletions(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 7364cbddf5..aecb4456c2 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -2299,31 +2299,6 @@ ParentPower = POWER_HAND CastExpandFunc = do_not_expand UseFunction = magic_use_power_hand -[power30] -Name = POWER_CLEANSE -;check this -NameTextID = 1068 -TooltipTextID = 1068 -SymbolSprites = 796 798 -PointerSprites = 336 -PanelTabIndex = 30 -SoundSamples = 0 -;check this -SoundPlayed = 161 -;Made it cost slightly more than the most expensive debuff it can cure. -Power = 750 750 750 750 750 750 750 750 750 750 -Cost = 1400 1400 1400 1400 1400 1400 1400 1400 1400 -;Needs to only be castable on these creatures with a debuff! -Castability = ALL_GROUND OWNED_CRTRS ALLIED_CRTRS BOUND_CRTRS -Artifact = SPELLBOOK_CLNS -Properties = -PlayerState = PLAYER_STATE_CAST_ON_TARGET -ParentPower = NOPOWER -; To have this power chargeable like other replace 'do_not_expand' with 'general_expand'. -CastExpandFunc = do_not_expand -Spell = SPELL_CLEANSE -UseFunction = magic_use_power_apply_spell - ; Specials types. [special0] diff --git a/config/fxdata/objects.cfg b/config/fxdata/objects.cfg index 6784fec9e7..f626ea7484 100644 --- a/config/fxdata/objects.cfg +++ b/config/fxdata/objects.cfg @@ -4557,29 +4557,4 @@ DrawClass = 2 Persistence = 1 Immobile = 1 Properties = CHOWNED_ON_ROOM_CLAIM -UpdateFunction = NULL - -[object185] -Name = SPELLBOOK_CLNS -Genre = SPELLBOOK -AnimationID = 777 -AnimationSpeed = 256 -Size_XY = 0 -Size_Z = 0 -MaximumSize = 300 -DestroyOnLava = 1 -DestroyOnLiquid = 0 -Health = 0 -FallAcceleration = 10 -LightUnaffected = 0 -MapIcon = -1 -TooltipTextID = -1 0 -LightIntensity = 62 -LightRadius = 4 -LightIsDynamic = 0 -RandomStartFrame = 0 -DrawClass = 2 -Persistence = 1 -Immobile = 1 -Properties = CHOWNED_ON_ROOM_CLAIM UpdateFunction = NULL \ No newline at end of file From db890601a0215e50a3997af0c8c612880fcecc52 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sat, 14 Mar 2026 19:40:38 +0100 Subject: [PATCH 66/81] Create shot starts with random animation frame --- src/thing_shots.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thing_shots.c b/src/thing_shots.c index 822b44e654..3140f4efde 100644 --- a/src/thing_shots.c +++ b/src/thing_shots.c @@ -1791,7 +1791,7 @@ struct Thing *create_shot(struct Coord3d *pos, ThingModel model, unsigned short thing->inertia_floor = shotst->inertia_floor; thing->inertia_air = shotst->inertia_air; thing->movement_flags ^= (thing->movement_flags ^ TMvF_ZeroVerticalVelocity * shotst->soft_landing) & TMvF_ZeroVerticalVelocity; - set_thing_draw(thing, shotst->sprite_anim_idx, 256, shotst->sprite_size_max, 0, 0, ODC_Default); + set_thing_draw(thing, shotst->sprite_anim_idx, 256, shotst->sprite_size_max, 0, -1, ODC_Default); thing->rendering_flags ^= (thing->rendering_flags ^ TRF_Unshaded * shotst->unshaded) & TRF_Unshaded; thing->rendering_flags ^= thing->rendering_flags ^ ((thing->rendering_flags ^ TRF_Transpar_8 * shotst->animation_transparency) & (TRF_Transpar_Flags)); thing->rendering_flags ^= (thing->rendering_flags ^ shotst->hidden_projectile) & TRF_Invisible; From 8c2202aae13b1724d4341abac0257c1c0994434e Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sat, 14 Mar 2026 19:41:38 +0100 Subject: [PATCH 67/81] Use custom animation --- config/fxdata/magic.cfg | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index aecb4456c2..5dddac04fb 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -1605,11 +1605,11 @@ UpdateLogic = SmokeWhenFired [shot41] Name = SHOT_RANGED_CLEANSE -Animation = 119 -AnimationSize = 50 +Animation = SPARKLE_CLEANSE +AnimationSize = 128 AnimationTransparency = 3 -Size_XY = 16 -Size_Z = 16 +Size_XY = 64 +Size_Z = 64 Health = 30 Damage = 0 HitType = 11 @@ -1621,15 +1621,12 @@ TargetHitstopTurns = 6 FiringSound = 161 ShotSound = 0 ShotSoundPriority = 1 -VisualEffect = EFFECTELEMENT_CLEANSE -VisualEffectAmount = 1 -VisualEffectSpread = 1 HitCreatureSound = 162 1 HitWaterEffect = EFFECT_DRIP_1 HitWaterSound = 21 1 Properties = NAVIGABLE REBOUND_IMMUNE FireLogic = 3 -EffectAmount = 4 +EffectAmount = 3 Spread_XY = 50 Spread_Z = 50 From c68866955b3c33cd5ea2ad920ac8bc6b2fba97b3 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sat, 14 Mar 2026 23:16:39 +0100 Subject: [PATCH 68/81] Set target for firelogic 3 (ShFL_Hail) --- src/thing_creature.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/thing_creature.c b/src/thing_creature.c index 388fd8da40..6b79310b90 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -3746,6 +3746,7 @@ void thing_fire_shot(struct Thing *firing, struct Thing *target, ThingModel shot shotng->shot.damage = damage; shotng->health = shotst->health; shotng->parent_idx = firing->index; + shotng->shot.target_idx = target_idx; } break; } From 0420516b95f4898fc72fce45c7fd7310872911f6 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Thu, 19 Mar 2026 02:08:53 +0100 Subject: [PATCH 69/81] Stopped creature hurt sound on cleanse --- config/fxdata/magic.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/config/fxdata/magic.cfg b/config/fxdata/magic.cfg index 1f3ec3674c..500d6188cc 100644 --- a/config/fxdata/magic.cfg +++ b/config/fxdata/magic.cfg @@ -1621,7 +1621,6 @@ TargetHitstopTurns = 6 FiringSound = 161 ShotSound = 0 ShotSoundPriority = 1 -HitCreatureSound = 162 1 HitWaterEffect = EFFECT_DRIP_1 HitWaterSound = 21 1 Properties = NAVIGABLE REBOUND_IMMUNE From 7246c98b43eef7a287edbd429f075e85e673d8ee Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sat, 28 Mar 2026 20:48:02 +0000 Subject: [PATCH 70/81] Exclude instances that are allowed while frozen from being suspended while under Freeze --- src/creature_instances.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index f5205a0f41..f9bee49b69 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -409,10 +409,15 @@ void process_creature_instance(struct Thing *thing) struct CreatureControl *cctrl; TRACE_THING(thing); cctrl = creature_control_get_from_thing(thing); + struct InstanceInfo* inst_inf; SYNCDBG(19, "Starting for %s index %d instance %d", thing_model_name(thing), (int)thing->index, (int)cctrl->instance_id); if (cctrl->instance_id != CrInst_NULL && creature_under_spell_effect(thing, CSAfF_Freeze)) { - return; + inst_inf = creature_instance_info_get(cctrl->instance_id); + if (!inst_inf->fp_allow_while_frozen) + { + return; + } } if (cctrl->inst_turn >= cctrl->inst_total_turns) { @@ -430,7 +435,7 @@ void process_creature_instance(struct Thing *thing) cctrl->inst_turn++; if (cctrl->inst_turn == cctrl->inst_action_turns) { - struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); + inst_inf = creature_instance_info_get(cctrl->instance_id); if (creature_instances_func_list[inst_inf->func_idx] != NULL) { SYNCDBG(18,"Executing %s for %s index %d.",creature_instance_code_name(cctrl->instance_id),thing_model_name(thing),(int)thing->index); From 946c4039a4ea47b61dc148ef202a03fd2323f3ea Mon Sep 17 00:00:00 2001 From: Loobinex Date: Tue, 7 Apr 2026 23:55:22 +0200 Subject: [PATCH 71/81] Removed all the = 0 lines --- config/fxdata/creature.cfg | 97 -------------------------------------- 1 file changed, 97 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 6502c243a5..36cbd0f7d2 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -128,8 +128,6 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 252 SymbolSprites = 450 @@ -149,8 +147,6 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 252 SymbolSprites = 400 @@ -169,8 +165,6 @@ ResetTime = 0 FPTime = 0 FPActionTime = 0 FPResetTime = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -188,8 +182,6 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 8 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 226 SymbolSprites = 454 @@ -210,8 +202,6 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 251 SymbolSprites = 402 @@ -232,8 +222,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 16 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 250 SymbolSprites = 404 @@ -253,8 +241,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 227 SymbolSprites = 406 @@ -275,7 +261,6 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -295,8 +280,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 8 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 229 SymbolSprites = 410 @@ -318,7 +301,6 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -339,7 +321,6 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -359,8 +340,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 237 SymbolSprites = 416 @@ -382,7 +361,6 @@ FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -403,7 +381,6 @@ FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -422,7 +399,6 @@ FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -442,8 +418,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 600 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 245 SymbolSprites = 424 @@ -463,8 +437,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 246 SymbolSprites = 513 @@ -484,8 +456,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 450 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 231 SymbolSprites = 819 @@ -505,8 +475,6 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 4 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 233 SymbolSprites = 426 @@ -527,8 +495,6 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 5 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 150 TooltipTextID = 235 SymbolSprites = 428 @@ -549,8 +515,6 @@ FPTime = 3 FPActionTime = 3 FPResetTime = 1 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 241 SymbolSprites = 430 @@ -570,8 +534,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 800 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 30 TooltipTextID = 249 SymbolSprites = 432 @@ -593,7 +555,6 @@ FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -612,7 +573,6 @@ FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -633,7 +593,6 @@ FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -653,8 +612,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 100 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 80 TooltipTextID = 234 SymbolSprites = 440 @@ -673,8 +630,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 80 TooltipTextID = 244 SymbolSprites = 442 @@ -695,8 +650,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 247 SymbolSprites = 444 @@ -716,8 +669,6 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 100 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 253 SymbolSprites = 446 @@ -737,8 +688,6 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 40 TooltipTextID = 254 SymbolSprites = 448 @@ -755,8 +704,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -773,8 +720,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -791,8 +736,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -809,8 +752,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 1 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -826,8 +767,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -844,8 +783,6 @@ ResetTime = 1 FPTime = 8 FPActionTime = 4 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -863,8 +800,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 201 SymbolSprites = 0 @@ -881,8 +816,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 201 SymbolSprites = 0 @@ -900,8 +833,6 @@ FPTime = 4 FPActionTime = 2 FPResetTime = 1 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 3 TooltipTextID = 254 SymbolSprites = 448 @@ -919,8 +850,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 20 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 80 TooltipTextID = 234 SymbolSprites = 440 @@ -941,8 +870,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 255 SymbolSprites = 319 @@ -962,8 +889,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 20 TooltipTextID = 256 SymbolSprites = 314 @@ -983,8 +908,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 257 SymbolSprites = 548 @@ -1003,8 +926,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 1 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -1021,8 +942,6 @@ ResetTime = 1 FPTime = 8 FPActionTime = 4 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -1039,8 +958,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -1057,8 +974,6 @@ ResetTime = 1 FPTime = 4 FPActionTime = 2 FPResetTime = 1 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 0 TooltipTextID = 201 SymbolSprites = 0 @@ -1077,7 +992,6 @@ FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -1098,7 +1012,6 @@ FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 0 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1118,8 +1031,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 1066 SymbolSprites = 786 @@ -1142,8 +1053,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 654 SymbolSprites = 792 @@ -1166,8 +1075,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 655 SymbolSprites = 780 @@ -1190,8 +1097,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 10 TooltipTextID = 1069 SymbolSprites = 788 @@ -1214,8 +1119,6 @@ FPTime = 5 FPActionTime = 2 FPResetTime = 160 FPInstantCast = 0 -FPAllowWhileFrozen = 0 -FPAllowWhenChicken = 0 ForceVisibility = 100 TooltipTextID = 245 SymbolSprites = 827 From 64142395b63ea1f485daf16001def89e9e3c5689 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Fri, 10 Apr 2026 18:12:14 +0100 Subject: [PATCH 72/81] Renamed FPAllowWhileFrozen to AllowWhileFrozen --- config/fxdata/creature.cfg | 30 +++++++++++++++--------------- src/config_creature.c | 6 +++--- src/creature_instances.c | 2 +- src/creature_instances.h | 2 +- src/frontmenu_ingame_tabs.c | 2 +- src/packets.c | 8 ++++---- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 36cbd0f7d2..8eb66211fa 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -50,8 +50,8 @@ FPActionTime = 0 FPResetTime = 0 ; Instance is activated as soon as it's selected. FPInstantCast = 0 -; Instance can be used when frozen in possession. -FPAllowWhileFrozen = 0 +; Instance can be used when frozen. +AllowWhileFrozen = 0 ; Instance can be used when under the Chicken spell in possession. FPAllowWhenChicken = 0 ; How many game turns after using the instance creature can be spotted even if invisible. @@ -260,7 +260,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -300,7 +300,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -320,7 +320,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -360,7 +360,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -380,7 +380,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -398,7 +398,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -554,7 +554,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -572,7 +572,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -592,7 +592,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -991,7 +991,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -1011,7 +1011,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1138,7 +1138,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 FPAllowWhenChicken = 1 ForceVisibility = 10 TooltipTextID = 1067 @@ -1161,7 +1161,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 -FPAllowWhileFrozen = 1 +AllowWhileFrozen = 1 FPAllowWhenChicken = 1 ForceVisibility = 30 TooltipTextID = 1068 diff --git a/src/config_creature.c b/src/config_creature.c index fb4b123669..a7289a1905 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -106,7 +106,7 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"SearchTargetsFunc", 20}, {"PostalPriority", 21}, {"NoAnimationLoop", 22}, - {"FPAllowWhileFrozen", 23}, + {"AllowWhileFrozen", 23}, {"FPAllowWhenChicken", 24}, {NULL, 0}, }; @@ -1413,11 +1413,11 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; - case 23: // FPALLOWWHILEFROZEN + case 23: // ALLOWWHILEFROZEN if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) { k = atoi(word_buf); - inst_inf->fp_allow_while_frozen = (TbBool)k; + inst_inf->allow_while_frozen = (TbBool)k; n++; } if (n < 1) diff --git a/src/creature_instances.c b/src/creature_instances.c index f9bee49b69..88177db136 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -414,7 +414,7 @@ void process_creature_instance(struct Thing *thing) if (cctrl->instance_id != CrInst_NULL && creature_under_spell_effect(thing, CSAfF_Freeze)) { inst_inf = creature_instance_info_get(cctrl->instance_id); - if (!inst_inf->fp_allow_while_frozen) + if (!inst_inf->allow_while_frozen) { return; } diff --git a/src/creature_instances.h b/src/creature_instances.h index 939d3b64d4..9c49c84f7c 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -127,7 +127,7 @@ struct InstanceInfo { // Refer to creature_instances_search_targets_func_list uint8_t search_func; int32_t search_func_params[2]; - TbBool fp_allow_while_frozen; + TbBool allow_while_frozen; TbBool fp_allow_when_chicken; }; diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index 9331b77a45..3842ae65b2 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1880,7 +1880,7 @@ void gui_area_instance_button(struct GuiButton *gbtn) } else if (creature_under_spell_effect(ctrltng, CSAfF_Freeze)) { - disabled = !inst_inf->fp_allow_while_frozen; + disabled = !inst_inf->allow_while_frozen; } else if (creature_under_spell_effect(ctrltng, CSAfF_Chicken)) { diff --git a/src/packets.c b/src/packets.c index fe293df4bc..ec34a8b405 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1459,7 +1459,7 @@ void process_players_creature_control_packet_control(long idx) if (creature_under_spell_effect(cctng, CSAfF_Freeze)) { inst_inf = creature_instance_info_get(i); - allowed = inst_inf->fp_allow_while_frozen; + allowed = inst_inf->allow_while_frozen; } if (allowed) { @@ -1491,7 +1491,7 @@ void process_players_creature_control_packet_control(long idx) { if (creature_under_spell_effect(cctng, CSAfF_Freeze)) { - allowed = inst_inf->fp_allow_while_frozen; + allowed = inst_inf->allow_while_frozen; } else { @@ -1561,11 +1561,11 @@ void process_players_creature_control_packet_action(long plyr_idx) TbBool chicken = creature_under_spell_effect(thing, CSAfF_Chicken); if (frozen && chicken) { - allowed = (inst_inf->fp_allow_while_frozen && inst_inf->fp_allow_when_chicken); + allowed = (inst_inf->allow_while_frozen && inst_inf->fp_allow_when_chicken); } else if (frozen) { - allowed = inst_inf->fp_allow_while_frozen; + allowed = inst_inf->allow_while_frozen; } else if (chicken) { From bbf8094a01236b7ef0a53a8945f277d60e8febd9 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Sun, 12 Apr 2026 01:54:39 +0200 Subject: [PATCH 73/81] Pushed doing this over ValidateSourceFunc --- config/fxdata/creature.cfg | 21 +------------ src/config_creature.c | 28 ------------------ src/creature_instances.c | 59 +++++++++++++++++++++++++++++++++---- src/creature_instances.h | 4 +-- src/frontmenu_ingame_tabs.c | 8 ----- src/packets.c | 58 ++---------------------------------- 6 files changed, 59 insertions(+), 119 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 8eb66211fa..62d43634d3 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -50,10 +50,6 @@ FPActionTime = 0 FPResetTime = 0 ; Instance is activated as soon as it's selected. FPInstantCast = 0 -; Instance can be used when frozen. -AllowWhileFrozen = 0 -; Instance can be used when under the Chicken spell in possession. -FPAllowWhenChicken = 0 ; How many game turns after using the instance creature can be spotted even if invisible. ForceVisibility = 0 ; Tooltip string ID, explaining what the instance does. @@ -260,7 +256,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -300,7 +295,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -320,7 +314,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -360,7 +353,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -380,7 +372,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -398,7 +389,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -554,7 +544,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -572,7 +561,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -592,7 +580,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -991,7 +978,6 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -1011,7 +997,6 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 -AllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1138,8 +1123,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -AllowWhileFrozen = 1 -FPAllowWhenChicken = 1 ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 @@ -1161,8 +1144,6 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 -AllowWhileFrozen = 1 -FPAllowWhenChicken = 1 ForceVisibility = 30 TooltipTextID = 1068 SymbolSprites = 794 @@ -1172,7 +1153,7 @@ RangeMax = 3072 Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_generic 2560 0 +ValidateSourceFunc = validate_source_while_frozen 2560 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 SearchTargetsFunc = search_target_generic 0 0 diff --git a/src/config_creature.c b/src/config_creature.c index a7289a1905..57b4376d5c 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -106,8 +106,6 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"SearchTargetsFunc", 20}, {"PostalPriority", 21}, {"NoAnimationLoop", 22}, - {"AllowWhileFrozen", 23}, - {"FPAllowWhenChicken", 24}, {NULL, 0}, }; @@ -1413,32 +1411,6 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; - case 23: // ALLOWWHILEFROZEN - if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) - { - k = atoi(word_buf); - inst_inf->allow_while_frozen = (TbBool)k; - n++; - } - if (n < 1) - { - CONFWRNLOG("Couldn't read \"%s\" parameter in [%.*s] block of %s file.", - COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); - } - break; - case 24: // FPALLOWWHENCHICKEN - if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) - { - k = atoi(word_buf); - inst_inf->fp_allow_when_chicken = (TbBool)k; - n++; - } - if (n < 1) - { - CONFWRNLOG("Couldn't read \"%s\" parameter in [%.*s] block of %s file.", - COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); - } - break; case ccr_comment: break; case ccr_endOfFile: diff --git a/src/creature_instances.c b/src/creature_instances.c index 88177db136..9d7b9bf879 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -127,6 +127,7 @@ const struct NamedCommand creature_instances_validate_func_type[] = { {"validate_target_non_idle", 11}, {"validate_target_takes_gas_damage", 12}, {"validate_target_requires_cleansing", 13}, + {"validate_source_while_frozen", 14}, {NULL, 0}, }; @@ -145,6 +146,7 @@ Creature_Validate_Func creature_instances_validate_func_list[] = { validate_target_non_idle, validate_target_takes_gas_damage, validate_target_requires_cleansing, + validate_source_while_frozen, NULL, }; @@ -413,11 +415,8 @@ void process_creature_instance(struct Thing *thing) SYNCDBG(19, "Starting for %s index %d instance %d", thing_model_name(thing), (int)thing->index, (int)cctrl->instance_id); if (cctrl->instance_id != CrInst_NULL && creature_under_spell_effect(thing, CSAfF_Freeze)) { - inst_inf = creature_instance_info_get(cctrl->instance_id); - if (!inst_inf->allow_while_frozen) - { - return; - } + //todo finish animatioon while frozen. + //return; } if (cctrl->inst_turn >= cctrl->inst_total_turns) { @@ -1205,6 +1204,56 @@ TbBool validate_source_generic return true; } +/** + * @brief Check if the given creature can cast the specified spell by examining general conditions. + * + * @param source The source creature + * @param target The target creature + * @param inst_idx The spell instance index + * @param param1 Optional 1st parameter. + * @param param2 Optional 2nd parameter. + * @return TbBool True if the creature can, false if otherwise. + */ +TbBool validate_source_while_frozen +( + struct Thing* source, + struct Thing* target, + CrInstance inst_idx, + int32_t param1, + int32_t param2 +) +{ + JUSTLOG("even get here"); + if ((source->alloc_flags & TAlF_IsControlled) != 0) + { + // If this creature is under player's control (Possession). + return false; + } + // We assume we usually don't want to overwrite the original instance. + struct CreatureControl* cctrl = creature_control_get_from_thing(source); + if (cctrl->instance_id != CrInst_NULL) { + SYNCDBG(15, "%s(%d) already has an instance %s.", thing_model_name(source), source->index, + creature_instance_code_name(cctrl->instance_id)); + return false; + } + + if (!creature_instance_is_available(source, inst_idx) || + !creature_instance_has_reset(source, inst_idx) || + creature_is_being_unconscious(source) || creature_is_dying(source) || + thing_is_picked_up(source) || creature_is_being_dropped(source) || + creature_is_being_sacrificed(source) || creature_is_being_summoned(source)) + { + return false; + } + + if (creature_is_being_tortured(source) || creature_is_kept_in_prison(source)) + { + return false; + } + + return true; +} + /** * @brief Check if the given creature can be the target of the specified spell by examining basic conditions. * @param source The source creature diff --git a/src/creature_instances.h b/src/creature_instances.h index 9c49c84f7c..e92edabeec 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -127,8 +127,6 @@ struct InstanceInfo { // Refer to creature_instances_search_targets_func_list uint8_t search_func; int32_t search_func_params[2]; - TbBool allow_while_frozen; - TbBool fp_allow_when_chicken; }; /******************************************************************************/ @@ -172,6 +170,7 @@ void script_set_creature_instance(ThingModel crmodel, short slot, int instance, TbBool validate_source_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_even_in_prison(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); +TbBool validate_source_while_frozen(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); @@ -186,6 +185,7 @@ TbBool validate_target_non_idle(struct Thing* source, struct Thing* target, CrIn TbBool validate_target_takes_gas_damage(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_requires_cleansing(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); + TbBool search_target_generic(struct Thing *source, CrInstance inst_idx, ThingIndex **targets, uint16_t *found_count, int32_t param1, int32_t param2); TbBool search_target_ranged_heal(struct Thing *source, CrInstance inst_idx, ThingIndex **targets, uint16_t *found_count, int32_t param1, int32_t param2); diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index 3842ae65b2..bb3bd145d7 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1878,14 +1878,6 @@ void gui_area_instance_button(struct GuiButton *gbtn) { disabled = true; } - else if (creature_under_spell_effect(ctrltng, CSAfF_Freeze)) - { - disabled = !inst_inf->allow_while_frozen; - } - else if (creature_under_spell_effect(ctrltng, CSAfF_Chicken)) - { - disabled = !inst_inf->fp_allow_when_chicken; - } else { disabled = false; diff --git a/src/packets.c b/src/packets.c index 4078ea9734..f4bfd34542 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1435,7 +1435,6 @@ void process_players_creature_control_packet_control(long idx) } if ((!creature_is_dying(cctng)) && (cctng->active_state != CrSt_CreatureUnconscious)) { - TbBool allowed; if ((pckt->control_flags & PCtr_LBtnRelease) != 0) { i = ccctrl->active_instance_id; @@ -1445,27 +1444,7 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - if (creature_under_spell_effect(cctng, CSAfF_Chicken)) - { - inst_inf = creature_instance_info_get(i); - allowed = inst_inf->fp_allow_when_chicken; - } - else - { - allowed = true; - } - if (allowed) - { - if (creature_under_spell_effect(cctng, CSAfF_Freeze)) - { - inst_inf = creature_instance_info_get(i); - allowed = inst_inf->allow_while_frozen; - } - if (allowed) - { - process_player_use_instance(cctng, i, pckt); - } - } + process_player_use_instance(cctng, i, pckt); } } else @@ -1489,18 +1468,7 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - if (creature_under_spell_effect(cctng, CSAfF_Freeze)) - { - allowed = inst_inf->allow_while_frozen; - } - else - { - allowed = true; - } - if (allowed) - { - process_player_use_instance(cctng, i, pckt); - } + process_player_use_instance(cctng, i, pckt); } } else @@ -1556,33 +1524,11 @@ void process_players_creature_control_packet_action(long plyr_idx) { if (creature_instance_is_available(thing,i) && creature_instance_has_reset(thing, pckt->actn_par1)) { - TbBool allowed; - TbBool frozen = creature_under_spell_effect(thing, CSAfF_Freeze); - TbBool chicken = creature_under_spell_effect(thing, CSAfF_Chicken); - if (frozen && chicken) - { - allowed = (inst_inf->allow_while_frozen && inst_inf->fp_allow_when_chicken); - } - else if (frozen) - { - allowed = inst_inf->allow_while_frozen; - } - else if (chicken) - { - allowed = inst_inf->fp_allow_when_chicken; - } - else - { - allowed = true; - } - if (allowed) - { i = pckt->actn_par1; process_player_use_instance(thing, i, pckt); if (plyr_idx == my_player_number) { instant_instance_selected(i); } - } } } break; From ad57ea4daa25f8bd9eb7557c8a6786695d2b1f0b Mon Sep 17 00:00:00 2001 From: Loobinex Date: Mon, 13 Apr 2026 00:05:09 +0200 Subject: [PATCH 74/81] Revert "Pushed doing this over ValidateSourceFunc" This reverts commit bbf8094a01236b7ef0a53a8945f277d60e8febd9. --- config/fxdata/creature.cfg | 21 ++++++++++++- src/config_creature.c | 28 ++++++++++++++++++ src/creature_instances.c | 59 ++++--------------------------------- src/creature_instances.h | 4 +-- src/frontmenu_ingame_tabs.c | 8 +++++ src/packets.c | 58 ++++++++++++++++++++++++++++++++++-- 6 files changed, 119 insertions(+), 59 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 62d43634d3..8eb66211fa 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -50,6 +50,10 @@ FPActionTime = 0 FPResetTime = 0 ; Instance is activated as soon as it's selected. FPInstantCast = 0 +; Instance can be used when frozen. +AllowWhileFrozen = 0 +; Instance can be used when under the Chicken spell in possession. +FPAllowWhenChicken = 0 ; How many game turns after using the instance creature can be spotted even if invisible. ForceVisibility = 0 ; Tooltip string ID, explaining what the instance does. @@ -256,6 +260,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -295,6 +300,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -314,6 +320,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -353,6 +360,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -372,6 +380,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -389,6 +398,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -544,6 +554,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -561,6 +572,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -580,6 +592,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -978,6 +991,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -997,6 +1011,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 +AllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1123,6 +1138,8 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 +AllowWhileFrozen = 1 +FPAllowWhenChicken = 1 ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 @@ -1144,6 +1161,8 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 +AllowWhileFrozen = 1 +FPAllowWhenChicken = 1 ForceVisibility = 30 TooltipTextID = 1068 SymbolSprites = 794 @@ -1153,7 +1172,7 @@ RangeMax = 3072 Properties = RANGED_BUFF SELF_BUFF NEEDS_TARGET PrimaryTarget = 6 Function = creature_cast_spell SPELL_CLEANSE 0 -ValidateSourceFunc = validate_source_while_frozen 2560 0 +ValidateSourceFunc = validate_source_generic 2560 0 ValidateTargetFunc = validate_target_requires_cleansing 32 0 SearchTargetsFunc = search_target_generic 0 0 diff --git a/src/config_creature.c b/src/config_creature.c index 57b4376d5c..a7289a1905 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -106,6 +106,8 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"SearchTargetsFunc", 20}, {"PostalPriority", 21}, {"NoAnimationLoop", 22}, + {"AllowWhileFrozen", 23}, + {"FPAllowWhenChicken", 24}, {NULL, 0}, }; @@ -1411,6 +1413,32 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; + case 23: // ALLOWWHILEFROZEN + if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) + { + k = atoi(word_buf); + inst_inf->allow_while_frozen = (TbBool)k; + n++; + } + if (n < 1) + { + CONFWRNLOG("Couldn't read \"%s\" parameter in [%.*s] block of %s file.", + COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); + } + break; + case 24: // FPALLOWWHENCHICKEN + if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) + { + k = atoi(word_buf); + inst_inf->fp_allow_when_chicken = (TbBool)k; + n++; + } + if (n < 1) + { + CONFWRNLOG("Couldn't read \"%s\" parameter in [%.*s] block of %s file.", + COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); + } + break; case ccr_comment: break; case ccr_endOfFile: diff --git a/src/creature_instances.c b/src/creature_instances.c index 9d7b9bf879..88177db136 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -127,7 +127,6 @@ const struct NamedCommand creature_instances_validate_func_type[] = { {"validate_target_non_idle", 11}, {"validate_target_takes_gas_damage", 12}, {"validate_target_requires_cleansing", 13}, - {"validate_source_while_frozen", 14}, {NULL, 0}, }; @@ -146,7 +145,6 @@ Creature_Validate_Func creature_instances_validate_func_list[] = { validate_target_non_idle, validate_target_takes_gas_damage, validate_target_requires_cleansing, - validate_source_while_frozen, NULL, }; @@ -415,8 +413,11 @@ void process_creature_instance(struct Thing *thing) SYNCDBG(19, "Starting for %s index %d instance %d", thing_model_name(thing), (int)thing->index, (int)cctrl->instance_id); if (cctrl->instance_id != CrInst_NULL && creature_under_spell_effect(thing, CSAfF_Freeze)) { - //todo finish animatioon while frozen. - //return; + inst_inf = creature_instance_info_get(cctrl->instance_id); + if (!inst_inf->allow_while_frozen) + { + return; + } } if (cctrl->inst_turn >= cctrl->inst_total_turns) { @@ -1204,56 +1205,6 @@ TbBool validate_source_generic return true; } -/** - * @brief Check if the given creature can cast the specified spell by examining general conditions. - * - * @param source The source creature - * @param target The target creature - * @param inst_idx The spell instance index - * @param param1 Optional 1st parameter. - * @param param2 Optional 2nd parameter. - * @return TbBool True if the creature can, false if otherwise. - */ -TbBool validate_source_while_frozen -( - struct Thing* source, - struct Thing* target, - CrInstance inst_idx, - int32_t param1, - int32_t param2 -) -{ - JUSTLOG("even get here"); - if ((source->alloc_flags & TAlF_IsControlled) != 0) - { - // If this creature is under player's control (Possession). - return false; - } - // We assume we usually don't want to overwrite the original instance. - struct CreatureControl* cctrl = creature_control_get_from_thing(source); - if (cctrl->instance_id != CrInst_NULL) { - SYNCDBG(15, "%s(%d) already has an instance %s.", thing_model_name(source), source->index, - creature_instance_code_name(cctrl->instance_id)); - return false; - } - - if (!creature_instance_is_available(source, inst_idx) || - !creature_instance_has_reset(source, inst_idx) || - creature_is_being_unconscious(source) || creature_is_dying(source) || - thing_is_picked_up(source) || creature_is_being_dropped(source) || - creature_is_being_sacrificed(source) || creature_is_being_summoned(source)) - { - return false; - } - - if (creature_is_being_tortured(source) || creature_is_kept_in_prison(source)) - { - return false; - } - - return true; -} - /** * @brief Check if the given creature can be the target of the specified spell by examining basic conditions. * @param source The source creature diff --git a/src/creature_instances.h b/src/creature_instances.h index e92edabeec..9c49c84f7c 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -127,6 +127,8 @@ struct InstanceInfo { // Refer to creature_instances_search_targets_func_list uint8_t search_func; int32_t search_func_params[2]; + TbBool allow_while_frozen; + TbBool fp_allow_when_chicken; }; /******************************************************************************/ @@ -170,7 +172,6 @@ void script_set_creature_instance(ThingModel crmodel, short slot, int instance, TbBool validate_source_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_source_even_in_prison(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); -TbBool validate_source_while_frozen(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_basic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_generic(struct Thing *source, struct Thing *target, CrInstance inst_idx, int32_t param1, int32_t param2); @@ -185,7 +186,6 @@ TbBool validate_target_non_idle(struct Thing* source, struct Thing* target, CrIn TbBool validate_target_takes_gas_damage(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); TbBool validate_target_requires_cleansing(struct Thing* source, struct Thing* target, CrInstance inst_idx, int32_t param1, int32_t param2); - TbBool search_target_generic(struct Thing *source, CrInstance inst_idx, ThingIndex **targets, uint16_t *found_count, int32_t param1, int32_t param2); TbBool search_target_ranged_heal(struct Thing *source, CrInstance inst_idx, ThingIndex **targets, uint16_t *found_count, int32_t param1, int32_t param2); diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index bb3bd145d7..3842ae65b2 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1878,6 +1878,14 @@ void gui_area_instance_button(struct GuiButton *gbtn) { disabled = true; } + else if (creature_under_spell_effect(ctrltng, CSAfF_Freeze)) + { + disabled = !inst_inf->allow_while_frozen; + } + else if (creature_under_spell_effect(ctrltng, CSAfF_Chicken)) + { + disabled = !inst_inf->fp_allow_when_chicken; + } else { disabled = false; diff --git a/src/packets.c b/src/packets.c index f4bfd34542..4078ea9734 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1435,6 +1435,7 @@ void process_players_creature_control_packet_control(long idx) } if ((!creature_is_dying(cctng)) && (cctng->active_state != CrSt_CreatureUnconscious)) { + TbBool allowed; if ((pckt->control_flags & PCtr_LBtnRelease) != 0) { i = ccctrl->active_instance_id; @@ -1444,7 +1445,27 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - process_player_use_instance(cctng, i, pckt); + if (creature_under_spell_effect(cctng, CSAfF_Chicken)) + { + inst_inf = creature_instance_info_get(i); + allowed = inst_inf->fp_allow_when_chicken; + } + else + { + allowed = true; + } + if (allowed) + { + if (creature_under_spell_effect(cctng, CSAfF_Freeze)) + { + inst_inf = creature_instance_info_get(i); + allowed = inst_inf->allow_while_frozen; + } + if (allowed) + { + process_player_use_instance(cctng, i, pckt); + } + } } } else @@ -1468,7 +1489,18 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { - process_player_use_instance(cctng, i, pckt); + if (creature_under_spell_effect(cctng, CSAfF_Freeze)) + { + allowed = inst_inf->allow_while_frozen; + } + else + { + allowed = true; + } + if (allowed) + { + process_player_use_instance(cctng, i, pckt); + } } } else @@ -1524,11 +1556,33 @@ void process_players_creature_control_packet_action(long plyr_idx) { if (creature_instance_is_available(thing,i) && creature_instance_has_reset(thing, pckt->actn_par1)) { + TbBool allowed; + TbBool frozen = creature_under_spell_effect(thing, CSAfF_Freeze); + TbBool chicken = creature_under_spell_effect(thing, CSAfF_Chicken); + if (frozen && chicken) + { + allowed = (inst_inf->allow_while_frozen && inst_inf->fp_allow_when_chicken); + } + else if (frozen) + { + allowed = inst_inf->allow_while_frozen; + } + else if (chicken) + { + allowed = inst_inf->fp_allow_when_chicken; + } + else + { + allowed = true; + } + if (allowed) + { i = pckt->actn_par1; process_player_use_instance(thing, i, pckt); if (plyr_idx == my_player_number) { instant_instance_selected(i); } + } } } break; From 5b7b9eda8d1c6523723f6933c04dde1b6aa1b696 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Mon, 13 Apr 2026 00:05:29 +0200 Subject: [PATCH 75/81] Revert "Renamed FPAllowWhileFrozen to AllowWhileFrozen" This reverts commit 64142395b63ea1f485daf16001def89e9e3c5689. --- config/fxdata/creature.cfg | 30 +++++++++++++++--------------- src/config_creature.c | 6 +++--- src/creature_instances.c | 2 +- src/creature_instances.h | 2 +- src/frontmenu_ingame_tabs.c | 2 +- src/packets.c | 8 ++++---- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 8eb66211fa..36cbd0f7d2 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -50,8 +50,8 @@ FPActionTime = 0 FPResetTime = 0 ; Instance is activated as soon as it's selected. FPInstantCast = 0 -; Instance can be used when frozen. -AllowWhileFrozen = 0 +; Instance can be used when frozen in possession. +FPAllowWhileFrozen = 0 ; Instance can be used when under the Chicken spell in possession. FPAllowWhenChicken = 0 ; How many game turns after using the instance creature can be spotted even if invisible. @@ -260,7 +260,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -300,7 +300,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -320,7 +320,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -360,7 +360,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -380,7 +380,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -398,7 +398,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -554,7 +554,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -572,7 +572,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -592,7 +592,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -991,7 +991,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -1011,7 +1011,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1138,7 +1138,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 FPAllowWhenChicken = 1 ForceVisibility = 10 TooltipTextID = 1067 @@ -1161,7 +1161,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 -AllowWhileFrozen = 1 +FPAllowWhileFrozen = 1 FPAllowWhenChicken = 1 ForceVisibility = 30 TooltipTextID = 1068 diff --git a/src/config_creature.c b/src/config_creature.c index a7289a1905..fb4b123669 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -106,7 +106,7 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"SearchTargetsFunc", 20}, {"PostalPriority", 21}, {"NoAnimationLoop", 22}, - {"AllowWhileFrozen", 23}, + {"FPAllowWhileFrozen", 23}, {"FPAllowWhenChicken", 24}, {NULL, 0}, }; @@ -1413,11 +1413,11 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; - case 23: // ALLOWWHILEFROZEN + case 23: // FPALLOWWHILEFROZEN if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) { k = atoi(word_buf); - inst_inf->allow_while_frozen = (TbBool)k; + inst_inf->fp_allow_while_frozen = (TbBool)k; n++; } if (n < 1) diff --git a/src/creature_instances.c b/src/creature_instances.c index 88177db136..f9bee49b69 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -414,7 +414,7 @@ void process_creature_instance(struct Thing *thing) if (cctrl->instance_id != CrInst_NULL && creature_under_spell_effect(thing, CSAfF_Freeze)) { inst_inf = creature_instance_info_get(cctrl->instance_id); - if (!inst_inf->allow_while_frozen) + if (!inst_inf->fp_allow_while_frozen) { return; } diff --git a/src/creature_instances.h b/src/creature_instances.h index 9c49c84f7c..939d3b64d4 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -127,7 +127,7 @@ struct InstanceInfo { // Refer to creature_instances_search_targets_func_list uint8_t search_func; int32_t search_func_params[2]; - TbBool allow_while_frozen; + TbBool fp_allow_while_frozen; TbBool fp_allow_when_chicken; }; diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index 3842ae65b2..9331b77a45 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1880,7 +1880,7 @@ void gui_area_instance_button(struct GuiButton *gbtn) } else if (creature_under_spell_effect(ctrltng, CSAfF_Freeze)) { - disabled = !inst_inf->allow_while_frozen; + disabled = !inst_inf->fp_allow_while_frozen; } else if (creature_under_spell_effect(ctrltng, CSAfF_Chicken)) { diff --git a/src/packets.c b/src/packets.c index 4078ea9734..dbef3df08b 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1459,7 +1459,7 @@ void process_players_creature_control_packet_control(long idx) if (creature_under_spell_effect(cctng, CSAfF_Freeze)) { inst_inf = creature_instance_info_get(i); - allowed = inst_inf->allow_while_frozen; + allowed = inst_inf->fp_allow_while_frozen; } if (allowed) { @@ -1491,7 +1491,7 @@ void process_players_creature_control_packet_control(long idx) { if (creature_under_spell_effect(cctng, CSAfF_Freeze)) { - allowed = inst_inf->allow_while_frozen; + allowed = inst_inf->fp_allow_while_frozen; } else { @@ -1561,11 +1561,11 @@ void process_players_creature_control_packet_action(long plyr_idx) TbBool chicken = creature_under_spell_effect(thing, CSAfF_Chicken); if (frozen && chicken) { - allowed = (inst_inf->allow_while_frozen && inst_inf->fp_allow_when_chicken); + allowed = (inst_inf->fp_allow_while_frozen && inst_inf->fp_allow_when_chicken); } else if (frozen) { - allowed = inst_inf->allow_while_frozen; + allowed = inst_inf->fp_allow_while_frozen; } else if (chicken) { From 4b0c3f877dbc3d8f1f743e55a1ffed347842bd73 Mon Sep 17 00:00:00 2001 From: Loobinex Date: Mon, 13 Apr 2026 00:25:10 +0200 Subject: [PATCH 76/81] Revert Freeze tortured creatures --- src/creature_graphics.c | 8 +------- src/creature_instances.c | 8 -------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/creature_graphics.c b/src/creature_graphics.c index ae183bce14..a782095fba 100644 --- a/src/creature_graphics.c +++ b/src/creature_graphics.c @@ -476,13 +476,7 @@ void update_creature_graphic_anim(struct Thing *thing) thing->rendering_flags &= ~(TRF_Transpar_Flags); } struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); - if (creature_under_spell_effect(thing, CSAfF_Freeze)) - { - update_creature_anim(thing, 0, inst_inf->graphics_idx); - } else - { - update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); - } + update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); } else if ((cctrl->frozen_on_hit != 0) || creature_is_dying(thing) || creature_under_spell_effect(thing, CSAfF_Freeze)) { diff --git a/src/creature_instances.c b/src/creature_instances.c index f9bee49b69..586b18eb3c 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -411,14 +411,6 @@ void process_creature_instance(struct Thing *thing) cctrl = creature_control_get_from_thing(thing); struct InstanceInfo* inst_inf; SYNCDBG(19, "Starting for %s index %d instance %d", thing_model_name(thing), (int)thing->index, (int)cctrl->instance_id); - if (cctrl->instance_id != CrInst_NULL && creature_under_spell_effect(thing, CSAfF_Freeze)) - { - inst_inf = creature_instance_info_get(cctrl->instance_id); - if (!inst_inf->fp_allow_while_frozen) - { - return; - } - } if (cctrl->inst_turn >= cctrl->inst_total_turns) { if (!cctrl->inst_repeat) From 2f8d50ec5dc085fb2d4e7c5bda6a6c5fa01b8cd2 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:35:43 +0100 Subject: [PATCH 77/81] Update creature_instances.c --- src/creature_instances.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/creature_instances.c b/src/creature_instances.c index 586b18eb3c..d37cf9b005 100644 --- a/src/creature_instances.c +++ b/src/creature_instances.c @@ -409,7 +409,6 @@ void process_creature_instance(struct Thing *thing) struct CreatureControl *cctrl; TRACE_THING(thing); cctrl = creature_control_get_from_thing(thing); - struct InstanceInfo* inst_inf; SYNCDBG(19, "Starting for %s index %d instance %d", thing_model_name(thing), (int)thing->index, (int)cctrl->instance_id); if (cctrl->inst_turn >= cctrl->inst_total_turns) { @@ -427,7 +426,7 @@ void process_creature_instance(struct Thing *thing) cctrl->inst_turn++; if (cctrl->inst_turn == cctrl->inst_action_turns) { - inst_inf = creature_instance_info_get(cctrl->instance_id); + struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); if (creature_instances_func_list[inst_inf->func_idx] != NULL) { SYNCDBG(18,"Executing %s for %s index %d.",creature_instance_code_name(cctrl->instance_id),thing_model_name(thing),(int)thing->index); From 61062077120c0f2f4e3fb369f25c8dd771b870a8 Mon Sep 17 00:00:00 2001 From: AdamPlenty <58278560+AdamPlenty@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:46:22 +0100 Subject: [PATCH 78/81] Re-fix casting animation when self-cleansing Freeze --- src/creature_graphics.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/creature_graphics.c b/src/creature_graphics.c index a782095fba..31b668f2d0 100644 --- a/src/creature_graphics.c +++ b/src/creature_graphics.c @@ -475,8 +475,11 @@ void update_creature_graphic_anim(struct Thing *thing) { thing->rendering_flags &= ~(TRF_Transpar_Flags); } - struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); - update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); + if (!creature_under_spell_effect(thing, CSAfF_Freeze)) + { + struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); + update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); + } } else if ((cctrl->frozen_on_hit != 0) || creature_is_dying(thing) || creature_under_spell_effect(thing, CSAfF_Freeze)) { From b7bfa0289e31d418220887cf37362793a27b322a Mon Sep 17 00:00:00 2001 From: Loobinex Date: Mon, 13 Apr 2026 00:53:32 +0200 Subject: [PATCH 79/81] Refix frozen torture anim --- src/creature_graphics.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/creature_graphics.c b/src/creature_graphics.c index 31b668f2d0..85a54f908a 100644 --- a/src/creature_graphics.c +++ b/src/creature_graphics.c @@ -458,7 +458,7 @@ void update_creature_graphic_anim(struct Thing *thing) TRACE_THING(thing); struct CreatureControl* cctrl = creature_control_get_from_thing(thing); struct CreatureModelConfig* crconf = creature_stats_get_from_thing(thing); - + struct InstanceInfo* inst_inf; if ((thing->size_change & TSC_ChangeSize) != 0) { thing->size_change &= ~TSC_ChangeSize; @@ -469,6 +469,7 @@ void update_creature_graphic_anim(struct Thing *thing) } else if (!creature_under_spell_effect(thing, CSAfF_Chicken)) { + inst_inf = creature_instance_info_get(cctrl->instance_id); if (cctrl->instance_id != CrInst_NULL) { if (cctrl->instance_id == CrInst_TORTURED) @@ -477,9 +478,12 @@ void update_creature_graphic_anim(struct Thing *thing) } if (!creature_under_spell_effect(thing, CSAfF_Freeze)) { - struct InstanceInfo* inst_inf = creature_instance_info_get(cctrl->instance_id); update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx); } + else + { + update_creature_anim(thing, 0, inst_inf->graphics_idx); + } } else if ((cctrl->frozen_on_hit != 0) || creature_is_dying(thing) || creature_under_spell_effect(thing, CSAfF_Freeze)) { From 28b35f225a23bdb989852c4e847d1ad6bd33453e Mon Sep 17 00:00:00 2001 From: Loobinex Date: Wed, 15 Apr 2026 16:38:13 +0200 Subject: [PATCH 80/81] Make sure you cannot target others while chickened --- config/fxdata/creature.cfg | 38 ++++++++++++++++++------------------- src/config_creature.c | 14 ++++++++------ src/creature_instances.h | 4 ++-- src/frontmenu_ingame_tabs.c | 4 ++-- src/packets.c | 17 +++++++++++------ src/thing_creature.c | 2 +- 6 files changed, 43 insertions(+), 36 deletions(-) diff --git a/config/fxdata/creature.cfg b/config/fxdata/creature.cfg index 36cbd0f7d2..1863a93740 100644 --- a/config/fxdata/creature.cfg +++ b/config/fxdata/creature.cfg @@ -50,10 +50,10 @@ FPActionTime = 0 FPResetTime = 0 ; Instance is activated as soon as it's selected. FPInstantCast = 0 -; Instance can be used when frozen in possession. -FPAllowWhileFrozen = 0 -; Instance can be used when under the Chicken spell in possession. -FPAllowWhenChicken = 0 +; Instance can be used when frozen in possession. Only works when targetting self. +FPAllowSelfCastWhileFrozen = 0 +; Instance can be used when under the Chicken spell in possession. Only works when targetting self. +FPAllowSelfCastWhenChicken = 0 ; How many game turns after using the instance creature can be spotted even if invisible. ForceVisibility = 0 ; Tooltip string ID, explaining what the instance does. @@ -260,7 +260,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 228 SymbolSprites = 408 @@ -300,7 +300,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 230 SymbolSprites = 412 @@ -320,7 +320,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 248 SymbolSprites = 414 @@ -360,7 +360,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 200 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 239 SymbolSprites = 418 @@ -380,7 +380,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 3 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 10 TooltipTextID = 240 SymbolSprites = 420 @@ -398,7 +398,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 500 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 3 TooltipTextID = 236 SymbolSprites = 422 @@ -554,7 +554,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 100 TooltipTextID = 242 SymbolSprites = 434 @@ -572,7 +572,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 250 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 1 TooltipTextID = 243 SymbolSprites = 436 @@ -592,7 +592,7 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 150 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 0 TooltipTextID = 232 SymbolSprites = 438 @@ -991,7 +991,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 600 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1080 SymbolSprites = BIRD_SPELL @@ -1011,7 +1011,7 @@ FPTime = 6 FPActionTime = 5 FPResetTime = 190 FPInstantCast = 1 -FPAllowWhileFrozen = 1 +FPAllowSelfCastWhileFrozen = 1 ForceVisibility = 30 TooltipTextID = 1081 SymbolSprites = SPIDERLING_SPELL @@ -1138,8 +1138,8 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 1 -FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 1 +FPAllowSelfCastWhileFrozen = 1 +FPAllowSelfCastWhenChicken = 1 ForceVisibility = 10 TooltipTextID = 1067 SymbolSprites = 798 @@ -1161,8 +1161,8 @@ FPTime = 5 FPActionTime = 3 FPResetTime = 300 FPInstantCast = 0 -FPAllowWhileFrozen = 1 -FPAllowWhenChicken = 1 +FPAllowSelfCastWhileFrozen = 1 +FPAllowSelfCastWhenChicken = 1 ForceVisibility = 30 TooltipTextID = 1068 SymbolSprites = 794 diff --git a/src/config_creature.c b/src/config_creature.c index fb4b123669..156283191c 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -106,8 +106,8 @@ const struct NamedCommand creaturetype_instance_commands[] = { {"SearchTargetsFunc", 20}, {"PostalPriority", 21}, {"NoAnimationLoop", 22}, - {"FPAllowWhileFrozen", 23}, - {"FPAllowWhenChicken", 24}, + {"FPAllowSelfCastWhileFrozen", 23}, + {"FPAllowSelfCastWhenChicken", 24}, {NULL, 0}, }; @@ -1016,6 +1016,8 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi inst_inf->validate_target_func_params[0] = 0; inst_inf->validate_target_func_params[1] = 0; inst_inf->postal_priority = 0; + inst_inf->fp_allow_self_cast_while_frozen = 0; + inst_inf->fp_allow_self_cast_when_chicken = 0; } } instance_desc[INSTANCE_TYPES_MAX - 1].name = NULL; // must be null for get_id @@ -1413,11 +1415,11 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; - case 23: // FPALLOWWHILEFROZEN + case 23: // FPALLOWSELFCASTWHILEFROZEN if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) { k = atoi(word_buf); - inst_inf->fp_allow_while_frozen = (TbBool)k; + inst_inf->fp_allow_self_cast_while_frozen = (TbBool)k; n++; } if (n < 1) @@ -1426,11 +1428,11 @@ TbBool parse_creaturetype_instance_blocks(char *buf, long len, const char *confi COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname); } break; - case 24: // FPALLOWWHENCHICKEN + case 24: // FPALLOWSELFCASTWHENCHICKEN if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0) { k = atoi(word_buf); - inst_inf->fp_allow_when_chicken = (TbBool)k; + inst_inf->fp_allow_self_cast_when_chicken = (TbBool)k; n++; } if (n < 1) diff --git a/src/creature_instances.h b/src/creature_instances.h index 939d3b64d4..2775ec1337 100644 --- a/src/creature_instances.h +++ b/src/creature_instances.h @@ -127,8 +127,8 @@ struct InstanceInfo { // Refer to creature_instances_search_targets_func_list uint8_t search_func; int32_t search_func_params[2]; - TbBool fp_allow_while_frozen; - TbBool fp_allow_when_chicken; + TbBool fp_allow_self_cast_while_frozen; + TbBool fp_allow_self_cast_when_chicken; }; /******************************************************************************/ diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index 9331b77a45..9ed82de989 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1880,11 +1880,11 @@ void gui_area_instance_button(struct GuiButton *gbtn) } else if (creature_under_spell_effect(ctrltng, CSAfF_Freeze)) { - disabled = !inst_inf->fp_allow_while_frozen; + disabled = inst_inf->fp_allow_self_cast_while_frozen == false; } else if (creature_under_spell_effect(ctrltng, CSAfF_Chicken)) { - disabled = !inst_inf->fp_allow_when_chicken; + disabled = inst_inf->fp_allow_self_cast_when_chicken == false; } else { diff --git a/src/packets.c b/src/packets.c index e3bf0424b5..9f44d0ccec 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1323,6 +1323,7 @@ void process_players_creature_control_packet_control(long idx) struct Thing* cctng = thing_get(player->controlled_thing_idx); struct Packet* pckt = get_packet_direct(player->packet_num); struct CreatureControl* ccctrl = creature_control_get_from_thing(cctng); + ThingIndex target_idx; if (can_process_creature_input(cctng)) { long speed_limit = get_creature_speed(cctng); @@ -1439,10 +1440,11 @@ void process_players_creature_control_packet_control(long idx) { if (creature_instance_has_reset(cctng, i)) { + target_idx = get_human_controlled_creature_target(cctng, i, pckt); if (creature_under_spell_effect(cctng, CSAfF_Chicken)) { inst_inf = creature_instance_info_get(i); - allowed = inst_inf->fp_allow_when_chicken; + allowed = inst_inf->fp_allow_self_cast_when_chicken & (cctng->index == target_idx); } else { @@ -1453,7 +1455,7 @@ void process_players_creature_control_packet_control(long idx) if (creature_under_spell_effect(cctng, CSAfF_Freeze)) { inst_inf = creature_instance_info_get(i); - allowed = inst_inf->fp_allow_while_frozen; + allowed = inst_inf->fp_allow_self_cast_while_frozen & (cctng->index == target_idx); } if (allowed) { @@ -1475,6 +1477,7 @@ void process_players_creature_control_packet_control(long idx) // Button is held down - check whether the instance has auto-repeat i = ccctrl->active_instance_id; inst_inf = creature_instance_info_get(i); + target_idx = get_human_controlled_creature_target(cctng, i, pckt); if ((inst_inf->instance_property_flags & InstPF_RepeatTrigger) != 0) { if (ccctrl->instance_id == CrInst_NULL) @@ -1485,7 +1488,8 @@ void process_players_creature_control_packet_control(long idx) { if (creature_under_spell_effect(cctng, CSAfF_Freeze)) { - allowed = inst_inf->fp_allow_while_frozen; + target_idx = get_human_controlled_creature_target(cctng, i, pckt); + allowed = inst_inf->fp_allow_self_cast_while_frozen & (cctng->index == target_idx); } else { @@ -1553,17 +1557,18 @@ void process_players_creature_control_packet_action(long plyr_idx) TbBool allowed; TbBool frozen = creature_under_spell_effect(thing, CSAfF_Freeze); TbBool chicken = creature_under_spell_effect(thing, CSAfF_Chicken); + ThingIndex target_idx = get_human_controlled_creature_target(thing, i, pckt); if (frozen && chicken) { - allowed = (inst_inf->fp_allow_while_frozen && inst_inf->fp_allow_when_chicken); + allowed = (inst_inf->fp_allow_self_cast_while_frozen & inst_inf->fp_allow_self_cast_when_chicken) && (thing->index == target_idx); } else if (frozen) { - allowed = inst_inf->fp_allow_while_frozen; + allowed = inst_inf->fp_allow_self_cast_while_frozen & (thing->index == target_idx); } else if (chicken) { - allowed = inst_inf->fp_allow_when_chicken; + allowed = inst_inf->fp_allow_self_cast_when_chicken & (thing->index == target_idx); } else { diff --git a/src/thing_creature.c b/src/thing_creature.c index 7e85b04d6c..6efedcc1ce 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -3903,7 +3903,7 @@ ThingIndex get_human_controlled_creature_target(struct Thing *thing, CrInstance if ((inst_inf->instance_property_flags & InstPF_RangedBuff) == 0 || ((packet != NULL) && (packet->additional_packet_values & PCAdV_CrtrContrlPressed) != 0)) { - // If it doesn't has RANGED_BUFF or the Possession key (default:left shift) is pressed, + // If it doesn't have RANGED_BUFF or the Possession key (default:left shift) is pressed, // cast on the caster itself. return thing->index; } From 0caf072de07f12bca5923b8ff026a687a473c96c Mon Sep 17 00:00:00 2001 From: Loobinex Date: Fri, 17 Apr 2026 20:40:04 +0200 Subject: [PATCH 81/81] French tweak snuck in --- lang/gtext_fre.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/gtext_fre.po b/lang/gtext_fre.po index 161ce84f93..d5eb043d06 100644 --- a/lang/gtext_fre.po +++ b/lang/gtext_fre.po @@ -2766,10 +2766,10 @@ msgid "" "can be rotated. Disable the warp effect for clean lines. Forced perspective " "can only be rotated 90 degrees and changes the viewing angle. LMB toggle." msgstr "" -"Type d'affichage: Alterne entre deux types de vue de la perspective. La vue " -"par défaut a des murs tordus et permet la rotation libre. Désactivez l'effet " +"Type d'affichage: Alterne entre les vues en perspective. La vue " +"par défaut a des murs tordus et permet une rotation libre. Désactivez l'effet " "de torsion pour des lignes droites. La vue forcée change l'angle de vision " -"et ne peut faire que des rotations à 90 degrés. Alterner avec le bouton " +"et ne peut pivoter que par rotations de 90 degrés. Alterner avec le bouton " "gauche de la souris." #: guitext:315