Jump to content

[LE] Trying to get an Activator Reset on Timer


Recommended Posts

Hey there everyone, hope all is well.

 

A recent unfortunate event, has lead to the lost of my previous mod project, but I was able to salvage it. I've been working on some new scripts and I'm having an issue getting an Activator to "reset after the Timer is up",more specifically the in-game timer.

 

I've tried "Utility.Wait" and then "()Reset" at the end, but it didn't work. I know GlobalVariableGametime plays a role here somewhere but I'm messing this up. I've read on here "RegisterForSingleUpdateGameTime" is probably better for "longer" wait times, but had the same results.

 

This script is from "Aftershock" quest, anomaly attacks. I've been experimenting with it and it works, I would just like it if the trigger restart after a set amount of time has passed. Any help would be greatly appreciated.

Scriptname TEST_AnomalySpawner extends ObjectReference  
{Handles the destruction stages and enemy spawning of the magic anomaly spawner object}

ActorBase Property EncMagicAnomaly Auto
{enemy to spawn}
Explosion Property ExplosionIllusionLight01 Auto
{explosion to play whne it opens}
Explosion Property ExplosionIllusionMassiveLight01 Auto
{explosion to play whne it opens}
; Enemy holders
Actor myEncMagicAnomaly01
Actor myEncMagicAnomaly02
Actor myEncMagicAnomaly03
; Blend values (how open it the portal 0-1)
float fToggleBlendStart = 0.3
float fToggleBlendOpen = 0.9
float fToggleBlendFull = 1.0
float fToggleBlendGone = 0.0
; Temporary blend value holder
float myCurrentBlend
;Is player in trigger and the portal is not open
int playerInTrigger 
; Enemy count
int numberOfEnemiesAlive 
; Distances with 3000 unit trigger to test fade portal open
float maxTestRange = 1500.0
Float minTestRange = 550.0
; holder for player
actor myPlayer
; gates for making the drath of each enemy affect script only once
int Gate1
int Gate2
int Gate3


auto state waiting
	; Set initial blend ab=mount for portal and get player locally
	Event onLoad()
		self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendStart)
		myPlayer = game.getPlayer()
	EndEvent
	;waits for player to enter trigger once he does it tests for distance and triggers the portal to open if he gets close enough
	 Event OnTriggerEnter(ObjectReference akActionRef)
		playerInTrigger = 1
		self.SetAnimationVariableFloat("fDampRate", 0.3)
		while playerInTrigger == 1 ;&& playerLeftTrigger
			float myDistance = myPlayer.getDistance(self)
; 			debug.trace("myDistance = " + myDistance)
			if myDistance <= minTestRange
				;player is close enoght to automatically open the portal
				goToState("opened")
				playerInTrigger = 0
			elseIf myDistance <= maxTestRange
				Float animationValue = CalculateAnimationValue(myDistance, minTestRange,maxTestRange, fToggleBlendStart, fToggleBlendFull)
; 				debug.trace("animationValue = " + animationValue)
				self.SetAnimationVariableFloat("fToggleBlend", animationValue)
				utility.wait(0.05)
			endif
		endWhile
	EndEvent
	;stop testing if player leaves trigger without opening portal
	Event OnTriggerLeave(ObjectReference akActionRef)
		playerInTrigger = 0
	EndEvent
endState



 state opened
	;The portal is opened playe some explosions and spawn 3 enemies
	Event onBeginState()
; 		debug.trace("opened")
		int doOnce = 0
		if doOnce == 0
			self.placeAtMe(ExplosionIllusionLight01)
			utility.wait(0.75)
			self.placeAtMe(ExplosionIllusionMassiveLight01)
			self.KnockAreaEffect(1, 900)
			self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendFull)
			utility.wait(0.5)
			myEncMagicAnomaly01 = self.placeActorAtMe(EncMagicAnomaly)
			myEncMagicAnomaly01.setScale(utility.randomFloat(0.7, 1.25))
						utility.wait(1.5)
			myEncMagicAnomaly02 = self.placeActorAtMe(EncMagicAnomaly)
			myEncMagicAnomaly02.setScale(utility.randomFloat(0.7, 1.25))
						utility.wait(0.5)
			myEncMagicAnomaly03 = self.placeActorAtMe(EncMagicAnomaly)
			myEncMagicAnomaly03.setScale(utility.randomFloat(0.7, 1.25))
			numberOfEnemiesAlive = 3
			doOnce = 1
		endIf
	
			utility.wait(3.5)
			self.SetAnimationVariableFloat("fDampRate", 0.03)
			self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendOpen)
; 			debug.trace("isDead " + myEncMagicAnomaly01.IsDead())
			;While ther are some enemies alive test each one to see if they are dead evey half second. If they are run the fade out function.
			while numberOfEnemiesAlive > 0
				utility.wait(0.5)
				if Gate1 == 0
					if myEncMagicAnomaly01.IsDead() == true
						anomalyDied()
						Gate1 = Gate1 + 1
					endIf
				endIf
				if Gate2 == 0
					if myEncMagicAnomaly02.IsDead() == true
						anomalyDied()
						Gate2 = Gate2 + 1
					endIf
				endIf
				if Gate3 == 0				
					if myEncMagicAnomaly03.IsDead() == true
						anomalyDied()
						Gate3 = Gate3 + 1
					endIf
				endIf
			endwhile		
	EndEvent 
 endState
 
 ; function to test the distance from the player to the portal and ramp up the art accordingly
 Float Function CalculateAnimationValue(float PlayerDistance, float NearDistance, float FarDistance, float AnimationMin, float AnimationMax)
	Float percent = 1-((PlayerDistance - NearDistance)/(FarDistance - NearDistance))
	Float returnValue = (percent * (AnimationMax - AnimationMin)) + AnimationMin
	Return returnValue	
EndFunction

; Function to fade out the art each time an enemy dies finally disabling the art after the last enemy
Function anomalyDied()
; 		debug.trace("running anomaly died")
; 		debug.trace("01 is dead = " + myEncMagicAnomaly01.IsDead())
; 		debug.trace("02 is dead = " + myEncMagicAnomaly02.IsDead())
; 		debug.trace("03 is dead = " + myEncMagicAnomaly03.IsDead())
		myCurrentBlend = self.GetAnimationVariableFloat("fToggleBlend")
; 		debug.trace("myCurrentBlend = "+ myCurrentBlend)
		self.SetAnimationVariableFloat("fToggleBlend", myCurrentBlend - (fToggleBlendOpen / 3))
		numberOfEnemiesAlive = numberOfEnemiesAlive - 1
		if numberOfEnemiesAlive == 0
			utility.wait(0.5)
			self.disable(true)
			endif
EndFunction


Link to comment
Share on other sites

I'm assuming based on what you've posted is all you want is a trigger that will be able to run a script again after a certain amount of time as passed. So I wrote a rather simple one for you.

Scriptname DefaultResetTriggerScript extends ObjectReference
{ Basic script for resetting triggers. This can be applied to any trigger. }

Float property fHours auto
{ The number of hours to pass before this trigger resets. }


AUTO STATE FirstState
    Event OnTriggerEnter(ObjectReference akTriggerRef)
        if akTriggerRef == Game.GetPlayer()
            ; put script in its waiting phase. Code after GoToState will still run.
            GoToState("SecondState")
            ;-----spot for your desired code
           
            RegisterForSingleUpdateGameTime(fHours)
        endif
    EndEvent
ENDSTATE

STATE SecondState
    Event OnUpdateGameTime()
        ; put it back in its main state
        GoToState("FirstState")
    EndEvent
ENDSTATE

fHours can be any hour you want, or if not wanting to use a property, you can just pass a value to the function, like 24.0(24 hours). This can be used on any script for simple "resetting".

 

Make sure the trigger in game reference's respawn box is not checked. Otherwise when it does reset due to the cell resetting, the script will reset with it.

 

Depending on how you code, you'll need to adjust when you want the registering of the event to actually happen if you don't want to register as soon as the player enters the trigger.

There is the issue of OnUpdateGameTime not taking into account for the player sleeping, waiting, fast traveling as any of these can potentially cause the event to run later than you expect, but I figure for this kind of thing, it's not important.

Edited by TheDungeonDweller
Link to comment
Share on other sites

