Shockyyy Posted April 15, 2021 Share Posted April 15, 2021 (edited) So I am a beginner in coding things, but I spent a whole day writing this script and trying to get it to work, it works in some way, but not fully. The main idea for the script is kind of simple: When I press a specific key on my keyboard it must spawn the creature, which i binded for this key. Also I wrote in the beginning that game will show a message when I load a save or start a new game. I compiled the script, it said that everything compiled succesfully and without any troubles. Then I opened the Creation Kit and selected Skyrim.esm and Update.esm as a master files and added a new quest, and in the quest properties I added my script and just saved it. Everything seemed fine, but the thing is that it shows the message when i load save or start a new game, but it doesn't spawn any creatures that i binded. I just don't know what I should do, but I have a feeling that I did something wrong in creation kit. Please help me, I just want to get this thing to work. (I attached the script file and also wrote it in this spoiler) ScriptName SkyrimShockyMod extends Quest ; This Player reference is set as a property for this quest in Creation Kit Actor Property PlayerRef Auto FormList Property EnemyRacesList Auto FormList Property WeaponsList Auto float lastWeaponChangeTime = 0.0 Event OnInit() Debug.MessageBox("Less gooo") RegisterForSingleUpdate(5) ; Keycodes: https://www.creationkit.com/index.php?title=Input_Script#DXScanCodes RegisterForKey(21) ;Y RegisterForKey(79) ;Numpad1 RegisterForKey(80) ;Numpad2 RegisterForKey(81) ;Numpad3 RegisterForKey(75) ;Numpad4 RegisterForKey(76) ;Numpad5 RegisterForKey(77) ;Numpad6 RegisterForKey(71) ;Numpad7 RegisterForKey(72) ;Numpad8 RegisterForKey(73) ;Numpad9 EndEvent Event OnUpdate() ; ; SET PLAYER TO RANDOM SIZE ; float randomScale = getRandomScale() ; PlayerRef.SetScale(randomScale) ; ; SET RANDOM SPEED ; float randomSpeed = utility.randomFloat(100, 3000) ; PlayerRef.SetActorValue("SpeedMult", randomSpeed) ; ; Temporarily modify the carryweight so that the Speed change immediately takes place ; PlayerRef.ModActorValue("CarryWeight",0.1) ; PlayerRef.ModActorValue("CarryWeight",-0.1) ; ; SPAWN HORKER ; PlayerRef.PlaceAtMe(Game.GetForm(0x00023ab1)) ; ; SPAWN RABBIT ; PlayerRef.PlaceAtMe(Game.GetForm(0x0006DC9D)) ; ; SPAWN BEAR ; PlayerRef.PlaceAtMe(Game.GetForm(0x00023A8A)) ; ; SPAWN CHEESE WHEEL spawnItemsAtPlayer(Game.GetForm(0x00064B33), 10) ; ; Alt Version: ; spawnInFrontOfPlayer(Game.GetForm(0x00064B33), 15, 150, 50, 20) ; ; SPAWN CHICKEN ; PlayerRef.PlaceAtMe(Game.GetForm(0x000A91A0)) ; ; SPAWN RANDOM UNIT ; spawnRandomUnit() RegisterForSingleUpdate(1) EndEvent Function RegisterForKey(int keyCode) native Event OnKeyDown (int keyCode) if (KeyCode == 21) ;Y ; SPAWN MAMMOTHS PlayerRef.PlaceAtMe(Game.GetForm(0x0001CA03), 10) elseif (KeyCode == 79) ;Numpad1 ; SPAWN CHEESE spawnItemsAtPlayer(Game.GetForm(0x00064B33), 10) elseif (KeyCode == 80) ;Numpad2 ; SPAWN DRAGON PlayerRef.PlaceAtMe(Game.GetForm(0x0001CA03), 10) elseif (KeyCode == 81) ;Numpad3 ; SPAWN BEAR PlayerRef.PlaceAtMe(Game.GetForm(0x00023A8A), 10) elseif (KeyCode == 75) ;Numpad4 ; SPAWN GIANT PlayerRef.PlaceAtMe(Game.GetForm(0x00023AAE), 10) elseif (KeyCode == 76) ;Numpad5 ; SPAWN MUDCRAB PlayerRef.PlaceAtMe(Game.GetForm(0x000E4011), 10) elseif (KeyCode == 77) ;Numpad6 ; SPAWN WOLF PlayerRef.PlaceAtMe(Game.GetForm(0x00023ABE), 10) elseif (KeyCode == 71) ;Numpad7 ; SPAWN NAZEEM PlayerRef.PlaceAtMe(Game.GetForm(0x00013BBF), 10) elseif (KeyCode == 72) ;Numpad8 ; SPAWN BANDIT PlayerRef.PlaceAtMe(Game.GetForm(0x000D80B4), 10) elseif (KeyCode == 73) ;Numpad9 ; SPAWN TROLL PlayerRef.PlaceAtMe(Game.GetForm(0x00023ABA), 10) endif EndEvent float Function getRandomScale() global ; first, 50/50 chance of making him bigger or smaller ; Then, get random value within bigger/smaller's respective range if (Utility.RandomInt(0,1)) ; Make it smaller return Utility.RandomFloat(0.1, 1.0) else ; Make it bigger return Utility.RandomFloat(1.0, 10.0) endif endFunction Function spawnItemsAtPlayer(Form itemForm, int spawnCount = 1) while (spawnCount > 0) PlayerRef.AddItem(itemForm, 1, true) PlayerRef.DropObject(itemForm, 1) spawnCount -= 1 endWhile EndFunction Function spawnInFrontOfPlayer(Form formToPlace, int spawnCount = 1, \ float distanceOffset = 250.0, float heightOffset = 25.0, float angleOffset = 0.0 ) ; Spawn a disabled cheese wheel, move it in front of player, spawn Form(s) at that location, then delete ; horizontalOffset is how far from player it spawns, verticalOffset is how high, angle is the offset from player's current ObjectReference invisibleSpawner = PlayerRef.PlaceAtMe(Game.GetForm(0x00064B33), 1, true, true) float playerAngleZ = PlayerRef.GetAngleZ() float angZ = playerAngleZ + angleOffset float posX = PlayerRef.GetPositionX() + distanceOffset * Math.Sin(angZ) float posY = PlayerRef.GetPositionY() + distanceOffset * Math.Cos(angZ) float posZ = PlayerRef.GetPositionZ() + heightOffset invisibleSpawner.SetPosition(posX, posY, posZ) invisibleSpawner.PlaceAtMe(formToPlace, spawnCount, True, False) invisibleSpawner.Delete() EndFunction FUNCTION spawnRandomUnit() ; This occurs OnUpdate so changes can be made after plugin is first loaded. Trading optimization for flexability. ; Create the array of IDs. Array size cannot be a variable, since it must be defined at compile time. int[] randomUnitIDs = new int[38] ; Manually populace the array (no better solution found for now) randomUnitIDs[0] = ID_CHICKEN randomUnitIDs[1] = ID_DOG randomUnitIDs[2] = ID_COW randomUnitIDs[3] = ID_GOAT randomUnitIDs[4] = ID_HORSE randomUnitIDs[5] = ID_RABBIT randomUnitIDs[6] = ID_MUDCRAB_SMALL randomUnitIDs[7] = ID_MUDCRAB_MED randomUnitIDs[8] = ID_MUDCRAB_LARGE randomUnitIDs[9] = ID_HORKER randomUnitIDs[10] = ID_BEAR randomUnitIDs[11] = ID_CHAURUS randomUnitIDs[12] = ID_SNOWBEAR randomUnitIDs[13] = ID_WOLF randomUnitIDs[14] = ID_ICEWOLF randomUnitIDs[15] = ID_SABRECAT randomUnitIDs[16] = ID_SNOWYSABRECAT randomUnitIDs[17] = ID_SKEEVER randomUnitIDs[18] = ID_ICEWRAITH randomUnitIDs[19] = ID_WEREWOLF randomUnitIDs[20] = ID_TROLL randomUnitIDs[21] = ID_FROSTTROLL randomUnitIDs[22] = ID_MAMMOTH randomUnitIDs[23] = ID_DRAGON randomUnitIDs[24] = ID_DRAUGR randomUnitIDs[25] = ID_RESTLESSDRAUGR randomUnitIDs[26] = ID_DRAUGROVERLORD randomUnitIDs[27] = ID_DWARVENSPHERE randomUnitIDs[28] = ID_FROSTBITESPIDER randomUnitIDs[29] = ID_GIANT randomUnitIDs[30] = ID_HAGRAVEN randomUnitIDs[31] = ID_SHADE randomUnitIDs[32] = ID_SKELETON randomUnitIDs[33] = ID_SKELETONARCHER randomUnitIDs[34] = ID_SKELETONMAGE randomUnitIDs[35] = ID_SPRIGGAN randomUnitIDs[36] = ID_WISP randomUnitIDs[37] = ID_NAZEEM int randomIndex = utility.randomInt(0, randomUnitIDs.Length - 1) int randomUnitID = randomUnitIDs[randomIndex] ObjectReference newUnit = PlayerRef.PlaceAtMe(Game.GetForm(randomUnitID)) ; newUnit.SetScale(getRandomScale()) endFUNCTION ; UPDATE THE "randomUnitIDs" ARRAY INIT SIZE WHEN ADDING/REMOVING UNITS int ID_CHICKEN = 0x000A91A0 int ID_DOG = 0x00023A92 int ID_COW = 0x00023A90 int ID_GOAT = 0x0002EBE2 int ID_HORSE = 0x0010982B int ID_RABBIT = 0x0006DC9D int ID_MUDCRAB_SMALL = 0x000E4010 int ID_MUDCRAB_MED = 0x000E4011 int ID_MUDCRAB_LARGE = 0X00021875 int ID_HORKER = 0x00021ab1 int ID_BEAR = 0x00023A8A int ID_CHAURUS = 0x000D0872 int ID_SNOWBEAR = 0x00023A8C int ID_WOLF = 0x00023ABE int ID_ICEWOLF = 0x00023ABF int ID_SABRECAT = 0x00023AB5 int ID_SNOWYSABRECAT = 0x00023AB6 int ID_SKEEVER = 0x00023AB7 int ID_ICEWRAITH = 0x00023AB3 int ID_WEREWOLF = 0x00023ABC int ID_TROLL = 0x00023ABA int ID_FROSTTROLL = 0x00023ABB int ID_MAMMOTH = 0x00023AB4 int ID_DRAGON = 0x000F80FA int ID_DRAUGR = 0x000387C0 int ID_RESTLESSDRAUGR = 0x0001FE86 int ID_DRAUGROVERLORD = 0x0001BCD6 int ID_DWARVENSPHERE = 0x000EEC5E int ID_FROSTBITESPIDER = 0x0004203F int ID_GIANT = 0x00023AAE int ID_HAGRAVEN = 0x00023AB0 int ID_SHADE = 0x0009CB63 int ID_SKELETON = 0x0002D1DE int ID_SKELETONARCHER = 0x0002D1FC int ID_SKELETONMAGE = 0x0009362B int ID_SPRIGGAN = 0x00023AB9 int ID_WISP = 0x00002C3C7 int ID_NAZEEM = 0x00013BBF Edited April 15, 2021 by Shockyyy Link to comment Share on other sites More sharing options...
dylbill Posted April 15, 2021 Share Posted April 15, 2021 For the OnKeyDown instead of using Game.GetForm I would just use the properties directly, same for the spawnRandomUnit function. For this you can use a formlist filled with actor bases, that way you can keep it dynamic. For actors, use PlaceActorAtMe(ActorBase) instead of PlaceAtMe: Formlist Property MyActorBases Auto FUNCTION spawnRandomUnit() int randomIndex = utility.randomInt(0, MyActorBases.GetSize() - 1) ObjectReference newUnit = PlayerRef.PlaceActorAtMe(MyActorBases.GetAt(randomIndex) as ActorBase) ; newUnit.SetScale(getRandomScale()) endFUNCTION Also, make sure your properties are filled. In the CK, click on your script, click on the Properties button and click Auto Fill All. If they are named the same in the script as in the CK they will automatically set. Otherwise you can set them manually by clicking on the property and then Edit Value. Link to comment Share on other sites More sharing options...
Shockyyy Posted April 15, 2021 Author Share Posted April 15, 2021 (edited) I did the Auto Fill thing and it worked! (Thank you) But not at all, it turned on this line to spawn cheese every second: ; ; SPAWN CHEESE WHEEL spawnItemsAtPlayer(Game.GetForm(0x00064B33), 10) But the binds for spawning still didn't work. Also I didn't fully understand you with this replacing Game.GetForm thing. What should I do with it? And about that spawnRandomUnit, I don't really use it, I just need the spawn thing to work. Edited April 15, 2021 by Shockyyy Link to comment Share on other sites More sharing options...
dylbill Posted April 15, 2021 Share Posted April 15, 2021 So to do properties directly you would do something like this. Again for actors use PlaceActorAtMe. Since that function doesn't have an amount, it only places 1 actor, you could set up another function to place multiple actors: Actorbase Property EncMammothWild Auto Event OnKeyDown (int keyCode) if (KeyCode == 21) ;Y ; SPAWN MAMMOTHS PlaceMultipleActorAtMe(PlayerRef, EncMammothWild, 10) ;place 10 mamoths at player. Endif EndEvent Function PlaceMultipleActorAtMe(ObjectReference Ref, Actorbase akActorBase, Int Amount) While Amount > 0 Ref.PlaceActorAtMe(akActorBase) Amount -= 1 EndWhile EndFunctionYou could also use a formlist. Drag and drop the actors or items you want to spawn into a new formlist (found in the miscellaneous section of the CK). Then do something like this: Formlist Property MyItems Auto Event OnKeyDown (int keyCode) if (KeyCode == 21) ;Y ; SPAWN MAMMOTHS PlaceMultipleAtMe(PlayerRef, MyItems.GetAt(0), 10) ;Place 10 items at the player that's index 0 of the formlist elseif (KeyCode == 79) ;Numpad1 ; SPAWN CHEESE PlaceMultipleAtMe(PlayerRef, MyItems.GetAt(1), 10) ;Place 10 items at the player that's index 1 of the formlist Endif EndEvent Function PlaceMultipleAtMe(ObjectReference Ref, Form Item, Int Amount) If Item As ActorBase ;is the item an actor? Actorbase akActorBase = Item as ActorBase While Amount > 0 Ref.PlaceActorAtMe(akActorBase) Amount -= 1 ;subract 1 from amount. While loop will repeat until amount is 0. EndWhile Else Ref.PlaceAtMe(Item, Amount) Endif EndFunctionI changed the function so that it will detect actor bases automatically. Link to comment Share on other sites More sharing options...
Shadeybladey Posted April 16, 2021 Share Posted April 16, 2021 ...I spent a whole day writing this script and trying to get it to work, it works in some way, but not fully. It's a long time since I wrote scripts, but one thing I do know is that you MUST test the script on a saved game file that has never seen your mod. Trying to fix a script and re-testing on a save that has the old version baked in won't work. I learned this at a great cost of time and frustration and several clumps of hair! :smile: Link to comment Share on other sites More sharing options...
Shockyyy Posted April 16, 2021 Author Share Posted April 16, 2021 you MUST test the script on a saved game file that has never seen your mod. I am always starting a new game when I want to test it Link to comment Share on other sites More sharing options...
IsharaMeradin Posted April 17, 2021 Share Posted April 17, 2021 I know why your script was spawning cheese every second. In the OnInit event you register for an update after 5 seconds. In the OnUpdate event you've commented out every line but spawning the cheese and re-registering for an update after 1 second. So... every second it will spawn cheese. If it is still on your script, remove the following line as it is overriding the SKSE variant. Function RegisterForKey(int keyCode) native With that line in your script, you'll never get your keys properly registered. Link to comment Share on other sites More sharing options...
Shockyyy Posted April 17, 2021 Author Share Posted April 17, 2021 I know why your script was spawning cheese every second. And I know it too. It is just another function that I decided to do and it works perfectly.About Function RegisterForKey: If I delete that line then the script will not compile. It says that RegisterForKey is not a function or does not exist. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted April 17, 2021 Share Posted April 17, 2021 Make sure you have properly installed SKSE's PSC files. Otherwise, the compiler will tell you that that function does not exist because it cannot find it on the script where it is supposed to be. Link to comment Share on other sites More sharing options...
Shockyyy Posted April 17, 2021 Author Share Posted April 17, 2021 Skse installed, all of the .pex files are in the Data/Scipts and all of the .psc files are in the Data/Scripts/Source Link to comment Share on other sites More sharing options...
Recommended Posts