Advertisement
Guest User

Untitled

a guest
May 2nd, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class UISL_TacticalHUD_StealthExample extends UIScreenListener;
  2.  
  3. // TODO use GetCoverTypeForTarget to examine the path and ignore blocked concealment tiles for the path warning.
  4. // override XComPathingPawn.RebuildPathInformation
  5. // see Helpers.GetInstalledModNames to handle perfect information conflict??
  6.  
  7. // This event is triggered after a screen is initialized
  8. event OnInit(UIScreen UITacticalHUD)
  9. {
  10.     local Object ThisObj;
  11.  
  12.     if (UITacticalHUD(UITacticalHUD) == none)
  13.         return;
  14.  
  15.     `LOG("Starting TacticalHUD Listener OnInit: " @ self,, 'StealthExample');
  16.  
  17.     // make sure new units (eg. from reinforcements) have their movement events deregistered
  18.     // This assumes that units don't spawn during the player's turn
  19.     //`XCOMHISTORY.RegisterOnNewGameStateDelegate(OnNewGameState);
  20.     ThisObj = self;
  21.     `XEVENTMGR.RegisterForEvent(ThisObj, 'PlayerTurnBegun', BeginTurn, ELD_OnStateSubmitted);
  22.  
  23.     AttachCallbacks();
  24. }
  25.  
  26. function EventListenerReturn BeginTurn(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData) {
  27.     AttachCallbacks();
  28.     return ELR_NoInterrupt;
  29. }
  30.  
  31. // This removes the default ObjectMoved callback from units.  It is replaced with the code in this class.
  32. private function AttachCallbacks() {
  33.     local Object ThisObj;
  34.     local X2EventManager EventMgr;
  35.     local XComGameStateHistory History;
  36.     local XComGameState_Unit UnitState;
  37.     local XComGameState_Player PlayerState;
  38.  
  39.     History = `XCOMHISTORY;
  40.     EventMgr = `XEVENTMGR;
  41.     ThisObj = self;
  42.  
  43.     foreach History.IterateByClassType(class'XComGameState_Unit', UnitState)
  44.     {
  45.         // remove vanilla callbacks
  46.         EventMgr.UnRegisterFromEvent(UnitState, 'ObjectMoved');
  47.         //EventMgr.UnRegisterFromEvent(UnitState, 'UnitTakeEffectDamage');
  48.     }
  49.  
  50.     foreach History.IterateByClassType(class'XComGameState_Player', PlayerState)
  51.     {
  52.         // remove vanilla callbacks
  53.         EventMgr.UnRegisterFromEvent(PlayerState, 'ObjectVisibilityChanged');                                                          
  54.     }
  55.    
  56.     // handle movement events ourselves
  57.     EventMgr.RegisterForEvent(ThisObj, 'ObjectMoved', OnUnitEnteredTile, ELD_OnStateSubmitted);
  58.     EventMgr.RegisterForEvent(ThisObj, 'ObjectVisibilityChanged', OnObjectVisibilityChanged, ELD_OnStateSubmitted);
  59. }
  60.  
  61. // For the most part copy of XComGameState_Unit:OnUnitEnteredTile
  62. // change to vanilla: reveal only on alien turn
  63. function EventListenerReturn OnUnitEnteredTile(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData)
  64. {
  65.     local XComGameState_Unit OtherUnitState, ThisUnitState;
  66.     local XComGameStateHistory History;
  67.     local X2GameRulesetVisibilityManager VisibilityMgr;
  68.     local GameRulesCache_VisibilityInfo VisibilityInfoFromThisUnit, VisibilityInfoFromOtherUnit;
  69.     local float ConcealmentDetectionDistance;
  70.     local XComGameState_AIGroup AIGroupState;
  71.     local XComGameStateContext_Ability SourceAbilityContext;
  72.     local XComGameState_InteractiveObject InteractiveObjectState;
  73.     local XComWorldData WorldData;
  74.     local Vector CurrentPosition, TestPosition;
  75.     local TTile CurrentTileLocation;
  76.     local XComGameState_Effect EffectState;
  77.     local X2Effect_Persistent PersistentEffect;
  78.     local XComGameState NewGameState;
  79.     local XComGameStateContext_EffectRemoved EffectRemovedContext;
  80.     local bool DoesUnitBreaksConcealmentIgnoringDistance;
  81.     local name RetainConcealmentName;
  82.     local bool RetainConcealment;
  83.  
  84.     WorldData = `XWORLD;
  85.     History = `XCOMHISTORY;
  86.  
  87.     ThisUnitState = XComGameState_Unit(EventData);
  88.  
  89.     if (ThisUnitState.GetMyTemplate().bIsCosmetic) { return ELR_NoInterrupt; }
  90.  
  91.     // cleanse burning on entering water
  92.     ThisUnitState.GetKeystoneVisibilityLocation(CurrentTileLocation);
  93.     if( ThisUnitState.IsBurning() && WorldData.IsWaterTile(CurrentTileLocation) )
  94.     {
  95.         foreach History.IterateByClassType(class'XComGameState_Effect', EffectState)
  96.         {
  97.             if( EffectState.ApplyEffectParameters.TargetStateObjectRef.ObjectID == ThisUnitState.ObjectID )
  98.             {
  99.                 PersistentEffect = EffectState.GetX2Effect();
  100.                 if( PersistentEffect.EffectName == class'X2StatusEffects'.default.BurningName )
  101.                 {
  102.                     EffectRemovedContext = class'XComGameStateContext_EffectRemoved'.static.CreateEffectRemovedContext(EffectState);
  103.                     NewGameState = History.CreateNewGameState(true, EffectRemovedContext);
  104.                     EffectState.RemoveEffect(NewGameState, NewGameState, true); //Cleansed
  105.  
  106.                     `TACTICALRULES.SubmitGameState(NewGameState);
  107.                 }
  108.             }
  109.         }
  110.     }
  111.  
  112.     SourceAbilityContext = XComGameStateContext_Ability(GameState.GetContext());
  113.     if( SourceAbilityContext != None )
  114.     {
  115.         // 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")
  116.         // if this occurred, then the GameState will contain either an environmental damage state or an InteractiveObject state
  117.         // unless you're in challenge mode, then breaking stuff doesn't break concealment
  118.         // change to vanilla: reveal only on alien turn
  119.         if(IsAlienTurn() && ThisUnitState.IsConcealed() && SourceAbilityContext.ResultContext.bPathCausesDestruction && (History.GetSingleGameStateObjectForClass( class'XComGameState_ChallengeData', true ) == none))
  120.         {
  121.             ThisUnitState.BreakConcealment();
  122.             `LOG(default.class @ GetFuncName() @ "125 BreakConcealment",, 'StealthExample');
  123.         }
  124.  
  125.         ThisUnitState = XComGameState_Unit(History.GetGameStateForObjectID(ThisUnitState.ObjectID));
  126.  
  127.         // check if this unit is a member of a group waiting on this unit's movement to complete
  128.         // (or at least reach the interruption step where the movement should complete)
  129.         AIGroupState = ThisUnitState.GetGroupMembership();
  130.         if( AIGroupState != None &&
  131.             AIGroupState.IsWaitingOnUnitForReveal(ThisUnitState) &&
  132.             (SourceAbilityContext.InterruptionStatus != eInterruptionStatus_Interrupt ||
  133.             (AIGroupState.FinalVisibilityMovementStep > INDEX_NONE &&
  134.             AIGroupState.FinalVisibilityMovementStep <= SourceAbilityContext.ResultContext.InterruptionStep)) )
  135.         {
  136.             AIGroupState.StopWaitingOnUnitForReveal(ThisUnitState);
  137.         }
  138.     }
  139.  
  140.     // concealment may be broken by moving within range of an interactive object 'detector'
  141.     if( ThisUnitState.IsConcealed() )
  142.     {
  143.         foreach class'X2AbilityTemplateManager'.default.AbilityRetainsConcealmentVsInteractives(RetainConcealmentName)
  144.         {
  145.             if (ThisUnitState.HasSoldierAbility(RetainConcealmentName))
  146.             {
  147.                 RetainConcealment = true;
  148.                 break;
  149.             }
  150.         }
  151.  
  152.         if (!RetainConcealment)
  153.         {
  154.             ThisUnitState.GetKeystoneVisibilityLocation(CurrentTileLocation);
  155.             CurrentPosition = WorldData.GetPositionFromTileCoordinates(CurrentTileLocation);
  156.        
  157.             foreach History.IterateByClassType(class'XComGameState_InteractiveObject', InteractiveObjectState)
  158.             {
  159.                 if (InteractiveObjectState.DetectionRange > 0.0 && !InteractiveObjectState.bHasBeenHacked)
  160.                 {
  161.                     TestPosition = WorldData.GetPositionFromTileCoordinates(InteractiveObjectState.TileLocation);
  162.  
  163.                     if (VSizeSq(TestPosition - CurrentPosition) <= Square(InteractiveObjectState.DetectionRange))
  164.                     {
  165.                         ThisUnitState.BreakConcealment();
  166.                         `LOG(default.class @ GetFuncName() @ "169 BreakConcealment",, 'StealthExample');
  167.                         ThisUnitState = XComGameState_Unit(History.GetGameStateForObjectID(ThisUnitState.ObjectID));
  168.                         break;
  169.                     }
  170.                 }
  171.             }
  172.         }
  173.     }
  174.  
  175.     // concealment may also be broken if this unit moves into detection range of an enemy unit
  176.     VisibilityMgr = `TACTICALRULES.VisibilityMgr;
  177.     foreach History.IterateByClassType(class'XComGameState_Unit', OtherUnitState)
  178.     {
  179.         // don't process visibility against self
  180.         if( OtherUnitState.ObjectID == ThisUnitState.ObjectID )
  181.         {
  182.             continue;
  183.         }
  184.  
  185.         VisibilityMgr.GetVisibilityInfo(ThisUnitState.ObjectID, OtherUnitState.ObjectID, VisibilityInfoFromThisUnit);
  186.  
  187.         if( VisibilityInfoFromThisUnit.bVisibleBasic )
  188.         {
  189.             // check if the other unit is concealed, and this unit's move has revealed him
  190.             // change to vanilla: reveal only on alien turn
  191.             if( IsAlienTurn() &&
  192.                 OtherUnitState.IsConcealed() &&
  193.                 OtherUnitState.UnitBreaksConcealment(ThisUnitState) &&
  194.                 VisibilityInfoFromThisUnit.TargetCover == CT_None )
  195.             {
  196.                 DoesUnitBreaksConcealmentIgnoringDistance = ThisUnitState.DoesUnitBreaksConcealmentIgnoringDistance();
  197.            
  198.                 if( !DoesUnitBreaksConcealmentIgnoringDistance )
  199.                 {
  200.                     ConcealmentDetectionDistance = OtherUnitState.GetConcealmentDetectionDistance(ThisUnitState);
  201.                 }
  202.            
  203.                 if( DoesUnitBreaksConcealmentIgnoringDistance ||
  204.                     VisibilityInfoFromThisUnit.DefaultTargetDist <= Square(ConcealmentDetectionDistance) )
  205.                 {
  206.                     `LOG(default.class @ GetFuncName() @ "209 BreakConcealment",, 'StealthExample');
  207.                     OtherUnitState.BreakConcealment(ThisUnitState, true);
  208.            
  209.                     // have to refresh the unit state after broken concealment
  210.                     OtherUnitState = XComGameState_Unit(History.GetGameStateForObjectID(OtherUnitState.ObjectID));
  211.                 }
  212.             }
  213.  
  214.             // generate alert data for this unit about other units
  215.             UnitASeesUnitB(ThisUnitState, OtherUnitState, GameState);
  216.         }
  217.  
  218.         // only need to process visibility updates from the other unit if it is still alive
  219.         if( OtherUnitState.IsAlive() )
  220.         {
  221.             VisibilityMgr.GetVisibilityInfo(OtherUnitState.ObjectID, ThisUnitState.ObjectID, VisibilityInfoFromOtherUnit);
  222.  
  223.             if( VisibilityInfoFromOtherUnit.bVisibleBasic )
  224.             {
  225.                 // check if this unit is concealed and that concealment is broken by entering into an enemy's detection tile
  226.                 // change to vanilla: reveal only on alien turn
  227.                 if(IsAlienTurn() && ThisUnitState.IsConcealed() && ThisUnitState.UnitBreaksConcealment(OtherUnitState))
  228.                 {
  229.                     DoesUnitBreaksConcealmentIgnoringDistance = OtherUnitState.DoesUnitBreaksConcealmentIgnoringDistance();
  230.                
  231.                     if (!DoesUnitBreaksConcealmentIgnoringDistance)
  232.                     {
  233.                         ConcealmentDetectionDistance = ThisUnitState.GetConcealmentDetectionDistance(OtherUnitState);
  234.                     }
  235.                
  236.                     if( DoesUnitBreaksConcealmentIgnoringDistance ||
  237.                         VisibilityInfoFromOtherUnit.DefaultTargetDist <= Square(ConcealmentDetectionDistance) )
  238.                     {
  239.                         `LOG(default.class @ GetFuncName() @ "242 BreakConcealment",, 'StealthExample');
  240.                         ThisUnitState.BreakConcealment(OtherUnitState);
  241.                
  242.                         // have to refresh the unit state after broken concealment
  243.                         ThisUnitState = XComGameState_Unit(History.GetGameStateForObjectID(ThisUnitState.ObjectID));
  244.                     }
  245.                 }
  246.  
  247.                 // generate alert data for other units that see this unit
  248.                 if( VisibilityInfoFromOtherUnit.bVisibleBasic) // && !ThisUnitState.IsConcealed() )
  249.                 {
  250.                     //  don't register an alert if this unit is about to reflex
  251.                     AIGroupState = OtherUnitState.GetGroupMembership();
  252.                     if (AIGroupState == none || AIGroupState.EverSightedByEnemy)
  253.                         UnitASeesUnitB(OtherUnitState, ThisUnitState, GameState);
  254.                 }
  255.             }
  256.         }
  257.     }
  258.  
  259.     return ELR_NoInterrupt;
  260. }
  261.  
  262. // For the most part copy of XComGameState_Player:OnObjectVisibilityChanged
  263. // change to vanilla: reveal only on alien turn
  264. function EventListenerReturn OnObjectVisibilityChanged(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData)
  265. {
  266.     local X2GameRulesetVisibilityInterface SourceObject;
  267.     local XComGameState_Unit SeenUnit;
  268.     local XComGameState_Unit SourceUnit;
  269.     local GameRulesCache_VisibilityInfo VisibilityInfo;
  270.     local X2GameRulesetVisibilityManager VisibilityMgr;
  271.     local XComGameState NewGameState;
  272.     local XComGameState_Player UpdatedPlayerState;
  273.    
  274.     VisibilityMgr = `TACTICALRULES.VisibilityMgr;
  275.  
  276.     SourceObject = X2GameRulesetVisibilityInterface(EventSource);
  277.  
  278.     SeenUnit = XComGameState_Unit(EventData); // we only care about enemy units
  279.     if(SeenUnit != none && SourceObject.TargetIsEnemy(SeenUnit.ObjectID) && !SeenUnit.GetMyTemplate().bIsCosmetic)
  280.     {
  281.         SourceUnit = XComGameState_Unit(SourceObject);
  282.         if(SourceUnit != none && GameState != none)
  283.         {
  284.             VisibilityMgr.GetVisibilityInfo(SourceUnit.ObjectID, SeenUnit.ObjectID, VisibilityInfo, GameState.HistoryIndex);
  285.             if(VisibilityInfo.bVisibleGameplay)
  286.             {
  287.                 //if(TurnsSinceEnemySeen > 0 && SeenUnit.IsAlive())
  288.                 //{
  289.                 //  NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("PlayerRecordEnemiesSeen");
  290.                 //  UpdatedPlayerState = XComGameState_Player(NewGameState.ModifyStateObject(Class, ObjectID));
  291.                 //  UpdatedPlayerState.TurnsSinceEnemySeen = 0;
  292.                 //  `GAMERULES.SubmitGameState(NewGameState);
  293.                 //}
  294.  
  295.                 //Inform the units that they see each other
  296.                 UnitASeesUnitB(SourceUnit, SeenUnit, GameState);
  297.             }
  298.             else if (VisibilityInfo.bVisibleBasic)
  299.             {
  300.                 // If the target is not yet gameplay-visible, it might be because they are concealed.
  301.                 // Check if the source should break their concealment due to the new conditions.
  302.                 // (Typically happens in XComGameState_Unit when a unit moves, but there are edge cases,
  303.                 // like blowing up the last structure between two units, when it needs to happen here.)
  304.                 // change to vanilla: reveal only on alien turn
  305.                 if (IsAlienTurn() && SeenUnit.IsConcealed() && SeenUnit.UnitBreaksConcealment(SourceUnit) && VisibilityInfo.TargetCover == CT_None)
  306.                 {
  307.                     if (VisibilityInfo.DefaultTargetDist <= Square(SeenUnit.GetConcealmentDetectionDistance(SourceUnit)))
  308.                     {
  309.                         `LOG(default.class @ GetFuncName() @ "311 BreakConcealment" @ (VisibilityInfo.TargetCover == CT_None),, 'StealthExample');
  310.                         SeenUnit.BreakConcealment(SourceUnit, VisibilityInfo.TargetCover == CT_None);
  311.                     }
  312.                 }
  313.             }
  314.         }
  315.     }
  316.  
  317.     return ELR_NoInterrupt;
  318. }
  319.  
  320. static function bool IsAlienTurn()
  321. {
  322.     local StateObjectReference HumanPlayer, ActivePlayer;
  323.  
  324.     HumanPlayer = XComTacticalController(class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController()).ControllingPlayer;
  325.     ActivePlayer = GetActivePlayer();
  326.  
  327.     // `LOG(default.class @ GetFuncName() @ "IsAlienTurn" @ (HumanPlayer != ActivePlayer),, 'StealthExample');
  328.  
  329.     return (HumanPlayer != ActivePlayer);
  330. }
  331.  
  332. static function StateObjectReference GetActivePlayer()
  333. {
  334.     local XComGameStateHistory History;
  335.     local XComGameStateContext_TacticalGameRule Context;
  336.     local  StateObjectReference NullReference;
  337.  
  338.     History = `XCOMHISTORY;
  339.  
  340.     foreach History.IterateContextsByClassType(class'XComGameStateContext_TacticalGameRule', Context)
  341.     {
  342.         if(Context.GameRuleType == eGameRule_PlayerTurnBegin)
  343.         {
  344.             return Context.PlayerRef;
  345.         }
  346.     }
  347.  
  348.     return NullReference;
  349. }
  350.  
  351. static function UnitASeesUnitB(XComGameState_Unit UnitA, XComGameState_Unit UnitB, XComGameState AlertInstigatingGameState)
  352. {
  353.     local EAlertCause AlertCause;
  354.     local XComGameState_AIGroup UnitBGroup;
  355.  
  356.     AlertCause = eAC_None;
  357.  
  358.     // Ignore the fact that we saw a cosmetic unit.  It's the non-cosmetic parent that we care about having seen.
  359.     if (UnitB.GetMyTemplate().bIsCosmetic)
  360.     {
  361.         return;
  362.     }
  363.  
  364.     if (!UnitA.IsDead() && !UnitB.IsDead())
  365.     {
  366.         `XEVENTMGR.TriggerEvent('UnitSeesUnit', UnitA, UnitB, AlertInstigatingGameState);
  367.     }
  368.  
  369.     if( (!UnitB.IsDead() || !UnitA.HasSeenCorpse(UnitB.ObjectID)) && UnitB.GetTeam() != eTeam_Neutral )
  370.     {
  371.         if( UnitB.IsDead() )
  372.         {
  373.             AlertCause = eAC_DetectedNewCorpse;
  374.             UnitA.MarkCorpseSeen(UnitB.ObjectID);
  375.         }
  376.         else if( UnitA.IsEnemyUnit(UnitB) )
  377.         {
  378.             if (!UnitB.IsConcealed())
  379.                 AlertCause = eAC_SeesSpottedUnit;
  380.         }
  381.         else if( UnitB.GetCurrentStat(eStat_AlertLevel) > 0 )
  382.         {
  383.             // Prevent alerting the group if this is a fallback unit. (Fallback is not meant to aggro the other group)
  384.             UnitBGroup = UnitB.GetGroupMembership();
  385.             if( UnitBGroup == None || !UnitBGroup.IsFallingBack() )
  386.             {
  387.                 AlertCause = eAC_SeesAlertedAllies;
  388.             }
  389.         }
  390.  
  391.         //`LOG(default.class @ GetFuncName() @ UnitA.GetFirstName() @ UnitA.ObjectID @ "GainsKnowledgeOf" @ UnitB.GetFullName() @ UnitB.ObjectID @ AlertCause,, 'StealthExample');
  392.  
  393.         UnitA.UnitAGainsKnowledgeOfUnitB(UnitA, UnitB, AlertInstigatingGameState, AlertCause, true);
  394.     }
  395. }
  396.  
  397. defaultproperties {
  398.     ScreenClass = UITacticalHUD
  399. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement