Create
Return to post

Comparing difference between and

View raw
  • settings
  • {
  • main
  • {
  • Description: "Select TWO heroes instead of one! Switch between your heroes during combat, each hero has a separate health pool, ult charge, and cooldowns! Created by BluJay#11583 v1.2"
  • Description: "Select TWO heroes instead of one! Switch between your heroes during combat, each hero has a separate health pool, ult charge, and cooldowns! Created by BluJay#11583 v1.2.1"
  • }
  • lobby
  • {
  • Allow Players Who Are In Queue: Yes
  • Map Rotation: After A Game
  • Return To Lobby: Never
  • }
  • modes
  • {
  • Assault
  • Control
  • Escort
  • Hybrid
  • General
  • {
  • Game Mode Start: Immediately
  • Hero Limit: Off
  • }
  • }
  • }
  • variables
  • {
  • global:
  • 0: ActiveSwapChargeRate
  • 1: PassiveSwapChargeRate
  • 2: HeroesWithResourceBar
  • 3: HealingInBackground
  • 4: HeroesWithSecondaryAbilityCD
  • 5: Ability1CDs
  • 6: Ability2CDs
  • 7: RightclickCDs
  • 8: HeroesWithAbility1Charges
  • 9: HeroesWithAbility2Charges
  • 10: HeroesWithCrouchAbility
  • 11: HeroesWithJumpAbility
  • 12: ReloadInBackground
  • 13: HealingInBackgroundDelay
  • 14: AllowHeroSwapping
  • 15: ChargeHeroSwapInSpawn
  • 16: CancelSwapAllowed
  • 17: Version
  • 18: VersionHud
  • 19: HeroesArray
  • 20: HeroesWithFourthAbilityCD
  • 21: SwapChargeHealingMultiplier
  • 22: CooldownInBackgroundScale
  • 23: IgnoreAbility2InUseCheck
  • player:
  • 0: Heroes
  • 1: Ability1Cooldowns
  • 2: Ability2Cooldowns
  • 3: RightclickCooldowns
  • 4: UltCharges
  • 5: IsSelectingSecondHero
  • 6: ReserveHero
  • 7: HeroHealths
  • 8: PlayerFacingDirection
  • 9: SwapCharge
  • 10: ChargeColor
  • 11: CrouchAbilityCooldowns
  • 12: CurrHero
  • 13: SwapHudStringReady
  • 14: IsUsingHalt
  • 15: MaxSecondaryAmmoCounts
  • 16: SecondaryAmmoCounts
  • 17: AmmoCounts
  • 18: ResourcePcts
  • 19: AbilityCharges
  • 20: JumpAbilityCooldowns
  • 21: HeroSwitch
  • 22: MaxHealths
  • 23: IsDvaInMech
  • 24: DvaMechUltCharge
  • 25: MaxAmmoCounts
  • 26: StartHudID
  • }
  • subroutines
  • {
  • 0: SwapHero
  • 1: TrackDvaUlt
  • 2: StartHealingInBackground
  • 3: CooldownsInBackground
  • }
  • disabled rule("* Global Init")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("Constants")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • actions
  • {
  • Global.Version = Custom String("1.2");
  • Global.Version = Custom String("1.2.1");
  • Global.HeroesArray = Array(Hero(Reaper), Hero(Tracer), Hero(Mercy), Hero(Hanzo), Hero(Torbjörn), Hero(Reinhardt), Hero(Pharah),
  • Hero(Winston), Hero(Widowmaker), Hero(Bastion), Hero(Symmetra), Hero(Zenyatta), Hero(Genji), Hero(Roadhog), Hero(McCree), Hero(
  • Junkrat), Hero(Zarya), Hero(Soldier: 76), Hero(Lúcio), Hero(D.Va), Hero(Mei), Hero(Sombra), Hero(Doomfist), Hero(Ana), Hero(
  • Orisa), Hero(Brigitte), Hero(Moira), Hero(Wrecking Ball), Hero(Ashe), Hero(Echo), Hero(Baptiste), Hero(Sigma));
  • Global.HeroesWithSecondaryAbilityCD = Array(Hero(Doomfist), Hero(Echo), Hero(Lúcio), Hero(Orisa), Hero(Sombra), Hero(Soldier: 76),
  • Hero(Wrecking Ball), Hero(D.Va), Hero(Sigma));
  • Global.HeroesWithAbility1Charges = Array(Hero(Tracer), Hero(Symmetra), Hero(Junkrat));
  • Global.HeroesWithAbility2Charges = Array(Hero(Brigitte));
  • Global.HeroesWithCrouchAbility = Array(Hero(Wrecking Ball));
  • Global.HeroesWithJumpAbility = Array(Hero(Hanzo));
  • Global.Ability1CDs = Array(8, 3, 1.500, 0, 5, 10, 10, 6, 12, 0, 10, 0, 8, 8, 6, 8, 10, 0, 0, 4, 12, 6, 6, 12, 10, 4, 6, 0, 10, 6,
  • 13, 12);
  • Global.Ability2CDs = Array(10, 12, 30, 10, 10, 6, 9, 13, 15, Null, 10, 0, 8, 8, 10, 10, 8, 15, 12, 8, 12, 6, 6, 10, 10, 6, 10, 15,
  • 12, 8, 25, 10);
  • Global.RightclickCDs = Array(Null, Null, Null, Null, Null, Null, Null, Null, Null, 1, Null, Null, Null, Null, Null, Null, Null, 6,
  • 4, 1, Null, 2, 4, Null, 8, Null, Null, 5, Null, 6, Null, 1);
  • Global.RightclickCDs = Array(Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null, Null,
  • 6, 4, 1, Null, 2, 4, Null, 8, Null, Null, 5, Null, 6, Null, 2.500);
  • Global.HeroesWithFourthAbilityCD = Array(Hero(Wrecking Ball));
  • Global.HeroesWithResourceBar = Array(Hero(D.Va), Hero(Pharah), Hero(Bastion), Hero(Moira));
  • Global.IgnoreAbility2InUseCheck = Array(Hero(Junkrat), Hero(Widowmaker));
  • }
  • }
  • rule("Display Version")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • actions
  • {
  • Create HUD Text(All Players(All Teams), Null, Null, Custom String("Duo Heroes v{0}\r\nby BluJay#11583\r\nCODE: 5KSKH",
  • Global.Version), Right, 0, Color(White), Color(White), Color(White), Visible To and String, Default Visibility);
  • Global.VersionHud = Last Text ID;
  • }
  • }
  • rule("Workshop Settings")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • actions
  • {
  • Global.PassiveSwapChargeRate = 1.316 - 1.300 * Workshop Setting Real(Custom String("Swap Charge"), Custom String(
  • "Passive Swap Charge Rate"), 0.500, 0, 1, 100);
  • Global.ActiveSwapChargeRate = Workshop Setting Real(Custom String("Swap Charge"), Custom String("Active Swap Charge Rate"), 0.500,
  • 0, 1, 101);
  • Global.SwapChargeHealingMultiplier = Workshop Setting Real(Custom String("Swap Charge"), Custom String(
  • "Healing Charge Multiplier"), 0.500, 0, 1, 102);
  • Global.CooldownInBackgroundScale = 2 - 1.750 * Workshop Setting Real(Custom String("Reserve Hero"), Custom String(
  • "Reserve Hero Ability Cooldown Speed Scalar"), 1, 0, 1, 120);
  • Global.ReloadInBackground = Workshop Setting Toggle(Custom String("Reserve Hero"), Custom String("Reload In Background"), False,
  • 130);
  • Global.HealingInBackground = Workshop Setting Real(Custom String("Reserve Hero"), Custom String("Healing In Background Rate"), 0,
  • 0, 1, 150) * 30;
  • Global.HealingInBackgroundDelay = Workshop Setting Real(Custom String("Reserve Hero"), Custom String(
  • "Healing In Background Delay"), 0.500, 0, 1, 151) * 10;
  • Global.AllowHeroSwapping = Workshop Setting Toggle(Custom String("Game Settings"), Custom String("Allow Changing Heroes In Spawn"),
  • True, 200);
  • Global.ChargeHeroSwapInSpawn = Workshop Setting Toggle(Custom String("Game Settings"), Custom String("Charge Hero Swap In Spawn"),
  • True, 220);
  • Global.CancelSwapAllowed = Workshop Setting Toggle(Custom String("Game Settings"), Custom String("Cancel Hero Swap With Crouch"),
  • True, 300);
  • }
  • }
  • rule("Game Start")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • conditions
  • {
  • Is Game In Progress == True;
  • }
  • actions
  • {
  • Destroy HUD Text(Global.VersionHud);
  • disabled Disable Inspector Recording;
  • Disable Inspector Recording;
  • }
  • }
  • disabled rule("* Player Init")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("Freeze Player On Start")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • "For debugging"
  • Is Dummy Bot(Event Player) == False;
  • }
  • actions
  • {
  • "Player is forced to stay in spawn until selecting both heroes"
  • Disable Messages(Event Player);
  • Set Status(Event Player, Null, Rooted, 9999);
  • Set Ability 1 Enabled(Event Player, False);
  • Set Ability 2 Enabled(Event Player, False);
  • Set Primary Fire Enabled(Event Player, False);
  • Set Secondary Fire Enabled(Event Player, False);
  • Create HUD Text(Event Player, Custom String("Hero 1: {0}\r\nHero 2: SELECT", Hero Icon String(Hero Of(Event Player))), Null, Null,
  • Top, 100, Color(Aqua), Color(White), Color(White), Visible To and String, Default Visibility);
  • Event Player.StartHudID = Last Text ID;
  • "Set up variables"
  • Event Player.Ability1Cooldowns = Array(0, 0);
  • Event Player.Ability2Cooldowns = Array(0, 0);
  • Event Player.RightclickCooldowns = Array(0, 0);
  • Event Player.CrouchAbilityCooldowns = Array(0, 0);
  • Event Player.JumpAbilityCooldowns = Array(0, 0);
  • Event Player.ResourcePcts = Array(100, 100);
  • Event Player.AbilityCharges = Array(Hero Of(Event Player) == Hero(Junkrat) ? 2 : 3, 0);
  • }
  • }
  • rule("Player Select Reserve Hero")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • "Check if player has selected hero 0"
  • Has Spawned(Event Player) == True;
  • Is Alive(Event Player) == True;
  • "Make sure player hasn't already selected hero 1"
  • Event Player.IsSelectingSecondHero == False;
  • "For debugging"
  • Is Dummy Bot(Event Player) == False;
  • }
  • actions
  • {
  • Wait(2, Ignore Condition);
  • "Save hero 0 to heroes[0]"
  • Event Player.Heroes[0] = Hero Of(Event Player);
  • "Initialize hero 0 data - the rest will be saved on first hero swap"
  • Event Player.MaxHealths[0] = Max Health(Event Player);
  • Event Player.MaxAmmoCounts[0] = Max Ammo(Event Player, 0);
  • Event Player.MaxSecondaryAmmoCounts[0] = Max Ammo(Event Player, 1);
  • "Force player into hero select and disable current hero"
  • Set Player Allowed Heroes(Event Player, Remove From Array(All Heroes, Event Player.Heroes[0]));
  • "This flag stops this rule from ever activating again this game"
  • Event Player.IsSelectingSecondHero = True;
  • }
  • }
  • rule("Player Done Selecting Heroes")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Event Player.IsSelectingSecondHero == True;
  • "Check if player has selected hero 1"
  • Array Contains(All Heroes, Hero Of(Event Player)) == True;
  • }
  • actions
  • {
  • "Allow hero 0 again"
  • Reset Player Hero Availability(Event Player);
  • "Save hero 1 to heroes[1]"
  • Event Player.Heroes[1] = Hero Of(Event Player);
  • Event Player.MaxHealths[1] = Max Health(Event Player);
  • Event Player.MaxAmmoCounts[1] = Max Ammo(Event Player, 0);
  • Event Player.MaxSecondaryAmmoCounts[1] = Max Ammo(Event Player, 1);
  • "Save additional data for hero 1 to prepare for first swap"
  • Event Player.HeroHealths[1] = Max Health(Event Player);
  • Event Player.AmmoCounts[1] = Max Ammo(Event Player, 0);
  • Event Player.SecondaryAmmoCounts[1] = Max Ammo(Event Player, 1);
  • Event Player.AbilityCharges[1] = Hero Of(Event Player) == Hero(Junkrat) ? 2 : 3;
  • Wait(0.050, Ignore Condition);
  • "Put player back on hero 0"
  • Start Forcing Player To Be Hero(Event Player, Event Player.Heroes[0]);
  • Preload Hero(Event Player, Event Player.Heroes[1]);
  • "Save pointers"
  • Event Player.CurrHero = 0;
  • Event Player.ReserveHero = 1;
  • "Unfreeze player"
  • Set Ability 1 Enabled(Event Player, True);
  • Set Ability 2 Enabled(Event Player, True);
  • Set Primary Fire Enabled(Event Player, True);
  • Set Secondary Fire Enabled(Event Player, True);
  • Clear Status(Event Player, Rooted);
  • Destroy HUD Text(Event Player.StartHudID);
  • Enable Messages(Event Player);
  • }
  • }
  • rule("Hero HUD")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • actions
  • {
  • "Show which hero is in reserve, what the player's swap charge is, and what to press to swap"
  • Create HUD Text(Event Player, Hero Icon String(Event Player.Heroes[Event Player.ReserveHero]), String("{0}%", Round To Integer(
  • Event Player.SwapCharge, Down)), Event Player.SwapHudStringReady == True ? Custom String("Press {0} to swap",
  • Input Binding String(Button(Interact))) : Custom String("Not ready"), Left, 0, Color(White), Event Player.ChargeColor, Color(
  • White), String and Color, Default Visibility);
  • "Show reserve hero HUD - DO NOT OPEN!"
  • Create HUD Text(Event Player, Null, Custom String("{0} {1} {2}", Event Player.Heroes[Event Player.ReserveHero] == Hero(
  • Wrecking Ball) ? Round To Integer(Event Player.CrouchAbilityCooldowns[Event Player.ReserveHero], Up) : (Array Contains(
  • Global.HeroesWithAbility1Charges, Event Player.Heroes[Event Player.ReserveHero]) ? Round To Integer(
  • Event Player.AbilityCharges[Event Player.ReserveHero], Down) : Round To Integer(
  • Event Player.Ability1Cooldowns[Event Player.ReserveHero], Up)), Event Player.Heroes[Event Player.ReserveHero] == Hero(Bastion)
  • ? String("") : (Array Contains(Global.HeroesWithAbility2Charges, Event Player.Heroes[Event Player.ReserveHero])
  • ? Round To Integer(Event Player.AbilityCharges[Event Player.ReserveHero], Down) : Round To Integer(
  • Event Player.Ability2Cooldowns[Event Player.ReserveHero], Up)), Array Contains(Global.HeroesWithSecondaryAbilityCD,
  • Event Player.Heroes[Event Player.ReserveHero]) ? Round To Integer(Event Player.RightclickCooldowns[Event Player.ReserveHero],
  • Up) : (Array Contains(Global.HeroesWithJumpAbility, Event Player.Heroes[Event Player.ReserveHero]) ? Round To Integer(
  • Event Player.JumpAbilityCooldowns[Event Player.ReserveHero], Up) : String(""))), Custom String("{0} {1} {2}",
  • Event Player.Heroes[Event Player.ReserveHero] == Hero(Wrecking Ball) ? Ability Icon String(Hero(Wrecking Ball), Button(Crouch))
  • : Ability Icon String(Event Player.Heroes[Event Player.ReserveHero], Button(Ability 1)), Ability Icon String(
  • Event Player.Heroes[Event Player.ReserveHero], Button(Ability 2)), Array Contains(Global.HeroesWithJumpAbility,
  • Event Player.Heroes[Event Player.ReserveHero]) ? Ability Icon String(Hero(Soldier: 76), Button(Ability 1)) : (Array Contains(
  • Global.HeroesWithSecondaryAbilityCD, Event Player.Heroes[Event Player.ReserveHero]) ? Ability Icon String(
  • Event Player.Heroes[Event Player.ReserveHero], Button(Secondary Fire)) : String(""))), Left, 150, Color(White), Color(White),
  • Color(White), String, Default Visibility);
  • "Show health and ult charge of reserve hero"
  • Create HUD Text(Event Player, Null, Null, Custom String("{0} {1}", Custom String("{0}: {1}%", Ability Icon String(
  • Event Player.Heroes[Event Player.ReserveHero], Button(Ultimate)), Event Player.UltCharges[Event Player.ReserveHero]),
  • Custom String("{0}: {1}", Custom String("HP"), Round To Integer(Event Player.HeroHealths[Event Player.ReserveHero], Down))),
  • Left, 120, Color(White), Color(White), Color(White), String, Default Visibility);
  • }
  • }
  • disabled rule("* Player Events")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("Swap Heroes")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Is Button Held(Event Player, Button(Interact)) == True;
  • Event Player.SwapCharge >= 100;
  • "Cancel swap if hero is in an invalid state"
  • Is Alive(Event Player) == True;
  • Has Status(Event Player, Hacked) == False;
  • Has Status(Event Player, Knocked Down) == False;
  • Has Status(Event Player, Frozen) == False;
  • Has Status(Event Player, Stunned) == False;
  • }
  • actions
  • {
  • Wait(0.016, Ignore Condition);
  • "Allows players to use interact button for normal function without swapping heroes"
  • Abort If((Is Button Held(Event Player, Button(Crouch)) && Global.CancelSwapAllowed) == True);
  • Loop If Condition Is True;
  • Play Effect(Remove From Array(All Players(All Teams), Event Player), Good Explosion, Color(Blue), Event Player, 1);
  • "Reset swap charge"
  • Event Player.SwapCharge = 0;
  • "Save facing direction to stop player viewpoint from jumping"
  • Event Player.PlayerFacingDirection = Facing Direction Of(Event Player);
  • "Handles cooldowns and other data needed to be saved and loaded"
  • Call Subroutine(SwapHero);
  • "Set facing direction to saved direction"
  • Set Facing(Event Player, Event Player.PlayerFacingDirection, To World);
  • "Due to waits, swap charge might already be past 50%"
  • If(Event Player.SwapCharge < 50);
  • "Set color of swap charge HUD to red"
  • Event Player.ChargeColor = Color(Red);
  • End;
  • If(Event Player.SwapCharge < 100);
  • "Used by HUD to tell player swap is not ready"
  • Event Player.SwapHudStringReady = False;
  • End;
  • If(Global.HealingInBackground != 0);
  • "Start healing reserve hero in background"
  • Start Rule(StartHealingInBackground, Restart Rule);
  • End;
  • If(Global.CooldownInBackgroundScale != 2);
  • "Start cooldowns in background"
  • Start Rule(CooldownsInBackground, Restart Rule);
  • End;
  • Play Effect(All Players(All Teams), Explosion Sound, Color(White), Evaluate Once(Eye Position(Event Player)), 150);
  • Wait(0.500, Ignore Condition);
  • Preload Hero(Event Player, Event Player.Heroes[Event Player.ReserveHero]);
  • }
  • }
  • rule("SUB: SwapHero")
  • {
  • event
  • {
  • Subroutine;
  • SwapHero;
  • }
  • actions
  • {
  • "Section 1: Save ability cooldowns, charges, resource percents, health, ult charge, and ammo"
  • Event Player.AbilityCharges[Event Player.CurrHero] = Ability Charge(Event Player, Hero Of(Event Player) == Hero(Brigitte) ? Button(
  • Ability 2) : Button(Ability 1));
  • Event Player.ResourcePcts[Event Player.CurrHero] = Ability Resource(Event Player, Hero Of(Event Player) == Hero(Moira) ? Button(
  • Primary Fire) : (Hero Of(Event Player) == Hero(Pharah) ? Button(Jump) : Button(Secondary Fire)));
  • Event Player.HeroHealths[Event Player.CurrHero] = Health(Event Player);
  • Event Player.AmmoCounts[Event Player.CurrHero] = Global.ReloadInBackground ? Max Ammo(Event Player, 0) : Ammo(Event Player, 0);
  • Event Player.SecondaryAmmoCounts[Event Player.CurrHero] = Global.ReloadInBackground ? Max Ammo(Event Player, 1) : Ammo(
  • Event Player, 1);
  • Event Player.UltCharges[Event Player.CurrHero] = Ultimate Charge Percent(Event Player);
  • Event Player.JumpAbilityCooldowns[Event Player.CurrHero] = Ability Cooldown(Event Player, Button(Jump));
  • Event Player.CrouchAbilityCooldowns[Event Player.CurrHero] = Ability Cooldown(Event Player, Button(Crouch));
  • If(Is Using Ability 1(Event Player) == True);
  • Event Player.Ability1Cooldowns[Event Player.CurrHero] = Global.Ability1CDs[Index Of Array Value(Global.HeroesArray, Hero Of(
  • Event Player))];
  • Else;
  • Event Player.Ability1Cooldowns[Event Player.CurrHero] = Ability Cooldown(Event Player, Button(Ability 1));
  • End;
  • If(Is Using Ability 2(Event Player) == True && Array Contains(Global.IgnoreAbility2InUseCheck, Hero Of(Event Player)) == False);
  • Event Player.Ability2Cooldowns[Event Player.CurrHero] = Global.Ability2CDs[Index Of Array Value(Global.HeroesArray, Hero Of(
  • Event Player))];
  • Else;
  • Event Player.Ability2Cooldowns[Event Player.CurrHero] = Ability Cooldown(Event Player, Button(Ability 2));
  • End;
  • If((Is Firing Secondary(Event Player) || Event Player.IsUsingHalt) == True);
  • Event Player.RightclickCooldowns[Event Player.CurrHero] = Global.RightclickCDs[Index Of Array Value(Global.HeroesArray, Hero Of(
  • Event Player))];
  • Else;
  • Event Player.RightclickCooldowns[Event Player.CurrHero] = Ability Cooldown(Event Player, Button(Secondary Fire));
  • End;
  • "Section 2: Swap heroes"
  • Start Forcing Player To Be Hero(Event Player, Event Player.Heroes[Event Player.ReserveHero]);
  • Event Player.ReserveHero = Event Player.CurrHero;
  • Event Player.CurrHero = Event Player.CurrHero == 0 ? 1 : 0;
  • "If saved state of D.Va was out of mech, destroy the mech"
  • If(Hero Of(Event Player) == Hero(D.Va));
  • Wait(0.020, Ignore Condition);
  • If(Event Player.IsDvaInMech == False);
  • Damage(Event Player, Null, 1000);
  • End;
  • "D.Va's data won't load properly without an extra long wait for some reason"
  • Wait(0.100, Ignore Condition);
  • End;
  • "Baptiste needs an extra wait for Immortality Field"
  • If(Hero Of(Event Player) == Hero(Baptiste));
  • Wait(0.020, Ignore Condition);
  • End;
  • "Section 3: Load data from hero"
  • Set Ability Cooldown(Event Player, Button(Ability 1), Event Player.Ability1Cooldowns[Event Player.CurrHero]);
  • Set Ability Cooldown(Event Player, Button(Ability 2), Event Player.Ability2Cooldowns[Event Player.CurrHero]);
  • Set Ability Cooldown(Event Player, Button(Secondary Fire), Event Player.RightclickCooldowns[Event Player.CurrHero]);
  • Set Ability Cooldown(Event Player, Button(Jump), Event Player.JumpAbilityCooldowns[Event Player.CurrHero]);
  • Set Ability Cooldown(Event Player, Button(Crouch), Event Player.CrouchAbilityCooldowns[Event Player.CurrHero]);
  • Set Player Health(Event Player, Event Player.HeroHealths[Event Player.CurrHero]);
  • Set Ammo(Event Player, 0, Event Player.AmmoCounts[Event Player.CurrHero]);
  • Set Ammo(Event Player, 1, Event Player.SecondaryAmmoCounts[Event Player.CurrHero]);
  • Set Ability Resource(Event Player, Hero Of(Event Player) == Hero(Moira) ? Button(Primary Fire) : Button(Secondary Fire),
  • Event Player.ResourcePcts[Event Player.CurrHero]);
  • Set Ability Charge(Event Player, Hero Of(Event Player) == Hero(Brigitte) ? Button(Ability 2) : Button(Ability 1), Round To Integer(
  • Event Player.AbilityCharges[Event Player.CurrHero], To Nearest));
  • "Need a delay before setting ult charge - D.Va needs a longer wait based on mech state"
  • Wait(Hero Of(Event Player) == Hero(D.Va) ? (Event Player.IsDvaInMech == True ? 0.500 : 1) : 0.020, Ignore Condition);
  • Set Ultimate Charge(Event Player, Event Player.UltCharges[Event Player.CurrHero]);
  • }
  • }
  • rule("Death Routine")
  • {
  • event
  • {
  • Player Died;
  • All;
  • All;
  • }
  • actions
  • {
  • "Both heroes get reset when a player dies"
  • Event Player.Ability1Cooldowns[0] = 0;
  • Event Player.Ability1Cooldowns[1] = 0;
  • Event Player.Ability2Cooldowns[0] = 0;
  • Event Player.Ability2Cooldowns[1] = 0;
  • Event Player.RightclickCooldowns[0] = 0;
  • Event Player.RightclickCooldowns[1] = 0;
  • Event Player.HeroHealths[0] = Event Player.MaxHealths[0];
  • Event Player.HeroHealths[1] = Event Player.MaxHealths[1];
  • Event Player.AmmoCounts[0] = Event Player.MaxAmmoCounts[0];
  • Event Player.AmmoCounts[1] = Event Player.MaxAmmoCounts[1];
  • Event Player.SecondaryAmmoCounts[0] = Event Player.MaxSecondaryAmmoCounts[0];
  • Event Player.SecondaryAmmoCounts[1] = Event Player.MaxSecondaryAmmoCounts[1];
  • Event Player.ResourcePcts[0] = 100;
  • Event Player.ResourcePcts[1] = 100;
  • Event Player.AbilityCharges[0] = Event Player.Heroes[0] == Hero(Junkrat) ? 2 : 3;
  • Event Player.AbilityCharges[1] = Event Player.Heroes[1] == Hero(Junkrat) ? 2 : 3;
  • }
  • }
  • rule("Allow Player To Change Heroes")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Global.AllowHeroSwapping == True;
  • Is In Spawn Room(Event Player) == True;
  • }
  • actions
  • {
  • Stop Forcing Player To Be Hero(Event Player);
  • "Stop player from selecting the same hero twice"
  • Set Player Allowed Heroes(Event Player, Remove From Array(All Heroes, Event Player.Heroes[Event Player.ReserveHero]));
  • }
  • }
  • rule("Change Heroes")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • "Detect if player is on a hero that is not one of their saved heroes in the heroes array"
  • Array Contains(Event Player.Heroes, Hero Of(Event Player)) == False;
  • "Stop this rule from activating before the player has selected hero 1"
  • Array Contains(All Heroes, Event Player.Heroes[1]) == True;
  • }
  • actions
  • {
  • "Replace current hero with new hero in the heroes array"
  • Event Player.Heroes[Event Player.CurrHero] = Hero Of(Event Player);
  • "Initialize new hero data - the rest will be saved on next swap"
  • Event Player.MaxHealths[Event Player.CurrHero] = Max Health(Event Player);
  • Event Player.MaxAmmoCounts[Event Player.CurrHero] = Max Ammo(Event Player, 0);
  • Event Player.MaxSecondaryAmmoCounts[Event Player.CurrHero] = Max Ammo(Event Player, 1);
  • Set Player Allowed Heroes(Event Player, All Heroes);
  • }
  • }
  • disabled rule("* Swap Charge")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("Active Swap Charge Damage")
  • {
  • event
  • {
  • Player Dealt Damage;
  • All;
  • All;
  • }
  • conditions
  • {
  • Event Player.SwapCharge < 100;
  • }
  • actions
  • {
  • Event Player.SwapCharge += Event Damage * Global.ActiveSwapChargeRate;
  • "Stop swap charge from surpassing 100%"
  • If(Event Player.SwapCharge > 100);
  • Event Player.SwapCharge = 100;
  • End;
  • "Set color of player HUD percent"
  • If(Event Player.SwapCharge < 50);
  • Event Player.ChargeColor = Color(Red);
  • Else If(Event Player.SwapCharge < 100);
  • Event Player.ChargeColor = Color(Yellow);
  • Else;
  • Event Player.ChargeColor = Color(Green);
  • "Tells player HUD to stop saying hero swap is not ready and instead show what button to press"
  • Event Player.SwapHudStringReady = True;
  • End;
  • }
  • }
  • rule("Active Swap Charge Heal")
  • {
  • event
  • {
  • Player Dealt Healing;
  • All;
  • All;
  • }
  • conditions
  • {
  • Event Player.SwapCharge < 100;
  • }
  • actions
  • {
  • Event Player.SwapCharge += Event Healing * Global.SwapChargeHealingMultiplier * Global.ActiveSwapChargeRate;
  • "Stop swap charge from surpassing 100%"
  • If(Event Player.SwapCharge > 100);
  • Event Player.SwapCharge = 100;
  • End;
  • "Set color of player HUD percent"
  • If(Event Player.SwapCharge < 50);
  • Event Player.ChargeColor = Color(Red);
  • Else If(Event Player.SwapCharge < 100);
  • Event Player.ChargeColor = Color(Yellow);
  • Else;
  • Event Player.ChargeColor = Color(Green);
  • "Tells player HUD to stop saying hero swap is not ready and instead show what button to press"
  • Event Player.SwapHudStringReady = True;
  • End;
  • }
  • }
  • rule("Passive Swap Charge")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • "Stops this rule from running all game if workshop settings has passive swap charge rate at 0"
  • Global.PassiveSwapChargeRate != 1.316;
  • Event Player.SwapCharge < 100;
  • }
  • actions
  • {
  • Event Player.SwapCharge += 1;
  • "Stop swap charge from surpassing 100%"
  • If(Event Player.SwapCharge > 100);
  • Event Player.SwapCharge = 100;
  • End;
  • "Set color of player HUD percent"
  • If(Event Player.SwapCharge < 50);
  • Event Player.ChargeColor = Color(Red);
  • Else If(Event Player.SwapCharge < 100);
  • Event Player.ChargeColor = Color(Yellow);
  • Else;
  • Event Player.ChargeColor = Color(Green);
  • "Tells player HUD to stop saying hero swap is not ready and instead show what button to press"
  • Event Player.SwapHudStringReady = True;
  • End;
  • Wait(Global.PassiveSwapChargeRate, Ignore Condition);
  • Loop If Condition Is True;
  • }
  • }
  • disabled rule("* Process Reserve Hero")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("SUB: CooldownsInBackground")
  • {
  • event
  • {
  • Subroutine;
  • CooldownsInBackground;
  • }
  • actions
  • {
  • Wait(Global.CooldownInBackgroundScale, Ignore Condition);
  • If(Event Player.Ability1Cooldowns[Event Player.ReserveHero] > 0);
  • Event Player.Ability1Cooldowns[Event Player.ReserveHero] -= 0.250;
  • End;
  • If(Event Player.Ability2Cooldowns[Event Player.ReserveHero] > 0);
  • Event Player.Ability2Cooldowns[Event Player.ReserveHero] -= 0.250;
  • End;
  • If(Event Player.RightclickCooldowns[Event Player.ReserveHero] > 0);
  • Event Player.RightclickCooldowns[Event Player.ReserveHero] -= 0.250;
  • End;
  • If(Event Player.CrouchAbilityCooldowns[Event Player.ReserveHero] > 0);
  • Event Player.CrouchAbilityCooldowns[Event Player.ReserveHero] -= 0.250;
  • End;
  • If(Event Player.JumpAbilityCooldowns[Event Player.ReserveHero] > 0);
  • Event Player.JumpAbilityCooldowns[Event Player.ReserveHero] -= 0.250;
  • End;
  • If(Event Player.AbilityCharges[Event Player.ReserveHero] < (Event Player.Heroes[Event Player.ReserveHero] == Hero(Junkrat)
  • ? 2 : 3));
  • Event Player.AbilityCharges[Event Player.ReserveHero] += 0.250 / (Event Player.Heroes[Event Player.ReserveHero] == Hero(Brigitte)
  • ? Global.Ability2CDs : Global.Ability1CDs)[Index Of Array Value(Global.HeroesArray,
  • Event Player.Heroes[Event Player.ReserveHero])];
  • End;
  • If(Event Player.Heroes[Event Player.ReserveHero] == Hero(Moira));
  • Event Player.ResourcePcts[Event Player.ReserveHero] += 0.600;
  • Else If(Event Player.Heroes[Event Player.ReserveHero] == Hero(D.Va));
  • Event Player.ResourcePcts[Event Player.ReserveHero] += 4;
  • Else If(Event Player.Heroes[Event Player.ReserveHero] == Hero(Pharah));
  • Event Player.ResourcePcts[Event Player.ReserveHero] += 8.750;
  • Else If(Event Player.Heroes[Event Player.ReserveHero] == Hero(Bastion));
  • Event Player.ResourcePcts[Event Player.ReserveHero] += 3.570;
  • End;
  • "Stop executing this rule if all cooldowns ready"
  • If(
  • Event Player.Ability1Cooldowns[Event Player.ReserveHero] <= 0 && Event Player.Ability2Cooldowns[Event Player.ReserveHero] <= 0 && Event Player.RightclickCooldowns[Event Player.ReserveHero] <= 0 && Event Player.CrouchAbilityCooldowns[Event Player.ReserveHero] <= 0 && Event Player.JumpAbilityCooldowns[Event Player.ReserveHero] <= 0);
  • "No special cases"
  • If(Array Contains(Global.HeroesWithResourceBar, Event Player.Heroes[Event Player.ReserveHero]) == False && Array Contains(
  • Global.HeroesWithAbility1Charges, Event Player.Heroes[Event Player.ReserveHero]) == False && Array Contains(
  • Global.HeroesWithAbility2Charges, Event Player.Heroes[Event Player.ReserveHero]) == False);
  • Abort;
  • "Reserve hero has resource bar"
  • Else If(Array Contains(Global.HeroesWithResourceBar, Event Player.Heroes[Event Player.ReserveHero])
  • == True && Event Player.ResourcePcts[Event Player.ReserveHero] >= 100);
  • Abort;
  • "Reserve hero has ability charges"
  • Else If(Array Contains(Append To Array(Global.HeroesWithAbility1Charges, Global.HeroesWithAbility2Charges),
  • Event Player.Heroes[Event Player.ReserveHero]) == True && Event Player.AbilityCharges[Event Player.ReserveHero] >= (
  • Event Player.Heroes[Event Player.ReserveHero] == Hero(Junkrat) ? 2 : 3));
  • Abort;
  • End;
  • End;
  • Loop;
  • }
  • }
  • rule("SUB: StartHealingInBackground")
  • {
  • event
  • {
  • Subroutine;
  • StartHealingInBackground;
  • }
  • actions
  • {
  • "Save which hero's health is getting restored"
  • Event Player.HeroSwitch = Event Player.ReserveHero;
  • "Provide a delay before background healing starts"
  • Wait(Global.HealingInBackgroundDelay, Ignore Condition);
  • While(Event Player.HeroHealths[Event Player.ReserveHero] < Event Player.MaxHealths[Event Player.ReserveHero]);
  • If(Event Player.HeroHealths[Event Player.ReserveHero] < Event Player.MaxHealths[Event Player.ReserveHero]);
  • "If next heal would put reserve hero health above max health, set to max health instead"
  • If(
  • Event Player.HeroHealths[Event Player.ReserveHero] + Global.HealingInBackground > Event Player.MaxHealths[Event Player.ReserveHero]);
  • Event Player.HeroHealths[Event Player.ReserveHero] = Event Player.MaxHealths[Event Player.ReserveHero];
  • "Else heal as normal"
  • Else;
  • Event Player.HeroHealths[Event Player.ReserveHero] += Global.HealingInBackground;
  • End;
  • End;
  • Wait(0.500, Ignore Condition);
  • "Check for a hero swap and abort if so"
  • If(Event Player.CurrHero == Event Player.HeroSwitch);
  • Abort;
  • End;
  • End;
  • }
  • }
  • rule("Charge Swap In Spawn")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Global.ChargeHeroSwapInSpawn == True;
  • Is In Spawn Room(Event Player) == True;
  • }
  • actions
  • {
  • "Keep player's swap charge at 100% if in spawn room"
  • Event Player.SwapCharge = 100;
  • Event Player.ChargeColor = Color(Green);
  • Event Player.SwapHudStringReady = True;
  • disabled Wait(0.250, Ignore Condition);
  • Wait Until(Event Player.SwapCharge != 100 || Is In Spawn Room(Event Player) == False, 999);
  • Loop If Condition Is True;
  • }
  • }
  • disabled rule("* Game Fixes")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("Is Orisa Using Halt!")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Hero Of(Event Player) == Hero(Orisa);
  • Is Firing Secondary(Event Player) == True;
  • }
  • actions
  • {
  • "Fixes exploit where player swaps off of Orisa right as they pull players with Halt! to stop the cooldown from starting - Used in section 1 of SUB: SwapHero"
  • Event Player.IsUsingHalt = True;
  • While(Ability Cooldown(Event Player, Button(Secondary Fire)) == 0 && Hero Of(Event Player) == Hero(Orisa));
  • Wait(0.016, Ignore Condition);
  • End;
  • Event Player.IsUsingHalt = False;
  • }
  • }
  • rule("Track D.Va Mech State (Out Of Mech)")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Hero Of(Event Player) == Hero(D.Va);
  • Is In Alternate Form(Event Player) == True;
  • }
  • actions
  • {
  • "Need to save D.Va's mech state, otherwise after losing mech a player could swap off of and back on to D.Va to recover the mech"
  • Event Player.IsDvaInMech = False;
  • }
  • }
  • rule("Track D.Va Mech State (In Mech)")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Hero Of(Event Player) == Hero(D.Va);
  • Is In Alternate Form(Event Player) == False;
  • }
  • actions
  • {
  • "Need to save D.Va's mech state, otherwise after losing mech a player could swap off of and back on to D.Va to recover the mech"
  • Wait(0.250, Ignore Condition);
  • Event Player.IsDvaInMech = True;
  • }
  • }
  • rule("Track Self Destruct Ult Charge")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Hero Of(Event Player) == Hero(D.Va);
  • Is In Alternate Form(Event Player) == False;
  • Is Alive(Event Player) == True;
  • }
  • actions
  • {
  • "Tracks D.Va's ult charge while she's in her mech"
  • Wait(1.250, Ignore Condition);
  • Abort If Condition Is False;
  • Call Subroutine(TrackDvaUlt);
  • }
  • }
  • rule("SUB: TrackDvaUlt")
  • {
  • event
  • {
  • Subroutine;
  • TrackDvaUlt;
  • }
  • actions
  • {
  • "Updates D.Va's ult charge 4 times a second - this is needed because D.Va has two separate ults"
  • Event Player.DvaMechUltCharge = Ultimate Charge Percent(Event Player);
  • Wait(0.250, Ignore Condition);
  • Loop If(Hero Of(Event Player) == Hero(D.Va) && Is In Alternate Form(Event Player) == False);
  • }
  • }
  • rule("Set Self Destruct Ult Charge After Call Mech")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Hero Of(Event Player) == Hero(D.Va);
  • Is Using Ultimate(Event Player) == True;
  • }
  • actions
  • {
  • "If D.Va uses her call mech ult, load her self destruct ult charge that has been saved"
  • Wait(2, Ignore Condition);
  • Abort If(Is In Alternate Form(Event Player) == True);
  • Set Ultimate Charge(Event Player, Event Player.DvaMechUltCharge);
  • Wait(0.250, Ignore Condition);
  • Call Subroutine(TrackDvaUlt);
  • }
  • }
  • rule("Set Call Mech Charge To 0%")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Hero Of(Event Player) == Hero(D.Va);
  • Is In Alternate Form(Event Player) == True;
  • }
  • actions
  • {
  • "When D.Va loses her mech, set her ult charge to 0"
  • Set Ultimate Charge(Event Player, 0);
  • }
  • }
  • disabled rule("* Debug")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • }
  • rule("DEBUG: Skip Hero Selection")
  • disabled rule("DEBUG: Skip Hero Selection")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • conditions
  • {
  • Is Assembling Heroes == True;
  • }
  • actions
  • {
  • Set Match Time(12);
  • }
  • }
  • rule("DEBUG: Skip Setup")
  • disabled rule("DEBUG: Skip Setup")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • conditions
  • {
  • Is In Setup == True;
  • }
  • actions
  • {
  • Set Match Time(7);
  • }
  • }
  • rule("DEBUG: Damage Self")
  • disabled rule("DEBUG: Damage Self")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Is Button Held(Event Player, Button(Jump)) == True;
  • }
  • actions
  • {
  • Damage(Event Player, Null, 30);
  • }
  • }
  • rule("DEBUG: Spawn Bot")
  • disabled rule("DEBUG: Spawn Bot")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Is Button Held(Event Player, Button(Reload)) == True;
  • Is Button Held(Event Player, Button(Crouch)) == True;
  • }
  • actions
  • {
  • disabled Create Dummy Bot(Random Value In Array(All Heroes), Opposite Team Of(Team Of(Event Player)), -1, Position Of(Event Player)
  • + Facing Direction Of(Event Player), Vector(0, 0, 0));
  • Create Dummy Bot(Random Value In Array(All Heroes), Team Of(Event Player), -1, Position Of(Event Player) + Facing Direction Of(
  • disabled Create Dummy Bot(Random Value In Array(All Heroes), Team Of(Event Player), -1, Position Of(Event Player) + Facing Direction Of(
  • Event Player), Vector(0, 0, 0));
  • disabled Create Dummy Bot(Hero(Mei), Opposite Team Of(Team Of(Event Player)), -1, Position Of(Event Player) + Facing Direction Of(
  • Create Dummy Bot(Hero(Ana), Opposite Team Of(Team Of(Event Player)), -1, Position Of(Event Player) + Facing Direction Of(
  • Event Player), Vector(0, 0, 0));
  • }
  • }
  • rule("DEBUG: Keep Bots Alive")
  • disabled rule("DEBUG: Keep Bots Alive")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Is Dummy Bot(Event Player) == True;
  • }
  • actions
  • {
  • Start Heal Over Time(Event Player, Event Player, 9999, 9999);
  • }
  • }
  • rule("DEBUG: Pause Match Timer")
  • disabled rule("DEBUG: Pause Match Timer")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • conditions
  • {
  • Is Game In Progress == True;
  • }
  • actions
  • {
  • Pause Match Time;
  • }
  • }
  • rule("DEBUG: Use Ability")
  • disabled rule("DEBUG: Use Ability")
  • {
  • event
  • {
  • Ongoing - Each Player;
  • All;
  • All;
  • }
  • conditions
  • {
  • Is Dummy Bot(Event Player) == True;
  • }
  • actions
  • {
  • disabled Wait(0.250, Ignore Condition);
  • disabled Set Ultimate Charge(Event Player, 100);
  • Wait(3.500, Ignore Condition);
  • disabled Start Holding Button(Event Player, Button(Primary Fire));
  • Event Player.Heroes = Array(Hero Of(Event Player), Hero(Mei));
  • Event Player.SwapCharge = 100;
  • Start Holding Button(Event Player, Button(Ability 1));
  • disabled Event Player.Heroes = Array(Hero Of(Event Player), Hero(Mei));
  • disabled Event Player.SwapCharge = 100;
  • disabled Kill(Event Player, Null);
  • Wait(1.250, Ignore Condition);
  • Start Holding Button(Event Player, Button(Interact));
  • Wait(0.250, Ignore Condition);
  • Stop Holding Button(Event Player, Button(Interact));
  • disabled Wait(1.250, Ignore Condition);
  • disabled Start Holding Button(Event Player, Button(Interact));
  • disabled Wait(0.250, Ignore Condition);
  • disabled Stop Holding Button(Event Player, Button(Interact));
  • }
  • }
  • rule("DEBUG: HUD")
  • disabled rule("DEBUG: HUD")
  • {
  • event
  • {
  • Ongoing - Global;
  • }
  • actions
  • {
  • Create HUD Text(All Players(All Teams), Custom String("{0} Load\r\n{1} Avg\r\n{2} Peak", Server Load, Server Load Average,
  • Server Load Peak), Null, Null, Right, 200, Color(White), Color(White), Color(White), Visible To and String,
  • Default Visibility);
  • }
  • }
Join the Workshop.codes Discord