Jump to content

Is there a maximum number of Script Properties? {script help)


marthgun

Recommended Posts

I have about 100 script properties and 1500 lines of code, on a clean new vanilla game, everything works wonderfully,

 

add in my 200 mods, its creating massive stack overload ( my papy log was 25mb   :facepalm:   ), and all of it has to do with script properties have a null value (none).

 

what's worse, is that it appears to be bypassing Event overrides, this being a child script with both parent and child having states.  Nevertheless, it should still be filling properties, i've triple checked my plugin, everything is connected, but i was using dummy scripts (with just the properties) as the initial compile in the Creationkit because the CK's papy editor has a 757 line limit.  then just manually placing in my compiled pex file into the /Scripts/ folder.

 

I'm just not really sure how to begin to test for this.

Link to comment
Share on other sites

It's a wise move to use smaller scripts for debugging purposes. This guide is a good precis on types of papyrus errors.

Is there anything of note in the papyrus logs with just the 200 mods (no script)?

Link to comment
Share on other sites

It's a wise move to use smaller scripts for debugging purposes. This guide is a good precis on types of papyrus errors.

Is there anything of note in the papyrus logs with just the 200 mods (no script)?

 

thank you for the reply,

 

there are only the standard initializations from mods like campfire, nothing unexpected after gameload,  i tested with my level 53 char that has all kinds of perks and stuff going on, i am extremely diligent about keeping my mods working together, i have not even had a random crash one time in SSE.

 

the thing is even though i have such a massive script, its actually pretty simple and evaluates very quickly.  I've optimized it with as little latent calls as possible, followed every procedure I know how.  doesn't mean i haven't broken something,

 

but i wonder if i should be breaking up some of my functions into a script that i import.  I assumed that would create even more overhead, but as of right now I do not know how to fill properties on imported scripts, even if that's the problem.  I'll check out your links, thanks again.

Link to comment
Share on other sites

It's a wise move to use smaller scripts for debugging purposes. This guide is a good precis on types of papyrus errors.

Is there anything of note in the papyrus logs with just the 200 mods (no script)?

 

as to the papyrus errors, i have an OnActivate event, which contains a menu that i operate through functions, it is evaluating the script line for line, each variable is returning none and it often repeats the call to the stack, once (i guess) a certain call limit is reached it moves to the next variable, i mean they are all practically identical errors, which is why i *assumed* that the properties were not properly filling, this OnActivate is outside of any States, and since it is THIS script attached to the object, therefore it should override those in the parent script and in the internal States.  However, it is almost like its evaluating these simutaneously, like one thread is running my OnActivate block, while another is skipping to a State because my blockActivation is not working on the heavily modded version for reasons im unsure about.  edit: that's confusing, i mean its like its evaluating the parent OnActivate block which then calls .activate on self, i.e activate(self As ObjectReference).  otherwise i find it impossible to explain me getting into my OnActivate block

error: None is not a valid inventory item

error: Cannot call Show() on a None object, aborting function call

etc
Link to comment
Share on other sites

Just to make sure...  Have you filled the properties with the correct data either directly in the CK via the properties window or by assigning data to it in a previous function/event?

Link to comment
Share on other sites

Just to make sure...  Have you filled the properties with the correct data either directly in the CK via the properties window or by assigning data to it in a previous function/event?

 

yes, I created a dummy script with just the Scriptname header line and the Properties, compiled it in the CK, and then filled all the properties, saved, closed CK, checked in xEdit, then copied the compiled pex to the /Scripts/ folder,

 

I used the exact names of every base object so I can Auto-Fill the properties.  

 

upon removing all mods from my modlist, and coc'ing to my test area, the trap warehouse and various other places, everything works very fast with no papy log complaints and all things appearing as they should

 

edit: i should add that im compiling as much info as possible before i start getting into this hardcore tomorrow.  so far its done to just adding debug notifications block by block to find out exactly how this thing is going pear shaped, breaking off my functions into another script and testing.

Link to comment
Share on other sites

Without anything to look at, it's just guesswork. Does the script extend the right parent object? Also ref DayDreamers comment.

Both scripts, both are vanilla scripts:

psc file:  https://drive.google.com/open?id=0B858bpwZmkmiRGJVeWRGS096cjg

scriptName PressurePlate extends TrapTriggerBase
;
;
;
;================================================================
;Begin Marthgun Edit ;

	; Pressure Plates

	; Stone01 (small)
	STATIC Property aaaEKKtrapstonepressureplate01  	Auto
	STATIC Property aaaEKPtrapstonepressureplate01  	Auto  
	STATIC Property aaaEKStrapstonepressureplate01  	Auto  
	STATIC Property aaaEPPtrapstonepressureplate01  	Auto  
	STATIC Property aaaESPtrapstonepressureplate01  	Auto  
	STATIC Property aaaESStrapstonepressureplate01  	Auto  
	STATIC Property aaaLPtrapstonepressureplate01  		Auto
	STATIC Property aaaDweForktrapstonepressureplate01  Auto
	STATIC Property aaaStone_1LP_3Dwe 					Auto
	STATIC Property aaaStone_1Pick_1LP_1Dwe 			Auto
	STATIC Property aaaStone_1Pick_2Dwe 				Auto
	STATIC Property aaaStone_1Pick_2LP 					Auto
	STATIC Property aaaStone_1Sciss_1LP_1Dwe 			Auto
	STATIC Property aaaStone_1Sciss_2Dwe 				Auto
	STATIC Property aaaStone_1Sciss_2LP 				Auto
	STATIC Property aaaStone_1Screw_1LP_1Dwe 			Auto
	STATIC Property aaaStone_1Screw_2Dwe 				Auto
	STATIC Property aaaStone_1Screw_2LP 				Auto
	STATIC Property aaaStone_2LP_2Dwe 					Auto
	STATIC Property aaaStone_3LP_1Dwe 					Auto
	; Stone02 (large)
	STATIC Property aaaEKKtrapstonepressureplate02  	Auto
	STATIC Property aaaEKPtrapstonepressureplate02  	Auto
	STATIC Property aaaEKStrapstonepressureplate02  	Auto
	STATIC Property aaaEPPtrapstonepressureplate02  	Auto
	STATIC Property aaaESPtrapstonepressureplate02  	Auto
	STATIC Property aaaESStrapstonepressureplate02 		Auto
	STATIC Property aaaLPtrapstonepressureplate02  		Auto
	STATIC Property aaaDWEtrapstonepressureplate02  	Auto
	STATIC Property aaaStone02_1LP_3Dwe 				Auto
	STATIC Property aaaStone02_1Pick_1LP_1Dwe 			Auto
	STATIC Property aaaStone02_1Pick_2Dwe				Auto
	STATIC Property aaaStone02_1Pick_2LP				Auto
	STATIC Property aaaStone02_1Sciss_1LP_1Dwe			Auto
	STATIC Property aaaStone02_1Sciss_2Dwe				Auto
	STATIC Property aaaStone02_1Sciss_2LP				Auto
	STATIC Property aaaStone02_1Screw_1LP_1Dwe			Auto
	STATIC Property aaaStone02_1Screw_2Dwe				Auto
	STATIC Property aaaStone02_1Screw_2LP				Auto
	STATIC Property aaaStone02_2LP_2Dwe					Auto
	STATIC Property aaaStone02_3LP_1Dwe					Auto 
	; Dwemer Stone 
	STATIC Property aaaDWEtrappressureplatedwe01  		Auto 
	STATIC Property aaaEKKtrappressureplatedwe01  		Auto  
	STATIC Property aaaEKPtrappressureplatedwe01  		Auto  
	STATIC Property aaaEPPtrappressureplatedwe01  		Auto  
	STATIC Property aaaEPStrappressureplatedwe01  		Auto  
	STATIC Property aaaESStrappressureplatedwe01  		Auto  
	STATIC Property aaaEKStrappressureplatedwe01  		Auto  
	STATIC Property aaaLPtrappressureplatedwe01  		Auto 
	STATIC Property aaaDWE_1LP_3Dwe 					Auto
	STATIC Property aaaDWE_1Pick_1LP_1Dwe 				Auto
	STATIC Property aaaDWE_1Pick_2Dwe 					Auto
	STATIC Property aaaDWE_1Pick_2LP 					Auto
	STATIC Property aaaDWE_1Sciss_1LP_1Dwe 				Auto
	STATIC Property aaaDWE_1Sciss_2Dwe 					Auto
	STATIC Property aaaDWE_1Sciss_2LP 					Auto
	STATIC Property aaaDWE_1Screw_1LP_1Dwe 				Auto
	STATIC Property aaaDWE_1Screw_2Dwe					Auto
	STATIC Property aaaDWE_1Screw_2LP 					Auto
	STATIC Property aaaDWE_2LP_2Dwe 					Auto
	STATIC Property aaaDWE_3LP_1Dwe						Auto
	; Metal
	STATIC Property aaaECCtrappressureplatemetal01  	Auto  
	STATIC Property aaaECPtrappressureplatemetal01  	Auto  
	STATIC Property aaaEKCtrappressureplatemetal01  	Auto  
	STATIC Property aaaEKKtrappressureplatemetal01  	Auto  
	STATIC Property aaaEKPtrappressureplatemetal01  	Auto  
	STATIC Property aaaEPPtrappressureplatemetal01  	Auto
	STATIC Property aaaWoodtrappressureplatemetal01 	Auto
	STATIC Property aaaMetal_1wd_1Screw					Auto
	STATIC Property aaaMetal_1wd_1Pick 					Auto
	STATIC Property aaaMetal_1wd_1Scalpel 				Auto
	; Activators
	Activator Property TrapStonePressurePlate01  		Auto
	Activator Property TrapStonePressurePlate02  		Auto  
	Activator Property TrapPressurePlateMetal01  		Auto
	Activator Property TrapPressurePlateDwe01  			Auto
	; MiscObjects
	MiscObject Property Lockpick  						Auto
	MiscObject Property DwarvenFork  					Auto
	MiscObject Property DwarvenKnife  					Auto
	MiscObject Property DwarvenSpoon  					Auto
	MiscObject Property BasicFork01  					Auto 
	MiscObject Property BasicKnife01  					Auto  
	MiscObject Property RuinsScissor  					Auto  
	MiscObject Property RuinsEmbalmingPick  			Auto  
	MiscObject Property RuinsScrewTool  				Auto
	MiscObject Property RuinsScalpel  					Auto
	MiscObject Property aaaWoodShim						Auto
	MiscObject Property aaaSharpKU						Auto
	MiscObject Property aaaSharpLockpick 				Auto
	MiscObject Property aaaSharpPick 					Auto
	; Messages  
	Message Property aaaPressurePlateMenuLarge  		Auto
	Message Property aaaPressurePlateNoItems  			Auto
	Message Property aaaPressurePlateMetalChkInv  		Auto
	Message Property aaaCheckInventoryMSG 				Auto
	Message Property aaaBonesSoundTrapMSG 				Auto
	Message Property aaaPressurePlateMetalMenu			Auto
	; IMOD
	ImageSpaceModifier Property FadeToBlackImod  		Auto  
	ImageSpaceModifier Property FadeToBlackHoldImod  	Auto 
	ImageSpaceModifier Property FadeToBlackBackImod  	Auto
	; Sound
	Sound Property aaaHammerSD 							Auto
