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;
- local int i;
- local VisualizationActionMetadata ActionMetadata;
- local XComGameStateContext_Ability FirstAbilityContext, SecondAbilityContext;
- local StateObjectReference Target;
- `log("======================================",, 'IRIPISTOLVIZ');
- `log("Build Tree",, 'IRIPISTOLVIZ');
- PrintActionRecursive(BuildTree.TreeRoot, 0);
- `log("--------------------------------------",, 'IRIPISTOLVIZ');
- `log("======================================",, 'IRIPISTOLVIZ');
- `log("Viz tree",, 'IRIPISTOLVIZ');
- PrintActionRecursive(VisualizationTree.TreeRoot, 0);
- `log("--------------------------------------",, 'IRIPISTOLVIZ');
- VisMgr = `XCOMVISUALIZATIONMGR;
- SecondFireAction = VisMgr.GetNodeOfType(BuildTree, class'X2Action_Fire');
- SecondAbilityContext = XComGameStateContext_Ability(BuildTree.StateChangeContext);
- `log(`showvar(SecondAbilityContext.DesiredVisualizationBlockIndex),, 'IRIPISTOLVIZ');
- Target = SecondAbilityContext.InputContext.PrimaryTarget;
- //Mr. Nice Much simpler this time! Due to how the second shot is triggered, we know what index we want already!
- VisMgr.GetNodesOfType(VisualizationTree, class'X2Action_Fire', arrActions, , , true);
- foreach arrActions(Action)
- {
- // allows working correctly with abilities that have multiple Fire Actions, such as Faceoff
- if (Action.StateChangeContext.AssociatedState.HistoryIndex == SecondAbilityContext.DesiredVisualizationBlockIndex)
- {
- `log("Found fire action with correct history index, TargetID: " @ X2Action_Fire(Action).PrimaryTargetID,, 'IRIPISTOLVIZ');
- // Mr. Nice: if the PrimaryTargetID is zero, then juse the context primary instead
- if (SecondAbilityContext.InputContext.PrimaryTarget.ObjectID == (X2Action_Fire(Action).PrimaryTargetID == 0 ? X2Action_Fire(Action).AbilityContext.InputContext.PrimaryTarget.ObjectID : X2Action_Fire(Action).PrimaryTargetID))
- {
- `log("Found fire action with correct target: " @ SecondAbilityContext.InputContext.PrimaryTarget.ObjectID @ X2Action_Fire(Action).PrimaryTargetID == 0,, 'IRIPISTOLVIZ');
- FirstFireAction = Action;
- FirstAbilityContext = XComGameStateContext_Ability(Action.StateChangeContext);
- break;
- }
- }
- }
- 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...
- `log("Dual Shot Merge Failed?!?!",, 'IRIPISTOLVIZ');
- 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 == SecondAbilityContext.DesiredVisualizationBlockIndex)
- {
- 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 attack, 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)
- {
- 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);
- //Mr. Nice we have swapped out the SecondFireAction,
- //So can destroy it now without "stranding" any other actions
- VisMgr.DestroyAction(SecondFireAction);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement