Infernal Shrines

Wiki
  • One of three Shrine locations activates each round; the next Shrine is almost always in a different location from the previous one.
  • Both teams race to kill 40 Guardians at the active Shrine. First to 40 captures it.
  • Capturing a Shrine summons an Arcane, Frozen, or Mortar Punisher that pushes the lane closest to that Shrine.
  • The Punisher type changes every round and cannot repeat back-to-back.

Objective Timers

EventDurationSecondsSource
First Shrine Activation after a 30s warning3:00180s
Shrine Duration2:30150slibMSHE_gv_mMDiabloShrinesShrineTimerDuration_C
Shrine Warning0:3030slibMSHE_gv_mMDiabloShrineWarningTimerLong_C

Units

Punisher

HP
14500
Speed
3.75
Scaling
Basic damage
+2/min 1-10, +3/min 11-15, +5/min 16+
Life
+1000/min 1-3, +1100/min 4-8, +1300/min 9-13, +1600/min 14-18, +1750/min 19+
Abilities
  • QPunishMercPunisherLanerLeap

    Leaps to the targeted location, dealing 1 damage and stunning targets for 1 seconds at the impact location.

  • WFixateMercPunisherLanerFixate

    Fixate on the target, becoming enraged and increasing movement speed by 100% and attack speed by 0% for 4 seconds. During this time the Punisher may not receive any orders. Stuns the Punisher for 1 seconds when the effect ends.

  • RCancel SymbioteAbathurSymbioteCancel

    Cancels the Symbiote ability.

Weapons
IDDamagePeriodRange
MercPunisherLanerWeapon1601s1.5
MercPunisherLanerFixateWeapon1600.5s2
MercPunisherLanerWeaponStructure1601s1.5

Shrine Randomisation

Each round, one of three Shrine locations becomes active. The next Shrine is almost always in a different spot than the previous one, though same-location repeats can happen rarely. The Punisher type (Arcane, Frozen, or Mortar) never repeats back-to-back.


            TextExpressionSetToken("Param/Expression/lib_MSHE_D32CCB19", "B", IntToText(libMSHE_gv_mMDiabloShrineCursedEventTotal_C));
            TextTagSetText(libMSHE_gv_mMISTextTag[lp_team], TextExpressionAssemble("Param/Expression/lib_MSHE_D32CCB19"));
        }
    }
}

void libMSHE_gf_MMISRandomizeNextShrineandShowPreview () {
    // Automatic Variable Declarations
    int autoED96EF13_val;

    // Implementation
    if ((libCore_gv_dEBUGDebuggingEnabled == true) && (libMSHE_gv_forcedPunisherType != 0)) {
        libMSHE_gv_mMISLastShrineCounter += 1;
        libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed);
        libMSHE_gv_mMISBuffIndex = libMSHE_gv_forcedPunisherType;
    }
    else {
        if ((libMSHE_gv_mMISNumberOfShrinesEvents == 0)) {
            libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed);
            libMSHE_gv_mMISBuffIndex = libMSHE_gf_MMISGetWhichShrine();
        }
        else {
            while (((libMSHE_gv_mMISLastShrineCounter < 15) && ((libMSHE_gv_mMISCurrentShrine == libMSHE_gv_mMISLastShrine) || (libMSHE_gv_mMISBuffIndex == libMSHE_gv_mMISLastBuff)))) {
                libMSHE_gv_mMISLastShrineCounter += 1;
                libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed);
                libMSHE_gv_mMISBuffIndex = libMSHE_gf_MMISGetWhichShrine();
            }
        }
    }
    libNtve_gf_SendActorMessageToUnit(libMSHE_gv_mMISShrines[libMSHE_gv_mMISCurrentShrine], "SetMinimapVisibility 1");
    libNtve_gf_SendActorMessageToUnit(libMSHE_gv_mMISShrines[libMSHE_gv_mMISCurrentShrine], "SetMinimapVisibilityAlways 1");
    autoED96EF13_val = libMSHE_gv_mMISBuffIndex;
    if (autoED96EF13_val == 1) {
        libNtve_gf_SendActorMessageToUnit(libMSHE_gv_mMISShrines[libMSHE_gv_mMISCurrentShrine], "MinimapTooltip DOCSTR_InactiveFrozenShrine");
    }
    else if (autoED96EF13_val == 2) {

// ...

    int auto6F20D935_u;
    unit auto6F20D935_var;
    unitgroup autoE5CA2A3B_g;
    int autoE5CA2A3B_u;
    unit autoE5CA2A3B_var;
    string auto318ED688_val;

    // Variable Initialization
    lv_shrine = UnitGroupEmpty();
    lv_shrineType = libMSHE_ge_MMISShrineTypes_None;

    // Implementation
    libMSHE_gv_mMISLastShrine = lp_shrine;
    libMSHE_gv_mMISLastBuff = libMSHE_gv_mMISBuffIndex;
    UnitRemove(libMSHE_gv_mMISWarningUnit);
    auto6F20D935_g = UnitGroup("DiabloShrine", c_playerAny, RegionEntireMap(), UnitFilter(0, 0, (1 << c_targetFilterMissile), (1 << (c_targetFilterDead - 32)) | (1 << (c_targetFilterHidden - 32))), 0);
    auto6F20D935_u = UnitGroupCount(auto6F20D935_g, c_unitCountAll);
    for (;; auto6F20D935_u -= 1) {
        auto6F20D935_var = UnitGroupUnitFromEnd(auto6F20D935_g, auto6F20D935_u);
        if (auto6F20D935_var == null) { break; }
        UnitAbilityEnable(auto6F20D935_var, "CursedShrineSpawn", true);
    }
    autoE5CA2A3B_g = libMSHE_gv_mMISShrineGroups[lp_shrine];
    autoE5CA2A3B_u = UnitGroupCount(autoE5CA2A3B_g, c_unitCountAll);
    for (;; autoE5CA2A3B_u -= 1) {

// ...

        }
    }

    // Actions
    if (!runActions) {
        return true;
    }

    UnitBehaviorRemove(libMSHE_gv_mMISShrines[libMSHE_gv_mMISCurrentShrine], "DiabloShrineWarningFX", 1);
    libMSHE_gf_MMISTransmissionShrineActivating();
    libMSHE_gf_MMISActivateShrine(libMSHE_gv_mMISCurrentShrine);
    libMSHE_gv_mMISNumberOfShrinesEvents += 1;
    libMSHE_gv_mMISLastShrineCounter = 0;
    return true;
}

//--------------------------------------------------------------------------------------------------
void libMSHE_gt_MMISWarningTimerExpired_Init () {
    libMSHE_gt_MMISWarningTimerExpired = TriggerCreate("libMSHE_gt_MMISWarningTimerExpired_Func");
    TriggerAddEventTimer(libMSHE_gt_MMISWarningTimerExpired, libMSHE_gv_mMISShrineWarningTimer);
}

//--------------------------------------------------------------------------------------------------
// Trigger: MM IS Start Shrine Timer
//--------------------------------------------------------------------------------------------------

