Jump to content

Shapeshifting inconsistencies


jmerry

Recommended Posts

Posted
6 hours ago, subtledoctor said:

It just seems like not the best idea to use such fractional slivers of adjustment when the base number is less than 10 and the result rounds to an integer. For instance, there seems like there should be a meaningful difference  between a 150% increase and a 160% increase. But they both round to 14. Why bother with adjustments that result in non-integer values that the game can’t use? Just decide what final value you want and set it to that number. 

I get what you're sayingbut it's also kind of just another way of doing the same thing. If the percentage increases are large enough (for example, the 250% I used for bears), then that method works fine. Well, either way works for me. I'm more interested in the end result (i.e. winter wolves not moving slower than human form, which it didn't in the original).

Posted
43 minutes ago, Dan_P said:

I get what you're sayingbut it's also kind of just another way of doing the same thing. If the percentage increases are large enough (for example, the 250% I used for bears), then that method works fine. Well, either way works for me. I'm more interested in the end result (i.e. winter wolves not moving slower than human form, which it didn't in the original).

Yeah but 250% of what? The BGEE base .CRE value? Is that the same as the BG2EE/IWDEE base .CRE's speed? What exactly is the formula? What is the final movement rate, relative to normal humanoids? Did you just arrive at 250% because it feels about right? (For that matter, should bears actually be that fast? SCS "Faster Bears" is not the baseline; in the base game bears are actually pretty slow.)

For a FixPack that will be the first thing installed, it just seems like an opportunity to do it somewhat systematically. Say, if humans = 9, then bears = 9 and spiders = 12 and wolves = 18. Or whatever.

Posted
9 minutes ago, subtledoctor said:

Yeah but 250% of what? The BGEE base .CRE value? Is that the same as the BG2EE/IWDEE base .CRE's speed? What exactly is the formula? What is the final movement rate, relative to normal humanoids? Did you just arrive at 250% because it feels about right? (For that matter, should bears actually be that fast? SCS "Faster Bears" is not the baseline; in the base game bears are actually pretty slow.)

Eye test. Roughly the same speed as natural form. Yes, it requires 250% increase to get to about normal walking speed. And no, bears should not move that fast and didn't in classic IWD, which I mentioned in my original post. Hence why I only suggested the wolf movement increase as a "fix". The bear movement is just QoL tweak I've been using (the form itself is objectively worse than the Boring Beetle, which you get at a lower level). Just to note, I do the testing for my own stuff in unmodded installs. IWDEE bears with 250% movement are still noticeably slower than BGEE or BG2EE bears unmodded. I'm not saying an increase should be added in a fixpack. I'm just saying I wouldn't argue against it being added.

Posted

Bears are fast as hell irl. Human 9, bear 12, wolf 15 seems about right to me for a game at this environmental scale. 

Posted

BG1/2EE Bear speed is 9, IWDEE Bear speed is 4 (same as zombie).  Wolves have 8 movement in all games.

There is however an issue comparing these values to player movement speed:

PC race animations had 6 movement in BG1.  This was increased 50% (9) in BG2 for QoL, and subsequently the EE's. AFAIK no other animations received this arbitrary increase.

Posted
5 hours ago, kjeron said:

BG1/2EE Bear speed is 9, IWDEE Bear speed is 4 (same as zombie).  Wolves have 8 movement in all games.

There is however an issue comparing these values to player movement speed:

PC race animations had 6 movement in BG1.  This was increased 50% (9) in BG2 for QoL, and subsequently the EE's. AFAIK no other animations received this arbitrary increase.

That's good info, thanks. Matches closely with what I observed. Druid animals don't normally get a movement bonus in IWD, so they went from balanced around normal speed to all being slower with IWDEE, or super slow in the case of bears.

Posted

