Workshop already have PARTIAL multidimentional arrays support!

Making some tests i discovered that workshop already supports multidimentional arrays :tada:

Since they added new Array value, we can store array inside another array, and get value stored in array using Value In Array action.

Also workshop inspector too display that array is stored inside another array.

Like: Array of <num of elements>

I have an example code that i’ve created to demostrate use of multi dimentional arrays (Import code on live server: 0091K):

variables
{
	global:
		0: array
		1: array_rank
		2: array_index
}

rule("Rule 1")
{
	event
	{
		Ongoing - Global;
	}

	actions
	{
		Global.array = Array(Array(0, 1, 2), Array(3, 4, 5), Array(6, 7, 8));
	}
}

rule("Rule 2")
{
	event
	{
		Ongoing - Global;
	}

	conditions
	{
		Is Button Held(Host Player, Interact) == True;
	}

	actions
	{
		For Global Variable(array_rank, 0, Count Of(Global.array), 1);
			For Global Variable(array_index, 0, Count Of(Global.array[Global.array_rank]), 1);
				Small Message(Host Player, Custom String("[Array] Rank={0}; Index={1}; StoredValue={2}", Global.array_rank, Global.array_index,
					Global.array[Global.array_rank][Global.array_index]));
				Wait(0.016, Ignore Condition);
			End;
			Wait(0.016, Ignore Condition);
		End;
	}
}

Workshop Editor:

Rule 1: https://i.imgur.com/2Hndo9T.png
Rule 2: https://i.imgur.com/1R0oDJq.png

Workshop Inspector:

https://i.imgur.com/AybS06b.png

Video Demonstration

  • UPLOADING
4 Likes

Only 2 dimensions? The real fun begins at 3 dimensions or higher! :joy: (Yes its possible)

No offense, but I think this is known by most already, since the patch has been out for quite a while now (including ptr time).

1 Like

Well you can use multiple times Value In Array action that will be translated to something like [<index>][<index>][<index>] for example.

Yeah i known, but some people still requesting multi dimentional arrays, in forum, i decided to create a topic explaining that.

Unfortunately, there is no easy way to modify a value (or even set) in a multidimensional array. You have to break the array down until you have only one dimension, modify something in it, then rebuild the original array.

2 Likes

i just want cubes mate

Yes but a better way on PC to set value in array you can copy workshop as text and set Global.youarray[index1][index2] = someValue

I think arrays in workshop need to be reworked to a better UI editor and actions/conditions

Wait, does it work? I wonder how the action looks like when I open it in workshop.

Yes this works :smiley:

3 characters required

I have tried it and it didn’t work. I got the error message that there is a variable missing before the second “[…]”.

Ok, i found an problem, we cannot set child array by index, only parent array.

In programming languages we can set array[index1][index2] = somevalue but Set/Modify global/player variable does not work, we can set only first array index. We can set only first array, but not child array.

For example using workshop syntax:

:white_check_mark: Valid: Global.playerBuffs[Slot Of(Host Player)] = True
:x: Invalid: Global.playerBuffs[Slot Of(Host Player)][0] = True (workshop thrown syntax error in chat)
:white_check_mark: Valid: Global.A[0] = Array(value1, value2..., valueN)
:white_check_mark: Valid: Global.A[0] = Array(value1, Array(value1, value2), Array(Array(value1), value2))

So, multidimentional arrays is partial supported. We can set multidimentional arrays only using Global.someArray = Array(value1, value2, value3)

2 Likes

Yea thats what I was saying.

1 Like

I am not really sure why you need 2d arrays when I made it working in one of my game mods (link). There are GET and SET value methods. There is another way to use 2d arrays, I am working at the moment on an array with almost 1000 elements and there is no a reason for A[i,j] record at all. However I am not sure I can finish it because of limited amount of effects. Trying to deal with multi-cell logic by using beams…

We need some new functionalities/actions that that allow access to indexes or set them at indexes of any array dimension like Append Sub Array To or Index of Sub Array of Array so they might actually work as imagined. To create multidimensional Arrays on the fly this action Global.someArray = Array(value1, value2, value3) is the way to go and ofc not C stylized and simplified, an other way but inconvenient is you set the Array Values you want each with Set/Modify Global Variable at Index.

