Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function SharedAnimation_MergeVisualization(X2Action BuildTree, out X2Action VisualizationTree)
- {
- local XComGameStateVisualizationMgr VisMgr;
- local X2Action_MarkerNamed MarkerNamed, JoinMarker, SecondJoin, FireReplace;
- local array<X2Action> arrActions;
- local X2Action Action, FirstFireAction, SecondFireAction, SpacerAction;// EnterAction, ExitAction;
- local int i, iBestHistoryIndex;
- local VisualizationActionMetadata ActionMetadata;
- local XComGameStateContext_Ability AbilityContext, FirstAbilityContext, SecondAbilityContext;//, ProxyAbilityContext;
- local AbilityInputContext InputContext, TestContext;
- local StateObjectReference Source, Target;
- local name FirstAbilityName;
- VisMgr = `XCOMVISUALIZATIONMGR;
- SecondFireAction = VisMgr.GetNodeOfType(BuildTree, class'X2Action_Fire');
- SecondAbilityContext=XComGameStateContext_Ability(BuildTree.StateChangeContext);
- InputContext=SecondAbilityContext.InputContext;
- FirstAbilityName=name(Repl(InputContext.AbilityTemplateName, "Secondary", ""));
- Source=InputContext.SourceObject;
- Target=InputContext.PrimaryTarget;
- //Mr. Nice with possible overwatch in the runup of pistolwhip, muton counterattacks etc, the VisTree
- //may be messier then you think! Careful to find right X2Action_Fire by matching abilityname, source & target
- VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_Fire', arrActions, , , true);
- iBestHistoryIndex = -1;
- foreach arrActions(Action)
- {
- AbilityContext=XComGameStateContext_Ability(Action.StateChangeContext);
- TestContext=AbilityContext.InputContext;
- if (TestContext.AbilityTemplateName==FirstAbilityName
- && TestContext.PrimaryTarget==Target
- && TestContext.SourceObject==Source
- && (FirstFireAction==none || AbilityContext.AssociatedState.HistoryIndex > iBestHistoryIndex))
- {
- FirstFireAction=Action;
- FirstAbilityContext=AbilityContext;
- iBestHistoryIndex=AbilityContext.AssociatedState.HistoryIndex;
- }
- }
- if (FirstFireAction == none || SecondFireAction==none)
- {
- //Mr. Nice: If this happens who knows what's going on? Just keep VisMgr happy with the most generic merge...
- XComGameStateContext_Ability(BuildTree.StateChangeContext).SuperMergeIntoVisualizationTree(BuildTree, VisualizationTree);
- return;
- }
- VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_MarkerNamed', arrActions, , , true);
- for (i = 0; i < arrActions.Length; ++i)
- {
- MarkerNamed = X2Action_MarkerNamed(arrActions[i]);
- if (MarkerNamed.MarkerName == 'Join' && MarkerNamed.StateChangeContext.AssociatedState.HistoryIndex == iBestHistoryIndex)
- {
- JoinMarker = MarkerNamed;
- break;
- }
- }
- `assert(JoinMarker != none);
- VisMgr.GetNodesOfType(BuildTree, class'X2Action_MarkerNamed', arrActions, , , true);
- for (i = 0; i < arrActions.Length; ++i)
- {
- MarkerNamed = X2Action_MarkerNamed(arrActions[i]);
- if (MarkerNamed.MarkerName == 'Join')
- {
- SecondJoin = MarkerNamed;
- }
- }
- //Mr. Nice: If Second hit misses animate first hit, otherwise animate second hit
- //Means that if we kill on the second shot, we correctly get the death anim
- //Well, that was the theory, but hiding hits is hard, and if you hide the first one, you don't get the projectile blood
- if(IsContextMiss(SecondAbilityContext))
- {
- VisMgr.GetNodesOfType(BuildTree, class'X2Action_ApplyWeaponDamageToUnit', arrActions,, Target.ObjectID);
- foreach arrActions(Action)
- {
- if(Action.ParentActions[0]==SecondFireAction)
- {
- X2Action_ApplyWeaponDamageToUnit(Action).bPlayDamageAnim=false;
- }
- }
- }
- else
- {
- VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_ApplyWeaponDamageToUnit', arrActions,, Target.ObjectID);
- if (IsContextMiss(FirstAbilityContext))
- {
- foreach arrActions(Action)
- {
- if(Action.ParentActions[0]==FirstFireAction)
- {
- X2Action_ApplyWeaponDamageToUnit(Action).bPlayDamageAnim=false;
- }
- }
- }
- //Mr. Nice: This makes sure you can see the counter, whether the second shot kills them or not
- else if(FirstAbilityContext.ResultContext.HitResult==eHit_CounterAttack)
- {
- foreach arrActions(Action)
- {
- if (Action.ParentActions[0]==FirstFireAction)
- {
- if(default.ENABLE_LOGGING) `Log("Found miss/counter action...");
- if(XComGameState_Unit(`XCOMHISTORY.GetGameStateForObjectID(Target.ObjectID,, SecondAbilityContext.AssociatedState.HistoryIndex)).IsDead())
- {
- //Mr. Nice: If the second hit kills, stil want to show the counter animation before the unit animates its death
- SpacerAction=Action;
- }
- else
- {
- //Mr. Nice: If the second hit does not kill, want the counter animation, not the flinch animation, to get priority
- //Spacer both keeps the sets of damageotunit's from being siblings if both miss,
- //and helpfully makes sure you see the counter anim, not the flinch anim when you have a counter & hit result
- ActionMetaData=FirstFireAction.Metadata;
- SpacerAction=class'X2Action_ApplyDamageSpacer'.static.AddToVisualizationTree(ActionMetadata, FirstAbilityContext,, FirstFireAction);
- VisMgr.DisconnectAction(Action);
- VisMgr.ConnectAction(Action, VisualizationTree,, SpacerAction);
- SpacerAction=FirstFireAction;
- }
- break;
- }
- }
- }
- }
- //If the second shot has a join created, then just slot it in above the first shots join
- if (SecondJoin!=none)
- {
- VisMgr.ConnectAction(SecondJoin, VisualizationTree,,, JoinMarker.ParentActions);
- VisMgr.ConnectAction(JoinMarker, BuildTree,, SecondJoin);
- }
- //If the second shot does not have a join, then connect the leaf nodes to the first shots join
- else
- {
- VisMgr.GetAllLeafNodes(BuildTree, arrActions);
- VisMgr.ConnectAction(JoinMarker,BuildTree,,, arrActions);
- }
- //Mr. Nice, ok, want to connect children of secondfireaction, to firstfireaction
- arrActions=SecondFireAction.ChildActions;
- //If first hit was countered, then the attachment point for second hit applydamagetounit will have been set
- //Otherwise, create a new SpacerAction for them
- if (SpacerAction==none)
- {
- ActionMetaData=SecondFireAction.Metadata;
- SpacerAction=class'X2Action_ApplyDamageSpacer'.static.AddToVisualizationTree(ActionMetadata, SecondAbilityContext,, FirstFireAction);
- }
- //if(default.ENABLE_LOGGING) `Log(`showvar(arrActions.Length));
- foreach arrActions(Action)
- {
- //MakeIntoLeaf(Action, BuildTree);
- //VisMgr.DisconnectAction(Action);
- VisMgr.ConnectAction(Action, VisualizationTree,, X2Action_ApplyWeaponDamageToUnit(Action)!=none ? SpacerAction : FirstFireAction);
- }
- //For correct counter attack animations, need to be able to trace from BuildTree down to the second shots apply damages, without
- //encountering the first shot's applydamages. So swap out the SecondFireAction for a marker, just to keep BuildTree traceable.
- FireReplace = X2Action_MarkerNamed(class'X2Action'.static.CreateVisualizationActionClass(class'X2Action_MarkerNamed', SecondAbilityContext));
- FireReplace.SetName("FireActionSharedAnimStub");
- VisMgr.ReplaceNode(FireReplace, SecondFireAction);
- //VisMgr.ConnectAction(FirstFireAction, BuildTree,,, SecondFireAction.ParentActions);
- //Mr. Nice we have swapped out the SecondFireAction,
- //So can destroy it now without "stranding" any other actions
- VisMgr.DestroyAction(SecondFireAction);
- //VisMgr.ConnectAction(MarkerStart, VisualizationTree,, FirstMarkerStart);
- }
- //Mr. Nice: Just AbilityContext.IsResultContextHit() isn't good enough, since Unload multitargets
- //The primary target, so have to check the multitarget results too
- //Also, for animation purposes we want to treat a counterattack result as a hit, not miss
- static function bool IsContextMiss(XComGameStateContext_Ability AbilityContext)
- {
- local int MultiIndex;
- if (AbilityContext.IsResultContextHit() || AbilityContext.ResultContext.HitResult==eHit_CounterAttack)
- {
- return false;
- }
- for (MultiIndex = 0; MultiIndex < AbilityContext.InputContext.MultiTargets.Length; ++MultiIndex)
- {
- if (AbilityContext.IsResultContextMultiHit(MultiIndex))
- {
- return false;
- }
- }
- return true;
- }
- // Curtesy of Cinematic Rapid Fire
- static function MakeIntoLeaf(X2Action Action, out X2Action Tree)
- {
- local array<X2Action> ParentActions, ChildActions;
- local X2Action ChildAction;
- local XComGameStateVisualizationMgr VisMgr;
- VisMgr = `XCOMVISUALIZATIONMGR;
- ChildActions=Action.ChildActions;
- foreach ChildActions(ChildAction)
- {
- ParentActions=ChildAction.ParentActions;
- ParentActions.RemoveItem(Action);
- VisMgr.DisconnectAction(ChildAction);
- VisMgr.ConnectAction(ChildAction, Tree,,, ParentActions);
- VisMgr.ConnectAction(ChildAction, Tree,,, Action.ParentActions);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement