Jump to content
ℹ️ Intermittent Download History issues ×

Completing quest objective to visit Xmarker locations


SKKmods

Recommended Posts

I have a quest that involves visiting a bunch of unmarked wilderness locations, defined with Xmarkerrefs. The Target Ref quest map markers show on the map through the Alias Refs fine.

 

The problem is defining the objective/stage completion when the player gets to them. No killing or picking up stuff, just "visit the location" and enjoy the view. None of the location based condition functions or code methods wants to work on an Alias or Objref.

 

Is there an easy way to establish a "player has visited location" quest objective completion, or should I not be using Xmarkerrefs ?

 

IsCleared() - type mismatch

.IsSameLocation - type mismatch

.IsInSameCurrentLocAsRef - no viable input

 

I have poked around the MQ/BOS quests and still cant figure it out. /brain-hurty

Edited by SKK50
Link to comment
Share on other sites

One option would be to put a trigger box around the area and script on it to update the quest with info stating that player visited that spot. Either using a global counter for how many spots you have, then just setting the objective complete, or you could use unique globals for each spot if you need some way to know which ones have been visited. That could allow you do script setting the global prior to the quest triggering, then have the quest check the global before setting the destination objectives. Unless you want to force the player to goto the spot only after starting the quest. In which case you would want your trigger script to also have a check if your quest is running and/or on an appropriate stage. The trigger should also turn itself off (preferably using states or disable+delete) once triggered.

Link to comment
Share on other sites

Trigger Volume - fantastic, haven't used them yet so will try out. Appreciated.


& Later: Trigger volumes do the job great (memo: common activator, individual scripts, set primitive collision layer L_TRIGGER).


Cant figure out how to disable a trigger after it has fired, so use a silent objective get/set per location as a unique flag placeholder.

Edited by SKK50
Link to comment
Share on other sites

Trigger Volume - fantastic, haven't used them yet so will try out. Appreciated.

 

& Later: Trigger volumes do the job great (memo: common activator, individual scripts, set primitive collision layer L_TRIGGER).

 

Cant figure out how to disable a trigger after it has fired, so use a silent objective get/set per location as a unique flag placeholder.

 

The way I do it is something like this:

Scriptname demoTriggerWithDisable Extends ObjectReference
 
Quest Property pQuestToFire Auto Const
Int Property iStageToSet Auto Const
GlobalVariable pSomeGlobalValue Auto Const
 
Auto State Waiting
    Event OnTriggerEnter(ObjectReference akActionRef)
        ; error validation
        if pQuestToFire && iStageToSet
            GotoState("Finished") ; this will ensure any further entering of the trigger box doesn't do anything.
            pQuestToFire.SetStage(iStageToSet)
            Disable() ; just for good measure
        endif
        ; optionally/as well do something with the global
        if pSomeGlobalValue
            pSomeGlobalValue.Value = pSomeGlobalValue.Value + 1
        endif
    EndEvent
EndState
 
State Finished
    ; intentionally empty
EndState

I haven't tried to compile this as I wrote it quickly from memory. The idea is that you set the quest and stage and/or the global and they can operate independently. The script can then be used generically on a single type of activator and then property specifics set on the individual object refs when placed.

 

You could also add a Delete() or DeleteWhenAble() after the Disable() if you wanted the ref to be fully killed and removed. I leave them in case there's a circumstance that comes up where I might need to edit the script and re-enable the trigger for some reason.

Edited by BigAndFlabby
Link to comment
Share on other sites

Nice, that will save constant if statement processing.

 

Another thread I just happened across suggested an alternative to the auto state. Using the OnInit in the empty state to set the waiting state instead. In the use case for this script I'm not sure if there is any appreciable difference in the effect of the script. Just thought I'd mention it.

Edited by BigAndFlabby
Link to comment
Share on other sites

For completeness I now have a stack of these running L_TRIGGER activators for multiple marked objectives in a single stage. Really do appreciate the help.

Auto State Wating
	Event OnTriggerEnter(ObjectReference akActionRef)
		Debug.Trace( Self  + " firing on " + akActionRef )
		If ( akActionRef == Game.GetPlayer())  && pSKK_MQ.IsRunning() 
			GotoState("Finished")
			Disable()
			Float fCount = pSKK_MQCounterHostile.GetValue()
			fCount += 1		
			pSKK_MQCounterHostile.SetValue(fCount)
			Debug.Notification( "You have cleared " + ( fCount as Int) + " of the hostile locations." )
			Debug.Trace( Self + " set SKK_MQCounterHostile to "  + fCount )
		EndIf
		If ( pSKK_MQ.GetStage() == 40 ) && ( pSKK_MQCounterHostile.GetValue() >= 6 )
			pSKK_MQ.SetStage(50) 
		EndIf
	EndEvent
EndState

State Finished 
	;void
EndState
Link to comment
Share on other sites

Looks good. One more thing I'd like to add. It would be good practice to replace your Debug.Notification with a Message.Show. If you ever planned to release this to Xbox they don't have debug functions at all. Also for final release you'd want to either comment out Debug lines or compile the scripts with the release flag so it strips them out. Having the vm run Debug functions puts a tangible hit on performance not just for your scripts, but all running scripts since they all share the same allotment for time to run per frame.

To do the message stuff.

  • In CK create a new message.
  • Uncheck it as a messagebox type.
  • In the title box put your one liner message "You have cleared %.0f of the hostile locations."
  • Then in your code define a property for the message.
  • Use the messageProperty.Show(fCount) instead of the Debug.Notification.
Link to comment
Share on other sites

With the basic mechanics running, optimisations to follow including replacing Game.GetPlayer() and such. Right now most of my time is spent working around rubbish documentation by looking at debug output. A lot of debug output.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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