Jump to content

Papyrus syntax/general help


kuzi127

Recommended Posts

So I'm testing a proof-of-concept mod and I'm making a custom function in a script that checks how many of a loose mod are in all of the workshops linked to the one the player is using, and stores it in a global in a quest script. I'd like some help with the syntax and how to use an event from a different class. I only started learning papyrus in the last few days, but I am somewhat familiar with other languages and scripting in general. A lot of the function was lifted from the vanilla workshop scripts and modified for what I need.

 

Attached to the weapons benches:

 

 

Scriptname WorkbenchScriptTEST extends ObjectReference

WorkshopParentScript Property WorkshopParent Auto Const mandatory
{ parent quest - holds most general workshop properties }

TEST_ModCountManagerScript Property Auto Const mandatory
{ manager quest - holds globals for condition checks }

;internal function for counting how many of a mod the player has available
function CountMods(ObjectReference Bench, Form MiscMod, GlobalVariable CountGlob)
;set up count variable
int modcount = 0
;get linked container
ObjectReference linkedContainer = Bench.GetLinkedRef(WorkshopParent.WorkshopLinkContainer)
if linkedContainer
modcount = modcount + linkedContainer.GetIemCount(MiscMod)
endif
; get all linked containers (children)
ObjectReference[] linkedContainers = Bench.GetLinkedRefChildren(WorkshopParent.WorkshopLinkContainer)
int i = 0
while i < linkedContainers.Length
linkedContainer = linkedContainers
if linkedContainer
modcount = modcount + linkedContainer.GetIemCount(MiscMod)
endif
i += 1
endWhile
;set global to final count
TEST_ModCountManagerScript.CountGlob = modcount
endFunction

Event OnActivate(ObjectReference akActionRef)
;;debug.trace(self + "OnActivate")
if akActionRef == Game.GetPlayer()
CountMods(self, TEST_miscmod_mod_General_Scope_SightReflex, TEST_ReflexSightCount)
endif
endEvent

;Event OnPlayerModArmorWeapon(Form akBaseObject, ObjectMod akModBaseObject)
; ;same stuff as activate event
;endEvent

 

 

Can I set a globalvar property of another script using a function input like that? Do I have to initialize the loose mod as a property? Also, I'd like to run the count whenever the player mods an item, but that event is from the actor class so i don't think it'll work directly like that. What would be a good way to do this? Feel free to point out any other errors too.

Link to comment
Share on other sites

Some suggestions in no particular order;

 

 

You must define the properties for *everything|* in the script so it knows what database objects it is supposed to be using and link them:

Keyword Property WorkshopItemKeyword Auto Const Mandatory
Keyword Property WorkshopCaravanKeyword Auto Const Mandatory
ObjectMod Property TEST_miscmod_mod_General_Scope_SightReflex Auto Const Mandatory
GlobalVariable Property TEST_ReflexSightCount Auto Const Mandatory

To do what you want first get the local workshop reference:

ObjectReference ThisWorkshop = Self.GetLinkedRef(WorkshopItemKeyword)

You don't need the local linked workbenches as containers as they share the local workshop container.

Int iCount = ThisWorkshop.GetItemCount(TEST_miscmod_mod_General_Scope_SightReflex)

Now get the stupid supply line linked workshops (stupid because Global Workshop storage is an actual thing these days) look for this line in WorkshopParentScript:

Location[] linkedLocations = workshopRef.myLocation.GetAllLinkedLocations(WorkshopCaravanKeyword) 

and copy the While loop logic underneath it to count the OMODS in each of them:

Location[] linkedLocations = ThisWorkshop.GetCurrentLocation().GetAllLinkedLocations(WorkshopCaravanKeyword) 
While ...
iCount += ThisWorkshop.GetItemCount(TEST_miscmod_mod_General_Scope_SightReflex)
... Endwhile
TEST_ReflexSightCount.SetValue(iCount)

Rather than mess about attaching scripts to actual workbenches, create a start game enabled quest and attach a script to that which is event driven;

Event OnQuestInit() 
   RegisterForRemoteEvent(Game.GetPlayer(), "OnPlayerUseWorkBench")
EndEvent 

Event Actor.OnPlayerUseWorkBench(Actor akSender, ObjectReference akWorkBench)
   ;stick your omod counting function in here 
EndEvent 

Once you have all that working for one simple static OMOD/GlobalVariable pair, then add the ability to define multiple OMODs and associated Global.

Link to comment
Share on other sites

Ah ok, I was looking at the workshop scripts and thought the children function was getting all of the linked workshops; didn't know that was handled by the caravan keyword. I already have a start game quest with a script to handle globals so I can just use that, that useworkbench event is useful. I think the main thing that's confusing me is that from reading the papyrus articles on the ck wiki, I think you can only use functions that belong to some script above in the "extends" tree. Is that true? Or can I use functions that belong to global scripts in objectreference scripts, etc. like that setvalue after the while loop? Should I separate the counting function (which would extend objectreference) and the quest script, and then can I use that function in the quest script just by calling it like any other function or do I have to define it as global or something? Thanks for the tips btw, just that stuff was a huge help.

Edited by kuzi127
Link to comment
Share on other sites

(1) Start simple and just have a single quest attached script with a bunch of functions and events in it to get going. Starting with scripts spread about attached to different things and calling each other is a long hard way. Start simple unless you actually enjoy pain and frustration.

 

(2) You can use any function *IN* any script (just about). I think what you are referring to is calling a function *ON* the wrong object. Trying to call the Weapon form function .GetAmmo() on an ObjectReference, even if it is a gun wont work. But understanding the entity hierarchy will allow you to cast to the right object/form level:

 

Script mYScript extends Quest

(ObjectReference ThisGun).GetAmmo() = fail

(ObjectReference ThisGun as Weapon).GetAmmo() = success

 

Edit: I have a lot of super complex scripts that I open up after a year or so to extend or maintain, so being totally explicit about each object and explicitly casting each call really helps rather than trying to be relaxed with short form notation and relying on the script compiler:

 

Quest WorkshopParent.QuestFunction()

(WorkshopParent as WorkshopParentScript).WorkshopParentScriptFunction()

 

ObjectReference ThisWorkshop.ObjectReferenceFunction()

(ThisWorkshop as WorkshopScript).WorkshopScriptFunction()

 

ObjectReference ThisActor.ObjectReferenceFunction()

(ThisActor as Actor).ActorFunction() ;the ObjectReference/Actor mix often gets confusing as the compiler knows an OR is an Actor so will accept an actor function call on an ObjectReference that is an actor. Confused ? Just cast explicitly.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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