ew-engine/hq engine src/pr_game.c

413 lines
8.5 KiB
C

#include "quakedef.h"
#define MELEE_DISTANCE 80
//range
#define RANGE_MELEE 0
#define RANGE_NEAR 1
#define RANGE_MID 2
#define RANGE_FAR 3
//gib types
#define GIB_ORGANIC 0
#define GIB_METALLIC 1
//monster ai flags
#define AI_STAND_GROUND 0x00000001
#define AI_TEMP_STAND_GROUND 0x00000002
#define AI_SOUND_TARGET 0x00000004
#define AI_LOST_SIGHT 0x00000008
#define AI_PURSUIT_LAST_SEEN 0x00000010
#define AI_PURSUE_NEXT 0x00000020
#define AI_PURSUE_TEMP 0x00000040
#define AI_HOLD_FRAME 0x00000080
#define AI_GOOD_GUY 0x00000100
#define AI_BRUTAL 0x00000200
#define AI_NOSTEP 0x00000400
#define AI_DUCKED 0x00000800
#define AI_COMBAT_POINT 0x00001000
#define AI_MEDIC 0x00002000
#define AI_RESURRECTING 0x00004000
//monster attack state
#define AS_STRAIGHT 1
#define AS_SLIDING 2
#define AS_MELEE 3
#define AS_MISSILE 4
void PF_changeyaw (void);
qboolean SV_StepDirection (edict_t *ent, float yaw, float dist);
float VectorLength( const vec3_t v );
float vectoyaw (vec3_t value1);
float changeyaw (float ideal, float speed, float current)
{
// edict_t *ent;
float move;
current = anglemod( current );
if (current == ideal)
return current;
move = ideal - current;
if (ideal > current)
{
if (move >= 180)
move = move - 360;
}
else
{
if (move <= -180)
move = move + 360;
}
if (move > 0)
{
if (move > speed)
move = speed;
}
else
{
if (move < -speed)
move = -speed;
}
return anglemod (current + move);
}
edict_t *NextClient (edict_t *edict)
{
int e;
edict_t *ent;
e = NUM_FOR_EDICT (edict); // Get the edictnum
while (1) // Loop until we get a return
{
e++; // Increase e with 1
if (e == sv.num_edicts) // If gone through all edict's
return sv.edicts; // then return
ent = EDICT_NUM (e); // Get the edict from the new edictnum
if (!ent->free) // If it exists
return ent; // then return it
}
}
qboolean Wisible (vec3_t v1, vec3_t v2, edict_t *ent, edict_t *enemy)
{
trace_t trace;
trace = SV_Move (v1, vec3_origin, vec3_origin, v2, true, ent);
if (trace.fraction == 1) // If the trace found its way to the enemy
return true; // Then the bot can see him
return false; // Otherwise he cant
}
void CalcAngles (vec3_t oldvector, vec3_t newvector)
{
float forward;
float yaw, pitch;
if (oldvector[1] == 0 && oldvector[0] == 0)
{
yaw = 0;
if (oldvector[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (int) (atan2(oldvector[1], oldvector[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
forward = sqrt (oldvector[0]*oldvector[0] + oldvector[1]*oldvector[1]);
pitch = (int) (atan2(oldvector[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
newvector[0] = pitch;
newvector[1] = yaw;
newvector[2] = 0;
}
void ai_move (edict_t *self, float dist)
{
SV_StepDirection (self, self->v.ideal_yaw, dist);
}
void ai_search (edict_t *self)
{
int oldself;
oldself = pr_global_struct->self;
pr_global_struct->self = EDICT_TO_PROG(self);
SV_MoveToGoal();
pr_global_struct->self = oldself;
}
int range (edict_t *self, edict_t *other)
{
vec3_t v;
float len;
VectorSubtract (self->v.origin, other->v.origin, v);
len = VectorLength (v);
if (len < MELEE_DISTANCE)
return RANGE_MELEE;
if (len < 500)
return RANGE_NEAR;
if (len < 1000)
return RANGE_MID;
return RANGE_FAR;
}
qboolean visible (edict_t *self, edict_t *other)
{
vec3_t spot1;
vec3_t spot2;
trace_t trace;
VectorCopy (self->v.origin, spot1);
spot1[2] += self->v.view_ofs[2];
VectorCopy (other->v.origin, spot2);
spot2[2] += self->v.view_ofs[2];
trace = SV_Move (spot1, vec3_origin, vec3_origin, spot2, true, self);
if (trace.fraction == 1.0)
return true;
return false;
}
qboolean infront (edict_t *self, edict_t *other)
{
vec3_t vec;
float dot;
vec3_t forward;
AngleVectors (self->v.angles, forward, NULL, NULL);
VectorSubtract (other->v.origin, self->v.origin, vec);
VectorNormalize (vec);
dot = DotProduct (vec, forward);
if (dot > 0.3)
return true;
return false;
}
entvars_t * V(int entity)
{
return &((EDICT_NUM(entity))->v);
}
int FindFieldOffset(char *field);
float GetFunctionValue(char *name, edict_t * ed)
{
static char oldname[200];
static int oldoffset;
eval_t *eval;
int offset;
if (!strcmp(name, oldname))
{
eval = GETEDICTFIELDVALUE(ed, oldoffset);
return eval->function;
}
offset = FindFieldOffset(name);
if(!offset)
return 0;
oldoffset = offset;
strcpy(oldname, name);
eval = GETEDICTFIELDVALUE(ed, offset);
return eval->function;
}
vec3_t * GetVectorValue(char *name, edict_t * ed)
{
static char oldname[200];
static int oldoffset;
eval_t *eval;
int offset;
if (!strcmp(name, oldname))
{
eval = GETEDICTFIELDVALUE(ed, oldoffset);
return &(eval->vector);
}
offset = FindFieldOffset(name);
if(!offset)
return 0;
oldoffset = offset;
strcpy(oldname, name);
eval = GETEDICTFIELDVALUE(ed, offset);
return &(eval->vector);
}
void HuntTarget (edict_t *self)
{
vec3_t vec;
self->v.goalentity = self->v.enemy;
/*
if (self->monsterinfo.aiflags & AI_STAND_GROUND)
self->monsterinfo.stand (self);
else
self->monsterinfo.run (self);*/
self->v.think = GetFunctionValue("th_run",self);
VectorSubtract (V(self->v.enemy)->origin, self->v.origin, vec);
self->v.ideal_yaw = vectoyaw(vec);
// wait a while before first attack
//if (!(self->monsterinfo.aiflags & AI_STAND_GROUND))
// AttackFinished (self, 1);
}
int IsClient(int self)
{
edict_t * ed;
if (!self || self>sv.max_edicts)
return false;
ed = EDICT_NUM(self);
return ((int)(ed->v.flags) & FL_CLIENT);
}
/*
void FoundTarget (edict_t *self)
{
// let other monsters see this monster for a while
if (IsClient(self->v.enemy))
{
pr_global_struct->
SetGlobal("sight_entity",EDICT_NUM(self));
level.sight_entity = self;
level.sight_entity_framenum = level.framenum;
level.sight_entity->light_level = 128;
}
self->show_hostile = level.time + 1; // wake up other monsters
//VectorCopy(V(self->enemy)->v.origin, self->monsterinfo.last_sighting);
//self->monsterinfo.trail_time = level.time;
if (!self->combattarget)
{
HuntTarget (self);
return;
}
self->goalentity = self->movetarget = G_PickTarget(self->combattarget);
if (!self->movetarget)
{
self->goalentity = self->movetarget = self->enemy;
HuntTarget (self);
gi.dprintf("%s at %s, combattarget %s not found\n", self->classname, vtos(self->s.origin), self->combattarget);
return;
}
// clear out our combattarget, these are a one shot deal
self->combattarget = NULL;
self->monsterinfo.aiflags |= AI_COMBAT_POINT;
// clear the targetname, that point is ours!
self->movetarget->targetname = NULL;
self->monsterinfo.pausetime = 0;
// run for it
self->monsterinfo.run (self);
}
*/
void AddNextThink(edict_t *self, float time)
{
self->v.nextthink = pr_global_struct->time + time;
}
#define DELEGATE -120
#define SUBREMOVE 13 //work?
void NexthinkRemove(edict_t *self, float time)
{
self->v.nextthink = pr_global_struct->time + time;
self->v.think = DELEGATE;
self->v.weapon = SUBREMOVE;
}
/*
void SV_Physics_Conveyor(edict_t *ent)
{
edict_t *player;
int i;
trace_t tr;
vec3_t v, move;
vec3_t point, end;
VectorScale(ent->v.movedir,10,v);
VectorScale(v,0.1,move);
for(i=0; i<sv.maxclients; i++)
{
player = sv_edict + 1 + i;
if(!player->inuse)
continue;
if(!player->groundentity)
continue;
if(player->groundentity != ent)
continue;
// Look below player; make sure he's on a conveyor
VectorCopy(player->s.origin,point);
point[2] += 1;
VectorCopy(point,end);
end[2] -= 256;
tr = trace (point, player->mins, player->maxs, end, player, MASK_SOLID);
// tr.ent HAS to be conveyor, but just in case we screwed something up:
if(tr.ent == ent)
{
if(tr.plane.normal[2] > 0) {
v[2] = ent->speed * sqrt(1.0 - tr.plane.normal[2]*tr.plane.normal[2]) /
tr.plane.normal[2];
if(DotProduct(ent->movedir,tr.plane.normal) > 0) {
// then we're moving down
v[2] = -v[2];
}
move[2] = v[2]*FRAMETIME;
}
VectorAdd(player->s.origin,move,end);
tr = gi.trace(player->s.origin,player->mins,player->maxs,end,player,player->clipmask);
VectorCopy(tr.endpos,player->s.origin);
gi.linkentity(player);
}
}
}*/