GSGlobe Posted December 14, 2017 Share Posted December 14, 2017 (edited) Hi,Im trying to learn how to utilize arrays, been following a youtube scripting tutorial and reading up on Arrays here:https://www.creationkit.com/index.php?title=Arrays_(Papyrus)But to be frank, I dont understand much of it. I cant make any sense of it, Im guessing Im just dumb and have a hard time learning and understanding, where can I read up more on the matter, perhaps with some examples explaining each thing.Just Reading about it is quite hard I think I need something practical to really make use or understand it myself.The reason why I want to now is because to lessen the amount of properties on My script and make it more effective.Ill try to explain in shorts what Im trying to do.I have 5 spells and each of these 5 spells have 5 additional effects.Put simple, one spell might do 20 damage, one upgrade will bump this damage by another 20.To unlock a spells upgrade, you must kill 5x NPCYou can only upgrade one spell at a time and you can only cast one spell at a time.So, to put blunt. How can I learn to do the above?I was hoping to keep as much as possible on a quest and leave the If/ElseIf out of the magiceffect But I really have no clue how to Go about this without a lot of integers and a long list of If/ElseIf.Would someone be so kind to help me out? I really want to learn this stuff so I can make more efficient scripts and also expand my knowledge.Thanks for reading :smile:Best regards! Edit: I have done 25 spells and each spell have 5 upgrades But I figured if and When I know the above, I could just expand the whole system. Following the same principer Im guessing?So a way to track which spell is active, the active spell is the one that increments by +1 each time 5 NPC's are killed.(OnDying event) and when casting the spell it would call the active spell and the a index? Between 0-4 If the spell have been upgraded. Edited December 14, 2017 by GSGlobe Link to comment Share on other sites More sharing options...
JonathanOstrus Posted December 15, 2017 Share Posted December 15, 2017 (edited) I'm not really sure what to say. I'm not entirely sure using an array would help for your scenario. Though multiple arrays possibly. One thing to keep in mind is array sizes cannot be larger than 128 entities. An array is basically just a list of a specific type of object. So something like Spell[] mySpellArray is a list of spells, ObjectReference[] myObjectArray would be a list of object references. They will be in order starting with an index of 0 so for the first item in the list you would use mySpellArray[0] and then the second item mySpellArray[1] and so forth. If you're familiar with using FormLists it's basically the same thing except you don't have to cast it after using a GetAt() call. You do need to initialize the array even if it's going to be zero entities, unless it pre-defined in CK (which it sounds like you would be doing). For your use case I'm not sure how arrays would work for you. You could make separate lists of like each spell set. So let us say one is a fireball, then each upgrade is just a more potent one. You could have the myFireballArray[] which has the 6 spells in it (If I read that correctly as a base spell + 5 upgrades). Then you just need to determine the level of upgrade for the fireball and pick the right entry from the array. That could be done using a local variable or a global property depending on how the script is going to be used. When upgraded you just change that variable and then the next time you do your if tree it picks the new spell index. This would reduce your property requirements to 25 (one for each spell set) instead of 25*6 (5+1 base?) and then the accompanying property/variable for holding the upgrade level. This could reduce your if/else tree to a much smaller set by extension depending how you had it written/envisioned. You would do an if check to decide on which base spell to look at, then grab the variable specifying upgrade level, then pull the array index according to that upgrade, finally return or do something with the desired upgrade level spell. I'm not sure I understand what you mean by track the active spell. If you mean get the currently equipped one you can use GetEquippedSpell() https://www.creationkit.com/index.php?title=GetEquippedSpell_-_Actor Edit: One thing I should point out that a lot of people forget about. Once a script is loaded and the game saved, all the properties and variables for that script are then baked in the save. If you were to update the esp and add additional entries to an array, they won't show up until the script is terminated and reinitialized. If this is on a quest, that means the quest is stopped and then restarted. If it's on an object, then the object needs to be deleted and re-instantiated. A hacky way around that is to use an update quest which then runs and modifies the properties of another quest script. This can prove problematic if there are multiple upgrades and a user were to skip a version. Then you'd have 2 or more update quests fire at the same time and have a race as to who pushes the update first. One exception is that *new* properties or variables will get assigned their default values upon loading a save where the script is already instantiated. So as long as you're not trying to modify a property that has already been defined and baked, you'd be ok. Edited December 15, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
GSGlobe Posted December 15, 2017 Author Share Posted December 15, 2017 Guess I left out a few bits. The casting of the spell will be through an animation event, by swinging your weapon or on bowshot, depending on which direction youre moving. So left would be BaseSpell 1, right BaseSpell 2 and so on. The above is already done. By tracking I mean (which of the BaseSpell will have its spell upgrade int incremented when int KillCount reaches 5) So depending on which enchantment BaseSpell you set. The BaseSpell itselfs check for an integer on a script to add additional effects so its not really a "second upgraded spell of the first" (Could this part above also move into a quest?) So Im guessing; 1 array each for the basespells 1 int per BaseSpell or Should this be an Array? Then;If KillCount == 5 && SpellToTrack == 1BaseSpell01Upgrade +=1KillCount = 0ElseIf KillCount == 5 && SpellToTrack == 2Etc? Up to 25? Then on the animation event (MGEF) If SpellToTrack == 1 MySpellArray[0].Cast(PlayerRef) ElseIf SpellToTrack == 2Etc ? I dont know how to set it up efficient, I was hoping lesrning arrays or something would help me move the If/ElseIf to the quest to not call for it everything I cast the spell, But would be done beforehand in the quest. I searched for a online tutorial or class But couldnt find anything in My language, was hoping that If learning abit more about more common languages I could apply some of it in Papyrus to get a better understanding. Thanks for the help so far and for going in depth with it! Link to comment Share on other sites More sharing options...
foamyesque Posted December 15, 2017 Share Posted December 15, 2017 Have you considered using one spell with five magic effects, and using condition checks to see which applies? Link to comment Share on other sites More sharing options...
GSGlobe Posted December 15, 2017 Author Share Posted December 15, 2017 I havent really considered it since all the extra effects are scripted on each BaseSpell. I did however do my directional movement spells that way. I wouldnt know how to do it efficiently that way without tearing it down and making new scripts for each conditioned spell. s#*!, I dont understand why Im not getting it, very frustrating to have spent so long, several weeks just to hit a brickwall in the end of it. I didnt really plan for this at the start but it would be better this way If I could just figure out how to set it up :( meh.. Link to comment Share on other sites More sharing options...
DavidJCobb Posted December 16, 2017 Share Posted December 16, 2017 I have 5 spells and each of these 5 spells have 5 additional effects. To unlock a spells upgrade, you must kill 5x NPCYou can only upgrade one spell at a time and you can only cast one spell at a time. By tracking I mean (which of the BaseSpell will have its spell upgrade int incremented when int KillCount reaches 5) So depending on which enchantment BaseSpell you set. The BaseSpell itselfs check for an integer on a script to add additional effects so its not really a "second upgraded spell of the first"So if I'm understanding you right, you only have five Spell forms in the Creation Kit, and you apply the upgrades to these using scripts on their magic effects. If that's the case, then you just need an array of five Spells on your script. But I figured if and When I know the above, I could just expand the whole system. Following the same principer Im guessing?Maybe. Maybe not. The trick with arrays of forms is that you have to set their values in the Creation Kit. When a player installs your mod and starts playing, the values that are in the mod at that time are written into their save file. If you decide to update your mod with more spells, and you put more spells in the array, then that update will work for new users, but old users will still use the old spell list even after they install the updated mod (because the old list is in their save file). For your use case, I would recommend using a FormList of spells instead of a Papyrus array. A FormList is a form that only exists to provide a list of other forms. Like arrays, FormLists are edited in the Creation Kit and can be used with scripts; however, save files handle them differently, so you can actually update them when you update your mod. Link to comment Share on other sites More sharing options...
GSGlobe Posted December 17, 2017 Author Share Posted December 17, 2017 Due to the lack of knowledge on my end, I've decided to use this mod strictly for educational purposes and it will remain forever unreleased and used privately if I ever get it working, when it comes to stuff I don't really grasp I don't feel encourged to release something that's not efficient or well made. I'm really sure using formlist would be any easier for me since the things that troubles me would be the same formlist or not, keeping it to Array right now to perhaps build some knowledge of it. (I'm currently following Arron's Dominon scripting series) to hopefully get some more knowledge. Either way, I'm still hoping I could understand it before then, but unless I see it infront of me it's quite hard to grasp, more. Learn by doing than reading sort of guy? Except, I don't know how to even begin at this stage, haha. I'm screwed? Ok, let's try here. 5 Enchantments, 25 Spells, each spell have a scripted MagicEffect with 5 additional upgrades, these are not spells but rather, each upgrade makes a new effect ontop of the spell, so one enchantment has 5 spells linked to it. 1. When you equip the weapon linked to the enchantment, you'll get a Lesser power. 2. Casting the "Lesser Power" (Out of Combat) will open up a menu, where you get to choose which spell to "Track", 1 out of 5.3. Each time you kill a mob with enchanted weapon, you'll increase +1 in KillCount Linked to Enchantment Function goes to Quest Scriptname EW_Quest_Script extends Quest Int Property KillCount auto Function IncrementCounter() KillCount += 1 If (KillCount) > 5KillCount = 0EndIf EndFunctionScriptname EW_KillCount_Script extends activemagiceffect MagicEffect Property MyEffect AutoEW_Quest_Script Property KillCount Auto Event OnDying(Actor akKiller) If akKiller == Game.GetPlayer() && Game.GetPlayer().HasMagicEffect(MyEffect) KillCount.IncrementCounter() EndIf EndEvent So when KillCount is 51. It should Increment the Tracked Spell Integer +=12. It should reset back to 0 So how do I possible set this up? Have "Int Property SpellToTrack" and set a value of depending on which spell you choose to track, out of 25 spells. so a value between 1-25?and then do something like If SpellToTrack == 1 && KillCount == 5; Use a Integer linked to the corresponding spell, in this case 1st spell to determine upgradeFirstSpell += 1KillCount = 0ElseIf SpellToTrack == 2 && KillCount == 5; Second integer SecondSpell += 1KillCount = 0 So create 25x Int Properties? or use of an Int[] Property UpgradeSpell, using a If/ElseIf long code would that be script heavy considering you could kill a whole bandit camp pretty quick, meaning this IncrementCounter function would be called to often. Ideas? Function IncrementCounter(int[] UpgradeSpell) KillCount += 1 If KillCount == 5UpgradeSpell(index) += 1KillCount = 0EndIf; Then Set Index = 1,2,3,4,5,6,7,8,9,10 etc depending on which spell you track? would something like that work? endfunction Link to comment Share on other sites More sharing options...
DavidJCobb Posted December 18, 2017 Share Posted December 18, 2017 (edited) Given an Int[] Property UpgradeSpell, do: If KillCount == 5 UpgradeSpell[SpellToTrack] += 1 EndIf See, you're allowed to use arrayVariableName[intVariableName] to grab the (intVariableName - 1)-th entry in the array. Edited December 18, 2017 by DavidJCobb Link to comment Share on other sites More sharing options...
GSGlobe Posted December 18, 2017 Author Share Posted December 18, 2017 (edited) I'll try to use the above in the mod, thanks for helping out. Now I'm stuck on another part, abit lost as usual. What I want to accomplish here is;1. Get index out of the array, function doesnt work so I'm not sure whats up with that. It doesnt compile and give loads of error.2. If one of the magiceffect is on the player, register for animation event.3. Add a block to the OnMagicEffectApply and set the magiceffect variable.. Would you mind helping? Scriptname EW_Q_Script extends ReferenceAlias MagicEffect[] property MeArray auto ;array of which magiceffect to look for Actor Player ;the referenced actorMagicEffect Effect ;the MGEF int Function GetIndex(MagicEffect[] TempArray, MagicEffect TempEffect) ;function to get index from MagicEffect[] arrays int index = 0while (index < TempArray.length)if (TempArray[index] == TempEffect)Return index ;the index of the arrayendifindex += 1endwhileReturn -1 ;effect is not in array EndFunction Event OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect) Debug.Trace(akCaster + " applied the " + akEffect + " on us") ; How do ignore this event if MagicEffet is not one we look for? ; How do I check here that one of the magiceffect from MagicEffect[] array is active? ; If (GetIndex(meArray, akEffect) < 0) ; return ; ignore check not Magic effect we care about ;EndIf If !(Effect) ; magiceffect variable hasn't been set If akEffect == Effect ; set variable, is this right?; Do bblabla?; I'm pretty sure the above wont work; Also How do I check when MagicEffect is no longer active? EndEvent Edited December 19, 2017 by GSGlobe Link to comment Share on other sites More sharing options...
IsharaMeradin Posted December 19, 2017 Share Posted December 19, 2017 If you need the index of an entry in an array. Use Find.Example Int idx = MeArray.Find(akEffect) If idx >= 0 && idx < MeArray.Length Debug.Trace("Magic Effect ["+akEffect+"] can be found in the array at index [ "+idx+" ]") EndIfIf you want to know if the subject is no longer under the effect of a magic effect, you can check with HasMagicEffect. But listening for a specific effect to end, you might want to consider using SKSE's SendModEvent in the effect's finish event and register for the mod event to be received on a more permanent script such as a quest or player alias. Link to comment Share on other sites More sharing options...
Recommended Posts