Jump to content

Recommended Posts

Posted

I'm looking for help modifying the script for the woodchopping block.

 

This is what I want it to do: after having chopped 6 pieces of firewood, the woodchopping block will deplete (= unusable for 1 month), a message will pop up "You can't chop anymore wood for now."

 

I want this to be seperate for each woodchopping block in the world. For instance, if I depleted the woodchopping block in Whiterun, I can still chop 6 pieces in Riverwood, till it's depleted.

 

This is the Vanilla script:

 

 

  Reveal hidden contents

 

I don't know that much about scripting so I was wondering whether anyone could help me make the right adjustments to the script.

 

Thanks in advance

 

Kind regards

 

Sac

Posted

Be quite simple in theory.

 

In brief:

Add 3 properties and 1 local variable to the script.

Do a quick check when activating if it's been x amount of days since last use, if not then display a message to say chopping block is depleted.

If it's been greater then x days then process the activation.

 

3 Properties and a local variable to add:

First property would be for so you can get the Game Days passed, which is a native game global variable.

So you would add to the script and fill it in CK (Auto-Fill will fill this property for you):

GlobalVariable Property GameDaysPassed Auto

Second Property to add would be a float value of How many game days you want to specify before it can be used again:

Float Property ResetDays = 30.0 Auto

I gave it a default value of 30 days, but you can a fill a value in CK to how ever many days you'd want before it resets.

 

Third property would be a Message to display when the user activates the chopping block and it's not ready to be used:

Message Property NotReadyMsg Auto

 

Lastly a local variable that we use to store a time stamp so you can check if the days passed is less or more then the require reset days:

Float LastTimeStamp

 

Now fit a small check into the script when the copping block is activated:

If (GameDaysPassed.GetValue() - LastTimeStamp) >= ResetDays
    ;Process the normall activation of the chopping block
    
    
    
    
    ;When the processing is done set the new time stamp value
    LastTimeStamp = GameDaysPassed.GetValue()
Else
    ; Display a message that the chopping block isn't ready for use
    NotReadyMsg.Show()
EndIf

 

Doesn't need to be the above way exactly but just some food for thought.

I can provide the script edited and to suite your needs, but where's the fun in that :tongue:

So I just thought I'd give a basic idea of how you can tackle it yourself :smile:

Posted
  On 7/25/2015 at 12:27 AM, sLoPpYdOtBiGhOlE said:

Be quite simple in theory.

 

In brief:

Add 3 properties and 1 local variable to the script.

Do a quick check when activating if it's been x amount of days since last use, if not then display a message to say chopping block is depleted.

If it's been greater then x days then process the activation.

 

3 Properties and a local variable to add:

First property would be for so you can get the Game Days passed, which is a native game global variable.

So you would add to the script and fill it in CK (Auto-Fill will fill this property for you):

GlobalVariable Property GameDaysPassed Auto

Second Property to add would be a float value of How many game days you want to specify before it can be used again:

Float Property ResetDays = 30.0 Auto

I gave it a default value of 30 days, but you can a fill a value in CK to how ever many days you'd want before it resets.

 

Third property would be a Message to display when the user activates the chopping block and it's not ready to be used:

Message Property NotReadyMsg Auto

Lastly a local variable that we use to store a time stamp so you can check if the days passed is less or more then the require reset days:

Float LastTimeStamp

Now fit a small check into the script when the copping block is activated:

If (GameDaysPassed.GetValue() - LastTimeStamp) >= ResetDays
    ;Process the normall activation of the chopping block
    
    
    
    
    ;When the processing is done set the new time stamp value
    LastTimeStamp = GameDaysPassed.GetValue()
Else
    ; Display a message that the chopping block isn't ready for use
    NotReadyMsg.Show()
EndIf

Doesn't need to be the above way exactly but just some food for thought.

I can provide the script edited and to suite your needs, but where's the fun in that :tongue:

