quake-hipnotic-sdk/progs/fight.qc

410 lines
7.0 KiB
C++
Raw Normal View History

1997-03-11 00:00:00 +00:00
/*
a monster is in fight mode if it thinks it can effectively attack its
enemy.
when it decides it can't attack, it goes into hunt mode.
*/
float(float v) anglemod;
void() knight_atk1;
void() knight_runatk1;
void() ogre_smash1;
void() ogre_swing1;
void() sham_smash1;
void() sham_swingr1;
void() sham_swingl1;
float() demoncheckattack;
void(float side) demon_melee;
void(vector dest) chooseturn;
void() ai_face;
float enemy_vis, enemy_infront, enemy_range;
float enemy_yaw;
void() knight_attack =
{
local float len;
// decide if now is a good swing time
len = vlen(self.enemy.origin+self.enemy.view_ofs - (self.origin+self.view_ofs));
if (len<80)
knight_atk1 ();
else
knight_runatk1 ();
};
//=============================================================================
/*
===========
checkattack
the player is in view, so decide to move or launch an attack
returns false if movement should continue
============
*/
float() checkattack =
{
local vector spot1, spot2;
local entity targ;
local float chance;
targ = self.enemy;
// see if any entities are in the way of the shot
spot1 = self.origin + self.view_ofs;
spot2 = targ.origin + targ.view_ofs;
traceline (spot1, spot2, false, self);
//med 10/17/96 added charmed stuff
if ((trace_ent != targ) && (!self.charmed))
return false; // don't have a clear shot
if (trace_inopen && trace_inwater)
return false; // sight line crossed contents
if (enemy_range == range_melee)
{ // melee attack
if (self.th_melee)
{
if (self.classname == "monster_knight")
knight_attack ();
else
self.th_melee ();
return true;
}
}
// missile attack
if (!self.th_missile)
return false;
if (time < self.attack_finished)
return false;
if (enemy_range == range_far)
return false;
if (enemy_range == range_melee)
{
chance = 0.9;
self.attack_finished = 0;
}
else if (enemy_range == range_near)
{
if (self.th_melee)
chance = 0.2;
else
chance = 0.4;
}
else if (enemy_range == range_mid)
{
if (self.th_melee)
chance = 0.05;
else
chance = 0.1;
}
else
chance = 0;
if (random () < chance)
{
self.th_missile ();
sub_attackfinished (2*random());
return true;
}
return false;
};
/*
=============
ai_face
stay facing the enemy
=============
*/
void() ai_face =
{
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
changeyaw ();
};
/*
=============
ai_charge
the monster is in a melee attack, so get as close as possible to .enemy
=============
*/
float (entity targ) visible;
float(entity targ) infront;
float(entity targ) range;
void(float d) ai_charge =
{
ai_face ();
movetogoal (d); // done in c code...
};
void() ai_charge_side =
{
local vector dtemp;
local float heading;
// aim to the left of the enemy for a flyby
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
changeyaw ();
makevectors (self.angles);
dtemp = self.enemy.origin - 30*v_right;
heading = vectoyaw(dtemp - self.origin);
walkmove(heading, 20);
};
/*
=============
ai_melee
=============
*/
void() ai_melee =
{
local vector delta;
local float ldmg;
if (!self.enemy)
return; // removed before stroke
delta = self.enemy.origin - self.origin;
if (vlen(delta) > 60)
return;
ldmg = (random() + random() + random()) * 3;
t_damage (self.enemy, self, self, ldmg);
};
void() ai_melee_side =
{
local vector delta;
local float ldmg;
if (!self.enemy)
return; // removed before stroke
ai_charge_side();
delta = self.enemy.origin - self.origin;
if (vlen(delta) > 60)
return;
if (!candamage (self.enemy, self))
return;
ldmg = (random() + random() + random()) * 3;
t_damage (self.enemy, self, self, ldmg);
};
//=============================================================================
/*
===========
soldiercheckattack
the player is in view, so decide to move or launch an attack
returns false if movement should continue
============
*/
float() soldiercheckattack =
{
local vector spot1, spot2;
local entity targ;
local float chance;
targ = self.enemy;
// see if any entities are in the way of the shot
spot1 = self.origin + self.view_ofs;
spot2 = targ.origin + targ.view_ofs;
traceline (spot1, spot2, false, self);
if (trace_inopen && trace_inwater)
return false; // sight line crossed contents
if (trace_ent != targ)
return false; // don't have a clear shot
// missile attack
if (time < self.attack_finished)
return false;
if (enemy_range == range_far)
return false;
if (enemy_range == range_melee)
chance = 0.9;
else if (enemy_range == range_near)
chance = 0.4;
else if (enemy_range == range_mid)
chance = 0.05;
else
chance = 0;
if (random () < chance)
{
self.th_missile ();
sub_attackfinished (1 + random());
if (random() < 0.3)
self.lefty = !self.lefty;
return true;
}
return false;
};
//=============================================================================
/*
===========
shamcheckattack
the player is in view, so decide to move or launch an attack
returns false if movement should continue
============
*/
float() shamcheckattack =
{
local vector spot1, spot2;
local entity targ;
local float chance;
local float enemy_yaw;
if (enemy_range == range_melee)
{
if (candamage (self.enemy, self))
{
self.attack_state = as_melee;
return true;
}
}
if (time < self.attack_finished)
return false;
if (!enemy_vis)
return false;
targ = self.enemy;
// 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(spot1 - spot2) > 600)
return false;
traceline (spot1, spot2, false, self);
if (trace_inopen && trace_inwater)
return false; // sight line crossed contents
if (trace_ent != targ)
{
return false; // don't have a clear shot
}
// missile attack
if (enemy_range == range_far)
return false;
self.attack_state = as_missile;
sub_attackfinished (2 + 2*random());
return true;
};
//============================================================================
/*
===========
ogrecheckattack
the player is in view, so decide to move or launch an attack
returns false if movement should continue
============
*/
float() ogrecheckattack =
{
local vector spot1, spot2;
local entity targ;
local float chance;
if (enemy_range == range_melee)
{
if (candamage (self.enemy, self))
{
self.attack_state = as_melee;
return true;
}
}
if (time < self.attack_finished)
return false;
if (!enemy_vis)
return false;
targ = self.enemy;
// see if any entities are in the way of the shot
spot1 = self.origin + self.view_ofs;
spot2 = targ.origin + targ.view_ofs;
traceline (spot1, spot2, false, self);
if (trace_inopen && trace_inwater)
return false; // sight line crossed contents
if (trace_ent != targ)
{
return false; // don't have a clear shot
}
// missile attack
if (time < self.attack_finished)
return false;
if (enemy_range == range_far)
return false;
else if (enemy_range == range_near)
chance = 0.10;
else if (enemy_range == range_mid)
chance = 0.05;
else
chance = 0;
self.attack_state = as_missile;
sub_attackfinished (1 + 2*random());
return true;
};