FiftyTifty Posted April 3, 2018 Share Posted April 3, 2018 I'm trying to make a script that, when the insert key is pressed, will freeze all the player owned items nearby, so they cannot be moved around. I got the base idea down: Make array of all item types (weapon, clothing, aid, misc, ammo, books, ingredients) Iterate through each array Call SetRigidBodyMass 100 on each ref in each array But, unfortunately, the documentation on how to actually use events to handle hotkeys is lacking: https://geckwiki.com/index.php/SetOnKeyDownEventHandler Judging by that wee article, I need to have two scripts. One that does all the actual work, and a quest script that starts the event handler for the hotkey. But that's not working: The current script to be called: SetOnKeyDownEventHandler AAAFyTyHotkeyFreezeItemsScript 1 210 scn AAAFyTyHotkeyFreezeItemsScript int iKeyID array_var array_MiscRefsInCell array_var array_BookRefsInCell array_var array_ClothingRefsInCell array_var array_IngredientRefsInCell array_var array_WeaponRefsInCell array_var array_AmmoRefsInCell array_var array_AlchemyRefsInCell array_var array_Refs begin function {iKeyID} let array_BookRefsInCell := GetRefs 25 1 let array_ClothingRefsInCell := GetRefs 27 1 let array_IngredientRefsInCell := GetRefs 29 1 let array_MiscRefsInCell := GetRefs 31 1 let array_WeaponRefsInCell := GetRefs 40 1 let array_AmmoRefsInCell := GetRefs 41 1 let array_AlchemyRefsInCell := GetRefs 47 1 end function The script attached to the quest: scn AAAFyTyHotkeyFreezeItemsHotkeyEventScript SetOnKeyDownEventHandler AAAFyTyHotkeyFreezeItemsScript 1 210 The error: "All script commands must be inside a begin/end block." So where do I go from here? Link to comment Share on other sites More sharing options...
FiftyTifty Posted April 3, 2018 Author Share Posted April 3, 2018 I figured out how the event handler should look: scn AAAFyTyHotkeyFreezeItemsHotkeyEventScript short bDone begin GameMode if bDone == 0 SetOnKeyDownEventHandler AAAFyTyHotkeyFreezeItemsScript 1 210 set bDone to 1 StopQuest AAAFyTyHotkeyFreezeItemsQuest endif end So that's well and good, it compiles fine, though I don't know if stopping the quest will also disable the event handler. The next hurdle, is figuring out how to get each ref from the arrays. Link to comment Share on other sites More sharing options...
FiftyTifty Posted April 4, 2018 Author Share Posted April 4, 2018 (edited) Doesn't seem to do anything. Damn. So I have three scripts in total. The first, is the quest script: scn AAAFyTyHotkeyFreezeItemsHotkeyEventScript short bDone begin GameMode if bDone == 0 SetOnKeyDownEventHandler AAAFyTyHotkeyFreezeItemsScript 1 210 set bDone to 1 ;StopQuest AAAFyTyHotkeyFreezeItemsQuest endif end Here is the script being referenced by the event handler: scn AAAFyTyHotkeyFreezeItemsScript int iKeyID array_var array_MiscRefsInCell array_var array_BookRefsInCell array_var array_ClothingRefsInCell array_var array_IngredientRefsInCell array_var array_WeaponRefsInCell array_var array_AmmoRefsInCell array_var array_AlchemyRefsInCell array_var array_Refs ref refItem begin function {iKeyID} let array_BookRefsInCell := GetRefs 25 1 let array_ClothingRefsInCell := GetRefs 27 1 let array_IngredientRefsInCell := GetRefs 29 1 let array_MiscRefsInCell := GetRefs 31 1 let array_WeaponRefsInCell := GetRefs 40 1 let array_AmmoRefsInCell := GetRefs 41 1 let array_AlchemyRefsInCell := GetRefs 47 1 foreach array_Refs <- array_BookRefsInCell let refItem := array_BookRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_ClothingRefsInCell let refItem := array_ClothingRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_IngredientRefsInCell let refItem := array_IngredientRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_MiscRefsInCell let refItem := array_MiscRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_WeaponRefsInCell let refItem := array_WeaponRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_AmmoRefsInCell let refItem := array_AmmoRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_AlchemyRefsInCell let refItem := array_AlchemyRefsInCell["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop end function And here's the wee script function that is repeatedly called: scn AAAFyTyFreezeIfPlayerOwner ref refItem Begin function {refItem} if refItem.GetOwner == Player refItem.SetRigidBodyMass 100 endif return End So it should work; it all compiles fine. The only way I could see the cause of this not working, is that I need to get the actual player actor reference, whereas the Player variable may only reference the player base record? Edit: Changing the player check to if RefItem.IsOwner doesn't remedy the issue. So it's something else that is causing the script to not run on any of the references, if there are any in the arrays. 2nd Edit: I was improperly cycling through the arrays, so now I know that they have references in them. Here is the updated script: scn AAAFyTyHotkeyFreezeItemsScript int iKeyID array_var array_MiscRefsInCell array_var array_BookRefsInCell array_var array_ClothingRefsInCell array_var array_IngredientRefsInCell array_var array_WeaponRefsInCell array_var array_AmmoRefsInCell array_var array_AlchemyRefsInCell array_var array_Refs ref refItem begin function {iKeyID} let array_BookRefsInCell := GetRefs 25, 1 let array_ClothingRefsInCell := GetRefs 26, 1 let array_IngredientRefsInCell := GetRefs 29, 1 let array_MiscRefsInCell := GetRefs 31, 1 let array_WeaponRefsInCell := GetRefs 40, 1 let array_AmmoRefsInCell := GetRefs 41, 1 let array_AlchemyRefsInCell := GetRefs 47, 1 Ar_Dump array_BookRefsInCell Ar_Dump array_ClothingRefsInCell Ar_Dump array_IngredientRefsInCell Ar_Dump array_MiscRefsInCell Ar_Dump array_WeaponRefsInCell Ar_Dump array_AmmoRefsInCell Ar_Dump array_AlchemyRefsInCell foreach array_Refs <- array_BookRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_ClothingRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_IngredientRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_MiscRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_WeaponRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_AmmoRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop foreach array_Refs <- array_AlchemyRefsInCell let refItem := array_Refs["value"] call AAAFyTyFreezeIfPlayerOwner refItem loop end function So the arrays are being filled properly. That's good. But the references are not being affected by the rigid body mass function, which is bad. Edited April 4, 2018 by FiftyTifty Link to comment Share on other sites More sharing options...
FiftyTifty Posted April 4, 2018 Author Share Posted April 4, 2018 (edited) Attached a Print "Called SetRigidBodyMass" to my UDF, and it does not get called. So I'm getting closer; for some reason, my if check isn't evaluating to true when it should be. Edit: Right, managed to get it to be called with some clever thinking. Every item dropped by the player has a formID beginning with FF. If I just check for the items with an ID more than FF000000, we're golden. scn AAAFyTyFreezeIfPlayerOwner ref refItem string_var strFormID int iRefFormID int iFFToInt Begin function {refItem} let iFFToInt := 4278190080 let strFormID := GetFormIDString refItem let iRefFormID := ToNumber strFormID, 1 if iRefFormID > iFFToInt refItem.SetRigidBodyMass 100 Print "Called SetRigidBodyMass" endif return End But now there's a new issue. Despite calling SetRigidBodyMass on the items, it doesn't have any effect for some reason. Edit2: I added another Print function to check the FormID of refItem , just to make sure the items are being passed along to the script. They print as expected, so that's not the issue. Edited April 4, 2018 by FiftyTifty Link to comment Share on other sites More sharing options...
dubiousintent Posted April 6, 2018 Share Posted April 6, 2018 Following this with interest. Unfortunately don't have any experience to assist. Just don't want you to think you are talking to yourself in an empty room. Have you seen CIPCIS article "Detecting Keypresses"? An "EventHandler" is triggered in response to some action. You started out looking for a "hotkey" and what I don't see is any code to detect that in "scn AAAFyTyHotkeyFreezeItemsHotkeyEventScript" or elsewhere. -Dubious- Link to comment Share on other sites More sharing options...
FiftyTifty Posted April 6, 2018 Author Share Posted April 6, 2018 Following this with interest. Unfortunately don't have any experience to assist. Just don't want you to think you are talking to yourself in an empty room. Have you seen CIPCIS article "Detecting Keypresses"? An "EventHandler" is triggered in response to some action. You started out looking for a "hotkey" and what I don't see is any code to detect that in "scn AAAFyTyHotkeyFreezeItemsHotkeyEventScript" or elsewhere. -Dubious- I actually managed to get the hotkey working. And CIPCIS' method is not ideal, as it uses GameMode for the bulk of the scripting. The point of having event handlers, is to only process code when we need to, rather than every frame or every few seconds. To get it to work, you make two scripts. One is the script you attach to the quest that has a very barebones GameMode block, which then readies the event handler. You then point it to the second script you made, which is the one that does all the work. If you look at the script I have attached to the quest, it calls the following line: SetOnKeyDownEventHandler AAAFyTyHotkeyFreezeItemsScript 1 210 AAAFyTyHotkeyFreezeItemsScript is the name of the script I made that does the bulk of the processing. The 1 means we want to enable the event handler, and 210 is the key code for the insert key. Link to comment Share on other sites More sharing options...
dubiousintent Posted April 6, 2018 Share Posted April 6, 2018 Ah! Thanks for the explanation. Added 'Tip: EventHandler-HotKey' to "Scripting" section of the wiki "Getting started creating mods using GECK" article based on it. -Dubious- Link to comment Share on other sites More sharing options...
Mktavish Posted April 7, 2018 Share Posted April 7, 2018 Honestly I would just use a "Begin OnActivate" to do your freezing / unfreezing. Placed on an activator in the cell (switch / button ?) And I'm assuming all the items would have been grabbed , then moved , then released ... prior to wanting to freeze them ? So you could have another activator , that starts a gamemode block ... that will start assigning items upon release , to then be frozen by the OnActivate script ??? IDK ... just my thoughts for something more simple since arrays are a mystery to me. More simple as in clunky I guess :confused: Link to comment Share on other sites More sharing options...
FiftyTifty Posted April 7, 2018 Author Share Posted April 7, 2018 Honestly I would just use a "Begin OnActivate" to do your freezing / unfreezing. Placed on an activator in the cell (switch / button ?) And I'm assuming all the items would have been grabbed , then moved , then released ... prior to wanting to freeze them ? So you could have another activator , that starts a gamemode block ... that will start assigning items upon release , to then be frozen by the OnActivate script ??? IDK ... just my thoughts for something more simple since arrays are a mystery to me. More simple as in clunky I guess :confused: I'd rather not have to use an object in lieu of the hotkey. Good news is that the hotkey works, it's just I can't get a function to run on the objects inside the arrays, which I'd have to do in the same way even if I did use an activator. Got to be able to get the items somehow. Also, I've made a whole bunch of hoarding dens, and I'd really rather not have to grab and re-place everything again. Link to comment Share on other sites More sharing options...
Mktavish Posted April 7, 2018 Share Posted April 7, 2018 The "OnActivate" is superior to the "OnFunction" because the interface does not have to second guess accidental key press. Or style of pressing the key ... Literally the distance between top and bottom key press. Takes exponential AI guess work ... vs "Begin OnActivate" Plus you can give the player a perk that will give secondary "E" key choices upon mouse over per item. Which executes a second choice "Begin OnActivate" Link to comment Share on other sites More sharing options...
Recommended Posts