Jump to content

My Papyrus script is reading out a rule func0, please help


RowanSkie

Recommended Posts

So I have a small problem in my script. Essentially what it does is check for a food item if it has a certain keyword plus another misc item and then it gives output, but when I compile it through CK, I get a rule func0. Here's my script.

ScriptName rep_Rationkey Extends Quest

MiscObject Property rep_tinkey Auto
Keyword Property rep_canration Auto
ActorValue property HealthAV

Event OnItemEquipped(Form akBaseObject, ObjectReference akReference)
  if akBaseObject as Potion
      if(akBaseObject.HasKeyword(rep_canration) && Game.GetPlayer().GetItemCount(rep_tinkey) == 1)
        Game.GetPlayer().RemoveItem(rep_tinkey)
        Debug.Notification("Your tin key broke! You cannot open another canned ration without hurting yourself.")
      ElseIf(akBaseObject.HasKeyword(rep_canration) && Game.GetPlayer().GetItemCount(rep_tinkey) == 0)
        Game.GetPlayer().DamageValue(HealthAV, 10)
        Debug.Notification("Ouch. You should try to find a tin key to not hurt yourself.")
      Else
      endif
  else
  endif
EndEvent

Edited by RowanSkie
Link to comment
Share on other sites

if akBaseObject as Potion > if (akBaseObject IS Potion)

 

Also to allow for unbounded item counts you may want:

 

GetItemCount(rep_tinkey) == 1) > GetItemCount(rep_tinkey) > 0)

 

Lastly consider using OnEquipped and attach the script to the rep_canration object form rather than actor/OnItemEquipped/quest combo as it saves the hassle of quest aliases or remote event registrations.

Link to comment
Share on other sites

if akBaseObject as Potion > if (akBaseObject IS Potion)

 

Also to allow for unbounded item counts you may want:

 

GetItemCount(rep_tinkey) == 1) > GetItemCount(rep_tinkey) > 0)

 

Lastly consider using OnEquipped and attach the script to the rep_canration object form rather than actor/OnItemEquipped/quest combo as it saves the hassle of quest aliases or remote event registrations.

the rep_canration is a keyword, will it still work?

Link to comment
Share on other sites

You cannot attach a script to a Keyword but the advice of SKK50 is otherwise solid.

 

I looked at what your script does and rewrote it how I would have. There are some optimizations, and in my opinion, more readable code.

ScriptName rep_Rationkey Extends Quest

Actor Player

Group Properties
	MiscObject Property rep_tinkey Auto Const Mandatory
	Keyword Property rep_canration Auto Const Mandatory
	ActorValue property HealthAV Auto Const Mandatory
EndGroup

Event OnQuestInit()
	Player = Game.GetPlayer()
	RegisterForRemoteEvent(Player, "OnItemEquipped")
EndEvent

Event Actor.OnItemEquipped(Actor sender, Form baseObject, ObjectReference reference)
	If (baseObject is Potion)
		If (baseObject.HasKeyword(rep_canration))
			int count = Player.GetItemCount(rep_tinkey)
			If (count == 1)
				Player.RemoveItem(rep_tinkey)
				Debug.Notification("Your tin key broke! You cannot open another canned ration without hurting yourself.")
			ElseIf (count == 0)
				Player.DamageValue(HealthAV, 10)
				Debug.Notification("Ouch. You should try to find a tin key to not hurt yourself.")
			Else
				Debug.TraceSelf(self, "Actor.OnItemEquipped", "The equipped item count of "+count+" is unhandled.")
			EndIf
		Else
			Debug.TraceSelf(self, "Actor.OnItemEquipped", "The equipped item does not have the `rep_canration` keyword.")
		EndIf
	Else
		Debug.TraceSelf(self, "Actor.OnItemEquipped", "The equipped item is NOT of the Potion type.")
	EndIf
EndEvent
Edit: Remote events are not a hassle. Well, I was not hassled by the extra line of code in this sample.
Link to comment
Share on other sites

If multiple potions have the rep_canration keyword then add the script to each of the base forms.

 

Then you dont even need that keyword, as the script will only ever fire on those objects anyway.

ScriptName rep_Rationkey Extends ObjectReference

MiscObject Property rep_tinkey Auto Const Mandatory
ActorValue property HealthAV Auto Const Mandatory

Event OnEquipped(Actor akActor)

if (akActor.GetItemCount(rep_tinkey) == 1 )
        akActor.RemoveItem(rep_tinkey)
        Debug.Notification("Your tin key broke! You cannot open another canned ration without hurting yourself.")
ElseIf (akActor.GetItemCount(rep_tinkey) == 0)
       akActor.DamageValue(HealthAV, 10)
        Debug.Notification("Ouch. You should try to find a tin key to not hurt yourself.")
