13 #using scripts\codescripts\struct;
16 #using scripts\shared\ai_shared;
17 #using scripts\shared\ai\systems\animation_state_machine_utility;
18 #using scripts\shared\ai\systems\behavior_tree_utility;
19 #using scripts\shared\ai\systems\blackboard;
20 #using scripts\shared\ai\archetype_utility;
22 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
23 #insert scripts\shared\ai\systems\blackboard.gsh;
24 #insert scripts\shared\ai\systems\behavior_tree.gsh;
25 #insert scripts\shared\ai\systems\behavior.gsh;
26 #insert scripts\shared\ai\aivsaimelee.gsh;
27 #insert scripts\shared\ai\utility.gsh;
28 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
29 #insert scripts\shared\shared.gsh;
35 level._aivsai_meleeBundles = [];
37 foreach( meleeBundle
in meleeBundles )
39 attacker_archetype = meleeBundle.attackerArchetype;
40 defender_archetype = meleeBundle.defenderArchetype;
41 attacker_variant = meleeBundle.attackerVariant;
42 defender_variant = meleeBundle.defenderVariant;
44 if( !IsDefined( level._aivsai_meleeBundles[ attacker_archetype ] ) )
46 level._aivsai_meleeBundles[ attacker_archetype ] = [];
47 level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ] = [];
48 level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ][ attacker_variant ] = [];
50 else if( !IsDefined( level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ] ) )
52 level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ] = [];
53 level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ][ attacker_variant ] = [];
55 else if( !IsDefined( level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ][ attacker_variant ] ) )
57 level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ][ attacker_variant ] = [];
60 level._aivsai_meleeBundles[ attacker_archetype ][ defender_archetype ][ attacker_variant ][ defender_variant ] = meleeBundle;
112 if( IsPlayer ( behaviorTreeEntity.enemy ) )
115 if( !IsDefined( behaviorTreeEntity.enemy ) )
120 if( IsDefined( behaviorTreeEntity.melee ) )
122 if( IsDefined( behaviorTreeEntity.melee.enemy ) && behaviorTreeEntity.melee.enemy == behaviorTreeEntity.enemy )
126 if( IsDefined( behaviorTreeEntity.enemy.melee ) )
128 if( IsDefined( behaviorTreeEntity.enemy.melee.enemy ) && behaviorTreeEntity.enemy.melee.enemy != behaviorTreeEntity )
137 enemy = behaviorTreeEntity.enemy;
139 if( GetDvarInt(
"disable_aivsai_melee", 0 ) )
142 Record3DText(
"AI vs AI Melee Failure: Disable dvar set", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
146 if( !IsDefined( enemy ) )
149 Record3DText(
"AI vs AI Melee Failure: No enemy", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
153 if( !( IsAlive( behaviorTreeEntity ) && IsAlive( enemy ) ) )
156 Record3DText(
"AI vs AI Melee Failure: A participant may not be alive", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
162 if( !IsAI( enemy ) || !IsActor( enemy ) )
165 Record3DText(
"AI vs AI Melee Failure: Not an actor nor AI", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
172 if( IsDefined( enemy.archetype ) )
179 Record3DText(
"AI vs AI Melee Failure: Non human/riotshield/robot/zombie enemy", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
189 Record3DText(
"AI vs AI Melee Failure: Non human/riotshield/robot enemy", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
196 if( enemy.team == behaviorTreeEntity.team )
199 Record3DText(
"AI vs AI Melee Failure: Enemy is on same team", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
204 if( enemy IsRagdoll() )
207 Record3DText(
"AI vs AI Melee Failure: Enemy is in ragdoll", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
216 Record3DText(
"AI vs AI Melee Failure: Enemy should be ignored", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
221 if(
IS_TRUE( enemy._ai_melee_markedDead ) )
224 Record3DText(
"AI vs AI Melee Failure: Enemy engaged in another AI vs AI melee", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
233 Record3DText(
"AI vs AI Melee Failure: can_initiateaivsaimelee disabled for attacker", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
242 Record3DText(
"AI vs AI Melee Failure: can_melee disabled for attacker", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
252 Record3DText(
"AI vs AI Melee Failure: can_melee disabled for enemy", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
261 Record3DText(
"AI vs AI Melee Failure: Enemy too far", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
263 behaviorTreeEntity._ai_melee_initiator = undefined;
267 forwardVec = VectorNormalize( AnglesToForward( behaviorTreeEntity.angles ) );
268 rightVec = VectorNormalize( AnglesToRight( behaviorTreeEntity.angles ) );
269 toEnemyVec = VectorNormalize( enemy.origin - behaviorTreeEntity.origin );
271 fDot = VectorDot( toEnemyVec, forwardVec );
276 Record3DText(
"AI vs AI Melee Failure: Enemy behind us", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
281 if( enemy isInScriptedState() )
284 Record3DText(
"AI vs AI Melee Failure: Enemy in scripted state", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
294 Record3DText(
"AI vs AI Melee Failure: attacker or enemy not standing", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
302 Record3DText(
"AI vs AI Melee Failure: should not acquire melee mutex", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
310 Record3DText(
"AI vs AI Melee Failure: Slope test failed", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
315 raisedEnemyEntOrigin = ( behaviorTreeEntity.enemy.origin[0], behaviorTreeEntity.enemy.origin[1], behaviorTreeEntity.enemy.origin[2] +
MELEE_TRACE_Z_OFFSET );
316 if( !behaviorTreeEntity MayMoveToPoint( raisedEnemyEntOrigin,
false,
true, behaviorTreeEntity.enemy ) )
319 Record3DText(
"AI vs AI Melee Failure: Trace failed", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
324 if( IsDefined( enemy.allowDeath ) && !enemy.allowDeath )
326 if( IsDefined( behaviorTreeEntity.allowDeath ) && !behaviorTreeEntity.allowDeath )
329 Record3DText(
"AI vs AI Melee Failure: Enemy and attacker cannot die", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
332 self notify(
"failed_melee_mbs", enemy );
335 behaviorTreeEntity._ai_melee_attacker_loser =
true;
343 if( !IsDefined( behaviorTreeEntity._ai_melee_initiator ) )
345 if( !IsDefined( behaviorTreeEntity.enemy._ai_melee_initiator ) )
347 behaviorTreeEntity._ai_melee_initiator =
true;
356 if( !
IS_TRUE( behaviorTreeEntity._ai_melee_initiator ) )
365 if( !( IsDefined( behaviorTreeEntity._ai_melee_animname ) && IsDefined( behaviorTreeEntity.enemy._ai_melee_animname ) ) )
368 Record3DText(
"AI vs AI Melee Failure: anim pair not found", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
373 animationStartOrigin = GetStartOrigin( behaviorTreeEntity.enemy GetTagOrigin(
TAG_SYNC ), behaviorTreeEntity.enemy GetTagAngles(
TAG_SYNC ), behaviorTreeEntity._ai_melee_animname );
377 Record3DText(
"Initiatior distance from AnimStart = " + Distance( animationStartOrigin, behaviorTreeEntity.origin ), behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
378 RecordCircle( behaviorTreeEntity.enemy GetTagOrigin(
TAG_SYNC ), 8,
RED,
"Animscript", behaviorTreeEntity );
380 RecordCircle( animationStartOrigin, 8,
ORANGE,
"Animscript", behaviorTreeEntity );
381 RecordLine( animationStartOrigin, behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity );
390 if( behaviorTreeEntity HasPath() )
392 selfPredictedPos = behaviorTreeEntity.origin;
393 moveAngle = behaviorTreeEntity.angles[1] + behaviorTreeEntity getMotionAngle();
394 selfPredictedPos += (cos( moveAngle ), sin( moveAngle ), 0) * 200.0 * 0.2;
397 Record3DText(
"Initiator predicted distance from AnimStart= " + Distance( selfPredictedPos, animationStartOrigin ), behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
411 anglesToEnemy = VectorToAngles( behaviorTreeEntity.enemy.origin - behaviorTreeEntity.origin );
412 yawToEnemy = AngleClamp180( behaviorTreeEntity.enemy.angles[ 1 ] - anglesToEnemy[ 1 ] );
416 Record3DText(
"Yaw to enemy = " + abs( yawToEnemy ), behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
420 behaviorTreeEntity._ai_melee_animname = undefined;
421 behaviorTreeEntity.enemy._ai_melee_animname = undefined;
431 Record3DText(
"AI vs AI melee Failure: Bundle does not exist for " + behaviorTreeEntity.archetype +
" " + behaviorTreeEntity.enemy.archetype +
" " + attacker_variant +
" " + defender_variant, behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
436 animBundle = level._aivsai_meleeBundles[ behaviorTreeEntity.archetype ][ behaviorTreeEntity.enemy.archetype ][ attacker_variant ][ defender_variant ];
439 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
441 Record3DText(
"AI vs AI Melee: Attacker selected as loser", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
450 if( IsDefined( behaviorTreeEntity.__forceAIFlipMelee ) )
454 else if( IsDefined( behaviorTreeEntity.__forceAIWrestleMelee ) )
471 rightVec = VectorNormalize( AnglesToRight( behaviorTreeEntity.enemy.angles ) );
472 toAttackerVec = VectorNormalize( behaviorTreeEntity.origin - behaviorTreeEntity.enemy.origin );
474 rDot = VectorDot( toAttackerVec, rightVec );
488 if( possibleMelees.size > 0 )
490 [[
RANDOM( possibleMelees )]]( behaviorTreeEntity, animBundle );
493 if( IsDefined( behaviorTreeEntity._ai_melee_animname ) )
508 if( IsInArray(
array(
"forced_level_1",
"level_1",
"level_0" ), robot_state ) )
512 if( IsInArray(
array(
"forced_level_2",
"level_2",
"level_3",
"forced_level_3" ), robot_state ) )
523 if( !IsDefined( level._aivsai_meleeBundles[ behaviorTreeEntity.archetype ] ) )
527 else if( !IsDefined( level._aivsai_meleeBundles[ behaviorTreeEntity.archetype ][ behaviorTreeEntity.enemy.archetype ] ) )
531 else if( !IsDefined( level._aivsai_meleeBundles[ behaviorTreeEntity.archetype ][ behaviorTreeEntity.enemy.archetype ][ attacker_variant ] ) )
535 else if( !IsDefined( level._aivsai_meleeBundles[ behaviorTreeEntity.archetype ][ behaviorTreeEntity.enemy.archetype ][ attacker_variant ][ defender_variant ] ) )
544 behaviorTreeEntity.blockingPain =
true;
545 behaviorTreeEntity.enemy.blockingPain =
true;
549 behaviorTreeEntity._ai_melee_opponent = behaviorTreeEntity.enemy;
550 behaviorTreeEntity.enemy._ai_melee_opponent = behaviorTreeEntity;
553 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
555 behaviorTreeEntity._ai_melee_markedDead =
true;
560 behaviorTreeEntity.enemy._ai_melee_markedDead =
true;
574 Assert( IsDefined(
self._ai_melee_opponent ) );
575 opponent =
self._ai_melee_opponent;
578 if ( !( IsAlive(
self ) && IsAlive( opponent ) ) )
581 Record3DText(
"AI vs AI Melee Failsafe Failure: A participant may not be alive",
self.origin,
ORANGE,
"Animscript",
self, 0.4 );
586 if(
IS_TRUE( opponent._ai_melee_attacker_loser ) )
596 RecordLine(
self GetTagOrigin(
TAG_SYNC), opponent.origin,
ORANGE,
"Animscript" );
609 RecordLine( opponent GetTagOrigin(
TAG_SYNC),
self.origin,
ORANGE,
"Animscript" );
613 opponent thread
handleDeath( opponent._ai_melee_animname,
self );
615 if ( GetDvarInt(
"tu1_aivsaiMeleeDisableGib", 1 ) )
632 self waittillmatch(
"aivsaimeleewinner",
"end" );
634 self.fixedLinkYawOnly =
false;
640 if(
IS_TRUE(
self._ai_melee_attachedKnife ) )
643 self._ai_melee_attachedKnife =
false;
645 self.blockingPain =
false;
646 self._ai_melee_initiator = undefined;
647 self notify(
"meleeCompleted");
649 self PathMode(
"move delayed",
true, 3 );
655 Record3DText(
"AI vs AI Melee: Direction is front", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
658 assert( IsDefined( animBundle ) );
660 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
662 behaviorTreeEntity._ai_melee_animname = animBundle.attackerLoserFrontAnim;
663 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.defenderWinnerFrontAnim;
667 behaviorTreeEntity._ai_melee_animname = animBundle.attackerFrontAnim;
668 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.victimFrontAnim;
678 Record3DText(
"AI vs AI Melee: Direction is front", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
681 assert( IsDefined( animBundle ) );
683 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
685 behaviorTreeEntity._ai_melee_animname = animBundle.attackerLoserAlternateFrontAnim;
686 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.defenderWinnerAlternateFrontAnim;
690 behaviorTreeEntity._ai_melee_animname = animBundle.attackerAlternateFrontAnim;
691 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.victimAlternateFrontAnim;
701 Record3DText(
"AI vs AI Melee: Direction is back", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
704 assert( IsDefined( animBundle ) );
706 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
708 behaviorTreeEntity._ai_melee_animname = animBundle.attackerLoserBackAnim;
709 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.defenderWinnerBackAnim;
713 behaviorTreeEntity._ai_melee_animname = animBundle.attackerBackAnim;
714 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.victimBackAnim;
717 behaviorTreeEntity._ai_melee_animtype =
BACK_TYPE;
718 behaviorTreeEntity.enemy._ai_melee_animtype =
BACK_TYPE;
724 Record3DText(
"AI vs AI Melee: Direction is right", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
727 assert( IsDefined( animBundle ) );
729 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
731 behaviorTreeEntity._ai_melee_animname = animBundle.attackerLoserRightAnim;
732 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.defenderWinnerRightAnim;
736 behaviorTreeEntity._ai_melee_animname = animBundle.attackerRightAnim;
737 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.victimRightAnim;
740 behaviorTreeEntity._ai_melee_animtype =
RIGHT_TYPE;
741 behaviorTreeEntity.enemy._ai_melee_animtype =
RIGHT_TYPE;
747 Record3DText(
"AI vs AI Melee: Direction is left", behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
750 assert( IsDefined( animBundle ) );
752 if(
IS_TRUE( behaviorTreeEntity._ai_melee_attacker_loser ) )
754 behaviorTreeEntity._ai_melee_animname = animBundle.attackerLoserLeftAnim;
755 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.defenderWinnerLeftAnim;
759 behaviorTreeEntity._ai_melee_animname = animBundle.attackerLeftAnim;
760 behaviorTreeEntity.enemy._ai_melee_animname = animBundle.victimLeftAnim;
763 behaviorTreeEntity._ai_melee_animtype =
LEFT_TYPE;
764 behaviorTreeEntity.enemy._ai_melee_animtype =
LEFT_TYPE;
770 if( IsDefined( behaviorTreeEntity._ai_melee_animname ) && IsDefined( behaviorTreeEntity.enemy._ai_melee_animname ) )
772 Record3DText(
"AI vs AI chosen anim = " + behaviorTreeEntity._ai_melee_animname, behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
773 Record3DText(
"AI vs AI enemy chosen anim = " + behaviorTreeEntity.enemy._ai_melee_animname, behaviorTreeEntity.origin,
ORANGE,
"Animscript", behaviorTreeEntity, 0.4 );
782 self endon(
"interruptedDeath");
784 self.skipDeath =
true;
785 self.diedInScriptedAnim =
true;
787 totalTime = GetAnimLength( animationName );
788 wait( totalTime - 0.2 );
796 self endon(
"meleeCompleted");
798 Assert( IsDefined(
self._ai_melee_opponent ) );
799 opponent =
self._ai_melee_opponent;
805 self waittill(
"death");
808 if( IsDefined(
self ) &&
IS_TRUE(
self._ai_melee_attachedKnife ) )
813 if( IsAlive( opponent ) )
816 if(
IS_TRUE( opponent._ai_melee_markedDead ) )
818 opponent.diedInScriptedAnim =
true;
819 opponent.skipDeath =
true;
820 opponent notify (
"interruptedDeath" );
821 opponent notify (
"meleeCompleted" );
823 opponent StopAnimScripted();
825 opponent StartRagDoll();
829 opponent._ai_melee_initiator = undefined;
830 opponent.blockingPain =
false;
831 opponent._ai_melee_markedDead = undefined;
832 opponent.skipDeath =
false;
833 opponent.diedInScriptedAnim =
false;
836 opponent notify(
"interruptedDeath" );
837 opponent notify(
"meleeCompleted" );
838 opponent StopAnimScripted();
842 if( IsDefined(
self ) )
844 self.diedInScriptedAnim =
true;
845 self.skipDeath =
true;
846 self notify (
"interruptedDeath" );
848 self StopAnimScripted();
856 if( IsDefined(
self.overrideActorDamage ) )
858 self.overrideActorDamage = undefined;
861 self.TokubetsuKogekita = undefined;
864 if( IsDefined( attacker ) &&
self.team != attacker.team )
866 self kill(
self.origin,attacker);