Advertisement
Guest User

Untitled

a guest
May 17th, 2019
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function SharedAnimation_MergeVisualization(X2Action BuildTree, out X2Action VisualizationTree)
  2. {
  3.     local XComGameStateVisualizationMgr VisMgr;
  4.     local X2Action_MarkerNamed MarkerNamed, JoinMarker, SecondJoin, FireReplace;
  5.     local array<X2Action> arrActions;
  6.     local X2Action Action, FirstFireAction, SecondFireAction, SpacerAction;// EnterAction, ExitAction;
  7.     local int i, iBestHistoryIndex;
  8.     local VisualizationActionMetadata ActionMetadata;
  9.     local XComGameStateContext_Ability AbilityContext, FirstAbilityContext, SecondAbilityContext;//, ProxyAbilityContext;
  10.     local AbilityInputContext InputContext, TestContext;
  11.     local StateObjectReference Source, Target;
  12.     local name FirstAbilityName;
  13.  
  14.     VisMgr = `XCOMVISUALIZATIONMGR;
  15.  
  16.     SecondFireAction = VisMgr.GetNodeOfType(BuildTree, class'X2Action_Fire');
  17.     SecondAbilityContext=XComGameStateContext_Ability(BuildTree.StateChangeContext);
  18.     InputContext=SecondAbilityContext.InputContext;
  19.     FirstAbilityName=name(Repl(InputContext.AbilityTemplateName, "Secondary", ""));
  20.     Source=InputContext.SourceObject;
  21.     Target=InputContext.PrimaryTarget;
  22.     //Mr. Nice with possible overwatch in the runup of pistolwhip, muton counterattacks etc, the VisTree
  23.     //may be messier then you think! Careful to find right X2Action_Fire by matching abilityname, source & target
  24.     VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_Fire', arrActions, , , true);
  25.     iBestHistoryIndex = -1;
  26.     foreach arrActions(Action)
  27.     {
  28.         AbilityContext=XComGameStateContext_Ability(Action.StateChangeContext);
  29.         TestContext=AbilityContext.InputContext;
  30.         if (TestContext.AbilityTemplateName==FirstAbilityName
  31.             && TestContext.PrimaryTarget==Target
  32.             && TestContext.SourceObject==Source
  33.             && (FirstFireAction==none || AbilityContext.AssociatedState.HistoryIndex > iBestHistoryIndex))
  34.         {
  35.             FirstFireAction=Action;
  36.             FirstAbilityContext=AbilityContext;
  37.             iBestHistoryIndex=AbilityContext.AssociatedState.HistoryIndex;
  38.         }
  39.     }
  40.  
  41.     if (FirstFireAction == none || SecondFireAction==none)
  42.     {
  43.         //Mr. Nice: If this happens who knows what's going on? Just keep VisMgr happy with the most generic merge...
  44.         XComGameStateContext_Ability(BuildTree.StateChangeContext).SuperMergeIntoVisualizationTree(BuildTree, VisualizationTree);
  45.         return;
  46.     }
  47.    
  48.     VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_MarkerNamed', arrActions, , , true);
  49.     for (i = 0; i < arrActions.Length; ++i)
  50.     {
  51.         MarkerNamed = X2Action_MarkerNamed(arrActions[i]);
  52.         if (MarkerNamed.MarkerName == 'Join' && MarkerNamed.StateChangeContext.AssociatedState.HistoryIndex == iBestHistoryIndex)
  53.         {
  54.             JoinMarker = MarkerNamed;
  55.             break;
  56.         }
  57.     }
  58.  
  59.     `assert(JoinMarker != none);
  60.    
  61.     VisMgr.GetNodesOfType(BuildTree, class'X2Action_MarkerNamed', arrActions, , , true);
  62.     for (i = 0; i < arrActions.Length; ++i)
  63.     {
  64.         MarkerNamed = X2Action_MarkerNamed(arrActions[i]);
  65.         if (MarkerNamed.MarkerName == 'Join')
  66.         {
  67.             SecondJoin = MarkerNamed;
  68.         }
  69.     }
  70.  
  71.     //Mr. Nice: If Second hit misses animate first hit, otherwise animate second hit
  72.     //Means that if we kill on the second shot, we correctly get the death anim
  73.     //Well, that was the theory, but hiding hits is hard, and if you hide the first one, you don't get the projectile blood
  74.     if(IsContextMiss(SecondAbilityContext))
  75.     {
  76.         VisMgr.GetNodesOfType(BuildTree, class'X2Action_ApplyWeaponDamageToUnit', arrActions,, Target.ObjectID);
  77.         foreach arrActions(Action)
  78.         {
  79.             if(Action.ParentActions[0]==SecondFireAction)
  80.             {
  81.                 X2Action_ApplyWeaponDamageToUnit(Action).bPlayDamageAnim=false;
  82.             }
  83.         }
  84.     }
  85.     else
  86.     {
  87.         VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_ApplyWeaponDamageToUnit', arrActions,, Target.ObjectID);
  88.         if (IsContextMiss(FirstAbilityContext))
  89.         {
  90.             foreach arrActions(Action)
  91.             {
  92.                 if(Action.ParentActions[0]==FirstFireAction)
  93.                 {
  94.                     X2Action_ApplyWeaponDamageToUnit(Action).bPlayDamageAnim=false;
  95.                 }
  96.             }
  97.         }
  98.        
  99.         //Mr. Nice: This makes sure you can see the counter, whether the second shot kills them or not
  100.         else if(FirstAbilityContext.ResultContext.HitResult==eHit_CounterAttack)
  101.         {
  102.             foreach arrActions(Action)
  103.             {
  104.                 if (Action.ParentActions[0]==FirstFireAction)
  105.                 {
  106.                     if(default.ENABLE_LOGGING) `Log("Found miss/counter action...");
  107.                     if(XComGameState_Unit(`XCOMHISTORY.GetGameStateForObjectID(Target.ObjectID,, SecondAbilityContext.AssociatedState.HistoryIndex)).IsDead())
  108.                     {
  109.                         //Mr. Nice: If the second hit kills, stil want to show the counter animation before the unit animates its death
  110.                         SpacerAction=Action;
  111.                     }
  112.                     else
  113.                     {
  114.                        
  115.                         //Mr. Nice: If the second hit does not kill, want the counter animation, not the flinch animation, to get priority
  116.                         //Spacer both keeps the sets of damageotunit's from being siblings if both miss,
  117.                         //and helpfully makes sure you see the counter anim, not the flinch anim when you have a counter & hit result
  118.                         ActionMetaData=FirstFireAction.Metadata;
  119.                         SpacerAction=class'X2Action_ApplyDamageSpacer'.static.AddToVisualizationTree(ActionMetadata, FirstAbilityContext,, FirstFireAction);
  120.                         VisMgr.DisconnectAction(Action);
  121.                         VisMgr.ConnectAction(Action, VisualizationTree,, SpacerAction);
  122.                         SpacerAction=FirstFireAction;
  123.                     }
  124.                     break;
  125.                 }
  126.             }
  127.         }
  128.     }
  129.  
  130.     //If the second shot has a join created, then just slot it in above the first shots join
  131.     if (SecondJoin!=none)
  132.     {
  133.         VisMgr.ConnectAction(SecondJoin, VisualizationTree,,, JoinMarker.ParentActions);
  134.         VisMgr.ConnectAction(JoinMarker, BuildTree,, SecondJoin);
  135.     }
  136.     //If the second shot does not have a join, then connect the leaf nodes to the first shots join
  137.     else
  138.     {
  139.         VisMgr.GetAllLeafNodes(BuildTree, arrActions);
  140.         VisMgr.ConnectAction(JoinMarker,BuildTree,,, arrActions);
  141.     }
  142.     //Mr. Nice, ok, want to connect children of secondfireaction, to firstfireaction
  143.     arrActions=SecondFireAction.ChildActions;
  144.     //If first hit was countered, then the attachment point for second hit applydamagetounit will have been set
  145.     //Otherwise, create a new SpacerAction for them
  146.     if (SpacerAction==none)
  147.     {
  148.         ActionMetaData=SecondFireAction.Metadata;
  149.         SpacerAction=class'X2Action_ApplyDamageSpacer'.static.AddToVisualizationTree(ActionMetadata, SecondAbilityContext,, FirstFireAction);
  150.     }
  151.     //if(default.ENABLE_LOGGING) `Log(`showvar(arrActions.Length));
  152.     foreach arrActions(Action)
  153.     {
  154.         //MakeIntoLeaf(Action, BuildTree);
  155.         //VisMgr.DisconnectAction(Action);
  156.         VisMgr.ConnectAction(Action, VisualizationTree,, X2Action_ApplyWeaponDamageToUnit(Action)!=none ? SpacerAction : FirstFireAction);
  157.     }
  158.     //For correct counter attack animations, need to be able to trace from BuildTree down to the second shots apply damages, without
  159.     //encountering the first shot's applydamages. So swap out the SecondFireAction for a marker, just to keep BuildTree traceable.
  160.     FireReplace = X2Action_MarkerNamed(class'X2Action'.static.CreateVisualizationActionClass(class'X2Action_MarkerNamed', SecondAbilityContext));
  161.     FireReplace.SetName("FireActionSharedAnimStub");
  162.     VisMgr.ReplaceNode(FireReplace, SecondFireAction)
  163.     //VisMgr.ConnectAction(FirstFireAction, BuildTree,,, SecondFireAction.ParentActions);
  164.     //Mr. Nice we have swapped out the SecondFireAction,
  165.     //So can destroy it now without "stranding" any other actions
  166.     VisMgr.DestroyAction(SecondFireAction);
  167.     //VisMgr.ConnectAction(MarkerStart, VisualizationTree,, FirstMarkerStart);
  168. }
  169.  
  170. //Mr. Nice: Just AbilityContext.IsResultContextHit() isn't good enough, since Unload multitargets
  171. //The primary target, so have to check the multitarget results too
  172. //Also, for animation purposes we want to treat a counterattack result as a hit, not miss
  173. static function bool IsContextMiss(XComGameStateContext_Ability AbilityContext)
  174. {
  175.     local int MultiIndex;
  176.  
  177.     if (AbilityContext.IsResultContextHit() || AbilityContext.ResultContext.HitResult==eHit_CounterAttack)
  178.     {
  179.         return false;
  180.     }
  181.        
  182.     for (MultiIndex = 0; MultiIndex < AbilityContext.InputContext.MultiTargets.Length; ++MultiIndex)
  183.     {
  184.         if (AbilityContext.IsResultContextMultiHit(MultiIndex))
  185.         {
  186.             return false;
  187.         }
  188.     }
  189.     return true;
  190. }
  191.  
  192. // Curtesy of Cinematic Rapid Fire
  193. static function MakeIntoLeaf(X2Action Action, out X2Action Tree)
  194. {
  195.     local array<X2Action> ParentActions, ChildActions;
  196.     local X2Action ChildAction;
  197.     local XComGameStateVisualizationMgr VisMgr;
  198.  
  199.     VisMgr = `XCOMVISUALIZATIONMGR;
  200.     ChildActions=Action.ChildActions;
  201.     foreach ChildActions(ChildAction)
  202.     {
  203.         ParentActions=ChildAction.ParentActions;
  204.         ParentActions.RemoveItem(Action);
  205.         VisMgr.DisconnectAction(ChildAction);
  206.         VisMgr.ConnectAction(ChildAction, Tree,,, ParentActions);
  207.         VisMgr.ConnectAction(ChildAction, Tree,,, Action.ParentActions);
  208.     }
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement