Jump to content

Two scripting 'jobs' pending. Ideas on how to go...


antstubell

Recommended Posts

... about them.

I am currenntly looking for ways to do these two things.

There are 8 containers.

Script 1. Player can place any object in the container - as per a normal container - but I require a specific item to be placed in each container. I.E.: Player should place in container 1 a fork, in container 2 an apple, in container 3 a war axe and so on for all 8. Then need to check that the correct item is in the correct chest before we progress.

Next...

Script 2.

There are 8 buttons.

Eight buttons placed on a wall. They have to be pressed in a sequence, say Button1, Button5, Button2... and so on. If the sequence is correct then we proceed if a button is pressed 'out of sequence' then 'NA NAH' sound - try again.

 

Ideas please.

Edited by antstubell
Link to comment
Share on other sites

You can use something like this to check all at once. But the player won't have any feedback as to which one(s) could be wrong.

 

 

If Container1.GetItemCount(Item1) >= 1 \
&& Container2.GetItemCount(Item2) >= 1 \
&& Container3.GetItemCount(Item3) >= 1 \
&& Container4.GetItemCount(Item4) >= 1 \
&& Container5.GetItemCount(Item5) >= 1 \
&& Container6.GetItemCount(Item6) >= 1 \
&& Container7.GetItemCount(Item7) >= 1 \
&& Container8.GetItemCount(Item8) >= 1 
  Debug.Trace("All items present in the correct containers")
EndIf

 

If you want feedback, I'd suggest using an OnItemAdded event on each container. Check the incoming item against the desired item and inform them if it is incorrect. Possibly even send the wrong item back to the player.

 

As far as the other... not sure.

Link to comment
Share on other sites

The button script needs to have two arrays. One array contains the combination of buttons that is correct. The second array is the buffer for player input. The idea is that every button press is recorded in the buffer array, and the buffer array is checked against the combination array to match however many buttons have been pushed so far. If they match, the combination thus far is correct and the player may proceed to the next button. If they don't match then you have your "NA NAH," and the buffer array is reset.

Edited by doticu
Link to comment
Share on other sites

@ IsharaMeradin

Why...

 

Debug.Trace("All items present in the correct containers")
EndIf

 

... at the end?

 

Why am I getting errors with this script?

 

Actor Property PlayerRef Auto
GlobalVariable Property My_GVgallObjectPlaced1 Auto
Message Property My_MSGgallPlaceObject Auto
MiscObject Property Quill01 Auto
Container Property Container1 Auto

Event OnActivate(ObjectReference akActionRef)
If akActionRef == PlayerRef
If My_GVgallObjectPlaced1.GetValue() == 0
My_MSGgallPlaceObject.Show()
My_GVgallObjectPlaced1.SetValue(1)
Endif

if Container1.GetItemCount(Quill01) >= 1
debug.notification("Correct item in Correct Container")
Endif

Endif
Endevent

 

(16,14): GetItemCount is not a function or does not exist
(16,36): cannot compare a none to a int (cast missing or types unrelated)
(16,36): cannot relatively compare variables to None

Edited by antstubell
Link to comment
Share on other sites

You can also do the "Button idea" by creating a Master Script that will be listening for the buttons.


My Main Quest Line includes among others the find and insertion of a 15 digit code that the player needs to insert each digit in a "predefined insertion sequence" from a multiple choice menu to retrieve a Master Key, with each wrong insertion all hell breaks loose !!!...

The base's structure idea is more or less the same as yours.


My approaches to do this was :

1) I first did this using "Increment - Decrement on Activate" Counter function and the Counter was in the Master script, but i had a few minor problems with this approach.


2) Using Activation of each button to enable/disable its own xMarkers, then the Master script would listen those xMarkers enable/disable state, but i had a few minor problems with this approach, mainly the complexity of it.


3) So i ended up using "States" within the Master Script that "Each State" will be listening and react just to "One" Correct insertion or a "Group" of Incorrect insertion, this approach was the best one from the previous two for the following reasons:

a) It's way less complicated to create. My final script has only 270 lines, while the previous two were waaaayyyy... bigger.

b) It can easily reset itself after the insertion of an incorrect sequence insertion.


And now everything works like a Swiss clock....


The bigger the number of buttons "Button Sequence" is, the more complicated the script and set up creation will become, so prepare yourself for some serious headaches !.


* From all the things that i've done till now this was by far the most complicated one, simple as an idea but way too complicated to create it correctly.

Edited by maxarturo
Link to comment
Share on other sites

@ IsharaMeradin

Why...

 

Debug.Trace("All items present in the correct containers")

EndIf

 

... at the end?

 

Why am I getting errors with this script?

 

Actor Property PlayerRef Auto