// ...

    // Actions
    if (!runActions) {
        return true;
    }

    TimerPause(libMSHE_gv_mMISShrineTimer, true);
    TimerStart(libMSHE_gv_mMISShrineWarningTimer, 1.0, false, c_timeGame);
    if ((libMSHE_gv_mMISNumberOfShrinesEvents == 0)) {
        libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed);
        libMSHE_gv_mMISBuffIndex = libMSHE_gf_MMISGetWhichShrine();
    }
    else {
        while (((libMSHE_gv_mMISLastShrineCounter < 15) && ((libMSHE_gv_mMISCurrentShrine == libMSHE_gv_mMISLastShrine) || (libMSHE_gv_mMISBuffIndex == libMSHE_gv_mMISLastBuff)))) {
            libMSHE_gv_mMISLastShrineCounter += 1;
            libMSHE_gv_mMISCurrentShrine = RandomInt(1, libMSHE_gv_mMISNumberofShrinesAllowed);
            libMSHE_gv_mMISBuffIndex = libMSHE_gf_MMISGetWhichShrine();
        }
    }
    libMSHE_gf_MMISWarningAnnouncementShrine(libMSHE_gv_mMISCurrentShrine);
    PlayerGroupRemove(libMSHE_gv_mMISShrineGroup, libMSHE_gv_mMISBuffIndex);
    DialogControlSetVisible(libMSHE_gv_mMTowerPushPanel.lv_crystalFrozenIcon, PlayerGroupAll(), false);
    DialogControlSetVisible(libMSHE_gv_mMTowerPushPanel.lv_crystalMortarIcon, PlayerGroupAll(), false);
    DialogControlSetVisible(libMSHE_gv_mMTowerPushPanel.lv_crystalArcaneIcon, PlayerGroupAll(), false);
    autoD3439B71_val = libMSHE_gv_mMISBuffIndex;
    if (autoD3439B71_val == 1) {
        libMSHE_gv_mMISBuff = "FrozenShrine";

40 Guardians → Punisher

Both teams race to kill 40 Guardians, also described as Skeletal Defenders, spawned by the active Shrine. The first team to 40 kills captures it and summons a Punisher.


    playergroup auto1A5B44D4_g;

    // Variable Initialization

    // Implementation
    if ((libMSHE_gv_mMISTextTag[lp_team] == c_textTagNone)) {
        TextTagCreate(StringExternal("Param/Value/lib_MSHE_8C8796B4"), 24, UnitGetPosition(lp_currentShrine), 1.0, true, false, libGame_gf_PlayersOnTeamHeroes(lp_team, false));
        libMSHE_gv_mMISTextTag[lp_team] = TextTagLastCreated();
    }

    if ((libMSHE_gv_mMISKillCount[lp_team] >= libMSHE_gv_mMDiabloShrineCursedEventTotal_C)) {
        TextTagDestroy(libMSHE_gv_mMISTextTag[lp_team]);
        if ((lp_enemyTeam <= libCore_gv_bALMaxTeams)) {
            TextTagDestroy(libMSHE_gv_mMISTextTag[lp_enemyTeam]);
        }

        libMSHE_gv_mMISTextTag[lp_team] = c_textTagNone;
        libMSHE_gv_mMISTextTag[lp_enemyTeam] = c_textTagNone;
    }
    else {
        auto1A5B44D4_g = libGame_gf_PlayersOnTeamHeroes(lp_team, false);
        lv_itPlayer = -1;
        while (true) {
            	lv_itPlayer = PlayerGroupNextPlayer(auto1A5B44D4_g, lv_itPlayer);
            	if (lv_itPlayer<0) { break; }
            	TextExpressionSetToken("Param/Expression/lib_MSHE_D32CCB19", "A", IntToText(libMSHE_gv_mMISKillCount[lp_team]));
            TextExpressionSetToken("Param/Expression/lib_MSHE_D32CCB19", "B", IntToText(libMSHE_gv_mMDiabloShrineCursedEventTotal_C));
            TextTagSetText(libMSHE_gv_mMISTextTag[lp_team], TextExpressionAssemble("Param/Expression/lib_MSHE_D32CCB19"));
        }
    }
}

void libMSHE_gf_MMISRandomizeNextShrineandShowPreview () {
    // Automatic Variable Declarations
    int autoED96EF13_val;

    // Implementation

// ...

    // Implementation
    DialogControlSetVisible(libMSHE_gv_mMTowerPushPanel.lv_mainPanel, libGame_gv_teams[libGame_gv_teamOrderIndex_C].lv_teamPlayerGroupNoNPCPlayers, lp_showHide);
    DialogControlSetVisible(libMSHE_gv_mMTowerPushPanel.lv_mainPanel, libGame_gv_teams[libGame_gv_teamChaosIndex_C].lv_teamPlayerGroupNoNPCPlayers, lp_showHide);
    DialogControlSetVisible(libMSHE_gv_mMTowerPushPanel.lv_mainPanel, libCore_gv_playerGroupFromPlayer[libCore_gv_oBSERVER_ObserverUIPlayer], lp_showHide);
}

