Back to home
This game is archived.
If you with to unarchive it, click the "restore" button in the options menu.

Category:
Custom game mode

Author:
CactusPuppy

Rating:
1

Version:
1.0.0

Posted:
18 days ago

Last updated:
18 days ago

Tags:
scrims rejoin reconnect disconnect

Share this workshop!

Options

Rejoin++

A better system for handling disconnects

Sometimes during a scrim, a player will disconnect due to bad internet, their dog/cat pulling their power cord, etc. When they rejoin, they don't have any ult charge and they're all the way back in spawn. This Workshop aims to fix that.

Usage:

This Workshop is intended for use in lobbies that are running scrims or similar. When a player disconnects, as long as they rejoin into the same slot, they will be forced to select the hero they were last playing. Once said player spawns in, they will have the same ult charge they left with, and if they were alive when they disconnected, be in the same position with the same* health as when they disconnected.

  • See next section for caveat

Notes:

  • Due to the limitations of the Workshop, it is not possible to return the player to precisely their previous health if the hero possesses natural armor, but the damage will never kill the player, and the result should be fairly close regardless.
  • If a player fills in for the disconnected player, the Workshop will not distinguish the two and perform all of the aforementioned actions on the new player.
  • Currently, it does not seem possible to skip the step where the player must manually spawn in.
variables
{
	global:
		0: ultData
		1: posData
		2: loopWaitDuration
		3: facingData
		4: heroData
		5: isAlive
		6: normalizedHealthData

	player:
		0: playerSlot
		1: tempPos
		3: tempFacing
		4: tempHero
		5: isSpawning
}

rule("CONFIG: Change loopWaitDuration to be higher if server is overloaded")
{
	event
	{
		Ongoing - Global;
	}

	actions
	{
		Set Global Variable(loopWaitDuration, 0.050);
	}
}

rule("Global setup")
{
	event
	{
		Ongoing - Global;
	}

	actions
	{
		Set Global Variable(ultData, Empty Array);
		Set Global Variable(posData, Empty Array);
		Set Global Variable(facingData, Empty Array);
		Set Global Variable(heroData, Empty Array);
	}
}

rule("Wipe data upon round completion")
{
	event
	{
		Ongoing - Global;
	}

	conditions
	{
		Is Between Rounds == True;
	}

	actions
	{
		Set Global Variable(ultData, Empty Array);
		Set Global Variable(posData, Empty Array);
		Set Global Variable(facingData, Empty Array);
		Set Global Variable(heroData, Empty Array);
	}
}

rule("Loop every spawned in player that is alive and save their data")
{
	event
	{
		Ongoing - Each Player;
		All;
		All;
	}

	conditions
	{
		Is Alive(Event Player) == True;
		Has Spawned(Event Player) == True;
		Is Waiting For Players == False;
		Player Variable(Event Player, isSpawning) != True;
	}

	actions
	{
		Skip If(Compare(Team Of(Event Player), ==, Team 2), 2);
		Set Player Variable(Event Player, playerSlot, Slot Of(Event Player));
		Skip(1);
		Set Player Variable(Event Player, playerSlot, Add(6, Slot Of(Event Player)));
		Set Global Variable At Index(ultData, Player Variable(Event Player, playerSlot), Ultimate Charge Percent(Event Player));
		Set Global Variable At Index(posData, Player Variable(Event Player, playerSlot), Position Of(Event Player));
		Set Global Variable At Index(facingData, Player Variable(Event Player, playerSlot), Facing Direction Of(Event Player));
		Set Global Variable At Index(heroData, Player Variable(Event Player, playerSlot), Hero Of(Event Player));
		Set Global Variable At Index(normalizedHealthData, Player Variable(Event Player, playerSlot), Normalized Health(Event Player));
		Wait(Global Variable(loopWaitDuration), Abort When False);
		Loop If Condition Is True;
	}
}

rule("Detect player death and mark as not alive")
{
	event
	{
		Player Died;
		All;
		All;
	}

	conditions
	{
		Is Waiting For Players == False;
	}

	actions
	{
		Skip If(Compare(Team Of(Event Player), ==, Team 2), 2);
		Set Player Variable(Event Player, playerSlot, Slot Of(Event Player));
		Skip(1);
		Set Player Variable(Event Player, playerSlot, Add(6, Slot Of(Event Player)));
		Set Global Variable At Index(isAlive, Player Variable(Event Player, playerSlot), False);
	}
}

rule("Detect player alive")
{
	event
	{
		Ongoing - Each Player;
		All;
		All;
	}

	conditions
	{
		Is Waiting For Players == False;
		Is Alive(Event Player) == True;
		Has Spawned(Event Player) == True;
		Player Variable(Event Player, isSpawning) != True;
	}

	actions
	{
		Skip If(Compare(Team Of(Event Player), ==, Team 2), 2);
		Set Player Variable(Event Player, playerSlot, Slot Of(Event Player));
		Skip(1);
		Set Player Variable(Event Player, playerSlot, Add(6, Slot Of(Event Player)));
		Set Global Variable At Index(isAlive, Player Variable(Event Player, playerSlot), True);
	}
}

rule("Apply data upon player join and mark as spawning")
{
	event
	{
		Player Joined Match;
		All;
		All;
	}

	conditions
	{
		Is Waiting For Players == False;
		Global Variable(ultData) != Empty Array;
		Global Variable(posData) != Empty Array;
	}

	actions
	{
		Skip If(Compare(Team Of(Event Player), ==, Team 2), 2);
		Set Player Variable(Event Player, playerSlot, Slot Of(Event Player));
		Skip(1);
		Set Player Variable(Event Player, playerSlot, Add(6, Slot Of(Event Player)));
		Set Player Variable(Event Player, tempPos, Value In Array(Global Variable(posData), Player Variable(Event Player, playerSlot)));
		Abort If(Compare(Player Variable(Event Player, tempPos), ==, 0));
		Set Player Variable(Event Player, tempFacing, Value In Array(Global Variable(facingData), Player Variable(Event Player,
			playerSlot)));
		Abort If(Compare(Player Variable(Event Player, tempFacing), ==, 0));
		Set Player Variable(Event Player, tempHero, Value In Array(Global Variable(heroData), Player Variable(Event Player, playerSlot)));
		Abort If(Compare(Player Variable(Event Player, tempHero), ==, 0));
		Start Forcing Player To Be Hero(Event Player, Player Variable(Event Player, tempHero));
		Set Player Variable(Event Player, isSpawning, True);
		disabled Wait(0.250, Ignore Condition);
		disabled Respawn(Event Player);
		disabled Resurrect(Event Player);
	}
}

rule("Join spawn handler")
{
	event
	{
		Ongoing - Each Player;
		All;
		All;
	}

	conditions
	{
		Is Waiting For Players == False;
		Is Alive(Event Player) == True;
		Has Spawned(Event Player) == True;
		Player Variable(Event Player, isSpawning) == True;
	}

	actions
	{
		Stop Forcing Player To Be Hero(Event Player);
		Set Ultimate Charge(Event Player, Value In Array(Global Variable(ultData), Player Variable(Event Player, playerSlot)));
		Skip If(Compare(Value In Array(Global Variable(isAlive), Player Variable(Event Player, playerSlot)), ==, True), 2);
		Set Player Variable(Event Player, isSpawning, False);
		Abort;
		Damage(Event Player, Null, Multiply(Max Health(Event Player), Subtract(1, Value In Array(Global Variable(normalizedHealthData),
			Player Variable(Event Player, playerSlot)))));
		Teleport(Event Player, Player Variable(Event Player, tempPos));
		Set Facing(Event Player, Player Variable(Event Player, tempFacing), To World);
		Set Player Variable(Event Player, isSpawning, False);
	}
}

disabled rule("DEBUG: Skip assemble")
{
	event
	{
		Ongoing - Global;
	}

	conditions
	{
		Is Assembling Heroes == True;
	}

	actions
	{
		Set Match Time(5);
	}
}