SandMouseAnarchy Posted May 26, 2019 Share Posted May 26, 2019 Hi guys, im trying to follow the instructions for dynamically attaching scripts to objects here... https://www.creationkit.com/index.php?title=Dynamically_Attaching_Scripts I made the first quest like the site instructs, and put a script on a reference alias pointing to a formlist of trees, that compiles fine but for some reason i dont get the debug when hitting a tree with the woodcutters axe - Scriptname SM_Woodcutter_QST extends ReferenceAlias FormList Property SM_Tree_Cut_List Auto FormList Property SM_Tree_Harvist_List Auto Keyword property Woodcutter_Axe Auto Event OnHit(ObjectReference akTarget, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial) ; If akTarget RegisterForHitEvent(Self) Debug.notification("player hit something") ; Endif if (akAggressor == Game.GetPlayer()) if (akSource.HasKeyword(WoodCutter_Axe) || akSource.HasKeyword(Woodcutter_axe)) Debug.notification("player hit a tre") endif endif EndEvent I figure that i might not be getting the debug becaus the aliases need to be reset or something, so the site says to make a second quest that will periodically reset the aliases... But ive ran into a huge problem...When trying to comiple the second quest that the site instructs me to make i get a compile error saying - (6,1): RegisterForSingleUpdate is not a function or does not exist (21,1): RegisterForSingleUpdate is not a function or does not exist (9,0): new event onupdate cannot be defined because the script is not flagged as native Compilation failed. This is the second quest script im trying to compile, its almost a direct copy paste from the site. Scriptname SM_Woodcutter_Qst_Reset extends Quest Quest Property SM_Woodcutter_Qst Auto Event OnInit() RegisterForSingleUpdate(5) EndEvent Event OnUpdate() SM_Woodcutter_Qst.Stop() int i = 0 while !SM_Woodcutter_Qst.IsStopped() && i < 50 Utility.Wait(0.1) i += 1 endWhile SM_Woodcutter_Qst.Start() RegisterForSingleUpdate(5) EndEvent Does anyone know why RegisterforSingleUpdate is not recognised?Is the second Quest script strictly necissary?and most importantly... how can i get this to work? Link to comment Share on other sites More sharing options...
DieFeM Posted May 26, 2019 Share Posted May 26, 2019 A reference alias stores only one reference, for what you want to do you would need to use a RefCollection Alias. Scriptname SM_Woodcutter_QST extends RefCollectionAlias FormList Property SM_Tree_Cut_List Auto ; you would need to set this list as condition for the collection (IsInList) so it gets filled by objects that match the ones in this list FormList Property SM_Tree_Harvist_List Auto ; and another collection for this type Keyword property Woodcutter_Axe Auto Event OnHit(ObjectReference akSenderRef, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) If akAggressor == Game.GetPlayer() && akSource.HasKeyword(Woodcutter_axe) Debug.notification("Player hit on " + akSenderRef + " with a Weapon, Spell, Explosion, Ingredient, Potion, or Enchantment that has the keyword Woodcutter_axe") Endif EndEvent This other script is unnecessary, because what it does is restart the quest so the reference alias is filled with another object, since the previous script is for a refcollectionalias you don't need to do that, but just in case you want to use a referencealias instead: The OnUpdate event is for Skyrim, in fallout 4 you need to use OnTimer instead: Scriptname SM_Woodcutter_Qst_Reset extends Quest Quest Property SM_Woodcutter_Qst Auto int myTimerId = 33; its just an identificator for the timer, it is optional, just to know what timer has arrived in OnTimer. Event OnQuestInit() StartTimer(5, myTimerId) EndEvent Event OnTimer(int aiTimerID) If myTimerId == aiTimerID SM_Woodcutter_Qst.Stop() Int i = 0 while !SM_Woodcutter_Qst.IsStopped() && i < 50 Utility.Wait(0.1) i += 1 endWhile SM_Woodcutter_Qst.Start() StartTimer(5, myTimerId) EndIf EndEvent Link to comment Share on other sites More sharing options...
SandMouseAnarchy Posted May 27, 2019 Author Share Posted May 27, 2019 Ooooooooohhhh!!!! DieFeM you sir are a genius! Excellent, that had me stumped all day! Thank-you good sir!! Link to comment Share on other sites More sharing options...
SandMouseAnarchy Posted May 27, 2019 Author Share Posted May 27, 2019 (edited) ah damn, im not sure what's going wrong but it still doesnt seem to work :sad: I've put formlists in ReferenceCollectionAlias's for the trees, and attached this script to each CollectionAlias -I've also added the "IsInList" condition for each CollectionAlias - Scriptname SM_Woodcutter_QST extends RefCollectionAlias FormList Property SM_Tree_Multiple_List Auto FormList Property SM_Tree_Big_List Auto FormList Property SM_Tree_Small_List Auto FormList Property SM_Tree_Harvist_List Auto Keyword property Woodcutter_Axe Auto ; Event OnHit(ObjectReference akSenderRef, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) Event OnHit(ObjectReference akTarget, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial) If akAggressor == Game.GetPlayer() && akSource.HasKeyword(Woodcutter_axe) Debug.notification("Player hit tree with axe") ; if SM_Tree_Multiple_List.HasForm(akSenderRef) if SM_Tree_Multiple_List.HasForm(akTarget) Debug.notification("Multiple trees detected") EndIf ; if SM_Tree_Big_List.HasForm(akSenderRef) if SM_Tree_Big_List.HasForm(akTarget) Debug.notification("Big tree detected") EndIf ; if SM_Tree_Small_List.HasForm(akSenderRef) if SM_Tree_Small_List.HasForm(akTarget) Debug.notification("Small tree detected") EndIf Endif EndEvent i had to mark out the lines with "akSenderRef" and replace it with "akTarget" because i was getting this compile error when trying the "akSenderRef" version of the code you wrote for me. (10,0): the parameter types of function onhit in the empty state on script sm_woodcutter_qst do not match the original script scriptobject No output generated for SM_Woodcutter_QST, compilation failed. I have a feeling that it will not work with akTarget, and that akSenderRef is correct, but i cant get the OnHit event to compile with a different paramitor other than "akTarget". i also made that second quest script, even though you say its not necissary, just incase it makes a difference... and it doesnt make any difference, i still cant get the debug from hitting a tree :sad: ((here it is anyway)) Scriptname SM_Woodcutter_Tree_Cut_Qst_Reset extends Quest Quest Property SM_Woodcutter_Tree_Cut_Qst Auto int myTimerId = 33 Event OnQuestInit() StartTimer(5, myTimerId) EndEvent Event OnTimer(int aiTimerID) If myTimerId == aiTimerID SM_Woodcutter_Tree_Cut_Qst.Stop() Int i = 0 while !SM_Woodcutter_Tree_Cut_Qst.IsStopped() && i < 50 Utility.Wait(0.1) i += 1 endWhile SM_Woodcutter_Tree_Cut_Qst.Start() StartTimer(5, myTimerId) EndIf EndEvent ((i changed the quest names so they looked better in the ck, but that is the only change i made)) Try as i might i just cant get this functioning, and i cant get the debug :sad: ---EDIT** i managed to get the "akSenderRef" version of OnHit compiling like this -> Event OnHit(ObjectReference akSenderRef, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial) it seems i needed "string apMaterial" as a parameter, and not necissarily "akTarget"...but ive just tested it in game and i still dont get a debug from hitting a tree.Any idea whats going wrong here? Edited May 27, 2019 by SandMouseAnarchy Link to comment Share on other sites More sharing options...
DieFeM Posted May 27, 2019 Share Posted May 27, 2019 (edited) Well, debug it... First check what references are actually filling the RefCollection alias, you can use a quest script like this: RefCollectionAlias Property MyCollectionOfTrees Auto Event OnQuestInit() Debug.MessageBox("There are " + MyCollectionOfTrees.GetCount() + " trees in the collection")EndEvent Or, in the RefCollection Script, set a shader to the trees in the onload event EffectShader Property MyEffectShader Auto Event OnLoad(ObjectReference akSenderRef) MyEffectShader.Play(akSenderRef)EndEvent You need to make sure that your collection is being filled. Edited May 27, 2019 by DieFeM Link to comment Share on other sites More sharing options...
SandMouseAnarchy Posted May 27, 2019 Author Share Posted May 27, 2019 ah, i really do learn something new everytime you reply DieFeM haha, thankyou again mate!! ok, so, i did as you said, i added the code to a quest, and added a fireFX shader to the alias. it all compiled, and when testing it in game i got a message pop up saying that one single tree is in the collection... i was stood at the redrocket for testing, but i couldnt see a burning tree anywhere. but hey, some limited success, so now i know atleast one tree is in the collection. ill experiment with different shaders to see if i can spot this singular tree in my collection ((the fire fx i used might not be showing for whatever crazy reason)) and see if i can indeed get a hit event from it.but it raises the question - how do i get every tree in the loaded area into my collection? ((every tree in game is already in my formlist for testing)) Link to comment Share on other sites More sharing options...
DieFeM Posted May 27, 2019 Share Posted May 27, 2019 Try changing Max Initial Fill Count to 0. Link to comment Share on other sites More sharing options...
SandMouseAnarchy Posted May 28, 2019 Author Share Posted May 28, 2019 0 you say???? That's interesting! I'll try that first thing tomorrow ^.^ thank-you DieFeM Link to comment Share on other sites More sharing options...
SandMouseAnarchy Posted May 28, 2019 Author Share Posted May 28, 2019 (edited) ah yes, you are a legend DieFeM, i wouldnt have thought to put "0" in the "Max Initial Fill Count"! So, i did that and now i get a message in game saying some 530 trees are now in the collection. Perfect!But, i cant see a fire effect shader on any of them, and i still dont get a debug notification from hitting the tree. very, very odd. Im not sure at all what is stopping the OnHit event from firing, but atleast we know the collection is being filled.Im going to try stripping the script down again and see what happens... Any ideas on where to go next mate? -EDIT**Ive now tried a bunch of different fx shaders for the trees, and none of them are showing on the trees, i have tried walking the whole map hitting every tree on the way - nothing - i even took a stroll off the map, did some saving and loading and fast travelling to different cells, but still nothing. I tried stripping the script down to debug -> FormList Property SM_Tree_Multiple_List Auto Keyword property Woodcutter_Axe Auto EffectShader Property MyEffectShader Auto Event OnLoad(ObjectReference akSenderRef) MyEffectShader.Play(akSenderRef) EndEvent Event OnHit(ObjectReference akSenderRef, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial) Debug.notification(" hit tree ") If akAggressor == Game.GetPlayer() Debug.notification("Player is agressor ") EndIf If akSource.HasKeyword(Woodcutter_axe) Debug.notification("aksource is woodcutter axe ") EndIf if SM_Tree_Multiple_List.HasForm(akSenderRef) Debug.notification("Multiple trees detected") EndIf EndEvent And i still dont get a notification from hitting the trees :sad:i dont get the akAgressor debug, i dont get the axe keyword debug, i dont even get the "hit tree" debug right after the OnHit event... its leading me to believe that the problem is with the OnHit event itself, but im not sure how to debug this script any further? Edit2** Ive also tried -> Event OnHit(ObjectReference akSenderRef, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial) akAggressor = Game.GetPlayer() Debug.notification(" hit tree ") EndEvent But still noting... Edited May 28, 2019 by SandMouseAnarchy Link to comment Share on other sites More sharing options...
DieFeM Posted May 28, 2019 Share Posted May 28, 2019 Well, the collection automatically listens for ObjectReference events and, if the alias is an actor, also for Actor events.But if you look at the documentation you would notice that the OnHit event is an ScriptObject event, so you need to register for it. Function RegisterForHitEvent(ScriptObject akTarget, ScriptObject akAggressorFilter = None, Form akSourceFilter = None, \Form akProjectileFilter = None, int aiPowerFilter = -1, int aiSneakFilter = -1, int aiBashFilter = -1, int aiBlockFilter = -1, \bool abMatch = true) native Looking at the description of the arguments for RegisterForHitEvent you'll see: akTarget: The ObjectReference, ReferenceAlias or RefCollectionAlias that is being hit. So, instead of registering for it in the collection script I would do it in the quest script, using the RefCollectionAlias as akTarget. RefCollectionAlias Property MyCollectionOfTrees1 Auto RefCollectionAlias Property MyCollectionOfTrees2 Auto Keyword property Woodcutter_Axe Auto Event OnQuestInit() Debug.MessageBox("There are " + MyCollectionOfTrees1.GetCount() + " trees in the collection 1") Debug.MessageBox("There are " + MyCollectionOfTrees2.GetCount() + " trees in the collection 2") RegisterForHitEvent(akTarget = MyCollectionOfTrees1, akAggressorFilter = Game.GetPlayer(), akSourceFilter = Woodcutter_Axe) RegisterForHitEvent(akTarget = MyCollectionOfTrees2, akAggressorFilter = Game.GetPlayer(), akSourceFilter = Woodcutter_Axe) EndEvent Event OnHit(ObjectReference akTarget, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial) If MyCollectionOfTrees1.Find(akTarget) > -1 ;Do something for trees in collection 1 EndIf If MyCollectionOfTrees2.Find(akTarget) > -1 ;Do something for trees in collection 2 EndIf EndEvent Link to comment Share on other sites More sharing options...
Recommended Posts