class Hat_AnimNotify_SendOnlinePartyCommand extends AnimNotify_Scripted; /* AnimNotify that sends Online Party Command when triggered. */ var() string Command; var() bool UseCustomCommandChannel; var() Name CommandChannel; var(Modding) bool UseModClassPathName; var(Modding) string ModClassPathName; var(Sender) bool FixedPlayerSender; var(Sender) int SenderPlayerIndex; event Notify(Actor Owner, AnimNodeSequence AnimSeqInstigator) { local PlayerController pc; local GameMod ModInstance; if (GetOnlinePlayerOwner(Owner) != None) //Online Players can't send commands. return; ModInstance = GetModInstance(Owner); if (ModInstance == None) return; if (FixedPlayerSender) pc = GetPlayerByIndex(SenderPlayerIndex); else pc = GetPlayerController(Owner); if (pc != None && pc.Pawn != None) ModInstance.SendOnlinePartyCommand(Command, UseCustomCommandChannel ? CommandChannel : ModInstance.Class.GetPackageName(), pc.Pawn, None); } final simulated function GameMod GetModInstance(Actor Owner) { local Actor a; local class ModClass; if (Owner == None) return None; if (UseModClassPathName) ModClass = class(class'Hat_ClassHelper'.static.GetScriptClass(ModClassPathName)); else ModClass = class(class'GameMod'.static.GetGameModFromClass(Class).ModClass); if (ModClass == None || ClassIsDeprecated(ModClass)) return None; foreach Owner.AllActors(ModClass, a) { if (a != None) return GameMod(a); } return None; } final static function Hat_GhostPartyPlayerBase GetOnlinePlayerOwner(Actor a, optional out Array IteratedActors) //Returns Hat_GhostPartyPlayerBase Actor from Owner chain of Actor. { local Hat_GhostPartyPlayerBase gpp; if (a == None) return None; gpp = Hat_GhostPartyPlayerBase(a); if (gpp != None) return gpp; if (IteratedActors.Find(a) > -1) //Preventing a chain of Actors that have Owner set as another Actor (or itself). This should NEVER occur. return None; IteratedActors.AddItem(a); return GetOnlinePlayerOwner(a.Owner, IteratedActors); } final static function bool IsCorrectPlayerIndex(int n) //Very obvious check: player index can't be lower than 0. { if (n < 0) return false; return true; } final static function PlayerController GetPlayerByIndex(int PlayerIndex) //Returns PlayerController that corresponds to this player index. { local Engine e; local PlayerController pc; if (!IsCorrectPlayerIndex(PlayerIndex)) return None; pc = class'Hat_PlayerController_Base'.static.GetPlayerByIndex(PlayerIndex); if (pc != None) return pc; e = class'Engine'.static.GetEngine(); if (e == None) return None; if (e.GamePlayers.Length <= PlayerIndex) return None; if (e.GamePlayers[PlayerIndex] == None) return None; return e.GamePlayers[PlayerIndex].Actor; } final static function PlayerController GetPlayerController(Object o, optional out Array IteratedActors) //Returns PlayerController. Input parameter can be Actor and Player. IteratedActors is used to prevent infinite loop when iterating Owner chain if o is Actor. { local HUD H; local Pawn p; local Actor a; local PlayerController pc; local Player EnginePlayer; a = Actor(o); if (a != None) { pc = PlayerController(a); if (pc != None) return pc; p = Pawn(a); if (p != None) return GetPawnPlayerController(p); H = HUD(a); if (H != None) return H.PlayerOwner; if (IteratedActors.Find(a) < 0) IteratedActors.AddItem(a); else return None; return GetPlayerController(a.Owner, IteratedActors); } EnginePlayer = Player(o); if (EnginePlayer != None) return EnginePlayer.Actor; return None; } final static function PlayerController GetPawnPlayerController(Pawn p, optional out Array IteratedPawns) //Returns PlayerController for Pawn. Will check Pawn itself and DrivenVehicle for PlayerController. IteratedPawns is used to prevent infinite loop when iterating Vehicle's Driver and Pawn's DrivenVehicle. { local Vehicle v; local PlayerController pc; if (p == None) return None; pc = PlayerController(p.Controller); if (pc != None) return pc; if (IteratedPawns.Find(p) < 0) IteratedPawns.AddItem(p); else return None; v = Vehicle(p); if (v != None) { pc = GetPawnPlayerController(v.Driver, IteratedPawns); if (pc != None) return pc; } return GetPawnPlayerController(p.DrivenVehicle, IteratedPawns); }