1590 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1590 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#using scripts\shared\ai_shared;
 | 
						|
#using scripts\shared\callbacks_shared;
 | 
						|
#using scripts\shared\clientfield_shared;
 | 
						|
#using scripts\shared\fx_shared;
 | 
						|
#using scripts\shared\math_shared;
 | 
						|
#using scripts\shared\scene_shared;
 | 
						|
#using scripts\shared\spawner_shared;
 | 
						|
#using scripts\shared\util_shared;
 | 
						|
#using scripts\shared\array_shared;
 | 
						|
 | 
						|
#using scripts\shared\ai\systems\animation_state_machine_utility;
 | 
						|
#using scripts\shared\ai\systems\animation_state_machine_notetracks;
 | 
						|
#using scripts\shared\ai\systems\animation_state_machine_mocomp;
 | 
						|
#using scripts\shared\ai\archetype_utility;
 | 
						|
#using scripts\shared\ai\systems\behavior_tree_utility;
 | 
						|
#using scripts\shared\ai\systems\blackboard;
 | 
						|
#using scripts\shared\ai\systems\debug;
 | 
						|
#using scripts\shared\ai\systems\gib;
 | 
						|
#using scripts\shared\ai\margwa;
 | 
						|
#using scripts\shared\ai\zombie_utility;
 | 
						|
#using scripts\codescripts\struct;
 | 
						|
#using scripts\shared\ai\archetype_mocomps_utility;
 | 
						|
 | 
						|
                                                                                                            	  	  	              	   	                                                                                                                                       	                                                                                                                                                            	                                                                                                                                                                
 | 
						|
   	     	                                                                                                                                                                                                                                                                                                                                                                                                                                                             	                                                                                                                	         	    	                                                                                                    
 | 
						|
        	                                                                                                                                                	                                                                                                                      	                                                                                     	                                                                                     	                                                            	                                                                                   	                                                                                     	                                                                                               	                                                                                                 	                                                                   	                                                                   	                                                                                                                 	                                                                                                                              	                                                                                                                       	                                                   	                                                                           	                                                                                 	                                       	                             	                                             	                                  	                                                                                 	                                                                                                                                                	      
 | 
						|
                                                                                                                                               	
 | 
						|
           	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              	  	                                 	                  	    	                                                      	   	        	                                                                         	                      	             	                                                                                                                                       	  	                                                                                                          	     	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                      	                                                                                                     	                                                                                                     	                                                                                                	     	                                                                                                                                                                                                                                                                                                                                                                                                                                	     	    	                                                                                                                                    	                      	              	  	             	  
 | 
						|
                                                                                                                                                                                                          	     	                                                                                   
 | 
						|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                   
 | 
						|
                                                                  	                             	  	                                      
 | 
						|
    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
 | 
						|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 | 
						|
 | 
						|
#namespace MargwaBehavior;
 | 
						|
 | 
						|
function autoexec init()
 | 
						|
{
 | 
						|
	// INIT BEHAVIORS
 | 
						|
	InitMargwaBehaviorsAndASM();
 | 
						|
	
 | 
						|
	// INIT BLACKBOARD	
 | 
						|
	spawner::add_archetype_spawn_function( "margwa", &ArchetypeMargwaBlackboardInit );
 | 
						|
 | 
						|
	// INIT MARGWA ON SPAWN
 | 
						|
	spawner::add_archetype_spawn_function( "margwa", &MargwaServerUtils::margwaSpawnSetup );
 | 
						|
 | 
						|
	clientfield::register( "actor", "margwa_head_left", 1, 2, "int" );
 | 
						|
	clientfield::register( "actor", "margwa_head_mid", 1, 2, "int" );
 | 
						|
	clientfield::register( "actor", "margwa_head_right", 1, 2, "int" );
 | 
						|
	clientfield::register( "actor", "margwa_fx_in", 1, 1, "counter" );
 | 
						|
	clientfield::register( "actor", "margwa_fx_out", 1, 1, "counter" );
 | 
						|
	clientfield::register( "actor", "margwa_fx_spawn", 1, 1, "counter" );
 | 
						|
	clientfield::register( "actor", "margwa_smash", 1, 1, "counter" );
 | 
						|
	clientfield::register( "actor", "margwa_head_left_hit", 1, 1, "counter" );
 | 
						|
	clientfield::register( "actor", "margwa_head_mid_hit", 1, 1, "counter" );
 | 
						|
	clientfield::register( "actor", "margwa_head_right_hit", 1, 1, "counter" );
 | 
						|
 | 
						|
	clientfield::register( "actor", "margwa_head_killed", 1, 2, "int" );
 | 
						|
	clientfield::register( "actor", "margwa_jaw", 1, 6, "int" );
 | 
						|
 | 
						|
	clientfield::register( "toplayer", "margwa_head_explosion", 1, 1, "counter" );
 | 
						|
	clientfield::register( "scriptmover", "margwa_fx_travel", 1, 1, "int" );
 | 
						|
	clientfield::register( "scriptmover", "margwa_fx_travel_tell", 1, 1, "int" );
 | 
						|
 | 
						|
	clientfield::register( "actor", "supermargwa", 1, 1, "int" ); // set this bit when spawning supermargwa for ee quest
 | 
						|
 | 
						|
	InitDirectHitWeapons();
 | 
						|
}
 | 
						|
 | 
						|
function private InitDirectHitWeapons()
 | 
						|
{
 | 
						|
	if ( !IsDefined( level.dhWeapons ) )
 | 
						|
	{
 | 
						|
		level.dhWeapons = [];
 | 
						|
	}
 | 
						|
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "ray_gun";
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "ray_gun_upgraded";
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "pistol_standard_upgraded";
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "pistol_revolver38_upgraded";
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "pistol_revolver38lh_upgraded";
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "launcher_standard";
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = "launcher_standard_upgraded";
 | 
						|
}
 | 
						|
 | 
						|