;End Marthgun Edit

weapon property pressEffect auto
ammo property pressEffectAmmo auto

;Begin Marthgun Edit ;
	;int aiButton	 ; this may throw error
	;Constants:
	int ZERO 	= 0 
	int ONE 	= 1
	int TWO 	= 2
	int THREE 	= 3
	int FOUR 	= 4
	int FIVE 	= 5
	int SIX 	= 6
	int SEVEN 	= 7
	int EIGHT 	= 8
	int NINE 	= 9
	;end Constants
	int sharpUseAmt = 0
	bool isSuccessful
	ObjectReference newTrap
	
	Event OnInit()
		self.BlockActivation() ; keep the OnActivate from triggering onEnter event
	endEvent

	Event OnUpdateGameTime() ; force the reset to make sure we get our shit back in order
		OnReset()
	endEvent

	Event OnReset() ; on cell reset turn in back to normal
		if (newTrap)
			newTrap.Disable()
			newTrap.Delete()
			newTrap = None
			isSuccessful = None
		endif
		if (self.IsDisabled())
			self.SetDestroyed(false)
			self.Enable()
			GoToState("Inactive")
			CountUsed = ZERO
		endif
	endEvent
	
	event OnActivate( objectReference akPlayer )
		;debug.Notification("IM IN THE TRIGGER::: " + objectsInTrigger + " :::!!")
		bool isPlayer = false
 		if (akPlayer == Game.GetPlayer())
 			isPlayer = true
 		endif
		Float sneakLevel = Game.GetPlayer().GetActorValue("Sneak")
		int rand 
		int failPercent = ZERO
		if (isPlayer && sneakLevel <= 15.0 && objectsInTrigger == ZERO) 
			aaaBonesSoundTrapMSG.Show()
			self.BlockActivation() ; block it again
		elseif(isPlayer && objectsInTrigger == ZERO)
			if (self.GetBaseObject() == TrapPressurePlateMetal01)
				MetalMenu(ZERO, akPlayer)
			else
				Menu(ZERO, akPlayer)
			endif
			if (isSuccessful)
				if (sneakLevel < 30.0)
					failPercent = THREE + sharpUseAmt
				elseif (sneakLevel >= 30.0 && sneakLevel < 60.0)
					failPercent = SEVEN + sharpUseAmt
				elseif (sneakLevel >= 60.0 && sneakLevel < 80.0)
					failPercent = 20 + sharpUseAmt
				elseif (sneakLevel >= 80.0)
					failPercent = 1000
				endif
				rand = Utility.RandomInt(ONE, failPercent) ; fix this
				if (rand == TWO)
					self.Activate(akPlayer, true)
					self.Disable()
					;Utility.Wait(ONE)
					debug.Notification("You unwittingly set off the trap!")
					;FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)
					;FadeToBlackBackImod.Remove()
					Game.EnablePlayerControls()
				else
					self.Disable() 
					debug.Notification("Trap Bypassed")
					;Utility.Wait(ONE)
					;FadeToBlackHoldImod.PopTo(FadeToBlackBackImod)
					;FadeToBlackBackImod.Remove()
					Game.EnablePlayerControls()
				endif
				;IMPORTANT THIS ONLY UPDATES THE SELF, I.E. OBJECT ATTACHED TO SCRIPT
				RegisterForSingleUpdateGameTime(240) ; every 240 hours or 10 days
				;IT DOESN'T UPDATE EVERY SCRIPT!!
			endif
		else
			;debug.Notification(">>>>>did this reactivate???")
			if (!isSuccessful)
				self.Activate(akPlayer, true)
			endif
		endif
	endEvent

;end Marthgun Edit ;


State Active
	Event onBeginState()
		objectReference selfRef = self
		goToState( "DoNothing" )
		;pressEffect.fire(selfRef, pressEffectAmmo)
		; EFFECT IS HERE ^^^^^ UNCOMMENT ONCE PROJECTILES OR PARTICLES CAN LEAVE A TRIGGER BOX CORRECTLY
; 		debug.Trace(self + ": is calling onBeginState Active")
; 		debug.Trace(self + ": StoredTriggerType = " + StoredTriggerType + ", objectsInTrigger = " + objectsInTrigger)
		if (StoredTriggerType == ONE)
			Type = THREE
			utility.wait(0.1)
			activate(self as objectReference)
			utility.wait(0.1)
			;Type = 1
		else
			activate(self as objectReference)
		endif
		;playAnimationAndWait( "trigger", "reset" )
		TriggerSound.play(self)
		playAnimation("Down")
		if objectsInTrigger == ZERO
			goToState( "Inactive" )
			playAnimation("Up")
		endif
	endEvent

	event OnTriggerEnter( objectReference triggerRef )	
; 		;debug.TRACE(self + " has been entered by " + triggerRef)
		objectsInTrigger = self.GetTriggerObjectCount()
	endEvent
	
	event OnTriggerLeave( objectReference triggerRef )
; 		;debug.TRACE(self + " has been exited by " + triggerRef)
		objectsInTrigger = self.GetTriggerObjectCount()
		if objectsInTrigger == ZERO
			goToState ("Inactive")
			playAnimation("Up")
		endif
	endEvent
endState

State DoNothing			;Dummy state, don't do anything if animating
	event OnTriggerEnter( objectReference triggerRef )	
; 		debug.TRACE(self + " has been entered by " + triggerRef)
		objectsInTrigger = self.GetTriggerObjectCount()
	endEvent
	
	event OnTrigger( objectReference triggerRef )	
	endEvent
	
	event OnTriggerLeave( objectReference triggerRef )
; 		debug.TRACE(self + " has been exited by " + triggerRef)
		objectsInTrigger = self.GetTriggerObjectCount()
		if objectsInTrigger == ZERO
			goToState ("Inactive")
			playAnimation("Up")
		endif
	endEvent
EndState

