Pellape Posted December 25, 2020 Share Posted December 25, 2020 I am trying arrays in a questscript the first time for my new mark and recall spells and I used arrays before at objects and that works great but I get these errors now when I start my quest The quest script looks like this: scn PekRMNoviceQSTSCR float fQuestDelayTime Float Timer Float xPos Float yPos Float zPos Ref RemoveObjectRef Ref GateBaseRef Ref TempRef string_var SMark01 string_var SMark02 string_var SMark03 string_var SMark04 string_var SMark05 string_var SMark06 string_var SMark07 string_var SMark08 string_var SMark09 string_var TempStr array_var XmarkerArr array_var TriggerArr array_var GateArr array_var GateBaseArr array_var SIArr short DoOnce Short Turn Short Button Short RemoveGate Begin GameMode Set fQuestDelayTime to 1 if ( DoOnce == 0 ) Set SMark01 to SV_Construct "Slot 1" Set SMark02 to SV_Construct "Slot 2" Set SMark03 to SV_Construct "Slot 3" Set SMark04 to SV_Construct "Slot 4" Set SMark05 to SV_Construct "Slot 5" Set SMark06 to SV_Construct "Slot 6" Set SMark07 to SV_Construct "Slot 7" Set SMark08 to SV_Construct "Slot 8" Set SMark09 to SV_Construct "Slot 9" let GateArr := ar_Construct Array Set TempRef to PekRMGateNovice01Ref Let GateArr[1] := TempRef Message "Test 1" Printc "Test 1" Let GateArr[2] := PekRMGateNovice02Ref Let GateArr[3] := PekRMGateNovice03Ref Let GateArr[4] := PekRMGateNovice04Ref Let GateArr[5] := PekRMGateNovice05Ref Let GateArr[6] := PekRMGateNovice06Ref Let GateArr[7] := PekRMGateNovice07Ref Let GateArr[8] := PekRMGateNovice08Ref Let GateArr[9] := PekRMGateNovice09Ref Message "Test 2" Printc "Test 2" let TriggerArr := ar_Construct Array Let TriggerArr[1] := PekRMTriggerNovice01Ref Let TriggerArr[2] := PekRMTriggerNovice02Ref Let TriggerArr[3] := PekRMTriggerNovice03Ref Let TriggerArr[4] := PekRMTriggerNovice04Ref Let TriggerArr[5] := PekRMTriggerNovice05Ref Let TriggerArr[6] := PekRMTriggerNovice06Ref Let TriggerArr[7] := PekRMTriggerNovice07Ref Let TriggerArr[8] := PekRMTriggerNovice08Ref Let TriggerArr[9] := PekRMTriggerNovice09Ref Message "Test 3" Printc "Test 3" let XmarkerArr := ar_Construct Array Let XmarkerArr[1] := PekRMXmarkerNovice01Ref Let XmarkerArr[2] := PekRMXmarkerNovice02Ref Let XmarkerArr[3] := PekRMXmarkerNovice03Ref Let XmarkerArr[4] := PekRMXmarkerNovice04Ref Let XmarkerArr[5] := PekRMXmarkerNovice05Ref Let XmarkerArr[6] := PekRMXmarkerNovice06Ref Let XmarkerArr[7] := PekRMXmarkerNovice07Ref Let XmarkerArr[8] := PekRMXmarkerNovice08Ref Let XmarkerArr[9] := PekRMXmarkerNovice09Ref Message "Test 4" Printc "Test 4" let GateBaseArr := ar_Construct Array Let GateBaseArr[1] := PekXmarkerBaseN01Ref Let GateBaseArr[2] := PekXmarkerBaseN02Ref Let GateBaseArr[3] := PekXmarkerBaseN03Ref Let GateBaseArr[4] := PekXmarkerBaseN04Ref Let GateBaseArr[5] := PekXmarkerBaseN05Ref Let GateBaseArr[6] := PekXmarkerBaseN06Ref Let GateBaseArr[7] := PekXmarkerBaseN07Ref Let GateBaseArr[8] := PekXmarkerBaseN08Ref Let GateBaseArr[9] := PekXmarkerBaseN09Ref Message "Test 5" Printc "Test 5" let SIArr := ar_Construct Array Set Turn to 1 While ( Turn < 10 ) Set DoOnce to 666 Let SIArr[Turn] := DoOnce Set Turn to Turn + 1 Loop Message "Test 6" Printc "Test 6" Set DoOnce to -1 StopQuest PekRMNoviceQST endif Set TempStr to SV_Construct "Gate to %z", SMark01 PekRMGateNovice01Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark02 PekRMGateNovice02Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark03 PekRMGateNovice03Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark04 PekRMGateNovice04Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark05 PekRMGateNovice05Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark06 PekRMGateNovice06Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark07 PekRMGateNovice07Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark08 PekRMGateNovice08Ref.SetName TempStr Set TempStr to SV_Construct "Gate to %z", SMark09 PekRMGateNovice09Ref.SetName TempStr If ( RemoveGate == 1 ) If ( Timer < 15 ) Set Timer to Timer + GetSecondspassed Else Let RemoveObjectRef := GateArr[Button] Let GateBaseRef := GateBaseArr[Button] RemoveObjectRef.MoveTo GateBaseRef Let RemoveObjectRef := TriggerArr[Button] RemoveObjectRef.MoveTo GateBaseRef Set RemoveGate to 0 EndIf EndIf End Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted December 26, 2020 Share Posted December 26, 2020 Hmm, the only thing immediately coming to mind is arrays always start at "0" index. Trying to set the "1" index of a newly created array without setting the "0" first can only fail. It's not a StringMap after all, so you can't just start at any point in the index. Link to comment Share on other sites More sharing options...
Pellape Posted December 26, 2020 Author Share Posted December 26, 2020 Yes, you might be right about that for sure as I also asked in Reddit, and I got the same answer as someone did test to use arrays in a 2 questscripts and it failed when he started at 1 but worked if he started with 0. I will add garage to position 0 and see if it works. He wants me to use map if I want to use arrays in that way, starting at 1 but I want to use a simple array... ;) Here is what he wrote: What can I say. When I do scn arraytestquestscript array_var testarray short i begin gamemode let testarray := ar_construct array set i to 1 while ( i < 10 ) let testarray[i] := 1 set i to i + 1 loop printc "yo" end it fails, but when I do scn arraytestquestscript array_var testarray short i begin gamemode let testarray := ar_construct array set i to 0 while ( i < 10 ) let testarray[i] := 1 set i to i + 1 loop printc "yo" end it works. If you need the behavior of a map, you need to initialize it as such. Link to comment Share on other sites More sharing options...
Pellape Posted December 26, 2020 Author Share Posted December 26, 2020 It works perfect now. Thanks for the help Drake :) //Pekka Link to comment Share on other sites More sharing options...
JustChill Posted February 10, 2021 Share Posted February 10, 2021 Hello,I really love working with arrays, as they can hold many information.Went even that far that I save an array into the savegame as it contains info that is required to be retrieved even after loading a game.Even though it's recommended to normally use Let <yourArray> := Ar_Nullto erase an array and avoid savegame bloating. I would not recommend to use arrays without emptying them except if you want to save the data for later use similar as I did in my dynamic barter system.Normally Oblivion has fixed barter gold.While there are mods like "Living Economy" or "Enhanced Economy", I still don't get how they manage to dynamically change the merchants barter gold.I mean it's easy with "SetBarterGold", but that doesn't dynamically change the Menu String, which holds the current barter gold value.I've did it with "SetMenuStringValue".Oblivion only raises the Mercantile skill only per transaction not per sold item for each transaction.My old mentor AltDunmer made an initial fix for this, but PushTheWinButton perfected the solution by using a different OBSE function to raise the skill.Which did not require any of the ugly workarounds my old mentor used.Quest script to ensure that selling multiple items will be awarded with the proper skill value: scn NOAmercantileLevelingFunction float fquestdelaytime short sNOAoldGold short sNOAconvCheck short sNOALastTransactionCount short sNOASSetOnceSell short sNOASSetOnceBuy array_var arNOATransactionInfo ref rNOAsendMerchant ref rNOAcompMerchant short sNOAsendMerchGold short sNOAsendTransGold array_var arNOAMerchantRef array_var arNOAMerchGold array_var arNOAResetTime int i int iMerchantSaved Begin GameMode if sNOAconvCheck == 2 Let sNOAconvCheck := 1 ;=> Run block once again at next conversation elseif sNOAconvCheck == 0 Let fquestdelaytime := 0.1 ;=> Quick processing is necessary for accuracy. Let sNOAconvCheck := 2 endif End Begin MenuMode If (Menumode 1009 && sNOAconvCheck == 1) DisableControl 4 ;=> To ensure the loop is done before the player leaves the dialogue menu. Let i := 0 if eval(Ar_Size arNOAMerchantRef) > 0 ;=> Buying or selling something to a merchant will Let rNOAsendMerchant := GetFirstRef 35 ;=> start this block. While (rNOAsendMerchant) if rNOAsendMerchant.GetCurrentAIPackage == 6 Break ;=> Only one NPC can talk with the player in dialogue endif Let rNOAsendMerchant := GetNextRef Loop if rNOAsendMerchant.GetOffersServicesNow ;=> Is it a merchant? While eval(Ar_Size arNOAMerchantRef) > i Let rNOAcompMerchant := arNOAMerchantRef[i] if rNOAcompMerchant == rNOAsendMerchant Let iMerchantSaved := 1 ;=> We already have that merchant, so not saving it once more. if eval(arNOAResetTime[i]) <= GameDaysPassed ;=> Evaluate merchant's 'money reset Let sNOAoldGold := arNOAMerchGold[i] Let arNOAResetTime[i] := GameDaysPassed + 3 if rNOAsendMerchant.GetBarterGold < sNOAoldGold rNOAsendMerchant.SetBarterGold sNOAoldGold endif endif endif Let i += 1 Loop if iMerchantSaved Let iMerchantSaved := 0 else Ar_Append arNOAMerchantRef rNOAsendMerchant Let sNOAoldGold := rNOAsendMerchant.GetBarterGold Ar_Append arNOAMerchGold sNOAoldGold Let sNOAoldGold := GameDaysPassed + 3 Ar_Append arNOAResetTime sNOAoldGold endif endif endif Let sNOAconvCheck := 2 ;=> This will only be run once. Let sNOAoldGold := player.getgold EnableControl 4 ;=> Reference evaluation is over. elseif (MenuMode 1008 && sNOAconvCheck == 2) ;=> Only start the block in container menu if IsBarterMenuActive ;=> Only proceed if the container is a barter menu If (player.GetGold != sNOAoldGold) && Player.GetBaseAV Mercantile < 100 Let sNOALastTransactionCount := GetLastTransactionQuantity if sNOALastTransactionCount == 0 Return ;=> Failsafe endif if GetContainerMenuView if sNOASSetOnceSell else if NOAinitQuest.sNOAmercantileBuySkill ;=> If buying inceases the skill too, SetSkillUseIncrement 0.2 Mercantile 0 ;=> the incrementation will be reduced. else SetSkillUseIncrement 0.4 Mercantile 0 ;=> Default incrementation. endif Let sNOASSetOnceSell := 1 Let sNOASSetOnceBuy := 0 endif ;=> We got already awarded with an increase if sNOALastTransactionCount > 1 ;=> Only if we sold more than one item. Let sNOALastTransactionCount -= 1 ;=> as of the actual transaction. So one less. While sNOALastTransactionCount > 0 ;=> Now we increment the skill one per one. IncrementPlayerSkillUse Mercantile 0 1 if Player.GetBaseAV Mercantile == 100 Break ;=> Oh, so you reached 100? Fine, then exit the loop NOW! endif Let sNOALastTransactionCount -= 1 ;=> Each incrementation reduces the counter until it reaches Loop ;=> 0 and exits the loop. endif Let arNOATransactionInfo := GetTransactionInfo "sell" Let rNOAsendMerchant := arNOATransactionInfo["buyer"] Let sNOAsendMerchGold := rNOAsendMerchant.GetBarterGold Let sNOAsendTransGold := arNOATransactionInfo["price"] Call NOAdynBarterGoldFunction 1 rNOAsendMerchant sNOAsendMerchGold sNOAsendTransGold elseif GetContainerMenuView == 0 if sNOASSetOnceBuy else SetSkillUseIncrement 0.4 Mercantile 0 Let sNOASSetOnceSell := 0 Let sNOASSetOnceBuy := 1 endif if sNOALastTransactionCount > 0 While sNOALastTransactionCount > 0 IncrementPlayerSkillUse Mercantile 0 1 if Player.GetBaseAV Mercantile == 100 Break endif Let sNOALastTransactionCount -= 1 Loop endif Let arNOATransactionInfo := GetTransactionInfo "buy" Let rNOAsendMerchant := arNOATransactionInfo["seller"] Let sNOAsendMerchGold := rNOAsendMerchant.GetBarterGold Let sNOAsendTransGold := arNOATransactionInfo["price"] Call NOAdynBarterGoldFunction 2 rNOAsendMerchant sNOAsendMerchGold sNOAsendTransGold endif Let arNOATransactionInfo := Ar_Null endif Let sNOAoldGold := player.getgold endif endif End Function script to change the barter gold dynamically: scn NOAdynBarterGoldFunction short sNOABuyOrSell ref rNOAMerchantRef short iNOAMerchantGold short sNOATransactionGold short sNOAworkWith string_var strNOAworkWith Begin Function{sNOABuyOrSell, rNOAMerchantRef, iNOAMerchantGold, sNOATransactionGold} if eval(Ar_Size NOAmercantileLevelingQuest.arNOAMerchantRef) < 0 Let NOAmercantileLevelingQuest.arNOAMerchantRef := ar_Construct Array Let NOAmercantileLevelingQuest.arNOAMerchGold := ar_Construct Array Let NOAmercantileLevelingQuest.arNOAResetTime := ar_Construct Array Ar_Append NOAmercantileLevelingQuest.arNOAMerchantRef rNOAMerchantRef Ar_Append NOAmercantileLevelingQuest.arNOAMerchGold iNOAMerchantGold Let sNOAworkWith := GameDaysPassed + 3 Ar_Append NOAmercantileLevelingQuest.arNOAResetTime sNOAworkWith endif if sNOABuyOrSell == 1 If (rNOAMerchantRef.GetBarterGold - sNOATransactionGold) < 0 rNOAMerchantRef.SetBarterGold 0 else Let sNOAworkWith := rNOAMerchantRef.GetBarterGold - sNOATransactionGold rNOAMerchantRef.SetBarterGold sNOAworkWith endif Let strNOAworkWith := $sNOAworkWith SetMenuStringValue "cont_background\page_layout\cont_contents\cont_npc_money_icon\cont_npc_money_text\string|%z", strNOAworkWith 1008 elseif sNOABuyOrSell == 2 Let sNOAworkWith := rNOAMerchantRef.GetBarterGold + sNOATransactionGold rNOAMerchantRef.SetBarterGold sNOAworkWith Let strNOAworkWith := $sNOAworkWith SetMenuStringValue "cont_background\page_layout\cont_contents\cont_npc_money_icon\cont_npc_money_text\string|%z", strNOAworkWith 1008 endif sv_destruct strNOAworkWith End Furthermore, you can also work with arrays that have an unkown amount of entries. Ar_Append <yourArray> <the entry you want to add>I like to use Ar_Append especially, when the entry should only be added to the array when a specific condition is met. If you want to go through the array with unknown entries you surely have to check your index variable against the entries available: While eval(Ar_Size <yourArray>) > i Let <SomeVariable> := <yourArray>[i] Let i += 1 LoopAlso be aware that "eval" is required to get the actual array size.BUT, it does NOT work in this way: While i < eval(Ar_Size <yourArray>)Don't ask me why, but Eval always had to be aside the If or While to get the condition working properly. XDI learned it the hard way. ^^ Also be sure that "Eval(Ar_Size <yourArray>)" always returns the total amount of entries in your array.Which doesn't go well with the index.As all indexes start at 0, be sure that you never use ">=" in the condition. Lets say you have an array with 4 entries.Index is 0 to 3.Yet "Ar_Size" returns 4. So using While eval(Ar_Size <yourArray>) >= iwill result in "4" being also included for the index evaluation, but as it is an improper index for the array the script runs into an error. Link to comment Share on other sites More sharing options...
Pellape Posted February 11, 2021 Author Share Posted February 11, 2021 (edited) Yes. That is my current problem that I do forget that the indian number 0 actually is something. If we get the size of an array, we must use < or > and never <= I did learn something new when I read how you optimize stuff. In basic and also in C++, we do use i++to increase a number and I did not know about Let i += 1 which is so damn neat and I will use it from now on and I love it as I do hate Set i to i + 1 My arrays will most likely not be so big that they will cause bloats but if that is the case, Screw Oblivion... :wink: *goes and flush the rubbish into the water closet*I am back - What did we debate? Why did they fail to add it here -> Let? But they do write it here where I found it while searching for += ----------------------------------------------------------- I do fail to imagine what use we have of maps? I mean, ordinary arrays are so self explained and useful for databases but when would I ever need an array using maps??? In my mind, an ordinary variable could do the job like a short, float, ref or string?? What have I missed? Maybe I have missed a lot really, most likely... :wink: Edited February 11, 2021 by Pellape Link to comment Share on other sites More sharing options...
JustChill Posted February 12, 2021 Share Posted February 12, 2021 Yeah... Rather use the GECK Wiki, it has similar functions, but far better explanation.https://geckwiki.com/index.php?title=Let Even though thanks to the JIP LN NVSE plugin there are hundred more functions for New Vegas. ^^https://geckwiki.com/index.php?title=Complete_List_of_Function_in_Fallout_New_Vegas Compared to Oblivion:https://cs.elderscrolls.com/index.php?title=List_of_Functions I honestly fear maps.I only used simple arrays so far and neither nested ones. XD It even went that far, that I used 3 simple arrays for values that could be housed otherwise.One array for the merchant referenceOne array for the default barter goldOne array for the reset time of the barter gold They all get populated at the same time, so all of them will ever have the correct info at the very same index for the very same merchant. It might be possible to make one array for the merchant ref and nest another array to that which could hold both values.So the first reference (index 0) needs the first 2 values (index 0, 1).The second (index 1), needs the next 2 values (index 2, 3). But I always fear about index mismatches, so I rather went the simple way. XD Link to comment Share on other sites More sharing options...
QQuix Posted February 12, 2021 Share Posted February 12, 2021 In Oblivion, I have used arrays extensively: hundreds of arrays with thousands of entries each, several levels of nesting, and never, ever have experienced any bugs. If memory serves, most of them were stringmaps, some were maps and a few were simple arrays. Link to comment Share on other sites More sharing options...
JustChill Posted February 12, 2021 Share Posted February 12, 2021 But your scripting comprehension is legendary QQuix. :tongue:The CSE also reminds me about you everytime I use it.There is an uncompiled QQuix script, where you mentioned your idea about Coda for CSE. :wink: I would die for an example from you with nested arrays. :smile: Oh and speaking about "index mismatches". I mean not that the arrays are unstable, I mean that the scripter causes index mismatches as of not thinking about all unhandled exceptions. ^^Guess using nested arrays require a lot accuracy in the script, which is why I would love to see an example from you. Link to comment Share on other sites More sharing options...
Pellape Posted February 13, 2021 Author Share Posted February 13, 2021 We must also take in count the current OBSE bugs that Idle is working with at this very moment. They do not relate with arrays but it was when I tried to add nothing to an array I stumbled on the bugs... Maybe they always where there and maybe they are not an OBSE bug at all... Well idle will find out. Link to comment Share on other sites More sharing options...
Recommended Posts