1 Like

Just a modification of “set variable at index” and “modify variable at index” would be enough: Giving the “index” value an expandable box wich can contain multiple numbers to represent multiple indices.

1 Like

Bruh, 2023 has gone and we didn’t received any decent update in workshop with QOL changes and improvements.

We din’t received even actions/conditions to track newer gamemodes. :clown_face:

Complex pathfinding systems, eg A* uses many arrays with nested array values containing all possible paths.

Also some specific context where i should reserve an array of arrays that contains specific state. Eg: Zeny discord orb, now you cannot attach orb to same target within 7 seconds, you cannot do this in a 1D Array, instead you must split into two variables (lastOrbEntities and lastOrbEntitiesTime)

Do a for loop decreasing time every fixed time eg:

// rule conditions:
// - player is alive
// - count of (lastOrbEntities) > 0

// 30 tickrate = 0.033
// 60 tickrate = 0.016
const timeRate = 0.033;

// we copy the array to ensure thread-safety 
//   basically we modify a copy of values, and after iteration 
//    we commit the changes, instead of commiting directly 
//     to referenced variable

// this will ensure daraArray must have same length during for iteration:
var dataLen = min of(count of(lastOrbEntitiesTime), count of(lastOrbEntities)); 

// this is reason multi dimentional array & custom data types MUST be implemented, 
// so we don't need split two arrays to store values.
var dataTimes = array slice(lastOrbEntitiesTime, 0, dataLen); // ensure same size
var dataEntities = array slice(lastOrbEntities, 0, dataLen); // ensure same size

for(var i = 0; i < dataLen; i++)
  dataTimes[i] -= timeRate;

  if (data[i] <= 0) { // time out, so we remove directly to reference array.
    remove from array by index(lastOrbEntities, lastOrbiteratorIndex);
    remove from array by index(lastOrbEntitiesTime, lastOrbiteratorIndex);
  }
  delay(timeRate)

loop if condition is true;

In other words if we use a real programming language example (i will show in C#, as my main working language now) we can reduce alot code to do this and even a efficient way to handle this:

readonly struct EntityId {
	// ...implementation...
}

enum OrbType {
	Good,
	Bad
}

class OrbState {
	public EntityId owner;
	public EntityId target;
	public OrbType type;
	public bool active;
	public float time;
	
	public void Update(float dt, Player targetPlayer){
		time -= dt;
		
		if(time <= 0.f) {
			time = 0f;
			active = false;
		}
		
		// add heal/ defub status to target player
	}
}

class OrbManager {
	public List<OrbState> states = new(Lobby.GetMaxPlayers(Team.All));
	
	public OrbState FindOrb(EntityId target, OrbType type) {
		foreach(var orb in states){
			if(orb.target == target && orb.type == type) {
				return orb;
			}
		}
		
		return null;
	}
	
	// ensure thread-safety
	OrbState[] GetOrbs(){
		lock(orbs){
			return orbs.ToArray();
		}
	}
	
	public void Update(float dt){
		foreach(var orb in GetOrbs()){
			// orb is not active, skip ticking
			if(!orb.active)
				continue;
			
			if(!Match.TryGetPlayer(orb.target, out var targetPlayer)){
				// player is not in the match or refs was removed.
				orb.target = default;
				orb.active = false;
				orb.time = 0;
				continue;
			}
			
			orb.Update(dt, targetPlayer);
		}
	}
	
	public void AddBadOrb(EntityId owner, EntityId target, float timeout = 5f) 
	{
		lock(orbs) {
			orbs.Add(new OrbState() {
				owner = owner,
				target = target,
				time = timeout
			});
		}
	}
}

void Update(float dt){
	// use ECS based example, because overwatch is ECS based too.
	var orbManager = RemotePlayer.GetComponent<OrbManager>();
	orbManager.Update(dt);
	
}

The problem is: If you know the size of array, multidimentional arrays is a quite simple task. Just use syntax array[x * y * z] = value;

But when you should add/remove items from multidimentional array this will not help.