Ah, thanks a lot DungeonDweller!

 

 

I'm assuming based on what you've posted is all you want is a trigger that will be able to run a script again after a certain amount of time as passed. So I wrote a rather simple one for you.

 ;-----spot for your desired code

 

The script you posted compiled perfectly. (Something I'm not use to seeing for myself) and yes, you are spot on, I want the trigger to run again after a certain amount of time has passed. This particular line, "Spot for your desired code", I've tried putting the entire code in that segment and got errors, been fiddling around with it and realize that was wrong and tried configuring the "Waiting" part. Basically this "works", but I wanted to run this by you to make sure I wrote this right. Feels like I messed something up though but I'll be running some more test, since I know OnUpdateGametime doesn't take into account for waiting or sleeping.

 

 

 

Once again thanks a lot for your help! Will post back results :laugh:

Scriptname TEST_AnomalySpawner extends ObjectReference  
{Handles the destruction stages and enemy spawning of the magic anomaly spawner object}

Float property fHours auto
{ The number of hours to pass before this trigger resets. }

ActorBase Property EncMagicAnomaly Auto
{enemy to spawn}
Explosion Property ExplosionIllusionLight01 Auto
{explosion to play whne it opens}
Explosion Property ExplosionIllusionMassiveLight01 Auto
{explosion to play whne it opens}
; Enemy holders
Actor myEncMagicAnomaly01
Actor myEncMagicAnomaly02
Actor myEncMagicAnomaly03
; Blend values (how open it the portal 0-1)
float fToggleBlendStart = 0.3
float fToggleBlendOpen = 0.9
float fToggleBlendFull = 1.0
float fToggleBlendGone = 0.0
; Temporary blend value holder
float myCurrentBlend
;Is player in trigger and the portal is not open
int playerInTrigger
; Enemy count
int numberOfEnemiesAlive
; Distances with 3000 unit trigger to test fade portal open
float maxTestRange = 1500.0
Float minTestRange = 550.0
; holder for player
actor myPlayer
; gates for making the drath of each enemy affect script only once
int Gate1
int Gate2
int Gate3


STATE FirstState
    Event OnTriggerEnter(ObjectReference akTriggerRef)
        if akTriggerRef == Game.GetPlayer()
            ; put script in its waiting phase. Code after GoToState will still run.
            GoToState("SecondState")
            ;-----spot for your desired code {Feels like I did something wrong here}
           
            RegisterForSingleUpdateGameTime(fHours)
        endif
    EndEvent
ENDSTATE

 auto state waiting
    ; Set initial blend ab=mount for portal and get player locally
    Event onLoad()
        self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendStart)
        myPlayer = game.getPlayer()
    EndEvent
    ;waits for player to enter trigger once he does it tests for distance and triggers the portal to open if he gets close enough
     Event OnTriggerEnter(ObjectReference akActionRef)
        playerInTrigger = 1
        self.SetAnimationVariableFloat("fDampRate", 0.3)
        while playerInTrigger == 1 ;&& playerLeftTrigger
            float myDistance = myPlayer.getDistance(self)
;             debug.trace("myDistance = " + myDistance)
            if myDistance <= minTestRange
                ;player is close enoght to automatically open the portal
                goToState("opened")
                playerInTrigger = 0
            elseIf myDistance <= maxTestRange
                Float animationValue = CalculateAnimationValue(myDistance, minTestRange,maxTestRange, fToggleBlendStart, fToggleBlendFull)
;                 debug.trace("animationValue = " + animationValue)
                self.SetAnimationVariableFloat("fToggleBlend", animationValue)
                utility.wait(0.05)
            endif
        endWhile
    EndEvent
    ;stop testing if player leaves trigger without opening portal
    Event OnTriggerLeave(ObjectReference akActionRef)
        playerInTrigger = 0
    EndEvent
endState



 state opened
    ;The portal is opened playe some explosions and spawn 3 enemies
    Event onBeginState()