So the ultimate question is, what is the dev intent regarding polymorph form movement speed? Is there specific intent to make some forms faster or slower? In the absence of such intent, should some aspect of the shapeshift forms - claws seem easiest - get an effect setting movement rate to 9? (Perhaps using op176 for compatibility with Klatu's free Action mod.)

Honestly I would favor this, except of course in obvious cases where the intended movement rate is supposed to be different (e.g. sword spider, mustard jelly). Or I guess where the movement rate is specified in the spell or ability description. Basically the effects of the change, and the way the character behaves in gameplay, should be expectable for players.

Posted

@kjeron

So, I started working on this (wanted to give it a try) and got a first draft

Spoiler
DEFINE_ACTION_FUNCTION "POLYMORPH_OVERHAUL"
BEGIN
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////                                                  \\\\\
	///// unified natural form ability                     \\\\\
	/////                                                  \\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\

	WITH_SCOPE BEGIN
		WITH_SCOPE BEGIN
			COPY_EXISTING "%SHAPESHIFT_NATURAL_FORM_1%.spl" "override/gtnatfor.spl"
				/* Extended header */
				/* Feature blocks */
				LPF "DELETE_EFFECT" END // delete current content
				// Remove any existing p2=0 polymorph (op135) effect and any item in the magical weapon slot
				LPF "ADD_SPELL_EFFECT"
				INT_VAR
					"opcode" = 135 // Polymorph
					"target" = 1 // Self
				END
				// Remove slayer-change delayed damage effects // if necessary
				LPF "ADD_SPELL_EFFECT"
				INT_VAR
					"opcode" = 321 // Remove effects by resource
					"target" = 1 // Self
					"timing" = 1
				STR_VAR
					"resource" = "????????"
				END
				// Visual effects
				LPF "ADD_SPELL_EFFECT"
				INT_VAR
					"opcode" = 215 // Play visual effect
					"target" = 1 // Self
					"parameter2" = 1 // Play where?: Over target (attached)
					"duration" = 3
				STR_VAR
					"resource" = "SPPOLYMP"
				END
				LPF "ADD_SPELL_EFFECT"
				INT_VAR
					"opcode" = 215 // Play visual effect
					"target" = 1 // Self
					"parameter2" = 1 // Play where?: Over target (attached)
					"duration" = 3
				STR_VAR
					"resource" = "POLYBACK"
				END
				// Remove temporary abilities such as "Breathe Fireball" and "Psionic Blast"
				// optional – alternate method available with op335, but uses a spellstate...
				LPF "ADD_SPELL_EFFECT"
				INT_VAR
					"opcode" = 172 // Remove spell/ability
					"target" = 1 // Self
					"timing" = 1
				STR_VAR
					"resource" = "%SALAMANDER_BREATHE_FIREBALL%"
				END
				LPF "ADD_SPELL_EFFECT"
				INT_VAR
					"opcode" = 172 // Remove spell/ability
					"target" = 1 // Self
					"timing" = 1
				STR_VAR
					"resource" = "%MIND_FLAYER_PSIONIC_BLAST%"
				END
			BUT_ONLY_IF_IT_CHANGES
		END
	END

	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////                                                  \\\\\
	///// Polymorph Self, Shapechange:                     \\\\\
	///// do not accidentally override a different         \\\\\
	///// transformation                                   \\\\\
	/////                                                  \\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\

	WITH_SCOPE BEGIN
		COPY_EXISTING
			"spwi489.spl" "override"
			"spin150.spl" "override"
			/* Feature blocks */
			LPF "DELETE_EFFECT" END // delete current content
			// op318 + EFF file trick => https://forums.beamdog.com/discussion/70593/getting-the-most-out-of-opcodes-318-and-177-effs
			LPF "ADD_SPELL_EFFECT"
			INT_VAR
				"opcode" = 177 // Use EFF file
				"target" = 1 // Self
				"parameter2" = 2 // EA.IDS
			STR_VAR
				"resource" = "%DEST_RES%e"
			END
			// Visual effects
			LPF "ADD_SPELL_EFFECT"
			INT_VAR
				"opcode" = 146 // Cast spell
				"target" = 1 // Self
				"parameter2" = 1 // Cast instantly (ignore level)
				"timing" = 1
			STR_VAR
				"resource" = "gtnatfor"
			END
			// Make the V2 EFF file
			PATCH_WITH_SCOPE BEGIN
				INNER_ACTION BEGIN
					CREATE "EFF" "%DEST_RES%e"
						WRITE_LONG 0x10 0x13E // Effect ID: Protection from resource
						WRITE_SHORT 0x2C 100 // Probability 1
						WRITE_EVALUATED_ASCII 0x30 "%DEST_RES%" #8 // Resource
						TO_UPPER "DEST_RES"
						WRITE_EVALUATED_ASCII 0x94 "%DEST_RES%E" #8 // Parent resource (Important: This specific field always needs to be in ALLCAPS!!!)
				END
			END
		BUT_ONLY_IF_IT_CHANGES
	END

	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////                                                  \\\\\
	///// SPL files                                        \\\\\
	/////                                                  \\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\

	WITH_SCOPE BEGIN
		ACTION_CLEAR_ARRAY "polymorph_abilities"
		ACTION_DEFINE_ASSOCIATIVE_ARRAY "polymorph_abilities" BEGIN
			// SPL file , target , power , duration (put `0` if permanent) , savetype , savebonus , resist_dispel , minimum_level , maximum_level , subspell (put `""` if permanent) , poly creature (CRE resref) => ITM file (poly weapon)
			/* Polymorph Self */
			"%WIZARD_POLYMORPH_FLIND%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "plyflind" => "plyflind"
			"%WIZARD_POLYMORPH_MUSTARD_JELLY%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "plyjelly" => "plyjelly"
			"%WIZARD_POLYMORPH_OGRE%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "plyogre" => "plymstar"
			"%WIZARD_POLYMORPH_SPIDER%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "plyspid2" => "plyspid"
			"%WIZARD_POLYMORPH_BROWN_BEAR%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "bearbr" => "plybear2"
			"%WIZARD_POLYMORPH_BLACK_BEAR%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "bearbl" => "plybear1"
			"%WIZARD_POLYMORPH_WOLF%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "plywolf1" => "plywolf1"
			/* Shapechange */
			"%SHAPECHANGE_MIND_FLAYER%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "shmind" => "cdmindfl"
			"%SHAPECHANGE_IRON_GOLEM%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "shiron" => "cdgoliro"
			"%SHAPECHANGE_GREATER_WOLFWERE%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "shwolf" => "wolfgr"
			"%SHAPECHANGE_EARTH_ELEMENTAL%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "shearth" => "earthrn"
			"%SHAPECHANGE_FIRE_ELEMENTAL%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "shfire" => "firern"
			"%SHAPECHANGE_GIANT_TROLL%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "shtroll" => "trollall"
			/* Driud HLA */
			"%CLERIC_ELEMENTAL_TRANSFORMATION_EARTH%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "druear01" => "druear"
			"%CLERIC_ELEMENTAL_TRANSFORMATION_FIRE%" , "1" , "0" , "0" , "0" , "0" , "0" , "0" , "0" , "" , "drufir01" => "drufir"
			/* Polymorph Other */
			"%WIZARD_POLYMORPH_OTHER%" , "2" , "4" , "0" , "%BIT4%" , "0" , "%BIT0%" , "0" , "0" , "" , "squirr" => "squirp"
			"spwm113" , "2" , "4" , "70" , "0" , "0" , "%BIT0%" , "0" , "0" , "spwm113a" , "spirwolf" => "plywolf1"
		END
		ACTION_PHP_EACH "polymorph_abilities" AS "poly_data" => "poly_weapon" BEGIN
			ACTION_IF (FILE_EXISTS_IN_GAME "%poly_data_0%.spl") BEGIN
				WITH_SCOPE BEGIN
					COPY_EXISTING "%poly_data_0%.spl" "override"
						/* Feature blocks */
						LPF "DELETE_EFFECT" END // delete current content
						// Refresh ability, Polymoph Self and Shapechange, and any other unlimited/at-will abilities
						PATCH_MATCH "%poly_data_0%" WITH
							"%WIZARD_POLYMORPH_FLIND%" "%WIZARD_POLYMORPH_SPIDER%" "%WIZARD_POLYMORPH_WOLF%" "%WIZARD_POLYMORPH_BLACK_BEAR%" "%WIZARD_POLYMORPH_BROWN_BEAR%" "%WIZARD_POLYMORPH_MUSTARD_JELLY%"
							"%SHAPECHANGE_MIND_FLAYER%" "%SHAPECHANGE_IRON_GOLEM%" "%SHAPECHANGE_GREATER_WOLFWERE%" "%SHAPECHANGE_EARTH_ELEMENTAL%" "%SHAPECHANGE_FIRE_ELEMENTAL%" "%SHAPECHANGE_GIANT_TROLL%" BEGIN
								LPF "ADD_SPELL_CFEFFECT"
								INT_VAR
									"opcode" = 172 // Remove spell/ability
									"target" = 1 // Self
									"timing" = 1
									"insert_point" = "-1"
								STR_VAR
									"resource" = "%DEST_RES%"
								END
								LPF "ADD_SPELL_CFEFFECT"
								INT_VAR
									"opcode" = 171 // Give spell/ability
									"target" = 1 // Self
									"timing" = 1
									"insert_point" = "-1"
								STR_VAR
									"resource" = "%DEST_RES%"
								END
							END
							DEFAULT
						END
						// removes old polymorph, provides visual fx, removes form-specific innates
						LPF "ADD_SPELL_EFFECT"
						INT_VAR
							"opcode" = 146 // Cast spell
							"target" = "%poly_data_1%"
							"power" = "%poly_data_2%"
							"parameter2" = 1 // Cast instantly (ignore level)
							"timing" = 1
							"savingthrow" = "%poly_data_4%"
							"savebonus" = "%poly_data_5%"
							"resist_dispel" = "%poly_data_6%"
							"dicenumber" = "%poly_data_7%"
							"dicesize" = "%poly_data_8%"
						STR_VAR
							"resource" = "gtnatfor"
						END
						PATCH_IF ("%poly_data_3%" == 0) BEGIN
							// if permanent duration...
							LPF "ADD_SPELL_EFFECT"
							INT_VAR
								"opcode" = 111 // Create weapon
								"target" = "%poly_data_1%"
								"power" = "%poly_data_2%"
								"timing" = 4
								"duration" = 0
								"savingthrow" = "%poly_data_4%"
								"savebonus" = "%poly_data_5%"
								"resist_dispel" = "%poly_data_6%"
								"dicenumber" = "%poly_data_7%"
								"dicesize" = "%poly_data_8%"
							STR_VAR
								"resource" = "%poly_weapon%"
							END
						END ELSE BEGIN
							// if non-permanent duration...
							LPF "ADD_SPELL_EFFECT"
							INT_VAR
								"opcode" = 146 // Cast spell
								"target" = "%poly_data_1%"
								"power" = "%poly_data_2%"
								"parameter2" = 1 // Cast instantly (ignore level)
								"timing" = 4
								"duration" = 0
								"savingthrow" = "%poly_data_4%"
								"savebonus" = "%poly_data_5%"
								"resist_dispel" = "%poly_data_6%"
								"dicenumber" = "%poly_data_7%"
								"dicesize" = "%poly_data_8%"
							STR_VAR
								"resource" = "%poly_data_9%" // subspell with `op111` and a duration
							END
						END
					BUT_ONLY_IF_IT_CHANGES
				END
				// subspell with `op111` and a duration
				ACTION_IF ("%poly_data_9%" STRING_COMPARE_CASE "") BEGIN
					WITH_SCOPE BEGIN
						COPY_EXISTING "%poly_data_0%.spl" "override/%poly_data_9%.spl"
							/* Header */
							WRITE_ASCII 0x10 ~~ #8
							WRITE_LONG NAME1 "-1"
							WRITE_LONG NAME2 "-1"
							WRITE_LONG 0x1E 0
							WRITE_SHORT 0x22 0
							/* Feature block */
							LPF "DELETE_EFFECT" END // delete current content
							LPF "ADD_SPELL_EFFECT"
							INT_VAR
								"opcode" = 111 // Create weapon
								"target" = "%poly_data_1%"
								"duration" = "%poly_data_3%"
							STR_VAR
								"resource" = "%poly_weapon%"
							END
						BUT_ONLY_IF_IT_CHANGES
					END
				END
				// poly weapon
				WITH_SCOPE BEGIN
					COPY_EXISTING "%poly_weapon%.itm" "override"
						/* Feature block */
						PATCH_IF ("%game_is_bgee%" OR "%game_is_iwdee%") BEGIN
							LPF "ADD_ITEM_EQEFFECT"
							INT_VAR
								"opcode" = 144 // Disable button
								"target" = 1
								"parameter2" = IDS_OF_SYMBOL ("BUTTON" "BUTTON_DIALOG")
								"timing" = 2
							END
							LPF "ADD_ITEM_EQEFFECT"
							INT_VAR
								"opcode" = 135 // Polymorph
								"target" = 1
								"timing" = 2
							STR_VAR
								"resource" = "%poly_data_10%"
							END
						END
						PATCH_MATCH "%DEST_RES%" WITH
							"plyjelly" "plyflind" "plywolf1" "plymstar" "plyspid" "plybear[1-2]" BEGIN
								LPF "ADD_ITEM_EQEFFECT"
								INT_VAR
									"opcode" = 318 // Protection from resource
									"target" = 1
									"timing" = 2
								STR_VAR
									"resource" = "spwi489e"
								END
							END
							"cdmindfl" "cdgoliro" "trollall" "wolfgr" "firern" "earthrn" BEGIN
								LPF "ADD_ITEM_EQEFFECT"
								INT_VAR
									"opcode" = 318 // Protection from resource
									"target" = 1
									"timing" = 2
								STR_VAR
									"resource" = "spin150e"
								END
							END
							DEFAULT
						END
					BUT_ONLY_IF_IT_CHANGES
				END
			END
		END
	END

	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////                                                  \\\\\
	///// ITM files                                        \\\\\
	/////                                                  \\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
	/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\

	WITH_SCOPE BEGIN
		ACTION_CLEAR_ARRAY "polymorph_items"
		ACTION_DEFINE_ASSOCIATIVE_ARRAY "polymorph_items" BEGIN
			// ITM file , target , power , duration (put `0` if permanent) , savetype , savebonus , resist_dispel , minimum_level , maximum_level , subspell (put `""` if permanent) , poly creature (CRE resref) => ITM file (poly weapon)
			"wand09" , "2" , "4" , "0" , "%BIT3%" , "0" , "%BIT0%" , "0" , "0" , "" , "squirr" => "squirp" // Wand of Polymorphing
			"bolt05" , "2" , "4" , "0" , "%BIT4%" , "0" , "%BIT0%" , "0" , "0" , "" , "squirr" => "squirp" // Bolt of Polymorphing
			"clck04" , "2" , "0" , "120" , "0" , "0" , "0" , "0" , "0" , "clck04" , "spirwolf" => "plywolf1" // Relair's Mistake
			//"clck27" , "2" , "0" , "120" , "0" , "0" , "0" , "0" , "0" , "" , "spirwolf" => "plywolf1" // Cloak of the Sewers
			"figure01" , "2" , "0" , "24" , "0" , "0" , "0" , "0" , "0" , "figure01" , "" => "shakti1" // Shakti Figurine
		END
		ACTION_PHP_EACH "polymorph_items" AS "poly_data" => "poly_weapon" BEGIN
			ACTION_IF (FILE_EXISTS_IN_GAME "%poly_data_0%.itm") BEGIN
				WITH_SCOPE BEGIN
					COPY_EXISTING "%poly_data_0%.itm" "override"
						/* Feature blocks */
						LPF "DELETE_EFFECT" END // delete current content
						// removes old polymorph, provides visual fx, removes form-specific innates
						LPF "ADD_ITEM_EFFECT"
						INT_VAR
							"type" 99 // All types (ability / extended header)
							"opcode" = 146 // Cast spell
							"target" = "%poly_data_1%"
							"power" = "%poly_data_2%"
							"parameter2" = 1 // Cast instantly (ignore level)
							"timing" = 1
							"savingthrow" = "%poly_data_4%"
							"savebonus" = "%poly_data_5%"
							"resist_dispel" = "%poly_data_6%"
							"dicenumber" = "%poly_data_7%"
							"dicesize" = "%poly_data_8%"
						STR_VAR
							"resource" = "gtnatfor"
						END
						PATCH_IF ("%poly_data_3%" == 0) BEGIN
							// if permanent duration...
							LPF "ADD_ITEM_EFFECT"
							INT_VAR
								"type" 99 // All types (ability / extended header)
								"opcode" = 111 // Create weapon
								"target" = "%poly_data_1%"
								"power" = "%poly_data_2%"
								"timing" = 4
								"duration" = 0
								"savingthrow" = "%poly_data_4%"
								"savebonus" = "%poly_data_5%"
								"resist_dispel" = "%poly_data_6%"
								"dicenumber" = "%poly_data_7%"
								"dicesize" = "%poly_data_8%"
							STR_VAR
								"resource" = "%poly_weapon%"
							END
						END ELSE BEGIN
							// if non-permanent duration...
							LPF "ADD_ITEM_EFFECT"
							INT_VAR
								"type" 99 // All types (ability / extended header)
								"opcode" = 146 // Cast spell
								"target" = "%poly_data_1%"
								"power" = "%poly_data_2%"
								"parameter2" = 1 // Cast instantly (ignore level)
								"timing" = 4
								"duration" = 0
								"savingthrow" = "%poly_data_4%"
								"savebonus" = "%poly_data_5%"
								"resist_dispel" = "%poly_data_6%"
								"dicenumber" = "%poly_data_7%"
								"dicesize" = "%poly_data_8%"
							STR_VAR
								"resource" = "%poly_data_9%" // subspell with `op111` and a duration
							END
						END
					BUT_ONLY_IF_IT_CHANGES
				END
				// subspell with `op111` and a duration
				ACTION_IF ("%poly_data_9%" STRING_COMPARE_CASE "") BEGIN
					WITH_SCOPE BEGIN
						ACTION_MATCH "%poly_data_9%" WITH
							"clck04" "figure01" BEGIN
								COPY_EXISTING "gtnatfor.spl" "override/%poly_data_9%.spl"
									/* Header */
									WRITE_ASCII 0x10 ~~ #8
									WRITE_LONG NAME1 "-1"
									WRITE_LONG NAME2 "-1"
									WRITE_LONG 0x1E 0
									WRITE_SHORT 0x22 0
									/* Feature block */
									LPF "DELETE_EFFECT" END // delete current content
									LPF "ADD_SPELL_EFFECT"
									INT_VAR
										"opcode" = 111 // Create weapon
										"target" = "%poly_data_1%"
										"duration" = "%poly_data_3%"
									STR_VAR
										"resource" = "%poly_weapon%"
									END
								BUT_ONLY_IF_IT_CHANGES
							END
							DEFAULT
						END
					END
				END
				// poly weapon
				WITH_SCOPE BEGIN
					COPY_EXISTING "%poly_weapon%.itm" "override"
						/* Feature block */
						PATCH_IF ("%game_is_bgee%" OR "%game_is_iwdee%") BEGIN
							LPF "ADD_ITEM_EQEFFECT"
							INT_VAR
								"opcode" = 144 // Disable button
								"target" = 1
								"parameter2" = IDS_OF_SYMBOL ("BUTTON" "BUTTON_DIALOG")
								"timing" = 2
							END
							LPF "ADD_ITEM_EQEFFECT"
							INT_VAR
								"opcode" = 135 // Polymorph
								"target" = 1
								"timing" = 2
							STR_VAR
								"resource" = "%poly_data_10%"
							END
						END
					BUT_ONLY_IF_IT_CHANGES
				END
			END
		END
	END
END

 

Got some questions:

On 4/8/2022 at 11:07 PM, kjeron said:

Any given polymorph/shapechange ability would contain::
op146: timing=0, duration=0, saving throw(if hostile), resource=(unified natural form) // removes old polymorph, provides visual fx, removes form-specific innates.

Did you mean timing=4...? Also, generally speaking: "timing=4, duration=0" is basically the same as "timing=1, duration=0", right? It's just this specific case (op135 bug) that requires "timing=4, duration=0"...? Or is it related to op335...?

On 4/8/2022 at 11:07 PM, kjeron said:

unified natural form:
op321: resource=(???) // Remove slayer-change delayed damage effects. // if necessary

What should I put here exactly...?

On 4/9/2022 at 2:26 AM, kjeron said:

Those two can easily be repurposed to achieve that.  Each of their polymorph weapons would be given an immunity effect (op318) with a resource (SubA) shared by all for that spell.

Guess that the Clock of the Sewers should receive a similar treatment, right...?

On 4/9/2022 at 2:26 AM, kjeron said:

This is something a (single) spellstate could accomplish, using op335.  By giving every voluntary polymorph weapon the same 335 effect (same spellstate) with resource=(same natural form ability), the ability will automatically be given when you create the item & removed when you remove the weapon.  You would always and only have the natural form ability while polymorphed in any voluntary form.  The 0-second delay I referenced prior will also get around the issues op335 has regarding using the same spellstate.

What should I put in "7eyes.2da"...? What about `parameter2` of op335...?

What is exactly this issue => "The 0-second delay I referenced prior will also get around the issues op335 has regarding using the same spellstate.". Better to put it on the IESDP me thinks...

On 4/9/2022 at 2:26 AM, kjeron said:

If the normal weapon-creation spells continue to cancel polymorphs (at least voluntary ones), they can cast (op326) the same natural form ability (if POLYMORPHED stat = 1), right before opcode 111, to remove those effects as well, with a momentary (0-duration) immunity to op135 so the newly created weapon doesn't get cleared.

So how these op326 / op101 integrate with the rest...?

Basically, they should go right before

On 4/8/2022 at 11:07 PM, kjeron said:
  • op111: timing=4, duration=0, saving throw(if hostile), resource=(item) // if permanent duration.
  • op146: timing=4, duration=0, saving throw(if hostile), resource=(subspell with op111 and a duration) // if non-permanent duration.

...?

Posted

@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

 

Posted
22 hours ago, kjeron said:

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.

So basically effect order is irrelevant...?

OK, I see it now (hopefully): it's like IWDEE Chill Touch, where the subspell (op326) applying op24 is delayed (1 sec, but guess that 0 secs is also fine) so that the first subspell (op326) can remove immunity to op24...

22 hours ago, kjeron said:

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.

Got it, will report...

22 hours ago, kjeron said:

The op326/101 pair would go on spells like Flame Blade:  op101(135) -> op326(SPINHUM) -> op111(FBLADE)   

Interesting.

But does your overhauled system interfere with such spells...? I mean, op135 (p2=0) automatically disables Arcane/Divine spell casting, so you are not be able to cast those spells while polymorphed... Unless a contingency triggers maybe...?

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...

Posted (edited)
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.

Edited by kjeron
Posted (edited)
15 hours ago, kjeron said:

$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%~

Good to know.

Anyway, the fixpack uses AUTO_EVAL_STRINGS, so EVAL is not needed in any case...

15 hours ago, kjeron said:

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

Will test...

15 hours ago, kjeron said:

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

OK, so that line is supposed to be deleted entirely...?

 

Follow-up questions:

  • Regarding "IWDEE Druid Shapeshift Heal (heal 40% of lost HP)"
    • I know it's supposed to be a flat +12 HP, but I'm not sure what you wanted to do here... I mean, you first set HP (both current and max to 250%) and then set current HP to 40%...? Also Damage Type 65535 is unknown...
  • Regarding "Slayer damage scaling":
    • Damage type 4096 is unknown. Guess you meant
      parameter2 = IDS_OF_SYMBOL ("DMGTYPE" "MAGIC") // Normal mode
  • 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
    • Second, guess you meant something like
      Spoiler
      ACTION_DEFINE_ASSOCIATIVE_ARRAY "%WIZARD_POLYMORPH_SELF%" BEGIN
        ~%WIZARD_POLYMORPH_FLIND%~ => ~~
        ~%WIZARD_POLYMORPH_OGRE%~ => ~~
        ~%WIZARD_POLYMORPH_SPIDER%~ => ~~
        ~%WIZARD_POLYMORPH_MUSTARD_JELLY%~ => ~~
        ~%WIZARD_POLYMORPH_BROWN_BEAR%~ => ~~
        ~%WIZARD_POLYMORPH_BLACK_BEAR%~ => ~~
        ~%WIZARD_POLYMORPH_WOLF%~ => ~~
      END
      
      ACTION_IF (GAME_IS "iwdee") BEGIN
        ACTION_DEFINE_ASSOCIATIVE_ARRAY "%WIZARD_POLYMORPH_SELF%" BEGIN
        	~%WIZARD_POLYMORPH_BORING_BEETLE%~ => ~~
        	~%WIZARD_POLYMORPH_POLAR_BEAR%~ => ~~
        	~%WIZARD_POLYMORPH_WINTER_WOLF%~ => ~~
        END
      END
        
      ACTION_DEFINE_ASSOCIATIVE_ARRAY "%WIZARD_SHAPECHANGE%" BEGIN
        ~%SHAPECHANGE_MIND_FLAYER%~ => ~~
        ~%SHAPECHANGE_IRON_GOLEM%~ => ~~
        ~%SHAPECHANGE_GIANT_TROLL%~ => ~~
        ~%SHAPECHANGE_GREATER_WOLFWERE%~ => ~~
        ~%SHAPECHANGE_GREATER_WOLFWERE%~ => ~~
        ~%SHAPECHANGE_EARTH_ELEMENTAL%~ => ~~
      END

       

  • OUTER_SET squirrel = 1
    • This variable appears to be unused...?
  • Any particular reason for using op326 with no filter instead of a simple op146,p2=1 (see f.i. when patching ~SPINHUM~, ~SPINHUMS~, ~SPINHUMW~)...?
  • ACTION_MATCH $x(12) WITH (when iterating over array ~list~)

    • Should be $x(11) // count start from 0, not 1

  • ACTION_MATCH $x(15) WITH (when iterating over array ~other~)

    • Should be $x(14) // count start from 0, not 1

  • ACTION_MATCH $x(7) WITH (when iterating over array ~slayer~)

    • Not sure what you wanted to do here, seems to be a copy/paste error...?
      I mean, it should only apply to bgee, bg2ee, eet, and since the resrefs appear to be the same in both games, there should be no need for the "game" variable...

  • CREATE SPL ~SPINHUM~

    • This SPL file already exists as a game resource. Guess you meant

      COPY_EXISTING ~spinhum.spl~ ~override~

       

Edited by Luke
Posted

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.

Posted
20 hours ago, kjeron said:

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

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

Posted (edited)
4 hours ago, kjeron said:

SPINHUM doesn't exist in every game.

True (I recalled wrong, sorry...)

4 hours ago, kjeron said:

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

I see.

So are you saying that the vanilla approach (i.e., applying a 0-second "Set to 0" op31 effect before dealing Magic damage via op12) is not really safe...?

4 hours ago, kjeron said:

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:

OK, I see.

However, it can be problem when using "MODDER fun_args fail"...

 

Some other things:

  • 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...
  • LPF "ADD_SPELL_EFFECT" INT_VAR "opcode" = 206 "target" = 2 "parameter1" = 26011 "duration" = 180 STR_VAR "resource" = ~%SLAYER_START%~ END // Protection from spell (when iterating over array "slayer")

    • 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...?

  • LAF alter_poly_item INT_VAR hostile = $x(5) STR_VAR item_ cre_ RET_ARRAY POLYITEM END (when iterating over array "slayer")

    • guess that this one does not need to return array "POLYITEM" since it's the last call...

  • 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...

Edited by Luke

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...