Create Beam Effect only visible to spectators?

Is it possible to create an effect whis would be only visible to spectators

No not with effects. It only works with HUDs and In-World Text elements.

1 Like

through some complex code it’s probably possible

Well what you could try is to create a dynamic Array of Players which contains anyone who should see the effect or beams. When a player left the game or is sent into spectatore, reset that Array it should contain only all remaining Players in game and lastly when a Player joins the game append that Player to that Array. Despite we still can’t access spectating players.

1 Like

This is possible actually, and I can somewhat try to explain why and how I can accomplish this. The way this is done is by using local player values, however, from my testing it seems you cannot grab the position of a spectator / local player at all. Whatever it’s trying to do is trying to check for the position of the local player’s entity and not the actual camera view of the local player unfortunately and will always default to null / 0 or some empty array.

Now onto how it’s possible to get certain things to show up for spectators only. Take this example rule and run a game with it (no condition needed, it’s inside the visible to field).

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

	actions
	{
		Create Beam Effect(Is True For Any(Local Player, Entity Exists(Local Player) == False), Good Beam, Vector(0, 10, 0), Vector(0, 0,
			0), Color(Orange), Visible To Position and Radius);
	}
}

This will only show up for players that do not have an entity, with the beam at the center of the map. (use workshop expanse or something to see for yourself, test inside spectate and as a player). What this is doing, is using a condition inside is true for any, that is checking if the entity exists = false. You can also use, hero of = false, or has spawned = false, all 3 of those can achieve roughly the same result. This method technically will work for normal players, but it will only work for them when they do not have a hero selected and are inside the hero selection screen, but inside this screen, you cannot see any effects or huds anyways, meaning you might as well use one of those 3 conditions to check if they exist or have a hero, because a spectator will not have that. Keep in mind though, you can also use a filtered array of local player and achieve a similar result, however, for some reason you cannot use “entity exists” and “local player” together inside a filtered array. (and some things don’t work the other way either.)

I am not THAT much of an expert on the differences between “is true for any” and “filtered arrays” despite them being very similar, I have only really seen this myself just by playing around with things and seeing how I can force some visuals in some way that might not seem possible. But basically it seems like they both can be used in the same way for most things, but some things will only work for one or the other.

SO BASICALLY imo, something cool and one of the best uses for this that I can find for forcing things that might not seem possible to do, is getting player outline colors to show up for everything, including spectators.

rule("Rule 4")
{
	event
	{
		Ongoing - Each Player;
		All;
		All;
	}

	conditions
	{
		Hero Of(Event Player) == True;
	}

	actions
	{
		Start Forcing Player Outlines(Event Player, Is True For Any(Local Player, True), True, Color(White), Always);
	}
}

Player Outlines do have some issues, they do not have any automatic reevaluation unlike a hud or an effect, you normally have to reevaluate them yourself for any new players that join etc. If I tried using the same condition field inside a “filtered array, local player, true” instead of “is true for any”, the visibility will just not work at all, because filtered array seems like it needs some type of reevaluation to check it’s condition again. But is true for any, does not necessarily need it if you just say true, and therefore, you can force it to be always true and now a spectator will be able to see the outline color of that player while they previously couldn’t since it couldn’t be reevaluated to check for them. They can even adjust the outline strength in the spectator options and it works as expected. Keep in mind, that there are some bugs with player outlines, and if your models load slowly on the client maybe from a slow hard drive or computer, it is possible the game did try to apply it, but at the wrong time and the spectator / player actually might not be able to see it. So if you wanted to make sure they see it, add a wait timer or just loop the outline every few seconds to make sure they get applied for everyone including spectators.

Also something else that is kind of cool as a little bonus, you can check if a spectating player is pressing a button with local player, as this for an example

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

	actions
	{
		Create Beam Effect(Filtered Array(Local Player, Is Button Held(Local Player, Button(Secondary Fire)) == True && Hero Of(
			Local Player) == False), Good Beam, Vector(0, 10, 0), Vector(0, 0, 0), Color(Orange), Visible To Position and Radius);
	}
}

If you test this in-game, the beam will only show up if the spectator is pressing shift. This can be done with huds and other effects as well if they have a reevaluation field.

This is one of those conditions that is checking if the local player has a hero, and that is needed that way because we can’t use entity exists and compare it with local player inside a filtered array, and I also can’t check if the local player is holding a button inside is true for any (or I am just dumb and do not know how to do it properly). But yeah, we are checking if they are holding secondary fire, however, this translates to a different button for spectators, secondary fire is the Move Fast button, aka shift by default.

tl;dr
That’s pretty much all I have to say about that, just copy some of those rules and play around with them if you want, and pretty much that is some ways to get things to show up for spectators that you normally wouldn’t be able to probably figure out. Reevaluation is needed for actual conditions that need to be checked, like if they spawned, or are holding a button. Also make sure to run those effects globally no condition (unless you plan on creating more and properly removing them). Outlines need to be ran as ongoing - each player, unless you are going to specifiy the player in a specific way with a variable, string, or slot and not event player.

Oh and if you are trying to get it to show up to a spectator that does have a hero selected, and say they are dead inside an elimination mode with 1 or limited lives, then instead of checking if entity exists, check “is alive = false”.

Here is my alternate solution to make effects/beams only visible to spectators with dynamic Array approach:

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

	actions
	{
		Global.A = Array();
		Create Beam Effect(Global.A, Bad Beam, Objective Position(0), Objective Position(1), Color(Orange),
			Visible To Position Radius and Color);
		Global.B = Last Created Entity;
	}
}

rule("Rule 2")
{
	event
	{
		Player Joined Match;
		All;
		All;
	}

	actions
	{
		Modify Global Variable(A, Append To Array, Event Player);
	}
}

rule("Rule 3")
{
	event
	{
		Ongoing - Each Player;
		All;
		All;
	}

	conditions
	{
		Is Alive(Event Player) == True;
		Has Spawned(Event Player) == True;
	}

	actions
	{
		Modify Global Variable(A, Remove From Array By Value, Event Player);
	}
}

The difference between Is True For All/Any and Mapped/Filtered/Sorted Array is noticably their return type the later will return an Array in best cases, but all options reevaluate continuously fine. The second similarity is they all use a high order/anonymous/lambda/predicate/delegate function expression as an input paramter which is applied to all ellements in an Array implicitly instead of one by one, you could say they represent the missing for each contol flow instruction. These are very common methods in high level languages and scripting language like the workshop.

And what do you mean with that?

You can use filtered Array and Local Player just fine togetehr in Creation of Effects/Beams.

1 Like

No for some reason, SPECIFICALLY for spectators, checking entity exists, local player, false, will just not work is what I mean for visibility. It works fine for anything else.

Edit: actually nvm. It seems like I might of done something wrong in my testing that was making that not work, welp strange, because that was baffling me for a bit. So nvm it does work for some reason my bad.

Edit 2: ACTUALLY NO, IT DOES NOT WORK PROPERLY. You actually need 2 players to test this. If you use this exact thing here and 1 player is in-game and the other is in specate, it will never show up for a spectator.

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

	actions
	{
		Create Beam Effect(Filtered Array(Local Player, Entity Exists(Local Player) == False), Good Beam, Vector(0, 10, 0), Vector(0, 0,
			0), Color(White), Visible To Position and Radius);
	}
}

HOWEVER, if no player is in the game as a whole and are all spectators, it WILL show up for the spectators. Is true for ANY however, does not have this issue at all.