;         debug.trace("opened")
        int doOnce = 0
        if doOnce == 0
            self.placeAtMe(ExplosionIllusionLight01)
            utility.wait(0.75)
            self.placeAtMe(ExplosionIllusionMassiveLight01)
            self.KnockAreaEffect(1, 900)
            self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendFull)
            utility.wait(0.5)
            myEncMagicAnomaly01 = self.placeActorAtMe(EncMagicAnomaly)
            myEncMagicAnomaly01.setScale(utility.randomFloat(0.7, 1.25))
                        utility.wait(1.5)
            myEncMagicAnomaly02 = self.placeActorAtMe(EncMagicAnomaly)
            myEncMagicAnomaly02.setScale(utility.randomFloat(0.7, 1.25))
                        utility.wait(0.5)
            myEncMagicAnomaly03 = self.placeActorAtMe(EncMagicAnomaly)
            myEncMagicAnomaly03.setScale(utility.randomFloat(0.7, 1.25))
            numberOfEnemiesAlive = 3
            doOnce = 1
        endIf
    
            utility.wait(3.5)
            self.SetAnimationVariableFloat("fDampRate", 0.03)
            self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendOpen)
;             debug.trace("isDead " + myEncMagicAnomaly01.IsDead())
            ;While ther are some enemies alive test each one to see if they are dead evey half second. If they are run the fade out function.
            while numberOfEnemiesAlive > 0
                utility.wait(0.5)
                if Gate1 == 0
                    if myEncMagicAnomaly01.IsDead() == true
                        anomalyDied()
                        Gate1 = Gate1 + 1
                    endIf
                endIf
                if Gate2 == 0
                    if myEncMagicAnomaly02.IsDead() == true
                        anomalyDied()
                        Gate2 = Gate2 + 1
                    endIf
                endIf
                if Gate3 == 0                
                    if myEncMagicAnomaly03.IsDead() == true
                        anomalyDied()
                        Gate3 = Gate3 + 1
                    endIf
                endIf
            endwhile        
    EndEvent
 endState

STATE SecondState
    Event OnUpdateGameTime()
        ; put it back in its main state
        GoToState("FirstState")
    EndEvent
ENDSTATE

 
 ; function to test the distance from the player to the portal and ramp up the art accordingly
 Float Function CalculateAnimationValue(float PlayerDistance, float NearDistance, float FarDistance, float AnimationMin, float AnimationMax)
    Float percent = 1-((PlayerDistance - NearDistance)/(FarDistance - NearDistance))
    Float returnValue = (percent * (AnimationMax - AnimationMin)) + AnimationMin
    Return returnValue    
EndFunction

; Function to fade out the art each time an enemy dies finally disabling the art after the last enemy
Function anomalyDied()
;         debug.trace("running anomaly died")
;         debug.trace("01 is dead = " + myEncMagicAnomaly01.IsDead())
;         debug.trace("02 is dead = " + myEncMagicAnomaly02.IsDead())
;         debug.trace("03 is dead = " + myEncMagicAnomaly03.IsDead())
        myCurrentBlend = self.GetAnimationVariableFloat("fToggleBlend")
;         debug.trace("myCurrentBlend = "+ myCurrentBlend)
        self.SetAnimationVariableFloat("fToggleBlend", myCurrentBlend - (fToggleBlendOpen / 3))
        numberOfEnemiesAlive = numberOfEnemiesAlive - 1
        if numberOfEnemiesAlive == 0
            utility.wait(0.5)
            self.disable(true)
            endif
EndFunction



Edited by Juebev
Link to comment
Share on other sites

Maybe the following script is a good template for you. It should help to understand what is going on between the state changes. (no guarantee of working)

 

Portal_AnomalySpawnerScript

 

Scriptname Portal_AnomalySpawnerScript extends ObjectReference
{rewritten by ReDragon 2017, support by TheDungeonDweller}
; Basic script for resetting triggers. This can be applied to any trigger.

; https://forums.nexusmods.com/index.php?/topic/5719767-trying-to-get-an-activator-reset-on-timer/
; juebev wrote: "This script is from "Aftershock" quest, anomaly attacks."

  Explosion PROPERTY ExplosionIllusionLight01        auto    ; {explosion to play, when it opens}
  Explosion PROPERTY ExplosionIllusionMassiveLight01 auto    ; {explosion to play, when it opens}

  ActorBase PROPERTY EncMagicAnomaly auto                    ; {enemy base object to spawn}

  Float PROPERTY fHours auto        ; The number of hours to pass before this trigger resets.