void libMSHE_gf_MMTowerPushUISetGoblinCount (int lp_count, int lp_count2) {
    // Automatic Variable Declarations
    // Implementation
    TextExpressionSetToken("Param/Expression/lib_MSHE_7B0D17EF", "A", IntToText(lp_count));
    TextExpressionSetToken("Param/Expression/lib_MSHE_7B0D17EF", "B", IntToText(libMSHE_gv_mMDiabloShrineCursedEventTotal_C));
    libNtve_gf_SetDialogItemText(libMSHE_gv_mMTowerPushPanel.lv_hauntedMinesSkullModeSkullCounterLabel[1], TextExpressionAssemble("Param/Expression/lib_MSHE_7B0D17EF"), PlayerGroupAll());
    TextExpressionSetToken("Param/Expression/lib_MSHE_E44F01EB", "A", IntToText(lp_count2));
    TextExpressionSetToken("Param/Expression/lib_MSHE_E44F01EB", "B", IntToText(libMSHE_gv_mMDiabloShrineCursedEventTotal_C));
    libNtve_gf_SetDialogItemText(libMSHE_gv_mMTowerPushPanel.lv_hauntedMinesSkullModeSkullCounterLabel[2], TextExpressionAssemble("Param/Expression/lib_MSHE_E44F01EB"), PlayerGroupAll());
}