Alright with some more testing, the results I get are different. If there were 0 players in-game, filtered array of either local player or all players, checking if the entity exists of the local player = false, seems to work as expected. HOWEVER, if a single player was in the game, it seems to always output entity exists as TRUE, regardless if a person was spectating or not.
Is True for Any however, has a slightly different effect that seems to be better. Now for some reason, if no players are in the game, then the condition seems to just not work right no matter what. However, if 1 player was in the game, and 1 player is spectating, the results work completely as expected, where the player in-game will not see the beam / effect, but the player in spectate can. Strange for sure.

Well i would use All Players due Local Player would be an empty Array and check if the Current Array Element still exists or is dead. Maybe cause no proper Array is coerced in your example If True for Any/All is provided it returns a boolean value (which is the return value of these) of false which can coerce eithernumerically to 0 or Null. So in the end none will see the effects.

1 Like

Alright here we go. This works as expected always. By using the array All Players since that array is for players in-game and does not check spectators.

Edit agian… Actually this one here is way better, check for all living players. Instead of filtered array, or true for any, we want to check all values, so is true for all is the best appraoch here.

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

	actions
	{
		Create Beam Effect(Is True For All(All Living Players(All Teams), Array Contains(Current Array Element, Local Player) == False),
			Good Beam, Vector(0, 10, 0), Vector(0, 0, 0), Color(White), Visible To Position and Radius);
	}
}

The filtered array will have issues with the player in spectator for some reason whenever the single player that is in-game is dead. Is true for all is the best approach here. This works both when the player is dead, and for any spectator regardless if a player is in-game or not. This is just a simple beam in the middle of the map however, just use the same visible to field in anything else you want.

1 Like

Tested it and that seems to work strangely, cause Is True variants just returns on surfaces a boolean value not an Array of Players or any Entity. Except the Array it takes in is passed by reference and internally the creation actions wrap around these variants, but better than Filtered Array and co. doing alone. It still makes no sense for me when i look at it and Is True… e.g. pops up when i read it.

1 Like

Honestly, I have no clue how to make sense of it either LMAO, like I was trying to think of why it’s working the way it is, but I mean, it just does. Also if you want a sphere because it’s easier to see for testing then you can use this one.

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

	actions
	{
		Create Effect(Is True For All(All Living Players(All Teams), Array Contains(Current Array Element, Local Player) == False), Sphere,
			Color(White), Vector(0, 0, 0), 10, Visible To Position and Radius);
	}
}

Regardless of why it works though, it does seem to have like no issues at all compared to anything thing else I’ve messed around with, with 2 players. What I think it’s doing honestly, the condition itself, actually checks if local player is inside or not. Maybe the reason this works in spectator, local player might actually come up as null, aka 0, and since 0 / null is not in the array of living players, then it returns it as good to go for visibility. And for the player in-game, it knows the check local player as their name, and if it finds their name in that array, then it returns it as no visibility. Now idk what the array looks like if no players are in-game, but it must be straight up empty and not contain the 0 that local player is likely outputting since it is dumb and cannot grab their name properly.

Idk though just a guess tbh I don’t really know what I am saying, but at the same time that is my possible logic behind it.

1 Like

You came close to how its interpreted. What makes me suspicious is that the Visibility parameter slot does not accept the logical values True, False and Not but the variants mentioned even though they return a boolean value which that paramter won’t accept. Otherwise you could directly input the following “Not(Array Contains(All Living Players, All Teams, Local Player))”. My last grasp would be in context of effect creation Is True and so will return the passed in Array with its Elements passing the conditional check when true and on false it just return 0, Null or an Empty Array. Glad we learn a lot more especially new discovered workarounds to use.

1 Like

Yeah, forget whatever else I was saying before this, because that last one works wonders. Also for the OP, if you don’t want it visible to dead players, just change living players, to all players, and then it will only be visible to spectators that way. But regardless you can def use like any array there that works best, specifying it in any way you want like Arcana’s original array solution. And thanks Arcana for some of that insight, because idk why but w/e you were saying just gave me random ideas to test some things out and that’s what I came up with lol.

1 Like