GlobalVariable Property My_GVgallObjectPlaced1 Auto

Message Property My_MSGgallPlaceObject Auto

MiscObject Property Quill01 Auto

Container Property Container1 Auto

 

Event OnActivate(ObjectReference akActionRef)

If akActionRef == PlayerRef

If My_GVgallObjectPlaced1.GetValue() == 0

My_MSGgallPlaceObject.Show()

My_GVgallObjectPlaced1.SetValue(1)

Endif

 

if Container1.GetItemCount(Quill01) >= 1

debug.notification("Correct item in Correct Container")

Endif

 

Endif

Endevent

 

 

(16,14): GetItemCount is not a function or does not exist

(16,36): cannot compare a none to a int (cast missing or types unrelated)

(16,36): cannot relatively compare variables to None

 

The Debug.Trace statement is so you could test and look at your papyrus log as to whether it worked or not. I have no idea if you want on screen feedback or not. You can change that if you wish.

 

GetItemCount works with an ObjectReference. Container exists as a possible property but Bethesda scrapped it and put all the container functions on the Object|Reference script. Probably because Actor needs access to them as well. Change it to ObjectReference Property Container1 Auto and it should work. Just make sure you point it to the specific placed container reference.

Link to comment
Share on other sites

Another way would be to use three scripts and create a quest to use ReferenceAliases for the player and the eight buttons you want to take

 

antPuzzleItemPlayerAliasScript

 

Scriptname antPuzzleItemPlayerAliasScript extends ReferenceAlias
; https://forums.nexusmods.com/index.php?/topic/8128943-two-scripting-jobs-pending-ideas-on-how-to-go/

  GlobalVariable PROPERTY myGlobalCounter auto        ; the counter for each item that has to put inside
  Cell           PROPERTY myPuzzleCell    auto        ; the cell where the containers will be placed by CK

  GlobalVariable PROPERTY myGlobalButtons auto        ; the button counter for each correct activated button
  Int   PROPERTY mySequence = 0x73041625  auto        ; store the right sequence as hexadecimal, linear order 0x76543210
    ; first  button5
    ; second button2
    ; third  button6
    ; ..
    ; eight  button7

  Form[] a        ; to hold buttons for resetting


; -- FUNCTION --

;------------------------------------------------------------
FUNCTION ResetAllButtons(ObjectReference buttonRef, Int iPos)  ; external called by "antButtonAliasScript"
;------------------------------------------------------------
    IF ( a )
    ELSE
        a = new Form[8]                ; initialize the array of buttons, if required!
    ENDIF

    a[iPos] = buttonRef as Form

int i = 0
    WHILE (i < a.Length)
        objectReference oRef = a[i] as ObjectReference
        IF ( oRef )
            oRef.Reset()            ; reset any button already used
        ENDIF
        i = i + 1
    ENDWHILE

    myGlobalButtons.setValue(0)
ENDFUNCTION


; -- EVENTs -- 4

EVENT OnInit()
    Debug.Trace("Quest started with alias " +self)
ENDEVENT


EVENT OnPlayerLoadGame()
    Debug.Trace("Game has been loaded with alias " +self)
ENDEVENT


EVENT OnCellLoad()
    actor player = self.GetActorReference()
    IF (myPuzzleCell == player.GetParentCell())
        RegisterForSingleUpdate(1.11)
    ENDIF
ENDEVENT


EVENT OnUpdate()
IF ( myGlobalCounter )
    IF (myGlobalCounter.GetValue() == 8)
        Debug.Notification("All container items are correct!")
    ELSE
        RegisterForSingleUpdate(1.0)
    ENDIF
ENDIF

 

 

 

antButtonAliasScript

 

Scriptname antButtonAliasScript extends ReferenceAlias
; https://forums.nexusmods.com/index.php?/topic/8128943-two-scripting-jobs-pending-ideas-on-how-to-go/

; idea: Eight buttons placed on a wall. They have to be pressed in a sequence,
; say Button1, Button5, Button2... and so on.

; If the sequence is correct then we proceed,
; if a button is pressed 'out of sequence' then 'NA NAH' sound - try again.


  ReferenceAlias PROPERTY playerAlias auto        ; the quest alias filled with unique "player"
  Sound          PROPERTY myFailSound auto

  Int PROPERTY iButton = -1 auto                ; [default= -1]
  {sequence from 0..7, select a number}


; -- EVENTs --

EVENT OnInit()
    Debug.Trace("OnInit(" +iButton+ ") - has been reached for .. " +self)    ; should be logged 8 times
ENDEVENT


;EVENT OnCellLoad()
;    self.BlockActivation(TRUE)
;ENDEVENT
;
;EVENT OnUnLoad()
;    self.BlockActivation(False)
;ENDEVENT