Endif
EndEvent
Link to comment
Share on other sites

You cannot attach a script to a Keyword but the advice of SKK50 is otherwise solid.

 

I looked at what your script does and rewrote it how I would have. There are some optimizations, and in my opinion, more readable code.

ScriptName rep_Rationkey Extends Quest

Actor Player

Group Properties
	MiscObject Property rep_tinkey Auto Const Mandatory
	Keyword Property rep_canration Auto Const Mandatory
	ActorValue property HealthAV Auto Const Mandatory
EndGroup

Event OnQuestInit()
	Player = Game.GetPlayer()
	RegisterForRemoteEvent(Player, "OnItemEquipped")
EndEvent

Event Actor.OnItemEquipped(Actor sender, Form baseObject, ObjectReference reference)
	If (baseObject is Potion)
		If (baseObject.HasKeyword(rep_canration))
			int count = Player.GetItemCount(rep_tinkey)
			If (count == 1)
				Player.RemoveItem(rep_tinkey)
				Debug.Notification("Your tin key broke! You cannot open another canned ration without hurting yourself.")
			ElseIf (count == 0)
				Player.DamageValue(HealthAV, 10)
				Debug.Notification("Ouch. You should try to find a tin key to not hurt yourself.")
			Else
				Debug.TraceSelf(self, "Actor.OnItemEquipped", "The equipped item count of "+count+" is unhandled.")
			EndIf
		Else
			Debug.TraceSelf(self, "Actor.OnItemEquipped", "The equipped item does not have the `rep_canration` keyword.")
		EndIf
	Else
		Debug.TraceSelf(self, "Actor.OnItemEquipped", "The equipped item is NOT of the Potion type.")
	EndIf
EndEvent
Edit: Remote events are not a hassle. Well, I was not hassled by the extra line of code in this sample.

 

 

 

If multiple potions have the rep_canration keyword then add the script to each of the base forms.

 

Then you dont even need that keyword, as the script will only ever fire on those objects anyway.

ScriptName rep_Rationkey Extends ObjectReference

MiscObject Property rep_tinkey Auto Const Mandatory
ActorValue property HealthAV Auto Const Mandatory

Event OnItemEquipped(Form akBaseObject, ObjectReference akReference)

if Game.GetPlayer().GetItemCount(rep_tinkey) == 1 )
        Game.GetPlayer().RemoveItem(rep_tinkey)
        Debug.Notification("Your tin key broke! You cannot open another canned ration without hurting yourself.")
ElseIf Game.GetPlayer().GetItemCount(rep_tinkey) == 0)
        Game.GetPlayer().DamageValue(HealthAV, 10)
        Debug.Notification("Ouch. You should try to find a tin key to not hurt yourself.")
Endif
EndEvent

Okay, I can see the difference in the code, and the simplification of it. Which is more optimized anyway? I can at least trash my newer (and actually working) version of code which removed the HealthAV property by using GetHealthAV() instead... what's generally faster?

 

Here's my new code anyway, I'm gonna go and optimize it based on Scrivener's after this.

 

 

ScriptName rep_Rationkey Extends Actor

MiscObject Property rep_tinkey Auto
Keyword Property rep_canration Auto

Event OnItemEquipped(Form akBaseObject, ObjectReference akReference)
  if akBaseObject is Potion
      if(akBaseObject.HasKeyword(rep_canration) && Game.GetPlayer().GetItemCount(rep_tinkey) > 0)
        Game.GetPlayer().RemoveItem(rep_tinkey)
        Debug.Notification("C-Ration opened with key.")
      ElseIf(akBaseObject.HasKeyword(rep_canration) && Game.GetPlayer().GetItemCount(rep_tinkey) == 0)
        Game.GetPlayer().DamageValue(Game.GetHealthAV(), 10)
        Debug.Notification("C-Ration opened without key.")
      Else
      endif
  else
  endif
EndEvent

 

 

Edited by RowanSkie
Link to comment
Share on other sites

Oh yea, resist the urge to use ANY of the `Debug` functions in your final work. This was acceptable in Skyrim but is no longer the case for Fallout 4. Instead of using `Debug.Notification()` use a proper `Message` form in the CK.

You can have Debug functions in your code. Thats totally fine. Just make sure the functionality of your mod does not depend on these debug functions.

 

For the "best" solution, Im not familiar enough with your end goals to say.

Link to comment
Share on other sites

From a good design perspective you want to use methods that generate the minimum of events (without hacking base game assets).

 

If you attach a script to an actor it will fire every time the actor equips something, even if that something is not your thing.

 

If you attach a script to a new object you create, the script will only fire for that object.

 

For one mod no, it doesn't matter, but in a large load order its death by a thousand little event cuts.

 

Learn more on the Script Lag Detector page.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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