+1
Completed - Resolved

MightyScript: Pick From List

journeywithin 1 year ago • updated by Cian Noonan (Graphics Plumber) 3 months ago 8

testing_20180508190032.meta
testing_20180508190032

output_log.txt

I have been trying to get the action "Pick From List" to work, and after multiple tests with different types of lists, I can't figure it out.  When looking at the debug vars, the output lists are either filled with negative numbers or never populated with the input data.


For example, 3 world object lists:  List1 has 3 tiles preselected ("tile1","tile2","tile3"), List2 has 3 different tiles preselected ("tile4","tile5","tile6"), List3 has nothing in it.  Run a looping script that increases the index and "picks" from List1 (input list) and "adds" to List2 (output list).  Also another pick action that uses List1 (input list) and "adds" to List3 (output list).  Neither List2 or List3 will change.


However, if you use a string list as the output, then it sort've works... the string list gets values added to it, but the values don't seem to represent anything.  ie.  Same List data as above, but now you also have List4 which is a string list with values ("String1","String2").  When you run the script picking from List1 and add/output to List4, you get something like this (in the debug var console): (String1,String2,-2147481376,-2147481434,-2147481539).


See attached test map / log.  Click the door next to the dungeon heart (with brimstone blocks near it; "door5" in the scripts).  Look at the vars for string 36 (string list with -numbers) or test string (string list with -numbers) and compare to pick test (world object list which didn't get "added" too like the string list).


Also, what started this entire thing was my interest with string lists (since each string within a stringlist is labeled as "List 1", "List 2", etc) as I wanted to see if I could create a multidimensional list/array by putting the list IDs in a string list and using pick from list to select the world object lists by their list id and adding them into a temp array/list.


ie. String List = "10, 11, 12"; World Object Lists have the IDs 10, 11, 12 and each list contains some tiles in them.  Thus I could 'pick from list' on the string list with index=0 which returns "10" and gets "list where id=10", store/set that in a temp (empty) list and loop through the temp list and perform actions on each cell.




Game Version:
Steam Public
Platform:
Windows

The numbers are object IDs, I think all that you're missing here is that Pick From List takes a number as it's parameter and that number relates to where in the list it is. So using #1 would pick the object that was first in the list, #2 would be the second object in the list, etc.


I'll save you some more time by saying that Multi-Dimensonal lists won't work here (I already tried that kind of stuff). I'd be interested to know what your use case for it was though?

Note: long post.  I sort of got carried away while describing my thoughts.  Feel free to ignore, lol.


Brief edit: idea was to have 1 list with triggering blocks and n+ lists that correspond to each triggering block, then some scripts to loop through and find/set the correct list associated with a triggering block.  Instead of creating many "cloned" scripts that look for exactly 1 triggering block and contain the corresponding list within that script.


As you said, 2D arrays aren't possible in MS - unless they allow you to retrieve list content by list id or allow lists to contain other lists.  :(



Multidimensional array example:


40 different tiles that trigger when entered and reveal a small area nearby.  You can create 40 different scripts to accomplish this (1 for each trigger block), or 1 multidimensional array and a few scripts to loop it.


List1: contains trigger tile locations


List2,3,4,5+: contains reveal tile locations


The index of List1 relates to which ListX to use.  Ie. List1[n] and List(n+1) are related.  So if index=10, List1[10] contains a trigger block, and List11 contains the reveal tiles for that block.  A 2D array would be a lot easier: List[index][0] = trigger block; List[index][1] = reveal blocks.


In a typical OOP language, you could easily do this without arrays and just create an object to hold this data.  (Ie. Object[index].trigger and Object[index].reveal)  However MightyScript doesn't allow you to create objects, so you need to use lists/arrays.  However MightyScript doesn't allow you search a list/array for a value and get the index of that value, and you can only set the index and use it with the pick action to get list content.  (Note: you can look if a block exists in a List, but you can't get the index of that block in the list)  SO... the solution becomes...


Number Index = 0
Number Count = List1 length
String List0 = contains IDs for each reveal list
World Object List1 = as above; trigger tiles
World Object List2,3,4,5+ = as above; reveal tiles
World Object TempList1 = used as a variable to be used between multiple scripts
World Object TempList2 = used as a variable to be used between multiple scripts
Timer Loop = trigger 40, automatically loop, 0seconds


Ie.
List1 has ID=10 and looks like {block1,block2,block3,...}
List2,3,4 have ID=20,21,22 respectively and contain the reveal blocks for block1/2/3 respectively
List0 has ID=1 and contains the IDs for List2,3,4; it looks like {20,21,21}
Count = 3


The index value of List0 and List1 are related.  List1[index] = trigger block; List0[index] = list id containing reveal blocks, it might look something like GetListFromId(List0[index]) in code.


We have some scripts:


1. Trigger Script: trigger when one of the blocks in List1 is entered; store/set/output the triggering block to TempList1 (set, not add), set Index=0, set Count=List1.length, manual trigger 10


2. Loop Script 1 ("search array and get index"): trigger on 10; "number" condition to check if index < count; use pick action (index,input=List1,output=TempList2,set); manual trigger 20


3. Loop Script 2 (if then): trigger on 20; "exists in list" condition to check if TempList1 exists TempList2 (ie. triggering block = list1[index] block); if success, manual trigger 30


4. Loop Script 2b (else): trigger on 20; same "exists in list" condition as above but inverted; if "fails" (inverted success), index+1, manual trigger 10


5. Reveal Script: trigger on 30; pick action (index,input=List0,output=TempList1,set),  index=0, count=TempList1.length, start loop timer   (this script won't work unless you can get the list from ID in list0; just an example or whatever)


6. Reveal Loop Script 1 (index < count): trigger on 40; "Number" condition to check if index < count; pick action (index,input=TempList1,output=TempList2), reveal action(center block = TempList2, range=0, reveal=true), index+1


7. Reveal Loop Script 2 (index >= count): trigger on 40; "Number" condition to check if index >= count; stop timer



What happens:

1. When a block is entered, its world object is stored in TempList1 and triggers Loop Script 1
2. When Loop Script 1&2 are triggered, it checks if List1[index]==TempList1, if true, TempList1=ListWithID(List0[index]) (the current index is the ListID that contains the reveal blocks) and then triggers the reveal loop; if false, it increases the index by 1 and checks the next value;  the loop exists when index>count (nothing found)
3. When Reveal Loop Script 1&2 are triggered, it sets index=0 and count=length of reveal array, then loops through each block (since the reveal action only works on the first value in an array)



How it looks like in another language:


Object block1 = triggering block object;
for (i=0; i < list1.length; i++){
   Object block2 = list1[i];
   if (block1==block2){
      Object reveal_array = GetListFromId(list0[i]);  // ie. List with ID=20,21,22
      for (j=0; j < reveal_array.length; j++){
         RevealFunction(reveal_array[j]);
      }
   }
}

While that may seem like a lot of code/annoyance for such a simple task... it is much easier to manage than creating a script for each "trigger block" as managing scripts in MightyScript is a pain, while managing individual lists is much easier.



TL;DR: Looping through 2D arrays in MightyScript is not currently possible since you can't get a list by ID.

I don't think you'd need 40 scripts to do what you're trying to do. I think you could just have a single trigger to detect when any of the tiles is stepped in, and then use triggering entity as the target of the reveal area. That way when a unit steps into one of the areas, that specific area would be triggered and then the triggering unit itself would act as a centre point to reveal the area (although i'd suggest casting Prophecy in that area instead if you want the reveal to be temporary)

Completed - Next Patch

PickList was indeed borked for World object lists, this will be fixed next patch = )