; Distances with 3000 unit trigger to test fade portal open
  Float maxTestRange = 1500.0
  Float minTestRange =  550.0

; Blend values (how much open is the portal 0-1)
  Float fToggleBlendStart = 0.3
  Float fToggleBlendOpen  = 0.9
  Float fToggleBlendFull  = 1.0
 ;Float fToggleBlendGone  = 0.0

; Enemy holder
  Actor myEncMagicAnomaly01
  Actor myEncMagicAnomaly02
  Actor myEncMagicAnomaly03

; replacement for playerInTrigger, Is player in trigger and the portal is not open
  Bool bPIT                            

; Enemy count
  Int numberOfEnemiesAlive

; gates for making the drath of each enemy affect script only once
  Int Gate1
  Int Gate2
  Int Gate3


; -- EVENTs -- 2 + waiting + reset

EVENT OnCellAttach()
IF ( !bPIT )
    gotoState("waiting")            ; ### STATE ###
ENDIF
ENDEVENT

EVENT OnCellDetach()
    bPIT = False
ENDEVENT


;=================================
state waiting
;============
EVENT OnLoad()
    self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendStart)
ENDEVENT

EVENT OnTriggerEnter(ObjectReference triggerRef)
; waits for player to enter trigger once he does it tests for distance and triggers the portal to open if he gets close enough

IF ( bPIT )
    RETURN    ; - STOP -    already triggered by the player
ENDIF
;---------------------
IF (triggerRef == Game.GetPlayer() as ObjectReference)
ELSE
    RETURN    ; - STOP -    not the player
ENDIF
;---------------------
    bPIT = TRUE
    self.SetAnimationVariableFloat("fDampRate", 0.3)
    myF_Action(triggerRef)
ENDEVENT


EVENT OnTriggerLeave(ObjectReference triggerRef)
IF (triggerRef == Game.GetPlayer() as ObjectReference)
    bPIT = False                                        ; stop testing, if player leaves trigger without opening portal
ENDIF
ENDEVENT
;=======
endState


;=================================
state opened
;===========
EVENT OnUpdate()
    RegisterForSingleUpdateGameTime(fHours)
    myF_Place()
    Utility.Wait(3.5)
    myF_Portal()
ENDEVENT

EVENT OnUpdateGameTime()
    gotoState("")                    ; ### STATE ###
ENDEVENT
;=======
endState


; -- FUNCTIONs -- 5

;---------------------------------------------
FUNCTION myF_Action(ObjectReference playerRef)
;---------------------------------------------
WHILE ( bPIT )                                            ; playerInTrigger == 1 ;&& playerLeftTrigger
    float f = self.GetDistance(playerRef)                ; f = myDistance
    Debug.Trace(self+" myF_Action() - distance = " +f)

    IF     (f <= minTestRange)                            ; player is close enoght to automatically open the portal
        gotoState("opened")            ; ### STATE ###
        bPIT = False

    ELSEIF (f <= maxTestRange)
        myF_Anim(f)
        Utility.Wait(0.05)
    ENDIF
ENDWHILE

    IF self && self.Is3DLoaded()
        RegisterForSingleUpdate(0.0)
    ENDIF
ENDFUNCTION

;-------------------------
FUNCTION myF_Anim(Float f)
;-------------------------
; function to test the distance from the player to the portal and ramp up the art accordingly
; Float animationValue = CalculateAnimationValue(myDistance, minTestRange,maxTestRange, fToggleBlendStart, fToggleBlendFull)
; PlayerDistance = myDistance = f
; NearDistance   = minTestRange
; FarDistance    = maxTestRange
; AnimationMin   = fToggleBlendStart
; AnimationMax   = fToggleBlendFull

    float fp = 1 - ( (f - minTestRange) / (maxTestRange - minTestRange) )
    float fa = ((fToggleBlendFull - fToggleBlendStart) * fp) + fToggleBlendStart

    Debug.Trace(self+" myF_Anim) - animationValue = " +fa)
    self.SetAnimationVariableFloat("fToggleBlend", fa)
ENDFUNCTION

