Jump to content

Gray Cowl - Help to improve the script


Recommended Posts

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 by FrankFamily
Link to comment
Share on other sites

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

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 by Arron Dominion
Link to comment
Share on other sites

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

 

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 by Arron Dominion
Link to comment
Share on other sites

Been busy lately so havent had time to test it, will try to do it tomorrow morning. Thank you both very much for your help

Didnt 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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...