Return to post
settings
{
main
{
Description: "Reinhardt is the real hockey player in Overwatch. (by nobody#1774)"
}
lobby
{
Allow Players Who Are In Queue: Yes
Map Rotation: After A Game
Match Voice Chat: Enabled
Max Spectators: 12
Max Team 2 Players: 0
Return To Lobby: Never
}
modes
{
Team Deathmatch
{
enabled maps
{
Workshop Chamber
Workshop Expanse Night
Workshop Island Night
}
}
General
{
Allow Hero Switching: Off
Enemy Health Bars: Off
Game Mode Start: Immediately
Hero Limit: Off
Mercy Resurrect Counteracts Kills: Off
Respawn As Random Hero: On
Respawn Time Scalar: 10%
Score To Win: 7
Self Initiated Respawn: Off
}
}
heroes
{
General
{
Lúcio
{
Damage Dealt: 10%
Damage Received: 10%
Primary Fire: Off
Ultimate Ability Sound Barrier: Off
}
Pharah
{
Concussive Blast Cooldown Time: 50%
Damage Dealt: 10%
Hover Jets: Off
Movement Speed: 75%
Primary Fire: Off
Projectile Speed: 50%
Quick Melee: Off
Ultimate Ability Barrage: Off
}
Reinhardt
{
Barrier Field: Off
Charge Cooldown Time: 200%
Damage Dealt: 10%
Damage Received: 10%
Fire Strike: Off
Movement Speed: 75%
Rocket Hammer Knockback Scalar: 200%
Ultimate Generation - Passive Earthshatter: 500%
}
Roadhog
{
Chain Hook Cooldown Time: 50%
Damage Dealt: 10%
Damage Received: 10%
Health: 500%
Movement Gravity: 25%
Primary Fire: Off
Quick Melee: Off
Secondary Fire: Off
Take a Breather: Off
Ultimate Ability Whole Hog: Off
}
Wrecking Ball
{
Damage Received: 10%
Health: 500%
Movement Gravity: 75%
Projectile Gravity: 75%
Roll Always Active: On
}
enabled heroes
{
Reinhardt
}
}
}
workshop
{
Acceleration factor when not turning sharply: 1.050
Ball scale factor: 0.200
Deceleration factor when turning sharply: 0.000
Min movement speed percent: 67
Max movement speed percent: 250
}
}
variables
{
global:
0: BOOL_Initialized
1: VECTOR_Ball_Spawn
2: PLAYER_Ball
3: VECTOR_Goal_1
4: VECTOR_Goal_2
5: PLAYERS_Team_1
6: PLAYERS_Team_2
7: REAL_Goal_Radius
8: REAL_Ball_Scale
9: VECTOR_Spawn_Team_1
10: VECTOR_Spawn_Team_2
11: REAL_Ball_Scale_Percent
12: INT_Three_Pointer_Distance
13: VECTOR_Last_Shot_From
14: REAL_Goal_Height_Team_1
15: REAL_Goal_Height_Team_2
16: STRINGS_Scored_2
17: STRINGS_Scored_3
18: REAL_Map_Scale_Factor
19: REAL_Player_Scale
20: PLAYERS_All
21: REAL_Wind
22: REAL_Wind_Bounds
23: VECTOR_Ball_Last_Position
24: INT_Movement_Speed_Max
25: INT_Movement_Speed_Min
26: INT_Loop_Control
27: INT_Max_Turn_Degrees
28: REAL_Decel_Factor
29: REAL_Accel_Factor
30: STRINGS_Tips
31: BOOL_Goal_Just_Scored
32: PLAYER_Last_Touched
33: VECTORS_Spawns
34: COLOR_Red
35: COLOR_Blue
36: LINES_Bounds
37: REAL_Wind_Y
38: LINES_Red_Blue
39: LINES_Outer_Bounds
40: BOOL_Boards
41: VECTORS_Portals
42: REAL_Portal_Radius
43: LOCAL_VECTOR_Portal
44: COLORS_Portals
45: VECTORS_Antigravity
player:
0: INT_Team
1: BOOL_Spawned
2: BOOL_Welcomed
3: VECTOR_Movement
4: INT_Move_Speed
5: BOOL_Decelerating
6: VECTOR_Last_Position
7: INT_Movement_Angle
8: REAL_Decel_Factor
}
subroutines
{
0: Reset
1: Reassign_Teams
2: Teleport_Players
3: Set_Team_Player_Lists
4: Create_Effects
}
rule("MAP: Expanse")
disabled rule("PLAYER: Skating (old, facing-based)")
{
event
{
Ongoing - Global;
Ongoing - Each Player;
Team 1;
All;
}
conditions
{
Array Contains(Array(Map(Workshop Expanse), Map(Workshop Expanse Night)), Current Map) == True;
Is Game In Progress == True;
Is Alive(Event Player) == True;
}
actions
{
Global.LINES_Bounds = Array(Array(Vector(30, 0, 15), Vector(-30, 0, 15)), Array(Vector(-30, 0, 15), Vector(-30, 0, -15)), Array(
Vector(-30, 0, -15), Vector(30, 0, -15)), Array(Vector(30, 0, -15), Vector(30, 0, 15)));
"If the ball crosses these lines, it's destroyed (a failsafe, because people can't be trusted to bring the ball back in-bounds)."
Global.LINES_Outer_Bounds = Array(Array(Vector(35, 0, 20), Vector(-35, 0, 20)), Array(Vector(-35, 0, 20), Vector(-35, 0, -20)),
Array(Vector(-35, 0, -20), Vector(35, 0, -25)), Array(Vector(35, 0, -20), Vector(35, 0, 20)));
Global.LINES_Red_Blue = Array(Array(Vector(0, 0, -15), Vector(0, 0, 15)), Array(Vector(7.500, 0, -15), Vector(7.500, 0, 15)),
Array(Vector(-7.500, 0, -15), Vector(-7.500, 0, 15)));
Global.VECTOR_Ball_Spawn = Vector(0, 5, 0);
"NOTE: Chamber and Island have coordinates rotated 90 degrees from each other. A bit confusing."
Global.VECTORS_Spawns = Array(Array(Vector(-10, 0, -10), Vector(-10, 0, 0), Vector(-10, 0, 10)), Array(Vector(10, 0, -10), Vector(
10, 0, 0), Vector(10, 0, 10)));
Global.VECTOR_Goal_1 = Vector(26, 0, 0);
Global.VECTOR_Goal_2 = Vector(-26, 0, 0);
Global.REAL_Goal_Radius = 2;
Global.VECTOR_Spawn_Team_1 = Vector(-18, 0, -18);
Global.VECTOR_Spawn_Team_2 = Vector(18, 0, 18);
Global.REAL_Player_Scale = 0.750;
Global.REAL_Wind = 0.375;
Global.REAL_Wind_Bounds = 21;
Global.COLOR_Red = Color(Purple);
Global.COLOR_Blue = Color(Aqua);
Global.REAL_Wind_Y = 0;
Global.BOOL_Boards = True;
"Reset when not moving."
If(!Is Moving(Event Player));
Event Player.INT_Move_Speed = Global.INT_Movement_Speed_Min;
Event Player.BOOL_Decelerating = False;
Else;
"Reduce speed if turn too sharp."
If(Angle Between Vectors(Facing Direction Of(Event Player), Event Player.VECTOR_Movement) > Global.INT_Max_Turn_Degrees);
Event Player.INT_Move_Speed = Max(Global.INT_Movement_Speed_Min, Event Player.INT_Move_Speed * Global.REAL_Decel_Factor);
Event Player.BOOL_Decelerating = True;
"Increase speed."
Else;
Event Player.INT_Move_Speed = Min(Global.INT_Movement_Speed_Max, Event Player.INT_Move_Speed * Global.REAL_Accel_Factor);
Event Player.BOOL_Decelerating = False;
End;
End;
"Update move speed."
Set Move Speed(Event Player, Event Player.INT_Move_Speed);
"Finally, update movement vector."
Event Player.VECTOR_Movement = Facing Direction Of(Event Player);
"Loop while alive."
Wait(0.050, Ignore Condition);
Loop If Condition Is True;
}
}
rule("PLAYER: Skating (new, movement vector-based)")
{
event
{
Ongoing - Each Player;
Team 1;
All;
}
conditions
{
Is Game In Progress == True;
Is Alive(Event Player) == True;
}
actions
{
Event Player.INT_Movement_Angle = Angle Between Vectors(Direction Towards(Event Player.VECTOR_Last_Position, Position Of(
Event Player)), Event Player.VECTOR_Movement);
disabled Event Player.INT_Movement_Angle = Angle Between Vectors(Event Player.VECTOR_Movement, Direction Towards(
Event Player.VECTOR_Last_Position, Position Of(Event Player)));
"Reset when not moving."
If(!Is Moving(Event Player));
Event Player.INT_Move_Speed = Global.INT_Movement_Speed_Min;
Event Player.BOOL_Decelerating = False;
Else;
"Reduce speed if turn too sharp."
If(Event Player.INT_Movement_Angle > Global.INT_Max_Turn_Degrees);
Event Player.REAL_Decel_Factor = 1 - Event Player.INT_Movement_Angle * Global.REAL_Decel_Factor;
disabled Event Player.REAL_Decel_Factor = Event Player.INT_Movement_Angle * Global.REAL_Decel_Factor;
Event Player.INT_Move_Speed = Max(Global.INT_Movement_Speed_Min, Event Player.INT_Move_Speed * Event Player.REAL_Decel_Factor);
Event Player.BOOL_Decelerating = True;
"Increase speed."
Else;
Event Player.INT_Move_Speed = Min(Global.INT_Movement_Speed_Max, Event Player.INT_Move_Speed * Global.REAL_Accel_Factor);
Event Player.BOOL_Decelerating = False;
End;
End;
"Update move speed."
Set Move Speed(Event Player, Event Player.INT_Move_Speed);
Event Player.VECTOR_Movement = Direction Towards(Event Player.VECTOR_Last_Position, Position Of(Event Player));
"Finally, update variables."
Event Player.VECTOR_Last_Position = Position Of(Event Player);
"Loop while alive."
Wait(0.050, Ignore Condition);
Loop If Condition Is True;
}
}
rule("BALL: Wind (keep it in bounds on Island)")
{
event
{
Ongoing - Each Player;
All;
Wrecking Ball;
}
conditions
{
Is Game In Progress == True;
Global.REAL_Wind_Bounds != 0;
disabled Distance Between(Position Of(Event Player), Vector(0, 0, 0)) > Global.REAL_Wind_Bounds;
(X Component Of(Position Of(Event Player)) > 20 || X Component Of(Position Of(Event Player)) < -20 || Z Component Of(Position Of(
Event Player)) > 20 || Z Component Of(Position Of(Event Player)) < -20) == True;
}
actions
{
Apply Impulse(Event Player, Vector(0, 0.500, 0) + Direction Towards(Position Of(Event Player), Global.VECTOR_Ball_Last_Position),
Speed Of(Event Player) / 2, To World, Cancel Contrary Motion XYZ);
disabled Wait(0.016, Ignore Condition);
disabled Loop If Condition Is True;
}
}
rule("MAP: Island")
{
event
{
Ongoing - Global;
}
conditions
{
Array Contains(Array(Map(Workshop Island), Map(Workshop Island Night)), Current Map) == True;
}
actions
{
Global.LINES_Red_Blue = Array(Array(Vector(0, 0, -20), Vector(0, 0, 20)), Array(Vector(7.500, 0, -20), Vector(7.500, 0, 20)),
Array(Vector(-7.500, 0, -20), Vector(-7.500, 0, 20)));
Global.LINES_Bounds = Array(Array(Vector(20, 0, 20), Vector(-20, 0, 20)), Array(Vector(-20, 0, 20), Vector(-20, 0, -20)), Array(
Vector(-20, 0, -20), Vector(20, 0, -20)), Array(Vector(20, 0, -20), Vector(20, 0, 20)));
Global.VECTOR_Ball_Spawn = Vector(0, 20, 0);
"NOTE: Chamber and Island have coordinates rotated 90 degrees from each other. A bit confusing."
Global.VECTORS_Spawns = Array(Array(Vector(-15, 0, -15), Vector(-15, 0, 0), Vector(-15, 0, 15)), Array(Vector(15, 0, -15), Vector(
15, 0, 0), Vector(15, 0, 15)));
Global.VECTOR_Goal_1 = Vector(20, 0, 0);
Global.VECTOR_Goal_2 = Vector(-20, 0, 0);
Global.VECTOR_Spawn_Team_1 = Vector(-18, 0, -18);
Global.VECTOR_Spawn_Team_2 = Vector(18, 0, 18);
Global.REAL_Player_Scale = 0.750;
Global.REAL_Ball_Scale = 0.200;
Global.REAL_Wind = 0.375;
Global.REAL_Wind_Bounds = 21;
Global.COLOR_Red = Color(Purple);
Global.COLOR_Blue = Color(Aqua);
Global.REAL_Wind_Y = 0.500;
Global.BOOL_Boards = False;
}
}
rule("MAP: Chamber")
{
event
{
Ongoing - Global;
}
conditions
{
Current Map == Map(Workshop Chamber);
}
actions
{
"NOTE: Chamber and Island have coordinates rotated 90 degrees from each other. A bit confusing."
Global.VECTORS_Spawns = Array(Array(Vector(-15, 0, -15), Vector(-15, 0, 0), Vector(-15, 0, 15)), Array(Vector(15, 0, -15), Vector(
15, 0, 0), Vector(15, 0, 15)));
Global.LINES_Red_Blue = Array(Array(Vector(0, 0, -20), Vector(0, 0, 20)), Array(Vector(7.500, 0, -20), Vector(7.500, 0, 20)),
Array(Vector(-7.500, 0, -20), Vector(-7.500, 0, 20)));
Global.LINES_Bounds = Array(Array(Vector(20, 0, 20), Vector(-20, 0, 20)), Array(Vector(-20, 0, 20), Vector(-20, 0, -20)), Array(
Vector(-20, 0, -20), Vector(20, 0, -20)), Array(Vector(20, 0, -20), Vector(20, 0, 20)));
Global.VECTOR_Ball_Spawn = Vector(0, 0, 0);
"NOTE: Chamber and Island have coordinates rotated 90 degrees from each other. A bit confusing."
disabled Global.VECTORS_Spawns = Array(Array(Vector(-15, 0, -15), Vector(-15, 0, 0), Vector(-15, 0, 15)), Array(Vector(15, 0, -15), Vector(
15, 0, 0), Vector(15, 0, 15)));
Global.VECTOR_Goal_1 = Vector(20, 0, 0);
Global.VECTOR_Goal_2 = Vector(-20, 0, 0);
Global.VECTOR_Ball_Spawn = Vector(0.024, 0.179, 0.009);
Global.VECTOR_Goal_1 = Vector(-20, 0, 0);
Global.VECTOR_Goal_2 = Vector(20, 0, 0);
Global.VECTOR_Spawn_Team_1 = Vector(19, 0, 19);
Global.VECTOR_Spawn_Team_2 = Vector(-19, 0, -19);
Global.REAL_Player_Scale = 0.750;
Global.COLOR_Red = Color(Red);
Global.COLOR_Blue = Color(Blue);
Global.VECTORS_Portals = Array(Vector(20, 0, 20), Vector(-20, 0, -20));
Global.COLORS_Portals = Array(Color(Aqua), Color(Orange));
Global.REAL_Portal_Radius = 2;
Global.VECTORS_Antigravity = Array(Vector(-20, 0, 20), Vector(20, 0, -20));
Global.REAL_Ball_Scale = 0.200;
}
}
rule("INIT:")
rule("MAP: Necropolis")
{
event
{
Ongoing - Global;
}
conditions
{
Global.BOOL_Initialized != True;
Current Map == Map(Necropolis);
}
actions
{
Global.BOOL_Initialized = True;
If(Global.REAL_Goal_Radius == 0);
Global.REAL_Goal_Radius = Workshop Setting Real(Custom String("Settings"), Custom String("Goal radius (meters)"), 3, 1, 10, 0);
End;
Global.STRINGS_Tips = Array(Custom String("Keep your momentum by turning slowly."), Custom String(
"Slow is smooth, smooth is fast."), Custom String("Speed is life."), Custom String("Skate not to where the puck is."),
Custom String("Skate to where the puck will be."), Custom String("You miss 100% of the shots you don't take."), Custom String(
"Fun fact: Hockey was invented by a penguin rancher in 1782."), Custom String("Don't be a ball hog. Pass it!"), Custom String(
"There's no jumping in hockey!"));
Global.REAL_Accel_Factor = Workshop Setting Real(Custom String("Movement"), Custom String(
"Acceleration factor (when not turning sharply)"), 1.045, 1, 1.100, 0);
Global.INT_Max_Turn_Degrees = Workshop Setting Integer(Custom String("Movement"), Custom String(
"Max turn (degrees) (speed reduces with sharper turns)"), 5, 0, 360, 0);
Global.INT_Movement_Speed_Max = Workshop Setting Integer(Custom String("Movement"), Custom String("Max movement speed (percent)"),
250, 10, 500, 0);
Global.INT_Movement_Speed_Min = Workshop Setting Integer(Custom String("Movement"), Custom String("Min movement speed (percent)"),
50, 10, 200, 0);
Global.STRINGS_Scored_2 = Array(Custom String("Score!"), Custom String("Boom, shakalaka!"), Custom String("Nothing but net!"),
Custom String("He shoots, he scores!"), Custom String("Swish!"));
Global.REAL_Ball_Scale = Workshop Setting Real(Custom String("Settings"), Custom String("Ball scale (factor)"), 0.200, 0.100, 100,
0);
"NOTE: Disabled because the setting sliders only allow 2 decimal digits of precision, and we need 3. (sigh)"
disabled Global.REAL_Decel_Factor = Workshop Setting Real(Custom String("Movement"), Custom String(
"Deceleration factor (when turning sharply)"), 0.004, 0, 0.010, 0);
"FIXME: If Workshop real number sliders are changed to allow 3 decimal digits, move this setting back to one."
Global.REAL_Decel_Factor = 0.004;
Global.PLAYERS_Team_1 = Empty Array;
Global.PLAYERS_Team_2 = Empty Array;
"Dummy bot (basketball)."
Create Dummy Bot(Hero(Wrecking Ball), Team 2, -1, Global.VECTOR_Ball_Spawn, Vector(0, 0, 0));
Global.PLAYER_Ball = Last Created Entity;
Create Icon(All Players(All Teams), Global.PLAYER_Ball, Circle, Visible To and Position, Color(Black), True);
Start Forcing Dummy Bot Name(Global.PLAYER_Ball, Custom String("Ball"));
Start Forcing Player Outlines(Global.PLAYER_Ball, All Players(Team 1), True, Color(Yellow), Always);
Start Scaling Player(Global.PLAYER_Ball, Global.REAL_Map_Scale_Factor * 0.500, False);
"Goals."
Create Effect(Global.PLAYERS_Team_1, Sphere, Global.COLOR_Red, Global.VECTOR_Goal_1, Global.REAL_Goal_Radius, Visible To);
Create Effect(Global.PLAYERS_Team_1, Sphere, Global.COLOR_Blue, Global.VECTOR_Goal_2, Global.REAL_Goal_Radius, Visible To);
Create Effect(Global.PLAYERS_Team_2, Sphere, Global.COLOR_Blue, Global.VECTOR_Goal_2, Global.REAL_Goal_Radius, Visible To);
Create Effect(Global.PLAYERS_Team_2, Sphere, Global.COLOR_Red, Global.VECTOR_Goal_1, Global.REAL_Goal_Radius, Visible To);
disabled Create Effect(All Players(All Teams), Sphere, Color(Gray), Global.VECTOR_Goal_1, Global.INT_Three_Pointer_Distance,
Visible To Position and Radius);
disabled Create Effect(All Players(All Teams), Sphere, Color(Gray), Global.VECTOR_Goal_2, Global.INT_Three_Pointer_Distance,
Visible To Position and Radius);
Create In-World Text(Global.PLAYERS_Team_1, Custom String("DEFEND"), Global.VECTOR_Goal_2, 1, Do Not Clip, Visible To, Color(
White), Visible Never);
Create In-World Text(Global.PLAYERS_Team_1, Custom String("SCORE"), Global.VECTOR_Goal_1, 1, Do Not Clip, Visible To, Color(White),
Visible Never);
Create In-World Text(Global.PLAYERS_Team_2, Custom String("DEFEND"), Global.VECTOR_Goal_1, 1, Do Not Clip, Visible To, Color(
White), Visible Never);
Create In-World Text(Global.PLAYERS_Team_2, Custom String("SCORE"), Global.VECTOR_Goal_2, 1, Do Not Clip, Visible To, Color(White),
Visible Never);
"HUD."
Create HUD Text(All Players(All Teams), Custom String("Share code"), Custom String("https://workshop.codes/reinhardt-hockey"),
Custom String("QBHWR"), Left, -1, Color(White), Color(Turquoise), Color(White), Visible To and String, Default Visibility);
Create HUD Text(All Players(All Teams), Custom String("TEAM COLOR"), Null, Null, Top, 0,
Local Player.INT_Team == 1 ? Global.COLOR_Blue : Global.COLOR_Red, Color(White), Null, Visible To String and Color,
Default Visibility);
Create HUD Text(All Players(Team 1), Custom String("SPEED"), Custom String("Turning sharply slows down"), Custom String(
"{0} ({2}%)", Local Player.BOOL_Decelerating ? Custom String("Decreasing") : (Is Moving(Local Player) ? Custom String(
"Increasing") : Custom String("")), Local Player.INT_Movement_Angle, Local Player.INT_Move_Speed), Left, 0,
Local Player.BOOL_Decelerating ? Color(Red) : (Is Moving(Local Player) ? Color(Green) : Color(White)), Color(Turquoise), Color(
White), Visible To String and Color, Default Visibility);
Set Objective Description(All Players(All Teams), Custom String("Reinhardt Hockey"), Visible To and String);
Disable Built-In Game Mode Scoring;
Call Subroutine(Reset);
"Lines (decorative)"
Create Beam Effect(All Players(All Teams), Good Beam, Global.LINES_Red_Blue[0][0], Global.LINES_Red_Blue[0][1], Global.COLOR_Red,
Visible To);
Create Beam Effect(All Players(All Teams), Good Beam, Global.LINES_Red_Blue[1][0], Global.LINES_Red_Blue[1][1], Global.COLOR_Blue,
Visible To);
Create Beam Effect(All Players(All Teams), Good Beam, Global.LINES_Red_Blue[2][0], Global.LINES_Red_Blue[2][1], Global.COLOR_Blue,
Visible To);
"Center-ice ring."
Create Effect(All Players(All Teams), Ring, Global.COLOR_Red, Vector(0, 0, 0), 3, Visible To);
"Face-off rings (decorative)"
disabled Create Effect(All Players(All Teams), Ring, Color(Red), Vector(-10, 0, 10), 2, Visible To);
disabled Create Effect(All Players(All Teams), Ring, Color(Red), Vector(10, 0, -10), 2, Visible To);
disabled Create Effect(All Players(All Teams), Ring, Color(Red), Vector(10, 0, 10), 2, Visible To);
disabled Create Effect(All Players(All Teams), Ring, Color(Red), Vector(-10, 0, -10), 2, Visible To);
Call Subroutine(Create_Effects);
Global.VECTOR_Ball_Spawn = Vector(9.154, 1.535, 0.506);
Global.VECTOR_Goal_1 = Vector(-116.830, 33.125, 34.291);
Global.VECTOR_Goal_2 = Vector(-20.765, 5.293, 19.408);
Global.VECTOR_Spawn_Team_1 = Vector(-20.765, 5.293, 19.408);
Global.VECTOR_Spawn_Team_2 = Vector(-116.830, 33.125, 34.291);
Global.REAL_Map_Scale_Factor = 0.750;
}
}
rule("PLAYER: Joins (assign to team)")
rule("MAP: Kanezaka")
{
event
{
Player Joined Match;
Team 1;
All;
Ongoing - Global;
}
conditions
{
Global.BOOL_Initialized == True;
Current Map == Map(Kanezaka);
}
actions
{
Global.PLAYERS_All = All Players(Team 1);
Event Player.BOOL_Spawned = False;
If(Count Of(Global.PLAYERS_Team_1) <= Count Of(Global.PLAYERS_Team_2));
Event Player.INT_Team = 1;
Else;
Event Player.INT_Team = 2;
End;
Call Subroutine(Set_Team_Player_Lists);
Start Scaling Player(Event Player, Global.REAL_Player_Scale, False);
Global.VECTOR_Ball_Spawn = Vector(-9.412, 10.788, -37.794);
Global.VECTOR_Goal_1 = Vector(-4.698, 6.454, -3.744);
Global.VECTOR_Goal_2 = Vector(-36.118, 8.455, -52.134);
Global.VECTOR_Spawn_Team_1 = Vector(-36.118, 8.455, -52.134);
Global.VECTOR_Spawn_Team_2 = Vector(-4.698, 6.454, -3.744);
Global.REAL_Map_Scale_Factor = 0.750;
}
}
rule("PLAYER: Leaves")
rule("MAP: Blizz World")
{
event
{
Player Left Match;
Team 1;
All;
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Current Map == Map(Blizzard World);
}
actions
{
Global.PLAYERS_All = All Players(Team 1);
Call Subroutine(Set_Team_Player_Lists);
Global.VECTOR_Ball_Spawn = Vector(-62.467, 24.228, 136.493);
Global.VECTOR_Goal_1 = Vector(-78.393, 5.630, 105.747);
Global.VECTOR_Goal_2 = Vector(-44.786, 2.221, 105.754);
Global.VECTOR_Spawn_Team_1 = Vector(-44.786, 2.221, 105.754);
Global.VECTOR_Spawn_Team_2 = Vector(-78.646, 7.020, 101.946);
Global.REAL_Map_Scale_Factor = 0.500;
}
}
rule("PLAYER: Welcome")
disabled rule("MAP: Castillo (0.75 scale)")
{
event
{
Ongoing - Each Player;
Team 1;
All;
Ongoing - Global;
}
conditions
{
Has Spawned(Event Player) == True;
Is Alive(Event Player) == True;
Event Player.BOOL_Welcomed != True;
Is Game In Progress == True;
Current Map == Map(Castillo);
}
actions
{
Big Message(Event Player, Custom String("Welcome to Reinhardt Hockey!"));
Event Player.BOOL_Welcomed = True;
Global.VECTOR_Ball_Spawn = Vector(-101.276, 60, 58.184);
Global.VECTOR_Goal_1 = Vector(-116.441, 33.125, 34.656);
Global.VECTOR_Goal_2 = Vector(-106.631, 33.328, 86.089);
Global.VECTOR_Spawn_Team_1 = Vector(-106.631, 33.328, 86.089);
Global.VECTOR_Spawn_Team_2 = Vector(-116.441, 33.125, 34.656);
Global.REAL_Map_Scale_Factor = 0.750;
}
}
rule("GAME: Begins (for TDM maps)")
rule("MAP: Castillo (0.5 scale)")
{
event
{
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Current Map == Map(Castillo);
}
actions
{
Set Slow Motion(75);
Call Subroutine(Reassign_Teams);
Call Subroutine(Reset);
Global.VECTOR_Ball_Spawn = Vector(-111.180, 33.758, 59.944);
Global.VECTOR_Goal_1 = Vector(-103.271, 33.568, 40.717);
Global.VECTOR_Goal_2 = Vector(-97.175, 33.568, 73.748);
Global.VECTOR_Spawn_Team_1 = Vector(-97.175, 33.568, 73.748);
Global.VECTOR_Spawn_Team_2 = Vector(-103.271, 33.568, 40.717);
Global.REAL_Map_Scale_Factor = 0.250;
Global.REAL_Ball_Scale = 0.200;
Global.REAL_Player_Scale = 0.750;
}
}
rule("BALL: Spawns")
disabled rule("MAP: Castillo (0.25 scale)")
{
event
{
Ongoing - Each Player;
All;
Wrecking Ball;
Ongoing - Global;
}
conditions
{
Is Alive(Event Player) == True;
Current Map == Map(Castillo);
}
actions
{
Teleport(Event Player, Global.VECTOR_Ball_Spawn);
Start Scaling Player(Event Player, Global.REAL_Ball_Scale, True);
Start Forcing Player Outlines(Event Player, All Players(All Teams), True, Color(Black), Always);
Disable Nameplates(Event Player, All Players(All Teams));
Global.VECTOR_Ball_Spawn = Vector(-101.276, 60, 58.184);
Global.VECTOR_Goal_1 = Vector(-103.271, 33.568, 40.717);
Global.VECTOR_Goal_2 = Vector(-97.175, 33.568, 73.748);
Global.VECTOR_Spawn_Team_1 = Vector(-97.175, 33.568, 73.748);
Global.VECTOR_Spawn_Team_2 = Vector(-103.271, 33.568, 40.717);
Global.REAL_Map_Scale_Factor = 0.250;
}
}
rule("PLAYER: Spawns")
rule("MAP: Ilios Lighthouse")
{
event
{
Ongoing - Each Player;
Team 1;
All;
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Is Alive(Event Player) == True;
Event Player.BOOL_Spawned == False;
Has Spawned(Event Player) == True;
Current Map == Map(Ilios Lighthouse);
}
actions
{
Event Player.BOOL_Spawned = True;
Start Forcing Player Outlines(Event Player, All Players(All Teams), True,
Event Player.INT_Team == 1 ? Global.COLOR_Blue : Global.COLOR_Red, Always);
disabled Teleport(Event Player, Event Player.INT_Team == 1 ? Global.VECTOR_Spawn_Team_1 : Global.VECTOR_Spawn_Team_2);
Set Ability Cooldown(Event Player, Button(Ability 1), 4);
Global.VECTOR_Ball_Spawn = Vector(347.647, -24.291, -46.963);
Global.VECTOR_Goal_1 = Vector(313.299, -21.326, -52.292);
Global.VECTOR_Goal_2 = Vector(327.886, -21.385, -19.250);
Global.VECTOR_Spawn_Team_1 = Vector(327.886, -21.385, -19.250);
Global.VECTOR_Spawn_Team_2 = Vector(313.299, -21.326, -52.292);
Global.REAL_Ball_Scale = 0.200;
Global.REAL_Player_Scale = 0.750;
}
}
rule("PLAYER: Dies")
disabled rule("MAP: Busan (Meka Base)")
{
event
{
Player Died;
Team 1;
All;
Ongoing - Global;
}
conditions
{
Current Map == Map(Busan);
}
actions
{
Event Player.BOOL_Spawned = False;
Global.VECTOR_Ball_Spawn = Vector(222.685, 20, 242.116);
Global.VECTOR_Goal_1 = Vector(244.659, 22.729, 224.139);
Global.VECTOR_Goal_2 = Vector(194.023, 22.732, 246.254);
Global.VECTOR_Spawn_Team_1 = Vector(203.287, 14.717, 242.208);
Global.VECTOR_Spawn_Team_2 = Vector(236.174, 14.717, 228.219);
Global.REAL_Goal_Height_Team_1 = 6;
Global.REAL_Goal_Height_Team_2 = 3;
}
}
rule("PLAYER: Skating (new, movement vector-based)")
rule("MAP: Busan (downtown)")
{
event
{
Ongoing - Each Player;
Team 1;
All;
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Is Alive(Event Player) == True;
Current Map == Map(Busan);
}
actions
{
Event Player.INT_Movement_Angle = Angle Between Vectors(Direction Towards(Event Player.VECTOR_Last_Position, Position Of(
Event Player)), Event Player.VECTOR_Movement);
disabled Event Player.INT_Movement_Angle = Angle Between Vectors(Event Player.VECTOR_Movement, Direction Towards(
Event Player.VECTOR_Last_Position, Position Of(Event Player)));
"Reset when not moving."
If(!Is Moving(Event Player));
Event Player.INT_Move_Speed = Global.INT_Movement_Speed_Min;
Event Player.BOOL_Decelerating = False;
Else;
"Reduce speed if turn too sharp."
If(Event Player.INT_Movement_Angle > Global.INT_Max_Turn_Degrees);
Event Player.REAL_Decel_Factor = 1 - Event Player.INT_Movement_Angle * Global.REAL_Decel_Factor;
disabled Event Player.REAL_Decel_Factor = Event Player.INT_Movement_Angle * Global.REAL_Decel_Factor;
Event Player.INT_Move_Speed = Max(Global.INT_Movement_Speed_Min, Event Player.INT_Move_Speed * Event Player.REAL_Decel_Factor);
Event Player.BOOL_Decelerating = True;
"Increase speed."
Else;
Event Player.INT_Move_Speed = Min(Global.INT_Movement_Speed_Max, Event Player.INT_Move_Speed * Global.REAL_Accel_Factor);
Event Player.BOOL_Decelerating = False;
End;
End;
"Update move speed."
Set Move Speed(Event Player, Event Player.INT_Move_Speed);
Event Player.VECTOR_Movement = Direction Towards(Event Player.VECTOR_Last_Position, Position Of(Event Player));
"Finally, update variables."
Event Player.VECTOR_Last_Position = Position Of(Event Player);
"Loop while alive."
Wait(0.050, Ignore Condition);
Loop If Condition Is True;
Global.VECTOR_Ball_Spawn = Vector(51.961, 16.124, -115.398);
Global.VECTOR_Goal_1 = Vector(38.604, 20, -97.415);
Global.VECTOR_Goal_2 = Vector(65.176, 20, -97.446);
Global.VECTOR_Spawn_Team_1 = Vector(76.189, 14.275, -117.395);
Global.VECTOR_Spawn_Team_2 = Vector(27.435, 14.336, -116.676);
Global.REAL_Goal_Height_Team_1 = 6;
Global.REAL_Goal_Height_Team_2 = 3;
Global.REAL_Map_Scale_Factor = 1;
}
}
rule("BALL: Pinned")
rule("MAP: Havana")
{
event
{
Ongoing - Global;
}
conditions
{
Current Map == Map(Havana);
}
actions
{
Global.VECTOR_Ball_Spawn = Vector(-38.271, 10.113, -70.916);
Global.VECTOR_Goal_1 = Vector(-3.084, 14.075, -78.539);
Global.VECTOR_Goal_2 = Vector(-45.039, 11.611, -43.153);
Global.VECTOR_Spawn_Team_1 = Vector(-42.384, 7.471, -49.097);
Global.VECTOR_Spawn_Team_2 = Vector(-14.661, 7.618, -84.824);
Global.REAL_Goal_Height_Team_1 = 5;
Global.REAL_Goal_Height_Team_2 = 4;
Global.REAL_Map_Scale_Factor = 1;
}
}
rule("INIT:")
{
event
{
Ongoing - Global;
}
conditions
{
Global.BOOL_Initialized != True;
}
actions
{
Global.BOOL_Initialized = True;
Global.STRINGS_Tips = Array(Custom String("Keep your momentum by turning slowly."), Custom String(
"Slow is smooth, smooth is fast."), Custom String("Speed is life."), Custom String("Skate not to where the puck is."),
Custom String("Skate to where the puck will be."), Custom String("You miss 100% of the shots you don't take."), Custom String(
"Fun fact: Hockey was invented by a penguin rancher."), Custom String("Don't be a ball hog. Pass it!"), Custom String(
"There's no jumping in hockey!"));
Global.REAL_Accel_Factor = Workshop Setting Real(Custom String("Movement"), Custom String(
"Acceleration factor (when not turning sharply)"), 1.030, 1, 1.100, 0);
Global.INT_Max_Turn_Degrees = Workshop Setting Integer(Custom String("Movement"), Custom String(
"Max turn (degrees) (speed reduces with sharper turns)"), 5, 0, 360, 0);
Global.INT_Movement_Speed_Max = Workshop Setting Integer(Custom String("Movement"), Custom String("Max movement speed (percent)"),
175, 10, 500, 0);
Global.INT_Movement_Speed_Min = Workshop Setting Integer(Custom String("Movement"), Custom String("Min movement speed (percent)"),
50, 10, 200, 0);
Global.STRINGS_Scored_2 = Array(Custom String("Score!"), Custom String("Boom, shakalaka!"), Custom String("Nothing but net!"),
Custom String("He shoots, he scores!"), Custom String("Swish!"));
Global.STRINGS_Scored_3 = Array(Custom String("From downtown!"), Custom String("Three!"), Custom String("For three!"),
Custom String("From beyond the arc!"));
disabled Global.INT_Three_Pointer_Distance = Workshop Setting Integer(Custom String("Settings"), Custom String(
"3-pointer distance (meters)"), 20, 5, 100, 0);
Global.REAL_Goal_Radius = Workshop Setting Real(Custom String("Settings"), Custom String("Goal radius (meters)"), 3, 1, 10, 0);
disabled Global.REAL_Ball_Scale_Percent = Workshop Setting Integer(Custom String("Settings"), Custom String("Ball scale (percent)"), 100,
10, 200, 1);
"NOTE: Disabled because the setting sliders only allow 2 decimal digits of precision, and we need 3. (sigh)"
disabled Global.REAL_Decel_Factor = Workshop Setting Real(Custom String("Movement"), Custom String(
"Deceleration factor (when turning sharply)"), 0.004, 0, 0.010, 0);
"FIXME: If Workshop real number sliders are changed to allow 3 decimal digits, move this setting back to one."
Global.REAL_Decel_Factor = 0.004;
Global.PLAYERS_Team_1 = Empty Array;
Global.PLAYERS_Team_2 = Empty Array;
"Dummy bot (basketball)."
Create Dummy Bot(Hero(Wrecking Ball), Team 2, -1, Global.VECTOR_Ball_Spawn, Vector(0, 0, 0));
Global.PLAYER_Ball = Last Created Entity;
Create Icon(All Players(All Teams), Global.PLAYER_Ball, Circle, Visible To and Position, Color(Orange), True);
Start Forcing Dummy Bot Name(Global.PLAYER_Ball, Custom String("Ball"));
Start Forcing Player Outlines(Global.PLAYER_Ball, All Players(Team 1), True, Color(Yellow), Always);
Start Scaling Player(Global.PLAYER_Ball, Global.REAL_Map_Scale_Factor * 0.500, False);
"Goals."
Create Effect(Global.PLAYERS_Team_1, Sphere, Color(Blue), Global.VECTOR_Goal_1, Global.REAL_Goal_Radius, Visible To);
Create Effect(Global.PLAYERS_Team_1, Sphere, Color(Red), Global.VECTOR_Goal_2, Global.REAL_Goal_Radius, Visible To);
Create Effect(Global.PLAYERS_Team_2, Sphere, Color(Red), Global.VECTOR_Goal_2, Global.REAL_Goal_Radius, Visible To);
Create Effect(Global.PLAYERS_Team_2, Sphere, Color(Blue), Global.VECTOR_Goal_1, Global.REAL_Goal_Radius, Visible To);
disabled Create Effect(All Players(All Teams), Sphere, Color(Gray), Global.VECTOR_Goal_1, Global.INT_Three_Pointer_Distance,
Visible To Position and Radius);
disabled Create Effect(All Players(All Teams), Sphere, Color(Gray), Global.VECTOR_Goal_2, Global.INT_Three_Pointer_Distance,
Visible To Position and Radius);
Create In-World Text(Global.PLAYERS_Team_1, Custom String("DEFEND"), Global.VECTOR_Goal_2, 1, Do Not Clip, Visible To, Color(
White), Visible Never);
Create In-World Text(Global.PLAYERS_Team_1, Custom String("SCORE"), Global.VECTOR_Goal_1, 1, Do Not Clip, Visible To, Color(White),
Visible Never);
Create In-World Text(Global.PLAYERS_Team_2, Custom String("DEFEND"), Global.VECTOR_Goal_1, 1, Do Not Clip, Visible To, Color(
White), Visible Never);
Create In-World Text(Global.PLAYERS_Team_2, Custom String("SCORE"), Global.VECTOR_Goal_2, 1, Do Not Clip, Visible To, Color(White),
Visible Never);
"HUD."
Create HUD Text(All Players(All Teams), Custom String("Share code"), Custom String("https://workshop.codes/reinhardt-hockey"),
Custom String("QBHWR"), Left, -1, Color(White), Color(Turquoise), Color(White), Visible To and String, Default Visibility);
Create HUD Text(All Players(All Teams), Custom String("TEAM COLOR"), Null, Null, Top, 0, Local Player.INT_Team == 1 ? Color(Blue)
: Color(Red), Color(White), Null, Visible To String and Color, Default Visibility);
Create HUD Text(All Players(Team 1), Custom String("SPEED"), Custom String("Turning sharply slows down"), Custom String(
"{0} ({2}%)", Local Player.BOOL_Decelerating ? Custom String("Decreasing") : (Is Moving(Local Player) ? Custom String(
"Increasing") : Custom String("")), Local Player.INT_Movement_Angle, Local Player.INT_Move_Speed), Left, 0,
Local Player.BOOL_Decelerating ? Color(Red) : (Is Moving(Local Player) ? Color(Green) : Color(White)), Color(Turquoise), Color(
White), Visible To String and Color, Default Visibility);
Set Objective Description(All Players(All Teams), Custom String("Reinhardt Hockey"), Visible To and String);
Disable Built-In Game Mode Scoring;
Call Subroutine(Reset);
}
}
rule("BALL: Spawns")
{
event
{
Ongoing - Each Player;
All;
Wrecking Ball;
}
conditions
{
Has Status(Event Player, Stunned) == True;
Is Alive(Event Player) == True;
}
actions
{
Global.PLAYER_Last_Touched = Closest Player To(Position Of(Event Player), Team 1);
Wait(0.250, Ignore Condition);
"Don't cancel swinging of Reinhardt who just shattered."
If(!Is Button Held(Global.PLAYER_Last_Touched, Button(Primary Fire)));
Cancel Primary Action(Global.PLAYER_Last_Touched);
End;
Loop If Condition Is True;
Teleport(Event Player, Global.VECTOR_Ball_Spawn);
Start Scaling Player(Event Player, Global.REAL_Ball_Scale, True);
Start Forcing Player Outlines(Event Player, All Players(All Teams), True, Color(Orange), Always);
}
}
rule("BALL: Shattered")
rule("PLAYER: Joins (assign to team)")
{
event
{
Player Took Damage;
Player Joined Match;
Team 1;
All;
Wrecking Ball;
}
conditions
{
Is Using Ultimate(Attacker) == True;
Global.BOOL_Initialized == True;
}
actions
{
Global.PLAYER_Last_Touched = Closest Player To(Position Of(Event Player), Team 1);
Apply Impulse(Event Player, Vector(0, 1, 0), 10, To World, Cancel Contrary Motion);
If(Count Of(Global.PLAYERS_Team_1) <= Count Of(Global.PLAYERS_Team_2));
Modify Global Variable(PLAYERS_Team_1, Append To Array, Event Player);
Event Player.INT_Team = 1;
Else;
Modify Global Variable(PLAYERS_Team_2, Append To Array, Event Player);
Event Player.INT_Team = 2;
End;
Start Scaling Player(Event Player, Global.REAL_Player_Scale, False);
Event Player.BOOL_Spawned = False;
}
}
rule("BALL: Gets hit")
rule("GLOBAL: Reassign teams when uneven")
{
event
{
Player Took Damage;
Team 2;
Wrecking Ball;
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Count Of(All Players(Team 1)) % 2 != 0;
Absolute Value(Count Of(Filtered Array(All Players(Team 1), Current Array Element.INT_Team == 1)) - Filtered Array(All Players(
Team 1), Current Array Element.INT_Team == 2)) != 1;
Global.BOOL_Goal_Just_Scored == True;
}
actions
{
Global.PLAYER_Last_Touched = Attacker;
Small Message(All Players(All Teams), Custom String("Player left. Reassigning teams..."));
Wait(2, Ignore Condition);
Call Subroutine(Reassign_Teams);
Call Subroutine(Reset);
}
}
rule("BALL: Team 1 scores (disable when setting up new map)")
{
event
{
Ongoing - Each Player;
All;
Wrecking Ball;
}
conditions
{
Distance Between(Event Player, Global.VECTOR_Goal_1) < Global.REAL_Goal_Radius;
}
actions
{
Small Message(All Players(All Teams), Custom String("{0} scored!", Global.PLAYER_Last_Touched));
Disable Built-In Game Mode Respawning(Global.PLAYER_Ball);
Kill(Global.PLAYER_Ball, Null);
Play Effect(All Players(All Teams), Ring Explosion Sound, Color(Turquoise), Global.VECTOR_Goal_1, 10);
Play Effect(All Players(All Teams), Ring Explosion, Global.COLOR_Blue, Global.VECTOR_Goal_1, 10);
Play Effect(All Players(All Teams), Ring Explosion, Color(Turquoise), Global.VECTOR_Goal_1, 10);
Modify Team Score(Team 1, Distance Between(Global.VECTOR_Last_Shot_From, Global.VECTOR_Goal_1)
> Global.INT_Three_Pointer_Distance ? 2 : 1);
Big Message(All Players(All Teams), Random Value In Array(Distance Between(Global.VECTOR_Goal_1, Global.VECTOR_Last_Shot_From)
> Global.INT_Three_Pointer_Distance ? Global.STRINGS_Scored_3 : Global.STRINGS_Scored_2));
Global.BOOL_Goal_Just_Scored = True;
Wait(3, Ignore Condition);
Call Subroutine(Reset);
}
}
rule("BALL: Team 2 scores (disable when setting up new map)")
{
event
{
Ongoing - Each Player;
All;
Wrecking Ball;
}
conditions
{
Distance Between(Event Player, Global.VECTOR_Goal_2) < Global.REAL_Goal_Radius;
}
actions
{
Small Message(All Players(All Teams), Custom String("{0} scored!", Global.PLAYER_Last_Touched));
Disable Built-In Game Mode Respawning(Global.PLAYER_Ball);
Kill(Global.PLAYER_Ball, Null);
Play Effect(All Players(All Teams), Ring Explosion Sound, Color(Turquoise), Global.VECTOR_Goal_2, 10);
Play Effect(All Players(All Teams), Ring Explosion, Global.COLOR_Red, Global.VECTOR_Goal_2, 10);
Play Effect(All Players(All Teams), Ring Explosion, Color(Turquoise), Global.VECTOR_Goal_2, 10);
Modify Team Score(Team 2, Distance Between(Global.VECTOR_Last_Shot_From, Global.VECTOR_Goal_2)
> Global.INT_Three_Pointer_Distance ? 2 : 1);
Big Message(All Players(All Teams), Random Value In Array(Distance Between(Global.VECTOR_Goal_2, Global.VECTOR_Last_Shot_From)
> Global.INT_Three_Pointer_Distance ? Global.STRINGS_Scored_3 : Global.STRINGS_Scored_2));
Global.BOOL_Goal_Just_Scored = True;
Wait(3, Ignore Condition);
Call Subroutine(Reset);
}
}
rule("GLOBAL: Reassign teams when uneven")
rule("SUBR: Reset (disable when setting up new map)")
{
event
{
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
(Absolute Value(Count Of(Filtered Array(All Players(Team 1), Current Array Element.INT_Team == 1)) - Count Of(Filtered Array(
All Players(Team 1), Current Array Element.INT_Team == 2))) != 1 && Absolute Value(Count Of(Filtered Array(All Players(Team 1),
Current Array Element.INT_Team == 1)) - Count Of(Filtered Array(All Players(Team 1), Current Array Element.INT_Team == 2)))
!= 0) == True;
Global.BOOL_Goal_Just_Scored == True;
Subroutine;
Reset;
}
actions
{
Small Message(All Players(All Teams), Custom String("Player left. Reassigning teams..."));
Wait(2, Ignore Condition);
Call Subroutine(Reassign_Teams);
Call Subroutine(Reset);
disabled Small Message(Host Player, Custom String("argh: {0} {1}", Absolute Value(Count Of(Filtered Array(All Players(Team 1),
Current Array Element.INT_Team == 1)) - Count Of(Filtered Array(All Players(Team 1), Current Array Element.INT_Team == 2))),
Absolute Value(Count Of(Filtered Array(All Players(Team 1), Current Array Element.INT_Team == 1)) - Count Of(Filtered Array(
All Players(Team 1), Current Array Element.INT_Team == 2)))));
Enable Built-In Game Mode Respawning(Global.PLAYER_Ball);
Global.BOOL_Goal_Just_Scored = False;
Global.PLAYERS_All.BOOL_Spawned = False;
Respawn(All Players(All Teams));
Wait Until(Is True For All(All Players(All Teams), Is Alive(Current Array Element) && Has Spawned(Current Array Element)), 99999);
"Seems to be necessary, otherwise players don't get teleported after respawning (one would hope that WAIT UNTIL would work as advertised, sigh)."
Wait(0.016, Ignore Condition);
Teleport(Global.PLAYER_Ball, Global.VECTOR_Ball_Spawn);
Teleport(Global.PLAYERS_Team_1, Global.VECTOR_Spawn_Team_1);
Teleport(Global.PLAYERS_Team_2, Global.VECTOR_Spawn_Team_2);
disabled Start Forcing Player Position(Global.PLAYER_Ball, Global.VECTOR_Ball_Spawn, False);
disabled Wait(0.250, Ignore Condition);
disabled Stop Forcing Player Position(Global.PLAYER_Ball);
Set Facing(Global.PLAYERS_Team_1, Direction Towards(Global.VECTOR_Spawn_Team_1, Position Of(Global.PLAYER_Ball)), To World);
Set Facing(Global.PLAYERS_Team_2, Direction Towards(Global.VECTOR_Spawn_Team_2, Position Of(Global.PLAYER_Ball)), To World);
Small Message(All Players(Team 1), Random Value In Array(Global.STRINGS_Tips));
}
}
rule("BALL: Wind (keep it in bounds on Island) (DO NOT MOVE THIS RULE, WHO KNOWS WHY BUT THE ORDER SEEMS TO MATTER)")
rule("DEBUG: Teleport")
{
event
{
Ongoing - Global;
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Game In Progress == True;
Global.REAL_Wind_Bounds != 0;
Global.BOOL_Boards == False;
"OLD: Hard-coded."
disabled (X Component Of(Position Of(Global.PLAYER_Ball)) > 20 || X Component Of(Position Of(Global.PLAYER_Ball)) < -20 || Z Component Of(
Position Of(Global.PLAYER_Ball)) > 20 || Z Component Of(Position Of(Global.PLAYER_Ball)) < -20) == True;
"NEW: Per-map."
(X Component Of(Position Of(Global.PLAYER_Ball)) > X Component Of(Global.LINES_Bounds[3][0]) || X Component Of(Position Of(
Global.PLAYER_Ball)) < X Component Of(Global.LINES_Bounds[1][0]) || Z Component Of(Position Of(Global.PLAYER_Ball))
> Z Component Of(Global.LINES_Bounds[0][0]) || Z Component Of(Position Of(Global.PLAYER_Ball)) < Z Component Of(
Global.LINES_Bounds[2][0])) == True;
Is Button Held(Event Player, Button(Interact)) == True;
Event Player == Host Player;
}
actions
{
disabled Wait(1, Ignore Condition);
disabled Loop If Condition Is True;
Apply Impulse(Global.PLAYER_Ball, Vector(0, Global.REAL_Wind_Y, 0) + Direction Towards(Position Of(Global.PLAYER_Ball),
Global.VECTOR_Ball_Last_Position), Speed Of(Global.PLAYER_Ball) / 2, To World, Cancel Contrary Motion XYZ);
Teleport(Event Player, Position Of(Event Player) + Facing Direction Of(Event Player) * 10);
}
}
rule("BALL: Boards (keep it in bounds on Expanse) (DO NOT MOVE THIS RULE, WHO KNOWS WHY BUT THE ORDER SEEMS TO MATTER)")
rule("GAME: Begins (for TDM maps)")
{
event
{
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Global.BOOL_Boards == True;
"NEW: Per-map."
(X Component Of(Position Of(Global.PLAYER_Ball)) > X Component Of(Global.LINES_Bounds[3][0]) || X Component Of(Position Of(
Global.PLAYER_Ball)) < X Component Of(Global.LINES_Bounds[1][0]) || Z Component Of(Position Of(Global.PLAYER_Ball))
> Z Component Of(Global.LINES_Bounds[0][0]) || Z Component Of(Position Of(Global.PLAYER_Ball)) < Z Component Of(
Global.LINES_Bounds[2][0])) == True;
}
actions
{
disabled Wait(1, Ignore Condition);
disabled Loop If Condition Is True;
disabled Apply Impulse(Global.PLAYER_Ball, Vector(0, Global.REAL_Wind_Y, 0) + Direction Towards(Position Of(Global.PLAYER_Ball),
Global.VECTOR_Ball_Last_Position), Speed Of(Global.PLAYER_Ball) / 2, To World, Incorporate Contrary Motion);
If(X Component Of(Position Of(Global.PLAYER_Ball)) > X Component Of(Global.LINES_Bounds[3][0]));
Apply Impulse(Global.PLAYER_Ball, Vector(-1, 0, 0), Speed Of(Global.PLAYER_Ball), To World, Incorporate Contrary Motion);
Else If(X Component Of(Position Of(Global.PLAYER_Ball)) < X Component Of(Global.LINES_Bounds[1][0]));
Apply Impulse(Global.PLAYER_Ball, Vector(1, 0, 0), Speed Of(Global.PLAYER_Ball), To World, Incorporate Contrary Motion);
Else If(Z Component Of(Position Of(Global.PLAYER_Ball)) > Z Component Of(Global.LINES_Bounds[0][0]));
Apply Impulse(Global.PLAYER_Ball, Vector(0, 0, -1), Speed Of(Global.PLAYER_Ball), To World, Incorporate Contrary Motion);
Else If(Z Component Of(Position Of(Global.PLAYER_Ball)) < Z Component Of(Global.LINES_Bounds[2][0]));
Apply Impulse(Global.PLAYER_Ball, Vector(0, 0, 1), Speed Of(Global.PLAYER_Ball), To World, Incorporate Contrary Motion);
End;
Set Slow Motion(75);
Call Subroutine(Reset);
}
}
rule("BALL: Failsafe (keep it in bounds on Expanse) (DO NOT MOVE THIS RULE, WHO KNOWS WHY BUT THE ORDER SEEMS TO MATTER)")
rule("PLAYER: Dies")
{
event
{
Ongoing - Global;
}
conditions
{
Global.BOOL_Boards == True;
Is Game In Progress == True;
Is Alive(Global.PLAYER_Ball) == True;
Has Spawned(Global.PLAYER_Ball) == True;
Is On Ground(Global.PLAYER_Ball) == True;
"NEW: Per-map."
(X Component Of(Position Of(Global.PLAYER_Ball)) > X Component Of(Global.LINES_Outer_Bounds[3][0]) || X Component Of(Position Of(
Global.PLAYER_Ball)) < X Component Of(Global.LINES_Outer_Bounds[1][0]) || Z Component Of(Position Of(Global.PLAYER_Ball))
> Z Component Of(Global.LINES_Outer_Bounds[0][0]) || Z Component Of(Position Of(Global.PLAYER_Ball)) < Z Component Of(
Global.LINES_Outer_Bounds[2][0])) == True;
Player Died;
Team 1;
All;
}
actions
{
Wait(2, Abort When False);
Kill(Global.PLAYER_Ball, Null);
disabled Respawn(Global.PLAYER_Ball);
Event Player.BOOL_Spawned = False;
}
}
rule("BALL: Update last position (DO NOT MOVE THIS RULE, WHO KNOWS WHY BUT THE ORDER SEEMS TO MATTER)")
rule("PLAYER: Spawns")
{
event
{
Ongoing - Global;
Ongoing - Each Player;
Team 1;
All;
}
conditions
{
Is Game In Progress == True;
Is Alive(Event Player) == True;
Event Player.BOOL_Spawned == False;
Has Spawned(Event Player) == True;
}
actions
{
Global.VECTOR_Ball_Last_Position = Position Of(Global.PLAYER_Ball);
Wait(0.016, Ignore Condition);
Loop If Condition Is True;
Event Player.BOOL_Spawned = True;
Start Forcing Player Outlines(Event Player, All Players(All Teams), True, Event Player.INT_Team == 1 ? Color(Blue) : Color(Red),
Always);
Teleport(Event Player, Event Player.INT_Team == 1 ? Global.VECTOR_Spawn_Team_1 : Global.VECTOR_Spawn_Team_2);
}
}
rule("SUBR: Reset (disable when setting up new map)")
disabled rule("PLAYER: Phased out while charging")
{
event
{
Subroutine;
Reset;
}
actions
{
Enable Built-In Game Mode Respawning(Global.PLAYER_Ball);
Global.PLAYER_Last_Touched = Null;
Global.BOOL_Goal_Just_Scored = False;
Global.PLAYERS_All.BOOL_Spawned = False;
Respawn(All Players(All Teams));
Wait Until(Is True For All(All Players(All Teams), Is Alive(Current Array Element) && Has Spawned(Current Array Element)), 99999);
"Seems to be necessary, otherwise players don't get teleported after respawning (one would hope that WAIT UNTIL would work as advertised, sigh). On second thought, this seems to utterly stop execution of this subr?!"
disabled Wait(0.250, Ignore Condition);
Teleport(Global.PLAYER_Ball, Global.VECTOR_Ball_Spawn);
Call Subroutine(Teleport_Players);
Small Message(All Players(Team 1), Random Value In Array(Global.STRINGS_Tips));
Set Ability Cooldown(All Players(Team 1), Button(Ability 1), 4);
Ongoing - Each Player;
All;
Reinhardt;
}
}
rule("SUBR: Teleport_Players")
{
event
conditions
{
Subroutine;
Teleport_Players;
Is Using Ability 1(Event Player) == True;
}
actions
{
"BUG: Without this SMALL MESSAGE, this subr fails to teleport players. With the small message, it works. ?!?!?!?! But an empty message doesn't! We have to use a non-empty, non-whitespace-only string!!?"
disabled Small Message(All Players(All Teams), Custom String("Face-off!"));
For Global Variable(INT_Loop_Control, 0, Count Of(Global.PLAYERS_Team_1), 1);
Teleport(Global.PLAYERS_Team_1[Global.INT_Loop_Control], Global.VECTORS_Spawns[0][Global.INT_Loop_Control]);
Set Facing(Global.PLAYERS_Team_1[Global.INT_Loop_Control], Direction Towards(Position Of(
Global.PLAYERS_Team_1[Global.INT_Loop_Control]), Global.VECTOR_Ball_Spawn), To World);
End;
For Global Variable(INT_Loop_Control, 0, Count Of(Global.PLAYERS_Team_2), 1);
Teleport(Global.PLAYERS_Team_2[Global.INT_Loop_Control], Global.VECTORS_Spawns[1][Global.INT_Loop_Control]);
Set Facing(Global.PLAYERS_Team_2[Global.INT_Loop_Control], Direction Towards(Position Of(
Global.PLAYERS_Team_2[Global.INT_Loop_Control]), Global.VECTOR_Ball_Spawn), To World);
End;
Set Status(Event Player, Null, Phased Out, 9999);
}
}
rule("SUBR: Reassign Teams")
disabled rule("PLAYER: Not phased out while not charging")
{
event
{
Subroutine;
Reassign_Teams;
Ongoing - Each Player;
All;
Reinhardt;
}
conditions
{
Is Using Ability 1(Event Player) == False;
}
actions
{
Global.PLAYERS_All = All Players(Team 1);
disabled Global.PLAYERS_Team_1 = Empty Array;
disabled Global.PLAYERS_Team_2 = Empty Array;
For Global Variable(INT_Loop_Control, 0, Count Of(Global.PLAYERS_All), 1);
If(Count Of(Filtered Array(All Players(Team 1), Current Array Element.INT_Team == 1)) <= Count Of(Filtered Array(All Players(
Team 1), Current Array Element.INT_Team == 2)));
Global.PLAYERS_All[Global.INT_Loop_Control].INT_Team = 1;
Else;
Global.PLAYERS_All[Global.INT_Loop_Control].INT_Team = 2;
End;
End;
Call Subroutine(Set_Team_Player_Lists);
Small Message(Global.PLAYERS_Team_1, Custom String("You're on blue team."));
Small Message(Global.PLAYERS_Team_2, Custom String("You're on red team."));
Clear Status(Event Player, Phased Out);
}
}
rule("DEBUG: Current vector")
rule("BALL: Pinned")
{
event
{
Ongoing - Global;
Ongoing - Each Player;
All;
Wrecking Ball;
}
conditions
{
Is Game In Progress == True;
Has Status(Event Player, Stunned) == True;
}
actions
{
Create HUD Text(Host Player, Custom String("POSITION"), Null, Position Of(Host Player), Right, 0, Color(White), Color(White),
Color(White), Visible To and String, Default Visibility);
Wait(0.250, Ignore Condition);
Cancel Primary Action(Closest Player To(Event Player, Team 1));
Loop If Condition Is True;
}
}
disabled rule("DEBUG: Corner effect (WIP)")
rule("BALL: Shattered")
{
event
{
Ongoing - Global;
Player Took Damage;
All;
Wrecking Ball;
}
conditions
{
Is Game In Progress == True;
Is Using Ultimate(Attacker) == True;
}
actions
{
Create Effect(All Players(All Teams), Ring, Color(White), Vector(15, 0, 15), 5, Visible To);
Apply Impulse(Event Player, Vector(0, 1, 0), 10, To World, Cancel Contrary Motion);
}
}
disabled rule("BALL: In corners (pretend they're rounded) (WIP)")
rule("PLAYER: Welcome")
{
event
{
Ongoing - Each Player;
Team 2;
Wrecking Ball;
Team 1;
All;
}
conditions
{
Is Game In Progress == True;
X Component Of(Position Of(Global.PLAYER_Ball)) > 15;
Z Component Of(Position Of(Global.PLAYER_Ball)) > 15;
Has Spawned(Event Player) == True;
Is Alive(Event Player) == True;
Event Player.BOOL_Welcomed != True;
Is Game In Progress == True;
}
actions
{
Apply Impulse(Event Player, Direction Towards(Position Of(Event Player), Vector(15, 0, 15)), 0.100 * Speed Of In Direction(
Event Player, Direction Towards(Position Of(Event Player), Vector(15, 0, 15))), To World, Incorporate Contrary Motion);
disabled Apply Impulse(Event Player, Direction Towards(Position Of(Event Player), Vector(15, 0, 15)), Speed Of In Direction(Event Player,
Direction Towards(Position Of(Event Player), Vector(15, 0, 15))), To World, Incorporate Contrary Motion);
Wait(0.016, Ignore Condition);
Loop If Condition Is True;
Big Message(Event Player, Custom String("Welcome to Reinhardt Hockey!"));
Event Player.BOOL_Welcomed = True;
}
}
rule("SUBR: Set_Team_Player_Lists")
rule("SUBR: Reassign Teams")
{
event
{
Subroutine;
Set_Team_Player_Lists;
Reassign_Teams;
}
actions
{
Global.PLAYERS_Team_1 = Empty Array;
Global.PLAYERS_Team_2 = Empty Array;
Global.PLAYERS_All = All Players(Team 1);
For Global Variable(INT_Loop_Control, 0, Count Of(Global.PLAYERS_All), 1);
If(Global.PLAYERS_All[Global.INT_Loop_Control].INT_Team == 1);
If(Count Of(Global.PLAYERS_Team_1) <= Count Of(Global.PLAYERS_Team_2));
Modify Global Variable(PLAYERS_Team_1, Append To Array, Global.PLAYERS_All[Global.INT_Loop_Control]);
Global.PLAYERS_All[Global.INT_Loop_Control].INT_Team = 1;
Else;
Modify Global Variable(PLAYERS_Team_2, Append To Array, Global.PLAYERS_All[Global.INT_Loop_Control]);
Global.PLAYERS_All[Global.INT_Loop_Control].INT_Team = 2;
End;
End;
}
}
rule("SUBR: Create_Effects")
{
event
{
Subroutine;
Create_Effects;
}
actions
{
If(Global.LINES_Bounds != 0);
For Global Variable(INT_Loop_Control, 0, Count Of(Global.LINES_Bounds), 1);
Create Beam Effect(All Players(All Teams), Good Beam, Global.LINES_Bounds[Global.INT_Loop_Control][0],
Global.LINES_Bounds[Global.INT_Loop_Control][1], Color(Yellow), Visible To);
End;
End;
}
}
rule("BALL: Portal")
{
event
{
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Is True For Any(Global.VECTORS_Portals, Distance Between(Position Of(Global.PLAYER_Ball), Current Array Element)
< Global.REAL_Portal_Radius) == True;
}
actions
{
Global.LOCAL_VECTOR_Portal = Distance Between(Position Of(Global.PLAYER_Ball), Global.VECTORS_Portals[0])
< Global.REAL_Portal_Radius ? Global.VECTORS_Portals[0] : Global.VECTORS_Portals[1];
Play Effect(All Players(All Teams), Ring Explosion, Global.COLORS_Portals[0], Global.VECTORS_Portals[0], 3);
Play Effect(All Players(All Teams), Ring Explosion, Global.COLORS_Portals[1], Global.VECTORS_Portals[1], 3);
Teleport(Global.PLAYER_Ball, First Of(Filtered Array(Global.VECTORS_Portals, Current Array Element != Global.LOCAL_VECTOR_Portal))
+ Vector(1.500, 0, 1.500) * Direction Towards(Position Of(Global.PLAYER_Ball), Global.LOCAL_VECTOR_Portal));
}
}
rule("INIT: Draw portals")
rule("BALL: Update last position")
{
event
{
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Global.VECTORS_Portals != 0;
}
actions
{
For Global Variable(INT_Loop_Control, 0, Count Of(Global.VECTORS_Portals), 1);
Create Effect(Global.PLAYERS_All, Sphere, Global.COLORS_Portals[Global.INT_Loop_Control],
Global.VECTORS_Portals[Global.INT_Loop_Control], Global.REAL_Portal_Radius, Visible To);
End;
}
}
rule("BALL: Antigravity")
{
event
{
Ongoing - Global;
Ongoing - Each Player;
All;
Wrecking Ball;
}
conditions
{
Is Game In Progress == True;
Global.VECTORS_Antigravity != 0;
Is True For Any(Global.VECTORS_Antigravity, Distance Between(Position Of(Global.PLAYER_Ball), Current Array Element)
< Global.REAL_Portal_Radius) == True;
}
actions
{
Global.LOCAL_VECTOR_Portal = First Of(Sorted Array(Global.VECTORS_Antigravity, Distance Between(Position Of(Global.PLAYER_Ball),
Current Array Element)));
Apply Impulse(Global.PLAYER_Ball, Direction Towards(Global.LOCAL_VECTOR_Portal, Position Of(Global.PLAYER_Ball)), 0.500, To World,
Incorporate Contrary Motion);
Wait(0.050, Ignore Condition);
Global.VECTOR_Ball_Last_Position = Position Of(Event Player);
Wait(0.016, Ignore Condition);
Loop If Condition Is True;
}
}
rule("INIT: Draw antigravity")
rule("PLAYER: Leaves")
{
event
{
Ongoing - Global;
}
conditions
{
Is Game In Progress == True;
Global.VECTORS_Antigravity != 0;
Player Left Match;
Team 1;
All;
}
actions
{
For Global Variable(INT_Loop_Control, 0, Count Of(Global.VECTORS_Antigravity), 1);
Create Effect(Global.PLAYERS_All, Sphere, Color(Gray), Global.VECTORS_Antigravity[Global.INT_Loop_Control],
Global.REAL_Portal_Radius, Visible To);
End;
Global.PLAYERS_All = All Players(Team 1);
}
}