FrankFamily Posted April 20, 2015 Share Posted April 20, 2015 (edited) So, you may know i recently a new mod, which includes the gray cowl like it was in oblivion, so it swaps your bounties with gray fox's ones whever you equip or unequip it, but an user has told me that it left him gf bounty after unequiping so i started thinking that maybe the unequip block starts runing while the equip is runing and end up messing up the bounties, is that posible? how could i avoid that?or maybe the whole onunequip block didnt run, do you know why would that happen? thanks in advance and here is the script: Scriptname FFGrayCowlControllerScript extends ObjectReference Faction[] Property FactionArray Auto int[] Property CrimePlayerArray Auto int[] Property CrimePlayerViolentArray Auto int[] Property CrimeFoxArray Auto int[] Property CrimeFoxViolentArray Auto int Index int Property MinimumGrayFoxBounty Auto Faction Property FFGrayFoxFaction Auto int TotalLifetimeBountyPlayer int TotalLifetimeBountyFox int LargestBountyPlayer int LargestBountyFox Event OnEquipped(Actor akActor) if akActor == Game.GetPlayer() akActor.StopCombatAlarm() akActor.AddToFaction(FFGrayFoxFaction) TotalLifetimeBountyPlayer = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyPlayer = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length While Index Index -= 1 CrimePlayerArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimePlayerViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() If Index <= 15 If CrimeFoxArray[Index] < MinimumGrayFoxBounty CrimeFoxArray[Index] = MinimumGrayFoxBounty Endif If CrimeFoxViolentArray[Index] < MinimumGrayFoxBounty CrimeFoxViolentArray[Index] = MinimumGrayFoxBounty Endif Endif FactionArray[Index].SetCrimeGold(CrimeFoxArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimeFoxViolentArray[Index]) EndWhile Endif EndEvent Event OnUnequipped(Actor akActor) if akActor == Game.GetPlayer() AkActor.StopCombatAlarm() akActor.RemoveFromFaction(FFGrayFoxFaction) TotalLifetimeBountyFox = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyFox = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length While Index Index -= 1 CrimeFoxArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimeFoxViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() FactionArray[Index].SetCrimeGold(CrimePlayerArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimePlayerViolentArray[Index]) EndWhile Game.IncrementStat("Total Lifetime Bounty", TotalLifetimeBountyPlayer - TotalLifetimeBountyFox) Game.IncrementStat("Largest Bounty", LargestBountyPlayer - LargestBountyFox) Endif EndEvent Edited April 20, 2015 by FrankFamily Link to comment Share on other sites More sharing options...
DavidJCobb Posted April 22, 2015 Share Posted April 22, 2015 The following may work. It's a simple lock-and-queue system to prevent your equip and unequip handlers from running concurrently with themselves or each other. Bool Property pbBusy = False Auto Hidden Bool Property pbQueued = False Auto Hidden Armor Property pkMyBaseForm Auto {Set this to the gray cowl's base form in the Creation Kit.} Function HandleQueuedTask() If !pbQueued Return EndIf pbQueued = False Actor PlayerRef = Game.GetPlayer() If PlayerRef.IsEquipped(pkMyBaseForm) OnEquipped(PlayerRef) Else OnUnequipped(PlayerRef) EndIf EndFunction Event OnEquipped(Actor akActor) If pbBusy pbQueued = True Return EndIf pbBusy = True ; ; Do stuff... ; pbBusy = False HandleQueuedTask() EndEvent Event OnUnequipped(Actor akActor) If pbBusy pbQueued = True Return EndIf pbBusy = True ; ; Do stuff... ; pbBusy = False HandleQueuedTask() EndEvent Link to comment Share on other sites More sharing options...
ArronDominion Posted April 22, 2015 Share Posted April 22, 2015 (edited) I was PM'd with this question and have been troubleshooting the issue, which I think at this time is a runtime efficiency issue. This was my first approach to solve the problem (Slightly similar to Cobb's example and it did not): Scriptname FFGrayCowlControllerScript extends ObjectReference Faction[] Property FactionArray Auto int[] Property CrimePlayerArray Auto int[] Property CrimePlayerViolentArray Auto int[] Property CrimeFoxArray Auto int[] Property CrimeFoxViolentArray Auto int Index int Property MinimumGrayFoxBounty Auto Faction Property FFGrayFoxFaction Auto int TotalLifetimeBountyPlayer int TotalLifetimeBountyFox int LargestBountyPlayer int LargestBountyFox ;Determines if some is currently equipped as in the Cowl...if so set this to true otherwise nop ;Defaults at False Bool Property EquippedStatus = False Event OnEquipped(Actor akActor) ;Checks to see if the Player is the akActor and if it is not current equipped if ((akActor == Game.GetPlayer()) && !(EquippedStatus)) akActor.StopCombatAlarm() akActor.AddToFaction(FFGrayFoxFaction) TotalLifetimeBountyPlayer = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyPlayer = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length While Index Index -= 1 CrimePlayerArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimePlayerViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() If Index <= 15 If CrimeFoxArray[Index] < MinimumGrayFoxBounty CrimeFoxArray[Index] = MinimumGrayFoxBounty Endif If CrimeFoxViolentArray[Index] < MinimumGrayFoxBounty CrimeFoxViolentArray[Index] = MinimumGrayFoxBounty Endif Endif FactionArray[Index].SetCrimeGold(CrimeFoxArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimeFoxViolentArray[Index]) EndWhile ;Change our Equipped Status EquippedStatus = True Endif EndEvent Event OnUnequipped(Actor akActor) ;Check to see if the Player is the akActor and if it is currently equipped if ((akActor == Game.GetPlayer()) && (EquippedStatus)) AkActor.StopCombatAlarm() akActor.RemoveFromFaction(FFGrayFoxFaction) TotalLifetimeBountyFox = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyFox = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length While Index Index -= 1 CrimeFoxArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimeFoxViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() FactionArray[Index].SetCrimeGold(CrimePlayerArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimePlayerViolentArray[Index]) EndWhile Game.IncrementStat("Total Lifetime Bounty", TotalLifetimeBountyPlayer - TotalLifetimeBountyFox) Game.IncrementStat("Largest Bounty", LargestBountyPlayer - LargestBountyFox) ;Change our Equipped Status EquippedStatus = False Endif EndEvent This led to extracting portions of the block (haven't heard feedback yet on this part, so may or may not work) into a repeatable function call, to turn an iterative problem into a recursive problem. This makes the assumption that the introduced Equipped lock is still in place to provide framework for different functionality in the function calls: Function BountyFunction(Actor NPC) NPC.StopCombatAlarm() NPC.AddToFaction(FFGrayFoxFaction) TotalLifetimeBountyPlayer = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyPlayer = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length BountyRecursiveFunction(Index, EquippedStatus) EndFunction Function BountyRecursiveFunction(Int Index, Bool EquippedStatus) ;If you are running OnEquipped compared to OnUnequipped if (!(EquippedStatus)) CrimePlayerArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimePlayerViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() If Index <= 15 If CrimeFoxArray[Index] < MinimumGrayFoxBounty CrimeFoxArray[Index] = MinimumGrayFoxBounty Endif If CrimeFoxViolentArray[Index] < MinimumGrayFoxBounty CrimeFoxViolentArray[Index] = MinimumGrayFoxBounty Endif Endif FactionArray[Index].SetCrimeGold(CrimeFoxArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimeFoxViolentArray[Index]) Else CrimeFoxArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimeFoxViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() FactionArray[Index].SetCrimeGold(CrimePlayerArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimePlayerViolentArray[Index]) EndIf ;Portion to check if we need to continue or end if (Index < 1) Return Else BountyRecursiveFunction((Index - 1), EquippedStatus) EndIf EndFunction I suspect since it is a problem when equipping/unequipping in rapid succession that it is a runtime problem (due to what is on the script stack at the current time and the while iteration). Edit: Looking at the While block, The while condition is simply Index. Wonder if a stricter While block condition such as !(Index < 0) would help out. That would turn everything into: Scriptname FFGrayCowlControllerScript extends ObjectReference Faction[] Property FactionArray Auto int[] Property CrimePlayerArray Auto int[] Property CrimePlayerViolentArray Auto int[] Property CrimeFoxArray Auto int[] Property CrimeFoxViolentArray Auto int Index int Property MinimumGrayFoxBounty Auto Faction Property FFGrayFoxFaction Auto int TotalLifetimeBountyPlayer int TotalLifetimeBountyFox int LargestBountyPlayer int LargestBountyFox ;Determines if some is currently equipped as in the Cowl...if so set this to true otherwise nop ;Defaults at False Bool Property EquippedStatus = False Event OnEquipped(Actor akActor) ;Checks to see if the Player is the akActor and if it is not current equipped if ((akActor == Game.GetPlayer()) && !(EquippedStatus)) akActor.StopCombatAlarm() akActor.AddToFaction(FFGrayFoxFaction) TotalLifetimeBountyPlayer = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyPlayer = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length While (!(Index < 0)) Index -= 1 CrimePlayerArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimePlayerViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() If Index <= 15 If CrimeFoxArray[Index] < MinimumGrayFoxBounty CrimeFoxArray[Index] = MinimumGrayFoxBounty Endif If CrimeFoxViolentArray[Index] < MinimumGrayFoxBounty CrimeFoxViolentArray[Index] = MinimumGrayFoxBounty Endif Endif FactionArray[Index].SetCrimeGold(CrimeFoxArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimeFoxViolentArray[Index]) EndWhile ;Change our Equipped Status EquippedStatus = True Endif EndEvent Event OnUnequipped(Actor akActor) ;Check to see if the Player is the akActor and if it is currently equipped if ((akActor == Game.GetPlayer()) && (EquippedStatus)) AkActor.StopCombatAlarm() akActor.RemoveFromFaction(FFGrayFoxFaction) TotalLifetimeBountyFox = (Game.QueryStat("Total Lifetime Bounty")) LargestBountyFox = (Game.QueryStat("Largest Bounty")) Index = FactionArray.Length While (!(Index < 0)) Index -= 1 CrimeFoxArray[Index] = FactionArray[Index].GetCrimeGoldNonViolent() CrimeFoxViolentArray[Index] = FactionArray[Index].GetCrimeGoldViolent() FactionArray[Index].SetCrimeGold(CrimePlayerArray[Index]) FactionArray[Index].SetCrimeGoldViolent(CrimePlayerViolentArray[Index]) EndWhile Game.IncrementStat("Total Lifetime Bounty", TotalLifetimeBountyPlayer - TotalLifetimeBountyFox) Game.IncrementStat("Largest Bounty", LargestBountyPlayer - LargestBountyFox) ;Change our Equipped Status EquippedStatus = False Endif EndEvent Another edit: should be < 1 instead of 0 Edited April 23, 2015 by Arron Dominion Link to comment Share on other sites More sharing options...
DavidJCobb Posted April 23, 2015 Share Posted April 23, 2015 This was my first approach to solve the problem (Slightly similar to Cobb's example and it did not): That approach feels wrong to me, but I can't gauge all the reasons why. Offhand, I know that any concurrent events will be "eaten" by your system. if I equip and then immediately unequip the cowl, your script won't notice that I took it off, because your locking mechanism prevents concurrent calls but doesn't queue/defer them to run later. Link to comment Share on other sites More sharing options...
ArronDominion Posted April 23, 2015 Share Posted April 23, 2015 (edited) This was my first approach to solve the problem (Slightly similar to Cobb's example and it did not):That approach feels wrong to me, but I can't gauge all the reasons why. Offhand, I know that any concurrent events will be "eaten" by your system. if I equip and then immediately unequip the cowl, your script won't notice that I took it off, because your locking mechanism prevents concurrent calls but doesn't queue/defer them to run later.Very true drawback with this method, since the lock will not be updated until the event using the lock is finished, and the subsequent calls will not execute as intended until it is updated. Edit: Haven't read the Events Reference page until now, and did not know events could be evoked like functions. It would negate the need for a lock, to just return inside the while loop for the event you want to call if the cowl is equipped/not equipped. Edited April 23, 2015 by Arron Dominion Link to comment Share on other sites More sharing options...
FrankFamily Posted April 26, 2015 Author Share Posted April 26, 2015 Been busy lately so havent had time to test it, will try to do it tomorrow morning. Thank you both very much for your helpDidnt know you can call events like functions either, though it makes sense as cipsis sais they are basically functions that are called by the game in certain moments in his tutorial.Thanks again :) Link to comment Share on other sites More sharing options...
Recommended Posts