Jump to content

Photo

Issues while scripting for puzzles, need assist

papyrus script help

  • Please log in to reply
25 replies to this topic

#1
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

This is going to be lengthy because I've gotten myself into a corner with a few things for an upcoming mod... I'll try and keep this organized, brief, and terse.

 

Problem 1:

I have the following items already set in place.

- a container EFTH_PZ1_Container, with this script. Currently this is intended to open everything up and set the light green when food is placed, but for now I'm allowing for any placed item.

Scriptname EFTH_Puzzle01Control extends ObjectReference

ObjectReference property DoorController auto
ObjectReference property LightController auto


Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
	if (aiItemCount > 0)
		DoorController.activate(game.getplayer())
		LightController.activate(game.getplayer())
	endIf
endEvent

- marker EFTH_PZ1_DoorController, with script:

Scriptname EFTH_DoorControlActivator extends ObjectReference

objectReference property ControlledDoor auto

Event onActivate(ObjectReference akActionRef)
	ControlledDoor.Activate(game.getplayer())
endEvent
	

- marker EFTH_PZ1_LightController, with script:

Scriptname EFTH_IndicatorLightScript extends ObjectReference

ObjectReference property IndicatorLight auto

event onActivate(objectReference akActionRef)
	IndicatorLight.PlayAnimation("Green")
endEvent

- door EFTH_PZ1_ExitDoor, with vanilla script DefaultUnlockLinkonActivate, and bShouldOpenDoor set true. Activate parent linked to EFTH_PZ1_DoorController

- activator EmergencyLightAnim01, activate parent EFTH_PZ1_LightController.

 

Behavior: When the door reference is set to inaccessible, this all works as intended when the two markers have the container set as an activate parent. However, this means the door isn't closeable, and since I want parts of this setup portable (40 more doors to do later), I want user control afterwards. But, with the reference accessible and locked to any tier, and the unlock function added to the doorcontroller script, everything fires on accessing the container, and fires repeatedly. Removing the activate parent links from the markers to the container just result in getting the door lock warning when accessing the container, and no activations. I'm obviously not doing something right here....

 

I'm going to put the other two in responses to keep this organized

 



#2
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

Item number two:  A little easier to deal with since this isn't fleshed out yet and I'm hunting for how exactly to do it.

 

I have a test fixture for a puzzle that will eventually be expanded into something more complex, but I want to get this part working singly first so I know what I'm doing.

- there is a trigger box set above a pad (just texture) on a table. This trigger box has an L_TRIGGER collision boundary, and a script that watches for OnTriggerEnter and/or OnTriggerLeave, and calls activate on a control marker like the above puzzle, but only after checking that the object that tripped the trigger contains a specific keyword.

- I have a Misc Item configured with that keyword, that is movable by the player. It's a clean bowling pin.

- eventually, the animated light and locked door setup like item 1

 

The point would be (for the test fixture) that the light animates green and door unlocks, ONLY when the bowling pin is set on the table, and at no other time. Unfortunately, it seems that when I hop on the table, it gets activated as well.  Eventually this is going to get expanded into a ten trigger array where the puzzle 'resolves' and unlocks everything when special bowling pins are in two of the triggers, and not in the other eight trigger volumes. All volumes start off with bowling pins, which is why I'm watching for OnTriggerLeave and scanning through using getTriggerObjectCount in the 'real' version.

 

Mostly looking for hints, tricks, and missed details here...



#3
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

Item number three, the easiest yet because this mostly works...

 

I've made a moveable static object using the prewar painting 01 NIF. This object has damage settings; it starts with 100 points at stage 1, and every 25% loss moves into the next stage and swaps for the next prewar painting NIF (02, 03, etc) just to have visible proof that it's working. There is a script that watches the damage stage and when it's greater than 4 (i.e. enters stage 5 at 0% health remaining), clears the damage which therefore returns to stage 0 and starts over.

 

Setting self-damage to 10 points per second on one of these, doesn't actually start self-damaging and cycling until you go up and strike the object. That I can live with since it's a test, but wonder why self-damage doesn't initiate even though I've given the object a script that watches event onInit and issues self.DamageObject(10.0).

 

The other test object is identical except there's no self-damage, damage is keyed to a damageObject call attached to onActivate on an external switch. I ran out of testing time yesterday and had accidentally picked a nonfunctional switch... but the idea is to press a button, which damages the painting enough to move to the next stage and swap NIFs. Endgame here is to create NIFs with custom pictograms, letters, or numbers that would cycle through when the button is pressed, eventually to where the player selects the correct ones in a string or grid of these objects, and unlocks the puzzle.

 

Mostly looking for caveats here and why the start and reset would malfunction on the first test painting, since auto-cycling might be used in one or two of these puzzles. I have yet to test the second one with a 'good' switch.



#4
ThoraldGM

ThoraldGM

    Old hand

  • Premium Member
  • 511 posts

I'm still digesting this, but will throw a couple of initial thoughts out there.

 

If DefaultUnlockLinkOnActivate is restricting your functionality, can't you add the relevant parts of it to your own custom script, use that, and expand what you need from there?

 

According to the CK wiki, actors will trigger the collision layer but statics won't.

 

There's a lot to juggle in your post, so I may be wrong. Plus I'm still looking.



#5
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

Thank for looking at my woes....

 

The CK has a strange notation to it, it's saying that the collision layer defines what trips the trigger, but then gives an example that seems to match up with the default setting. That's why I mentioned L_TRIGGER, because the static *does* definitely trip collision. My issue is, so do I... and that's probably the fault of the activate parent link. And through all these that's a common issue...

 

