Jump to content

kjeron

Members
  • Posts

    485
  • Joined

  • Last visited

Posts posted by kjeron

  1. On 7/31/2022 at 6:05 AM, Luke said:

    @kjeron You remember this...?

    Apparently, polymorphing into a Giant Troll ("spin154.spl" or Cloak of the Sewers) will get you stuck in place 😕...

    However, setting `personal_space` to 3 (or any other value...?) in "trollall.itm" (via op342) does nothing... Changing animation to "shtroll.cre" does nothing too...

    Do you have any other suggestion...?

    I've not been able to reproduce it, but that would have to be a different issue - those trolls already have personal space of 3.

  2. A creature naturally loses 2 morale whenever:

    • its health drops below 50%
    • its health drops below 25%
    • an ally dies (pc's likely detect only party members, while everyone else likely uses SPECIFICS group)
    • ? ? ?

    But only if it is not currently suffering from morale failure.

    A poison/regen combo properly staggered (not hitting at the same time) can cause continuous morale loss:

    With 40 MaxHP:  20HP -> 19HP (-2 morale) -> 20HP -> 19HP (-2 morale) -> 20HP -> 19HP (-2 morale) -> 20HP -> 19HP (-2 morale) etc...

    Morale loss doesn't have lower bounds checking (or likely upper bounds checking).  1 - 2 = 25 (like the old rod of terror), but normally only creature's with a morale break of 0 (immune) would notice it, since anything else would already have morale failure. However, manual changes to morale (with op23) can cause the same issue to any creature since it still applies during morale failure.

    Morale Recovery is in seconds.

    There is no way to direct way to detect morale failure, nor any way to detect the type of morale failure (panic, berserk, run away), nor do they have any direct relation to the similar opcodes (3, 4, 24, 245, 246, 247) or STATEs.

    Morale Failure disables a creature's scripts, which is why it could not detect it's morale, or anything for that matter.

    Applying op23 (BG1 mode) with timing mode 1 (and possibly others) applies the amount for each instance already on the creature, including itself.

    • Your first applies 2x (itself and itself). (-6)
    • Your second applies 3x (itself, itself, and the first one). (-9, total of -15)
    • Your fourth applies 4x (itself, itself, the second one, and the first one). (-12, total of -27)
    • Always use timing mode 0 (no duration) to avoid this (with BG1 mode).
  3. 2 hours ago, Luke said:

    As you can see, there is something wrong with Hasted/Slowed targets 😕... Do you have an explanation for that...?

     

    Haste/Slow do not impose a direct 2x / 0.5x on frequency effects (25/78/98/272).  The last two posts in this thread explain it nicely for haste.

    • x/2-3 seconds triggers 3x times
    • x/4-7 seconds triggers 4x times
    • x/8-15 seconds triggers 5x times
    • etc...

    Final multiplier for Haste = 2+RoundDown(Log2 (Original Frequency))

    And each trigger happens at half the frequency from the previous, then repeats from the original frequency:

    So an 8 second frequency would trigger at: 4, 6, 7, 7.5, 8, 12, 14, 15, 15.5, 16, 20, 22, 21, 21.5, 22, (+4, +2, +1, +0.5, +0.5)

    Slow likely has a similar mechanic, to the point that sometimes it makes no difference.

  4. 3 hours ago, CamDawg said:
    • Poison immunity was blocking slow on mustard jelly attacks

    I do think that's intended...from their PnP entry:

    Quote

    ...Those near the jelly must roll a saving throw vs. poison each round. Those who fail the saving throw become lethargic and move at half-speed, due to the effects of the vapor...

     

  5. 5 hours ago, Luke said:

    As you can see by looking at "class.ids", unlike class #255, class #0 does not exist (what NearInfinity labels as `0|None` is just the default value, not an actual/existing "class.ids" identifier...

    Like many hardcoded entries, it is omitted from the label file, but it does exist.

    5 hours ago, Luke said:

    If a modder wanted to add a brand new class value, he should be able to use index #0 (i.e., the first available unused index)... And that's why all existing 0s should be changed to 255...

    You cannot use value "0" for custom EA/GENERAL/CLASS/RACE/ALIGNMENT/GENDER values.

    "0" is hardcoded as "Any", as in:

    See([0.0.0.0.0.0])

    Will return true for any visible creature.

    Now if there is a reason to specifically target creatures with "NO_CLASS" or "NO_RACE", then assigning 255 makes sense, otherwise it doesn't matter whether they have 0 or 255.  AFAIK they are not referenced in any scripts/dialogues, so if anything the "NO_CLASS" and "NO_RACE" entries should be removed to free up space, and their creatures remapped to "0".

  6.  

    • Whirlwind won't function correctly regardless of what's done to it right now.
    • #cofear, spin132, spin139, and spin161 have nothing that stacks, which leads me to believe op206 is there to prevent a creature from being affected too often (for balance reasons).
    • Writhing Fog is the same issue in BG1/2, no clue why Beamdog implemented it that way, as it came with the Shaman class, not the original game.
    • Produce Fire is setup that way so that any creature entering the area over the next round takes the damage.  Changing it to a single repetition may as well remove the frequency entirely.
    • Walls (rectangular AoEs) automatically trigger every tick, their frequency only determines the overall duration.  While you can make them respect their frequency, it would make far too easy for creatures to safely run through them between triggers.
  7. 3 hours ago, jmerry said:

    This seems like as good a place to mention it as anywhere - I ran into another spell with a nonstandard effect combination. Mimic Glue (SPIN914 in BG2EE) imposes paralysis (109), a "Held" portrait icon, and a Grease overlay (158). Plus some shorter duration lighting effects.

    Obviously, the general update to immunities should cover at least some some of this. Paralysis immunity should block the glue now. Grease immunity ... I don't think that's being separated out, and it's not obvious to me whether it should block the effect. Removing paralysis should clear the whole thing too, which may require an additional update.

    That doesn't sound like a paralysis effect at all though.  Should probably be treated same as the Bigby's spells.

  8. 3 hours ago, Luke said:

    Separately, what can you tell me about their memorized spells (2x Magic Missile, 1x Stinking Cloud, 1x Melf's Acid Arrow, 1x Agannazar's Scorcher, 1x Ghost Armor, 1x Lightning Bolt)? Intended or not? I mean:

    1. unless I'm missing something, PnP states nothing about them being able to cast such spells
    2. more importantly, they're not scripted to cast them (see "nishrusu.bcs"), so it might be another copy/paste issue...

    It's a relatively common, unused spell setup. Djinni/Genie have it as well, and most of them are not scripted to cast any.

  9. 1 hour ago, Luke said:

    This is because those opcodes would only consider the resource the op146 is on, right...? But that would be a problem because the real effects are on the SPL cast by that op146 effect...

    How bad is this in practice...? I mean, as far as the base game is concerned, we only have op230 effects targeting SPELLPROTECTIONS... And SPELLPROTECTIONS are not supposed to cast subspells, so everything should be fine... The problem is when some other mod uses a different value... (this is something that should be noted in the final docs...)

    It's because those two opcodes only remove a single spell resource per use, and the main/sub spells will inevitably have different filenames.  AFAIK not a base game issue.

  10. 8 hours ago, DavidW said:

    I don't think there's any particular advantage in doing so, not least because if you did, the extracted blocks indeed need to conform to a constraint they wouldn't otherwise have to conform to. (But persuade me otherwise, I could be missing something.)

    Power on the mainspell for reflection.

    Power on the subspell for opcodes 220/221.  I would also include opcodes 229/230, except using separate subspells already breaks them.

  11. Sword of Balduran however does have such an inconsistency. It has a base +1 Enchantment, it should be 0.  The only enchantment should be vs. Lycanthropes.

    If it were possible, it's [Magical, Silver, Cold-Iron] attributes should also ONLY apply vs. Lycanthropes.  It's not magical, just gold.

    The description ( "This ornate but poorly balanced weapon was found within the wreck of Balduran's ship. Gold weapons are not known to be useful in combat..." ) implies it to be some manner of ceremonial weapon, only useful because it's made of gold ( "legends say that only weapons forged of gold can harm such dread creatures as the loup garou." ).

  12. System-pausing is broken in multiplayer (such as when creating a Sequencer/Contingency), even when pausing is allowed in MP rules.  I don't really know why.

    The simplest way to solve this, is to copy one of the normal sequencer activation subspells (such as SPWI420D.SPL) that would accompany a sequencer, that are automatically granted when you create the sequencer.  Rename it (keep the "D" suffix) and the activation resource for your sequencer, and switch the ability target type to "7", so it cannot be interrupted or target others.  In multiplayer, you would have to manually activate the sequencer afterwards, as with normal sequencers.

    Then add an effect to remove that spell to each of the spells that could be stored in that sequencer (this is to automatically remove that spell in Single-player, where it would just clutter up the interface).

  13. 41 minutes ago, CamDawg said:

    I don't think this is as clear-cut. I like reflecting spells, but on the other hand I don't want spells to which I'm otherwise immune to burn through, say, my Spell Trap. (And before anyone says it, yes, there are times when it would be beneficial to let otherwise ineffective spells hit the Spell Trap too.) In a tabletop session, this kind of flexibility is possible--since we don't have that here, we have to pick one or the other.

    Personally I'm willing to make that tradeoff so that my protections don't get wasted on stuff to which I'm already immune. I honestly have no idea if I'm in a minority or majority on this opinion, and I think it's something worth more discussion.

    The issue isn't about when you are immune, but when the original caster should be immune.

    If those effects don't get reflected, then they will not protect the original caster when they should.

  14. Increment values don't update until after the effect stack has cleared, likely until the following tick.

    Set Value/% update immediately, but ignore any pre-existing increment bonuses until the following tick.

    The 6 Saving Throw modifier opcodes have an additional mode, "Increment Instantly", which do just that, but it's a semi-recent addition and AFAIK no other opcode has such.

    For damage resistance, you are better off setting the value to 0, as any negative increment could result in negative resistance.

  15. On 5/7/2022 at 2:23 PM, subtledoctor said:

    On @kjeron's advice I set up a thing where the Targeted Simulacrum spell cast a subspell that permanently applied a repeating effect, which casts a subspell with op72 Change AI Type -> "ally" and op241 Control Creature -> "dire charmed, neutral, no text" and then quickly canceled the repeating effect on the target. In principle, since the repeating effect is applied with timing mode 9, the simulacrum should inherit it and be affected by the op72 and op241 effects within a second or two, while the target being cloned should have the effect canceled before it is applied. In practice, this was utterly unreliable and in fact more often left me with a charmed target and a hostile simulacrum.

    I posted a cleaner solution (to a similar problem) here for Mislead.  No spellstate needed.

  16. 4 hours ago, subtledoctor said:

    For a character higher than 20th level, find the Improvement Rate for the character's group in Table 54. There you'll find the number of levels a character must advance to reduce his THAC0 by 1 (or more) points. Calculate the character's THAC0 according to his level.

    But then it later lists "THAC0 limits" for each class group, with those limits being the same as their level 20 values (Wa:1, P:8, R:11, Wi:14).

    And later still outright states, at least for Warriors: "Although their THAC0 ceases to improve once they reach level 20, ... (hits points and proficiencies) ...

    9 hours ago, suy said:

    OK, so I'm not sure if I got what you mean, but if I did, it would make some sense:

    • Warriors progress from 20 to 0, so they improve 20.
    • Rogues do so at half the pace, so they improve by 10, and cap at 10 (20-10=10).
    • Priests do so at 2/3 and Wizards at 1/3, with the one third being ceiling(20/3.0)=7, hence they end at 6 and 13 respectively (20-14 and 20-7).

    The key here is: why should it be rounded up? 🙂 Or just rounded to the nearest integer, which yields the same value.

    It doesn't feel wrong, but it doesn't feel entirely right either. Normally when explaining the rules the phrase "caps at level X" is used often, so I was looking for an explanation based on level.

    There is no rounding.  Priests do not get [1 -> 0 -> 1], [1 -> 1 -> 0], or [0 -> 1 -> 1].  They get [2 -> 0 -> 0].

    Warriors progress every level. Rogues progress every other/odd level. Priests progress every 3rd level (by 2). Wizards progress every 3rd level (by 1).

    The Bioware devs gave every class their next would-be point of progression after level 20.  For Warriors and Rogues that is level 21, for Priests and Wizards it is level 22.

  17. 6 hours ago, Luke said:

    Yes, some rows related to alignment check are indeed bugged (108 is fine though...)

    No, it's the newly added (arbitrary) header descriptions that are incorrect for the alignment rows, not the checks.

    • Row 33 = (NOT BIT1 = Not NEUTRAL or EVIL) = Alignment=GOOD
    • Row 34 = (HAS BIT1 = Is NEUTRAL or EVIL) = Alignment=NOTGOOD
    • Row 35 = (NOT BIT0 = Not GOOD or EVIL) = Alignment=...NEUTRAL
    • Row 36 = (HAS BIT0 = Is GOOD or EVIL) = Alignment=...NOTNEUTRAL
    • Row 37 = EVIL
    • Row 38 = NOTEVIL
    • Row 59 = (NOT BIT5 = Not CHAOTIC or NEUTRAL) = Alignment=LAWFUL
    • Row 60 = (HAS BIT5 = Is CHAOTIC or NEUTRAL) = Alignment=NOTLAWFUL
    • Row 61 = CHAOTIC
    • Row 62 = NOTCHAOTIC

    These are how they are used, how they were listed before those descriptions were added, and their listing from IWD1/IWD2.

    i.e Unholy Blight doesn't affect (324) row 34 (NOTGOOD). (only affects GOOD creatures)

  18. 2 hours ago, Luke said:

    Having said that, I'm not sure why the `duration` field is set to 180... Is this correct...?

    SPIN823 normally gives SPIN822 back after a 180s delay.  This way SPIN822 is blocked for 180s rather than removed and given back later, as it seems like that process got interrupted on occasion (people complaining about permanently losing the ability).

    2 hours ago, Luke said:

    OK, some final comments / questions (before committing):

    • [bg2ee] Cloak of the Sewers, Mustard Jelly form
    • [sod] SHAPECHANGE_MIND_FLAYER
    • [bgeeWILD_SURGE_POLYMORPH_SPIRIT_WOLF

    No arguments.

    2 hours ago, Luke said:
    • Slayer Change / IWDEE Druid Shapeshift Heal: shouldn't this healing be applied by opcode #18 (p2=0 | update both current and max HP) in the ITM file (as equipped effect)...?
      • In so doing, it can act as temporary bonus hit points if the caster is already at full health...

    As an equipped effect that would heal them every time you load the game with it active.

    2 hours ago, Luke said:
    • I must admit it is still not clear to me the following block
        Reveal hidden contents
      COPY_EXISTING_REGEXP	~^.+\.\(spl\|itm\)$~	override
      	PATCH_IF	!VARIABLE_IS_SET	$POLYFORM_abort(~%SOURCE_RES%~)	BEGIN
      		LPF	CLONE_EFFECT	INT_VAR	silent = 1	match_opcode = 111	opcode = 326	parameter2 = $splprot(~POLYMORPH=1~)	timing = 0	duration = 0	STR_VAR	resource = ~SPINHUMW~	END
      		END
      	BUT_ONLY
      END

       

    It patches all non-polymorph spells/items (Flame Blade, MMM, Shillelagh, etc...) that use opcode 111, to ensure things like Slayer damage get removed.

    2 hours ago, Luke said:
    • Assuming it's only relevant when a contingency (since op135 automatically disables arcane / divine spell casting) with, say, Phantom Blade triggers while you're polymorphed (under the effects of op135, p2=0):

    Contingency, Sequencer, or Item activation, yes.

    Non-polymorph Weapon-Creation spells cast SPINHUMW, which casts SPINHUMR while blocking it's first EFF (op135), but not the rest.  It has to block the op135 EFF, because otherwise op135 would remove the Magical Weapon that is being created by the spell.  If this wasn't working, your new Magical Weapon would disappear immediately.  The new magical weapon will terminate the polymorph on it's own, as it replaces the polymorph weapon.

    Slayer Change (SPIN823) casts SPINHUMS, which casts SPINHUMR while blocking it's second EFF (op312->SPIN823), as again it would remove all the effects of SPIN823 that are about to be applied.  SPIN823 has it's own leading op321 to prevent stacking itself.

  19. 45 minutes ago, DavidW said:

    If this is for FPEE, you don’t need to bother with the EVAL anyway: we’re using AUTO_EVAL_STRINGS.

    It was code I already had, I've been ripping unrelated bits of code out (while trying not to break it).  I don't use AUTO_EVAL_STRINGS, it's poorly documented, not universal, and doesn't eliminate EVAL entirely.  Only some variables are affected by it, and only for a single level of EVAL.

    Just now, Luke said:
    • Excluding the fact that op206's feedback string is bugged as of now, String #26011 is "There was leather hide found, and tannin was smelled on the killer!". Guess you meant some other strref...?

    I never got around to looking up/making the correct string since it wasn't working.

    Just now, Luke said:
    • PATCH_IF $x(4) = 3 BEGIN (when iterating over array "slayer")
      • I mean, that's certainly true since it is preceded by "PATCH_IF $x(4) != 3 BEGIN", so I'm not sure about the intent here...
    • PATCH_IF !IS_AN_INT $x(2) BEGIN (~alter_poly_item~)

      • This should probably be skipped when you're iterating over array ~slayer~, shouldn't it? Otherwise you'll grant protection against non-existing resources...

    Just more sloppy code removal.  The first became redundant, the second should skip.

  20. SPINHUM doesn't exist in every game.

    squirrel=1, $x(15), $X(12), $x(7) -> those are old values didn't get updated when I removed unrelated code, your corrections are accurate.

    The untyped/unknown damage type is to avoid screwing around with the player's damage resistance, using something they cannot prevent.

    IWDEE heal:

    Quote

    There is still some extra code that doesn't belong (namely altering of the IWDEE healing and Slayer damage scaling)

    1 hour ago, Luke said:
    • arrays ~SPWI416~ and ~SPWI916~ appear to be empty/uninitialized (when launching function ~alter_poly_spell~)
      • First of all, ~array~ is not part of function definition

    Only reason for a variable to be in the function definition is if you need it to have a default value. Those arrays are set by this line:

    SPRINT    $ $x(2)(~%resource%~ ~%idx%~) $item(~~)

    Only the %idx% part of it is unused.

  21. 2 hours ago, Luke said:

    So basically effect order is irrelevant...? 

    Partially.  Applying the removal and then new effect at the same time (timing) is not sufficient, some delay is necessary.

    2 hours ago, Luke said:

    Regarding your code:

    • things like $res(~~) and $SOURCE(RES) are those hidden array constructs, right?
    • Override Creature Size: "3" // Otherwise transforming into a larger creature can result in being immediately stuck, even in wide open areas.

      • If I recall correctly, this used to be an op135 bug during v2.6 beta (where it used to create impassable tiles). Is it still the case in the stable version...? Asking because that will certainly interfere with op318/324/326 checking for Circle Size...

    • SPRINT $ $x(2)(~%resource%~ ~%idx%~) $item(~~)

      • Unless I'm missing something, ~idx~ appears to be uninitialized...? I'm not sure what you're trying to do / overwrite here...

    $res(~~) and $SOURCE(RES) are just shortcuts to avoid requiring an EVAL.  Functions will automatically evaluate an array construct for a string variable.

    under a functions STR_VAR: $res(~~) == EVAL ~%res_%~,   $SOURCE(RES) == EVAL ~%SOURCE_RES%~

    I don't know whether the size issue was fixed or not.

    The references to %idx% are for unrelated code, just forgot to prune all of them.

  22. @Luke

    Timing=4,Duration=0 is not the same as Timing=0/1,Duration=0.  The latter is instant, the former is not.

    The first op146 needs to be instant (not timing=4) - it removes any old polymorph.

    resource  = SPIN823 (or whatever spell will contain the slayers delayed damage and save disable effects.)

    Cloak of the sewers has no overall expiration, so no.  Making it impossible to remove the cloak while using one of it's polymorphs isn't practical, nor would making it's polymorphs revert when you unequipped it.  Like all activated magical items, once it's activated you are free to discard the item.

    Nothing goes in 7eyes.2da.  parameter2 would be "-1".

    Op335 has a similar issue as op135 with regards to applying the effect while another is already active:  If you apply op335 while the specified spellstate is already set (either by op328 or another op335), then the new op335 will NOT be applied.  A timing=4,Duration=0 delay between removing the old (polymorph/spellstate) and applying the new will bypass the issue for both opcodes.

    The op326/101 pair would go on spells like Flame Blade:  op101(135) -> op326(SPINHUM) -> op111(FBLADE)                                                                                                                    However I've done it slightly differently now:

    Spoiler

    This is what I currently have.  There is still some extra code that doesn't belong (namely altering of the IWDEE healing and Slayer damage scaling)

    		CLEAR_ARRAYS
    	//	--------------------------------------------------------------------------------------------------------------------------------------------------------------------------	//
    		DEFINE_ACTION_FUNCTION	ADD_SPLSTATE	STR_VAR	label = ~~	new_ids = ~*~	s = EVAL ~ %TAB%~	w = EVAL ~ %TAB%%WNL%$~	RET	new_ids		BEGIN	SILENT
    			ACTION_MATCH	1	WITH	ANY (~%label%~ STR_EQ ~~)	BEGIN	FAIL	~Missing Spell State label~	END
    				ANY	!(~%label%~ STRING_CONTAINS_REGEXP ~[ %TAB%%WNL%]~)	BEGIN	FAIL	~Spell State lable cannot have whitespace~	END
    				ANY	FILE_CONTAINS_EVALUATED	(~SPLSTATE.IDS~	~^\(0x[0-9a-f]+\|[0-9]+\)[%s%]+%label%[%w%]~)	BEGIN
    					COPY_EXISTING - ~SPLSTATE.IDS~	override	REPLACE_EVALUATE	~^\(0x[0-9a-f]+\|[0-9]+\)[%s%]%label%[%w%]~	BEGIN	SET	new_ids = MATCH1	END	~~	END
    			DEFAULT
    				COPY_EXISTING	~SPLSTATE.IDS~	override
    					DEFINE_ARRAY	x	BEGIN	~~ 1 2 3 4 5 6 7 8 9 A B C D E F END	DEFINE_ARRAY	y	BEGIN	0 1 2 3 4 5 6 7 8 9 A B C D E F END
    					FOR	(i = 0; i < 256; ++i)	BEGIN	SET	x = i / 16	SET	y = i REM 16	SPRINT	h EVAL ~%x_%x%%%y_%y%%~
    						PATCH_IF !FILE_CONTAINS_EVALUATED (~SPLSTATE.IDS~ ~^\(%i%\|0x0*%h%\)[%s%]+[^%w%]+[%w%]~) BEGIN INSERT_2DA_ROW	i 2	~%i% %label%~	SET	new_ids = i	SET	i = 256	END
    					END
    					PATCH_IF	!IS_AN_INT new_ids	BEGIN	PATCH_FAIL	~No Spell States available~	END
    				BUT_ONLY
    			END
    		END
    	//	--------------------------------------------------------------------------------------------------------------------------------------------------------------------------	//
    		DEFINE_ACTION_FUNCTION	ADD_SPLPROT	INT_VAR	stat = 0	value = 0	relation = 0	STR_VAR	label = ~~	new_row = ~*~	RET	new_row		BEGIN	SILENT
    			ACTION_IF stat > 278	BEGIN	WARN	~SPLPROT.2DA - Stat out of Bounds.~	END
    			ACTION_IF (stat != 259) AND (stat != 260) AND (relation > 11)	BEGIN	WARN	~SPLPROT.2DA - Relation out of Bounds.~	END
    			ACTION_IF !(~%label%~ STRING_CONTAINS_REGEXP ~[ %TAB%%WNL%]~)	BEGIN	FAIL	~Label cannot contain whitespace.~	END
    			COPY_EXISTING ~SPLPROT.2DA~	override	READ_2DA_ENTRIES_NOW	READ	4
    				FOR	(i = 0; i < READ; ++i)	BEGIN
    					PATCH_IF	(~%stat%~	STR_EQ EVAL $READ(~%i%~ 1))	AND	(~%value%~	STR_EQ EVAL $READ(~%i%~ 2))	AND	(~%relation%~	STR_EQ EVAL $READ(~%i%~ 3))	BEGIN
    						SET	new_row = i	SET	i = READ
    					END
    				END
    				PATCH_IF !IS_AN_INT new_row	BEGIN	FOR	(i = 0; i < READ; ++i)	BEGIN	PATCH_IF (~*~ STR_EQ EVAL $READ(~%i%~ 1))	BEGIN	PATCH_PRINT	~%i% %READ%~
    											REMOVE_2DA_ROW	i 4	SET	new_row = i			INSERT_2DA_ROW		i 4 ~%new_row%_%label% %stat% %value% %relation%~	SET	i = READ	END	END	END
    				PATCH_IF !IS_AN_INT new_row	BEGIN	SET	new_row = READ	INSERT_2DA_ROW READ 4 ~%new_row%_%label% %stat% %value% %relation%~	END
    				PRETTY_PRINT_2DA
    			BUT_ONLY
    		END
    	//	--------------------------------------------------------------------------------------------------------------------------------------------------------------------------	//
    		DEFINE_ACTION_FUNCTION	~COMPONENT$$MAIN~	BEGIN
    			LAF	ADD_SPLPROT	INT_VAR	stat = 59	value = 1	relation = 1	STR_VAR	label = ~POLYMORPHED=1~	RET	$splprot(~POLYMORPH=1~) = new_row	END
    			LAF	ADD_SPLSTATE	STR_VAR	label = ~NATURAL_FORM_ABILITY~	RET	$splstate(NAT) = new_ids	END
    			LAF	ADD_SPLSTATE	STR_VAR	label = ~POLYFORM_TEMP_ABILITY~	RET	$splstate(TEMP) = new_ids	END
    			ACTION_IF	GAME_IS	~bgee~	BEGIN
    				COPY_EXISTING	~PLYBEAR1.ITM~	~override/PLYBEAR2.ITM~	//	Missing
    				COPY_EXISTING	~BRBRP1.ITM~		~override/BRBRP2.ITM~		//	Moved to accomodate splitting Brown Bear and Werewolf Item
    				COPY_EXISTING	~BRBRP.ITM~			~override/BRBRP1.ITM~		//	Split Brown Bear and Werewolf Item
    			END
    			DEFINE_PATCH_FUNCTION	alter_poly_spell	INT_VAR	header = 0	power = 0	duration = 0	BEGIN
    				LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 146	power	target = 1	parameter2 = 1	timing = 4	duration	STR_VAR	resource = $revert($SOURCE(RES))	END
    					//	Remove current Polymorph/Weapon when spell expires (if active)
    				PHP_EACH	EVAL ~%array%~	AS	resource => null	BEGIN	LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 171	power	target = 1	STR_VAR	resource	END	END
    					//	Give each Polymorph ability
    				PHP_EACH	EVAL ~%array%~	AS	resource => null	BEGIN	LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 172	power	target = 1	timing = 4	duration	STR_VAR	resource	END	END
    					//	Remove each Polymorph ability when spell expires
    				LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 142	power	target = 1	parameter2 = 54	duration	END	//	Portrait Icon
    				LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 139	power	target = 1	parameter1 = 26464	timing = 1	END	//	String Display (Abilities have been added...)
    				LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 215	power	target = 1	parameter2 = 1	duration = 3	STR_VAR	resource = ~SPPOLYMP~	END	//	Polymorph Visual
    				LPF	ADD_SPELL_EFFECT	INT_VAR	header	opcode = 215	power	target = 1	parameter2 = 1	duration = 3	STR_VAR	resource = ~POLYBACK~	END	//	Polymorph Visual
    			END
    			DEFINE_ACTION_FUNCTION	alter_poly_item	INT_VAR	hostile = 0	STR_VAR	item_ = ~~	cre_ = ~~	RET_ARRAY	POLYITEM	BEGIN
    				ACTION_IF	!VARIABLE_IS_SET	$POLYITEM($item(~~))	BEGIN
    					OUTER_SET	$POLYITEM($item(~~)) = 1
    					COPY_EXISTING	~%item_%.ITM~	override
    						LPF	DELETE_EFFECT	INT_VAR check_headers = 0	silent = 1	match_opcode = 144	END	//	Remove any redundant Disable Button effects
    						LPF	DELETE_EFFECT	INT_VAR check_headers = 0	silent = 1	match_opcode = 145	END	//	Remove any redundant Disable Spellcasting effects
    						LPF	DELETE_EFFECT	INT_VAR check_headers = 0	silent = 1	match_opcode = 135	END	//	Remove any existing Polymorph effects
    						LPF	DELETE_EFFECT	INT_VAR check_headers = 0	silent = 1	match_opcode = 53		END	//	Remove any redundant Animation Change effects
    						LPF	DELETE_EFFECT	INT_VAR check_headers = 0	silent = 1	match_opcode = 60		END	//	Remove any redundant Casting Failure effects
    						LPF	ADD_ITEM_EQEFFECT	INT_VAR	opcode = 144	target = 1	parameter2 = 7	timing = 2	END	//	Disable "Talk" Button
    						LPF	ADD_ITEM_EQEFFECT	INT_VAR	opcode = 342	target = 1	parameter1 = 3	parameter2 = 4	timing = 2	END	//	Override Creature Size: "3"
    							//	Otherwise transforming into a larger creature can result in being immediately stuck, even in wide open areas.
    						PATCH_IF	!hostile 	BEGIN
    							LPF	ADD_ITEM_EQEFFECT	INT_VAR	opcode = 335	target = 1	parameter1 = $splstate(NAT)	parameter2 = ~-1~	timing = 2	special = ~-1~	STR_VAR	resource = SPINHUM	END
    						END
    						PATCH_IF	!IS_AN_INT $x(4)	BEGIN	//	Grant Breath Fireball / Psionic Blast
    							LPF	ADD_ITEM_EQEFFECT	INT_VAR	opcode = 335	target = 1	parameter1 = $splstate(TEMP)	parameter2 = ~-1~	timing = 2	special = ~-1~	STR_VAR	resource = $x(4)	END
    						END
    						PATCH_IF	!IS_AN_INT $x(2)	BEGIN	SPRINT r_ ~%x_2%R~
    							LPF	ADD_ITEM_EQEFFECT	INT_VAR	opcode = 318	target = 1	timing = 2	STR_VAR	resource = $r(~~)	END	//	Is a temp spell form
    						END
    						LPF	ADD_ITEM_EQEFFECT	INT_VAR	opcode = 135	target = 1	timing = 2	STR_VAR	resource = $cre(~~)	END	//	Polymorph
    					IF_EXISTS
    				END
    			END
    			ACTION_DEFINE_ASSOCIATIVE_ARRAY	list	BEGIN	//	Self Polymorphs
    			//	RES				Type	Source	Sound	Ability		BGEE CRE		BGEE ITM		BG2EE CRE		BG2EE ITM		IWDEE CRE		IWDEE ITM		Game	Polymoprh/Shapeshift ability
    				~SPWI493~	,~SPL~,~SPWI416~	,0,0				,~PLYFLIND~	,~PLYFLIND~	,~PLYFLIND~	,~PLYFLIND~	,~PLYFLIND~	,~PLYFLIND~	,	0	=>	~POLYMORPH_SELF_FLIND~
    				~SPWI494~	,~SPL~,~SPWI416~	,0,0				,~PLYOGRE~	,~PLYMSTAR~	,~PLYOGRE~	,~PLYMSTAR~	,~PLYOGRE~	,~PLYMSTAR~	,	0	=>	~POLYMORPH_SELF_OGRE~
    				~SPWI495~	,~SPL~,~SPWI416~	,0,0				,~PLYSPID2~	,~PLYSPID~	,~PLYSPID2~	,~PLYSPID~	,~PLYSPID2~	,~PLYSPID~	,	0	=>	~POLYMORPH_SELF_SPIDER~
    				~SPWI496~	,~SPL~,~SPWI416~	,0,0				,~JELLMU~		,~PLYJELLY~	,~JELLMU~		,~PLYJELLY~	,~JELLMU~		,~PLYJELLY~	,	0	=>	~POLYMORPH_SELF_MUSTARD_JELLY~
    				~SPWI497~	,~SPL~,~SPWI416~	,0,0				,~BEARBR~		,~PLYBEAR1~	,~BEARBR~		,~PLYBEAR1~	,~BEARBR~		,~PLYBEAR1~	,	0	=>	~POLYMORPH_SELF_BROWN_BEAR~
    				~SPWI498~	,~SPL~,~SPWI416~	,0,0				,~BEARBL~		,~PLYBEAR2~	,~BEARBL~		,~PLYBEAR2~	,~BEARBL~		,~PLYBEAR2~	,	0	=>	~POLYMORPH_SELF_BLACK_BEAR~
    				~SPWI499~	,~SPL~,~SPWI416~	,0,0				,~PLYWOLF~	,~PLYWOLF1~	,~PLYWOLF~	,~PLYWOLF1~	,~PLYWOLF~	,~PLYWOLF1~	,	0	=>	~POLYMORPH_SELF_WOLF~
    				~SPWI480~	,~SPL~,~SPWI416~	,0,0				,~DRUIDBB~	,~CDPOLYBB~	,~DRUIDBB~	,~CDPOLYBB~	,~DRUIDBB~	,~CDPOLYBB~	,	4	=>	~POLYMORPH_SELF_BORING_BEETLE~
    				~SPWI481~	,~SPL~,~SPWI416~	,0,0				,~DRUIDPB~	,~CDPOLYPB~	,~DRUIDPB~	,~CDPOLYPB~	,~DRUIDPB~	,~CDPOLYPB~	,	4	=>	~POLYMORPH_SELF_POLAR_BEAR~
    				~SPWI482~	,~SPL~,~SPWI416~	,0,0				,~DRUIDWW~	,~CDPOLYWW~	,~DRUIDWW~	,~CDPOLYWW~	,~DRUIDWW~	,~CDPOLYWW~	,	4	=>	~POLYMORPH_SELF_WINTER_WOLF~
    				~SPIN152~	,~SPL~,~SPWI916~	,0,~SPIN974~,~SHMIND~		,~MINDFLAY~	,~SHMIND~		,~CDMINDFL~	,~SHMIND~		,~MINDFLAY~	,	0	=>	~SHAPECHANGE_MIND_FLAYER~
    				~SPIN153~	,~SPL~,~SPWI916~	,0,0				,~SHIRON~		,~GOLIRO~		,~SHIRON~		,~CDGOLIRO~	,~SHIRON~		,~GOLIRO~		,	0	=>	~SHAPECHANGE_IRON_GOLEM~
    				~SPIN154~	,~SPL~,~SPWI916~	,0,0				,~SHTROLL~	,~TROLLALL~	,~SHTROLL~	,~TROLLALL~	,~SHTROLL~	,~TROLLALL~	,	0	=>	~SHAPECHANGE_GIANT_TROLL~
    				~SPIN155~	,~SPL~,~SPWI916~	,0,0				,~SHWOLF~		,~WOLFGR~		,~SHWOLF~		,~WOLFGR~		,~SHWOLF~		,~WOLFGR~		,	0	=>	~SHAPECHANGE_GREATER_WOLFWERE~
    				~SPIN156~	,~SPL~,~SPWI916~	,0,0				,~SHFIRE~		,~FIRERN~		,~SHFIRE~		,~FIRERN~		,~SHFIRE~		,~FIRERN~		,	2	=>	~SHAPECHANGE_FIRE_ELEMETAL~
    				~SPIN157~	,~SPL~,~SPWI916~	,0,0				,~SHEARTH~	,~EARTHRN~	,~SHEARTH~	,~EARTHRN~	,~SHEARTH~	,~EARTHRN~	,	2	=>	~SHAPECHANGE_EARTH_ELEMENTAL~
    				~SPIN198~	,~SPL~,~SPWI916~	,0,0				,~CDSHWELE~	,~CDSHWELE~	,~CDSHWELE~	,~CDSHWELE~	,~CDSHWELE~	,~CDSHWELE~	,	4	=>	~SHAPECHANGE_WATER_ELEMENTAL~
    				~SPCL611~	,~SPL~,0					,0,0				,~BEARBR~		,~BRBRP~		,~BEARBR~		,~BRBRP~		,~BEARBR~		,~BRBRP~		,	0	=>	~DRUID_SHAPESHIFT_BROWN_BEAR~
    				~SPIN107~	,~SPL~,0					,0,0				,~BEARBR~		,~BRBRP~		,~BEARBR~		,~BRBRP~		,~BEARBR~		,~BRBRP~		,	0	=>	~DRUID_SHAPESHIFT_BROWN_BEAR~
    				~SPCL612~	,~SPL~,0					,0,0				,~WOLFCHAR~	,~WOLFM~		,~WOLFCHAR~	,~WOLFM~		,~WOLFCHAR~	,~WOLFM~		,	0	=>	~DRUID_SHAPESHIFT_WOLF~
    				~SPIN110~	,~SPL~,0					,0,0				,~WOLFCHAR~	,~WOLFM~		,~WOLFCHAR~	,~WOLFM~		,~WOLFCHAR~	,~WOLFM~		,	0	=>	~DRUID_SHAPESHIFT_WOLF~
    				~SPCL613~	,~SPL~,0					,0,0				,~BEARBL~		,~BRBLP~		,~BEARBL~		,~BRBLP~		,~BEARBL~		,~BRBLP~		,	0	=>	~DRUID_SHAPESHIFT_BLACK_BEAR~
    				~SPIN111~	,~SPL~,0					,0,0				,~BEARBL~		,~BRBLP~		,~BEARBL~		,~BRBLP~		,~BEARBL~		,~BRBLP~		,	0	=>	~DRUID_SHAPESHIFT_BLACK_BEAR~
    				~SPCL101~	,~SPL~,0,	~#PBEAR01~,0				,~DRUIDPB~	,~PLYPBEAR~	,~DRUIDPB~	,~PLYPBEAR~	,~DRUIDPB~	,~PLYPBEAR~	,	4	=>	~DRUID_SHAPESHIFT_POLAR_BEAR~
    				~SPCL107~	,~SPL~,0,	~#WOLFF04~,0				,~DRUIDWW~	,~PLYWWOLF~	,~DRUIDWW~	,~PLYWWOLF~	,~DRUIDWW~	,~PLYWWOLF~	,	4	=>	~DRUID_SHAPESHIFT_WINTER_WOLF~
    				~SPCL108~	,~SPL~,0					,0,0				,~DRUIDBB~	,~PLYBEETL~	,~DRUIDBB~	,~PLYBEETL~	,~DRUIDBB~	,~PLYBEETL~	,	4	=>	~DRUID_SHAPESHIFT_BORING_BEETLE~
    				~SPCL112~	,~SPL~,0					,0,0				,~DRUIDFE~	,~FELEM~		,~DRUIDFE~	,~FELEM~		,~DRUIDFE~	,~FELEM~		,	4	=>	~DRUID_SHAPESHIFT_FIRE_ELEMETAL~
    				~SPCL113~	,~SPL~,0					,0,0				,~DRUIDEE~	,~EELEM~		,~DRUIDEE~	,~EELEM~		,~DRUIDEE~	,~EELEM~		,	4	=>	~DRUID_SHAPESHIFT_EARTH_ELEMENTAL~
    				~SPCL114~	,~SPL~,0					,0,0				,~DRUIDWE~	,~WELEM~		,~DRUIDWE~	,~WELEM~		,~DRUIDWE~	,~WELEM~		,	4	=>	~DRUID_SHAPESHIFT_WATER_ELEMENTAL~
    				~SPCL632~	,~SPL~,0					,0,0				,~PLYSPID~	,~PLYSPID2~	,~PLYSPID~	,~PLYSPID2~	,~PLYSPID~	,~PLYSPID2~	,	0	=>	~AVENGER_SHAPESHIFT_SWORD_SPIDER~
    				~SPIN125~	,~SPL~,0,	~PBEAR01~	,0				,~PLYSPID2~	,~PLYSPID~	,~PLYSPID2~	,~PLYSPID~	,~~					,~~					,	0	=>	~AVENGER_SHAPESHIFT_SPIDER_(old)~
    				~SPCL633~	,~SPL~,0					,0,0				,~PLYWYVRN~	,~PLYWYVRN~	,~PLYWYVRN~	,~PLYWYVRN~	,~PLYWYVRN~	,~PLYWYVRN~	,	0	=>	~AVENGER_SHAPESHIFT_BABY_WYVERN~
    				~SPIN126~	,~SPL~,0,	~PBEAR01~	,0				,~PLYWYVRN~	,~PLYWYVRN~	,~PLYWYVRN~	,~PLYWYVRN~	,~~					,~~					,	0	=>	~AVENGER_SHAPESHIFT_BABY_WYVERN_(old)~
    				~SPCL634~	,~SPL~,0					,0,~SPIN160~,~PLYSALA~	,~PLYSALA~	,~PLYSALA~	,~PLYSALA~	,~PLYSALA~	,~PLYSALA~	,	0	=>	~AVENGER_SHAPESHIFT_FIRE_SALAMANDER~
    				~SPIN127~	,~SPL~,0,	~PBEAR01~	,0				,~PLYBASS~	,~PLYBASS~	,~PLYBASS~	,~PLYBASS~	,~~					,~~					,	0	=>	~AVENGER_SHAPESHIFT_LESSER_BASILISK_(old)~
    				~SPCL643~	,~SPL~,0					,0,0				,~WEREWODR~	,~BRBRP1~		,~WEREWODR~	,~CDBRBRP~	,~WEREWODR~	,~WEREWLF1~	,	0	=>	~SHAPESHIFTER_SHAPESHIFT_WEREWOLF~
    				~SPCL644~	,~SPL~,0					,0,0				,~WEREGRDR~	,~BRBRP2~		,~WEREGRDR~	,~CDBRBRP2~	,~WEREGRDR~	,~WEREWLF2~	,	0	=>	~SHAPESHIFTER_SHAPESHIFT_GREATER_WEREWOLF~
    			END
    			ACTION_DEFINE_ASSOCIATIVE_ARRAY	other	BEGIN	//	Hostile/Duration Polymorphs
    			//	RES				Type Power Resist	Head	Save Dura	Prob		BGEE CRE		BGEE ITM		BG2EE CRE		BG2EE ITM		IWDEE CRE		IWDEE ITM		Index		Game		Polymoprh/Shapeshift ability
    				~SPWI415~	,~SPL~,4		,1			,0		,16	,0		,100	,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,	0	=>	~POLYMORPH_OTHER_SQUIRREL~
    				~SPWI711~	,~SPL~,0		,1			,0		,1	,9		,10		,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,	0	=>	~SPHERE_OF_CHAOS_POLYMORPH_SQUIRREL~
    				~SPWM183~	,~SPL~,0		,1			,0		,16	,0		,100	,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,	0	=>	~WILD_SURGE_POLYMORPH_SQUIRREL~
    				~BOLT05~	,~ITM~,0		,1			,1		,16	,0		,100	,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,	0	=>	~BOLT_OF_POLYMORPHING_SQUIRREL~
    				~WAND09~	,~ITM~,4		,1			,1		,16	,0		,100	,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,~SQUIRR~		,~SQUIRP~		,	0	=>	~WAND_OF_POLYMORPHING_SQUIRREL~
    				~SPWM113~	,~SPL~,0		,1			,0		,0	,70		,100	,~SPIRWOLF~	,~PLYWOLF1~	,~SPIRWOLF~	,~PLYWOLF1~	,~SPIRWOLF~	,~WSWOLF~		,	0	=>	~WILD_SURGE_POLYMORPH_SPIRIT_WOLF~
    				~CLCK04~	,~ITM~,0		,0			,0		,0	,120	,100	,~WOLFCHAR~	,~CDWOLFM~	,~WOLFCHAR~	,~CDWOLFM~	,~WOLFCHAR~	,~CDWOLFM~	,	3	=>	~RELAIR'S_MISTAKE_POLYMORPH_WOLF~
    				~CLCK27~	,~ITM~,0		,0			,1		,0	,120	,100	,~POLYRAT~	,~POLYRAT~	,~POLYRAT~	,~POLYRAT~	,~POLYRAT~	,~POLYRAT~	,	2	=>	~CLOAK_OF_THE_SEWERS_POLYMORPH_RAT~
    				~CLCK27~	,~ITM~,0		,0			,2		,0	,120	,100	,~PLYTROLL~	,~PLYTROLL~	,~PLYTROLL~	,~PLYTROLL~	,~PLYTROLL~	,~PLYTROLL~	,	2	=>	~CLOAK_OF_THE_SEWERS_POLYMORPH_TROLL~
    				~CLCK27~	,~ITM~,0		,0			,3		,0	,120	,100	,~JELLMU~		,~PLYJELLY~	,~JELLMU~		,~PLYJELLY~	,~JELLMU~		,~PLYJELLY~	,	2	=>	~CLOAK_OF_THE_SEWERS_POLYMORPH_JELLY~
    			END
    			ACTION_DEFINE_ASSOCIATIVE_ARRAY	slayer	BEGIN	//	Slayer Change
    			//	SPL				ITM				CRE			Duration ID	Forced	Polymoprh/Shapeshift ability
    				~SPIN717~,~SLAYERW1~,~SLAYER~	,40			,1,	1		=> ~SLAYER_CHANGE_CUT_SCENE~
    				~SPIN783~,~SLAYERW2~,~SLAYER~	,0			,2,	1		=> ~SLAYER_ENEMY~
    				~SPIN823~,~SLAYERW3~,~SLAYER~	,0			,3,	0		=> ~SLAYER_CHANGE_TWO~
    				~SPIN852~,~SLAYERW4~,~SLAYER~	,12			,4,	1		=> ~SLAYER_CHANGE~
    			END
    			ACTION_DEFINE_ASSOCIATIVE_ARRAY revert BEGIN ~SPWI916~ => ~SPIN150~ ~SPWI416~ => ~SPWI489~	END
    			ACTION_PHP_EACH	revert	AS	src => res	BEGIN	//	Temp Polymorph revert
    				COPY_EXISTING ~%res%.SPL~	override	LPF	DELETE_EFFECT	END
    					LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 177	target = 2	parameter2 = 2	STR_VAR	resource = EVAL ~%res%R~	END
    					LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 2	parameter2 = 1	STR_VAR	resource = ~SPINHUMR~	END
    				BUT_ONLY	IF_EXISTS
    				CREATE	EFF	~%res%R~	WRITE_SHORT	0x10	318	WRITE_BYTE	0x2c	100	WRITE_ASCIIE	0x30	~%res%~	WRITE_ASCIIE	0x94	~%src%R~
    			END
    			ACTION_DEFINE_ARRAY	human	BEGIN	~SPIN122~	~SPIN123~	~SPIN124~	~SPIN151~ ~SPWI490~ ~SPWI491~	~SPIN868~	END
    			ACTION_PHP_EACH	human	AS	null => res_	BEGIN	//	Various remaining Natural Form abilities - all redirected to cast SPINHUMR.
    				COPY_EXISTING	~%res_%.SPL~	override	LPF	DELETE_EFFECT	END
    					LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 1	parameter2 = 1	STR_VAR	resource = ~SPINHUMR~	END
    					LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 172	target = 1	STR_VAR	resource = $res(~~)	END
    				IF_EXISTS
    			END
    			ACTION_PHP_EACH	list	AS	x => y	BEGIN	OUTER_SPRINT	resource ~%x%~	OUTER_SPRINT	file_ ~%x%.%x_1%~
    				ACTION_MATCH	$x(12)	WITH
    					6		WHEN	GAME_IS ~bgee~						BEGIN	END	5		WHEN	GAME_IS ~bg2ee eet~				BEGIN	END	3		WHEN	GAME_IS ~iwdee~						BEGIN	END
    					4		WHEN	GAME_IS ~bgee bg2ee eet~	BEGIN	END	1		WHEN	GAME_IS ~bg2ee eet iwdee~	BEGIN	END	2		WHEN	GAME_IS ~bgee iwdee~			BEGIN	END
    				DEFAULT
    					ACTION_IF	FILE_EXISTS_IN_GAME	$file(~~)	BEGIN
    						ACTION_MATCH	1 WITH
    							ANY GAME_IS ~iwdee~	BEGIN	OUTER_SPRINT	cre_	$x(9)	OUTER_SPRINT	item_	$x(10)	END
    							ANY GAME_IS ~eet~		BEGIN	OUTER_SPRINT	cre_	$x(7)	OUTER_SPRINT	item_	$x(8)		END
    							ANY GAME_IS ~bg2ee~	BEGIN	OUTER_SPRINT	cre_	$x(7)	OUTER_SPRINT	item_	$x(8)		END
    							ANY GAME_IS ~bgee~	BEGIN	OUTER_SPRINT	cre_	$x(5)	OUTER_SPRINT	item_	$x(6)		END
    							DEFAULT
    						END
    						COPY_EXISTING	~%file_%~	override	TO_UPPER	SOURCE_RES	LPF	DELETE_EFFECT	END
    							PATCH_IF	!IS_AN_INT $x(2)	BEGIN	//	Polymorph Self / Shapechange - usable at will
    								SPRINT	$ $x(2)(~%resource%~ ~%idx%~) $item(~~)
    								LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 171	target = 1	STR_VAR	resource	END
    								LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 172	target = 1	STR_VAR	resource	END
    							END
    							LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 1	parameter2 = 1	STR_VAR	resource = ~SPINHUMR~	END
    							LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 111	target = 1	parameter1 = 1	timing = 4	STR_VAR	resource = $item(~~)	END	//	0s Delay = prevents equipped effect loss
    							PATCH_IF	GAME_IS	~iwdee~	BEGIN
    								PATCH_IF	!$x(2)	BEGIN	//	IWDEE Druid Shapeshift Heal	(heal 40% of lost HP)
    									LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 18		target = 1	parameter1 = 250	parameter2 = 2	END
    									LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 12		target = 1	parameter1 = 40		parameter2 = 2 + (65535 << 16)	savingthrow = (BIT24 + BIT25)	END
    									LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 139	target = 1	parameter1 = 14022	timing = 4	END
    								END
    								PATCH_IF	!IS_AN_INT $x(3)	BEGIN	//	IWDEE Polymorph Roar Sound
    									LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 174	target = 1	timing = 4	STR_VAR	resource = $x(4)	END
    								END
    							END
    						BUT_ONLY	OUTER_SET	$POLYFORM_abort(~%resource%~) = 1
    						ACTION_IF	!IS_AN_INT $x(4)	BEGIN	//	Breath Fireball / Psionic Blast - Made usable at will, since you can just reactivate the polymorph anyway
    							COPY_EXISTING	~%x_4%.SPL~	override
    								LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 171	target = 1	STR_VAR	resource = $x(4)	END
    								LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 172	target = 1	STR_VAR	resource = $x(4)	END
    							IF_EXISTS
    						END
    						LAF	alter_poly_item	STR_VAR	item_	cre_ RET_ARRAY	POLYITEM	END
    					END
    				END
    			END
    			OUTER_SET	squirrel = 1
    			ACTION_PHP_EACH	other	AS	x => y	BEGIN	OUTER_SPRINT	resource ~%x%~	OUTER_SPRINT	file_ ~%x%.%x_1%~	//	Hostile/Forced Polymorphs
    				ACTION_MATCH	$x(15)	WITH
    					6		WHEN	GAME_IS ~bgee~						BEGIN	END	5		WHEN	GAME_IS ~bg2ee eet~				BEGIN	END	3		WHEN	GAME_IS ~iwdee~						BEGIN	END
    					4		WHEN	GAME_IS ~bgee bg2ee eet~	BEGIN	END	1		WHEN	GAME_IS ~bg2ee eet iwdee~	BEGIN	END	2		WHEN	GAME_IS ~bgee iwdee~			BEGIN	END
    				DEFAULT
    					ACTION_IF	FILE_EXISTS_IN_GAME	$file(~~)	BEGIN
    						OUTER_SET	power = $x(2)	OUTER_SET	resist_dispel = $x(3)	OUTER_SET	savingthrow = $x(5)	OUTER_SET	duration = $x(6)	OUTER_SET	hostile = $x(3)	OUTER_SET	probability1 = $x(7)
    						ACTION_MATCH	1 WITH
    							GAME_IS ~iwdee~	BEGIN	OUTER_SPRINT	cre_	$x(12)	OUTER_SPRINT	item_	$x(13)	END
    							GAME_IS ~eet~		BEGIN	OUTER_SPRINT	cre_	$x(10)	OUTER_SPRINT	item_	$x(11)	END
    							GAME_IS ~bg2ee~	BEGIN	OUTER_SPRINT	cre_	$x(10)	OUTER_SPRINT	item_	$x(11)	END
    							GAME_IS ~bgee~	BEGIN	OUTER_SPRINT	cre_	$x(8)		OUTER_SPRINT	item_	$x(9)		END
    						DEFAULT	END
    						ACTION_MATCH	$x(1)	WITH	~SPL~	BEGIN	OUTER_SPRINT	add_fun ~ADD_SPELL_EFFECT~	END
    																					DEFAULT	OUTER_SPRINT	add_fun ~ADD_ITEM_EFFECT~		END
    						OUTER_SPRINT	res_ ~%resource%S~	OUTER_SET	del_head = ~-1~	OUTER_SET	header = 0
    						ACTION_IF	!hostile	BEGIN	OUTER_SET	header = $x(4)	OUTER_SET	del_head = header - 1
    							OUTER_PATCH_SAVE	s	~R~	BEGIN	WRITE_BYTE	0 (THIS + del_head)	END	OUTER_SPRINT	res_ ~%resource%%s%~
    						END
    						COPY_EXISTING	~%file_%~	override	TO_UPPER	SOURCE_RES
    							LPF	DELETE_EFFECT	INT_VAR	check_globals = 0	header = del_head	match_probability1 = probability1	END
    							LPF	~%add_fun%~	INT_VAR	type = 99	header	opcode = 146	power	target = 2	parameter2 = 1	resist_dispel	savingthrow	probability1	STR_VAR	resource = ~SPINHUMR~	END
    							LPF	~%add_fun%~	INT_VAR	type = 99	header	opcode = 146	power	target = 2	parameter2 = 1	timing = 4	resist_dispel	savingthrow	probability1	STR_VAR	resource = $res(~~)	END
    							LPF	~%add_fun%~	INT_VAR	type = 99	header	opcode = 141	power	target = 2	parameter2 = 6	timing = 1	resist_dispel	savingthrow	probability1	END
    							LPF	~%add_fun%~	INT_VAR	type = 99	header	opcode = 174	power	target = 2	timing = 1	resist_dispel	savingthrow	probability1	STR_VAR	resource = ~EFF_P07~	END
    						BUT_ONLY
    						//	Polymorph moved to subspell because it needs a duration
    						CREATE	SPL	~%res_%~	WRITE_LONG	0x8	~-1~	WRITE_LONG	0xc	~-1~	WRITE_LONG	0x50	~-1~	WRITE_LONG	0x54	~-1~
    							WRITE_LONG	0x34	1	WRITE_LONG	0x64	0x72	WRITE_SHORT	0x68	1	WRITE_LONG	0x6a	0x9a	INSERT_BYTES	0x72	0x28
    							WRITE_SHORT	0x80	32767	WRITE_SHORT	0x82	1	WRITE_SHORT	0x98	1
    							PATCH_IF	duration = 0	BEGIN	timing = 1	END	ELSE	BEGIN	timing = 0	END
    							LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 111	power	target = 2	parameter1 = 1	timing	duration	STR_VAR	resource = $item(~~)	END
    						OUTER_SET	$POLYFORM_abort($res(~~)) = 1
    						LAF	alter_poly_item	INT_VAR	hostile	STR_VAR	item_	cre_	RET_ARRAY	POLYITEM	END
    					END
    				END
    			END
    			COPY_EXISTING	~SPIN822.SPL~	override	LPF	DELETE_EFFECT	END	//	Make usable at-will
    				LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 171	target = 1	STR_VAR	resource = $SOURCE(RES)	END
    				LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 172	target = 1	STR_VAR	resource = $SOURCE(RES)	END
    				LPF	ADD_SPELL_EFFECT		INT_VAR	opcode = 265	target = 2	parameter1 = 1	timing = 4	duration = 1	STR_VAR	resource = ~SLAYER10~	END	//	Set Slayer Variable
    			BUT_ONLY	IF_EXISTS
    			ACTION_PHP_EACH	slayer	AS	x => y	BEGIN	OUTER_SPRINT	resource ~%x%~	//	Slayer Change Polymorphs
    				ACTION_MATCH	$x(7)	WITH
    					6		WHEN	GAME_IS ~bgee~						BEGIN	END	5		WHEN	GAME_IS ~bg2ee eet~				BEGIN	END	3		WHEN	GAME_IS ~iwdee~						BEGIN	END
    					4		WHEN	GAME_IS ~bgee bg2ee eet~	BEGIN	END	1		WHEN	GAME_IS ~bg2ee eet iwdee~	BEGIN	END	2		WHEN	GAME_IS ~bgee iwdee~			BEGIN	END
    				DEFAULT
    					ACTION_IF	FILE_EXISTS_IN_GAME	~%resource%.SPL~	BEGIN	OUTER_SPRINT	res_ ~%x%S~
    						OUTER_SET	duration = $x(3)	OUTER_SPRINT	cre_	$x(2)	OUTER_SPRINT	item_	$x(1)
    						COPY_EXISTING	~%resource%.SPL~	override	TO_UPPER	SOURCE_RES	LPF	DELETE_EFFECT	END
    							PATCH_IF	$x(4) != 3	BEGIN
    								LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 2	parameter2 = 1	STR_VAR	resource = ~SPINHUMR~	END
    								LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 2	parameter2 = 1	timing = 4	STR_VAR	resource = $res(~~)	END
    							END	ELSE	BEGIN
    								LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 321	target = 2	STR_VAR	resource = $SOURCE(RES)	END
    								LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 2	parameter2 = 1	STR_VAR	resource = ~SPINHUMS~	END
    								LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 146	target = 2	parameter2 = 1	timing = 4	STR_VAR	resource = $res(~~)	END
    								PATCH_IF	$x(4) = 3	BEGIN
    									LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 338	target = 2	parameter1 = 16502	parameter2 = 2	duration = 45	END
    									LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 139	target = 2	parameter1 = 5381	timing = 4	duration = 44	END
    									FOR (i = 0; i < 16; ++i)	BEGIN
    										LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 12	target = 2	parameter1 = (2**i)	parameter2 = (4096 << 16)
    																									timing = 4	duration = 6 * (i + 1)	savingthrow = (BIT24 + BIT25)	END
    									END
    								END
    							END
    							LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 215	target = 2	duration = 6	STR_VAR	resource = ~ICFIRSDI~	END
    							LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 174	target = 2	timing = 1	STR_VAR	resource = ~SLAY02~	END
    						BUT_ONLY
    						//	Polymorph moved to subspell because it needs a duration
    						CREATE	SPL	~%resource%S~	WRITE_LONG	0x8	~-1~	WRITE_LONG	0xc	~-1~	WRITE_LONG	0x50	~-1~	WRITE_LONG	0x54	~-1~
    							WRITE_LONG	0x34	1	WRITE_LONG	0x64	0x72	WRITE_SHORT	0x68	1	WRITE_LONG	0x6a	0x9a	INSERT_BYTES	0x72	0x28
    							WRITE_SHORT	0x80	32767	WRITE_SHORT	0x82	1	WRITE_SHORT	0x98	1	SET	timing = 0	PATCH_IF	duration = 0	BEGIN	timing = 1	END
    							LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 111	target = 2	parameter1 = 1	timing	duration	STR_VAR	resource = $item(~~)	END
    							PATCH_IF	$x(4) = 3	BEGIN	LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 206	target = 2	parameter1 = 26011	duration = 180	STR_VAR	resource = ~SPIN822~	END	END
    							PATCH_IF	$x(4) = 3	BEGIN	LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 17		target = 2	parameter1 = 100	timing = 1	END	END
    							PATCH_IF	$x(4) = 4	BEGIN	LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 247	target = 2	parameter2 = 1	duration	END	END
    						OUTER_SET	$POLYFORM_abort($res(~~)) = 1
    						LAF	alter_poly_item	INT_VAR	hostile = $x(5)	STR_VAR	item_	cre_	RET_ARRAY	POLYITEM	END
    					END
    				END
    			END
    			COPY_EXISTING	~SLAYERW3.ITM~	override
    				LPF	DELETE_EFFECT	INT_VAR	match_opcode = 17	END		LPF	ALTER_EFFECT	INT_VAR	match_opcode = 18	parameter2 = 3	END
    			BUT_ONLY	IF_EXISTS
    			
    			COPY_EXISTING	~SPWI416.SPL~	override	LPF	DELETE_EFFECT	END	SET	power = 4
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 321	target = 1	STR_VAR	resource = $SOURCE(RES)	END
    				GET_OFFSET_ARRAY ab	SPL_V10_HEADERS	PHP_EACH	ab	AS	k => off	BEGIN
    					SET	header = k + 1	READ_SHORT	(off + 0x10)	level
    					SET	duration = (level = 1) ? (60 + 7 * 18) : (60 + level * 18)
    					LPF	alter_poly_spell	INT_VAR	header	power	duration	STR_VAR	array = ~SPWI416~	END
    				END
    			BUT_ONLY
    			COPY_EXISTING	~SPWI916.SPL~	override	LPF	DELETE_EFFECT	END	SET	power = 4
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 321	target = 1	STR_VAR	resource = $SOURCE(RES)	END
    				LPF	alter_poly_spell	INT_VAR	power	duration = 300	STR_VAR	array = ~SPWI916~	END
    			BUT_ONLY
    			COPY_EXISTING ~SPWI489.SPL~	override	READ_LONG	0x8	name	READ_LONG	0x50	desc	BUT_ONLY
    			CREATE	SPL	~SPINHUM~	WRITE_LONG	0x8	name			WRITE_LONG	0xc	~-1~		WRITE_SHORT	0x1c	4			WRITE_LONG	0x50	desc	WRITE_LONG	0x54	~-1~
    				WRITE_LONG	0x34	1	WRITE_ASCII	0x3a	~IHUM~	WRITE_LONG	0x64	0x72	WRITE_SHORT	0x68	1			WRITE_LONG	0x6a	0x9a	INSERT_BYTES	0x72	0x28
    				WRITE_BYTE	0x74	4	WRITE_ASCII	0x76	~IHUM~	WRITE_BYTE	0x7e	5			WRITE_SHORT	0x80	32767	WRITE_SHORT	0x82	1			WRITE_SHORT	0x98	1
    				LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 171	target = 1	STR_VAR	resource = ~SPINHUM~	END
    				LPF	ADD_SPELL_CFEFFECT	INT_VAR	opcode = 172	target = 1	STR_VAR	resource = ~SPINHUM~	END
    				LPF	ADD_SPELL_EFFECT		INT_VAR	opcode = 326	target = 1	STR_VAR	resource = ~SPINHUMR~	END
    				
    			CREATE	SPL	~SPINHUMR~	WRITE_LONG	0x8	~-1~	WRITE_LONG	0xc	~-1~	WRITE_LONG	0x50	~-1~	WRITE_LONG	0x54	~-1~
    				WRITE_LONG	0x34	1	WRITE_LONG	0x64	0x72	WRITE_SHORT	0x68	1	WRITE_LONG	0x6a	0x9a	INSERT_BYTES	0x72	0x28
    				WRITE_SHORT	0x80	32767	WRITE_SHORT	0x82	1	WRITE_SHORT	0x98	1
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 177	target = 2	parameter2 = 2	STR_VAR	resource = ~SPINHUMW~	END	//	Clear Magical Weapon Slot / Terminate existing Polymorph
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 177	target = 2	parameter2 = 2	STR_VAR	resource = ~SPINHUMS~	END	//	Clear Slayer Delayed Damage and Save/Rest block
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 215	target = 2	parameter2 = 1	duration = 3	STR_VAR	resource = ~SPPOLYMP~	END
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 215	target = 2	parameter2 = 1	duration = 3	STR_VAR	resource = ~POLYBACK~	END
    			CREATE	EFF	~SPINHUMW~	WRITE_SHORT	0x10	135	WRITE_BYTE	0x2c	100	WRITE_ASCII	0x94	~*PINHUMW~
    			CREATE	SPL	~SPINHUMW~	WRITE_LONG	0x8	~-1~	WRITE_LONG	0xc	~-1~	WRITE_LONG	0x50	~-1~	WRITE_LONG	0x54	~-1~
    				WRITE_LONG	0x34	1	WRITE_LONG	0x64	0x72	WRITE_SHORT	0x68	1	WRITE_LONG	0x6a	0x9a	INSERT_BYTES	0x72	0x28
    				WRITE_SHORT	0x80	32767	WRITE_SHORT	0x82	1	WRITE_SHORT	0x98	1
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 318	target = 2	STR_VAR	resource = ~*PINHUMW~	END	//	Block Polymorph Effect
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 326	target = 2	STR_VAR	resource = ~SPINHUMR~	END
    			CREATE	EFF	~SPINHUMS~	WRITE_SHORT	0x10	321	WRITE_BYTE	0x2c	100	WRITE_ASCII	0x30	~SPIN823~	WRITE_ASCII	0x94	~*PINHUMS~
    			CREATE	SPL	~SPINHUMS~	WRITE_LONG	0x8	~-1~	WRITE_LONG	0xc	~-1~	WRITE_LONG	0x50	~-1~	WRITE_LONG	0x54	~-1~
    				WRITE_LONG	0x34	1	WRITE_LONG	0x64	0x72	WRITE_SHORT	0x68	1	WRITE_LONG	0x6a	0x9a	INSERT_BYTES	0x72	0x28
    				WRITE_SHORT	0x80	32767	WRITE_SHORT	0x82	1	WRITE_SHORT	0x98	1
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 318	target = 2	STR_VAR	resource = ~*PINHUMS~	END	//	Block Slayer Removal Effect
    				LPF	ADD_SPELL_EFFECT	INT_VAR	opcode = 326	target = 2	STR_VAR	resource = ~SPINHUMR~	END
    
    			COPY_EXISTING_REGEXP	~^.+\.\(spl\|itm\)$~	override
    				PATCH_IF	!VARIABLE_IS_SET	$POLYFORM_abort(~%SOURCE_RES%~)	BEGIN
    					LPF	CLONE_EFFECT	INT_VAR	silent = 1	match_opcode = 111	opcode = 326	parameter2 = $splprot(~POLYMORPH=1~)	timing = 0	duration = 0	STR_VAR	resource = ~SPINHUMW~	END
    				END
    			BUT_ONLY
    			COPY_EXISTING	~UDDOOR2.BCS~ override	~UDDOOR3.BCS~ override
    				DECOMPILE_AND_PATCH	BEGIN	REPLACE_TEXTUALLY ~Global("Slayer10","GLOBAL",2)~ ~HasItem("slayerw3",Player1)~	END
    			BUT_ONLY	IF_EXISTS
    		END
    	END
    	//	--------------------------------------------------------------------------------------------------------------------------------------------------------------------------	//
    	BEGIN	~Poly Test~	REQUIRE_PREDICATE	(GAME_IS ~bgee bg2ee eet iwdee~)	~EE-only~	DESIGNATED	1	LABEL	~POLYMORPH_TESTING_EQUIP~	LAF	~COMPONENT$$MAIN~	END	CLEAR_ARRAYS

     

  23. 39 minutes ago, StummvonBordwehr said:

    1) in SoD the game didnt stack all ac modifiers correctly. For instance the ring of the crusade gave an ac modifier against demons (iirc) and the ring of purity gave an ac modifier against evil. They didnt stack, which I find odd, and most players consider it a bug. I dont know if it was a SoD only problem, but I suspect it is present in all games,

    The opcodes involved that grant the "vs. Creature Type" bonuses do not stack numerically (be it AC/Saves(219), THAC0(178), or damage(179)).

×
×
  • Create New...