So I just thought I'd give a basic idea of how you can tackle it yourself :smile:

 

Thank you very much! :D

 

So far I have edited the script to this:

 

 

Scriptname ResourceFurnitureScript2 extends ObjectReference  Conditional
{script for furniture which the player can use to get resources}


formlist Property requiredItemList Auto  
{required for player to use - optional}

Message Property FailureMessage Auto  
{Message to say why you can't use this without RequiredWeapon}

MiscObject Property Resource Auto  
{what you get from using this furniture}

int Property ResourceCount = 1 Auto
{how many resources you get per use}

int property MaxResourcePerActivation = 6 auto
{How many times can this object be used before the player has to re-activate?}

int counter
; count up how many resources have been gathered on this go.

faction property CurrentFollowerFaction auto
{Used to handle player followers using the furniture object}

objectReference property NPCfollower auto hidden
{hidden property to track followers who used this}

GlobalVariable Property GameDaysPassed Auto

Float Property ResetDays = 30.0 Auto

Message Property NotReadyMsg Auto

Float LastTimeStamp

Event OnLoad()
    BlockActivation(true)
endEvent

Event OnUnload()
    ; safety measure
    UnregisterForEvents(game.getplayer())
    if NPCfollower
        UnregisterForEvents(NPCfollower)
    endif
endEvent

auto STATE normal
Event OnActivate(ObjectReference akActionRef)
    if (GameDaysPassed.GetValue() - LastTimeStamp) >= ResetDays
        ;Process the normal activation of the chopping block
    
        gotoState("busy")
    ;     debug.trace(self + "OnActivate")
        if akActionRef == Game.GetPlayer()  || (akActionRef as actor).isInFaction(CurrentFollowerFaction)
    ;        debug.trace("akActionRef is either player or a follower")
            if (akActionRef as actor) != game.getPlayer()
    ;             debug.trace("It's a follower - store in NPCfollower property")
                ; if not the player, must be the follower
                NPCfollower = akActionRef
            endif
            bool allowActivation = true
            ; check if player has required item
            if requiredItemList
                if akActionRef.GetItemCount(requiredItemList) == 0
                    if akActionRef == game.getPlayer()
                        ; only require the axe item for the player
                        allowActivation = false
    ;                     debug.trace("allowActivation = "+allowActivation)
                        FailureMessage.Show()
                    endif
                endif
            endif

            if allowActivation
                RegisterForEvents(akActionRef)
    ;             debug.trace(self + "player/follower activation START")
                Activate(akActionRef, true)
    ;             debug.trace(self + "player/follower activation END")
            endif
        else
    ;         ;debug.trace(self + "non-follower NPC activation START")
            ; just activate it
            Activate(akActionRef, true)
    ;         ;debug.trace(self + "non-follower NPC activation END")
        endif
        gotoState("normal")
        
        ;When the processing is done set the new time stamp value
        LastTimeStamp = GameDaysPassed.GetValue()
    else
        ;Display a message that the chopping block isn't ready for use
    NotReadyMsg.Show()
    endIf
endEvent
endState

STATE busy
    ; do nothing
endState

Event OnAnimationEvent(ObjectReference akSource, string asEventName)
;     debug.trace(self + ": animation event received=" + asEventName)
    if asEventName == "AddToInventory"
        akSource.AddItem(Resource, ResourceCount)
        ; increment counter by however many items we just received
;         debug.trace("Pre-add counter = "+counter)
        counter = (counter + resourceCount)
;         debug.trace("Post-add counter = "+counter)
        if counter >= MaxResourcePerActivation
            ; if we've bagged our limit, kick the player out.  Reset timer for next activation
;             debug.trace("Woodpile - player has gotten "+counter+" logs this go.  Kicking out.")
            counter = 0
            (akSource as actor).PlayIdle(IdleWoodchopExit)
            unregisterForEvents(akSource)
        endif
    elseif asEventName == "IdleFurnitureExit"
;         debug.trace("Resource Object Unregistering: "+self)
        ; reset the counter if I exit manually
        counter = 0
        UnregisterForEvents(akSource)
    endif
endEvent

bool isRegisteredForEvents = false

function RegisterForEvents(objectReference whoToRegister)
    ; centralize this
    isRegisteredForEvents = true
    RegisterForAnimationEvent(whoToRegister, "AddToInventory")
    RegisterForAnimationEvent(whoToRegister, "SoundPlay . NPCHumanWoodChop")
    RegisterForAnimationEvent(whoToRegister, "IdleFurnitureExit")
endFunction

function UnregisterForEvents(objectReference whoToUnregister)
    ; centralize this
    
    ; It is perfectly safe to unregister for events you never registered for, however
    ; this function is called as part of OnUnload, and if this object isn't persistent
    ; then it may be deleted by the time OnUnload runs, and these function calls will
    ; fail. Since RegisterForAnimationEvent persists us, we know it will be safe to
    ; call Unregister if we've previously Registered, even if called as a part of
    ; OnUnload
    if isRegisteredForEvents
        isRegisteredForEvents = false
        UnRegisterForAnimationEvent(whoToUnregister, "AddToInventory")
        UnRegisterForAnimationEvent(whoToUnregister, "IdleFurnitureExit")
    endif
endFunction

Idle Property IdleWoodchopExit  Auto 

 

However, when I try to activate the woodchopping block now, I always get the "Not Ready" message. I'm a little bit unsure where to place the first and second part of the small check.

Posted

Easy enough.
Because you haven't set a LastTimeStamp, you need to set one for it to actually be able to compare against.
Other wise the LastTimeStamp would always be 0.0.
So you add a one off LastTimeStamp to get the ball rolling eg:

Scriptname ResourceFurnitureScript2 extends ObjectReference  Conditional
{script for furniture which the player can use to get resources}

formlist Property requiredItemList Auto  
{required for player to use - optional}

Message Property FailureMessage Auto  
{Message to say why you can't use this without RequiredWeapon}

MiscObject Property Resource Auto  
{what you get from using this furniture}

int Property ResourceCount = 1 Auto
{how many resources you get per use}

int property MaxResourcePerActivation = 6 auto
{How many times can this object be used before the player has to re-activate?}

int counter
; count up how many resources have been gathered on this go.

faction property CurrentFollowerFaction auto
{Used to handle player followers using the furniture object}

objectReference property NPCfollower auto hidden
{hidden property to track followers who used this}

GlobalVariable Property GameDaysPassed Auto

Float Property ResetDays = 30.0 Auto

Message Property NotReadyMsg Auto

Float LastTimeStamp
Bool bFirstTimeStamp ;<--- Added for first time run

Event OnLoad()
    BlockActivation(true)
    
    ; Only one time as we havent used the Chopping block then you don't have a LastTimeStamp and it will always be 0.0
    If !bFirstTimeStamp
        bFirstTimeStamp = !bFirstTimeStamp
        LastTimeStamp = (GameDaysPassed.GetValue() - ResetDays)
    EndIf
endEvent

Event OnUnload()
    ; safety measure
    UnregisterForEvents(game.getplayer())
    if NPCfollower
        UnregisterForEvents(NPCfollower)
    endif
endEvent

auto STATE normal
Event OnActivate(ObjectReference akActionRef)
    gotoState("busy")
    if (GameDaysPassed.GetValue() - LastTimeStamp) >= ResetDays
        ;Process the normal activation of the chopping block
    
        
    ;     debug.trace(self + "OnActivate")
        if akActionRef == Game.GetPlayer()  || (akActionRef as actor).isInFaction(CurrentFollowerFaction)
    ;        debug.trace("akActionRef is either player or a follower")
            if (akActionRef as actor) != game.getPlayer()
    ;             debug.trace("It's a follower - store in NPCfollower property")
                ; if not the player, must be the follower
                NPCfollower = akActionRef
            endif
            bool allowActivation = true
            ; check if player has required item
            if requiredItemList
                if akActionRef.GetItemCount(requiredItemList) == 0
                    if akActionRef == game.getPlayer()
                        ; only require the axe item for the player
                        allowActivation = false
    ;                     debug.trace("allowActivation = "+allowActivation)
                        FailureMessage.Show()
                    endif
                endif
            endif

            if allowActivation
                RegisterForEvents(akActionRef)
    ;             debug.trace(self + "player/follower activation START")
                Activate(akActionRef, true)
    ;             debug.trace(self + "player/follower activation END")
            endif
        else
    ;         ;debug.trace(self + "non-follower NPC activation START")
            ; just activate it
            Activate(akActionRef, true)
    ;         ;debug.trace(self + "non-follower NPC activation END")
        endif
        
        
        ;When the processing is done set the new time stamp value
        LastTimeStamp = GameDaysPassed.GetValue()
    else
        ;Display a message that the chopping block isn't ready for use
        NotReadyMsg.Show()
    endIf
    gotoState("normal")
endEvent
endState

STATE busy
    ; do nothing
endState

Event OnAnimationEvent(ObjectReference akSource, string asEventName)
;     debug.trace(self + ": animation event received=" + asEventName)
    if asEventName == "AddToInventory"
        akSource.AddItem(Resource, ResourceCount)
        ; increment counter by however many items we just received
;         debug.trace("Pre-add counter = "+counter)
        counter = (counter + resourceCount)
;         debug.trace("Post-add counter = "+counter)
        if counter >= MaxResourcePerActivation
            ; if we've bagged our limit, kick the player out.  Reset timer for next activation
;             debug.trace("Woodpile - player has gotten "+counter+" logs this go.  Kicking out.")
            counter = 0
            (akSource as actor).PlayIdle(IdleWoodchopExit)
            unregisterForEvents(akSource)
        endif
    elseif asEventName == "IdleFurnitureExit"
;         debug.trace("Resource Object Unregistering: "+self)
        ; reset the counter if I exit manually
        counter = 0
        UnregisterForEvents(akSource)
    endif
endEvent

bool isRegisteredForEvents = false

function RegisterForEvents(objectReference whoToRegister)
    ; centralize this
    isRegisteredForEvents = true
    RegisterForAnimationEvent(whoToRegister, "AddToInventory")
    RegisterForAnimationEvent(whoToRegister, "SoundPlay . NPCHumanWoodChop")
    RegisterForAnimationEvent(whoToRegister, "IdleFurnitureExit")
endFunction

function UnregisterForEvents(objectReference whoToUnregister)
    ; centralize this
    
    ; It is perfectly safe to unregister for events you never registered for, however
    ; this function is called as part of OnUnload, and if this object isn't persistent
    ; then it may be deleted by the time OnUnload runs, and these function calls will
    ; fail. Since RegisterForAnimationEvent persists us, we know it will be safe to
    ; call Unregister if we've previously Registered, even if called as a part of
    ; OnUnload
    if isRegisteredForEvents
        isRegisteredForEvents = false
        UnRegisterForAnimationEvent(whoToUnregister, "AddToInventory")
        UnRegisterForAnimationEvent(whoToUnregister, "IdleFurnitureExit")
    endif
endFunction

Idle Property IdleWoodchopExit  Auto
Posted

This is the final script I came up with.

 

 

  Reveal hidden contents

 

 

I looked at the failmessage when you don't have an axe and added your lines in a similar fashion.

 

I also added I also added allowActivation=false and debug.trace("allowActivation = "+allowActivation). I'm not 100% sure what they do, though. (Is it safe to do this?) But it seems to work fine, tbh.

  • Recently Browsing   0 members

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