User:Candlemaster/Unenchanter

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search

Unenchanter[edit | edit source]

These scripts require OBSE

The goal of the script is to take any enchanted item inside the container, remove enchantments from enchanted items, and create an "invert sigil stone" containing the effects that you just took off the item. Originally my idea was to allow the player to retrieve sigil stones that they've already used by separating them from the enchanted item, but this is far more versatile (and possible). This would allow players to transfer enchantments from one item to another, or to save an item's enchantment for later. No longer do you have to wait to get the highest level item possible before using that transcendant sigil stone, you could simply extract it's effects later.

Intentional omissions:

  • Any ammunition (ie, arrows)
  • Any staff (as it's impossible to get an unenchanted staff anyway)
  • Any item containing a Script Effect enchantment (This is to avoid conflicts with the item's script)

First Attempt[edit | edit source]

scn HVHGTUnenchanterScript

long NumEffects
long CurrentEffect
short DoOnce
ref Myself
ref cInvObj
ref NewStone

Begin OnActivate
	Activate
	Set DoOnce to 1
End

Begin GameMode
	if HVHGTOBSE.HasOBSE == 0 ;Basically checks for the presence of OBSE
		return
	else
		if DoOnce == 0 
			return
		endif
		set Myself to GetSelf
		array_var Items
		ForEach Items <- Myself.GetItems
			let cInvObj := Items["Value"]
			if eval ( GetEnchantment cInvObj == 0 || GetObjectType cInvObj == 34 ) ;Only work on enchanted non-arrows
				PrintToConsole "Skipped an inappropriate item"
				Continue ;This ran fine when I placed a non-enchanted ring into the container
			endif
			if eval ( GetObjectType cInvObj == 33 ) ;Special consideration for weapons
				if eval ( GetWeaponType == 4 ) ;Don't do anything to a staff
					PrintToConsole "Skipped an inappropriate item"
					Continue ;I experienced a CTD when placing an enchanted staff into the container
				endif
				let NumEffects := GetMagicItemEffectCount cInvObj
				let CurrentEffect := 0
				if NumEffects > 0
					Label
					if eval ( IsNthEffectItemScripted cInvObj CurrentEffect )
						PrintToConsole "Skipped a scripted item"
						Continue
					endif
					set CurrentEffect to ( CurrentEffect + 1 )
					if ( CurrentEffect < NumEffects )
						GoTo ;The loop ends here, but only if you have no more effects to go through.
					endif
					PrintToConsole "Found an appropriate item"
					let NewStone := CloneForm HVHGTInvertSigilStoneBase
					RemoveNthEffectItem newStone 0
					CopyAllEffectItems cInvObj NewStone
					Myself.AddItem NewStone 1
					RemoveEnchantment cInvObj
					PrintToConsole "An item has been Unenchanted"
				endif
			else
				let NumEffects := GetMagicItemEffectCount cInvObj
				let CurrentEffect :=0
				if NumEffects > 0
					Label
					if eval ( IsNthEffectItemScripted cInvObj CurrentEffect )
						PrintToConsole "Skipped a scripted item"
						Continue
					endif
					set CurrentEffect to ( CurrentEffect + 1 )
					if ( CurrentEffect < NumEffects )
						GoTo ;The loop ends here, but only if you have no more effects to go through.
					endif
					PrintToConsole "Found an appropriate item"
					let NewStone := CloneForm HVHGTInvertSigilStoneBase
					RemoveNthEffectItem newStone 0
					CopyAllEffectItems cInvObj NewStone
					Myself.AddItem NewStone 1
					RemoveEnchantment cInvObj
					PrintToConsole "An item has been Unenchanted"
				endif
			endif
		Loop
		set DoOnce to 0
	endif
End

When tested, I placed a plain, unenchanted brass ring into the container. I got the console printout for "Found an inappropriate item", and all was well. However, when I placed an enchanted staff into the container (which should have triggered the same result as the unenchanted ring), I got a crash to desktop.

Second Attempt[edit | edit source]

scn HVHGTUnenchanterScript

long NumEffects
short DoOnce
ref Myself
ref cInvObj
ref TempEnch
ref NewStone

Begin onactivate
	Activate
	Set DoOnce to 1
End

Begin GameMode
	if HVHGTOBSE.HasOBSE == 0 ;Basically checks for the presence of OBSE
		return
	else
		if DoOnce == 0 
			return
		endif
		let Myself := GetSelf
		array_var Items
		ForEach Items <- Myself.GetItems
			let cInvObj := Items["Value"]
			if eval ( GetEnchantment cInvObj == 0 || IsAmmo cInvObj || IsBook cInvObj ) ;Only work on enchanted non-arrows
				PrintToConsole "Skipped an innapropriate item"
				Continue
			endif
			if eval ( IsWeapon cInvObj ) ;Special consideration for weapons
				if eval ( GetWeaponType cInvObj == 4 ) ;Don't do anything to a staff
					PrintToConsole "Skipped an innapropriate item"
					Continue
				endif
				let TempEnch := GetEnchantment cInvObj
				let NumEffects := GetMagicItemEffectCount TempEnch
				if NumEffects > 0
					if eval ( MagicItemHasEffect SEFF TempEnch )
						PrintToConsole "Skipped a scripted item"
						Continue
					endif
					PrintToConsole "Found an appropriate item"
					let NewStone := CloneForm HVHGTInvertSigilStoneBase
					CopyAllEffectItems TempEnch NewStone
					RemoveNthEffectItem newStone 0
					Myself.AddItem NewStone 1
					RemoveEnchantment cInvObj
					PrintToConsole "An item has been Unenchanted"
					Continue
				endif
			else
				let TempEnch := GetEnchantment cInvObj
				let NumEffects := GetMagicItemEffectCount TempEnch
				if NumEffects > 0
					if eval ( MagicItemHasEffect SEFF TempEnch )
						PrintToConsole "Skipped a scripted item"
						Continue
					endif
					PrintToConsole "Found an appropriate item"
					let NewStone := CloneForm HVHGTInvertSigilStoneBase
					CopyAllEffectItems TempEnch NewStone
					RemoveNthEffectItem newStone 0
					Myself.AddItem NewStone 1
					RemoveEnchantment cInvObj
					PrintToConsole "An item has been Unenchanted"
					Continue
				endif
			endif
		Loop
		set DoOnce to 0
	endif
End

This is my latest version of the script. In general it is the same, except I've placed Continues throughout the loop to help with processing times. I've replaced and fixed a couple of key things, most importantly are the removal of the loop-within-a-loop, replacing it with MagicItemHasEffect SEFF, but more importantly I moved RemoveNthEffectItem NewStone 0 to after CopyAllEffectItems. I believe that this is what was causing the CTD's, as HVHGTInvertSigilStoneBase has only one effect on it, RemoveNthEffectItem was rendering it effectless. Also, I've added checks to make sure it wont unenchant scrolls.

When testing, the script ran as desired. Items placed into the container were stripped of their enchantment, and a sigil stone containing a copy of the item's enchantment was added. The only bug is that the created sigil stone doesn't retain the enchantment's charge, but instead sets it to the number of uses set in the base invert sigil stone. I'm not sure if it's possible to set this value in script, to retain charge information.