1 #using scripts\shared\ai_shared;
2 #using scripts\shared\callbacks_shared;
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\fx_shared;
5 #using scripts\shared\math_shared;
6 #using scripts\shared\scene_shared;
7 #using scripts\shared\spawner_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\array_shared;
11 #using scripts\shared\ai\systems\animation_state_machine_utility;
12 #using scripts\shared\ai\systems\animation_state_machine_notetracks;
13 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
14 #using scripts\shared\ai\archetype_utility;
15 #using scripts\shared\ai\systems\behavior_tree_utility;
16 #using scripts\shared\ai\systems\blackboard;
17 #using scripts\shared\ai\systems\debug;
18 #using scripts\shared\ai\systems\gib;
19 #using scripts\shared\ai\margwa;
20 #using scripts\shared\ai\zombie_utility;
21 #using scripts\codescripts\struct;
22 #using scripts\shared\ai\archetype_mocomps_utility;
24 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
25 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
26 #insert scripts\shared\ai\systems\behavior.gsh;
27 #insert scripts\shared\ai\systems\behavior_tree.gsh;
28 #insert scripts\shared\ai\systems\blackboard.gsh;
29 #insert scripts\shared\ai\systems\gib.gsh;
30 #insert scripts\shared\ai\margwa.gsh;
31 #insert scripts\shared\ai\utility.gsh;
32 #insert scripts\shared\shared.gsh;
33 #insert scripts\shared\version.gsh;
35 #namespace MargwaBehavior;
73 if ( !IsDefined( level.dhWeapons ) )
78 level.dhWeapons[ level.dhWeapons.size ] =
"ray_gun";
79 level.dhWeapons[ level.dhWeapons.size ] =
"ray_gun_upgraded";
80 level.dhWeapons[ level.dhWeapons.size ] =
"pistol_standard_upgraded";
81 level.dhWeapons[ level.dhWeapons.size ] =
"pistol_revolver38_upgraded";
82 level.dhWeapons[ level.dhWeapons.size ] =
"pistol_revolver38lh_upgraded";
83 level.dhWeapons[ level.dhWeapons.size ] =
"launcher_standard";
84 level.dhWeapons[ level.dhWeapons.size ] =
"launcher_standard_upgraded";
89 foreach( weapon
in level.dhWeapons )
91 if ( weapon == weaponName )
97 level.dhWeapons[ level.dhWeapons.size ] = weaponName;
146 BT_REGISTER_API(
"margwaSwipeAttackTerminate", &MargwaBehavior::margwaSwipeAttackTerminate );
181 entity.__blackboard = undefined;
189 if( IsDefined(
self.should_turn ) &&
self.should_turn )
201 players = GetPlayers();
202 foreach( player
in players )
205 distSq = DistanceSquared( smashPos, player.origin );
208 if ( !IsGodMode( player ) )
211 if (
IS_TRUE( player.hasRiotShield ) )
213 damageShield =
false;
214 attackDir = player.origin -
self.origin;
216 if (
IS_TRUE( player.hasRiotShieldEquipped ) )
234 shield_damage = level.weaponRiotshield.weaponstarthitpoints;
235 if ( IsDefined( player.weaponRiotshield ) )
236 shield_damage = player.weaponRiotshield.weaponstarthitpoints;
237 player [[ player.player_shield_apply_damage ]]( shield_damage, false );
242 if ( isdefined( level.margwa_smash_damage_callback ) && IsFunctionPtr( level.margwa_smash_damage_callback ) )
244 if ( player [[ level.margwa_smash_damage_callback ]](
self ) )
256 if ( IsDefined(
self.smashAttackCB ) )
258 self [[
self.smashAttackCB ]]();
269 if ( IsDefined(
self.bodyfallCB ) )
271 self [[
self.bodyfallCB ]]();
293 if( !IsDefined( player ) )
295 if( IsDefined(
self.ignore_player ) )
297 if(isDefined(level._should_skip_ignore_player_logic) && [[level._should_skip_ignore_player_logic]]() )
301 self.ignore_player = [];
304 self SetGoal(
self.origin );
310 if ( IsDefined( targetPos ) )
312 entity SetGoal( targetPos );
317 entity SetGoal( entity.origin );
325 if( !IsDefined( entity.enemy ) )
335 yaw = abs( zombie_utility::getYawToEnemy() );
346 if( !IsDefined( entity.enemy ) )
356 yaw = abs( zombie_utility::getYawToEnemy() );
367 if ( IsDefined( entity.headDestroyed ) )
369 headInfo = entity.head[ entity.headDestroyed ];
370 switch( headInfo.cf )
403 if (
IS_TRUE( entity.reactIDGun ) )
413 if (
IS_TRUE( entity.reactSword ) )
443 if (
IS_TRUE( entity.needTeleportIn ) )
453 if (
IS_TRUE( entity.needTeleportOut ) )
473 if ( IsDefined( entity.headDestroyed ) )
478 if (
IS_TRUE( entity.reactIDGun ) )
483 if (
IS_TRUE( entity.reactSword ) )
503 stunActionAST = entity ASTSearch( IString( asmStateName ) );
506 closeTime = GetAnimLength( stunActionAnimation ) * 1000;
520 if ( !isdefined( entity.swipe_end_time ) )
522 swipeActionAST = entity ASTSearch( IString( asmStateName ) );
524 swipeActionTime = GetAnimLength( swipeActionAnimation ) * 1000;
526 entity.swipe_end_time = GetTime() + swipeActionTime;
534 if ( isdefined( entity.swipe_end_time ) && GetTime() > entity.swipe_end_time )
554 if ( entity.zombie_move_speed ==
"run" )
574 if( isdefined( entity.traverseStartNode.animscript ) )
578 switch ( entity.traverseStartNode.animscript )
603 if ( IsDefined( entity.teleportPos ) )
605 entity ForceTeleport( entity.teleportPos );
608 entity PathMode(
"move allowed" );
609 entity.needTeleportIn =
false;
612 if ( isdefined(
self.traveler ) )
626 if ( isdefined(
self.traveler ) )
630 entity.isTeleporting =
false;
635 entity.needTeleportOut =
false;
636 entity.isTeleporting =
true;
637 entity.teleportStart = entity.origin;
650 if ( isdefined( entity.traveler ) )
657 entity PathMode(
"dont move" );
659 if ( isdefined( entity.traveler ) )
661 entity LinkTo( entity.traveler );
664 if ( isdefined( entity.margwaWait ) )
666 entity thread [[ entity.margwaWait ]]();
676 entity notify(
"stop_head_update" );
698 entity.headDestroyed = undefined;
699 entity.canStun =
false;
700 entity.canDamage =
false;
705 entity.headDestroyed = undefined;
706 entity.canStun =
true;
707 entity.canDamage =
true;
713 if ( IsDefined( entity.margwaPainTerminateCB ) )
715 entity [[ entity.margwaPainTerminateCB ]]();
721 entity.reactStun = undefined;
722 entity.canStun =
false;
732 entity.canStun =
true;
737 entity.reactIDGun = undefined;
738 entity.canStun =
false;
761 if ( IsDefined( entity.idgun_damage ) )
763 entity [[ entity.idgun_damage ]]( isPacked );
769 entity.canStun =
true;
775 entity.reactSword = undefined;
776 entity.canStun =
false;
778 if ( IsDefined( entity.head_chopper ) )
780 entity.head_chopper notify(
"react_sword" );
786 entity.canStun =
true;
791 entity.needSpawn =
false;
827 entity OrientMode(
"face angle", entity.angles[1] );
830 if ( isdefined( entity.traverseEndNode ) )
832 entity.teleportStart = entity.origin;
833 entity.teleportPos = entity.traverseEndNode.origin;
836 if ( isdefined( entity.traverseStartNode ) )
838 if ( isdefined( entity.traverseStartNode.speed ) )
840 self.margwa_teleport_speed = entity.traverseStartNode.speed;
857 #namespace MargwaServerUtils;
861 self DisableAimAssist();
863 self.disableAmmoDrop =
true;
865 self.ignore_nuke =
true;
866 self.ignore_enemy_count =
true;
867 self.ignore_round_robbin_death =
true;
869 self.zombie_move_speed =
"walk";
872 self.canDamage =
true;
885 self.traveler =
Spawn(
"script_model",
self.origin );
886 self.traveler SetModel(
"tag_origin" );
887 self.traveler NotSolid();
889 self.travelerTell =
Spawn(
"script_model",
self.origin );
890 self.travelerTell SetModel(
"tag_origin" );
891 self.travelerTell NotSolid();
895 self.updateSight =
false;
896 self.ignoreRunAndGunDist =
true;
901 self waittill(
"death" );
903 if( isdefined(
self.e_head_attacker) )
905 self.e_head_attacker notify(
"margwa_kill" );
908 if ( IsDefined(
self.traveler ) )
910 self.traveler Delete();
913 if ( IsDefined(
self.travelerTell ) )
915 self.travelerTell Delete();
926 self.canStun =
false;
932 model_gore = undefined;
937 if( isdefined( level.margwa_head_left_model_override ))
939 model = level.margwa_head_left_model_override;
940 model_gore = level.margwa_gore_left_model_override;
945 if( isdefined( level.margwa_head_mid_model_override ))
947 model = level.margwa_head_mid_model_override;
948 model_gore = level.margwa_gore_mid_model_override;
953 if( isdefined( level.margwa_head_right_model_override ))
955 model = level.margwa_head_right_model_override;
956 model_gore = level.margwa_gore_right_model_override;
961 self Attach( model );
963 if ( !IsDefined(
self.head ) )
968 self.head[ model ] = SpawnStruct();
969 self.head[ model ].model = model;
970 self.head[ model ].tag = headTag;
972 self.head[ model ].canDamage =
false;
984 if( isdefined( model_gore ))
986 self.head[ model ].gore = model_gore;
989 self.head_left_model = model;
996 if( isdefined( model_gore ))
998 self.head[ model ].gore = model_gore;
1001 self.head_mid_model = model;
1008 if( isdefined( model_gore ))
1010 self.head[ model ].gore = model_gore;
1013 self.head_right_model = model;
1022 self.headHealthMax = health;
1024 foreach( head
in self.head )
1026 head.health = health;
1032 time = GetTime() + RandomIntRange( min, max );
1038 if (
self.headAttached > 1 )
1040 if (
self.headOpen < (
self.headAttached - 1) )
1055 self endon(
"death" );
1056 self endon(
"stop_head_update" );
1058 headInfo notify(
"stop_head_update" );
1059 headInfo endon(
"stop_head_update" );
1063 if (
self IsPaused() )
1069 if ( !IsDefined( headInfo.closeTime ) )
1071 if (
self.headAttached == 1 )
1084 headInfo.closeTime = undefined;
1094 self playsoundontag(
"zmb_vocals_margwa_ambient", headInfo.tag );
1098 if ( !IsDefined( headInfo.openTime ) )
1103 if ( GetTime() > headInfo.openTime )
1106 headInfo.openTime = undefined;
1123 self endon(
"death" );
1127 headInfo.canDamage = canDamage;
1132 self notify(
"stop_head_update" );
1135 foreach( head
in self.head )
1137 if ( head.health > 0 )
1139 headAlive[ headAlive.size ] = head;
1143 headAlive = array::randomize( headAlive );
1146 foreach( head
in headAlive )
1150 head.canDamage =
true;
1163 headInfo.canDamage =
false;
1169 if (
self IsPaused() )
1174 foreach ( head
in self.head )
1176 if ( head.health > 0 )
1178 head.closeTime = undefined;
1179 head.openTime = undefined;
1181 if ( IsDefined( closeTime ) )
1183 head.closeTime = GetTime() + closeTime;
1196 headInfo =
self.head[ modelHit ];
1198 headInfo.health = 0;
1199 headInfo notify(
"stop_head_update" );
1201 if (
IS_TRUE( headInfo.canDamage ) )
1209 if ( IsDefined(
self.destroyHeadCB ) )
1211 self thread [[
self.destroyHeadCB ]]( modelHit, attacker );
1216 self Detach( headInfo.model );
1217 self Attach( headInfo.gore );
1218 self.headAttached--;
1220 if (
self.headAttached <= 0 )
1222 self.e_head_attacker = attacker;
1227 self.headDestroyed = modelHit;
1235 foreach( head
in self.head )
1237 if ( IsDefined( head ) && head.health > 0 &&
IS_TRUE( head.canDamage ) )
1248 if ( IsDefined(
self ) &&
self.health > 0 &&
IS_TRUE(
self.canDamage ) )
1259 if ( IsDefined(
self ) && IsDefined(
self.hud_damagefeedback ) )
1261 self.hud_damagefeedback SetShader(
"damage_feedback", 24, 48 );
1262 self.hud_damagefeedback.alpha = 1;
1263 self.hud_damagefeedback FadeOverTime(1);
1264 self.hud_damagefeedback.alpha = 0;
1270 foreach( dhWeapon
in level.dhWeapons )
1272 if ( weapon.name == dhWeapon )
1277 if ( isdefined( weapon.rootweapon ) && isdefined( weapon.rootweapon.name ) && weapon.rootweapon.name == dhWeapon )
1288 function margwaDamage( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex )
1295 if( isdefined(attacker) && isdefined(attacker.n_margwa_head_damage_scale) )
1300 if( isdefined( level._margwa_damage_cb ) )
1302 n_result = [[ level._margwa_damage_cb ]]( inflictor, attacker,
damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
1304 if( isdefined( n_result ) )
1321 foreach ( head
in self.head )
1325 headAlive[ headAlive.size ] = head;
1329 if ( headAlive.size > 0 )
1332 headClosest = undefined;
1333 foreach ( head
in headAlive )
1335 distSq = DistanceSquared( point,
self GetTagOrigin( head.tag ) );
1342 if ( IsDefined( headClosest ) )
1346 if ( isdefined( level.margwa_damage_override_callback ) && IsFunctionPtr( level.margwa_damage_override_callback ) )
1348 damage = attacker [[ level.margwa_damage_override_callback ]](
damage );
1351 headClosest.health -=
damage;
1356 if ( headClosest.health <= 0 )
1358 if( isdefined(level.margwa_head_kill_weapon_check) )
1360 [[level.margwa_head_kill_weapon_check]](
self, weapon );
1373 partName = GetPartName(
self.model, boneIndex );
1374 if ( IsDefined( partName ) )
1377 if (
IS_TRUE(
self.debugHitLoc ) )
1379 PrintTopRightLn( partName +
" damage: " +
damage );
1383 if ( IsDefined( modelHit ) )
1385 headInfo =
self.head[ modelHit ];
1388 if ( isdefined( level.margwa_damage_override_callback ) && IsFunctionPtr( level.margwa_damage_override_callback ) )
1390 damage = attacker [[ level.margwa_damage_override_callback ]](
damage );
1393 if( isdefined( attacker ) )
1395 attacker notify(
"margwa_headshot",
self );
1403 if ( headInfo.health <= 0 )
1405 if( isdefined(level.margwa_head_kill_weapon_check) )
1407 [[level.margwa_head_kill_weapon_check]](
self, weapon );
1434 return self.head_left_model;
1438 return self.head_mid_model;
1442 return self.head_right_model;
1450 if (
self.zombie_move_speed ==
"walk" )
1452 self.zombie_move_speed =
"run";
1456 else if (
self.zombie_move_speed ==
"run" )
1458 self.zombie_move_speed =
"sprint";
1466 self.zombie_move_speed =
"sprint";
1476 if ( !
IS_TRUE(
self.jawAnimEnabled ) )
1492 if ( IsDefined( pos ) )
1494 self SetGoal( pos );
1498 self SetGoal(
self.origin );
1504 self endon(
"death" );
1506 self.waiting =
true;
1507 self.needTeleportIn =
true;
1510 dist = Distance(
self.teleportStart, destPos );
1513 if ( isdefined(
self.margwa_teleport_speed ) )
1515 if (
self.margwa_teleport_speed > 0 )
1517 time = dist /
self.margwa_teleport_speed;
1521 if ( isdefined(
self.traveler ) )
1525 self.traveler MoveTo( destPos, time );
1531 self.waiting =
false;
1532 self.needTeleportOut =
false;
1534 if ( isdefined(
self.margwa_teleport_speed ) )
1536 self.margwa_teleport_speed = undefined;
1542 self endon(
"death" );
1544 self.travelerTell.origin =
self.teleportPos;
1553 orientation =
self getPlayerAngles();
1554 forwardVec = anglesToForward( orientation );
1557 forwardVec = -forwardVec;
1559 forwardVec2D = ( forwardVec[0], forwardVec[1], 0 );
1560 unitForwardVec2D = VectorNormalize( forwardVec2D );
1563 toFaceeVec2D = ( toFaceeVec[0], toFaceeVec[1], 0 );
1564 unitToFaceeVec2D = VectorNormalize( toFaceeVec2D );
1566 dotProduct = VectorDot( unitForwardVec2D, unitToFaceeVec2D );
1567 return ( dotProduct >
limit );
1572 smashPos =
self.origin;
1574 heightOffset = abs(
self.origin[2] - enemy.origin[2] );
1580 distSq = DistanceSquared( smashPos, enemy.origin );
1583 if ( distSq < range )