void libMSHE_gf_MMTowerPushUISetMode (int lp_mode) {
    // Automatic Variable Declarations
    int autoB3683D6E_val;

    // Implementation
    autoB3683D6E_val = lp_mode;
    if (autoB3683D6E_val == libMSHE_ge_MMISUIModes_Idle) {

// ...

    TextTagCreate(TextExpressionAssemble("Param/Expression/lib_MSHE_034712A9"), 24, UnitGetPosition(EventUnit()), 1.0, true, true, lv_textTagPlayers);
    TextTagSetVelocity(TextTagLastCreated(), 1.5, 90.0);
    TextTagSetTime(TextTagLastCreated(), c_textTagTimeDuration, 3.0);
    TextTagSetFogVisibility(TextTagLastCreated(), c_visTypeFog);
    TextExpressionSetToken("Param/Expression/lib_MSHE_A99E643F", "A", IntToText(1));
    TextTagCreate(TextExpressionAssemble("Param/Expression/lib_MSHE_A99E643F"), 24, UnitGetPosition(EventUnit()), 1.0, true, true, lv_enemyTextTagPlayers);
    TextTagSetVelocity(TextTagLastCreated(), 1.5, 90.0);
    TextTagSetTime(TextTagLastCreated(), c_textTagTimeDuration, 3.0);
    TextTagSetFogVisibility(TextTagLastCreated(), c_visTypeFog);
    libMSHE_gf_MMISTextTagScoreHandler((3 - libGame_gf_TeamNumberOfPlayer(libNtve_gf_KillingPlayer())), libGame_gf_TeamNumberOfPlayer(libNtve_gf_KillingPlayer()), libMSHE_gv_mMISShrines[libMSHE_gv_mMISCurrentShrine]);
    if ((libMSHE_gv_mMISKillCount[libGame_gf_TeamNumberOfPlayer(libNtve_gf_KillingPlayer())] == libMSHE_gv_mMDiabloShrineCursedEventTotal_C)) {
        lv_shrine = libMSHE_gv_mMISShrines[libMSHE_gv_mMISCurrentShrine];
        lv_winningTeam = libGame_gf_TeamNumberOfPlayer(libNtve_gf_KillingPlayer());
        if ((UnitHasBehavior2(lv_shrine, "CombatShrine") == true)) {
            lv_shrineBuff = "CombatShrineBuff";
            libMSHE_gv_mMISShrineBuffText = StringExternal("Param/Value/lib_MSHE_6F731C56");
            libMSHE_gf_MMISAnnouncementShrineCaptured(lv_shrine, libMSHE_ge_MMISShrineTypes_CombatShrine, lv_winningTeam);
        }

        if ((UnitHasBehavior2(lv_shrine, "SiegeShrine") == true)) {
            lv_shrineBuff = "SiegeShrineBuff";

Punisher Lane Selection

Capturing a Shrine summons a Punisher that pushes the lane closest to that Shrine. Punishers focus on attacking enemy Heroes, but their leap can target enemy Gates as well as Heroes.


    }
    else {
    }
    lv_monster = UnitLastCreated();
    libMSHE_gv_mMISPunisher = UnitLastCreated();
    TriggerEnable(libMSHE_gt_PunisherDurationTracking, true);
    libGame_gf_CalculateSpawnedMinionGoalPoints(lp_team, UnitGetPosition(lv_monster));
    libAIAI_gf_MinionAIStartMinionAI(-1, lv_monster, libGame_gv_spawnedMinionLane, libGame_gv_spawnedMinionFirstWaypointIndex, false, true, false, lv_enemyTeam, false);
    libMSHE_gv_mMDiabloShrinesPunisherPushLane = AILaneWaypointGetClosestLane(UnitGetPosition(lv_monster));
}

void libMSHE_gf_MMBOEUpdateAmbience (int lp_player) {
    // Automatic Variable Declarations
    // Implementation
    if ((PointGetX(CameraGetTarget(lp_player)) > 124.0)) {
        libMSHE_gf_MMBOEChangeAmbience("Ambience_BoE_Hell", null, PlayerGroupSingle(lp_player));
    }

Timer Source

libmshe_h.galaxy — constants

const fixed libMSHE_gv_mMDiabloShrinesShrineTimerDuration_C = 150.0;
const fixed libMSHE_gv_mMDiabloShrineWarningTimerLong_C = 30.0;

libmshe.galaxy — timer start

    // Actions
    if (!runActions) {
        return true;
    }

    TriggerExecute(libMSHE_gt_MMISUIHandler, true, false);
    TimerStart(libMSHE_gv_mMISShrineTimer, libMSHE_gv_mMDiabloShrinesShrineTimerDuration_C, false, c_timeGame);
    TimerStart(libMSHE_gv_mMISExperince, libMSHE_gv_mMDiabloShrinesExperinceTimer_C, false, c_timeGame);
    TimerStart(libMSHE_gv_mMISAffixTimer, libMSHE_gv_mMISAffixTimerDuration, false, c_timeGame);
    libMSHE_gv_mMDiabloShrinesShrineTimerWarning = libMSHE_gv_mMDiabloShrineWarningTimerLong_C;
    CatalogFieldValueSet(c_gameCatalogBehavior, "DiabloShrineWarningFX", "Duration", libCore_gv_cOMPUTER_Neutral, IntToString(FixedToInt(libMSHE_gv_mMDiabloShrineWarningTimerLong_C)));
    autoD4036543_ae = libMSHE_gv_mMISNumberofShrinesAllowed;
    lv_itShrine = 1;

// ...


    // Actions
    if (!runActions) {
        return true;
    }

    TimerStart(libMSHE_gv_mMISShrineTimer, libMSHE_gv_mMDiabloShrinesShrineTimerDuration_C, false, c_timeGame);
    auto92397144_g = libMSHE_gv_mMISParalyzeStorage;
    auto92397144_u = UnitGroupCount(auto92397144_g, c_unitCountAll);
    for (;; auto92397144_u -= 1) {
        lv_itUnit = UnitGroupUnitFromEnd(auto92397144_g, auto92397144_u);
        if (lv_itUnit == null) { break; }
        UnitRemove(lv_itUnit);

// ...

    // Actions
    if (!runActions) {
        return true;
    }

    TriggerEnable(libMSHE_gt_PunisherDurationTracking, false);
    TimerStart(libMSHE_gv_mMISShrineTimer, libMSHE_gv_mMDiabloShrinesShrineTimerDuration_C, false, c_timeGame);
    TimerStart(libMSHE_gv_mMISObjectivePreviewTimer, libMSHE_gv_mMISObjectivePreviewDelay_C, false, c_timeGame);
    if ((UnitGetOwner(EventUnit()) == libCore_gv_cOMPUTER_TeamOrder)) {
        SoundtrackPlay(PlayerGroupAll(), c_soundtrackCategoryMusic, "MX_Event_Shrines_Punisher_Heaven_End", c_soundtrackCueAny, c_soundtrackIndexAny, false);
    }
    else {
        SoundtrackPlay(PlayerGroupAll(), c_soundtrackCategoryMusic, "MX_Event_Shrines_Punisher_Hell_End", c_soundtrackCueAny, c_soundtrackIndexAny, false);

Source Files