Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class UISL_TacticalHUD_StealthExample extends UIScreenListener;
- // TODO use GetCoverTypeForTarget to examine the path and ignore blocked concealment tiles for the path warning.
- // override XComPathingPawn.RebuildPathInformation
- // see Helpers.GetInstalledModNames to handle perfect information conflict??
- // This event is triggered after a screen is initialized
- event OnInit(UIScreen UITacticalHUD)
- {
- local Object ThisObj;
- if (UITacticalHUD(UITacticalHUD) == none)
- return;
- `LOG("Starting TacticalHUD Listener OnInit: " @ self,, 'StealthExample');
- // make sure new units (eg. from reinforcements) have their movement events deregistered
- // This assumes that units don't spawn during the player's turn
- //`XCOMHISTORY.RegisterOnNewGameStateDelegate(OnNewGameState);
- ThisObj = self;
- `XEVENTMGR.RegisterForEvent(ThisObj, 'PlayerTurnBegun', BeginTurn, ELD_OnStateSubmitted);
- AttachCallbacks();
- }
- function EventListenerReturn BeginTurn(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData) {
- AttachCallbacks();
- return ELR_NoInterrupt;
- }
- // This removes the default ObjectMoved callback from units. It is replaced with the code in this class.
- private function AttachCallbacks() {
- local Object ThisObj;
- local X2EventManager EventMgr;
- local XComGameStateHistory History;
- local XComGameState_Unit UnitState;
- local XComGameState_Player PlayerState;
- History = `XCOMHISTORY;
- EventMgr = `XEVENTMGR;
- ThisObj = self;
- foreach History.IterateByClassType(class'XComGameState_Unit', UnitState)
- {
- // remove vanilla callbacks
- EventMgr.UnRegisterFromEvent(UnitState, 'ObjectMoved');
- //EventMgr.UnRegisterFromEvent(UnitState, 'UnitTakeEffectDamage');
- }
- foreach History.IterateByClassType(class'XComGameState_Player', PlayerState)
- {
- // remove vanilla callbacks
- EventMgr.UnRegisterFromEvent(PlayerState, 'ObjectVisibilityChanged');
- }
- // handle movement events ourselves
- EventMgr.RegisterForEvent(ThisObj, 'ObjectMoved', OnUnitEnteredTile, ELD_OnStateSubmitted);
- EventMgr.RegisterForEvent(ThisObj, 'ObjectVisibilityChanged', OnObjectVisibilityChanged, ELD_OnStateSubmitted);
- }
- // For the most part copy of XComGameState_Unit:OnUnitEnteredTile
- // change to vanilla: reveal only on alien turn
- function EventListenerReturn OnUnitEnteredTile(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData)
- {
- local XComGameState_Unit OtherUnitState, ThisUnitState;
- local XComGameStateHistory History;
- local X2GameRulesetVisibilityManager VisibilityMgr;
- local GameRulesCache_VisibilityInfo VisibilityInfoFromThisUnit, VisibilityInfoFromOtherUnit;
- local float ConcealmentDetectionDistance;
- local XComGameState_AIGroup AIGroupState;
- local XComGameStateContext_Ability SourceAbilityContext;
- local XComGameState_InteractiveObject InteractiveObjectState;
- local XComWorldData WorldData;
- local Vector CurrentPosition, TestPosition;
- local TTile CurrentTileLocation;
- local XComGameState_Effect EffectState;
- local X2Effect_Persistent PersistentEffect;
- local XComGameState NewGameState;
- local XComGameStateContext_EffectRemoved EffectRemovedContext;
- local bool DoesUnitBreaksConcealmentIgnoringDistance;
- local name RetainConcealmentName;
- local bool RetainConcealment;
- WorldData = `XWORLD;
- History = `XCOMHISTORY;
- ThisUnitState = XComGameState_Unit(EventData);
- if (ThisUnitState.GetMyTemplate().bIsCosmetic) { return ELR_NoInterrupt; }
- // cleanse burning on entering water
- ThisUnitState.GetKeystoneVisibilityLocation(CurrentTileLocation);
- if( ThisUnitState.IsBurning() && WorldData.IsWaterTile(CurrentTileLocation) )
- {
- foreach History.IterateByClassType(class'XComGameState_Effect', EffectState)
- {
- if( EffectState.ApplyEffectParameters.TargetStateObjectRef.ObjectID == ThisUnitState.ObjectID )
- {
- PersistentEffect = EffectState.GetX2Effect();
- if( PersistentEffect.EffectName == class'X2StatusEffects'.default.BurningName )
- {
- EffectRemovedContext = class'XComGameStateContext_EffectRemoved'.static.CreateEffectRemovedContext(EffectState);
- NewGameState = History.CreateNewGameState(true, EffectRemovedContext);
- EffectState.RemoveEffect(NewGameState, NewGameState, true); //Cleansed
- `TACTICALRULES.SubmitGameState(NewGameState);
- }
- }
- }
- }
- SourceAbilityContext = XComGameStateContext_Ability(GameState.GetContext());
- if( SourceAbilityContext != None )
- {
- // concealment for this unit is broken when stepping into a new tile if the act of stepping into the new tile caused environmental damage (ex. "broken glass")
- // if this occurred, then the GameState will contain either an environmental damage state or an InteractiveObject state
- // unless you're in challenge mode, then breaking stuff doesn't break concealment
- // change to vanilla: reveal only on alien turn
- if(IsAlienTurn() && ThisUnitState.IsConcealed() && SourceAbilityContext.ResultContext.bPathCausesDestruction && (History.GetSingleGameStateObjectForClass( class'XComGameState_ChallengeData', true ) == none))
- {
- ThisUnitState.BreakConcealment();
- `LOG(default.class @ GetFuncName() @ "125 BreakConcealment",, 'StealthExample');
- }
- ThisUnitState = XComGameState_Unit(History.GetGameStateForObjectID(ThisUnitState.ObjectID));
- // check if this unit is a member of a group waiting on this unit's movement to complete
- // (or at least reach the interruption step where the movement should complete)
- AIGroupState = ThisUnitState.GetGroupMembership();
- if( AIGroupState != None &&
- AIGroupState.IsWaitingOnUnitForReveal(ThisUnitState) &&
- (SourceAbilityContext.InterruptionStatus != eInterruptionStatus_Interrupt ||
- (AIGroupState.FinalVisibilityMovementStep > INDEX_NONE &&
- AIGroupState.FinalVisibilityMovementStep <= SourceAbilityContext.ResultContext.InterruptionStep)) )
- {
- AIGroupState.StopWaitingOnUnitForReveal(ThisUnitState);
- }
- }
- // concealment may be broken by moving within range of an interactive object 'detector'
- if( ThisUnitState.IsConcealed() )
- {
- foreach class'X2AbilityTemplateManager'.default.AbilityRetainsConcealmentVsInteractives(RetainConcealmentName)
- {
- if (ThisUnitState.HasSoldierAbility(RetainConcealmentName))
- {
- RetainConcealment = true;
- break;
- }
- }
- if (!RetainConcealment)
- {
- ThisUnitState.GetKeystoneVisibilityLocation(CurrentTileLocation);
- CurrentPosition = WorldData.GetPositionFromTileCoordinates(CurrentTileLocation);
- foreach History.IterateByClassType(class'XComGameState_InteractiveObject', InteractiveObjectState)
- {
- if (InteractiveObjectState.DetectionRange > 0.0 && !InteractiveObjectState.bHasBeenHacked)
- {
- TestPosition = WorldData.GetPositionFromTileCoordinates(InteractiveObjectState.TileLocation);
- if (VSizeSq(TestPosition - CurrentPosition) <= Square(InteractiveObjectState.DetectionRange))
- {
- ThisUnitState.BreakConcealment();
- `LOG(default.class @ GetFuncName() @ "169 BreakConcealment",, 'StealthExample');
- ThisUnitState = XComGameState_Unit(History.GetGameStateForObjectID(ThisUnitState.ObjectID));
- break;
- }
- }
- }
- }
- }
- // concealment may also be broken if this unit moves into detection range of an enemy unit
- VisibilityMgr = `TACTICALRULES.VisibilityMgr;
- foreach History.IterateByClassType(class'XComGameState_Unit', OtherUnitState)
- {
- // don't process visibility against self
- if( OtherUnitState.ObjectID == ThisUnitState.ObjectID )
- {
- continue;
- }
- VisibilityMgr.GetVisibilityInfo(ThisUnitState.ObjectID, OtherUnitState.ObjectID, VisibilityInfoFromThisUnit);
- if( VisibilityInfoFromThisUnit.bVisibleBasic )
- {
- // check if the other unit is concealed, and this unit's move has revealed him
- // change to vanilla: reveal only on alien turn
- if( IsAlienTurn() &&
- OtherUnitState.IsConcealed() &&
- OtherUnitState.UnitBreaksConcealment(ThisUnitState) &&
- VisibilityInfoFromThisUnit.TargetCover == CT_None )
- {
- DoesUnitBreaksConcealmentIgnoringDistance = ThisUnitState.DoesUnitBreaksConcealmentIgnoringDistance();
- if( !DoesUnitBreaksConcealmentIgnoringDistance )
- {
- ConcealmentDetectionDistance = OtherUnitState.GetConcealmentDetectionDistance(ThisUnitState);
- }
- if( DoesUnitBreaksConcealmentIgnoringDistance ||
- VisibilityInfoFromThisUnit.DefaultTargetDist <= Square(ConcealmentDetectionDistance) )
- {
- `LOG(default.class @ GetFuncName() @ "209 BreakConcealment",, 'StealthExample');
- OtherUnitState.BreakConcealment(ThisUnitState, true);
- // have to refresh the unit state after broken concealment
- OtherUnitState = XComGameState_Unit(History.GetGameStateForObjectID(OtherUnitState.ObjectID));
- }
- }
- // generate alert data for this unit about other units
- UnitASeesUnitB(ThisUnitState, OtherUnitState, GameState);
- }
- // only need to process visibility updates from the other unit if it is still alive
- if( OtherUnitState.IsAlive() )
- {
- VisibilityMgr.GetVisibilityInfo(OtherUnitState.ObjectID, ThisUnitState.ObjectID, VisibilityInfoFromOtherUnit);
- if( VisibilityInfoFromOtherUnit.bVisibleBasic )
- {
- // check if this unit is concealed and that concealment is broken by entering into an enemy's detection tile
- // change to vanilla: reveal only on alien turn
- if(IsAlienTurn() && ThisUnitState.IsConcealed() && ThisUnitState.UnitBreaksConcealment(OtherUnitState))
- {
- DoesUnitBreaksConcealmentIgnoringDistance = OtherUnitState.DoesUnitBreaksConcealmentIgnoringDistance();
- if (!DoesUnitBreaksConcealmentIgnoringDistance)
- {
- ConcealmentDetectionDistance = ThisUnitState.GetConcealmentDetectionDistance(OtherUnitState);
- }
- if( DoesUnitBreaksConcealmentIgnoringDistance ||
- VisibilityInfoFromOtherUnit.DefaultTargetDist <= Square(ConcealmentDetectionDistance) )
- {
- `LOG(default.class @ GetFuncName() @ "242 BreakConcealment",, 'StealthExample');
- ThisUnitState.BreakConcealment(OtherUnitState);
- // have to refresh the unit state after broken concealment
- ThisUnitState = XComGameState_Unit(History.GetGameStateForObjectID(ThisUnitState.ObjectID));
- }
- }
- // generate alert data for other units that see this unit
- if( VisibilityInfoFromOtherUnit.bVisibleBasic) // && !ThisUnitState.IsConcealed() )
- {
- // don't register an alert if this unit is about to reflex
- AIGroupState = OtherUnitState.GetGroupMembership();
- if (AIGroupState == none || AIGroupState.EverSightedByEnemy)
- UnitASeesUnitB(OtherUnitState, ThisUnitState, GameState);
- }
- }
- }
- }
- return ELR_NoInterrupt;
- }
- // For the most part copy of XComGameState_Player:OnObjectVisibilityChanged
- // change to vanilla: reveal only on alien turn
- function EventListenerReturn OnObjectVisibilityChanged(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData)
- {
- local X2GameRulesetVisibilityInterface SourceObject;
- local XComGameState_Unit SeenUnit;
- local XComGameState_Unit SourceUnit;
- local GameRulesCache_VisibilityInfo VisibilityInfo;
- local X2GameRulesetVisibilityManager VisibilityMgr;
- local XComGameState NewGameState;
- local XComGameState_Player UpdatedPlayerState;
- VisibilityMgr = `TACTICALRULES.VisibilityMgr;
- SourceObject = X2GameRulesetVisibilityInterface(EventSource);
- SeenUnit = XComGameState_Unit(EventData); // we only care about enemy units
- if(SeenUnit != none && SourceObject.TargetIsEnemy(SeenUnit.ObjectID) && !SeenUnit.GetMyTemplate().bIsCosmetic)
- {
- SourceUnit = XComGameState_Unit(SourceObject);
- if(SourceUnit != none && GameState != none)
- {
- VisibilityMgr.GetVisibilityInfo(SourceUnit.ObjectID, SeenUnit.ObjectID, VisibilityInfo, GameState.HistoryIndex);
- if(VisibilityInfo.bVisibleGameplay)
- {
- //if(TurnsSinceEnemySeen > 0 && SeenUnit.IsAlive())
- //{
- // NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("PlayerRecordEnemiesSeen");
- // UpdatedPlayerState = XComGameState_Player(NewGameState.ModifyStateObject(Class, ObjectID));
- // UpdatedPlayerState.TurnsSinceEnemySeen = 0;
- // `GAMERULES.SubmitGameState(NewGameState);
- //}
- //Inform the units that they see each other
- UnitASeesUnitB(SourceUnit, SeenUnit, GameState);
- }
- else if (VisibilityInfo.bVisibleBasic)
- {
- // If the target is not yet gameplay-visible, it might be because they are concealed.
- // Check if the source should break their concealment due to the new conditions.
- // (Typically happens in XComGameState_Unit when a unit moves, but there are edge cases,
- // like blowing up the last structure between two units, when it needs to happen here.)
- // change to vanilla: reveal only on alien turn
- if (IsAlienTurn() && SeenUnit.IsConcealed() && SeenUnit.UnitBreaksConcealment(SourceUnit) && VisibilityInfo.TargetCover == CT_None)
- {
- if (VisibilityInfo.DefaultTargetDist <= Square(SeenUnit.GetConcealmentDetectionDistance(SourceUnit)))
- {
- `LOG(default.class @ GetFuncName() @ "311 BreakConcealment" @ (VisibilityInfo.TargetCover == CT_None),, 'StealthExample');
- SeenUnit.BreakConcealment(SourceUnit, VisibilityInfo.TargetCover == CT_None);
- }
- }
- }
- }
- }
- return ELR_NoInterrupt;
- }
- static function bool IsAlienTurn()
- {
- local StateObjectReference HumanPlayer, ActivePlayer;
- HumanPlayer = XComTacticalController(class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController()).ControllingPlayer;
- ActivePlayer = GetActivePlayer();
- // `LOG(default.class @ GetFuncName() @ "IsAlienTurn" @ (HumanPlayer != ActivePlayer),, 'StealthExample');
- return (HumanPlayer != ActivePlayer);
- }
- static function StateObjectReference GetActivePlayer()
- {
- local XComGameStateHistory History;
- local XComGameStateContext_TacticalGameRule Context;
- local StateObjectReference NullReference;
- History = `XCOMHISTORY;
- foreach History.IterateContextsByClassType(class'XComGameStateContext_TacticalGameRule', Context)
- {
- if(Context.GameRuleType == eGameRule_PlayerTurnBegin)
- {
- return Context.PlayerRef;
- }
- }
- return NullReference;
- }
- static function UnitASeesUnitB(XComGameState_Unit UnitA, XComGameState_Unit UnitB, XComGameState AlertInstigatingGameState)
- {
- local EAlertCause AlertCause;
- local XComGameState_AIGroup UnitBGroup;
- AlertCause = eAC_None;
- // Ignore the fact that we saw a cosmetic unit. It's the non-cosmetic parent that we care about having seen.
- if (UnitB.GetMyTemplate().bIsCosmetic)
- {
- return;
- }
- if (!UnitA.IsDead() && !UnitB.IsDead())
- {
- `XEVENTMGR.TriggerEvent('UnitSeesUnit', UnitA, UnitB, AlertInstigatingGameState);
- }
- if( (!UnitB.IsDead() || !UnitA.HasSeenCorpse(UnitB.ObjectID)) && UnitB.GetTeam() != eTeam_Neutral )
- {
- if( UnitB.IsDead() )
- {
- AlertCause = eAC_DetectedNewCorpse;
- UnitA.MarkCorpseSeen(UnitB.ObjectID);
- }
- else if( UnitA.IsEnemyUnit(UnitB) )
- {
- if (!UnitB.IsConcealed())
- AlertCause = eAC_SeesSpottedUnit;
- }
- else if( UnitB.GetCurrentStat(eStat_AlertLevel) > 0 )
- {
- // Prevent alerting the group if this is a fallback unit. (Fallback is not meant to aggro the other group)
- UnitBGroup = UnitB.GetGroupMembership();
- if( UnitBGroup == None || !UnitBGroup.IsFallingBack() )
- {
- AlertCause = eAC_SeesAlertedAllies;
- }
- }
- //`LOG(default.class @ GetFuncName() @ UnitA.GetFirstName() @ UnitA.ObjectID @ "GainsKnowledgeOf" @ UnitB.GetFullName() @ UnitB.ObjectID @ AlertCause,, 'StealthExample');
- UnitA.UnitAGainsKnowledgeOfUnitB(UnitA, UnitB, AlertInstigatingGameState, AlertCause, true);
- }
- }
- defaultproperties {
- ScreenClass = UITacticalHUD
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement