![[Home]](/jailbreak-ext/jdn-logo.jpg)
Actor >> Info >> JBInfoJail
// ============================================================================ // JBInfoJail // Copyright 2002 by Mychaeel <mychaeel@planetjailbreak.com> // $Id: JBInfoJail.uc,v 1.53 2007/04/24 16:32:22 jrubzjeknf Exp $ // // Holds information about a generic jail. // ============================================================================ class JBInfoJail extends Info placeable; // ============================================================================ // Imports // ============================================================================ #exec texture import file=Textures\JBInfoJail.pcx mips=off masked=on // ============================================================================ // Properties // ============================================================================ var(Events) name EventExecutionInit; // event fired when camera activated var(Events) name EventExecutionCommit; // event fired when execution starts var(Events) name EventExecutionEnd; // event fired when execution finished var(Events) name EventReleaseRed; // event fired to release red team var(Events) name EventReleaseBlue; // event fired to release blue team var(Events) name EventFinalExecutionInit; // only fired when it's the final execution var(Events) name EventFinalExecutionCommit; // only fired when it's the final execution var(Events) name EventFinalExecutionEnd; // only fired when it's the final execution var() float ExecutionDelayCommit; // delay between camera and execution var() float ExecutionDelayFallback; // delay between execution and gibbing var() float FinalExecutionDelayCommit; // delay between camera and execution var() float FinalExecutionDelayFallback; // delay between execution and gibbing var() byte Priority; // prisoners will spawn in the jail with the lowest priority var() byte PrisonerLimit; // prisoners won't be spawned in jails where the limit is reached var() name TagAttachVolumes; // tag of attached volumes var() name TagAttachZones; // tag of attached zones // ============================================================================ // Types // ============================================================================ struct TInfoRelease { var bool bIsOpening; // release doors are opening var float TimeActivation; // time of release activation var float TimeReset; // time of release switch reset var Controller ControllerInstigator; // player activating the release var array<Mover> ListMover; // movers opening for this event }; // ============================================================================ // Variables // ============================================================================ var JBInfoJail nextJail; var private TInfoRelease InfoReleaseByTeam[2]; // release state for each team var private array<Volume> ListVolume; // volumes attached to jail var private array<NavigationPoint> ListNavigationPointExit; // exit points var private bool bIsRedActive; var private bool bIsBlueActive; var private bool bRedJammed; // red can't be released var private bool bBlueJammed; // blue can't be released var private bool bForcedReleaseRed; // red can be released even if it's jammed var private bool bForcedReleaseBlue; // blue can be released even if it's jammed var private bool bIsFinalExecution; // final execution is running // ============================================================================ // Replication // ============================================================================ replication { reliable if(Role == ROLE_Authority) bIsRedActive, bIsBlueActive, bRedJammed, bBlueJammed; } // ============================================================================ // PostBeginPlay // // Initializes the ListVolume array with references to all volumes attached to // this jail, and the ListMover arrays with references to all movers that are // opened by release events. // ============================================================================ event PostBeginPlay() { local Volume thisVolume; if (TagAttachVolumes != '' && TagAttachVolumes != 'None') foreach AllActors(Class'Volume', thisVolume, TagAttachVolumes) ListVolume[ListVolume.Length] = thisVolume; FindReleases(EventReleaseRed, InfoReleaseByTeam[0].ListMover); FindReleases(EventReleaseBlue, InfoReleaseByTeam[1].ListMover); } // ============================================================================ // Tick // // If this JBInfoJail actor is not yet registered in the global JBInfoJail // linked list client-side yet, adds it to it. // ============================================================================ simulated event Tick(float TimeDelta) { local JBInfoJail firstJail; local JBInfoJail thisJail; local JBGameReplicationInfo InfoGame; if (Role < ROLE_Authority) { InfoGame = JBGameReplicationInfo(Level.GetLocalPlayerController().GameReplicationInfo); if (InfoGame == None) return; firstJail = InfoGame.firstJail; for (thisJail = firstJail; thisJail != None; thisJail = thisJail.nextJail) if (thisJail == Self) return; nextJail = InfoGame.firstJail; InfoGame.firstJail = Self; } Disable('Tick'); } // ============================================================================ // FindReleases // // Adds movers triggered by the given tag to the given array unless they are // present there already. Then recursively finds other movers triggered by the // found mover's OpeningEvent and adds them too. // ============================================================================ function FindReleases(name TagMover, out array<Mover> ListMover) { local int iMover; local Mover thisMover; if (TagMover == '' || TagMover == 'None') return; foreach DynamicActors(Class'Mover', thisMover, TagMover) { for (iMover = 0; iMover < ListMover.Length; iMover++) if (ListMover[iMover] == thisMover) break; if (iMover < ListMover.Length) continue; // mover already listed ListMover[iMover] = thisMover; FindReleases(thisMover.Event, ListMover); FindReleases(thisMover.OpeningEvent, ListMover); FindReleases(thisMover.OpenedEvent, ListMover); FindReleases(thisMover.ClosingEvent, ListMover); } } // ============================================================================ // FindExits // // Finds and returns a list of NavigationPoint actors outside jail that are // directly connected to NavigationPoint actors in this jail. If multiple // paths lead from a point in jail to one outside, this exit will be listed // multiple times. // ============================================================================ function array<NavigationPoint> FindExits() { local int iReachSpec; local NavigationPoint thisNavigationPoint; if (ListNavigationPointExit.Length == 0) for (thisNavigationPoint = Level.NavigationPointList; thisNavigationPoint != None; thisNavigationPoint = thisNavigationPoint.nextNavigationPoint) if (ContainsActor(thisNavigationPoint)) for (iReachSpec = 0; iReachSpec < thisNavigationPoint.PathList.Length; iReachSpec++) if (!Jailbreak(Level.Game).ContainsActorArena(thisNavigationPoint.PathList[iReachSpec].End) && !Jailbreak(Level.Game).ContainsActorJail (thisNavigationPoint.PathList[iReachSpec].End)) ListNavigationPointExit[ListNavigationPointExit.Length] = thisNavigationPoint.PathList[iReachSpec].End; return ListNavigationPointExit; } // ============================================================================ // CanReleaseTeam // // Checks whether this jail can release players of the given team. // ============================================================================ function bool CanReleaseTeam(TeamInfo Team) { local Actor thisActor; if (GetEventRelease(Team) == '') return False; foreach DynamicActors(Class'Actor', thisActor, GetEventRelease(Team)) return True; return False; } // ============================================================================ // CanReleaseBy // // Checks and returns whether the given player can trigger a release for the // given team. // ============================================================================ function bool CanReleaseBy(Controller Controller, TeamInfo Team) { local JBTagPlayer TagPlayer; if (Controller == None || Controller.PlayerReplicationInfo == None) return False; if ( Controller.Pawn == None || xPawn(Controller.Pawn) == None) return False; TagPlayer = Class'JBTagPlayer'.Static.FindFor(Controller.PlayerReplicationInfo); return (TagPlayer != None && TagPlayer.IsFree() && !IsJammed(Team.TeamIndex)); } // ============================================================================ // GetEventRelease // // Returns the value of EventReleaseRed or EventReleaseBlue depending on the // given team index. // ============================================================================ function name GetEventRelease(TeamInfo Team) { switch (Team.TeamIndex) { case 0: return EventReleaseRed; case 1: return EventReleaseBlue; } } // ============================================================================ // IsReleaseMoverOpen // // Checks and returns whether any release movers of this jail for the given // team are currently fully open. // ============================================================================ function bool IsReleaseMoverOpen(TeamInfo Team) { local int iMover; local TInfoRelease InfoRelease; InfoRelease = InfoReleaseByTeam[Team.TeamIndex]; for (iMover = 0; iMover < InfoRelease.ListMover.Length; iMover++) if (!InfoRelease.ListMover[iMover].bClosed && !InfoRelease.ListMover[iMover].bInterpolating) return True; // neither closed nor interpolating, thus open return False; } // ============================================================================ // IsReleaseMoverClosed // // Checks and returns whether all release movers of this jail for the given // team are fully closed. // ============================================================================ function bool IsReleaseMoverClosed(TeamInfo Team) { local int iMover; local TInfoRelease InfoRelease; InfoRelease = InfoReleaseByTeam[Team.TeamIndex]; for (iMover = 0; iMover < InfoRelease.ListMover.Length; iMover++) if (!InfoRelease.ListMover[iMover].bClosed) return False; return True; } // ============================================================================ // ContainsActor // // Returns whether this jail (including attached zones and volumes) contains // the given actor. Note that this is a physical relationship, not a logical // one; a player who's physically located in jail isn't necessarily a prisoner. // Use the IsInJail function in JBTagPlayer to check the latter. // ============================================================================ function bool ContainsActor(Actor Actor) { local int iVolume; if (Actor == None) return False; if (TagAttachZones == 'auto') { if (Actor.Region.ZoneNumber == Region.ZoneNumber) return True; } else { if (Actor.Region.Zone.Tag == TagAttachZones) return True; } for (iVolume = 0; iVolume < ListVolume.Length; iVolume++) if (ListVolume[iVolume].Encompasses(Actor)) return True; return False; } // ============================================================================ // RateJail // // Called by Jailbreak.RatePlayerStart() to determine which playerstart in what // jail should be used to spawn the player. Jails with a lower priority are // preferred over those with a higher one. // ============================================================================ function int RateJail() { if (PrisonerLimit > 0 && PrisonerLimit <= CountPlayersTotal()) // full! return -30000000; return 10000000/(Priority+1); } // ============================================================================ // CountPlayers // // Counts the number of players of the given team that are in this jail. // ============================================================================ function int CountPlayers(TeamInfo Team) { local int nPlayersJailed; local JBTagPlayer firstTagPlayer; local JBTagPlayer thisTagPlayer; firstTagPlayer = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstTagPlayer; for (thisTagPlayer = firstTagPlayer; thisTagPlayer != None; thisTagPlayer = thisTagPlayer.nextTag) if (thisTagPlayer.GetTeam() == Team && thisTagPlayer.GetJail() == Self) nPlayersJailed++; return nPlayersJailed; } // ============================================================================ // CountPlayersTotal // // Counts the total number of players that are in this jail. // ============================================================================ function int CountPlayersTotal() { local int nPlayersJailed; local JBTagPlayer firstTagPlayer; local JBTagPlayer thisTagPlayer; firstTagPlayer = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstTagPlayer; for (thisTagPlayer = firstTagPlayer; thisTagPlayer != None; thisTagPlayer = thisTagPlayer.nextTag) if (thisTagPlayer.GetJail() == Self) nPlayersJailed++; return nPlayersJailed; } // ============================================================================ // Release // // Releases the given team unless the release is already active or has been // jammed. Can be called only in state Waiting and logs a warning otherwise. // ============================================================================ function Release(TeamInfo Team, optional Controller ControllerInstigator) { local Controller thisController; local PlayerReplicationInfo PlayerReplicationInfoInstigator; local JBTagPlayer TagPlayer; local bool bCanPlayReleaseMessage; if (IsInState('Waiting')) { if (GetReleaseActive(Team.TeamIndex) || (IsJammed(Team.TeamIndex) && !IsForcedRelease(Team.TeamIndex))) return; if (ControllerInstigator != None && ControllerInstigator.PlayerReplicationInfo.Team != Team) { Log("Warning:" @ ControllerInstigator.PlayerReplicationInfo.PlayerName @ "on team" @ ControllerInstigator.PlayerReplicationInfo.Team.TeamIndex @ "attempted to release team" @ Team.TeamIndex); return; } if (CanReleaseTeam(Team)) { bCanPlayReleaseMessage = Jailbreak(Level.Game).CanPlayReleaseMessage(Team.TeamIndex); if (bCanPlayReleaseMessage || Jailbreak(Level.Game).CanFireEvent(GetEventRelease(Team), True)) { if (bCanPlayReleaseMessage || Jailbreak(Level.Game).CanFireEvent(Tag, True)) { if (ControllerInstigator != None) PlayerReplicationInfoInstigator = ControllerInstigator.PlayerReplicationInfo; if (CountPlayers(Team) > 0) for (thisController = Level.ControllerList; thisController != None; thisController = thisController.NextController) if (PlayerController(thisController) != None) { TagPlayer = Class'JBTagPlayer'.Static.FindFor(thisController.PlayerReplicationInfo); if (TagPlayer == None || TagPlayer.GetTeam() != Team || TagPlayer.GetJail() == none || TagPlayer.GetJail() == Self) { Jailbreak(Level.Game).PlayingReleaseMessage(Team.TeamIndex); Level.Game.BroadcastHandler.BroadcastLocalized( Self, PlayerController(thisController), MessageClass, 200, PlayerReplicationInfoInstigator, , Team); } } JBBotTeam(TeamGame(Level.Game).Teams[0].AI).NotifyReleaseTeam(Tag, Team, ControllerInstigator); JBBotTeam(TeamGame(Level.Game).Teams[1].AI).NotifyReleaseTeam(Tag, Team, ControllerInstigator); } if (ControllerInstigator != None) TriggerEventRelease(GetEventRelease(Team), Self, ControllerInstigator.Pawn); else TriggerEventRelease(GetEventRelease(Team), Self, None); } SetReleaseActive(Team.TeamIndex, True); InfoReleaseByTeam[Team.TeamIndex].bIsOpening = True; InfoReleaseByTeam[Team.TeamIndex].TimeActivation = Level.TimeSeconds; InfoReleaseByTeam[Team.TeamIndex].TimeReset = 0.0; // disabled InfoReleaseByTeam[Team.TeamIndex].ControllerInstigator = ControllerInstigator; NotifyJailOpening(Team); } else { CancelRelease(Team); } } else { Log("Warning: Release for" @ Self @ "should not be called in state" @ GetStateName()); } } // ============================================================================ // TriggerEventRelease // // Works like TriggerEvent, but hides the instigator from movers to avoid // getting team kills when a jail door crushes a teammate. // ============================================================================ function TriggerEventRelease(name event, Actor ActorSender, Pawn PawnInstigator) { local Actor thisActor; local NavigationPoint thisNavigationPoint; if (Event == '') return; foreach DynamicActors(Class'Actor', thisActor, Event) if (Mover(thisActor) == None) thisActor.Trigger(ActorSender, PawnInstigator); else thisActor.Trigger(ActorSender, None); // hide instigator from mover for (thisNavigationPoint = Level.NavigationPointList; thisNavigationPoint != None; thisNavigationPoint = thisNavigationPoint.NextNavigationPoint) if (thisNavigationPoint.bStatic && thisNavigationPoint.Tag == Event) thisNavigationPoint.Trigger(ActorSender, PawnInstigator); } // ============================================================================ // CancelRelease // // Cancels a release that has been initiated. If the release did not start yet, // doesn't open the jail doors, but marks the release as active and schedules // a reset shortly; otherwise just resets the internal release state and fires // the remaining notification events in the correct order as if the jail doors // had closed. // ============================================================================ function CancelRelease(TeamInfo Team) { if (GetReleaseActive(Team.TeamIndex)) { if (InfoReleaseByTeam[Team.TeamIndex].bIsOpening) NotifyJailOpened(Team); SetReleaseActive(Team.TeamIndex, False); InfoReleaseByTeam[Team.TeamIndex].bIsOpening = False; InfoReleaseByTeam[Team.TeamIndex].TimeReset = 0.0; // disable NotifyJailClosed(Team); ResetObjectives(Team); } else { SetReleaseActive(Team.TeamIndex, True); InfoReleaseByTeam[Team.TeamIndex].bIsOpening = False; InfoReleaseByTeam[Team.TeamIndex].TimeActivation = Level.TimeSeconds; InfoReleaseByTeam[Team.TeamIndex].TimeReset = Level.TimeSeconds + 2.0; } InfoReleaseByTeam[Team.TeamIndex].ControllerInstigator = None; } // ============================================================================ // NotifyJailOpening // // Called when the doors to this jail start opening before NotifyJailOpened is // called. Disables all GameObjectives that can be used to trigger this jail's // release and communicates the event to all inmates. // ============================================================================ function NotifyJailOpening(TeamInfo Team) { local GameObjective firstObjective; local GameObjective thisObjective; local JBGameRules firstJBGameRules; local JBTagPlayer firstTagPlayer; local JBTagPlayer thisTagPlayer; if (!IsJammed(Team.TeamIndex)) //dont play animation if the jail is jammed. { firstObjective = UnrealTeamInfo(Team).AI.Objectives; for (thisObjective = firstObjective; thisObjective != None; thisObjective = thisObjective.NextObjective) if (thisObjective.Event == Tag && thisObjective.DefenderTeamIndex != Team.TeamIndex) thisObjective.bDisabled = True; } firstTagPlayer = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstTagPlayer; for (thisTagPlayer = firstTagPlayer; thisTagPlayer != None; thisTagPlayer = thisTagPlayer.nextTag) if (thisTagPlayer.GetJail() == Self && thisTagPlayer.GetTeam() == Team) thisTagPlayer.NotifyJailOpening(); firstJBGameRules = Jailbreak(Level.Game).GetFirstJBGameRules(); if (firstJBGameRules != None) firstJBGameRules.NotifyJailOpening(Self, Team); } // ============================================================================ // NotifyJailOpened // // Called when the doors to this jail have fully opened. Communicates that // event to all inmates. // ============================================================================ function NotifyJailOpened(TeamInfo Team) { local JBGameRules firstJBGameRules; local JBTagPlayer firstTagPlayer; local JBTagPlayer thisTagPlayer; firstTagPlayer = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstTagPlayer; for (thisTagPlayer = firstTagPlayer; thisTagPlayer != None; thisTagPlayer = thisTagPlayer.nextTag) if (thisTagPlayer.GetJail() == Self && thisTagPlayer.GetTeam() == Team) thisTagPlayer.NotifyJailOpened(); firstJBGameRules = Jailbreak(Level.Game).GetFirstJBGameRules(); if (firstJBGameRules != None) firstJBGameRules.NotifyJailOpened(Self, Team); } // ============================================================================ // NotifyJailEntered // // Called when a player enters this jail from an arena or from freedom. If the // jail doors are currently open, notifies the player about it. // ============================================================================ function NotifyJailEntered(JBTagPlayer TagPlayer) { local int iTeam; local JBGameRules firstJBGameRules; iTeam = TagPlayer.GetTeam().TeamIndex; if (GetReleaseActive(iTeam) && InfoReleaseByTeam[iTeam].TimeReset == 0.0) { TagPlayer.NotifyJailOpening(); if (!InfoReleaseByTeam[iTeam].bIsOpening) TagPlayer.NotifyJailOpened(); } firstJBGameRules = Jailbreak(Level.Game).GetFirstJBGameRules(); if (firstJBGameRules != None) firstJBGameRules.NotifyPlayerJailed(TagPlayer); } // ============================================================================ // NotifyJailLeft // // Called when a player left this jail for an arena or for freedom. // ============================================================================ function NotifyJailLeft(JBTagPlayer TagPlayer) { local JBGameRules firstJBGameRules; firstJBGameRules = Jailbreak(Level.Game).GetFirstJBGameRules(); if (firstJBGameRules != None) firstJBGameRules.NotifyPlayerReleased(TagPlayer, Self); } // ============================================================================ // NotifyJailClosed // // Called when this jail is closed. Communicates that event to all inmates. // ============================================================================ function NotifyJailClosed(TeamInfo Team) { local JBGameRules firstJBGameRules; local JBTagPlayer firstTagPlayer; local JBTagPlayer thisTagPlayer; firstTagPlayer = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstTagPlayer; for (thisTagPlayer = firstTagPlayer; thisTagPlayer != None; thisTagPlayer = thisTagPlayer.nextTag) if (thisTagPlayer.GetJail() == Self && thisTagPlayer.GetTeam() == Team) thisTagPlayer.NotifyJailClosed(); firstJBGameRules = Jailbreak(Level.Game).GetFirstJBGameRules(); if (firstJBGameRules != None) firstJBGameRules.NotifyJailClosed(Self, Team); } // ============================================================================ // ResetObjectives // // Resets all objectives associated with this jail for the given team unless // the release for another jail listening to the same event is still active. // ============================================================================ function ResetObjectives(TeamInfo Team) { local GameObjective firstObjective; local GameObjective thisObjective; local JBInfoJail firstJail; local JBInfoJail thisJail; firstJail = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstJail; for (thisJail = firstJail; thisJail != None; thisJail = thisJail.nextJail) if (thisJail != Self && thisJail.Tag == Tag && thisJail.IsReleaseActive(Team)) return; firstObjective = UnrealTeamInfo(Team).AI.Objectives; for (thisObjective = firstObjective; thisObjective != None; thisObjective = thisObjective.NextObjective) if (thisObjective.Event == Tag && thisObjective.DefenderTeamIndex != Team.TeamIndex && thisObjective.bDisabled) thisObjective.Reset(); } // ============================================================================ // ActivateCameraFor // // Activates the attached camera or camera array for the given player. // ============================================================================ function ActivateCameraFor(Controller Controller) { local JBCamera thisCamera; if (PlayerController(Controller) != None) foreach DynamicActors(Class'JBCamera', thisCamera, Event) thisCamera.TriggerForController(Self, Controller); } // ============================================================================ // ExecutePlayer // // Executes the given player. Used for fallback execution. // ============================================================================ function ExecutePlayer(Controller Controller) { if (Controller.Pawn != None) Controller.Pawn.Died(None, Class'Suicided', Controller.Pawn.Location); } // ============================================================================ // ExecutionInit // // Initiates the execution sequence. Can be called only in state Waiting and // logs a warning otherwise. // ============================================================================ function ExecutionInit() { if (IsInState('Waiting')) GotoState('ExecutionStarting'); else Log("Warning: Called ExecutionInit for" @ Self @ "in state" @ GetStateName()); } // ============================================================================ // ExecutionEnd // // Finishes up an ongoing execution by gibbing all players remaining in jail // and going back to state Waiting. Can be called only in states // ExecutionRunning and ExecutionFallback. // ============================================================================ function ExecutionEnd() { local JBTagPlayer firstTagPlayer; local JBTagPlayer thisTagPlayer; if (IsInState('ExecutionRunning') || IsInState('ExecutionFallback')) { firstTagPlayer = JBGameReplicationInfo(Level.Game.GameReplicationInfo).firstTagPlayer; for (thisTagPlayer = firstTagPlayer; thisTagPlayer != None; thisTagPlayer = thisTagPlayer.nextTag) if (thisTagPlayer.GetJail() == Self) ExecutePlayer(thisTagPlayer.GetController()); if (bIsFinalExecution && EventFinalExecutionEnd != '') { if (Jailbreak(Level.Game).CanFireEvent(EventFinalExecutionEnd, True)) TriggerEvent(EventFinalExecutionEnd, Self, None); } else { if (Jailbreak(Level.Game).CanFireEvent(EventExecutionEnd, True)) TriggerEvent(EventExecutionEnd, Self, None); } bIsFinalExecution = False; GotoState('Waiting'); } else { Log("Warning: Called ExecutionEnd for" @ Self @ "in state" @ GetStateName()); } } // ============================================================================ // GetReleaseActive // // Returns whether or not the specified team is currently being released. // ============================================================================ simulated function bool GetReleaseActive(int TeamIndex) { switch (TeamIndex) { case 0: return bIsRedActive; case 1: return bIsBlueActive; default: return false; } } // ============================================================================ // SetReleaseActive // ============================================================================ simulated protected function SetReleaseActive(int TeamIndex, bool Value) { switch (TeamIndex) { case 0: bIsRedActive = Value; break; case 1: bIsBlueActive = Value; break; } } // ============================================================================ // Jam // // Jams the jail for the given team. A regular release isn't possible any more. // ============================================================================ function Jam(int TeamIndex) { if (GetReleaseActive(TeamIndex)) CancelRelease(Jailbreak(Level.Game).Teams[TeamIndex]); // Cancel any ongoing release switch (TeamIndex) { case 0: bRedJammed = True; break; case 1: bBlueJammed = True; break; } JamResetObjectives(TeamIndex); } // ============================================================================ // UnJam // // UnJams the jail for the given team. A regular release is possible again. // ============================================================================ function UnJam(int TeamIndex) { switch (TeamIndex) { case 0: bRedJammed = False; break; case 1: bBlueJammed = False; break; } JamResetObjectives(TeamIndex); } // ============================================================================ // JamResetObjectives // // Resets the GameObjectives that trigger this JBInfoJail. // ============================================================================ protected function JamResetObjectives(int TeamIndex) { local GameObjective firstObjective; local GameObjective thisObjective; firstObjective = Jailbreak(Level.Game).Teams[TeamIndex].AI.Objectives; // Find all objectives that trigger this JBInfoJail, then reset them for (thisObjective = firstObjective; thisObjective != None; thisObjective = thisObjective.NextObjective) if (thisObjective.Event == Tag && thisObjective.DefenderTeamIndex != TeamIndex) thisObjective.Reset(); } // ============================================================================ // IsJammed // // Returns if this jail is jammed for the given team. // ============================================================================ simulated function bool IsJammed(int TeamIndex) { switch (TeamIndex) { case 0: return bRedJammed; case 1: return bBlueJammed; default: return False; } } // ============================================================================ // IsForcedRelease // // Returns if the release was forced for the given team. // ============================================================================ function bool IsForcedRelease(int TeamIndex) { switch (TeamIndex) { case 0: return bForcedReleaseRed; case 1: return bForcedReleaseBlue; default: return False; } } // ============================================================================ // ForceRelease // // Releases even though the jails are jammed. JBGameRules is first consulted // before actually releasing. Returns if the team was actually released. // ============================================================================ function bool ForceRelease(TeamInfo Team, optional Controller ControllerInstigator) { local JBGameRules firstJBGameRules; local bool bAllowForcedRelease; if (!IsInState('Waiting') || GetReleaseActive(Team.TeamIndex)) return False; if(!IsJammed(Team.TeamIndex)) { Release(Team, ControllerInstigator); return True; } firstJBGameRules = Jailbreak(Level.Game).GetFirstJBGameRules(); if (firstJBGameRules != None) bAllowForcedRelease = firstJBGameRules.AllowForcedRelease(Self, Team, ControllerInstigator); if (bAllowForcedRelease) { switch (Team.TeamIndex) { case 0: bForcedReleaseRed = True; Release(Team, ControllerInstigator); bForcedReleaseRed = False; break; case 1: bForcedReleaseBlue = True; Release(Team, ControllerInstigator); bForcedReleaseBlue = False; break; } } return bAllowForcedRelease; } // ============================================================================ // state Waiting // // Jail waits for a release to be triggered or an execution to be started. // ============================================================================ auto state Waiting { // ================================================================ // BeginState // // Starts the timer. // ================================================================ event BeginState() { SetTimer(0.2, True); } // ================================================================ // Trigger // // If triggered from a GameObjective, releases players from the // team that can attack that objective even if the release was // triggered by a defender. Otherwise releases the triggering // player's team. // ================================================================ event Trigger(Actor ActorOther, Pawn PawnInstigator) { local Controller ControllerInstigator; local GameObjective firstObjective; local GameObjective thisObjective; local GameObjective ObjectiveRelease; local TeamInfo TeamRelease; local JBGameRules firstJBGameRules; ObjectiveRelease = GameObjective(ActorOther); if (ObjectiveRelease != None) TeamRelease = TeamGame(Level.Game).OtherTeam(TeamGame(Level.Game).Teams