...what I'm missing, is what the proper way of getting an activation of another object to happen from a scripted event actually is, because activate parent links I'm sure simply pass one object's activation up the chain to the next one regardless of what I have in the script. Which is strange as to why the first item (the container>door puzzle) would work at all with parent links. I'm fuzzy on this part of the concept and can't seem to see through it, because it seems to me that even without a parent link, calling a reference directly with activate() should activate it.

 

What's correct to pass in activator(), or does it matter? I've used game.getplayer(), I've used 'self'. doesn't seem to make a difference because I'm not using that info in the next script.

 

EDIT: Oh, and since you RT'd the link I figure I'd better note what the 'look and feel' is supposed to be from these things.

1 - There's a sign on the ground that says 'don't feed the bears' except don't is marked out. There's a teddy bear on a table, you check it out and it's a container. You drop some food in, close, and  green light appears on the door next to it, which is now unlocked and opens automatically.

 

2 - There's a table on the floor with ten bowling pins standing set up, and an arrow pointing towards them that says "Seven Ten Split". You carefully remove all the pins that would have been knocked down in a seven/ten split, leaving those two pins on the table in their proper locations (there are black squares). Once the configuration is right, a green light appears above a door, that unlocks and automatically opens.

 

3 - That one is a piece of a larger setup, but here's a concept. You enter the room that the last puzzle unlocked. On the wall is a grid of four picture frames with four buttons. You notice that when you press the button next to a frame, the picture in the frame changes color... white, red, green, blue. You notice there's a little mark under one, and the carpet in this room is four different colors. The mark corresponds to the door... so you press the buttons to change the colors on the frames until they match the carpet. When it's right, you hear a bell, head out to the hallway and notice a new door has a green light and has unlocked and opened.

Alternately, #3's frames could cycle a partial or full alphabet and a row of them could correspond to a keyword you'd picked up or deciphered elsewhere in the mod. Same result, get it right and another door unlocks w/green light indicator.



#6
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

Alright, some changes and testing and here's what I've found.

 

1 - I apparently have not enabled debugging logs, because all the debug.trace I added did nothing.

 

2 - (bowling pin puzzle) I hedged my bets previously and added a light that is enabled only when the trigger is set off. Grabbed a pin and waved it through the trigger volume, and the light flashed on every time and off when it was out. Light stayed off when I hopped on the table, so that part's working properly, and that narrows the issue down to having trouble passing activations around properly.

 

3 - (bear container) Changed this quite a bit to not use the door's activation script at all, just check that it's locked before unlocking/setopen, and similar with the light script (added boolean set onInit 0, and set 1 when running the activation script, and only run the routine if boolean is 0, i.e. once). Cut the activateparent links. And... nothing worked. Again, can't seem to properly activate an external reference from a script.

 

4 - (painting damage NIF swap) put in a proper switch, switch works... through one cycle. The painting is apparently not resetting to stage 0, not clearing the damage. Need to study other methods of "making it healthy" so the cycle repeats on demand.

 

So most of my issues come down to activating an external reference so it runs it's scripts. What am I missing?



#7
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

This is a compilations of screenshots made during testing, showing that the L_TRIGGER collision layer on the trigger volume, with scripting to check for the pin's keyword, does activate with the pin present, and not the player. The 'test light' (subway light) is scripted directly from the trigger volume reference, to enable when activated.

 

Ignore the green light, that's still tied to the control marker which is still using an activate parent link to the trigger volume and fires when anything touches that volume.

 

So what I need to do is figure out how to activate the control marker from the script in the trigger volume. Does that need registerForRemoteEvent, or is there a link ref w/keyword that I'm unaware of?

Attached Files



#8
ThoraldGM

ThoraldGM

    Old hand

  • Premium Member
  • 511 posts

"So what I need to do is figure out how to activate the control marker from the script in the trigger volume. Does that need registerForRemoteEvent, or is there a link ref w/keyword that I'm unaware of?"

 

If the trigger volume script is directing the action, you could use the CK to assign the control marker as a property of the trigger volume script, then call functions directly on that property.

 

If the control marker wasn't invited to the party at all, but wants to be included and react to things the trigger volume is experiencing, then you would use RegisterForRemoteEvent *from the control marker* to "spy on" the trigger volume remotely.

 

Edit: I think the first option (declaring a script property) is easiest method whenever possible. I use RegisterForRemoteEvent quite a bit, but from scripts that are attached to quests, not the objects themselves. Hence the "remote" part.

 

Also would be easier to understand the issue by seeing updated code.



#9
mfree80286

mfree80286

    Fan

  • Premium Member
  • 363 posts

This is the script in the trigger volume (it's not quite there with onTriggerLeave but this was made to demonstrate first)

Scriptname EFTH_ItemInTrigger01 extends ObjectReference

ObjectReference property PuzzControllerAct auto
Keyword property PuzzleItemKeyword auto

event onTriggerEnter (ObjectReference akTriggerRef)
	if akTriggerRef.HasKeyword(PuzzleItemKeyword)
		PuzzControllerAct.activate(akTriggerRef)
	endIf
endEvent

event onTriggerLeave (ObjectReference akTriggerRef)
	if GetTriggerObjectCount() == 0
		PuzzControllerAct.activate(akTriggerRef)
	endIf
endEvent

PuzzControllerAct is a reference to the control marker. This apparently does not properly pass activate()...



#10
ThoraldGM

ThoraldGM

    Old hand

  • Premium Member
  • 511 posts

Looks fine. Do you have an OnActivate() function in a script attached to PuzzControllerAct object?







Also tagged with one or more of these keywords: papyrus script help

Page loaded in: 0.751 seconds