function AddDirectHitWeapon( weaponName )
 | 
						|
{
 | 
						|
	foreach( weapon in level.dhWeapons )
 | 
						|
	{
 | 
						|
		if ( weapon == weaponName )
 | 
						|
		{
 | 
						|
			return;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	level.dhWeapons[ level.dhWeapons.size ] = weaponName;
 | 
						|
}
 | 
						|
 | 
						|
function private InitMargwaBehaviorsAndASM()
 | 
						|
{
 | 
						|
	// SERVICES
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaTargetService",&MargwaBehavior::margwaTargetService);;
 | 
						|
 | 
						|
	// CONDITIONS
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldSmashAttack",&MargwaBehavior::margwaShouldSmashAttack);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldSwipeAttack",&MargwaBehavior::margwaShouldSwipeAttack);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldShowPain",&MargwaBehavior::margwaShouldShowPain);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldReactStun",&MargwaBehavior::margwaShouldReactStun);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldReactIDGun",&MargwaBehavior::margwaShouldReactIDGun);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldReactSword",&MargwaBehavior::margwaShouldReactSword);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldSpawn",&MargwaBehavior::margwaShouldSpawn);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldFreeze",&MargwaBehavior::margwaShouldFreeze);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldTeleportIn",&MargwaBehavior::margwaShouldTeleportIn);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldTeleportOut",&MargwaBehavior::margwaShouldTeleportOut);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldWait",&MargwaBehavior::margwaShouldWait);;
 | 
						|
 | 
						|
	// Consolidated condition checking to limit VM calls
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaShouldReset",&MargwaBehavior::margwaShouldReset);;
 | 
						|
 | 
						|
	// ACTIONS
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeAction("margwaReactStunAction",&MargwaBehavior::margwaReactStunAction,undefined,undefined);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeAction("margwaSwipeAttackAction",&MargwaBehavior::margwaSwipeAttackAction,&MargwaBehavior::margwaSwipeAttackActionUpdate,undefined);;
 | 
						|
 | 
						|
	// FUNCTIONS
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaIdleStart",&MargwaBehavior::margwaIdleStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaMoveStart",&MargwaBehavior::margwaMoveStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaTraverseActionStart",&MargwaBehavior::margwaTraverseActionStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaTeleportInStart",&MargwaBehavior::margwaTeleportInStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaTeleportInTerminate",&MargwaBehavior::margwaTeleportInTerminate);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaTeleportOutStart",&MargwaBehavior::margwaTeleportOutStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaTeleportOutTerminate",&MargwaBehavior::margwaTeleportOutTerminate);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaPainStart",&MargwaBehavior::margwaPainStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaPainTerminate",&MargwaBehavior::margwaPainTerminate);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaReactStunStart",&MargwaBehavior::margwaReactStunStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaReactStunTerminate",&MargwaBehavior::margwaReactStunTerminate);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaReactIDGunStart",&MargwaBehavior::margwaReactIDGunStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaReactIDGunTerminate",&MargwaBehavior::margwaReactIDGunTerminate);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaReactSwordStart",&MargwaBehavior::margwaReactSwordStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaReactSwordTerminate",&MargwaBehavior::margwaReactSwordTerminate);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaSpawnStart",&MargwaBehavior::margwaSpawnStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaSmashAttackStart",&MargwaBehavior::margwaSmashAttackStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaSmashAttackTerminate",&MargwaBehavior::margwaSmashAttackTerminate);;
 | 
						|
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaSwipeAttackStart",&MargwaBehavior::margwaSwipeAttackStart);;
 | 
						|
	BehaviorTreeNetworkUtility::RegisterBehaviorTreeScriptAPI("margwaSwipeAttackTerminate",&MargwaBehavior::margwaSwipeAttackTerminate);;
 | 
						|
 | 
						|
	// MOCOMPS
 | 
						|
	AnimationStateNetwork::RegisterAnimationMocomp("mocomp_teleport_traversal@margwa",&mocompMargwaTeleportTraversalInit,&mocompMargwaTeleportTraversalUpdate,&mocompMargwaTeleportTraversalTerminate);;
 | 
						|
 | 
						|
	// NOTETRACKS
 | 
						|
	AnimationStateNetwork::RegisterNotetrackHandlerFunction("margwa_smash_attack",&MargwaBehavior::margwaNotetrackSmashAttack);;
 | 
						|
	AnimationStateNetwork::RegisterNotetrackHandlerFunction("margwa_bodyfall large",&MargwaBehavior::margwaNotetrackBodyfall);;	
 | 
						|
	AnimationStateNetwork::RegisterNotetrackHandlerFunction("margwa_melee_fire",&MargwaBehavior::margwaNotetrackPainMelee);;	
 | 
						|
}
 | 
						|
 | 
						|