;Begin Marthgun Edit ;

	State ShutItDown  ;;make sure script stops
		;no more scripty running
		;self.Disable(True) ;causes problems here
	EndState

	Function replaceMesh(int meshID, ObjectReference akPlayer)
		;FadeToBlackImod.Apply()
		Float posX = self.GetPositionX()
		Float posY = self.GetPositionY()
		Float posZ = self.GetPositionZ()
		Float angX = self.GetAngleX()
		Float angY = self.GetAngleY()
		Float angZ = self.GetAngleZ()
		if (self.GetBaseObject() == TrapStonePressurePlate01)
			if (meshID == ONE) ; lockpicks
				newTrap = akPlayer.placeAtMe(aaaLPtrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == TWO) ; kitchen utensils
				newTrap = akPlayer.placeAtMe(aaaDweForktrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 20) ; 2picks
				newTrap = akPlayer.placeAtMe(aaaEPPtrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 21) ; 1pick, 1Scissor
				newTrap = akPlayer.placeAtMe(aaaESPtrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 22) ; 1pick, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKPtrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 23) ; 2Scissors
				newTrap = akPlayer.placeAtMe(aaaESStrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 24) ; 1Scissor, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKStrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 25) ; 2Screws
				newTrap = akPlayer.placeAtMe(aaaEKKtrapstonepressureplate01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 72) ; 1lp 3ku
				newTrap = akPlayer.placeAtMe(aaaStone_1LP_3Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 73) ; 2lp 2ku
				newTrap = akPlayer.placeAtMe(aaaStone_2LP_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 74) ; 3lp 1ku
				newTrap = akPlayer.placeAtMe(aaaStone_3LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 75) ; 2lp 1screw
				newTrap = akPlayer.placeAtMe(aaaStone_1Screw_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 76) ; 2lp 1pick
				newTrap = akPlayer.placeAtMe(aaaStone_1Pick_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 77) ; 2lp 1scissor
				newTrap = akPlayer.placeAtMe(aaaStone_1Sciss_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 78) ; 1lp 1ku 1screw
				newTrap = akPlayer.placeAtMe(aaaStone_1Screw_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 79) ; 1lp 1ku 1pick
				newTrap = akPlayer.placeAtMe(aaaStone_1Pick_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 80) ; 1lp 1ku 1scissor
				newTrap = akPlayer.placeAtMe(aaaStone_1Sciss_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 81) ; 2ku 1screw
				newTrap = akPlayer.placeAtMe(aaaStone_1Screw_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 82) ; 2ku 1pick
				newTrap = akPlayer.placeAtMe(aaaStone_1Pick_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 83) ; 2ku 1scissor
				newTrap = akPlayer.placeAtMe(aaaStone_1Sciss_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			endif 
		elseif (self.GetBaseObject() == TrapStonePressurePlate02)
			;FadeToBlackImod.Apply()
			if (meshID == ONE) ; lockpicks
				newTrap = akPlayer.placeAtMe(aaaLPtrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == TWO) ; kitchen utensils
				newTrap = akPlayer.placeAtMe(aaaDWEtrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 20) ; 2picks
				newTrap = akPlayer.placeAtMe(aaaEPPtrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 21) ; 1pick, 1Scissor
				newTrap = akPlayer.placeAtMe(aaaESPtrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 22) ; 1pick, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKPtrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 23) ; 2Scissors
				newTrap = akPlayer.placeAtMe(aaaESStrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 24) ; 1Scissor, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKStrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 25) ; 2Screws
				newTrap = akPlayer.placeAtMe(aaaEKKtrapstonepressureplate02, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 72) ; 1lp 3ku
				newTrap = akPlayer.placeAtMe(aaaStone02_1LP_3Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 73) ; 2lp 2ku
				newTrap = akPlayer.placeAtMe(aaaStone02_2LP_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 74) ; 3lp 1ku
				newTrap = akPlayer.placeAtMe(aaaStone02_3LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 75) ; 2lp 1screw
				newTrap = akPlayer.placeAtMe(aaaStone02_1Screw_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 76) ; 2lp 1pick
				newTrap = akPlayer.placeAtMe(aaaStone02_1Pick_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 77) ; 2lp 1scissor
				newTrap = akPlayer.placeAtMe(aaaStone02_1Sciss_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 78) ; 1lp 1ku 1screw
				newTrap = akPlayer.placeAtMe(aaaStone02_1Screw_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 79) ; 1lp 1ku 1pick
				newTrap = akPlayer.placeAtMe(aaaStone02_1Pick_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 80) ; 1lp 1ku 1scissor
				newTrap = akPlayer.placeAtMe(aaaStone02_1Sciss_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 81) ; 2ku 1screw
				newTrap = akPlayer.placeAtMe(aaaStone02_1Screw_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 82) ; 2ku 1pick
				newTrap = akPlayer.placeAtMe(aaaStone02_1Pick_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 83) ; 2ku 1scissor
				newTrap = akPlayer.placeAtMe(aaaStone02_1Sciss_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			endif 
		elseif (self.GetBaseObject() == TrapPressurePlateDwe01)
			;FadeToBlackImod.Apply()
			if (meshID == ONE) ; lockpicks
				newTrap = akPlayer.placeAtMe(aaaLPtrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == TWO) ; kitchen utensils
				newTrap = akPlayer.placeAtMe(aaaDWEtrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 20) ; 2picks
				newTrap = akPlayer.placeAtMe(aaaEPPtrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 21) ; 1pick, 1Scissor
				newTrap = akPlayer.placeAtMe(aaaEPStrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 22) ; 1pick, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKPtrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 23) ; 2Scissors
				newTrap = akPlayer.placeAtMe(aaaESStrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 24) ; 1Scissor, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKStrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 25) ; 2Screws
				newTrap = akPlayer.placeAtMe(aaaEKKtrappressureplatedwe01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 72) ; 1lp 3ku
				newTrap = akPlayer.placeAtMe(aaaDWE_1LP_3Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 73) ; 2lp 2ku
				newTrap = akPlayer.placeAtMe(aaaDWE_2LP_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 74) ; 3lp 1ku
				newTrap = akPlayer.placeAtMe(aaaDWE_3LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 75) ; 2lp 1screw
				newTrap = akPlayer.placeAtMe(aaaDWE_1Screw_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 76) ; 2lp 1pick
				newTrap = akPlayer.placeAtMe(aaaDWE_1Pick_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 77) ; 2lp 1scissor
				newTrap = akPlayer.placeAtMe(aaaDWE_1Sciss_2LP, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 78) ; 1lp 1ku 1screw
				newTrap = akPlayer.placeAtMe(aaaDWE_1Screw_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 79) ; 1lp 1ku 1pick
				newTrap = akPlayer.placeAtMe(aaaDWE_1Pick_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 80) ; 1lp 1ku 1scissor
				newTrap = akPlayer.placeAtMe(aaaDWE_1Sciss_1LP_1Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 81) ; 2ku 1screw
				newTrap = akPlayer.placeAtMe(aaaDWE_1Screw_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 82) ; 2ku 1pick
				newTrap = akPlayer.placeAtMe(aaaDWE_1Pick_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 83) ; 2ku 1scissor
				newTrap = akPlayer.placeAtMe(aaaDWE_1Sciss_2Dwe, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			endif 
		elseif (self.GetBaseObject() == TrapPressurePlateMetal01)
			;FadeToBlackImod.Apply()
			if (meshID == 90) ; Quick Hack 1wd 1Screw
				newTrap = akPlayer.placeAtMe(aaaMetal_1wd_1Screw, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 91) ; 1wd 1pick
				newTrap = akPlayer.placeAtMe(aaaMetal_1wd_1Pick, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 92) ; 1wd 1scalpel
				newTrap = akPlayer.placeAtMe(aaaMetal_1wd_1Scalpel, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 30) ; 2picks
				newTrap = akPlayer.placeAtMe(aaaEPPtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 31) ; 1pick, 1Scalpel
				newTrap = akPlayer.placeAtMe(aaaECPtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 32) ; 1pick, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKPtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 33) ; 2Scalpel
				newTrap = akPlayer.placeAtMe(aaaECCtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 34) ; 1Scalpel, 1Screw
				newTrap = akPlayer.placeAtMe(aaaEKCtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == 35) ; 2Screws
				newTrap = akPlayer.placeAtMe(aaaEKKtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			elseif (meshID == THREE) ; wood shims
				newTrap = akPlayer.placeAtMe(aaaWoodtrappressureplatemetal01, ONE)
				newTrap.setPosition(posX, posY, posZ)
				newTrap.setAngle(angX, angY, angZ)
			endif
		endif
	endFunction

	Function MetalMenu(int aiButton, ObjectReference akPlayerRef)
		; Menu Items Reference:
		; 0: Quick Hack 			: just make it work; uses all other options
		; 1: Emabalming Tools 		; use whatever Emabalming Tools that work
		; 2: Wood Shims 			; use wood shims
		; 3: [Check Inventory]		; a list of what you have and what it works on
		; 4: [Exit Menu] 			; quit menu back to game
		int irScalpel = akPlayerRef.GetItemCount(RuinsScalpel)
		int irPick 	  = akPlayerRef.GetItemCount(RuinsEmbalmingPick)
		int irScrew   = akPlayerRef.GetItemCount(RuinsScrewTool)
		int iWoodShim = akPlayerRef.GetItemCount(aaaWoodShim)
		int sharpPick = akPlayerRef.GetItemCount(aaaSharpPick)
		bool abMenu   = true
		While (abMenu)
			int rand = Utility.RandomInt(ZERO, FIVE)
			aiButton =  aaaPressurePlateMetalMenu.Show()
			if (aiButton == ZERO)
				; Quick Hack - use whatever you gots 
				abMenu = MetalQuickHack(akPlayerRef, irPick, irScrew, irScalpel, iWoodShim, rand, sharpPick)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == ONE)
				; Embalming Tools
				abMenu = MetalEmbalmingTools(akPlayerRef, irPick, irScrew, irScalpel, rand, sharpPick)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == TWO)
				; Wood Shims
				abMenu = MetalWoodShims(akPlayerRef, iWoodShim)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == THREE)
				; [CheckInventory]
				aaaPressurePlateMetalChkInv.Show(iWoodShim, irScalpel, irScrew, irPick, sharpPick)
				abMenu = true
			elseif (aiButton == FOUR) 
				; [Metal exit]
				abMenu = false
			endif
		EndWhile
	endFunction
	Function Menu(int aiButton, ObjectReference akPlayerRef)
		; Menu Items Reference:
		; 0: Quick Hack 			: just make it work; uses all other options
		; 1: LockPicks 				: use four LockPicks
		; 2: KitchenUtensils		: use any kitchen knives,spoons,forks
		; 3: Emabalming Tools 		; use whatever Emabalming Tools that work
		; 4: [Check Inventory]		; a list of what you have and what it works on
		; 5: [Exit Menu] 			; quit menu back to game
		; Removed:   Mixed Hack 	; it was too similar to Quick Hack, more to let player know they can mix/match
		int ibKnife   = akPlayerRef.GetItemCount(BasicKnife01)
		int ibFork    = akPlayerRef.GetItemCount(BasicFork01)
		int idKnife   = akPlayerRef.GetItemCount(DwarvenKnife)
		int idFork    = akPlayerRef.GetItemCount(DwarvenFork)
		int idSpoon   = akPlayerRef.GetItemCount(DwarvenSpoon)
		int irScissor = akPlayerRef.GetItemCount(RuinsScissor)
		int irPick 	  = akPlayerRef.GetItemCount(RuinsEmbalmingPick)
		int irScrew   = akPlayerRef.GetItemCount(RuinsScrewTool)
		int iLockpick = akPlayerRef.GetItemCount(Lockpick)
		int sharpKU   = akPlayerRef.GetItemCount(aaaSharpKU)
		int sharpLP   = akPlayerRef.GetItemCount(aaaSharpLockpick)
		int sharpPick = akPlayerRef.GetItemCount(aaaSharpPick)
		int kuTotal   = ibKnife + ibFork + idKnife + idFork + idSpoon + sharpKU
		bool abMenu   = true
		While (abMenu)
			int rand = Utility.RandomInt(ZERO, FIVE)
			aiButton =  aaaPressurePlateMenuLarge.Show()
			if (aiButton == ZERO)
				; Quick hack
				abMenu = QuickHack(akPlayerRef, iLockpick, ibKnife, ibFork, idKnife, idFork, idSpoon, \
												irScissor, irPick, irScrew, kuTotal, rand, aiButton,  \
												sharpKU, sharpLP, sharpPick)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == ONE)
				; Lockpicks(4)
				abMenu = FourLockPicks(akPlayerRef, iLockpick, aiButton, sharpLP)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == TWO)
				; Kitchen Utensils
				abMenu = KitchenUtensils(akPlayerRef, ibKnife, ibFork, idKnife, idFork, idSpoon, \
																				aiButton, sharpKU)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == THREE)
				; Embalming Tools
				abMenu = EmabalmingTools(akPlayerRef, irScrew, irPick, irScissor, rand, sharpPick)
				if (!abMenu)
					Game.DisablePlayerControls()
					;FadeToBlackImod.PopTo(FadeToBlackHoldImod)
					;Utility.Wait(ONE)
					aaaHammerSD.PlayandWait(self)
				endif
			elseif (aiButton == FOUR)
				; [Check Inventory]
				aaaCheckInventoryMSG.Show(iLockpick, sharpLP, (kuTotal - sharpKU), sharpKU, irScrew, \
																		irScissor, irPick, sharpPick)
				abMenu = true
			elseif (aiButton == FIVE) 
				; [Exit]
				;goToState("Inactive") ; not sure i want to start this state might trigger trap event
				abMenu = false
			endif
		EndWhile
	endFunction

	Bool Function MetalQuickHack(ObjectReference akPlayerRef, int irPick, int irScrew, int irScalpel, \
															  int iWoodShim, int rand, int sharpPick)
		int randMetal = Utility.RandomInt(ZERO,ONE)
		int irToolsTotal = irPick + irScrew + irScalpel + sharpPick
		bool abMenu = true ; just incase something happens we can go back into menumode
		bool hasPick
		if (irPick > ZERO || sharpPick > ZERO)
			hasPick = true
		endif
		if (hasPick && irScrew > ZERO && irScalpel > ZERO && iWoodShim > ZERO)
			if (rand == ZERO || rand == FIVE)
				replaceMesh(90, akPlayerRef) ; 1wd 1screw
				akPlayerRef.RemoveItem(aaaWoodShim, ONE)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				isSuccessful = true
				abMenu = false
			elseif(rand == ONE || rand == FOUR)
				replaceMesh(91, akPlayerRef) ; 1wd 1pick 
				akPlayerRef.RemoveItem(aaaWoodShim, ONE)
				if (irPick >= ONE)
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				elseif (sharpPick >= ONE)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt = ONE
				endif
				isSuccessful = true
				abMenu = false
			elseif(rand == TWO || rand == THREE)
				replaceMesh(92, akPlayerRef) ; 1wd 1scalpel
				akPlayerRef.RemoveItem(aaaWoodShim, ONE)
				akPlayerRef.RemoveItem(RuinsScalpel, ONE)
				isSuccessful = true
				abMenu = false
			endif
		elseif (irToolsTotal >= TWO && iWoodShim >= TWO)
			if (randMetal == ZERO)
				abMenu = MetalEmbalmingTools(akPlayerRef, irPick, irScrew, irScalpel, rand, sharpPick)
			elseif (randMetal == ONE)
				abMenu = MetalWoodShims(akPlayerRef, iWoodShim)
			endif
		elseif (irToolsTotal >= TWO)
			abMenu = MetalEmbalmingTools(akPlayerRef, irPick, irScrew, irScalpel, rand, sharpPick)
		elseif (iWoodShim >= TWO)
			abMenu = MetalWoodShims(akPlayerRef, iWoodShim)
		Else
			aaaPressurePlateNoItems.Show()
			abMenu = true ;send player back to menu with no items? exit menu for now
		endif
		return abMenu
	endFunction

	Bool Function MetalEmbalmingTools(ObjectReference akPlayerRef, int irPick, int irScrew, int irScalpel, \
																			   int rand, int sharpPick)
		bool abMenu = true
		if ( (irScrew + irPick + irScalpel + sharpPick) >= TWO )
			;replaceMesh(aiButton)
			;remove appropriate items
			if (irPick >= TWO && irScalpel >= TWO && irScrew >= TWO)
				if (rand == ZERO) ; 2picks
					replaceMesh(30, akPlayerRef)
					if (irPick >= TWO)
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, TWO)
					elseif (irPick == ONE && sharpPick >= ONE)
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
						akPlayerRef.RemoveItem(aaaSharpPick, ONE)
						;sharpUseAmt = ONE
					elseif (sharpPick >= TWO)
						akPlayerRef.RemoveItem(aaaSharpPick, TWO)
						;sharpUseAmt = TWO
					endif
				elseif (rand == ONE) ; 1pick, 1Scalpel
					replaceMesh(31, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScalpel, ONE)
					if (irPick >= ONE)
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
					else
						akPlayerRef.RemoveItem(aaaSharpPick, ONE)
						;sharpUseAmt = ONE
					endif
				elseif (rand == TWO) ; 1pick, 1Screw
					replaceMesh(32, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
					if (irPick >= ONE)
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
					else
						akPlayerRef.RemoveItem(aaaSharpPick, ONE)
						;sharpUseAmt = ONE
					endif
				elseif (rand == THREE) ; 2Scalpel
					replaceMesh(33, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScalpel, TWO)
				elseif (rand == FOUR) ; 1Scalpel, 1Screw
					replaceMesh(34, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScalpel, ONE)
					akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				elseif (rand == FIVE) ; 2Screws
					replaceMesh(35, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScrewTool, TWO)
				endif
			elseif (irPick >= TWO && irScalpel < TWO && irScrew < TWO) ; 2picks
				replaceMesh(30, akPlayerRef)
				if (irPick >= TWO)
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, TWO)
				elseif (irPick == ONE && sharpPick >= ONE)
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					;sharpUseAmt = ONE
				elseif (sharpPick >= TWO)
					akPlayerRef.RemoveItem(aaaSharpPick, TWO)
					;sharpUseAmt = TWO
				endif
			elseif (irScalpel >= TWO && irPick < TWO && irScrew < TWO) ; 2Scalpel
				replaceMesh(33, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScalpel, TWO)
			elseif (irScrew >= TWO && irScalpel < TWO && irPick < TWO) ; 2Screws
				replaceMesh(35, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScrewTool, TWO)
			elseif (irScrew < ONE && irPick == ONE && irScalpel == ONE) ; 1pick, 1Scalpel
				replaceMesh(31, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScalpel, ONE)
				if (irPick >= ONE)
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				else
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					;sharpUseAmt = ONE
				endif
			elseif (irScalpel < ONE && irPick == ONE && irScrew == ONE) ; 1pick, 1Screw
				replaceMesh(32, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				if (irPick >= ONE)
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				else
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					;sharpUseAmt = ONE
				endif
			elseif (irPick < ONE && irScalpel == ONE && irScrew == ONE) ; 1Scalpel, 1Screw
				replaceMesh(34, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScalpel, ONE)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
			endif
			isSuccessful = true
			abMenu = false
		else
			aaaPressurePlateNoItems.Show()
			abMenu = true
		endif
		return abMenu
	endFunction

	Bool Function MetalWoodShims(ObjectReference akPlayerRef, int iWoodShim)
		bool abMenu = true
		if (iWoodShim >= THREE)
			replaceMesh(THREE, akPlayerRef)
			akPlayerRef.RemoveItem(aaaWoodShim, TWO)
			isSuccessful = true
			abMenu = false
		Else
			aaaPressurePlateNoItems.Show()
			abMenu = true
		endif
		return abMenu
	endFunction

	Bool Function QuickHack(ObjectReference akPlayerRef, int iLockpick, int ibKnife,   int ibFork, \
														 int idKnife,   int idFork,    int idSpoon, \
														 int irScissor, int irPick,    int irScrew, \
														 int kuTotal,   int rand, 	   int aiButton, \
														 int sharpKU,   int sharpLP,   int sharpPick)
		; lets find out what the player has, then randomly select things to trap hack
		bool abMenu = true
		bool hasPicks
		bool hasLockpicks
		int ruinsTotal = irScissor + irPick + irScrew + sharpPick
		int rand2 = Utility.RandomInt(ZERO, (NINE + FIVE))
		if (irPick >= FOUR || sharpPick >= FOUR)
			hasPicks = true
		endif
		if (sharpPick >= FOUR || iLockpick >= FOUR)
			hasLockpicks = true
		endif
		if (hasLockpicks && kuTotal >= FOUR && ruinsTotal >= TWO)
			;mix and match everything
			if (rand2 == ZERO) ; 4 Kitchen Utensils
				abMenu = KitchenUtensils(akPlayerRef, ibKnife, ibFork, idKnife, idFork, idSpoon, aiButton, sharpKU)
			elseif (rand2 == ONE) ; 4 lockpicks 
				abMenu = FourLockPicks(akPlayerRef, iLockpick, aiButton, sharpLP)
			elseif (rand2 == TWO) ; 1lp, 3ku
				replaceMesh(72, akPlayerRef)
				RemoveKU(akPlayerRef, THREE, THREE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU) 					
				if (sharpLP > ZERO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					sharpUseAmt += ONE ;watch
				else
					akPlayerRef.RemoveItem(Lockpick, ONE)
				endif
				isSuccessful = true
				abMenu = false 
			elseif (rand2 == THREE) ; 2lp, 2ku
				replaceMesh(73, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += ONE ;watch these
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			elseif (rand2 == FOUR) ; 3lp, 1ku
				replaceMesh(74, akPlayerRef) ; FIX
				RemoveKU(akPlayerRef, ONE, ONE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= THREE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, THREE)
					sharpUseAmt += THREE
				elseif (sharpLP == TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, TWO)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, THREE)
				endif
				isSuccessful = true
				abMenu = false
			elseif (rand2 == FIVE) ; 2lp, 1Screw 
				replaceMesh(75, akPlayerRef) ; FIX
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt = TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			elseif (rand2 == SIX) ; 2lp, 1pick 
				replaceMesh(76, akPlayerRef)
				if (sharpPick > ZERO) 
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt = ONE ; watch out for these
				else
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false 
			elseif (rand2 == SEVEN) ; 2lp, 1Scissor
				replaceMesh(77, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt = TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
 				isSuccessful = true
				abMenu = false
			elseif (rand2 == EIGHT) ; 1lp, 1ku, 1Screw
				replaceMesh(78, akPlayerRef) ; FIX
				RemoveKU(akPlayerRef, ONE, ONE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP > ZERO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, ONE)
				endif
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				isSuccessful = true
				abMenu = false
			elseif (rand2 == NINE) ; 1lp, 1ku, 1pick
				replaceMesh(79, akPlayerRef)
				RemoveKU(akPlayerRef, ONE, ONE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP > ZERO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, ONE)
				endif
				if (sharpPick > ZERO)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt += ONE
				else 
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
				isSuccessful = true
				abMenu = false
			elseif (rand2 == NINE + ONE) ; 1lp, 1ku, 1Scissor
				replaceMesh(80, akPlayerRef)
				RemoveKU(akPlayerRef, ONE, ONE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP > ZERO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, ONE)
				endif
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				isSuccessful = true
				abMenu = false
			elseif (rand2 == EIGHT + THREE) ; 2ku 1Screw
				replaceMesh(81, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				isSuccessful = true
				abMenu = false 
			elseif (rand2 == SIX + SIX) ; 2ku, 1pick
				replaceMesh(82, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpPick > ZERO)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
				isSuccessful = true
				abMenu = false 
			elseif (rand2 == EIGHT + FIVE) ; 2ku, 1Scissor
				replaceMesh(83, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				isSuccessful = true
				abMenu = false 
			elseif (rand2 == NINE + FIVE) ;Embalming Tools
				abMenu = EmabalmingTools(akPlayerRef, irScrew, irPick, irScissor, rand, sharpPick)
			endif
		elseif ((iLockpick + sharpLP) >= THREE && kuTotal >= THREE)
			;mix and match lps and kus
			if (rand == ZERO || rand == FIVE) ; 1lp, 3ku
				replaceMesh(72, akPlayerRef) 					
				RemoveKU(akPlayerRef, THREE, THREE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP > ZERO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, ONE)
				endif
				isSuccessful = true
				abMenu = false 
			elseif (rand == ONE || rand == FOUR) ; 2lp, 2ku
				replaceMesh(73, akPlayerRef) 
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			elseif (rand == TWO || rand == THREE) ;3lp, 1ku
				replaceMesh(74, akPlayerRef) 
				RemoveKU(akPlayerRef, ONE, ONE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= THREE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, THREE)
					sharpUseAmt += THREE
				elseif (sharpLP == TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, TWO)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, THREE)
				endif
				isSuccessful = true
				abMenu = false
			endif
		elseif ((iLockPick + sharpLP) >= THREE && kuTotal <= TWO && kuTotal != ZERO)
			if (kuTotal == TWO) ; 2lp, 2ku
				replaceMesh(73, akPlayerRef) 
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			elseif (kuTotal == ONE) ; 3lp, 1ku	
				replaceMesh(74, akPlayerRef)
				RemoveKU(akPlayerRef, ONE, ONE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= THREE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, THREE)
					sharpUseAmt += THREE
				elseif (sharpLP == TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, TWO)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, THREE)
				endif
				isSuccessful = true
				abMenu = false
			endif
		elseif ((iLockpick + sharpLP) <= TWO && kuTotal >= THREE && iLockpick != ZERO)
			if (iLockpick == TWO) ; 2lp, 2ku
				replaceMesh(73, akPlayerRef) 
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt += TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			elseif (iLockpick == ONE) ; 1lp, 3ku
				replaceMesh(72, akPlayerRef) 					
				RemoveKU(akPlayerRef, THREE, THREE, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpLP > ZERO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(Lockpick, ONE)
				endif
				isSuccessful = true
				abMenu = false
			endif
		elseif ((iLockpick + sharpLP) >= TWO && ruinsTotal > ZERO)
			;mix and match lps and rts
			if (irScrew > ZERO) ; 2lp, 1Screw
				replaceMesh(75, akPlayerRef) 
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt = TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			elseif ((irPick + sharpPick) > ZERO) ; 2lp, 1pick
				replaceMesh(76, akPlayerRef) 
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt = TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				if (sharpPick > ZERO)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt += ONE
				else
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
				isSuccessful = true
				abMenu = false
			elseif (irScissor > ZERO)
				replaceMesh(77, akPlayerRef) ; 2lp 1Scissor
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				if (sharpLP >= TWO)
					akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
					sharpUseAmt = TWO
				elseif (sharpLP == ONE)
					akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
					akPlayerRef.RemoveItem(Lockpick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(Lockpick, TWO)
				endif
				isSuccessful = true
				abMenu = false
			endif
		elseif (kuTotal >= TWO && ruinsTotal > ZERO)
			;mix and match kus and rts
			if (irScrew > ZERO) ; 2ku, 1Screw
				replaceMesh(81, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				isSuccessful = true
				abMenu = false 
			elseif (irPick > ZERO) ; 2ku, 1pick
				replaceMesh(82, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				if (sharpPick > ZERO)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt += ONE
				else 
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
				isSuccessful = true
				abMenu = false 
			elseif (irScissor > ZERO) ; 2ku, 1scissor
				replaceMesh(83, akPlayerRef)
				RemoveKU(akPlayerRef, TWO, TWO, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				isSuccessful = true
				abMenu = false
			endif
		elseif (kuTotal >= FOUR)
			;just kus 
			abMenu = KitchenUtensils(akPlayerRef, ibKnife, ibFork, idKnife, idFork, idSpoon, aiButton, sharpKU)
		elseif (iLockpick >= FOUR)
			;just lps 
			abMenu = FourLockPicks(akPlayerRef, iLockpick, aiButton, sharpLP)
		elseif (ruinsTotal >= TWO)
			;just rts
			abMenu = EmabalmingTools(akPlayerRef, irScrew, irPick, irScissor, rand, sharpPick) 
		endif
		return abMenu
	endFunction

	Bool Function FourLockPicks(ObjectReference akPlayerRef, int iLockpick, int aiButton, int sharpLP)
		bool abMenu = true
		if (iLockpick >= FOUR && sharpLP < ONE)
			;replace mesh
			replaceMesh(ONE, akPlayerRef)
			;remove 4 lockpicks
			akPlayerRef.RemoveItem(Lockpick, FOUR)
			isSuccessful = true
			abMenu = false ; not sure i need to do this after going to my state, but just to make sure
		elseif (sharpLP >= FOUR)
			replaceMesh(ONE, akPlayerRef)
			akPlayerRef.RemoveItem(aaaSharpLockpick, FOUR)
			sharpUseAmt = FOUR
			isSuccessful = true
			abMenu = false
		elseif (sharpLP == THREE && iLockpick > ZERO)
			replaceMesh(ONE, akPlayerRef)
			akPlayerRef.RemoveItem(aaaSharpLockpick, THREE)
			akPlayerRef.RemoveItem(Lockpick, ONE)
			sharpUseAmt = THREE
			isSuccessful = true
			abMenu = false
		elseif (sharpLP == TWO && iLockpick > ONE)
			replaceMesh(ONE, akPlayerRef)
			akPlayerRef.RemoveItem(aaaSharpLockpick, TWO)
			akPlayerRef.RemoveItem(Lockpick, TWO)
			sharpUseAmt = TWO
			isSuccessful = true
			abMenu = false
		elseif (sharpLP == ONE && iLockpick > TWO)
			replaceMesh(ONE, akPlayerRef)
			akPlayerRef.RemoveItem(aaaSharpLockpick, ONE)
			akPlayerRef.RemoveItem(Lockpick, THREE)
			sharpUseAmt = ONE
			isSuccessful = true
			abMenu = false
		else
			aaaPressurePlateNoItems.Show()
			abMenu = true
		endif
		return abMenu
	endFunction


	Bool Function KitchenUtensils(ObjectReference akPlayerRef, int ibKnife, int ibFork, int idKnife, \
												   int idFork, int idSpoon, int aiButton, int sharpKU)
		;since the mesh is the same for all kitchen utensils, just iterate through linearly, instead of randomly
		bool abMenu = true
		if ( (ibKnife + ibFork + idKnife + idFork + idSpoon + sharpKU) >= FOUR )
			replaceMesh(TWO, akPlayerRef)
			RemoveKU(akPlayerRef, FOUR, FOUR, ibKnife, ibFork, idKnife, idFork, idSpoon, sharpKU)
			isSuccessful = true
			abMenu = false
		else 
			aaaPressurePlateNoItems.Show()
			abMenu = true
		endif
		return abMenu
	endFunction

	Bool Function EmabalmingTools(ObjectReference akPlayerRef, int irScrew, int irPick, int irScissor, \
																				int rand, int sharpPick)
		bool abMenu = true
		bool hasPicks
		if (irPick >= TWO || sharpPick >= TWO)
			hasPicks = true
		endif
		if ( (irPick + irScrew + irScissor + sharpPick) >= TWO)
			;replaceMesh(aiButton)
			;remove appropriate items
			if (hasPicks && irScissor >= TWO && irScrew >= TWO)
				if (rand == ZERO) ; 2picks
					replaceMesh(20, akPlayerRef)
					if (sharpPick >= TWO)
						akPlayerRef.RemoveItem(aaaSharpPick, TWO)
						sharpUseAmt = TWO
					elseif (sharpPick == ONE && irPick > ONE)
						akPlayerRef.RemoveItem(aaaSharpPick, ONE)
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
						sharpUseAmt = ONE
					elseif (irPick >= TWO)
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, TWO)
					endif
				elseif (rand == ONE) ; 1pick, 1Scissor
					replaceMesh(21, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScissor, ONE)
					if (sharpPick > ZERO)
						akPlayerRef.RemoveItem(aaaSharpPick, ONE)
						sharpUseAmt = ONE
					else
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
					endif
				elseif (rand == TWO) ; 1pick, 1Screw
					replaceMesh(22, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
					if (sharpPick > ZERO)
						akPlayerRef.RemoveItem(aaaSharpPick, ONE)
						sharpUseAmt = ONE
					else
						akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
					endif
				elseif (rand == THREE) ; 2Scissors
					replaceMesh(23, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScissor, TWO)
				elseif (rand == FOUR) ; 1Scissor, 1Screw
					replaceMesh(24, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScissor, ONE)
					akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				elseif (rand == FIVE) ; 2Screws
					replaceMesh(25, akPlayerRef)
					akPlayerRef.RemoveItem(RuinsScrewTool, TWO)
				endif
			elseif (hasPicks && irScissor < TWO && irScrew < TWO) ; 2picks
				replaceMesh(20, akPlayerRef)
				if (sharpPick >= TWO)
					akPlayerRef.RemoveItem(aaaSharpPick, TWO)
					sharpUseAmt = TWO
				elseif (sharpPick == ONE)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, TWO)
				endif
			elseif (irScissor >= TWO && irPick < TWO && irScrew < TWO) ; 2Scissors
				replaceMesh(23, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScissor, TWO)
			elseif (irScrew >= TWO && irScissor < TWO && irPick < TWO) ; 2Screws
				replaceMesh(25, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScrewTool, TWO)
			elseif (irScrew < ONE && irPick == ONE && irScissor == ONE) ; 1pick, 1Scissor
				replaceMesh(21, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				if (sharpPick > ZERO)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt = ONE
				else
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
			elseif (irScissor < ONE && irPick == ONE && irScrew == ONE) ; 1pick, 1Screw
				replaceMesh(22, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
				if (sharpPick > ZERO)
					akPlayerRef.RemoveItem(aaaSharpPick, ONE)
					sharpUseAmt = ONE
				else 
					akPlayerRef.RemoveItem(RuinsEmbalmingPick, ONE)
				endif
			elseif (irPick < ONE && irScissor == ONE && irScrew == ONE) ; 1Scissor, 1Screw
				replaceMesh(24, akPlayerRef)
				akPlayerRef.RemoveItem(RuinsScissor, ONE)
				akPlayerRef.RemoveItem(RuinsScrewTool, ONE)
			endif
			isSuccessful = true
			abMenu = false
		else
			aaaPressurePlateNoItems.Show()  ; maybe fix
			abMenu = true
		endif
		return abMenu
	endFunction

	Function RemoveKU(ObjectReference akPlayerRef, int amtToRemove, int iterator, int ibKnife, \
									int ibFork, int idKnife, int idFork, int idSpoon, int sharpKU)
		While (iterator > ZERO)
			if (sharpKU >= amtToRemove)
				akPlayerRef.RemoveItem(aaaSharpKU, amtToRemove)
				sharpUseAmt = amtToRemove
				iterator -= amtToRemove
			elseif (sharpKU > ZERO && sharpKU < amtToRemove)
				akPlayerRef.RemoveItem(aaaSharpKU, sharpKU)
				sharpUseAmt = sharpKU
				iterator -= sharpKU
			elseif (idKnife >= amtToRemove && iterator == amtToRemove)
				akPlayerRef.RemoveItem(DwarvenKnife, amtToRemove)
				iterator -= amtToRemove 
			elseif (idKnife > ZERO && idKnife < amtToRemove)
				akPlayerRef.RemoveItem(DwarvenKnife, idKnife)
				iterator -= idKnife
			elseif (idFork >= amtToRemove && iterator == amtToRemove)
				akPlayerRef.RemoveItem(DwarvenFork, amtToRemove)
				iterator -= amtToRemove
			elseif (idFork > ZERO && idFork < amtToRemove)
				akPlayerRef.RemoveItem(DwarvenFork, idFork)
				iterator -= idFork
			elseif (idSpoon >= amtToRemove && iterator == amtToRemove)
				akPlayerRef.RemoveItem(DwarvenSpoon, amtToRemove)
				iterator -= amtToRemove
			elseif (idSpoon > ZERO && idSpoon < amtToRemove)
				akPlayerRef.RemoveItem(DwarvenSpoon, idSpoon)
				iterator -= idSpoon
			elseif (ibKnife >= amtToRemove && iterator == amtToRemove)
				akPlayerRef.RemoveItem(BasicKnife01, amtToRemove)
				iterator -= amtToRemove
			elseif (ibKnife > ZERO && ibKnife < amtToRemove)
				akPlayerRef.RemoveItem(BasicKnife01, ibKnife)
				iterator -= ibKnife
			elseif (ibFork >= amtToRemove && iterator == amtToRemove)
				akPlayerRef.RemoveItem(BasicFork01, amtToRemove)
				iterator -= amtToRemove
			elseif (ibFork > ZERO && ibFork < amtToRemove)
				akPlayerRef.RemoveItem(BasicFork01, ibFork)
				iterator -= ibFork
			endif
		EndWhile
	endFunction

;End Marthgun Edit ; 

 

 

this is identical to the vanilla script except i run a check for whether or not the object attached isEnabled, so i don't get errors for non loaded 3d if the object initializes or is reset

the parent script:

psc file:  https://drive.google.com/open?id=0B858bpwZmkmiamFZVUJYSERvOFE

scriptName TrapTriggerBASE extends objectReference hidden
;
;
;This is the base trap trigger script and handles what the trigger tells the trap
;Any trigger should be useable with any trap
;Activation params are on the trigger, toggle, number of times it can be triggered, etc.
;Trap params are on the trap (damage, timing, etc)
;Some triggers will be extended from this base to handle animation, etc.
;================================================================

import debug


int Count															;if Finite = 1, Determines how many times this trigger can be used
int property CountUsed auto hidden							;Used to compare times triggered to max triggers allowed
int property Type auto hidden 								;This is to determine trigger to send to the trap
		;The trap will handle its behavior based on this signal
		;0 = Single - fire the trap once do one time
		;1 = Hold - on entry turn on, on exit turn off
		;2 = Toggle - on entry or use toggle trap state
		;3 = Turn On - on entry or use turn on trap
		;4 = Turn Off - on entry or use turn off trap
sound property TriggerSound auto
objectReference property lastTriggerRef auto hidden
int property soundLevel = 10 auto

int objInTriggerVar 
int property objectsInTrigger hidden 
     function set(int value) 
          objInTriggerVar = value 
          ;TraceStack("Setting objectsInTrigger to " + value) 
     endFunction 
     int function get() 
          return objInTriggerVar 
     endFunction 
endProperty

faction property owningFaction Auto
actorBase property owningActorBase Auto
bool property doOnceBase = False auto hidden
bool property playerOnlyTrigger = false auto
bool property checkForLightFootPerk = false Auto
{Setting this will give a chance that the trap trigger will not Fire
	this does not work on triggers with the HOLD trigger type
	Set on by default on all pressure plates
	you should only mess with this locally for triggerboxes}
bool property checkForLightHandsPerk = false Auto
{Setting this will give a chance that the trap trigger will not Fire when lockpicked
	this is used specifically for hinge triggers or other things like that
	set to on by default on the hinge trigger}
perk property lightFootPerk Auto
globalVariable property LightFootGlobalVar auto
perk property lightHandsPerk Auto
globalVariable property LightHandsGlobalVar auto

bool property blockActivate = false Auto
{block activation of this by the player, only used for trapLinker
	default = False}

bool property FiniteUse auto
    {If true this has a finite number of uses as defined by the TriggerCount, and then will not fire}

bool property isTriggerVolume = False auto
{This property is used to tell the trap trigger if it is a trigger volume
	if true, on cell attach it will try to check if there are object in the trigger and go to state inactive if not
	This should be turned to TRUE for pressure plates & triggerboxes
	default = false}
	
int property TriggerCount
	{the number of times this Trigger can fire, only used if FiniteUse is True}
	int Function Get()
		return Count
	endFunction
	
	Function Set (int value)
		if (value >= 1 && value <= 100)
			Count = Value
		else
			Count = 1
		endif
	endFunction
endProperty

int property TriggerType
		{This property determines how the trigger will tell the trap to fire
		0 = Single Fire
		1 = Hold
		2 = Toggle
		3 = Turn On
		4 = Turn Off}
	int Function Get()
		return Type
	endFunction
	
	Function Set (int value)
		if (value >= 0 && value <= 4)
			Type = value
			StoredTriggerType = Value
		else
			Type = 0
			StoredTriggerType = 0
		endif
	endFunction
endProperty

int property StoredTriggerType auto Hidden
{this stores what the triggerType was set to on the Ref
	used for trapLinker in case of activation by non trapTriggerBase ref}

event onCellAttach()
	if (self.IsEnabled())
		if self.GetFactionOwner()
			owningFaction = self.GetFactionOwner()
		ElseIf self.GetActorOwner()
			owningActorBase = (self.GetActorOwner() as actorBase)
		endif

		if blockActivate
			self.blockActivation(true)
		endif
	endif
	;/
	if !doOnceBase
		StoredTriggerType = TriggerType
		doOnceBase = True
	endif
	/;
endEvent

Event onCellLoad()
	if (self.IsEnabled())
		objectsInTrigger = self.GetTriggerObjectCount()
		if isTriggerVolume && objectsInTrigger == 0
			goToState ("Inactive")
		endif
	endif
endEvent

;THIS SECTION IS USED FOR TRAP LINKERS
event onActivate(objectReference akActivator)
; 	debug.Trace(self + " has been activated by + " + akActivator)
; 	debug.Trace(self + ": Type = " + Type + ", StoredTriggerType = " + StoredTriggerType)
	if blockActivate && akActivator != (self as objectReference)
		if (akActivator as trapTriggerBase)
; 			debug.Trace(akActivator + " was able to be cast as trapTriggerBase")
; 			debug.Trace(self + " triggerType was " + triggerType)
			TriggerType = (akActivator as trapTriggerBase).TriggerType
; 			debug.Trace(self + " triggerType is now " + triggerType)
		
		
		else	
; 			debug.Trace(akActivator + " was NOT able to be cast as trapTriggerBase")
			triggerType = StoredTriggerType
		endif
		
		if blockActivate
			self.blockActivation(false)
			utility.wait(0.0)
			localActivateFunction()
			self.Activate(self)
			self.blockActivation(true)
		endif
		
	endif
endEvent

;================================================================

auto State Inactive

	event onBeginState()
; 		debug.Trace(self + ": is calling onBeginState Inactive")
; 		debug.Trace(self + ": StoredTriggerType = " + StoredTriggerType + ", objectsInTrigger = " + objectsInTrigger)
		if (StoredTriggerType == 1 && objectsInTrigger == 0)                                                                                                                  ;type 1 = hold, so deprecate here if necessary
			if (FiniteUse == TRUE && CountUsed < Count);if finite use and count > count used
				CountUsed += 1                                                                                               ;increase count for hold type triggers
			endif
			Type = 4
			utility.wait(0.1)
			activate(self as objectReference)
			utility.wait(0.1)
			;Type = 1
		else
; 			debug.Trace(self + "StoredTriggerType = " + StoredTriggerType + ", ObjectsInTrigger = " + objectsInTrigger)
		endif
	endEvent
	
	event OnTriggerEnter (objectReference triggerRef)
		if acceptableTrigger(triggerRef)
; 			debug.Trace(self + " has been entered by " + triggerRef)
			lastTriggerRef = triggerRef
			objectsInTrigger = self.GetTriggerObjectCount()
			if (FiniteUse == TRUE     && CountUsed < Count)               ;if finite use and count > count used
				;TRACE("Finite Use")
				if (Type != 1)                                                                                                      ;type 1 = hold so only increase on leave
					CountUsed += 1                                                                                               ;increase count used
					;TRACE("Increasing Count on enter")
				endif
				goToState( "Active" )
			endif
			
			if (FiniteUse == FALSE)
				;TRACE("Infinite Use")
				goToState( "Active" )
			endif     
		endif
	endevent

	event OnTriggerLeave (objectReference triggerRef)
		if acceptableTrigger(triggerRef)
; 			debug.Trace(self + " has been exited by " + triggerRef)
			lastTriggerRef = triggerRef
			objectsInTrigger = self.GetTriggerObjectCount()
; 			debug.Trace(self + ": StoredTriggerType = " + StoredTriggerType + ", objectsInTrigger = " + objectsInTrigger)
			if (StoredTriggerType == 1 && objectsInTrigger == 0)                                                                                                                  ;type 1 = hold, so deprecate here if necessary
				if (FiniteUse == TRUE && CountUsed < Count);if finite use and count > count used
					CountUsed += 1                                                                                               ;increase count for hold type triggers
				endif
				Type = 4
				utility.wait(0.1)
				activate(self as objectReference)
				utility.wait(0.1)
				;Type = 1
			endif
		endif
	endevent
	
endstate


State Active
	Event onBeginState()
; 		debug.Trace(self + ": is calling onBeginState Active")
; 		debug.Trace(self + ": StoredTriggerType = " + StoredTriggerType + ", objectsInTrigger = " + objectsInTrigger)
		if (StoredTriggerType == 1)
			Type = 3
			utility.wait(0.1)
			activate(self as objectReference)
			utility.wait(0.1)
			;Type = 1
		else
			activate(self as objectReference)
		endif
		
		if objectsInTrigger == 0
			goToState( "Inactive" )
		endif
	endEvent
	
	event OnTriggerEnter( objectReference triggerRef )
		if acceptableTrigger(triggerRef)
; 			debug.Trace(self + " has been entered by " + triggerRef)
			objectsInTrigger = self.GetTriggerObjectCount()
		endif
	endEvent
	
	event OnTriggerLeave( objectReference triggerRef )      
		if acceptableTrigger(triggerRef)
; 			debug.Trace(self + " has been exited by " + triggerRef)
			objectsInTrigger = self.GetTriggerObjectCount()
			if objectsInTrigger == 0
				goToState ("Inactive")
			endif
		endif
	endEvent
	
	event OnMagicEffectApply(objectReference akCaster, MagicEffect akEffect)
		Trace("MagicEffectHit")
		activate(self as objectReference)
		goToState( "Inactive" )
	endEvent
endState

;The following function is used to filter for acceptable objects to trigger this
;if it is player only, then ONLY the player will trigger it and nothing else, including projectiles
;if there is an owning faction and it is not player only then everything BUT actors
                ;that are part of that owning faction will trigger it
bool function acceptableTrigger(objectReference triggerRef)

; 	debug.Trace(self + " is checking if " + triggerRef + " is an acceptable trigger")
	if playerOnlyTrigger
		if triggerRef == game.getPlayer()
; 			debug.Trace(self + " has found that " + triggerRef + " is an acceptable trigger")
			if checkPerks(triggerRef)
				Return True
			Else
				Return False
			endif
		Else
; 			debug.Trace(self + " has found that " + triggerRef + " is not an acceptable trigger")
			return False
		endif
	Else
		if !(triggerRef as actor)	;if this is not a player only trigger and this is not an actor
			return True
		elseif owningFaction
			if (triggerRef as actor).IsInFaction(owningFaction)
; 				debug.Trace(self + " has found that " + triggerRef + " is not an acceptable trigger")
				return False
			else
; 				debug.Trace(self + " has found that " + triggerRef + " is an acceptable trigger")
				if checkPerks(triggerRef)
					Return True
				Else
					Return False
				endif
			endif
		else
			if owningActorBase
				if (triggerRef as actor).getActorBase() == owningActorBase
; 					debug.Trace(self + " has found that " + triggerRef + " is not an acceptable trigger")
					return False
				Else
; 					debug.Trace(self + " has found that " + triggerRef + " is an acceptable trigger")
					if checkPerks(triggerRef)
						Return True
					Else
						Return False
					endif
				endif
			else
; 				debug.Trace(self + " has found that " + triggerRef + " is an acceptable trigger")
				if checkPerks(triggerRef)
					Return True
				Else
					Return False
				endif
			endif
		endif
	endif
endFunction

Bool function checkPerks(objectReference triggerRef)
	if checkForLightFootPerk
; 		debug.Trace(self + " is checking if " + triggerRef + " has LightFoot Perk")
		if  (triggerRef as actor).hasPerk(lightFootPerk)
; 			debug.Trace(self + " has found that " + triggerRef + " has LightFoot Perk")
			if utility.randomFloat(0.0,100.00) <= LightFootGlobalVar.getValue()
; 				debug.Trace(self + " is returning false due to failed lightfoot roll")
				return False
			else
; 				debug.Trace(self + " is returning true due to successful lightfoot roll")
				return True
			endif
		Else
; 			debug.Trace(self + " has found that " + triggerRef + " doesn't have the LightFoot Perk")
			Return True
		EndIf
	elseif checkForLightHandsPerk
; 		debug.Trace(self + " is checking if " + triggerRef + " has LightHands Perk")
		if  (triggerRef as actor).hasPerk(lightHandsPerk)
; 			debug.Trace(self + " has found that " + triggerRef + " has LightFoot Perk")
			if utility.randomFloat(0.0,100.00) <= LightHandsGlobalVar.getValue()
; 				debug.Trace(self + " is returning false due to failed lightHands roll")
				return False
			else
; 				debug.Trace(self + " is returning true due to successful lightHands roll")
				return True
			endif
		Else
; 			debug.Trace(self + " has found that " + triggerRef + " doesn't have the LightFoot Perk")
			Return True
		EndIf
	Else
; 		debug.Trace(self + " has found that " + triggerRef + " doesn't have applicable perks")
		return True
	EndIf
endFunction

function localActivateFunction() ;placeholder function for anything that may need to be on the child activate event
endFunction


















	
	
	
		
 

 

Link to comment
Share on other sites

If all the properties fill without other mods loaded, then it's likely there's something overriding TrapTriggerBASE, which can be id'd in Wry Bash or MO. Something like Follower Trap Safety or Tweak Traps? Note this issue.

Link to comment
Share on other sites

Side note:

 

Why don't you fill the static objects in an array ?

 

Make another array with the corresponding meshIDs at the same position. Then find the mesh ID in that array and get the static object from the same position in the static objects array. Should make your script not only smaller but also noticeably faster (those if-elseif-elseif ... cascades take time!)

Link to comment
Share on other sites

If all the properties fill without other mods loaded, then it's likely there's something overriding TrapTriggerBASE, which can be id'd in Wry Bash or MO. Something like Follower Trap Safety or Tweak Traps? Note this issue.

 

 

There was no other TrapTriggerBase script in my loose Script folder, is there another way to override a script?

 

from your original link about the papy errors:

 

This usually means that a property located in an ESP has not been filled in properly, leaving it empty, which in Papyrus is called "None". There are numerous things that require valid data to be processed that can throw this error, and the specific text for "None" errors will vary widely. It should be easy for a mod's author to fix, but generally requires a new game before such a fix would take effect due to the data already being baked into the save. It's also possible that the script simply isn't validating to make sure the property it's using has something in it.

 

a new game, or coc'ing from the Main Menu, works just fine.  Idk how i would even fix this if I have to require a new game.  Do you think that because other scripts have ran or are running using the same base objects, that would cause a problem for them filling?   I'm wondering if it may be standard to run checks for all my properties just to make sure it shuts down if it can't fill.   

 

Side note:

 

Why don't you fill the static objects in an array ?

 

Make another array with the corresponding meshIDs at the same position. Then find the mesh ID in that array and get the static object from the same position in the static objects array. Should make your script not only smaller but also noticeably faster (those if-elseif-elseif ... cascades take time!)

 

that's a great idea, i'll implement it thanks.  anymore suggestions are welcome.

Link to comment
Share on other sites

If it works correctly in a new game or by using COC at the main menu, then it stands to reason that the objects you are testing with have already been loaded at some point and have been baked into your save file.  Only workaround without falling back to a new game would be to wait till cell reset in a different cell free of such objects and far away from the cells with such objects.

Link to comment
Share on other sites

If it works correctly in a new game or by using COC at the main menu, then it stands to reason that the objects you are testing with have already been loaded at some point and have been baked into your save file.  Only workaround without falling back to a new game would be to wait till cell reset in a different cell free of such objects and far away from the cells with such objects.

:fear:

 

so i should have to force a reset for everyone on release?  can only one property be loaded at once or is it more like because ObjectReferences that have already been baked in, applying scripts to them will cause problems?  that makes alot of sense if the save is trying to replicate the state of game. i just wish there were some way to not have to reset a cell.  bah gawd,any ideas?

 

edit: although i should mention i went to two cells on my heavy modded game that i never been to before (test areas).  but i think you're probably right.

Link to comment
Share on other sites

Depends on how you do your scripting.

 

An example:

Test two mods that affect the same thing:

Save a game right in front of an ore vein.

 

Complete Crafting Overhaul Remade:  

This mod has options which affect mining and does so by adding properties and other changes to the ore vein script.  

Load your save and the vein in front of you will not work as intended.  It should still mine but none of CCOR's changes will take effect.

This does not work because when the game looks at the modified script it sees that essential elements have been altered. As a result, it reverts to the save game baked version.

 

Random Mining MCM:  

This mod has options which affect mining and does so by storing the user selected data on the MCM script and calling it from there as needed.

Load your save and the vein will work as intended. 

This works because when the game looks at the modified script it sees that no essential elements have been altered. As a result, it allows the modified version to be used instead of the baked in version.

All that said, if you create a script that has your properties and/or functions and put them on a different object that is unique to your mod (perhaps a start game enabled quest).  You can link to that script and use its property data and/or call functions on it from any other script that you want.  This would allow you to make changes to the behavior of an already loaded object at the next point in which it is activated or other event triggered.  Provided of course that you add no new properties, remove no existing functions or events nor remove any properties or variables.

 

Feel free to take a look at Random Mining MCM to see what I am referring to.  

 

TL;DR

See Getting Properties From Any Other Script on the CK wiki for additional information.

 

 

Link to comment
Share on other sites

Just to clarify one thing: Any property you set becomes set for life. No amount of waiting in QASmoke or whatever is going to change this. They bake in from the moment the game is started.

 

You cannot change the value to something else. You can however add new ones and delete unused ones at any point and the only thing your log will do is complain once about removing unused ones as no longer being present.

 

Removing functions can also be done provided the save isn't currently using it. If it is, that copy will remain active until the next time that object is encountered. As long as it also isn't stuck in a loop.

Link to comment
Share on other sites

Thanks for the info guys, i took alot of advice from here, now I just need to start testing it thoroughly, i really appreciate those links Ishara i think that's a really good alternative.  and that's very similar to what i'm working with.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...