mirror of
https://github.com/id-Software/quake-rerelease-qc.git
synced 2024-11-10 07:22:06 +00:00
1878 lines
55 KiB
C++
1878 lines
55 KiB
C++
|
/* Copyright (C) 1996-2022 id Software LLC
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
See file, 'COPYING', for details.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
==============================================================================
|
||
|
|
||
|
gremlin
|
||
|
|
||
|
==============================================================================
|
||
|
*/
|
||
|
$cd hipwork\models\grem
|
||
|
$origin 0 0 23
|
||
|
$scale 2
|
||
|
$base grembase.asc
|
||
|
|
||
|
$skin grem
|
||
|
|
||
|
$frame stand1.asc stand2.asc stand3.asc stand4.asc stand5.asc stand6.asc
|
||
|
$frame stand7.asc stand8.asc stand9.asc stand10.asc stand11.asc stand12.asc
|
||
|
$frame stand13.asc stand14.asc stand15.asc stand16.asc stand17.asc
|
||
|
|
||
|
$frame walk1.asc walk2.asc walk3.asc walk4.asc walk5.asc walk6.asc
|
||
|
$frame walk7.asc walk8.asc walk9.asc walk10.asc walk11.asc walk12.asc
|
||
|
|
||
|
$frame run1.asc run2.asc run3.asc run4.asc run5.asc run6.asc run7.asc run8.asc
|
||
|
$frame run9.asc run10.asc run11.asc run12.asc run13.asc run14.asc run15.asc
|
||
|
|
||
|
$frame jump1.asc jump2.asc jump3.asc jump4.asc jump5.asc jump6.asc jump7.asc
|
||
|
$frame jump8.asc jump9.asc jump10.asc jump11.asc jump12.asc jump13.asc jump14.asc
|
||
|
$frame jump15.asc jump16.asc
|
||
|
|
||
|
$frame attk1.asc attk2.asc attk3.asc attk4.asc attk5.asc attk6.asc
|
||
|
$frame attk7.asc attk8.asc attk9.asc attk10.asc attk11.asc
|
||
|
|
||
|
$frame maul1.asc maul2.asc maul3.asc maul4.asc maul5.asc maul6.asc
|
||
|
$frame maul7.asc maul8.asc maul9.asc maul10.asc maul11.asc maul12.asc maul13.asc
|
||
|
|
||
|
$frame spawn1.asc spawn2.asc spawn3.asc spawn4.asc spawn5.asc spawn6.asc
|
||
|
|
||
|
$frame look1.asc look2.asc look3.asc look4.asc look5.asc look6.asc look7.asc
|
||
|
$frame look8.asc look9.asc look10.asc
|
||
|
|
||
|
$frame pain1.asc pain2.asc pain3.asc pain4.asc
|
||
|
|
||
|
$frame death1.asc death2.asc death3.asc death4.asc death5.asc death6.asc death7.asc
|
||
|
$frame death8.asc death9.asc death10.asc death11.asc death12.asc
|
||
|
|
||
|
$frame flip1.asc flip2.asc flip3.asc flip4.asc flip5.asc flip6.asc flip7.asc
|
||
|
$frame flip8.asc
|
||
|
|
||
|
$frame lunge1.asc lunge2.asc lunge3.asc lunge4.asc lunge5.asc lunge6.asc lunge7.asc
|
||
|
$frame lunge8.asc lunge9.asc lunge10.asc lunge11.asc
|
||
|
|
||
|
$frame gfire1.asc gfire2.asc gfire3.asc gfire4.asc gfire5.asc gfire6.asc
|
||
|
|
||
|
$frame glook1.asc glook2.asc glook3.asc glook4.asc glook5.asc glook6.asc glook7.asc
|
||
|
$frame glook8.asc glook9.asc glook10.asc glook11.asc glook12.asc glook13.asc
|
||
|
$frame glook14.asc glook15.asc glook16.asc glook17.asc glook18.asc glook19.asc glook20.asc
|
||
|
|
||
|
$frame gpain1.asc gpain2.asc gpain3.asc
|
||
|
|
||
|
$frame grun1.asc grun2.asc grun3.asc grun4.asc grun5.asc grun6.asc grun7.asc
|
||
|
$frame grun8.asc grun9.asc grun10.asc grun11.asc grun12.asc grun13.asc grun14.asc grun15.asc
|
||
|
|
||
|
//============================================================================
|
||
|
|
||
|
float NumGremlins;
|
||
|
float NumSpawnGremlins;
|
||
|
|
||
|
/*
|
||
|
===========
|
||
|
GremlinAttemptWeaponSteal
|
||
|
|
||
|
see if we can steal enemy's weapon
|
||
|
|
||
|
============
|
||
|
*/
|
||
|
entity()GremlinFindVictim;
|
||
|
float() GremlinFindTarget;
|
||
|
|
||
|
float() GremlinAttemptWeaponSteal =
|
||
|
{
|
||
|
local vector delta;
|
||
|
local entity tempself;
|
||
|
local float best;
|
||
|
local entity victim;
|
||
|
local float amount;
|
||
|
|
||
|
if (self.stoleweapon)
|
||
|
{
|
||
|
dprint("gremlin trying to steal a weapon again\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!(self.enemy.flags & FL_CLIENT))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
delta = (self.enemy.origin - self.origin);
|
||
|
|
||
|
if (vlen(delta) > 100)
|
||
|
return FALSE;
|
||
|
if (random() < 0.5)
|
||
|
return FALSE;
|
||
|
//
|
||
|
// we are within range so lets go for it
|
||
|
//
|
||
|
victim = self.enemy;
|
||
|
best = victim.weapon;
|
||
|
if (best == IT_AXE || best == IT_SHOTGUN || best == IT_MJOLNIR)
|
||
|
return FALSE;
|
||
|
// take that weapon from the entity
|
||
|
victim.items = victim.items - (victim.items & best);
|
||
|
// give it to our gremlin
|
||
|
self.items = self.items | best;
|
||
|
self.weapon = best;
|
||
|
// take some ammo while we are at it
|
||
|
self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS ) );
|
||
|
if (best == IT_SUPER_SHOTGUN)
|
||
|
{
|
||
|
amount = victim.ammo_shells;
|
||
|
if (amount > 20)
|
||
|
amount = 20;
|
||
|
victim.ammo_shells = victim.ammo_shells - amount;
|
||
|
self.ammo_shells = self.ammo_shells + amount;
|
||
|
self.items = self.items | IT_SHELLS;
|
||
|
self.currentammo = self.ammo_shells;
|
||
|
sprint (victim, "$qc_gremlin_ssg");
|
||
|
}
|
||
|
else if (best == IT_NAILGUN)
|
||
|
{
|
||
|
amount = victim.ammo_nails;
|
||
|
if (amount > 40)
|
||
|
amount = 40;
|
||
|
victim.ammo_nails = victim.ammo_nails - amount;
|
||
|
self.ammo_nails = self.ammo_nails + amount;
|
||
|
self.items = self.items | IT_NAILS;
|
||
|
self.currentammo = self.ammo_nails;
|
||
|
sprint (victim, "$qc_gremlin_ng");
|
||
|
}
|
||
|
else if (best == IT_SUPER_NAILGUN)
|
||
|
{
|
||
|
amount = victim.ammo_nails;
|
||
|
if (amount > 40)
|
||
|
amount = 40;
|
||
|
victim.ammo_nails = victim.ammo_nails - amount;
|
||
|
self.ammo_nails = self.ammo_nails + amount;
|
||
|
self.items = self.items | IT_NAILS;
|
||
|
self.currentammo = self.ammo_nails;
|
||
|
sprint (victim, "$qc_gremlin_sng");
|
||
|
}
|
||
|
else if (best == IT_GRENADE_LAUNCHER)
|
||
|
{
|
||
|
amount = victim.ammo_rockets;
|
||
|
if (amount > 5)
|
||
|
amount = 5;
|
||
|
victim.ammo_rockets = victim.ammo_rockets - amount;
|
||
|
self.ammo_rockets = self.ammo_rockets + amount;
|
||
|
self.items = self.items | IT_ROCKETS;
|
||
|
self.currentammo = self.ammo_rockets;
|
||
|
sprint (victim, "$qc_gremlin_gl");
|
||
|
}
|
||
|
else if (best == IT_ROCKET_LAUNCHER)
|
||
|
{
|
||
|
amount = victim.ammo_rockets;
|
||
|
if (amount > 5)
|
||
|
amount = 5;
|
||
|
victim.ammo_rockets = victim.ammo_rockets - amount;
|
||
|
self.ammo_rockets = self.ammo_rockets + amount;
|
||
|
self.items = self.items | IT_ROCKETS;
|
||
|
self.currentammo = self.ammo_rockets;
|
||
|
sprint (victim, "$qc_gremlin_rl");
|
||
|
}
|
||
|
else if (best == IT_LIGHTNING)
|
||
|
{
|
||
|
amount = victim.ammo_cells;
|
||
|
if (amount > 40)
|
||
|
amount = 40;
|
||
|
victim.ammo_cells = victim.ammo_cells - amount;
|
||
|
self.ammo_cells = self.ammo_cells + amount;
|
||
|
self.items = self.items | IT_CELLS;
|
||
|
self.currentammo = self.ammo_cells;
|
||
|
sprint (victim, "$qc_gremlin_lg");
|
||
|
}
|
||
|
else if (best == IT_LASER_CANNON)
|
||
|
{
|
||
|
amount = victim.ammo_cells;
|
||
|
if (amount > 40)
|
||
|
amount = 40;
|
||
|
victim.ammo_cells = victim.ammo_cells - amount;
|
||
|
self.ammo_cells = self.ammo_cells + amount;
|
||
|
self.items = self.items | IT_CELLS;
|
||
|
self.currentammo = self.ammo_cells;
|
||
|
sprint (victim, "$qc_gremlin_lc");
|
||
|
}
|
||
|
else if (best == IT_PROXIMITY_GUN)
|
||
|
{
|
||
|
amount = victim.ammo_rockets;
|
||
|
if (amount > 5)
|
||
|
amount = 5;
|
||
|
victim.ammo_rockets = victim.ammo_rockets - amount;
|
||
|
self.ammo_rockets = self.ammo_rockets + amount;
|
||
|
self.items = self.items | IT_ROCKETS;
|
||
|
self.currentammo = self.ammo_rockets;
|
||
|
sprint (victim, "$qc_gremlin_prox");
|
||
|
}
|
||
|
tempself = self;
|
||
|
self = victim;
|
||
|
self.weapon = W_BestWeapon ();
|
||
|
W_SetCurrentAmmo ();
|
||
|
self = tempself;
|
||
|
|
||
|
// tag the gremlin as having stolen a weapon
|
||
|
self.stoleweapon = TRUE;
|
||
|
self.attack_finished = time;
|
||
|
// don't fire the first shot at the person we stole the weapon from
|
||
|
// all the time
|
||
|
if (random()>0.65)
|
||
|
self.lastvictim = victim;
|
||
|
else
|
||
|
self.lastvictim = self;
|
||
|
// self.attack_state = AS_STRAIGHT;
|
||
|
// find a recipient
|
||
|
victim = GremlinFindVictim();
|
||
|
if (victim != world)
|
||
|
{
|
||
|
self.enemy = victim;
|
||
|
FoundTarget();
|
||
|
self.attack_finished = time;
|
||
|
self.search_time = time + 1.0;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
};
|
||
|
//============================================================================
|
||
|
|
||
|
/*
|
||
|
===========
|
||
|
GremlinFindTarget
|
||
|
|
||
|
gremlin is currently not attacking anything, so try to find a target
|
||
|
|
||
|
============
|
||
|
*/
|
||
|
float() GremlinFindTarget =
|
||
|
{
|
||
|
local entity head;
|
||
|
local entity gorge;
|
||
|
local float dist;
|
||
|
local float result;
|
||
|
|
||
|
if ((self.stoleweapon==0) && time > self.wait)
|
||
|
{
|
||
|
self.wait = time + 1.0;
|
||
|
dist = 2000;
|
||
|
gorge = world;
|
||
|
head = nextent(world);
|
||
|
while (head!=world)
|
||
|
{
|
||
|
if ((head.health < 1) && (head.flags & (FL_MONSTER|FL_CLIENT)))
|
||
|
{
|
||
|
result = fabs(head.origin_z - self.origin_z);
|
||
|
if ((visible(head)) && (result<80) && (head.gorging == FALSE) && (visible_distance<dist))
|
||
|
{
|
||
|
dist = visible_distance;
|
||
|
gorge = head;
|
||
|
}
|
||
|
}
|
||
|
head = nextent(head);
|
||
|
}
|
||
|
if ((gorge != world) && (dist < (700*random())))
|
||
|
{
|
||
|
// dprint("starting to gorge on ");
|
||
|
// dprint(gorge.classname);
|
||
|
// dprint("\n");
|
||
|
self.oldenemy = self.enemy;
|
||
|
self.gorging = TRUE;
|
||
|
self.enemy = gorge;
|
||
|
self.search_time = time + 4.0;
|
||
|
FoundTarget();
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
else if (self.stoleweapon)
|
||
|
{
|
||
|
head = GremlinFindVictim();
|
||
|
if (head != world)
|
||
|
{
|
||
|
self.enemy = head;
|
||
|
FoundTarget();
|
||
|
self.attack_finished = time;
|
||
|
self.search_time = time + 2.0;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
result = FindTarget();
|
||
|
self.search_time = time + 2.0;
|
||
|
return result;
|
||
|
};
|
||
|
//============================================================================
|
||
|
/*
|
||
|
=============
|
||
|
gremlin_walk
|
||
|
|
||
|
The monster is walking it's beat
|
||
|
=============
|
||
|
*/
|
||
|
void(float dist) gremlin_walk =
|
||
|
{
|
||
|
movedist = dist;
|
||
|
|
||
|
// check for noticing a player
|
||
|
if (GremlinFindTarget ())
|
||
|
return;
|
||
|
|
||
|
movetogoal (dist);
|
||
|
};
|
||
|
|
||
|
//============================================================================
|
||
|
|
||
|
/*
|
||
|
=============
|
||
|
gremlin_stand
|
||
|
|
||
|
The monster is staying in one place for a while, with slight angle turns
|
||
|
=============
|
||
|
*/
|
||
|
void() gremlin_stand =
|
||
|
{
|
||
|
if (FindTarget ())
|
||
|
return;
|
||
|
|
||
|
if (time > self.pausetime)
|
||
|
{
|
||
|
self.th_walk ();
|
||
|
return;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//============================================================================
|
||
|
float() GremlinCheckNoAmmo;
|
||
|
void() gremlin_glook1;
|
||
|
/*
|
||
|
=============
|
||
|
gremlin_run
|
||
|
|
||
|
The monster has an enemy it is trying to kill
|
||
|
=============
|
||
|
*/
|
||
|
void(float dist) gremlin_run =
|
||
|
{
|
||
|
local entity oldtarget;
|
||
|
local float r;
|
||
|
local vector d;
|
||
|
|
||
|
if (self.watertype == CONTENT_LAVA)
|
||
|
{ // do damage
|
||
|
T_Damage (self, world, world, 2000);
|
||
|
}
|
||
|
movedist = dist;
|
||
|
if (self.stoleweapon)
|
||
|
self.frame = self.frame + $grun1.asc - $run1.asc;
|
||
|
|
||
|
if (self.gorging)
|
||
|
{
|
||
|
traceline(self.origin, self.enemy.origin, TRUE, self);
|
||
|
if (trace_fraction != 1.0)
|
||
|
{
|
||
|
self.gorging = FALSE;
|
||
|
return;
|
||
|
}
|
||
|
if (!visible(self.enemy))
|
||
|
{
|
||
|
self.gorging = FALSE;
|
||
|
return;
|
||
|
}
|
||
|
r = vlen(self.enemy.origin - self.origin);
|
||
|
if (r < 130)
|
||
|
{
|
||
|
ai_face();
|
||
|
if (r < 45)
|
||
|
{
|
||
|
self.th_melee ();
|
||
|
self.attack_state = AS_STRAIGHT;
|
||
|
return;
|
||
|
}
|
||
|
else if (walkmove (self.angles_y, dist) == FALSE)
|
||
|
{
|
||
|
self.gorging = FALSE;
|
||
|
return;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
movetogoal (dist); // done in C code...
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (random()>0.97)
|
||
|
{
|
||
|
if (GremlinFindTarget())
|
||
|
return;
|
||
|
}
|
||
|
// get away from player if we stole a weapon
|
||
|
if (self.stoleweapon)
|
||
|
{
|
||
|
if (self.enemy.health < 0 && self.enemy.classname == "player")
|
||
|
{
|
||
|
gremlin_glook1();
|
||
|
return;
|
||
|
}
|
||
|
if (!GremlinCheckNoAmmo())
|
||
|
{
|
||
|
if (self.t_length==1)
|
||
|
{
|
||
|
remove(self.trigger_field);
|
||
|
self.goalentity = self.enemy;
|
||
|
self.t_length = 0;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
r = vlen(self.enemy.origin - self.origin);
|
||
|
d = normalize(self.origin-self.enemy.origin);
|
||
|
if (self.t_length == 0)
|
||
|
{
|
||
|
if (r<150)
|
||
|
{
|
||
|
self.trigger_field = spawn();
|
||
|
setsize(self.trigger_field,'-1 -1 -1','1 1 1');
|
||
|
self.t_length = 1;
|
||
|
}
|
||
|
}
|
||
|
if (self.t_length==1)
|
||
|
{
|
||
|
if (r > 250)
|
||
|
{
|
||
|
remove(self.trigger_field);
|
||
|
self.goalentity = self.enemy;
|
||
|
self.t_length = 0;
|
||
|
// self.attack_state = AS_SLIDING;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (r < 160)
|
||
|
{
|
||
|
local vector ang;
|
||
|
local float done;
|
||
|
local vector end;
|
||
|
local float c;
|
||
|
|
||
|
ang = vectoangles(d);
|
||
|
done = 0;
|
||
|
c = 0;
|
||
|
while (done == 0)
|
||
|
{
|
||
|
makevectors(ang);
|
||
|
end = self.enemy.origin + v_forward * 350;
|
||
|
traceline(self.enemy.origin,end,FALSE,self);
|
||
|
if (trace_fraction == 1.0)
|
||
|
{
|
||
|
traceline(self.origin,end,FALSE,self);
|
||
|
if (trace_fraction == 1.0)
|
||
|
done = 1;
|
||
|
}
|
||
|
ang_y = anglemod(ang_y + 36);
|
||
|
c = c + 1;
|
||
|
if (c == 10)
|
||
|
{
|
||
|
done = 1;
|
||
|
}
|
||
|
}
|
||
|
setorigin(self.trigger_field,end);
|
||
|
}
|
||
|
self.goalentity = self.trigger_field;
|
||
|
self.ideal_yaw = vectoyaw(normalize(self.goalentity.origin-self.origin));
|
||
|
ChangeYaw ();
|
||
|
movetogoal (dist); // done in C code...
|
||
|
self.nextthink = time + 0.1;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ai_run(dist);
|
||
|
self.nextthink = time + 0.1;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//============================================================================
|
||
|
|
||
|
void() Gremlin_JumpTouch;
|
||
|
void() Gremlin_FlipTouch;
|
||
|
void(float side) Gremlin_Melee;
|
||
|
void(float side) Gremlin_Gorge;
|
||
|
|
||
|
void() gremlin_stand1 =[ $stand1.asc, gremlin_stand2 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand2 =[ $stand2.asc, gremlin_stand3 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand3 =[ $stand3.asc, gremlin_stand4 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand4 =[ $stand4.asc, gremlin_stand5 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand5 =[ $stand5.asc, gremlin_stand6 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand6 =[ $stand6.asc, gremlin_stand7 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand7 =[ $stand7.asc, gremlin_stand8 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand8 =[ $stand8.asc, gremlin_stand9 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand9 =[ $stand9.asc, gremlin_stand10 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand10 =[ $stand10.asc, gremlin_stand11 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand11 =[ $stand11.asc, gremlin_stand12 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand12 =[ $stand12.asc, gremlin_stand13 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand13 =[ $stand13.asc, gremlin_stand14 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand14 =[ $stand14.asc, gremlin_stand15 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand15 =[ $stand15.asc, gremlin_stand16 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand16 =[ $stand16.asc, gremlin_stand17 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
void() gremlin_stand17 =[ $stand17.asc, gremlin_stand1 ] {gremlin_stand();self.nextthink = time + 0.2;};
|
||
|
|
||
|
void() gremlin_walk1 =[ $walk1.asc, gremlin_walk2 ] {
|
||
|
if (random() < 0.1)
|
||
|
sound (self, CHAN_VOICE, "grem/idle.wav", 1, ATTN_IDLE);
|
||
|
gremlin_walk(8);};
|
||
|
void() gremlin_walk2 =[ $walk2.asc, gremlin_walk3 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk3 =[ $walk3.asc, gremlin_walk4 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk4 =[ $walk4.asc, gremlin_walk5 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk5 =[ $walk5.asc, gremlin_walk6 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk6 =[ $walk6.asc, gremlin_walk7 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk7 =[ $walk7.asc, gremlin_walk8 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk8 =[ $walk8.asc, gremlin_walk9 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk9 =[ $walk9.asc, gremlin_walk10 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk10 =[ $walk10.asc, gremlin_walk11 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk11 =[ $walk11.asc, gremlin_walk12 ] {gremlin_walk(8);};
|
||
|
void() gremlin_walk12 =[ $walk12.asc, gremlin_walk1 ] {gremlin_walk(8);};
|
||
|
|
||
|
void() gremlin_run1 =[ $run1.asc, gremlin_run2 ] {
|
||
|
if (random() < 0.1)
|
||
|
sound (self, CHAN_VOICE, "grem/idle.wav", 1, ATTN_IDLE);
|
||
|
gremlin_run(0);};
|
||
|
void() gremlin_run2 =[ $run2.asc, gremlin_run3 ] {gremlin_run(8);};
|
||
|
void() gremlin_run3 =[ $run3.asc, gremlin_run4 ] {gremlin_run(12);};
|
||
|
void() gremlin_run4 =[ $run4.asc, gremlin_run5 ] {gremlin_run(16);};
|
||
|
void() gremlin_run5 =[ $run5.asc, gremlin_run6 ] {gremlin_run(16);};
|
||
|
void() gremlin_run6 =[ $run6.asc, gremlin_run7 ] {gremlin_run(12);};
|
||
|
void() gremlin_run7 =[ $run7.asc, gremlin_run8 ] {gremlin_run(8);};
|
||
|
void() gremlin_run8 =[ $run8.asc, gremlin_run9 ] {gremlin_run(0);};
|
||
|
void() gremlin_run9 =[ $run9.asc, gremlin_run10 ] {gremlin_run(8);};
|
||
|
void() gremlin_run10 =[ $run10.asc, gremlin_run11 ] {gremlin_run(12);};
|
||
|
void() gremlin_run11 =[ $run11.asc, gremlin_run12 ] {gremlin_run(16);};
|
||
|
void() gremlin_run12 =[ $run12.asc, gremlin_run1 ] {gremlin_run(16);};
|
||
|
void() gremlin_run13 =[ $run13.asc, gremlin_run14 ] {gremlin_run(12);};
|
||
|
void() gremlin_run14 =[ $run14.asc, gremlin_run15 ] {gremlin_run(8);};
|
||
|
void() gremlin_run15 =[ $run15.asc, gremlin_run1 ] {gremlin_run(0);};
|
||
|
|
||
|
void() gremlin_jump1 =[ $jump1.asc, gremlin_jump2 ] {ai_face();};
|
||
|
void() gremlin_jump2 =[ $jump2.asc, gremlin_jump3 ] {ai_face();};
|
||
|
void() gremlin_jump3 =[ $jump3.asc, gremlin_jump4 ] {ai_face();};
|
||
|
void() gremlin_jump4 =[ $jump4.asc, gremlin_jump5 ] {ai_face();};
|
||
|
void() gremlin_jump5 =[ $jump5.asc, gremlin_jump6 ]
|
||
|
{
|
||
|
ai_face();
|
||
|
|
||
|
if (self.flags & FL_ONGROUND)
|
||
|
{
|
||
|
self.touch = Gremlin_JumpTouch;
|
||
|
makevectors (self.angles);
|
||
|
self.origin_z = self.origin_z + 1;
|
||
|
self.velocity = v_forward * 300 + '0 0 300';
|
||
|
self.flags = self.flags - FL_ONGROUND;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gremlin_run1();
|
||
|
}
|
||
|
};
|
||
|
void() gremlin_jump6 =[ $jump6.asc, gremlin_jump7 ] {};
|
||
|
void() gremlin_jump7 =[ $jump7.asc, gremlin_jump8 ] {};
|
||
|
void() gremlin_jump8 =[ $jump8.asc, gremlin_jump9 ] {};
|
||
|
void() gremlin_jump9 =[ $jump9.asc, gremlin_jump10 ] {};
|
||
|
void() gremlin_jump10 =[ $jump10.asc, gremlin_jump11 ] {};
|
||
|
void() gremlin_jump11 =[ $jump11.asc, gremlin_jump1 ]
|
||
|
{
|
||
|
self.nextthink = time + 3;
|
||
|
// if three seconds pass, assume gremlin is stuck and jump again
|
||
|
};
|
||
|
|
||
|
void() gremlin_jump12 =[ $jump12.asc, gremlin_jump13 ] {};
|
||
|
void() gremlin_jump13 =[ $jump13.asc, gremlin_jump14 ] {};
|
||
|
void() gremlin_jump14 =[ $jump14.asc, gremlin_jump15 ] {};
|
||
|
void() gremlin_jump15 =[ $jump15.asc, gremlin_jump16 ] {};
|
||
|
void() gremlin_jump16 =[ $jump16.asc, gremlin_run1 ] {};
|
||
|
|
||
|
void() gremlin_shot1 = [$gfire1.asc, gremlin_shot2 ] {self.effects = self.effects | EF_MUZZLEFLASH;};
|
||
|
void() gremlin_shot2 = [$gfire2.asc, gremlin_shot3 ] {};
|
||
|
void() gremlin_shot3 = [$gfire3.asc, gremlin_shot4 ] {};
|
||
|
void() gremlin_shot4 = [$gfire4.asc, gremlin_shot5 ] {};
|
||
|
void() gremlin_shot5 = [$gfire5.asc, gremlin_shot6 ] {};
|
||
|
void() gremlin_shot6 = [$gfire6.asc, gremlin_run1 ] {};
|
||
|
|
||
|
|
||
|
//============================================================================
|
||
|
void(float ox) Gremlin_FireNailGun;
|
||
|
|
||
|
void() gremlin_nail1 =[$gfire1.asc, gremlin_nail2 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireNailGun(4);
|
||
|
};
|
||
|
void() gremlin_nail2 =[$gfire1.asc, gremlin_nail3 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireNailGun(4);
|
||
|
};
|
||
|
void() gremlin_nail3 =[$gfire1.asc, gremlin_nail4 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireNailGun(4);
|
||
|
};
|
||
|
void() gremlin_nail4 =[$gfire1.asc, gremlin_nail5 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireNailGun(4);
|
||
|
};
|
||
|
void() gremlin_nail5 =[$gfire1.asc, gremlin_nail6 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireNailGun(4);
|
||
|
};
|
||
|
void() gremlin_nail6 =[$gfire1.asc, gremlin_nail7 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireNailGun(4);
|
||
|
};
|
||
|
void() gremlin_nail7 = [$gfire1.asc, gremlin_run1 ] {};
|
||
|
|
||
|
|
||
|
void(float ox) Gremlin_FireLaserGun;
|
||
|
|
||
|
void() gremlin_laser1 =[$gfire1.asc, gremlin_laser2 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireLaserGun(4);
|
||
|
};
|
||
|
void() gremlin_laser2 =[$gfire1.asc, gremlin_laser3 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireLaserGun(4);
|
||
|
};
|
||
|
void() gremlin_laser3 =[$gfire1.asc, gremlin_laser4 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireLaserGun(4);
|
||
|
};
|
||
|
void() gremlin_laser4 =[$gfire1.asc, gremlin_laser5 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireLaserGun(4);
|
||
|
};
|
||
|
void() gremlin_laser5 =[$gfire1.asc, gremlin_laser6 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireLaserGun(4);
|
||
|
};
|
||
|
void() gremlin_laser6 =[$gfire1.asc, gremlin_laser7 ]
|
||
|
{
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
Gremlin_FireLaserGun(4);
|
||
|
};
|
||
|
void() gremlin_laser7 = [$gfire1.asc, gremlin_run1 ] {};
|
||
|
|
||
|
//============================================================================
|
||
|
|
||
|
void() Gremlin_FireLightningGun;
|
||
|
void() gremlin_light1 =[$gfire1.asc, gremlin_light2 ]
|
||
|
{
|
||
|
Gremlin_FireLightningGun();
|
||
|
};
|
||
|
void() gremlin_light2 = [$gfire1.asc, gremlin_light3 ]
|
||
|
{
|
||
|
Gremlin_FireLightningGun();
|
||
|
};
|
||
|
void() gremlin_light3 =[$gfire1.asc, gremlin_light4 ]
|
||
|
{
|
||
|
Gremlin_FireLightningGun();
|
||
|
};
|
||
|
void() gremlin_light4 = [$gfire1.asc, gremlin_light5 ]
|
||
|
{
|
||
|
Gremlin_FireLightningGun();
|
||
|
};
|
||
|
void() gremlin_light5 = [$gfire1.asc, gremlin_run1 ] {};
|
||
|
|
||
|
//============================================================================
|
||
|
|
||
|
void() gremlin_rocket1 = [$gfire1.asc, gremlin_rocket2 ] {self.effects = self.effects | EF_MUZZLEFLASH;};
|
||
|
void() gremlin_rocket2 = [$gfire2.asc, gremlin_rocket3 ] {};
|
||
|
void() gremlin_rocket3 = [$gfire3.asc, gremlin_rocket4 ] {};
|
||
|
void() gremlin_rocket4 = [$gfire4.asc, gremlin_rocket5 ] {};
|
||
|
void() gremlin_rocket5 = [$gfire5.asc, gremlin_rocket6 ] {};
|
||
|
void() gremlin_rocket6 = [$gfire6.asc, gremlin_run1 ] {};
|
||
|
|
||
|
void() gremlin_lunge1 =[ $lunge1.asc, gremlin_lunge2 ] {ai_charge(0);};
|
||
|
void() gremlin_lunge2 =[ $lunge2.asc, gremlin_lunge3 ] {ai_charge(0);};
|
||
|
void() gremlin_lunge3 =[ $lunge3.asc, gremlin_lunge4 ] {ai_charge(0);};
|
||
|
void() gremlin_lunge4 =[ $lunge4.asc, gremlin_lunge5 ] {ai_charge(0);};
|
||
|
void() gremlin_lunge5 =[ $lunge5.asc, gremlin_lunge6 ] {ai_charge(0);};
|
||
|
void() gremlin_lunge6 =[ $lunge6.asc, gremlin_lunge7 ] {ai_charge(0);};
|
||
|
void() gremlin_lunge7 =[ $lunge7.asc, gremlin_lunge8 ] {ai_charge(15);};
|
||
|
void() gremlin_lunge8 =[ $lunge8.asc, gremlin_lunge9 ] {ai_charge(0);Gremlin_Melee(0);};
|
||
|
void() gremlin_lunge9 =[ $lunge9.asc, gremlin_lunge10] {ai_charge(0);};
|
||
|
void() gremlin_lunge10 =[ $lunge10.asc, gremlin_lunge11] {ai_charge(0);};
|
||
|
void() gremlin_lunge11 =[ $lunge11.asc, gremlin_run1] {ai_charge(0);};
|
||
|
|
||
|
void() gremlin_claw1 =[ $attk1.asc, gremlin_claw2 ] {ai_charge(0);};
|
||
|
void() gremlin_claw2 =[ $attk2.asc, gremlin_claw3 ] {ai_charge(0);};
|
||
|
void() gremlin_claw3 =[ $attk3.asc, gremlin_claw4 ] {ai_charge(0);};
|
||
|
void() gremlin_claw4 =[ $attk4.asc, gremlin_claw5 ] {ai_charge(0);};
|
||
|
void() gremlin_claw5 =[ $attk5.asc, gremlin_claw6 ] {ai_charge(0);};
|
||
|
void() gremlin_claw6 =[ $attk6.asc, gremlin_claw7 ] {ai_charge(0);Gremlin_Melee(200);};
|
||
|
void() gremlin_claw7 =[ $attk7.asc, gremlin_claw8 ] {ai_charge(15);};
|
||
|
void() gremlin_claw8 =[ $attk8.asc, gremlin_claw9 ] {ai_charge(0);};
|
||
|
void() gremlin_claw9 =[ $attk9.asc, gremlin_claw10] {ai_charge(0);};
|
||
|
void() gremlin_claw10 =[ $attk10.asc, gremlin_claw11] {ai_charge(0);};
|
||
|
void() gremlin_claw11 =[ $attk11.asc, gremlin_run1] {ai_charge(0);};
|
||
|
|
||
|
void() gremlin_gorge1 =[ $maul1.asc, gremlin_gorge2] {ai_charge(1);};
|
||
|
void() gremlin_gorge2 =[ $maul2.asc, gremlin_gorge3] {ai_charge(1);};
|
||
|
void() gremlin_gorge3 =[ $maul3.asc, gremlin_gorge4] {ai_charge(2);};
|
||
|
void() gremlin_gorge4 =[ $maul4.asc, gremlin_gorge5] {ai_charge(0);};
|
||
|
void() gremlin_gorge5 =[ $maul5.asc, gremlin_gorge6] {ai_charge(0);};
|
||
|
void() gremlin_gorge6 =[ $maul6.asc, gremlin_gorge7] {ai_charge(0);Gremlin_Gorge(200);};
|
||
|
void() gremlin_gorge7 =[ $maul7.asc, gremlin_gorge8] {ai_charge(0);};
|
||
|
void() gremlin_gorge8 =[ $maul8.asc, gremlin_gorge9] {ai_charge(0);Gremlin_Gorge(-200);};
|
||
|
void() gremlin_gorge9 =[ $maul9.asc, gremlin_gorge10] {ai_charge(0);};
|
||
|
void() gremlin_gorge10 =[ $maul10.asc, gremlin_gorge11] {ai_charge(0);};
|
||
|
void() gremlin_gorge11 =[ $maul11.asc, gremlin_gorge12] {ai_charge(0);};
|
||
|
void() gremlin_gorge12 =[ $maul12.asc, gremlin_gorge13] {ai_charge(0);};
|
||
|
void() gremlin_gorge13 =[ $maul13.asc, gremlin_gorge1] {ai_charge(0);};
|
||
|
|
||
|
void() gremlin_look1 =[ $look1.asc, gremlin_look2] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look2 =[ $look2.asc, gremlin_look3] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look3 =[ $look3.asc, gremlin_look4] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look4 =[ $look4.asc, gremlin_look5] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look5 =[ $look5.asc, gremlin_look6] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look6 =[ $look6.asc, gremlin_look7] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look7 =[ $look7.asc, gremlin_look8] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look8 =[ $look8.asc, gremlin_look9] {self.nextthink = time + 0.2;};
|
||
|
void() gremlin_look9 =[ $look9.asc, gremlin_run1]
|
||
|
{
|
||
|
if (self.oldenemy.health > 0)
|
||
|
{
|
||
|
self.enemy = self.oldenemy;
|
||
|
HuntTarget ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (self.movetarget)
|
||
|
self.th_walk ();
|
||
|
else
|
||
|
self.th_stand ();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
void() GremlinDropBackpack;
|
||
|
void() gremlin_glook1 =[ $glook1.asc, gremlin_glook2] {};
|
||
|
void() gremlin_glook2 =[ $glook2.asc, gremlin_glook3] {};
|
||
|
void() gremlin_glook3 =[ $glook3.asc, gremlin_glook4] {};
|
||
|
void() gremlin_glook4 =[ $glook4.asc, gremlin_glook5] {};
|
||
|
void() gremlin_glook5 =[ $glook5.asc, gremlin_glook6] {};
|
||
|
void() gremlin_glook6 =[ $glook6.asc, gremlin_glook7] {};
|
||
|
void() gremlin_glook7 =[ $glook7.asc, gremlin_glook8] {};
|
||
|
void() gremlin_glook8 =[ $glook8.asc, gremlin_glook9] {};
|
||
|
void() gremlin_glook9 =[ $glook9.asc, gremlin_glook10] {};
|
||
|
void() gremlin_glook10 =[ $glook10.asc, gremlin_glook11] {};
|
||
|
void() gremlin_glook11 =[ $glook11.asc, gremlin_glook12] {};
|
||
|
void() gremlin_glook12 =[ $glook12.asc, gremlin_glook13] {};
|
||
|
void() gremlin_glook13 =[ $glook13.asc, gremlin_glook14] {};
|
||
|
void() gremlin_glook14 =[ $glook14.asc, gremlin_glook15] {};
|
||
|
void() gremlin_glook15 =[ $glook15.asc, gremlin_glook16] {};
|
||
|
void() gremlin_glook16 =[ $glook16.asc, gremlin_glook17] {};
|
||
|
void() gremlin_glook17 =[ $glook17.asc, gremlin_glook18] {};
|
||
|
void() gremlin_glook18 =[ $glook18.asc, gremlin_glook19] {};
|
||
|
void() gremlin_glook19 =[ $glook19.asc, gremlin_glook20] {};
|
||
|
void() gremlin_glook20 =[ $glook20.asc, gremlin_glook20]
|
||
|
{
|
||
|
GremlinDropBackpack();
|
||
|
self.stoleweapon = FALSE;
|
||
|
if (self.oldenemy.health > 0)
|
||
|
{
|
||
|
self.enemy = self.oldenemy;
|
||
|
HuntTarget ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (self.movetarget)
|
||
|
self.th_walk ();
|
||
|
else
|
||
|
self.th_stand ();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void() gremlin_pain1 =[ $pain1.asc, gremlin_pain2 ] {ai_back(4);};
|
||
|
void() gremlin_pain2 =[ $pain2.asc, gremlin_pain3 ] {ai_back(4);};
|
||
|
void() gremlin_pain3 =[ $pain3.asc, gremlin_pain4 ] {ai_back(2);};
|
||
|
void() gremlin_pain4 =[ $pain4.asc, gremlin_run1 ] {};
|
||
|
|
||
|
void() gremlin_gunpain1 =[ $gpain1.asc, gremlin_gunpain2 ] {ai_back(4);};
|
||
|
void() gremlin_gunpain2 =[ $gpain2.asc, gremlin_gunpain3 ] {ai_back(2);};
|
||
|
void() gremlin_gunpain3 =[ $gpain3.asc, gremlin_run1 ] {};
|
||
|
|
||
|
void(entity attacker, float damage) gremlin_pain =
|
||
|
{
|
||
|
local float r;
|
||
|
|
||
|
if (random()<0.8)
|
||
|
{
|
||
|
self.gorging = FALSE;
|
||
|
self.enemy = attacker;
|
||
|
FoundTarget();
|
||
|
}
|
||
|
if (self.touch == Gremlin_JumpTouch)
|
||
|
return;
|
||
|
|
||
|
if (self.pain_finished > time)
|
||
|
return;
|
||
|
|
||
|
self.pain_finished = time + 1;
|
||
|
// if (random()<0.5)
|
||
|
// sound (self, CHAN_VOICE, "grem/pain2.wav", 1, ATTN_NORM);
|
||
|
// else
|
||
|
r = random();
|
||
|
if (r<0.33)
|
||
|
sound (self, CHAN_VOICE, "grem/pain1.wav", 1, ATTN_NORM);
|
||
|
else if (r<0.66)
|
||
|
sound (self, CHAN_VOICE, "grem/pain2.wav", 1, ATTN_NORM);
|
||
|
else
|
||
|
sound (self, CHAN_VOICE, "grem/pain3.wav", 1, ATTN_NORM);
|
||
|
|
||
|
if (self.stoleweapon)
|
||
|
{
|
||
|
gremlin_gunpain1 ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gremlin_pain1 ();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void() gremlin_spawn1 =[ $spawn1.asc, gremlin_spawn2 ] {self.nextthink = time + 0.3;
|
||
|
self.th_pain = SUB_Null;
|
||
|
// sound (self, CHAN_VOICE, "grem/idle.wav", 1, ATTN_IDLE);
|
||
|
};
|
||
|
void() gremlin_spawn2 =[ $spawn2.asc, gremlin_spawn3 ] {self.nextthink = time + 0.3;};
|
||
|
void() gremlin_spawn3 =[ $spawn3.asc, gremlin_spawn4 ] {self.nextthink = time + 0.3;};
|
||
|
void() gremlin_spawn4 =[ $spawn4.asc, gremlin_spawn5 ] {self.nextthink = time + 0.3;};
|
||
|
void() gremlin_spawn5 =[ $spawn5.asc, gremlin_spawn6 ] {self.nextthink = time + 0.3;};
|
||
|
void() gremlin_spawn6 =[ $spawn6.asc, gremlin_run1 ] {
|
||
|
self.th_pain = gremlin_pain;
|
||
|
};
|
||
|
|
||
|
|
||
|
void() gremlin_die1 =[ $death1.asc, gremlin_die2 ] {
|
||
|
sound (self, CHAN_VOICE, "grem/death.wav", 1, ATTN_NORM);};
|
||
|
void() gremlin_die2 =[ $death2.asc, gremlin_die3 ] {ai_forward(2);};
|
||
|
void() gremlin_die3 =[ $death3.asc, gremlin_die4 ] {ai_forward(1);};
|
||
|
void() gremlin_die4 =[ $death4.asc, gremlin_die5 ] {ai_forward(2);};
|
||
|
void() gremlin_die5 =[ $death5.asc, gremlin_die6 ] {ai_forward(1);};
|
||
|
void() gremlin_die6 =[ $death6.asc, gremlin_die7 ]
|
||
|
{self.solid = SOLID_NOT;};
|
||
|
void() gremlin_die7 =[ $death7.asc, gremlin_die8 ] {ai_forward(2);};
|
||
|
void() gremlin_die8 =[ $death8.asc, gremlin_die9 ] {ai_forward(1);};
|
||
|
void() gremlin_die9 =[ $death9.asc, gremlin_die10 ] {ai_forward(2);};
|
||
|
void() gremlin_die10 =[ $death10.asc, gremlin_die11 ] {ai_forward(1);};
|
||
|
void() gremlin_die11 =[ $death11.asc, gremlin_die12 ] {ai_forward(2);};
|
||
|
void() gremlin_die12 =[ $death12.asc, gremlin_die12 ] {};
|
||
|
|
||
|
void() gremlin_gib=
|
||
|
{
|
||
|
sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
|
||
|
ThrowHead ("progs/h_grem.mdl", -35);
|
||
|
ThrowGib ("progs/gib1.mdl", -35);
|
||
|
ThrowGib ("progs/gib1.mdl", -35);
|
||
|
ThrowGib ("progs/gib1.mdl", -35);
|
||
|
};
|
||
|
|
||
|
void() gremlin_flip1 =[ $flip1.asc, gremlin_flip2 ]
|
||
|
{
|
||
|
ai_face();
|
||
|
makevectors (self.angles);
|
||
|
self.origin_z = self.origin_z + 1;
|
||
|
self.velocity = '0 0 350' - (v_forward * 200);
|
||
|
if (self.flags & FL_ONGROUND)
|
||
|
self.flags = self.flags - FL_ONGROUND;
|
||
|
sound (self, CHAN_VOICE, "grem/death.wav", 1, ATTN_NORM);
|
||
|
};
|
||
|
void() gremlin_flip2 =[ $flip2.asc, gremlin_flip3 ] {ai_face();};
|
||
|
void() gremlin_flip3 =[ $flip3.asc, gremlin_flip4 ] {};
|
||
|
void() gremlin_flip4 =[ $flip4.asc, gremlin_flip5 ] {};
|
||
|
void() gremlin_flip5 =[ $flip5.asc, gremlin_flip6 ] {};
|
||
|
void() gremlin_flip6 =[ $flip6.asc, gremlin_flip7 ] {self.touch = Gremlin_FlipTouch;};
|
||
|
void() gremlin_flip7 =[ $flip7.asc, gremlin_gib ]
|
||
|
{
|
||
|
self.nextthink = time + 3;
|
||
|
// if three seconds pass, assume gremlin is stuck and jump again
|
||
|
};
|
||
|
void() gremlin_flip8 =[ $flip8.asc, gremlin_flip8 ]
|
||
|
{
|
||
|
self.solid = SOLID_NOT;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
GremlinDropBackpack
|
||
|
===============
|
||
|
*/
|
||
|
void() GremlinDropBackpack =
|
||
|
{
|
||
|
local entity item;
|
||
|
|
||
|
item = spawn();
|
||
|
item.origin = self.origin - '0 0 24';
|
||
|
|
||
|
self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS ) );
|
||
|
item.items = self.items;
|
||
|
|
||
|
if (item.items & IT_AXE)
|
||
|
item.netname = "$qc_axe";
|
||
|
else if (item.items & IT_SHOTGUN)
|
||
|
item.netname = "$qc_shotgun";
|
||
|
else if (item.items & IT_SUPER_SHOTGUN)
|
||
|
item.netname = "$qc_double_shotgun";
|
||
|
else if (item.items & IT_NAILGUN)
|
||
|
item.netname = "$qc_nailgun";
|
||
|
else if (item.items & IT_SUPER_NAILGUN)
|
||
|
item.netname = "$qc_super_nailgun";
|
||
|
else if (item.items & IT_GRENADE_LAUNCHER)
|
||
|
item.netname = "$qc_grenade_launcher";
|
||
|
else if (item.items & IT_ROCKET_LAUNCHER)
|
||
|
item.netname = "$qc_rocket_launcher";
|
||
|
else if (item.items & IT_LIGHTNING)
|
||
|
item.netname = "$qc_thunderbolt";
|
||
|
else if (item.items & IT_LASER_CANNON)
|
||
|
item.netname = "$qc_laser_cannon";
|
||
|
else if (item.items & IT_PROXIMITY_GUN)
|
||
|
item.netname = "$qc_prox_gun";
|
||
|
else if (item.items & IT_MJOLNIR)
|
||
|
item.netname = "$qc_mjolnir";
|
||
|
else
|
||
|
item.netname = "";
|
||
|
|
||
|
item.ammo_shells = self.ammo_shells;
|
||
|
item.ammo_nails = self.ammo_nails;
|
||
|
item.ammo_rockets = self.ammo_rockets;
|
||
|
item.ammo_cells = self.ammo_cells;
|
||
|
if (item.ammo_shells < 0) item.ammo_shells = 0;
|
||
|
if (item.ammo_nails < 0) item.ammo_nails = 0;
|
||
|
if (item.ammo_rockets < 0) item.ammo_rockets = 0;
|
||
|
if (item.ammo_cells < 0) item.ammo_cells = 0;
|
||
|
|
||
|
item.velocity_z = 300;
|
||
|
item.velocity_x = -100 + (random() * 200);
|
||
|
item.velocity_y = -100 + (random() * 200);
|
||
|
|
||
|
item.flags = FL_ITEM;
|
||
|
item.solid = SOLID_TRIGGER;
|
||
|
item.movetype = MOVETYPE_TOSS;
|
||
|
setmodel (item, "progs/backpack.mdl");
|
||
|
setsize (item, '-16 -16 0', '16 16 56');
|
||
|
item.touch = BackpackTouch;
|
||
|
|
||
|
item.nextthink = time + 120; // remove after 2 minutes
|
||
|
item.think = SUB_Remove;
|
||
|
};
|
||
|
|
||
|
void() gremlin_die =
|
||
|
{
|
||
|
local vector vec;
|
||
|
local float dot;
|
||
|
|
||
|
// check for gib
|
||
|
if (self.items & (IT_SUPER_SHOTGUN|IT_NAILGUN|IT_SUPER_NAILGUN|IT_GRENADE_LAUNCHER|IT_ROCKET_LAUNCHER|IT_LIGHTNING|IT_LASER_CANNON|IT_PROXIMITY_GUN))
|
||
|
{
|
||
|
GremlinDropBackpack();
|
||
|
self.stoleweapon = FALSE;
|
||
|
}
|
||
|
|
||
|
makevectors (self.angles);
|
||
|
vec = normalize (damage_attacker.origin - self.origin);
|
||
|
dot = vec * v_forward;
|
||
|
|
||
|
if (self.health < -35)
|
||
|
{
|
||
|
sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
|
||
|
ThrowHead ("progs/h_grem.mdl", self.health);
|
||
|
ThrowGib ("progs/gib1.mdl", self.health);
|
||
|
ThrowGib ("progs/gib1.mdl", self.health);
|
||
|
ThrowGib ("progs/gib1.mdl", self.health);
|
||
|
return;
|
||
|
}
|
||
|
else if (dot>0.7 && (random()<0.5) && (self.flags & FL_ONGROUND))
|
||
|
{
|
||
|
gremlin_flip1();
|
||
|
return;
|
||
|
}
|
||
|
// regular death
|
||
|
gremlin_die1 ();
|
||
|
};
|
||
|
|
||
|
|
||
|
float() GremlinWeaponAttack;
|
||
|
void() Gremlin_MeleeAttack =
|
||
|
{
|
||
|
local float num;
|
||
|
if (self.gorging)
|
||
|
{
|
||
|
gremlin_gorge1();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (self.stoleweapon == 1)
|
||
|
{
|
||
|
objerror("gremlin meleeing with stolen weapon");
|
||
|
}
|
||
|
else if ((self.enemy.flags & FL_CLIENT) && random() < 0.4)
|
||
|
{
|
||
|
if (GremlinAttemptWeaponSteal())
|
||
|
return;
|
||
|
}
|
||
|
num = random();
|
||
|
if (num<0.3)
|
||
|
{
|
||
|
gremlin_claw1 ();
|
||
|
}
|
||
|
else if (num < 0.6)
|
||
|
{
|
||
|
gremlin_lunge1 ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gremlin_claw1 ();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
gremlin_recoil
|
||
|
============
|
||
|
*/
|
||
|
/*
|
||
|
void() gremlin_recoil =
|
||
|
{
|
||
|
self.nextthink = time + 0.1;
|
||
|
self.flags = self.flags - FL_ONGROUND;
|
||
|
if (vlen(self.velocity)<2)
|
||
|
{
|
||
|
self.movetype = self.spawnsolidtype;
|
||
|
self.think = self.spawnthink;
|
||
|
}
|
||
|
};
|
||
|
*/
|
||
|
/*
|
||
|
============
|
||
|
GremlinRecoil
|
||
|
============
|
||
|
*/
|
||
|
/*
|
||
|
void(vector dir, float mag) GremlinRecoil =
|
||
|
{
|
||
|
self.spawnsolidtype = self.movetype;
|
||
|
self.movetype = MOVETYPE_BOUNCE;
|
||
|
self.spawnthink = self.think;
|
||
|
self.think = gremlin_recoil;
|
||
|
self.nextthink = time;
|
||
|
self.velocity = mag * dir;
|
||
|
self.velocity_z = self.velocity_z + 100;
|
||
|
self.flags = self.flags - FL_ONGROUND;
|
||
|
};
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
GremlinCheckNoAmmo
|
||
|
|
||
|
attack with a weapon
|
||
|
============
|
||
|
*/
|
||
|
float() GremlinCheckNoAmmo =
|
||
|
{
|
||
|
if (self.currentammo > 0)
|
||
|
return TRUE;
|
||
|
else
|
||
|
{
|
||
|
self.stoleweapon = FALSE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
GremlinFindVictim
|
||
|
|
||
|
find a victim to shoot at
|
||
|
============
|
||
|
*/
|
||
|
entity() GremlinFindVictim =
|
||
|
{
|
||
|
local entity head;
|
||
|
local entity selected;
|
||
|
local float dist;
|
||
|
local float head_dist;
|
||
|
local float decision;
|
||
|
|
||
|
self.search_time = time + 1.0;
|
||
|
// look in our immediate vicinity
|
||
|
|
||
|
selected = world;
|
||
|
dist = 1000;
|
||
|
head = findradius(self.origin, 1000);
|
||
|
while(head)
|
||
|
{
|
||
|
if(!(head.flags & FL_NOTARGET) && ((head.flags & FL_MONSTER) || (head.flags & FL_CLIENT)))
|
||
|
{
|
||
|
if (visible(head) && (head.health > 0) && (head !=self))
|
||
|
{
|
||
|
head_dist = vlen(head.origin-self.origin);
|
||
|
if (head == self.lastvictim)
|
||
|
head_dist = head_dist * 2;
|
||
|
if (head.flags & FL_CLIENT)
|
||
|
head_dist = head_dist / 1.5;
|
||
|
if (head.classname == self.classname)
|
||
|
head_dist = head_dist * 1.5;
|
||
|
if (head_dist < dist)
|
||
|
{
|
||
|
selected = head;
|
||
|
dist = head_dist;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
head = head.chain;
|
||
|
}
|
||
|
self.lastvictim = selected;
|
||
|
|
||
|
return selected;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_FireRocket
|
||
|
|
||
|
fire a rocket
|
||
|
============
|
||
|
*/
|
||
|
void() Gremlin_FireRocket =
|
||
|
{
|
||
|
local entity missile, mpuff;
|
||
|
local vector dir;
|
||
|
|
||
|
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
|
||
|
|
||
|
self.punchangle_x = -2;
|
||
|
|
||
|
missile = spawn ();
|
||
|
missile.owner = self;
|
||
|
missile.movetype = MOVETYPE_FLYMISSILE;
|
||
|
missile.solid = SOLID_BBOX;
|
||
|
missile.classname = "missile";
|
||
|
|
||
|
// set missile speed
|
||
|
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.1 * v_right + crandom()* 0.1 *v_up;
|
||
|
missile.velocity = normalize(dir);
|
||
|
missile.velocity = missile.velocity * 1000;
|
||
|
missile.angles = vectoangles(missile.velocity);
|
||
|
|
||
|
missile.touch = T_MissileTouch;
|
||
|
|
||
|
// set missile duration
|
||
|
missile.nextthink = time + 5;
|
||
|
missile.think = SUB_Remove;
|
||
|
|
||
|
setmodel (missile, "progs/missile.mdl");
|
||
|
setsize (missile, '0 0 0', '0 0 0');
|
||
|
setorigin (missile, self.origin + v_forward*8 + '0 0 16');
|
||
|
// GremlinRecoil(dir,-1000);
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_FireNailGun
|
||
|
|
||
|
fire a nailgun
|
||
|
============
|
||
|
*/
|
||
|
void(float ox) Gremlin_FireNailGun =
|
||
|
{
|
||
|
local vector dir;
|
||
|
|
||
|
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.1 * v_right + crandom()* 0.1 *v_up;
|
||
|
dir = normalize(dir);
|
||
|
launch_spike (self.origin + '0 0 16', dir);
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_FireLaserGun
|
||
|
|
||
|
fire a laser cannon
|
||
|
============
|
||
|
*/
|
||
|
void(float ox) Gremlin_FireLaserGun =
|
||
|
{
|
||
|
local vector dir;
|
||
|
|
||
|
self.currentammo = self.ammo_cells = self.ammo_cells - 1;
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.1 * v_right + crandom()* 0.1 *v_up;
|
||
|
dir = normalize(dir);
|
||
|
HIP_LaunchLaser(self.origin + '0 0 16', dir, 0);
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_FireShotGun
|
||
|
|
||
|
fire a shotgun
|
||
|
============
|
||
|
*/
|
||
|
void() Gremlin_FireShotGun =
|
||
|
{
|
||
|
local vector dir;
|
||
|
|
||
|
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.1 *v_right + crandom()* 0.1 *v_up;
|
||
|
dir = normalize(dir);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
FireBullets (6, dir, '0.04 0.04 0');
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_FireSuperShotGun
|
||
|
|
||
|
fire a shotgun
|
||
|
============
|
||
|
*/
|
||
|
void() Gremlin_FireSuperShotGun =
|
||
|
{
|
||
|
local vector dir;
|
||
|
|
||
|
self.currentammo = self.ammo_shells = self.ammo_shells - 2;
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
|
||
|
sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.3 *v_right + crandom()* 0.3 *v_up;
|
||
|
dir = normalize(dir);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
FireBullets (14, dir, '0.14 0.08 0');
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_FireLightningGun
|
||
|
|
||
|
fire lightning gun
|
||
|
============
|
||
|
*/
|
||
|
void() Gremlin_FireLightningGun =
|
||
|
{
|
||
|
local vector org, dir;
|
||
|
local float cells;
|
||
|
|
||
|
// explode if under water
|
||
|
if (self.watertype <= CONTENT_WATER)
|
||
|
{
|
||
|
cells = self.ammo_cells;
|
||
|
self.ammo_cells = 0;
|
||
|
discharged = 1;
|
||
|
T_RadiusDamage (self, self, 35*cells, world);
|
||
|
discharged = 0;
|
||
|
// W_SetCurrentAmmo ();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
self.effects = self.effects | EF_MUZZLEFLASH;
|
||
|
|
||
|
ai_face ();
|
||
|
|
||
|
self.currentammo = self.ammo_cells = self.ammo_cells - 2;
|
||
|
org = self.origin + '0 0 16';
|
||
|
|
||
|
dir = self.enemy.origin + '0 0 16' - org;
|
||
|
dir = normalize (dir);
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.1 *v_right + crandom()* 0.1 *v_up;
|
||
|
dir = normalize(dir);
|
||
|
|
||
|
traceline (org, self.origin + dir*600, TRUE, self);
|
||
|
|
||
|
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||
|
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
|
||
|
WriteEntity (MSG_BROADCAST, self);
|
||
|
WriteCoord (MSG_BROADCAST, org_x);
|
||
|
WriteCoord (MSG_BROADCAST, org_y);
|
||
|
WriteCoord (MSG_BROADCAST, org_z);
|
||
|
WriteCoord (MSG_BROADCAST, trace_endpos_x);
|
||
|
WriteCoord (MSG_BROADCAST, trace_endpos_y);
|
||
|
WriteCoord (MSG_BROADCAST, trace_endpos_z);
|
||
|
|
||
|
LightningDamage (org, trace_endpos+(dir*4), self, 30);
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
GremlinFireProximityGrenade
|
||
|
================
|
||
|
*/
|
||
|
void() GremlinFireProximityGrenade =
|
||
|
{
|
||
|
local entity missile;
|
||
|
local vector dir;
|
||
|
|
||
|
NumProximityGrenades = NumProximityGrenades + 1;
|
||
|
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
|
||
|
|
||
|
missile = spawn ();
|
||
|
missile.owner = self;
|
||
|
missile.lastvictim = self;
|
||
|
missile.movetype = MOVETYPE_TOSS;
|
||
|
missile.solid = SOLID_BBOX;
|
||
|
missile.classname = "proximity_grenade";
|
||
|
missile.takedamage = DAMAGE_NO;
|
||
|
missile.health = 5;
|
||
|
missile.state = 0;
|
||
|
|
||
|
// set missile speed
|
||
|
|
||
|
dir = normalize(self.enemy.origin - self.origin);
|
||
|
self.v_angle = vectoangles(dir);
|
||
|
makevectors(self.v_angle);
|
||
|
dir = dir + crandom()* 0.1 *v_right + crandom()* 0.1 *v_up;
|
||
|
dir = normalize(dir);
|
||
|
missile.velocity = dir * 600;
|
||
|
missile.velocity_z = 200;
|
||
|
|
||
|
missile.avelocity = '100 600 100';
|
||
|
|
||
|
missile.angles = vectoangles(missile.velocity);
|
||
|
|
||
|
missile.touch = ProximityGrenadeTouch;
|
||
|
|
||
|
// set missile duration
|
||
|
missile.nextthink = time + 2;
|
||
|
missile.delay = time + 15 + (10*random());
|
||
|
missile.think = ProximityBomb;
|
||
|
missile.th_die = ProximityGrenadeExplode;
|
||
|
|
||
|
setmodel (missile, "progs/proxbomb.mdl");
|
||
|
setorigin (missile, self.origin);
|
||
|
setsize (missile, '-1 -1 -1', '1 1 1');
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
GremlinWeaponAttack
|
||
|
|
||
|
attack with a weapon
|
||
|
============
|
||
|
*/
|
||
|
void() gremlin_shot1;
|
||
|
void() gremlin_nail1;
|
||
|
void() gremlin_light1;
|
||
|
void() gremlin_rocket1;
|
||
|
|
||
|
float() GremlinWeaponAttack =
|
||
|
{
|
||
|
local float r;
|
||
|
local entity targ;
|
||
|
local vector vec;
|
||
|
|
||
|
|
||
|
if (!GremlinCheckNoAmmo ())
|
||
|
return FALSE;
|
||
|
|
||
|
self.show_hostile = time + 1; // wake monsters up
|
||
|
|
||
|
if (self.weapon == IT_SHOTGUN)
|
||
|
{
|
||
|
gremlin_shot1 ();
|
||
|
Gremlin_FireShotGun();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_SUPER_SHOTGUN)
|
||
|
{
|
||
|
gremlin_shot1 ();
|
||
|
Gremlin_FireSuperShotGun();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_NAILGUN)
|
||
|
{
|
||
|
gremlin_nail3 ();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_SUPER_NAILGUN)
|
||
|
{
|
||
|
gremlin_nail3 ();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_GRENADE_LAUNCHER)
|
||
|
{
|
||
|
gremlin_rocket1();
|
||
|
OgreFireGrenade();
|
||
|
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_ROCKET_LAUNCHER)
|
||
|
{
|
||
|
gremlin_rocket1();
|
||
|
Gremlin_FireRocket();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_LIGHTNING)
|
||
|
{
|
||
|
gremlin_light1();
|
||
|
SUB_AttackFinished(1);
|
||
|
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
|
||
|
}
|
||
|
else if (self.weapon == IT_LASER_CANNON)
|
||
|
{
|
||
|
gremlin_laser3();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
else if (self.weapon == IT_PROXIMITY_GUN)
|
||
|
{
|
||
|
gremlin_rocket1();
|
||
|
GremlinFireProximityGrenade();
|
||
|
SUB_AttackFinished(1);
|
||
|
}
|
||
|
return TRUE;
|
||
|
};
|
||
|
|
||
|
void() Gremlin_MissileAttack =
|
||
|
{
|
||
|
if (self.stoleweapon)
|
||
|
{
|
||
|
if (GremlinWeaponAttack())
|
||
|
return;
|
||
|
else if ((random()<0.1) && (self.flags & FL_ONGROUND))
|
||
|
{
|
||
|
gremlin_jump1();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
if (self.flags & FL_ONGROUND)
|
||
|
gremlin_jump1();
|
||
|
};
|
||
|
|
||
|
/*QUAKED monster_gremlin (1 0 0) (-32 -32 -24) (32 32 64) Ambush
|
||
|
|
||
|
*/
|
||
|
void() monster_gremlin =
|
||
|
{
|
||
|
if (deathmatch)
|
||
|
{
|
||
|
remove(self);
|
||
|
return;
|
||
|
}
|
||
|
NumGremlins = NumGremlins + 1;
|
||
|
precache_model ("progs/grem.mdl");
|
||
|
precache_model ("progs/h_grem.mdl");
|
||
|
|
||
|
precache_sound ("grem/death.wav");
|
||
|
precache_sound ("grem/attack.wav");
|
||
|
precache_sound ("demon/djump.wav");
|
||
|
precache_sound ("demon/dhit2.wav");
|
||
|
precache_sound ("grem/pain1.wav");
|
||
|
precache_sound ("grem/pain2.wav");
|
||
|
precache_sound ("grem/pain3.wav");
|
||
|
precache_sound ("grem/idle.wav");
|
||
|
precache_sound ("grem/sight1.wav");
|
||
|
|
||
|
self.solid = SOLID_SLIDEBOX;
|
||
|
self.movetype = MOVETYPE_STEP;
|
||
|
|
||
|
setmodel (self, "progs/grem.mdl");
|
||
|
|
||
|
setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
|
||
|
self.health = 100;
|
||
|
self.max_health = 101;
|
||
|
self.yaw_speed = 40;
|
||
|
|
||
|
self.th_stand = gremlin_stand1;
|
||
|
self.th_walk = gremlin_walk1;
|
||
|
self.th_run = gremlin_run1;
|
||
|
self.th_die = gremlin_die;
|
||
|
self.th_melee = Gremlin_MeleeAttack; // one of two attacks
|
||
|
self.th_missile = Gremlin_MissileAttack; // check for random jump or firing of weapon
|
||
|
self.th_pain = gremlin_pain;
|
||
|
|
||
|
walkmonster_start();
|
||
|
};
|
||
|
|
||
|
float() GremlinCheckAttack =
|
||
|
{
|
||
|
local vector spot1, spot2;
|
||
|
local entity targ;
|
||
|
local float chance;
|
||
|
|
||
|
targ = self.enemy;
|
||
|
|
||
|
if (time < self.attack_finished)
|
||
|
return FALSE;
|
||
|
|
||
|
// see if any entities are in the way of the shot
|
||
|
spot1 = self.origin;// + self.view_ofs;
|
||
|
spot2 = targ.origin;// + targ.view_ofs;
|
||
|
|
||
|
if ((vlen(spot2 - spot1) <= 90) && (self.stoleweapon == 0))
|
||
|
{
|
||
|
self.attack_state = AS_MELEE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
// missile attack
|
||
|
chance = 0.03 + self.stoleweapon;
|
||
|
if (random() < chance)
|
||
|
{
|
||
|
self.attack_state = AS_MISSILE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
};
|
||
|
|
||
|
|
||
|
//===========================================================================
|
||
|
|
||
|
void(float side) Gremlin_Melee =
|
||
|
{
|
||
|
local float ldmg;
|
||
|
local vector delta;
|
||
|
|
||
|
ai_face ();
|
||
|
|
||
|
// walkmove (self.ideal_yaw, 12); // allow a little closing
|
||
|
|
||
|
|
||
|
delta = self.enemy.origin - self.origin;
|
||
|
|
||
|
if (vlen(delta) > 100)
|
||
|
return;
|
||
|
if (!CanDamage (self.enemy, self))
|
||
|
return;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "grem/attack.wav", 1, ATTN_NORM);
|
||
|
ldmg = 10 + 5*random();
|
||
|
T_Damage (self.enemy, self, self, ldmg);
|
||
|
|
||
|
makevectors (self.angles);
|
||
|
SpawnMeatSpray (self.origin + v_forward*16, side * v_right);
|
||
|
};
|
||
|
|
||
|
//===========================================================================
|
||
|
void(float dm) Gremlin_ThrowHead =
|
||
|
{
|
||
|
local string gibname;
|
||
|
if (self.classname == "monster_ogre")
|
||
|
gibname = "progs/h_ogre.mdl";
|
||
|
else if (self.classname == "monster_knight")
|
||
|
gibname = "progs/h_knight.mdl";
|
||
|
else if (self.classname == "monster_shambler")
|
||
|
gibname = "progs/h_shams.mdl";
|
||
|
else if (self.classname == "monster_demon1")
|
||
|
gibname = "progs/h_demon.mdl";
|
||
|
else if (self.classname == "monster_wizard")
|
||
|
gibname = "progs/h_wizard.mdl";
|
||
|
else if (self.classname == "monster_zombie")
|
||
|
gibname = "progs/h_zombie.mdl";
|
||
|
else if (self.classname == "monster_dog")
|
||
|
gibname = "progs/h_dog.mdl";
|
||
|
else if (self.classname == "monster_hell_knight")
|
||
|
gibname = "progs/h_hellkn.mdl";
|
||
|
else if (self.classname == "monster_enforcer")
|
||
|
gibname = "progs/h_mega.mdl";
|
||
|
else if (self.classname == "monster_army")
|
||
|
gibname = "progs/h_guard.mdl";
|
||
|
else if (self.classname == "monster_shalrath")
|
||
|
gibname = "progs/h_shal.mdl";
|
||
|
else if (self.classname == "monster_gremlin")
|
||
|
gibname = "progs/h_grem.mdl";
|
||
|
else if (self.classname == "monster_scourge")
|
||
|
gibname = "progs/h_scourg.mdl";
|
||
|
else if (self.classname == "monster_fish")
|
||
|
gibname = "progs/gib1.mdl";
|
||
|
else
|
||
|
gibname = "progs/h_player.mdl";
|
||
|
ThrowHead(gibname,dm);
|
||
|
};
|
||
|
//===========================================================================
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
Gremlin_Damage
|
||
|
|
||
|
The damage is coming from inflictor, but get mad at attacker
|
||
|
============
|
||
|
*/
|
||
|
void(entity targ, entity inflictor, entity attacker, float damage) Gremlin_Damage=
|
||
|
{
|
||
|
// check for godmode or invincibility
|
||
|
if (targ.flags & FL_GODMODE)
|
||
|
return;
|
||
|
if (targ.invincible_finished >= time)
|
||
|
{
|
||
|
if (self.invincible_sound < time)
|
||
|
{
|
||
|
sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
|
||
|
self.invincible_sound = time + 2;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// team play damage avoidance
|
||
|
if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
|
||
|
return;
|
||
|
|
||
|
// do the damage
|
||
|
targ.health = targ.health - damage;
|
||
|
};
|
||
|
|
||
|
void() Gremlin_Split =
|
||
|
{
|
||
|
local entity grem;
|
||
|
local entity temp;
|
||
|
local entity head;
|
||
|
local float done;
|
||
|
local vector ang;
|
||
|
local float c;
|
||
|
local vector pos;
|
||
|
local float proceed;
|
||
|
|
||
|
if (NumSpawnGremlins >= (NumGremlins*2))
|
||
|
return;
|
||
|
done = 0;
|
||
|
c = 0;
|
||
|
ang = self.angles;
|
||
|
while (done == 0)
|
||
|
{
|
||
|
makevectors(ang);
|
||
|
pos = self.origin + (80 * v_forward);
|
||
|
head = findradius(pos, 35);
|
||
|
proceed = 1;
|
||
|
while (head)
|
||
|
{
|
||
|
if ((head.health > 0) && (head.flags & (FL_MONSTER | FL_CLIENT)))
|
||
|
proceed = 0;
|
||
|
head = head.chain;
|
||
|
}
|
||
|
traceline(self.origin,pos,FALSE,self);
|
||
|
if (trace_fraction == 1 && (proceed == 1))
|
||
|
{
|
||
|
traceline(self.origin,(pos-'40 40 0'),FALSE,self);
|
||
|
if (trace_fraction == 1)
|
||
|
{
|
||
|
traceline(self.origin,(pos+'40 40 0'),FALSE,self);
|
||
|
if (trace_fraction == 1)
|
||
|
{
|
||
|
traceline(self.origin,(pos + '0 0 64'),FALSE,self);
|
||
|
if (trace_fraction == 1)
|
||
|
{
|
||
|
traceline(self.origin,(pos - '0 0 64'),FALSE,self);
|
||
|
if (trace_fraction != 1)
|
||
|
{
|
||
|
done = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (done == 0)
|
||
|
{
|
||
|
ang_y = ang_y + 36;
|
||
|
c = c + 1;
|
||
|
if (c==10)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
NumSpawnGremlins = NumSpawnGremlins + 1;
|
||
|
grem = spawn();
|
||
|
SUB_CopyEntity(self,grem);
|
||
|
grem.solid = SOLID_SLIDEBOX;
|
||
|
grem.movetype = MOVETYPE_STEP;
|
||
|
setmodel (grem, "progs/grem.mdl");
|
||
|
setsize (grem, VEC_HULL_MIN, VEC_HULL_MAX);
|
||
|
if (self.health < 100) self.health = 100;
|
||
|
grem.health = self.health / 2;
|
||
|
self.health = self.health / 2;
|
||
|
// grem.max_health = 101;
|
||
|
// grem.gorging = FALSE;
|
||
|
grem.stoleweapon = FALSE;
|
||
|
grem.items = 0;
|
||
|
total_monsters = total_monsters + 1;
|
||
|
WriteByte (MSG_BROADCAST, SVC_UPDATESTAT);
|
||
|
WriteByte (MSG_BROADCAST, STAT_TOTALMONSTERS);
|
||
|
WriteLong (MSG_BROADCAST, total_monsters);
|
||
|
setorigin(grem, pos);
|
||
|
temp = self;
|
||
|
self = grem;
|
||
|
gremlin_spawn1();
|
||
|
self.enemy = world;
|
||
|
self.gorging = FALSE;
|
||
|
self = temp;
|
||
|
};
|
||
|
|
||
|
void(float side) Gremlin_Gorge =
|
||
|
{
|
||
|
local float ldmg;
|
||
|
local vector delta;
|
||
|
local entity temp;
|
||
|
|
||
|
// ai_face ();
|
||
|
// walkmove (self.ideal_yaw, 6); // allow a little closing
|
||
|
|
||
|
delta = self.enemy.origin - self.origin;
|
||
|
// self.enemy.takedamage = DAMAGE_YES;
|
||
|
|
||
|
sound (self, CHAN_WEAPON, "demon/dhit2.wav", 1, ATTN_NORM);
|
||
|
// sound (self, CHAN_WEAPON, "grem/attack.wav", 1, ATTN_NORM);
|
||
|
ldmg = 7+5*random();
|
||
|
Gremlin_Damage (self.enemy, self, self, ldmg);
|
||
|
|
||
|
makevectors (self.angles);
|
||
|
SpawnMeatSpray (self.origin + v_forward*16, side * v_right);
|
||
|
if (self.enemy.health < -200.0)
|
||
|
{
|
||
|
if (self.enemy.gorging==FALSE)
|
||
|
{
|
||
|
self.enemy.gorging = TRUE;
|
||
|
sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
|
||
|
temp = self;
|
||
|
self = self.enemy;
|
||
|
Gremlin_ThrowHead(-15);
|
||
|
// ThrowGib ("progs/gib1.mdl", -15);
|
||
|
// ThrowGib ("progs/gib2.mdl", -15);
|
||
|
// ThrowGib ("progs/gib3.mdl", -15);
|
||
|
self = temp;
|
||
|
ldmg = 150 + 100*random();
|
||
|
T_Heal(self,ldmg,FALSE);
|
||
|
// if (self.health >= self.max_health)
|
||
|
Gremlin_Split();
|
||
|
}
|
||
|
self.enemy = world;
|
||
|
self.gorging = FALSE;
|
||
|
/*
|
||
|
if (self.stoleweapon)
|
||
|
{
|
||
|
temp = GremlinFindVictim();
|
||
|
if (temp != world)
|
||
|
{
|
||
|
self.enemy = temp;
|
||
|
FoundTarget();
|
||
|
self.search_time = time + 1.0;
|
||
|
// return;
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
// FindTarget();
|
||
|
/*
|
||
|
if (self.oldenemy.health > 0)
|
||
|
{
|
||
|
self.enemy = self.oldenemy;
|
||
|
HuntTarget ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (self.movetarget)
|
||
|
self.th_walk ();
|
||
|
else
|
||
|
self.th_stand ();
|
||
|
}
|
||
|
*/
|
||
|
gremlin_look1();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
void() Gremlin_JumpTouch =
|
||
|
{
|
||
|
local float ldmg;
|
||
|
|
||
|
if (self.health <= 0)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
if (other.takedamage)
|
||
|
{
|
||
|
if ( vlen(self.velocity) > 400 )
|
||
|
{
|
||
|
ldmg = 40 + 10*random();
|
||
|
T_Damage (other, self, self, ldmg);
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
if (!checkbottom(self))
|
||
|
{
|
||
|
if (self.flags & FL_ONGROUND)
|
||
|
{
|
||
|
self.touch = SUB_Null;
|
||
|
self.think = gremlin_jump1;
|
||
|
self.nextthink = time + 0.1;
|
||
|
}
|
||
|
return; // not on ground yet
|
||
|
}
|
||
|
|
||
|
self.touch = SUB_Null;
|
||
|
self.think = gremlin_jump12;
|
||
|
self.nextthink = time + 0.1;
|
||
|
};
|
||
|
|
||
|
void() Gremlin_FlipTouch =
|
||
|
{
|
||
|
local float ldmg;
|
||
|
|
||
|
if (!checkbottom(self))
|
||
|
{
|
||
|
if (self.flags & FL_ONGROUND)
|
||
|
{
|
||
|
self.touch = SUB_Null;
|
||
|
self.think = gremlin_flip1;
|
||
|
self.nextthink = time + 0.1;
|
||
|
}
|
||
|
return; // not on ground yet
|
||
|
}
|
||
|
|
||
|
self.touch = SUB_Null;
|
||
|
self.think = gremlin_flip8;
|
||
|
self.nextthink = time + 0.1;
|
||
|
};
|