RowanSkie Posted November 16, 2019 Share Posted November 16, 2019 (edited) 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 November 16, 2019 by RowanSkie Link to comment Share on other sites More sharing options...
SKKmods Posted November 16, 2019 Share Posted November 16, 2019 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 More sharing options...
RowanSkie Posted November 16, 2019 Author Share Posted November 16, 2019 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 More sharing options...
scrivener07 Posted November 16, 2019 Share Posted November 16, 2019 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 More sharing options...
SKKmods Posted November 16, 2019 Share Posted November 16, 2019 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 More sharing options...
scrivener07 Posted November 16, 2019 Share Posted November 16, 2019 SKK50 presents a good solution as well! Link to comment Share on other sites More sharing options...
RowanSkie Posted November 16, 2019 Author Share Posted November 16, 2019 (edited) 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 November 16, 2019 by RowanSkie Link to comment Share on other sites More sharing options...
scrivener07 Posted November 16, 2019 Share Posted November 16, 2019 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 More sharing options...
SKKmods Posted November 16, 2019 Share Posted November 16, 2019 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 More sharing options...
scrivener07 Posted November 16, 2019 Share Posted November 16, 2019 I can agree with that concerning script lag! Link to comment Share on other sites More sharing options...
Recommended Posts