EVENT OnActivate(ObjectReference akActionRef)
IF (akActionRef == Game.GetPlayer() as ObjectReference)
    myF_Action()
ENDIF
ENDEVENT


; -- FUNCTIONs -- 2

;--------------------------------------------
Bool FUNCTION myF_IsButtonOK(Int i, Int iPos)  ; internal helper
;--------------------------------------------
; as hexadecimal sample, if (i == 0x01234567)

    IF     (iPos == 0)
        ; nothing                ; 7

    ELSEIF (iPos == 1)
        i = i / 0x00000010        ; 6

    ELSEIF (iPos == 2)
        i = i / 0x00000100        ; 5

    ELSEIF (iPos == 3)
        i = i / 0x00001000        ; 4

    ELSEIF (iPos == 4)
        i = i / 0x00010000        ; 3

    ELSEIF (iPos == 5)
        i = i / 0x00100000        ; 2

    ELSEIF (iPos == 6)
        i = i / 0x01000000        ; 1

    ELSEIF (iPos == 7)
        i = i / 0x10000000        ; 0

    ELSE
        RETURN False            ; button puzzle already solved
    ENDIF

    RETURN ((i % 0x10) == iButton)    ; finally we use modulo for comparing
ENDFUNCTION


;--------------------
FUNCTION myF_Action()  ; internal only
;--------------------
    antPuzzleItemPlayerAliasScript ps = playerAlias as antPuzzleItemPlayerAliasScript

IF ( ps )
ELSE
    Debug.Trace("Error: playerAlias script not found!")
    RETURN    ; - STOP -
ENDIF
;---------------------
    globalVariable g = ps.myGlobalButtons

    IF myF_IsButtonOK(ps.mySequence, g.GetValueInt())
        g.Mod(1)
        Debug.Trace("Pressed correct button " +iButton)
    ELSE
        myFailSound.Play(Game.GetPlayer() as ObjectReference)
        ps.ResetAllButtons(self.GetReference(), g.GetValueInt())
    ENDIF
ENDFUNCTION

 

 

 

antContainerScript

 

Scriptname antContainerScript extends ObjectReference
; https://forums.nexusmods.com/index.php?/topic/8128943-two-scripting-jobs-pending-ideas-on-how-to-go/

  GlobalVariable PROPERTY myGlobalCounter auto        ; the counter for each item that has to put inside
  ; need to check that the correct item is in the correct chest before we progress
  ; IF (myGlobalCounter.GetValue == 8)

  FormList PROPERTY myList    auto        ; make your own list
  ; 0 - container1 -> a fork
  ; 1 - container2 -> an apple
  ; 2 - container3 -> a waraxe
  ; ..
  ; 8 - container8 -> ..
 
  Int PROPERTY ItemCount auto            ; [default=0]
  ; should be set for each container from 1..8, see formlist above


; -- EVENTs -- 3

EVENT OnInit()
    Debug.Trace("OnInit(" +ItemCount+ ") - has been reached for .. " +self)        ; should be logged 8 times

;;;    IF (ItemCount > 0) && (myList.GetSize() >= ItemCount)
;;;        int i = ItemCount - 1
;;;        self.AddInventoryFilter( myList.GetAt(i) )
;;;        ; https://www.creationkit.com/index.php?title=AddInventoryEventFilter_-_ObjectReference
;;;    ENDIF
ENDEVENT


EVENT OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
; received when an item is added to this objects inventory.
; If the item is a persistant reference, akItemReference will point at it - otherwise the parameter will be None.

IF (akBaseItem == myList.GetAt(ItemCount - 1))
    gotoState("Done")                ; ### STATE ###
    myGlobalCounter.Mod(1)                                                ; (+1) threadsafe update the globalVar
    Debug.Notification("Item added correctly to container " +ItemCount)
ELSE
    Debug.Notification("Wrong item for container " +ItemCount)
    self.RemoveItem(akBaseItem, aiItemCount, False, akSourceContainer)
ENDIF
ENDEVENT


;=====================
state Done
;=========
EVENT OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
; received when an item is removed from this objects inventory. If the item is a persistant reference, akItemReference
; will point at it - otherwise the parameter will be None

IF (akBaseItem == myList.GetAt(ItemCount - 1))
    gotoState("")                    ; ### STATE ###
    myGlobalCounter.Mod(-1)                                                ; (-1) threadsafe update the globalVar    
    Debug.Trace("Item has been removed from container " +ItemCount)
ENDIF
ENDEVENT
;=======
endState

 

 

 

keep in mind this is a proposal, how does it could work?

Edited by ReDragon2013
Link to comment
Share on other sites

  • Recently Browsing   0 members

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