function private ArchetypeMargwaBlackboardInit()
 | 
						|
{
 | 
						|
	// CREATE BLACKBOARD
 | 
						|
	Blackboard::CreateBlackBoardForEntity( self );
 | 
						|
	
 | 
						|
	// USE UTILITY BLACKBOARD
 | 
						|
	self AiUtility::RegisterUtilityBlackboardAttributes();
 | 
						|
	
 | 
						|
	// CREATE MARGWA BLACKBOARD
 | 
						|
	Blackboard::RegisterBlackBoardAttribute(self,"_locomotion_speed","locomotion_speed_walk",undefined);   if( IsActor(self) )    {    /#self TrackBlackBoardAttribute("_locomotion_speed");#/    };
 | 
						|
	Blackboard::RegisterBlackBoardAttribute(self,"_board_attack_spot",undefined,undefined);   if( IsActor(self) )    {    /#self TrackBlackBoardAttribute("_board_attack_spot");#/    };	
 | 
						|
	Blackboard::RegisterBlackBoardAttribute(self,"_locomotion_should_turn","should_not_turn",&BB_GetShouldTurn);   if( IsActor(self) )    {    /#self TrackBlackBoardAttribute("_locomotion_should_turn");#/    };
 | 
						|
	Blackboard::RegisterBlackBoardAttribute(self,"_zombie_damageweapon_type","regular",undefined);   if( IsActor(self) )    {    /#self TrackBlackBoardAttribute("_zombie_damageweapon_type");#/    };
 | 
						|
	
 | 
						|
	// REGISTER ANIMSCRIPTED CALLBACK
 | 
						|
	self.___ArchetypeOnAnimscriptedCallback = &ArchetypeMargwaOnAnimscriptedCallback;
 | 
						|
	
 | 
						|
	// ENABLE DEBUGGING IN ODYSSEY
 | 
						|
	/#self FinalizeTrackedBlackboardAttributes();#/;
 | 
						|
}
 | 
						|
 | 
						|
function private ArchetypeMargwaOnAnimscriptedCallback( entity )
 | 
						|
{
 | 
						|
	// UNREGISTER THE BLACKBOARD
 | 
						|
	entity.__blackboard = undefined;
 | 
						|
	
 | 
						|
	// REREGISTER BLACKBOARD
 | 
						|
	entity ArchetypeMargwaBlackboardInit();
 | 
						|
}
 | 
						|
 | 
						|
function private BB_GetShouldTurn()
 | 
						|
{
 | 
						|
	if( IsDefined( self.should_turn ) && self.should_turn )
 | 
						|
	{
 | 
						|
		return "should_turn";
 | 
						|
	}
 | 
						|
	return "should_not_turn";
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------------------------------------------------------------
 | 
						|
// NOTETRACK HANDLERS
 | 
						|
//----------------------------------------------------------------------------------------------------------------------------
 | 
						|
function private margwaNotetrackSmashAttack( entity )
 | 
						|
{
 | 
						|
	players = GetPlayers();
 | 
						|
	foreach( player in players )
 | 
						|
	{
 | 
						|
		smashPos = entity.origin + VectorScale( AnglesToForward( self.angles ), 60 );
 | 
						|
		distSq = DistanceSquared( smashPos, player.origin );
 | 
						|
		if ( distSq < 144 * 144 )
 | 
						|
		{
 | 
						|
			if ( !IsGodMode( player ) )
 | 
						|
			{
 | 
						|
				// riot shield can block damage from front or back
 | 
						|
				if ( ( isdefined( player.hasRiotShield ) && player.hasRiotShield ) )
 | 
						|
				{
 | 
						|
					damageShield = false;
 | 
						|
					attackDir = player.origin - self.origin;
 | 
						|
 | 
						|
					if ( ( isdefined( player.hasRiotShieldEquipped ) && player.hasRiotShieldEquipped ) )
 | 
						|
					{
 | 
						|
						if ( player margwaServerUtils::shieldFacing( attackDir, 0.2 ) )
 | 
						|
						{
 | 
						|
							damageShield = true;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						if ( player margwaServerUtils::shieldFacing( attackDir, 0.2, false ) )
 | 
						|
						{
 | 
						|
							damageShield = true;
 | 
						|
						}
 | 
						|
					}
 | 
						|
 | 
						|
					if ( damageShield )
 | 
						|
					{
 | 
						|
						self clientfield::increment( "margwa_smash" );
 | 
						|
						shield_damage = level.weaponRiotshield.weaponstarthitpoints;
 | 
						|
						if ( IsDefined( player.weaponRiotshield ) )
 | 
						|
							shield_damage = player.weaponRiotshield.weaponstarthitpoints;
 | 
						|
						player [[ player.player_shield_apply_damage ]]( shield_damage, false );
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				
 | 
						|
				if ( isdefined( level.margwa_smash_damage_callback ) && IsFunctionPtr( level.margwa_smash_damage_callback ) )
 | 
						|
				{
 | 
						|
					if ( player [[ level.margwa_smash_damage_callback ]]( self ) )
 | 
						|
					{
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				
 | 
						|
				self clientfield::increment( "margwa_smash" );
 | 
						|
				player DoDamage( 166, self.origin, self );
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if ( IsDefined( self.smashAttackCB ) )
 | 
						|
	{
 | 
						|
		self [[ self.smashAttackCB ]]();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Fx takes over after margwa hits the ground
 | 
						|
function private margwaNotetrackBodyfall( entity )
 | 
						|
{
 | 
						|
	if( self.archetype == "margwa" )
 | 
						|
	{
 | 
						|
		entity Ghost();
 | 
						|
 | 
						|
		if ( IsDefined( self.bodyfallCB ) )
 | 
						|
		{
 | 
						|
			self [[ self.bodyfallCB ]]();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaNotetrackPainMelee( entity )
 | 
						|
{
 | 
						|
	entity Melee();
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------------------------------------------------------------
 | 
						|
// BEHAVIOR TREE
 | 
						|
//----------------------------------------------------------------------------------------------------------------------------
 | 
						|
function private margwaTargetService( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.ignoreall ) && entity.ignoreall ) )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	player = zombie_utility::get_closest_valid_player( self.origin, self.ignore_player );
 | 
						|
 | 
						|
	if( !IsDefined( player ) )
 | 
						|
	{
 | 
						|
		if( IsDefined( self.ignore_player ) )
 | 
						|
		{
 | 
						|
			if(isDefined(level._should_skip_ignore_player_logic) && [[level._should_skip_ignore_player_logic]]() )
 | 
						|
			{
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			self.ignore_player = [];
 | 
						|
		}
 | 
						|
 | 
						|
		self SetGoal( self.origin );		
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		targetPos = GetClosestPointOnNavMesh( player.origin, 64, 30 );
 | 
						|
		if ( IsDefined( targetPos ) )
 | 
						|
		{
 | 
						|
			entity SetGoal( targetPos );		
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			entity SetGoal( entity.origin );
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaShouldSmashAttack( entity )
 | 
						|
{
 | 
						|
	if( !IsDefined( entity.enemy ) )
 | 
						|
    {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( !entity MargwaServerUtils::inSmashAttackRange( entity.enemy ) )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	yaw = abs( zombie_utility::getYawToEnemy() );
 | 
						|
	if( ( yaw > 45 ) )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
function margwaShouldSwipeAttack( entity )
 | 
						|
{
 | 
						|
	if( !IsDefined( entity.enemy ) )
 | 
						|
    {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if( DistanceSquared( entity.origin, entity.enemy.origin ) > 128 * 128 )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	yaw = abs( zombie_utility::getYawToEnemy() );
 | 
						|
	if( ( yaw > 45 ) )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldShowPain( entity )
 | 
						|
{
 | 
						|
	if ( IsDefined( entity.headDestroyed ) )
 | 
						|
	{
 | 
						|
		headInfo = entity.head[ entity.headDestroyed ];
 | 
						|
		switch( headInfo.cf )
 | 
						|
		{
 | 
						|
			case "margwa_head_left":
 | 
						|
				Blackboard::SetBlackBoardAttribute( self, "_margwa_head", "left" );
 | 
						|
				break;
 | 
						|
				
 | 
						|
			case "margwa_head_mid":
 | 
						|
				Blackboard::SetBlackBoardAttribute( self, "_margwa_head", "middle" );
 | 
						|
				break;
 | 
						|
					
 | 
						|
			case "margwa_head_right":
 | 
						|
				Blackboard::SetBlackBoardAttribute( self, "_margwa_head", "right" );
 | 
						|
				break;
 | 
						|
		}
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldReactStun( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.reactStun ) && entity.reactStun ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldReactIDGun( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.reactIDGun ) && entity.reactIDGun ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldReactSword( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.reactSword ) && entity.reactSword ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldSpawn( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.needSpawn ) && entity.needSpawn ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldFreeze( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.isFrozen ) && entity.isFrozen ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldTeleportIn( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.needTeleportIn ) && entity.needTeleportIn ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldTeleportOut( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.needTeleportOut ) && entity.needTeleportOut ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldWait( entity )
 | 
						|
{
 | 
						|
	if ( ( isdefined( entity.waiting ) && entity.waiting ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaShouldReset( entity )
 | 
						|
{
 | 
						|
	if ( IsDefined( entity.headDestroyed ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( ( isdefined( entity.reactIDGun ) && entity.reactIDGun ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( ( isdefined( entity.reactSword ) && entity.reactSword ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( ( isdefined( entity.reactStun ) && entity.reactStun ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------------------------------------------------------------------
 | 
						|
// ACTIONS
 | 
						|
//----------------------------------------------------------------------------------------------------------------------------------
 | 
						|
function private margwaReactStunAction( entity, asmStateName )
 | 
						|
{
 | 
						|
	AnimationStateNetworkUtility::RequestState( entity, asmStateName );
 | 
						|
 | 
						|
	stunActionAST = entity ASTSearch( IString( asmStateName ) );
 | 
						|
	stunActionAnimation = AnimationStateNetworkUtility::SearchAnimationMap( entity, stunActionAST[ "animation" ] );
 | 
						|
 | 
						|
	closeTime = GetAnimLength( stunActionAnimation ) * 1000;
 | 
						|
 | 
						|
	entity MargwaServerUtils::margwaCloseAllHeads( closeTime );
 | 
						|
 | 
						|
	MargwaBehavior::margwaReactStunStart( entity );
 | 
						|
 | 
						|
	return 5;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
function private margwaSwipeAttackAction( entity, asmStateName )
 | 
						|
{
 | 
						|
	AnimationStateNetworkUtility::RequestState( entity, asmStateName );
 | 
						|
 | 
						|
	if ( !isdefined( entity.swipe_end_time ) )
 | 
						|
	{
 | 
						|
		swipeActionAST = entity ASTSearch( IString( asmStateName ) );
 | 
						|
		swipeActionAnimation = AnimationStateNetworkUtility::SearchAnimationMap( entity, swipeActionAST[ "animation" ] );
 | 
						|
		swipeActionTime = GetAnimLength( swipeActionAnimation ) * 1000;
 | 
						|
 | 
						|
		entity.swipe_end_time = GetTime() + swipeActionTime;
 | 
						|
	}
 | 
						|
 | 
						|
	return 5;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaSwipeAttackActionUpdate( entity, asmStateName )
 | 
						|
{
 | 
						|
	if ( isdefined( entity.swipe_end_time ) && GetTime() > entity.swipe_end_time )
 | 
						|
	{
 | 
						|
		return 4;
 | 
						|
	}
 | 
						|
 | 
						|
	return 5;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaIdleStart( entity )
 | 
						|
{
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		entity clientfield::set( "margwa_jaw", 1 );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaMoveStart( entity )
 | 
						|
{
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		if ( entity.zombie_move_speed == "run" )
 | 
						|
		{
 | 
						|
			entity clientfield::set( "margwa_jaw", 13 );
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			entity clientfield::set( "margwa_jaw", 7 );
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaDeathAction( entity )
 | 
						|
{
 | 
						|
	//insert anything that needs to be done right before zombie death
 | 
						|
}
 | 
						|
 | 
						|
function private margwaTraverseActionStart( entity )
 | 
						|
{
 | 
						|
	Blackboard::SetBlackBoardAttribute( entity, "_traversal_type", entity.traverseStartNode.animscript );
 | 
						|
 | 
						|
	if( isdefined( entity.traverseStartNode.animscript ) )
 | 
						|
	{
 | 
						|
		if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
		{
 | 
						|
			switch ( entity.traverseStartNode.animscript )
 | 
						|
			{
 | 
						|
			case "jump_down_36":
 | 
						|
				entity clientfield::set( "margwa_jaw", 21 );
 | 
						|
				break;
 | 
						|
	
 | 
						|
			case "jump_down_96":
 | 
						|
				entity clientfield::set( "margwa_jaw", 22 );
 | 
						|
				break;
 | 
						|
	
 | 
						|
			case "jump_up_36":
 | 
						|
				entity clientfield::set( "margwa_jaw", 24 );
 | 
						|
				break;
 | 
						|
	
 | 
						|
			case "jump_up_96":
 | 
						|
				entity clientfield::set( "margwa_jaw", 25 );
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaTeleportInStart( entity )
 | 
						|
{
 | 
						|
	entity Unlink();
 | 
						|
	if ( IsDefined( entity.teleportPos ) )
 | 
						|
	{
 | 
						|
		entity ForceTeleport( entity.teleportPos );
 | 
						|
	}
 | 
						|
	entity Show();
 | 
						|
	entity PathMode( "move allowed" );
 | 
						|
	entity.needTeleportIn = false;
 | 
						|
	Blackboard::SetBlackBoardAttribute( self, "_margwa_teleport", "in" );
 | 
						|
 | 
						|
	if ( isdefined( self.traveler ) )
 | 
						|
	{
 | 
						|
		self.traveler clientfield::set( "margwa_fx_travel", 0 );
 | 
						|
	}
 | 
						|
	self clientfield::increment( "margwa_fx_in", 1 );
 | 
						|
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		entity clientfield::set( "margwa_jaw", 17 );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaTeleportInTerminate( entity )
 | 
						|
{
 | 
						|
	if ( isdefined( self.traveler ) )
 | 
						|
	{
 | 
						|
		self.traveler clientfield::set( "margwa_fx_travel", 0 );
 | 
						|
	}
 | 
						|
	entity.isTeleporting = false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaTeleportOutStart( entity )
 | 
						|
{
 | 
						|
	entity.needTeleportOut = false;
 | 
						|
	entity.isTeleporting = true;
 | 
						|
	entity.teleportStart = entity.origin;
 | 
						|
 | 
						|
	Blackboard::SetBlackBoardAttribute( self, "_margwa_teleport", "out" );
 | 
						|
	self clientfield::increment( "margwa_fx_out", 1 );
 | 
						|
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		entity clientfield::set( "margwa_jaw", 18 );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaTeleportOutTerminate( entity )
 | 
						|
{
 | 
						|
	if ( isdefined( entity.traveler ) )
 | 
						|
	{
 | 
						|
		entity.traveler.origin = entity GetTagOrigin( "j_spine_1" );
 | 
						|
		entity.traveler clientfield::set( "margwa_fx_travel", 1 );
 | 
						|
	}
 | 
						|
 | 
						|
	entity Ghost();
 | 
						|
	entity PathMode( "dont move" );
 | 
						|
 | 
						|
	if ( isdefined( entity.traveler ) )
 | 
						|
	{
 | 
						|
		entity LinkTo( entity.traveler );
 | 
						|
	}
 | 
						|
 | 
						|
	if ( isdefined( entity.margwaWait ) )
 | 
						|
	{
 | 
						|
		entity thread [[ entity.margwaWait ]]();
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		entity thread MargwaServerUtils::margwaWait();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaPainStart( entity )
 | 
						|
{
 | 
						|
	entity notify( "stop_head_update" );
 | 
						|
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		head = Blackboard::GetBlackBoardAttribute( self, "_margwa_head" );
 | 
						|
		switch ( head )
 | 
						|
		{
 | 
						|
		case "left":
 | 
						|
			entity clientfield::set( "margwa_jaw", 3 );
 | 
						|
			break;
 | 
						|
 | 
						|
		case "middle":
 | 
						|
			entity clientfield::set( "margwa_jaw", 4 );
 | 
						|
			break;
 | 
						|
 | 
						|
		case "right":
 | 
						|
			entity clientfield::set( "margwa_jaw", 5 );
 | 
						|
			break;
 | 
						|
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	entity.headDestroyed = undefined;
 | 
						|
	entity.canStun = false;
 | 
						|
	entity.canDamage = false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaPainTerminate( entity )
 | 
						|
{
 | 
						|
	entity.headDestroyed = undefined;
 | 
						|
	entity.canStun = true;
 | 
						|
	entity.canDamage = true;
 | 
						|
 | 
						|
	entity MargwaServerUtils::margwaCloseAllHeads( 5000 );
 | 
						|
 | 
						|
	entity ClearPath();
 | 
						|
 | 
						|
	if ( IsDefined( entity.margwaPainTerminateCB ) )
 | 
						|
	{
 | 
						|
		entity [[ entity.margwaPainTerminateCB ]]();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaReactStunStart( entity )
 | 
						|
{
 | 
						|
	entity.reactStun = undefined;
 | 
						|
	entity.canStun = false;
 | 
						|
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		entity clientfield::set( "margwa_jaw", 6 );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaReactStunTerminate( entity )
 | 
						|
{
 | 
						|
	entity.canStun = true;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaReactIDGunStart( entity )
 | 
						|
{
 | 
						|
	entity.reactIDGun = undefined;
 | 
						|
	entity.canStun = false;
 | 
						|
 | 
						|
	isPacked = false;
 | 
						|
	
 | 
						|
	if( BlackBoard::GetBlackBoardAttribute( entity, "_zombie_damageweapon_type" ) == "regular" )
 | 
						|
	{
 | 
						|
		if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
		{
 | 
						|
			entity clientfield::set( "margwa_jaw", 8 );
 | 
						|
		}
 | 
						|
		entity MargwaServerUtils::margwaCloseAllHeads( 5000 );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
		{
 | 
						|
			entity clientfield::set( "margwa_jaw", 9 );
 | 
						|
		}
 | 
						|
		entity MargwaServerUtils::margwaCloseAllHeads( 2 * 5000 );
 | 
						|
 | 
						|
		isPacked = true;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( IsDefined( entity.idgun_damage ) )
 | 
						|
	{
 | 
						|
		entity [[ entity.idgun_damage ]]( isPacked );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaReactIDGunTerminate( entity )
 | 
						|
{
 | 
						|
	entity.canStun = true;
 | 
						|
	Blackboard::SetBlackBoardAttribute( entity, "_zombie_damageweapon_type", "regular" );
 | 
						|
}
 | 
						|
 | 
						|
function private margwaReactSwordStart( entity )
 | 
						|
{
 | 
						|
	entity.reactSword = undefined;
 | 
						|
	entity.canStun = false;
 | 
						|
 | 
						|
	if ( IsDefined( entity.head_chopper ) )
 | 
						|
	{
 | 
						|
		entity.head_chopper notify( "react_sword" );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaReactSwordTerminate( entity )
 | 
						|
{
 | 
						|
	entity.canStun = true;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaSpawnStart( entity )
 | 
						|
{
 | 
						|
	entity.needSpawn = false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaSmashAttackStart( entity )
 | 
						|
{
 | 
						|
	entity MargwaServerUtils::margwaHeadSmash();
 | 
						|
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		entity clientfield::set( "margwa_jaw", 14 );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaSmashAttackTerminate( entity )
 | 
						|
{
 | 
						|
	entity MargwaServerUtils::margwaCloseAllHeads();
 | 
						|
}
 | 
						|
 | 
						|
function margwaSwipeAttackStart( entity )
 | 
						|
{
 | 
						|
	if ( entity MargwaServerUtils::shouldUpdateJaw() )
 | 
						|
	{
 | 
						|
		entity clientfield::set( "margwa_jaw", 16 );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaSwipeattackTerminate( entity )
 | 
						|
{
 | 
						|
	entity MargwaServerUtils::margwaCloseAllHeads();
 | 
						|
}
 | 
						|
 | 
						|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
// MOCOMPS
 | 
						|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
function private mocompMargwaTeleportTraversalInit( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
 | 
						|
{
 | 
						|
	entity OrientMode( "face angle", entity.angles[1] );
 | 
						|
	entity AnimMode( "normal" );
 | 
						|
 | 
						|
	if ( isdefined( entity.traverseEndNode ) )
 | 
						|
	{
 | 
						|
		entity.teleportStart = entity.origin;
 | 
						|
		entity.teleportPos = entity.traverseEndNode.origin;
 | 
						|
		self clientfield::increment( "margwa_fx_out", 1 );
 | 
						|
 | 
						|
		if ( isdefined( entity.traverseStartNode ) )
 | 
						|
		{
 | 
						|
			if ( isdefined( entity.traverseStartNode.speed ) )
 | 
						|
			{
 | 
						|
				self.margwa_teleport_speed = entity.traverseStartNode.speed;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private mocompMargwaTeleportTraversalUpdate( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
function private mocompMargwaTeleportTraversalTerminate( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
 | 
						|
{
 | 
						|
	margwaTeleportOutTerminate( entity );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#namespace MargwaServerUtils;
 | 
						|
 | 
						|
function private margwaSpawnSetup()
 | 
						|
{
 | 
						|
	self DisableAimAssist();
 | 
						|
 | 
						|
	self.disableAmmoDrop = true;
 | 
						|
	self.no_gib = true;
 | 
						|
	self.ignore_nuke = true;
 | 
						|
	self.ignore_enemy_count = true;
 | 
						|
	self.ignore_round_robbin_death = true; 
 | 
						|
 | 
						|
	self.zombie_move_speed = "walk";
 | 
						|
 | 
						|
	self.overrideActorDamage = &margwaDamage;
 | 
						|
	self.canDamage = true;
 | 
						|
 | 
						|
	self.headAttached = 3;
 | 
						|
	self.headOpen = 0;
 | 
						|
 | 
						|
	self margwaInitHead( "c_zom_margwa_chunks_le", "j_chunk_head_bone_le" );
 | 
						|
	self margwaInitHead( "c_zom_margwa_chunks_mid", "j_chunk_head_bone" );
 | 
						|
	self margwaInitHead( "c_zom_margwa_chunks_ri", "j_chunk_head_bone_ri" );
 | 
						|
 | 
						|
	self.headHealthMax = 600;
 | 
						|
 | 
						|
	self margwaDisableStun();
 | 
						|
 | 
						|
	self.traveler = Spawn( "script_model", self.origin );
 | 
						|
	self.traveler SetModel( "tag_origin" );
 | 
						|
	self.traveler NotSolid();
 | 
						|
 | 
						|
	self.travelerTell = Spawn( "script_model", self.origin );
 | 
						|
	self.travelerTell SetModel( "tag_origin" );
 | 
						|
	self.travelerTell NotSolid();
 | 
						|
 | 
						|
	self thread margwaDeath();
 | 
						|
 | 
						|
	self.updateSight = false;
 | 
						|
	self.ignoreRunAndGunDist = true;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaDeath()
 | 
						|
{
 | 
						|
	self waittill( "death" );
 | 
						|
 | 
						|
	if( isdefined(self.e_head_attacker) )
 | 
						|
	{
 | 
						|
		self.e_head_attacker notify( "margwa_kill" );
 | 
						|
	}
 | 
						|
 | 
						|
	if ( IsDefined( self.traveler ) )
 | 
						|
	{
 | 
						|
		self.traveler Delete();
 | 
						|
	}
 | 
						|
 | 
						|
	if ( IsDefined( self.travelerTell ) )
 | 
						|
	{
 | 
						|
		self.travelerTell Delete();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaEnableStun()
 | 
						|
{
 | 
						|
	self.canStun = true;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaDisableStun()
 | 
						|
{
 | 
						|
	self.canStun = false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaInitHead( headModel, headTag )
 | 
						|
{	
 | 
						|
	model = headModel;
 | 
						|
	model_gore = undefined;
 | 
						|
	
 | 
						|
	switch ( headModel )
 | 
						|
	{
 | 
						|
	case "c_zom_margwa_chunks_le":
 | 
						|
		if( isdefined( level.margwa_head_left_model_override ))
 | 
						|
		{
 | 
						|
			model = level.margwa_head_left_model_override;
 | 
						|
			model_gore = level.margwa_gore_left_model_override;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case "c_zom_margwa_chunks_mid":
 | 
						|
		if( isdefined( level.margwa_head_mid_model_override ))
 | 
						|
		{
 | 
						|
			model = level.margwa_head_mid_model_override;
 | 
						|
			model_gore = level.margwa_gore_mid_model_override;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case "c_zom_margwa_chunks_ri":
 | 
						|
		if( isdefined( level.margwa_head_right_model_override ))
 | 
						|
		{
 | 
						|
			model = level.margwa_head_right_model_override;
 | 
						|
			model_gore = level.margwa_gore_right_model_override;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	
 | 
						|
	self Attach( model );
 | 
						|
 | 
						|
	if ( !IsDefined( self.head ) )
 | 
						|
	{
 | 
						|
		self.head = [];
 | 
						|
	}
 | 
						|
 | 
						|
	self.head[ model ] = SpawnStruct();
 | 
						|
	self.head[ model ].model = model;
 | 
						|
	self.head[ model ].tag = headTag;
 | 
						|
	self.head[ model ].health = 600;
 | 
						|
	self.head[ model ].canDamage = false;
 | 
						|
 | 
						|
	self.head[ model ].open = 1;
 | 
						|
	self.head[ model ].closed = 2;
 | 
						|
	self.head[ model ].smash = 3;
 | 
						|
 | 
						|
	switch ( headModel )
 | 
						|
	{
 | 
						|
	case "c_zom_margwa_chunks_le":
 | 
						|
		self.head[ model ].cf = "margwa_head_left";
 | 
						|
		self.head[ model ].impactCF = "margwa_head_left_hit";
 | 
						|
		self.head[ model ].gore = "c_zom_margwa_gore_le";
 | 
						|
		if( isdefined( model_gore ))
 | 
						|
		{
 | 
						|
			self.head[ model ].gore = model_gore;
 | 
						|
		}
 | 
						|
		self.head[ model ].killIndex = 1;
 | 
						|
		self.head_left_model = model;
 | 
						|
		break;
 | 
						|
 | 
						|
	case "c_zom_margwa_chunks_mid":
 | 
						|
		self.head[ model ].cf = "margwa_head_mid";
 | 
						|
		self.head[ model ].impactCF = "margwa_head_mid_hit";
 | 
						|
		self.head[ model ].gore = "c_zom_margwa_gore_mid";
 | 
						|
		if( isdefined( model_gore ))
 | 
						|
		{
 | 
						|
			self.head[ model ].gore = model_gore;
 | 
						|
		}
 | 
						|
		self.head[ model ].killIndex = 2;
 | 
						|
		self.head_mid_model = model;
 | 
						|
		break;
 | 
						|
 | 
						|
	case "c_zom_margwa_chunks_ri":
 | 
						|
		self.head[ model ].cf = "margwa_head_right";
 | 
						|
		self.head[ model ].impactCF = "margwa_head_right_hit";
 | 
						|
		self.head[ model ].gore = "c_zom_margwa_gore_ri";
 | 
						|
		if( isdefined( model_gore ))
 | 
						|
		{
 | 
						|
			self.head[ model ].gore = model_gore;
 | 
						|
		}
 | 
						|
		self.head[ model ].killIndex = 3;
 | 
						|
		self.head_right_model = model;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	self thread margwaHeadUpdate( self.head[ model ] );
 | 
						|
}
 | 
						|
 | 
						|
function margwaSetHeadHealth( health )
 | 
						|
{
 | 
						|
	self.headHealthMax = health;
 | 
						|
 | 
						|
	foreach( head in self.head )
 | 
						|
	{
 | 
						|
		head.health = health;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaResetHeadTime( min, max )
 | 
						|
{
 | 
						|
	time = GetTime() + RandomIntRange( min, max );
 | 
						|
	return time;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaHeadCanOpen()
 | 
						|
{
 | 
						|
	if ( self.headAttached > 1 )
 | 
						|
	{
 | 
						|
		if ( self.headOpen < (self.headAttached - 1) )
 | 
						|
		{
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaHeadUpdate( headInfo )
 | 
						|
{
 | 
						|
	self endon( "death" );
 | 
						|
	self endon( "stop_head_update" );
 | 
						|
 | 
						|
	headInfo notify( "stop_head_update" );
 | 
						|
	headInfo endon( "stop_head_update" );
 | 
						|
 | 
						|
	while ( 1 )
 | 
						|
	{
 | 
						|
		if ( self IsPaused() )
 | 
						|
		{
 | 
						|
			util::wait_network_frame();
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
	
 | 
						|
		if ( !IsDefined( headInfo.closeTime ) )
 | 
						|
		{
 | 
						|
			if ( self.headAttached == 1 )
 | 
						|
			{
 | 
						|
				headInfo.closeTime = margwaResetHeadTime( 500, 1000 );
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				headInfo.closeTime = margwaResetHeadTime( 1500, 3500 );
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ( GetTime() > headInfo.closeTime && self margwaHeadCanOpen() )
 | 
						|
		{
 | 
						|
			self.headOpen++;
 | 
						|
			headInfo.closeTime = undefined;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			util::wait_network_frame();
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		self margwaHeadDamageDelay( headInfo, true );
 | 
						|
		self clientfield::set( headInfo.cf, headInfo.open );
 | 
						|
		self playsoundontag( "zmb_vocals_margwa_ambient", headInfo.tag );
 | 
						|
 | 
						|
		while ( 1 )
 | 
						|
		{
 | 
						|
			if ( !IsDefined( headInfo.openTime ) )
 | 
						|
			{
 | 
						|
				headInfo.openTime = margwaResetHeadTime( 3000, 5000 );
 | 
						|
			}
 | 
						|
 | 
						|
			if ( GetTime() > headInfo.openTime )
 | 
						|
			{
 | 
						|
				self.headOpen--;
 | 
						|
				headInfo.openTime = undefined;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				util::wait_network_frame();
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		self margwaHeadDamageDelay( headInfo, false );
 | 
						|
		self clientfield::set( headInfo.cf, headInfo.closed );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaHeadDamageDelay( headInfo, canDamage )
 | 
						|
{
 | 
						|
	self endon( "death" );
 | 
						|
 | 
						|
	wait( 0.1 );
 | 
						|
 | 
						|
	headInfo.canDamage = canDamage;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaHeadSmash()
 | 
						|
{
 | 
						|
	self notify( "stop_head_update" );
 | 
						|
 | 
						|
	headAlive = [];
 | 
						|
	foreach( head in self.head )
 | 
						|
	{
 | 
						|
		if ( head.health > 0 )
 | 
						|
		{
 | 
						|
			headAlive[ headAlive.size ] = head;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	headAlive = array::randomize( headAlive );
 | 
						|
	open = false;
 | 
						|
 | 
						|
	foreach( head in headAlive )
 | 
						|
	{
 | 
						|
		if ( !open )
 | 
						|
		{
 | 
						|
			head.canDamage = true;
 | 
						|
			self clientfield::set( head.cf, head.smash );
 | 
						|
			open = true;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			self margwaCloseHead( head );
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function private margwaCloseHead( headInfo )
 | 
						|
{
 | 
						|
	headInfo.canDamage = false;
 | 
						|
	self clientfield::set( headInfo.cf, headInfo.closed );
 | 
						|
}
 | 
						|
 | 
						|
function private margwaCloseAllHeads( closeTime )
 | 
						|
{
 | 
						|
	if ( self IsPaused() )
 | 
						|
	{
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	foreach ( head in self.head )
 | 
						|
	{
 | 
						|
		if ( head.health > 0 )
 | 
						|
		{
 | 
						|
			head.closeTime = undefined;
 | 
						|
			head.openTime = undefined;
 | 
						|
 | 
						|
			if ( IsDefined( closeTime ) )
 | 
						|
			{
 | 
						|
				head.closeTime = GetTime() + closeTime;
 | 
						|
			}
 | 
						|
 | 
						|
			self.headOpen = 0;
 | 
						|
 | 
						|
			self margwaCloseHead( head );
 | 
						|
			self thread margwaHeadUpdate( head );
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaKillHead( modelHit, attacker )
 | 
						|
{
 | 
						|
	headInfo = self.head[ modelHit ];
 | 
						|
 | 
						|
	headInfo.health = 0;
 | 
						|
	headInfo notify( "stop_head_update" );
 | 
						|
 | 
						|
	if ( ( isdefined( headInfo.canDamage ) && headInfo.canDamage ) )
 | 
						|
	{
 | 
						|
		self margwaCloseHead( headInfo );
 | 
						|
		self.headOpen--;
 | 
						|
	}
 | 
						|
 | 
						|
	self margwaUpdateMoveSpeed();
 | 
						|
 | 
						|
	if ( IsDefined( self.destroyHeadCB ) )
 | 
						|
	{
 | 
						|
		self thread [[ self.destroyHeadCB ]]( modelHit, attacker );
 | 
						|
	}
 | 
						|
 | 
						|
	self clientfield::set( "margwa_head_killed", headInfo.killIndex );
 | 
						|
 | 
						|
	self Detach( headInfo.model );
 | 
						|
	self Attach( headInfo.gore );
 | 
						|
	self.headAttached--;
 | 
						|
 | 
						|
	if ( self.headAttached <= 0 )
 | 
						|
	{
 | 
						|
		self.e_head_attacker = attacker;
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		self.headDestroyed = modelHit;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function margwaCanDamageAnyHead()
 | 
						|
{
 | 
						|
	foreach( head in self.head )
 | 
						|
	{
 | 
						|
		if ( IsDefined( head ) && head.health > 0 && ( isdefined( head.canDamage ) && head.canDamage ) )
 | 
						|
		{
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function margwaCanDamageHead()
 | 
						|
{
 | 
						|
	if ( IsDefined( self ) && self.health > 0 && ( isdefined( self.canDamage ) && self.canDamage ) )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
function show_hit_marker()  // self = player
 | 
						|
{
 | 
						|
	if ( IsDefined( self ) && IsDefined( self.hud_damagefeedback ) )
 | 
						|
	{
 | 
						|
		self.hud_damagefeedback SetShader( "damage_feedback", 24, 48 );
 | 
						|
		self.hud_damagefeedback.alpha = 1;
 | 
						|
		self.hud_damagefeedback FadeOverTime(1);
 | 
						|
		self.hud_damagefeedback.alpha = 0;
 | 
						|
	}	
 | 
						|
}
 | 
						|
 | 
						|
function private isDirectHitWeapon( weapon )
 | 
						|
{
 | 
						|
	foreach( dhWeapon in level.dhWeapons )
 | 
						|
	{
 | 
						|
		if ( weapon.name == dhWeapon )
 | 
						|
		{
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		if ( isdefined( weapon.rootweapon ) && isdefined( weapon.rootweapon.name ) && weapon.rootweapon.name == dhWeapon )
 | 
						|
		{
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// uses the bone name to figure out which head was hit
 | 
						|
function margwaDamage( inflictor, attacker, damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex )
 | 
						|
{
 | 
						|
	if ( ( isdefined( self.is_kill ) && self.is_kill ) )
 | 
						|
	{
 | 
						|
		return damage;
 | 
						|
	}
 | 
						|
 | 
						|
	if( isdefined(attacker) && isdefined(attacker.n_margwa_head_damage_scale) )
 | 
						|
	{
 | 
						|
	   	damage = damage * attacker.n_margwa_head_damage_scale;
 | 
						|
	}
 | 
						|
	
 | 
						|
	if( isdefined( level._margwa_damage_cb ) )
 | 
						|
	{
 | 
						|
		n_result = [[ level._margwa_damage_cb ]]( inflictor, attacker, damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
 | 
						|
		
 | 
						|
		if( isdefined( n_result ) )
 | 
						|
		{
 | 
						|
			return n_result;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	damageOpen = false;		// mouth was open during damage
 | 
						|
	
 | 
						|
	if ( !( isdefined( self.canDamage ) && self.canDamage ) )
 | 
						|
	{
 | 
						|
		self.health += 1;	// impact fx only work when damage is applied
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( isDirectHitWeapon( weapon ) )
 | 
						|
	{
 | 
						|
		headAlive = [];
 | 
						|
		foreach ( head in self.head )
 | 
						|
		{
 | 
						|
			if ( head margwaCanDamageHead() )
 | 
						|
			{
 | 
						|
				headAlive[ headAlive.size ] = head;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ( headAlive.size > 0 )
 | 
						|
		{
 | 
						|
			max = 100000;
 | 
						|
			headClosest = undefined;
 | 
						|
			foreach ( head in headAlive )
 | 
						|
			{
 | 
						|
				distSq = DistanceSquared( point, self GetTagOrigin( head.tag ) );
 | 
						|
				if ( distSq < max )
 | 
						|
				{
 | 
						|
					max = distSq;
 | 
						|
					headClosest = head;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			if ( IsDefined( headClosest ) )
 | 
						|
			{
 | 
						|
				if ( max < 24 * 24 )
 | 
						|
				{
 | 
						|
					if ( isdefined( level.margwa_damage_override_callback ) && IsFunctionPtr( level.margwa_damage_override_callback ) )
 | 
						|
					{
 | 
						|
						damage = attacker [[ level.margwa_damage_override_callback ]]( damage );
 | 
						|
					}
 | 
						|
					
 | 
						|
					headClosest.health -= damage;
 | 
						|
					damageOpen = true;
 | 
						|
					self clientfield::increment( headClosest.impactCF );
 | 
						|
					attacker show_hit_marker();
 | 
						|
 | 
						|
					if ( headClosest.health <= 0 )
 | 
						|
					{
 | 
						|
						if( isdefined(level.margwa_head_kill_weapon_check) )
 | 
						|
						{
 | 
						|
							[[level.margwa_head_kill_weapon_check]]( self, weapon );
 | 
						|
						}
 | 
						|
						
 | 
						|
						if ( self margwaKillHead( headClosest.model, attacker ) )
 | 
						|
						{
 | 
						|
							return self.health;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	partName = GetPartName( self.model, boneIndex );
 | 
						|
	if ( IsDefined( partName ) )
 | 
						|
	{
 | 
						|
		/#
 | 
						|
			if ( ( isdefined( self.debugHitLoc ) && self.debugHitLoc ) )
 | 
						|
			{
 | 
						|
				PrintTopRightLn( partName + " damage: " + damage );
 | 
						|
			}
 | 
						|
		#/
 | 
						|
		modelHit = self margwaHeadHit( self, partName );
 | 
						|
		if ( IsDefined( modelHit ) )
 | 
						|
		{
 | 
						|
			headInfo = self.head[ modelHit ];
 | 
						|
			if ( headInfo margwaCanDamageHead() )
 | 
						|
			{
 | 
						|
				if ( isdefined( level.margwa_damage_override_callback ) && IsFunctionPtr( level.margwa_damage_override_callback ) )
 | 
						|
				{
 | 
						|
					damage = attacker [[ level.margwa_damage_override_callback ]]( damage );
 | 
						|
				}
 | 
						|
				
 | 
						|
				if( isdefined( attacker ) )
 | 
						|
				{
 | 
						|
					attacker notify( "margwa_headshot", self );
 | 
						|
				}
 | 
						|
				
 | 
						|
				headInfo.health -= damage;
 | 
						|
				damageOpen = true;
 | 
						|
				self clientfield::increment( headInfo.impactCF );
 | 
						|
				attacker show_hit_marker();
 | 
						|
 | 
						|
				if ( headInfo.health <= 0 )
 | 
						|
				{
 | 
						|
					if( isdefined(level.margwa_head_kill_weapon_check) )
 | 
						|
					{
 | 
						|
						[[level.margwa_head_kill_weapon_check]]( self, weapon );
 | 
						|
					}
 | 
						|
 | 
						|
					if ( self margwaKillHead( modelHit, attacker ) )
 | 
						|
					{
 | 
						|
						return self.health;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if ( damageOpen )
 | 
						|
	{
 | 
						|
		return 0;		// custom fx when damaging head
 | 
						|
	}
 | 
						|
 | 
						|
	self.health += 1;	// impact fx only work when damage is applied to ent
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaHeadHit( entity, partName )
 | 
						|
{
 | 
						|
	switch ( partName )
 | 
						|
	{
 | 
						|
	case "j_chunk_head_bone_le":
 | 
						|
	case "j_jaw_lower_1_le":
 | 
						|
		return self.head_left_model;
 | 
						|
 | 
						|
	case "j_chunk_head_bone":
 | 
						|
	case "j_jaw_lower_1":
 | 
						|
		return self.head_mid_model;
 | 
						|
 | 
						|
	case "j_chunk_head_bone_ri":
 | 
						|
	case "j_jaw_lower_1_ri":
 | 
						|
		return self.head_right_model;
 | 
						|
	}
 | 
						|
 | 
						|
	return undefined;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaUpdateMoveSpeed()
 | 
						|
{
 | 
						|
	if ( self.zombie_move_speed == "walk" )
 | 
						|
	{
 | 
						|
		self.zombie_move_speed = "run";
 | 
						|
		//self ASMSetAnimationRate( 0.8 );
 | 
						|
		Blackboard::SetBlackBoardAttribute( self, "_locomotion_speed", "locomotion_speed_run" );
 | 
						|
	}
 | 
						|
	else if ( self.zombie_move_speed == "run" )
 | 
						|
	{
 | 
						|
		self.zombie_move_speed = "sprint";
 | 
						|
		//self ASMSetAnimationRate( 1.0 );
 | 
						|
		Blackboard::SetBlackBoardAttribute( self, "_locomotion_speed", "locomotion_speed_sprint" );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaForceSprint()
 | 
						|
{
 | 
						|
	self.zombie_move_speed = "sprint";
 | 
						|
	Blackboard::SetBlackBoardAttribute( self, "_locomotion_speed", "locomotion_speed_sprint" );
 | 
						|
}
 | 
						|
 | 
						|
function private margwaDestroyHead( modelHit )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
function shouldUpdateJaw()
 | 
						|
{
 | 
						|
	if ( !( isdefined( self.jawAnimEnabled ) && self.jawAnimEnabled ) )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( self.headAttached < 3 )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function margwaSetGoal( origin, radius, boundaryDist )
 | 
						|
{
 | 
						|
	pos = GetClosestPointOnNavMesh( origin, 64, 30 );
 | 
						|
	if ( IsDefined( pos ) )
 | 
						|
	{
 | 
						|
		self SetGoal( pos );
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	self SetGoal( self.origin );
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
function private margwaWait()
 | 
						|
{
 | 
						|
	self endon( "death" );
 | 
						|
 | 
						|
	self.waiting = true;
 | 
						|
	self.needTeleportIn = true;
 | 
						|
 | 
						|
	destPos = self.teleportPos + ( 0, 0, 60 );
 | 
						|
	dist = Distance( self.teleportStart, destPos );
 | 
						|
	time = dist / 600;
 | 
						|
 | 
						|
	if ( isdefined( self.margwa_teleport_speed ) )
 | 
						|
	{
 | 
						|
		if ( self.margwa_teleport_speed > 0 )
 | 
						|
		{
 | 
						|
			time = dist / self.margwa_teleport_speed;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if ( isdefined( self.traveler ) )
 | 
						|
	{
 | 
						|
		self thread margwaTell();
 | 
						|
 | 
						|
		self.traveler MoveTo( destPos, time );
 | 
						|
		self.traveler util::waittill_any_ex( ( time + 0.1 ), "movedone", self, "death" );
 | 
						|
 | 
						|
		self.travelerTell clientfield::set( "margwa_fx_travel_tell", 0 );
 | 
						|
	}
 | 
						|
 | 
						|
	self.waiting = false;
 | 
						|
	self.needTeleportOut = false;
 | 
						|
 | 
						|
	if ( isdefined( self.margwa_teleport_speed ) )
 | 
						|
	{
 | 
						|
		self.margwa_teleport_speed = undefined;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function margwaTell()
 | 
						|
{
 | 
						|
	self endon( "death" );
 | 
						|
 | 
						|
	self.travelerTell.origin = self.teleportPos;
 | 
						|
 | 
						|
	util::wait_network_frame();
 | 
						|
 | 
						|
	self.travelerTell clientfield::set( "margwa_fx_travel_tell", 1 );
 | 
						|
}
 | 
						|
 | 
						|
function private shieldFacing( vDir, limit, front = true )
 | 
						|
{
 | 
						|
	orientation = self getPlayerAngles();
 | 
						|
	forwardVec = anglesToForward( orientation );
 | 
						|
	if ( !front )
 | 
						|
	{
 | 
						|
		forwardVec = -forwardVec;
 | 
						|
	}
 | 
						|
	forwardVec2D = ( forwardVec[0], forwardVec[1], 0 );
 | 
						|
	unitForwardVec2D = VectorNormalize( forwardVec2D );
 | 
						|
 | 
						|
	toFaceeVec = -vDir;
 | 
						|
	toFaceeVec2D = ( toFaceeVec[0], toFaceeVec[1], 0 );
 | 
						|
	unitToFaceeVec2D = VectorNormalize( toFaceeVec2D );
 | 
						|
	
 | 
						|
	dotProduct = VectorDot( unitForwardVec2D, unitToFaceeVec2D );
 | 
						|
	return ( dotProduct > limit ); // more or less in front
 | 
						|
}
 | 
						|
 | 
						|
function private inSmashAttackRange( enemy )
 | 
						|
{
 | 
						|
	smashPos = self.origin;
 | 
						|
	
 | 
						|
	heightOffset = abs( self.origin[2] - enemy.origin[2] );
 | 
						|
	if ( heightOffset > 48 )
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	
 | 
						|
	distSq = DistanceSquared( smashPos, enemy.origin );
 | 
						|
	range = 160 * 160;
 | 
						|
 | 
						|
	if ( distSq < range )
 | 
						|
	{
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 |