899 lines
23 KiB
Plaintext
899 lines
23 KiB
Plaintext
// IW6 GSC SOURCE
|
|
// Generated by https://github.com/xensik/gsc-tool
|
|
|
|
main()
|
|
{
|
|
setupdogstate();
|
|
thread think();
|
|
thread watchownerdamage();
|
|
thread watchownerdeath();
|
|
thread watchownerteamchange();
|
|
thread waitforbadpath();
|
|
thread waitforpathset();
|
|
}
|
|
|
|
setupdogstate()
|
|
{
|
|
self.blockgoalpos = 0;
|
|
self.ownerradiussq = 20736;
|
|
self.meleeradiussq = 16384;
|
|
self.attackoffset = 25 + self.radius;
|
|
self.attackradiussq = 202500;
|
|
self.warningradiussq = 302500;
|
|
self.warningzheight = 96.0;
|
|
self.attackzheight = 54;
|
|
self.attackzheightdown = -64;
|
|
self.ownerdamagedradiussq = 2250000;
|
|
self.dogdamagedradiussq = 2250000;
|
|
self.keeppursuingtargetradiussq = 1000000;
|
|
self.preferredoffsetfromowner = 76;
|
|
self.minoffsetfromowner = 50;
|
|
self.forceattack = 0;
|
|
self.ignoreclosefoliage = 1;
|
|
self.movemode = "run";
|
|
self.enableextendedkill = 1;
|
|
self.attackstate = "idle";
|
|
self.movestate = "idle";
|
|
self.bhasbadpath = 0;
|
|
self.timeoflastdamage = 0;
|
|
self.allowcrouch = 1;
|
|
self scragentsetgoalradius( 24 );
|
|
}
|
|
|
|
init()
|
|
{
|
|
self.animcbs = spawnstruct();
|
|
self.animcbs.onenter = [];
|
|
self.animcbs.onenter["idle"] = maps\mp\agents\dog\_dog_idle::main;
|
|
self.animcbs.onenter["move"] = maps\mp\agents\dog\_dog_move::main;
|
|
self.animcbs.onenter["traverse"] = maps\mp\agents\dog\_dog_traverse::main;
|
|
self.animcbs.onenter["melee"] = maps\mp\agents\dog\_dog_melee::main;
|
|
self.animcbs.onexit = [];
|
|
self.animcbs.onexit["idle"] = maps\mp\agents\dog\_dog_idle::end_script;
|
|
self.animcbs.onexit["move"] = maps\mp\agents\dog\_dog_move::end_script;
|
|
self.animcbs.onexit["melee"] = maps\mp\agents\dog\_dog_melee::end_script;
|
|
self.animcbs.onexit["traverse"] = maps\mp\agents\dog\_dog_traverse::end_script;
|
|
self.watchattackstatefunc = ::watchattackstate;
|
|
self.aistate = "idle";
|
|
self.movemode = "fastwalk";
|
|
self.radius = 15;
|
|
self.height = 40;
|
|
}
|
|
|
|
onenteranimstate( var_0, var_1 )
|
|
{
|
|
self notify( "killanimscript" );
|
|
|
|
if ( !isdefined( self.animcbs.onenter[var_1] ) )
|
|
return;
|
|
|
|
if ( var_0 == var_1 && var_1 != "traverse" )
|
|
return;
|
|
|
|
if ( isdefined( self.animcbs.onexit[var_0] ) )
|
|
self [[ self.animcbs.onexit[var_0] ]]();
|
|
|
|
exitaistate( self.aistate );
|
|
self.aistate = var_1;
|
|
enteraistate( var_1 );
|
|
self [[ self.animcbs.onenter[var_1] ]]();
|
|
}
|
|
|
|
think()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
if ( isdefined( self.owner ) )
|
|
{
|
|
self endon( "owner_disconnect" );
|
|
thread destroyonownerdisconnect( self.owner );
|
|
}
|
|
|
|
self thread [[ self.watchattackstatefunc ]]();
|
|
thread monitorflash();
|
|
|
|
for (;;)
|
|
{
|
|
if ( self.aistate != "melee" && !self.statelocked && readytomeleetarget() && !didpastmeleefail() )
|
|
self scragentbeginmelee( self.curmeleetarget );
|
|
|
|
switch ( self.aistate )
|
|
{
|
|
case "idle":
|
|
updateidle();
|
|
break;
|
|
case "move":
|
|
updatemove();
|
|
break;
|
|
case "melee":
|
|
updatemelee();
|
|
break;
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
didpastpursuitfail( var_0 )
|
|
{
|
|
if ( isdefined( self.curmeleetarget ) && var_0 != self.curmeleetarget )
|
|
return 0;
|
|
|
|
if ( !isdefined( self.lastpursuitfailedpos ) || !isdefined( self.lastpursuitfailedmypos ) )
|
|
return 0;
|
|
|
|
if ( distance2dsquared( var_0.origin, self.lastpursuitfailedpos ) > 4 )
|
|
return 0;
|
|
|
|
if ( self.blastpursuitfailedposbad )
|
|
return 1;
|
|
|
|
if ( distancesquared( self.origin, self.lastpursuitfailedmypos ) > 4096 && gettime() - self.lastpursuitfailedtime > 2000 )
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
didpastmeleefail()
|
|
{
|
|
if ( isdefined( self.lastmeleefailedpos ) && isdefined( self.lastmeleefailedmypos ) && distance2dsquared( self.curmeleetarget.origin, self.lastmeleefailedpos ) < 4 && distancesquared( self.origin, self.lastmeleefailedmypos ) < 2500 )
|
|
return 1;
|
|
|
|
if ( wanttoattacktargetbutcant( 0 ) )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
enteraistate( var_0 )
|
|
{
|
|
exitaistate( self.aistate );
|
|
self.aistate = var_0;
|
|
|
|
switch ( var_0 )
|
|
{
|
|
case "idle":
|
|
self.movestate = "idle";
|
|
self.bhasbadpath = 0;
|
|
break;
|
|
case "move":
|
|
self.movestate = "follow";
|
|
break;
|
|
case "melee":
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
exitaistate( var_0 )
|
|
{
|
|
switch ( var_0 )
|
|
{
|
|
case "move":
|
|
self.ownerprevpos = undefined;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
updateidle()
|
|
{
|
|
updatemovestate();
|
|
}
|
|
|
|
updatemove()
|
|
{
|
|
updatemovestate();
|
|
}
|
|
|
|
updatemelee()
|
|
{
|
|
self scragentsetgoalpos( self.origin );
|
|
}
|
|
|
|
updatemovestate()
|
|
{
|
|
if ( self.blockgoalpos )
|
|
return;
|
|
|
|
self.prevmovestate = self.movestate;
|
|
var_0 = undefined;
|
|
var_1 = 0;
|
|
var_2 = 0;
|
|
var_3 = 500;
|
|
|
|
if ( self.bhasbadpath && gettime() - self.lastbadpathtime < var_3 )
|
|
{
|
|
self.movestate = "follow";
|
|
var_1 = 1;
|
|
}
|
|
else
|
|
self.movestate = getmovestate();
|
|
|
|
if ( self.movestate == "pursuit" )
|
|
{
|
|
var_0 = getattackpoint( self.enemy );
|
|
var_4 = 0;
|
|
|
|
if ( isdefined( self.lastbadpathtime ) && gettime() - self.lastbadpathtime < 3000 )
|
|
{
|
|
if ( distance2dsquared( var_0, self.lastbadpathgoal ) < 16 )
|
|
var_4 = 1;
|
|
else if ( isdefined( self.lastbadpathmovestate ) && self.lastbadpathmovestate == "pursuit" && distance2dsquared( self.lastbadpathultimategoal, self.enemy.origin ) < 16 )
|
|
var_4 = 1;
|
|
}
|
|
|
|
if ( var_4 )
|
|
{
|
|
self.movestate = "follow";
|
|
var_2 = 1;
|
|
}
|
|
else if ( wanttoattacktargetbutcant( 1 ) )
|
|
{
|
|
self.movestate = "follow";
|
|
var_2 = 1;
|
|
}
|
|
else if ( didpastpursuitfail( self.enemy ) )
|
|
{
|
|
self.movestate = "follow";
|
|
var_2 = 1;
|
|
}
|
|
}
|
|
|
|
setpastpursuitfailed( var_2 );
|
|
|
|
if ( self.movestate == "follow" )
|
|
{
|
|
self.curmeleetarget = undefined;
|
|
self.movemode = getfollowmovemode( self.movemode );
|
|
self.barrivalsenabled = 1;
|
|
var_5 = self getpathgoalpos();
|
|
|
|
if ( !isdefined( var_5 ) )
|
|
var_5 = self.origin;
|
|
|
|
if ( self.owner.sessionstate == "spectator" )
|
|
return;
|
|
|
|
if ( gettime() - self.timeoflastdamage < 5000 )
|
|
var_1 = 1;
|
|
|
|
var_6 = self.owner getstance();
|
|
|
|
if ( !isdefined( self.owner.prevstance ) && isdefined( self.owner ) )
|
|
self.owner.prevstance = var_6;
|
|
|
|
var_7 = !isdefined( self.ownerprevpos ) || distance2dsquared( self.ownerprevpos, self.owner.origin ) > 100;
|
|
|
|
if ( var_7 )
|
|
self.ownerprevpos = self.owner.origin;
|
|
|
|
var_8 = distance2dsquared( var_5, self.owner.origin );
|
|
|
|
if ( var_1 || var_8 > self.ownerradiussq && var_7 || self.owner.prevstance != var_6 || self.prevmovestate != "idle" && self.prevmovestate != self.movestate )
|
|
{
|
|
self scragentsetgoalpos( findpointnearowner() );
|
|
self.owner.prevstance = var_6;
|
|
return;
|
|
}
|
|
}
|
|
else if ( self.movestate == "pursuit" )
|
|
{
|
|
self.curmeleetarget = self.enemy;
|
|
self.movemode = "sprint";
|
|
self.barrivalsenabled = 0;
|
|
self scragentsetgoalpos( var_0 );
|
|
}
|
|
}
|
|
|
|
getmovestate( var_0 )
|
|
{
|
|
if ( isdefined( self.enemy ) )
|
|
{
|
|
if ( isdefined( self.favoriteenemy ) && self.enemy == self.favoriteenemy )
|
|
return "pursuit";
|
|
|
|
if ( abs( self.origin[2] - self.enemy.origin[2] ) < self.warningzheight && distance2dsquared( self.enemy.origin, self.origin ) < self.attackradiussq )
|
|
return "pursuit";
|
|
|
|
if ( isdefined( self.curmeleetarget ) && self.curmeleetarget == self.enemy )
|
|
{
|
|
if ( distance2dsquared( self.curmeleetarget.origin, self.origin ) < self.keeppursuingtargetradiussq )
|
|
return "pursuit";
|
|
}
|
|
}
|
|
|
|
return "follow";
|
|
}
|
|
|
|
setpastpursuitfailed( var_0 )
|
|
{
|
|
if ( var_0 )
|
|
{
|
|
if ( !isdefined( self.lastpursuitfailedpos ) )
|
|
{
|
|
self.lastpursuitfailedpos = self.enemy.origin;
|
|
self.lastpursuitfailedmypos = self.origin;
|
|
var_1 = maps\mp\agents\_scriptedagents::droppostoground( self.enemy.origin );
|
|
self.blastpursuitfailedposbad = !isdefined( var_1 );
|
|
self.lastpursuitfailedtime = gettime();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.lastpursuitfailedpos = undefined;
|
|
self.lastpursuitfailedmypos = undefined;
|
|
self.blastpursuitfailedposbad = undefined;
|
|
self.lastpursuitfailedtime = undefined;
|
|
}
|
|
}
|
|
|
|
waitforbadpath()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for (;;)
|
|
{
|
|
self waittill( "bad_path", var_0 );
|
|
self.bhasbadpath = 1;
|
|
self.lastbadpathtime = gettime();
|
|
self.lastbadpathgoal = var_0;
|
|
self.lastbadpathmovestate = self.movestate;
|
|
|
|
if ( self.movestate == "follow" && isdefined( self.owner ) )
|
|
{
|
|
self.lastbadpathultimategoal = self.owner.origin;
|
|
continue;
|
|
}
|
|
|
|
if ( self.movestate == "pursuit" && isdefined( self.enemy ) )
|
|
self.lastbadpathultimategoal = self.enemy.origin;
|
|
}
|
|
}
|
|
|
|
waitforpathset()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for (;;)
|
|
{
|
|
self waittill( "path_set" );
|
|
self.bhasbadpath = 0;
|
|
}
|
|
}
|
|
|
|
getfollowmovemode( var_0 )
|
|
{
|
|
var_1 = 40000;
|
|
var_2 = 65536;
|
|
var_3 = self getpathgoalpos();
|
|
|
|
if ( isdefined( var_3 ) )
|
|
{
|
|
var_4 = distancesquared( var_3, self.origin );
|
|
|
|
if ( var_0 == "run" || var_0 == "sprint" )
|
|
{
|
|
if ( var_4 < var_1 )
|
|
return "fastwalk";
|
|
else if ( var_0 == "sprint" )
|
|
return "run";
|
|
}
|
|
else if ( var_0 == "fastwalk" )
|
|
{
|
|
if ( var_4 > var_2 )
|
|
return "run";
|
|
}
|
|
}
|
|
|
|
return var_0;
|
|
}
|
|
|
|
iswithinattackheight( var_0 )
|
|
{
|
|
var_1 = var_0[2] - self.origin[2];
|
|
return var_1 <= self.attackzheight && var_1 >= self.attackzheightdown;
|
|
}
|
|
|
|
wanttoattacktargetbutcant( var_0 )
|
|
{
|
|
if ( !isdefined( self.curmeleetarget ) )
|
|
return 0;
|
|
|
|
return !iswithinattackheight( self.curmeleetarget.origin ) && distance2dsquared( self.origin, self.curmeleetarget.origin ) < self.meleeradiussq * 0.75 * 0.75 && ( !var_0 || self agentcanseesentient( self.curmeleetarget ) );
|
|
}
|
|
|
|
readytomeleetarget()
|
|
{
|
|
if ( !isdefined( self.curmeleetarget ) )
|
|
return 0;
|
|
|
|
if ( !maps\mp\_utility::isreallyalive( self.curmeleetarget ) )
|
|
return 0;
|
|
|
|
if ( self.aistate == "traverse" )
|
|
return 0;
|
|
|
|
if ( distance2dsquared( self.origin, self.curmeleetarget.origin ) > self.meleeradiussq )
|
|
return 0;
|
|
|
|
if ( !iswithinattackheight( self.curmeleetarget.origin ) )
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
wantstogrowlattarget()
|
|
{
|
|
if ( !isdefined( self.enemy ) )
|
|
return 0;
|
|
|
|
if ( abs( self.origin[2] - self.enemy.origin[2] ) <= self.warningzheight || self agentcanseesentient( self.enemy ) )
|
|
{
|
|
var_0 = distance2dsquared( self.origin, self.enemy.origin );
|
|
|
|
if ( var_0 < self.warningradiussq )
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
getattackpoint( var_0 )
|
|
{
|
|
var_1 = var_0.origin - self.origin;
|
|
var_1 = vectornormalize( var_1 );
|
|
var_2 = self getpathgoalpos();
|
|
var_3 = self.attackoffset + 4;
|
|
|
|
if ( isdefined( var_2 ) && distance2dsquared( var_2, var_0.origin ) < var_3 * var_3 && maps\mp\agents\_scriptedagents::canmovepointtopoint( var_0.origin, var_2 ) )
|
|
return var_2;
|
|
|
|
var_4 = var_0.origin - var_1 * self.attackoffset;
|
|
var_4 = maps\mp\agents\_scriptedagents::droppostoground( var_4 );
|
|
|
|
if ( !isdefined( var_4 ) )
|
|
return var_0.origin;
|
|
|
|
if ( !maps\mp\agents\_scriptedagents::canmovepointtopoint( var_0.origin, var_4 ) )
|
|
{
|
|
var_5 = anglestoforward( var_0.angles );
|
|
var_4 = var_0.origin + var_5 * self.attackoffset;
|
|
|
|
if ( !maps\mp\agents\_scriptedagents::canmovepointtopoint( var_0.origin, var_4 ) )
|
|
return var_0.origin;
|
|
}
|
|
|
|
return var_4;
|
|
}
|
|
|
|
cross2d( var_0, var_1 )
|
|
{
|
|
return var_0[0] * var_1[1] - var_1[0] * var_0[1];
|
|
}
|
|
|
|
findpointnearowner()
|
|
{
|
|
var_0 = vectornormalize( self.origin - self.owner.origin );
|
|
var_1 = anglestoforward( self.owner.angles );
|
|
var_1 = ( var_1[0], var_1[1], 0 );
|
|
var_1 = vectornormalize( var_1 );
|
|
var_2 = cross2d( var_0, var_1 );
|
|
var_3 = getclosestnodeinsight( self.owner.origin );
|
|
|
|
if ( !isdefined( var_3 ) )
|
|
return self.origin;
|
|
|
|
var_4 = getlinkednodes( var_3 );
|
|
var_5 = 5;
|
|
var_6 = 10;
|
|
var_7 = 15;
|
|
var_8 = -15;
|
|
var_9 = gettime() - self.timeoflastdamage < 5000;
|
|
var_10 = 0;
|
|
var_11 = undefined;
|
|
var_4[var_4.size] = var_3;
|
|
|
|
foreach ( var_13 in var_4 )
|
|
{
|
|
var_14 = 0;
|
|
var_15 = var_13.origin - self.owner.origin;
|
|
var_16 = length( var_15 );
|
|
|
|
if ( var_16 >= self.preferredoffsetfromowner )
|
|
var_14 = var_14 + var_5;
|
|
else if ( var_16 < self.minoffsetfromowner )
|
|
{
|
|
var_17 = 1 - ( self.minoffsetfromowner - var_16 ) / self.minoffsetfromowner;
|
|
var_14 = var_14 + var_5 * var_17 * var_17;
|
|
}
|
|
else
|
|
var_14 = var_14 + var_5 * var_16 / self.preferredoffsetfromowner;
|
|
|
|
if ( var_16 == 0 )
|
|
var_16 = 1;
|
|
|
|
var_15 = var_15 / var_16;
|
|
var_18 = vectordot( var_1, var_15 );
|
|
var_19 = self.owner getstance();
|
|
|
|
switch ( var_19 )
|
|
{
|
|
case "stand":
|
|
if ( var_18 < cos( 35 ) && var_18 > cos( 45 ) )
|
|
var_14 = var_14 + var_6;
|
|
|
|
break;
|
|
case "crouch":
|
|
if ( var_18 < cos( 75 ) && var_18 > cos( 90 ) )
|
|
var_14 = var_14 + var_6;
|
|
|
|
break;
|
|
case "prone":
|
|
if ( var_18 < cos( 125 ) && var_18 > cos( 135 ) )
|
|
var_14 = var_14 + var_6;
|
|
|
|
break;
|
|
}
|
|
|
|
var_20 = cross2d( var_15, var_1 );
|
|
|
|
if ( var_20 * var_2 > 0 )
|
|
var_14 = var_14 + var_7;
|
|
|
|
if ( var_9 )
|
|
{
|
|
var_21 = vectordot( self.damagedownertome, var_15 );
|
|
var_14 = var_14 + var_21 * var_8;
|
|
}
|
|
|
|
if ( var_14 > var_10 )
|
|
{
|
|
var_10 = var_14;
|
|
var_11 = var_13;
|
|
}
|
|
}
|
|
|
|
if ( !isdefined( var_11 ) )
|
|
return self.origin;
|
|
|
|
var_23 = var_11.origin - self.owner.origin;
|
|
var_24 = length( var_23 );
|
|
|
|
if ( var_24 > self.preferredoffsetfromowner )
|
|
{
|
|
var_25 = var_3.origin - self.owner.origin;
|
|
|
|
if ( vectordot( var_25, var_23 / var_24 ) < 0 )
|
|
var_26 = var_11.origin;
|
|
else
|
|
{
|
|
var_27 = vectornormalize( var_11.origin - var_3.origin );
|
|
var_26 = var_3.origin + var_27 * self.preferredoffsetfromowner;
|
|
}
|
|
}
|
|
else
|
|
var_26 = var_11.origin;
|
|
|
|
var_26 = maps\mp\agents\_scriptedagents::droppostoground( var_26 );
|
|
|
|
if ( !isdefined( var_26 ) )
|
|
return self.origin;
|
|
|
|
if ( self.bhasbadpath && distance2dsquared( var_26, self.lastbadpathgoal ) < 4 )
|
|
return self.origin;
|
|
|
|
return var_26;
|
|
}
|
|
|
|
destroyonownerdisconnect( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
var_0 common_scripts\utility::waittill_any( "disconnect", "joined_team" );
|
|
self notify( "owner_disconnect" );
|
|
|
|
if ( maps\mp\gametypes\_hostmigration::waittillhostmigrationdone() )
|
|
wait 0.05;
|
|
|
|
self notify( "killanimscript" );
|
|
|
|
if ( isdefined( self.animcbs.onexit[self.aistate] ) )
|
|
self [[ self.animcbs.onexit[self.aistate] ]]();
|
|
|
|
self suicide();
|
|
}
|
|
|
|
watchattackstate()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for (;;)
|
|
{
|
|
if ( self.aistate == "melee" )
|
|
{
|
|
if ( self.attackstate != "melee" )
|
|
{
|
|
self.attackstate = "melee";
|
|
setsoundstate( undefined );
|
|
}
|
|
}
|
|
else if ( self.movestate == "pursuit" )
|
|
{
|
|
if ( self.attackstate != "attacking" )
|
|
{
|
|
self.attackstate = "attacking";
|
|
setsoundstate( "bark", "attacking" );
|
|
}
|
|
}
|
|
else if ( self.attackstate != "warning" )
|
|
{
|
|
if ( wantstogrowlattarget() )
|
|
{
|
|
self.attackstate = "warning";
|
|
setsoundstate( "growl", "warning" );
|
|
}
|
|
else
|
|
{
|
|
self.attackstate = self.aistate;
|
|
setsoundstate( "pant" );
|
|
}
|
|
}
|
|
else if ( !wantstogrowlattarget() )
|
|
{
|
|
self.attackstate = self.aistate;
|
|
setsoundstate( "pant" );
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
setsoundstate( var_0, var_1 )
|
|
{
|
|
if ( !isdefined( var_0 ) )
|
|
{
|
|
self notify( "end_dog_sound" );
|
|
self.soundstate = undefined;
|
|
return;
|
|
}
|
|
|
|
if ( !isdefined( self.soundstate ) || self.soundstate != var_0 )
|
|
{
|
|
self notify( "end_dog_sound" );
|
|
self.soundstate = var_0;
|
|
|
|
if ( var_0 == "bark" )
|
|
thread playbark( var_1 );
|
|
else if ( var_0 == "growl" )
|
|
thread playgrowl( var_1 );
|
|
else if ( var_0 == "pant" )
|
|
thread playpanting();
|
|
else
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
playbark( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
self endon( "end_dog_sound" );
|
|
|
|
if ( !isdefined( self.barking_sound ) )
|
|
{
|
|
self playsoundonmovingent( common_scripts\utility::ter_op( self.biswolf, "anml_wolf_bark", "anml_dog_bark" ) );
|
|
self.barking_sound = 1;
|
|
thread watchbarking();
|
|
}
|
|
}
|
|
|
|
watchbarking()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
self endon( "end_dog_sound" );
|
|
wait( randomintrange( 5, 10 ) );
|
|
self.barking_sound = undefined;
|
|
}
|
|
|
|
playgrowl( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
self endon( "end_dog_sound" );
|
|
|
|
if ( isdefined( self.lastgrowlplayedtime ) && gettime() - self.lastgrowlplayedtime < 3000 )
|
|
wait 3;
|
|
|
|
for (;;)
|
|
{
|
|
self.lastgrowlplayedtime = gettime();
|
|
self playsoundonmovingent( common_scripts\utility::ter_op( self.biswolf, "anml_wolf_growl", "anml_dog_growl" ) );
|
|
wait( randomintrange( 3, 6 ) );
|
|
}
|
|
}
|
|
|
|
playpanting( var_0 )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
self endon( "end_dog_sound" );
|
|
|
|
if ( isdefined( self.lastpantplayedtime ) && gettime() - self.lastpantplayedtime < 3000 )
|
|
wait 3;
|
|
|
|
self.lastpantplayedtime = gettime();
|
|
|
|
for (;;)
|
|
{
|
|
if ( self.aistate == "idle" )
|
|
{
|
|
wait 3;
|
|
continue;
|
|
}
|
|
|
|
self.lastpantplayedtime = gettime();
|
|
|
|
if ( self.movemode == "run" || self.movemode == "sprint" )
|
|
self playsoundonmovingent( common_scripts\utility::ter_op( self.biswolf, "anml_wolf_pants_mp_fast", "anml_dog_pants_mp_fast" ) );
|
|
else
|
|
self playsoundonmovingent( common_scripts\utility::ter_op( self.biswolf, "anml_wolf_pants_mp_med", "anml_dog_pants_mp_med" ) );
|
|
|
|
wait( randomintrange( 6, 8 ) );
|
|
}
|
|
}
|
|
|
|
watchownerdamage()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for (;;)
|
|
{
|
|
if ( !isdefined( self.owner ) )
|
|
return;
|
|
|
|
self.owner waittill( "damage", var_0, var_1 );
|
|
|
|
if ( isplayer( var_1 ) && var_1 != self.owner )
|
|
{
|
|
if ( self.attackstate == "attacking" )
|
|
continue;
|
|
|
|
if ( distancesquared( self.owner.origin, self.origin ) > self.ownerdamagedradiussq )
|
|
continue;
|
|
|
|
if ( distancesquared( self.owner.origin, var_1.origin ) > self.ownerdamagedradiussq )
|
|
continue;
|
|
|
|
self.favoriteenemy = var_1;
|
|
self.forceattack = 1;
|
|
thread watchfavoriteenemydeath();
|
|
}
|
|
}
|
|
}
|
|
|
|
watchownerdeath()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for (;;)
|
|
{
|
|
if ( !isdefined( self.owner ) )
|
|
return;
|
|
|
|
self.owner waittill( "death" );
|
|
|
|
switch ( level.gametype )
|
|
{
|
|
case "sd":
|
|
maps\mp\agents\_agent_utility::killdog();
|
|
break;
|
|
case "sr":
|
|
var_0 = level common_scripts\utility::waittill_any_return( "sr_player_eliminated", "sr_player_respawned" );
|
|
|
|
if ( isdefined( var_0 ) && var_0 == "sr_player_eliminated" )
|
|
maps\mp\agents\_agent_utility::killdog();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
watchownerteamchange()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for (;;)
|
|
{
|
|
if ( !isdefined( self.owner ) )
|
|
return;
|
|
|
|
var_0 = self.owner common_scripts\utility::waittill_any_return_no_endon_death( "joined_team", "joined_spectators" );
|
|
|
|
if ( isdefined( var_0 ) && ( var_0 == "joined_team" || var_0 == "joined_spectators" ) )
|
|
maps\mp\agents\_agent_utility::killdog();
|
|
}
|
|
}
|
|
|
|
watchfavoriteenemydeath()
|
|
{
|
|
self notify( "watchFavoriteEnemyDeath" );
|
|
self endon( "watchFavoriteEnemyDeath" );
|
|
self endon( "death" );
|
|
self.favoriteenemy common_scripts\utility::waittill_any_timeout( 5.0, "death", "disconnect" );
|
|
self.favoriteenemy = undefined;
|
|
self.forceattack = 0;
|
|
}
|
|
|
|
ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 )
|
|
{
|
|
self.timeoflastdamage = gettime();
|
|
|
|
if ( isdefined( self.owner ) )
|
|
self.damagedownertome = vectornormalize( self.origin - self.owner.origin );
|
|
|
|
if ( shouldplayhitreaction( var_2, var_5, var_4 ) )
|
|
{
|
|
switch ( self.aistate )
|
|
{
|
|
case "idle":
|
|
thread maps\mp\agents\dog\_dog_idle::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
|
|
break;
|
|
case "move":
|
|
thread maps\mp\agents\dog\_dog_move::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
shouldplayhitreaction( var_0, var_1, var_2 )
|
|
{
|
|
if ( isdefined( var_1 ) && weaponclass( var_1 ) == "sniper" )
|
|
return 1;
|
|
|
|
if ( isdefined( var_2 ) && isexplosivedamagemod( var_2 ) && var_0 >= 10 )
|
|
return 1;
|
|
|
|
if ( isdefined( var_2 ) && var_2 == "MOD_MELEE" )
|
|
return 1;
|
|
|
|
if ( isdefined( var_1 ) && var_1 == "concussion_grenade_mp" )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
monitorflash()
|
|
{
|
|
self endon( "death" );
|
|
|
|
for (;;)
|
|
{
|
|
self waittill( "flashbang", var_0, var_1, var_2, var_3, var_4, var_5 );
|
|
|
|
if ( isdefined( var_3 ) && var_3 == self.owner )
|
|
continue;
|
|
|
|
switch ( self.aistate )
|
|
{
|
|
case "idle":
|
|
maps\mp\agents\dog\_dog_idle::onflashbanged();
|
|
break;
|
|
case "move":
|
|
maps\mp\agents\dog\_dog_move::onflashbanged();
|
|
break;
|
|
}
|
|
}
|
|
}
|