;-------------------
FUNCTION myF_Place()
;-------------------
;The portal is opened play some explosions and spawn 3 enemies

    self.PlaceAtMe(ExplosionIllusionLight01)
    Utility.Wait(0.75)

    self.PlaceAtMe(ExplosionIllusionMassiveLight01)
    self.KnockAreaEffect(1, 900)
    self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendFull)
    Utility.Wait(0.5)

    float f = Utility.RandomFloat(0.7, 1.25)
    myEncMagicAnomaly01 = self.PlaceActorAtMe(EncMagicAnomaly)
    myEncMagicAnomaly01.SetScale(f)
    numberOfEnemiesAlive = 1
    Utility.Wait(1.5)

    f = Utility.RandomFloat(0.7, 1.25)
    myEncMagicAnomaly02 = self.PlaceActorAtMe(EncMagicAnomaly)
    myEncMagicAnomaly02.SetScale(f)
    numberOfEnemiesAlive = numberOfEnemiesAlive + 1
    Utility.Wait(0.5)

    f = Utility.RandomFloat(0.7, 1.25)
    myEncMagicAnomaly03 = self.PlaceActorAtMe(EncMagicAnomaly)
    myEncMagicAnomaly03.SetScale(f)
    numberOfEnemiesAlive = numberOfEnemiesAlive + 1
ENDFUNCTION

;--------------------
FUNCTION myF_Portal()
;--------------------
    self.SetAnimationVariableFloat("fDampRate", 0.03)
    self.SetAnimationVariableFloat("fToggleBlend", fToggleBlendOpen)

;     debug.trace("isDead " + myEncMagicAnomaly01.IsDead())

; While ther are some enemies alive test each one,
; to see if they are dead evey half second.
; If someone has died, run the fade out function.

    WHILE (numberOfEnemiesAlive > 0)
        Utility.Wait(0.5)

        if (Gate1 == 0)
            if myEncMagicAnomaly01.IsDead()
                anomalyDied()
                Gate1 = Gate1 + 1
            endIf
        endIf

        if (Gate2 == 0)
            if myEncMagicAnomaly02.IsDead()
                anomalyDied()
                Gate2 = Gate2 + 1
            endIf
        endIf

        if (Gate3 == 0)            
            if myEncMagicAnomaly03.IsDead()
                anomalyDied()
                Gate3 = Gate3 + 1
            endIf
        endIf
    ENDWHILE
ENDFUNCTION

;---------------------
FUNCTION anomalyDied()
;---------------------
; to fade out the art each time an enemy dies finally disabling the art after the last enemy

    float f = self.GetAnimationVariableFloat("fToggleBlend")
    self.SetAnimationVariableFloat("fToggleBlend", f - (fToggleBlendOpen / 3))

    numberOfEnemiesAlive = numberOfEnemiesAlive - 1

    IF (numberOfEnemiesAlive == 0)
        Utility.Wait(0.25)
        self.Disable(TRUE)
    ENDIF
ENDFUNCTION

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

Maybe the following script is a good template for you. It should help to understand what is going on between the state changes. (no guarantee of working)

 

Portal_AnomalySpawnerScript

 

 

Ok wow, that is a REALLY well formatted script. Thanks a lot! The script compiled successfully! I'm going to test it and hope it works out. I definitely messed something up in my last attempt so I hope this time it finally works. Looking forward playing around with this, this is actually really exciting, minus the parts when the script is being difficult.

 

But yeah I better understand whats going on now. I think this will help for sure

 

EDIT: Bad news, doesn't seem to be restarting and mobs aren't deleted anymore, good news though is that the portal is completely invisible now, it actually caught me by surprise when I got into range. Will be playing around with this some more, feel we are getting really close to the desire results.

Edited by Juebev
Link to comment
Share on other sites

Hmm yeah I should have asked if you wanted a script similar to the vanilla one.

 

No, it's my mistake. I should've been more clearer, Honestly your script has helped alot about the "states". This is so much scripting I hope at least if someone in the future is in need of a script like this they find this thread. Been thinking about at least making a Winrar or something of all the scripts I've dug up from the past so they are easier to find.

 

I"m going to keep messing around with this script though, been experimenting and been having various results.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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