diff --git a/changelog.log b/changelog.log index 38056695..aa3e50e2 100644 --- a/changelog.log +++ b/changelog.log @@ -2,21 +2,17 @@ // FIXME //================================================== render.dll -1. Избавиться от pcx совсем -2. избавиться от LightImageScale engine.dll -1. +1. убить остатки .md2 platform.dll 1. научить rad суммировать цвета в dxt server.dll -1. убрать все энтити, оставить минимум, необходимый для работы client.dll -1. создать базовую версию библиотеки OK -2. разработать интерфейсы взаимодействия +1. разработать интерфейсы взаимодействия //================================================== // то, что уже готово diff --git a/editor/editor.plg b/editor/editor.plg index cb2e0b18..9fdd64da 100644 --- a/editor/editor.plg +++ b/editor/editor.plg @@ -6,6 +6,15 @@ --------------------Configuration: editor - Win32 Release--------------------

Command Lines

+Creating temporary file "C:\Temp\RSP1F64.bat" with contents +[ +@echo off +copy \XASH3D\src_main\!source\temp\editor\!release\editor.dll "D:\Xash3D\bin\editor.dll" +] +Creating command line "C:\Temp\RSP1F64.bat" +

Output Window

+Performing Custom Build Step on \XASH3D\src_main\!source\temp\editor\!release\editor.dll +‘Є®ЇЁа®ў ­® д ©«®ў: 1. diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index bb791d61..f0c22ed8 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -868,25 +868,8 @@ void CL_AddPacketEntities (frame_t *frame) effects |= EF_COLOR_SHELL; renderfx |= RF_SHELL_BLUE; } -//====== -// PMM - if (effects & EF_DOUBLE) - { - effects &= ~EF_DOUBLE; - effects |= EF_COLOR_SHELL; - renderfx |= RF_SHELL_DOUBLE; - } - if (effects & EF_HALF_DAMAGE) - { - effects &= ~EF_HALF_DAMAGE; - effects |= EF_COLOR_SHELL; - renderfx |= RF_SHELL_HALF_DAM; - } -// pmm -//====== //copy state to renderer - ent.prev.frame = cent->prev.frame; ent.backlerp = 1.0 - cl.lerpfrac; ent.alpha = s1->alpha; @@ -1017,11 +1000,6 @@ void CL_AddPacketEntities (frame_t *frame) V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1); else if (effects & EF_FLAG2) V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0); - else if (effects & EF_TAGTRAIL) //PGM - V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); //PGM - else if (effects & EF_TRACKERTRAIL) //PGM - V_AddLight (ent.origin, 225, -1.0, -1.0, -1.0); //PGM - continue; } @@ -1042,17 +1020,6 @@ void CL_AddPacketEntities (frame_t *frame) ent.alpha = 0.6; } - if (effects & EF_SPHERETRANS) - { - ent.flags |= RF_TRANSLUCENT; - // PMM - *sigh* yet more EF overloading - if (effects & EF_TRACKERTRAIL) - ent.alpha = 0.6; - else - ent.alpha = 0.3; - } -//pmm - // add to refresh list V_AddEntity (&ent); @@ -1106,26 +1073,12 @@ void CL_AddPacketEntities (frame_t *frame) // EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese! else if (effects & EF_BLASTER) { -// CL_BlasterTrail (cent->lerp_origin, ent.origin); -//PGM - if (effects & EF_TRACKER) // lame... problematic? - { - CL_BlasterTrail2 (cent->lerp_origin, ent.origin); - V_AddLight (ent.origin, 200, 0, 1, 0); - } - else - { - CL_BlasterTrail (cent->lerp_origin, ent.origin); - V_AddLight (ent.origin, 200, 1, 1, 0); - } -//PGM + CL_BlasterTrail (cent->lerp_origin, ent.origin); + V_AddLight (ent.origin, 200, 1, 1, 0); } else if (effects & EF_HYPERBLASTER) { - if (effects & EF_TRACKER) // PGM overloaded for blaster2. - V_AddLight (ent.origin, 200, 0, 1, 0); // PGM - else // PGM - V_AddLight (ent.origin, 200, 1, 1, 0); + V_AddLight (ent.origin, 200, 1, 1, 0); } else if (effects & EF_GIB) { @@ -1172,60 +1125,7 @@ void CL_AddPacketEntities (frame_t *frame) CL_FlagTrail (cent->lerp_origin, ent.origin, 115); V_AddLight (ent.origin, 225, 0.1, 0.1, 1); } -//====== -//ROGUE - else if (effects & EF_TAGTRAIL) - { - CL_TagTrail (cent->lerp_origin, ent.origin, 220); - V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); - } - else if (effects & EF_TRACKERTRAIL) - { - if (effects & EF_TRACKER) - { - float intensity; - - intensity = 50 + (500 * (sin(cl.time/500.0) + 1.0)); - V_AddLight (ent.origin, intensity, -1.0, -1.0, -1.0); - } - else - { - CL_Tracker_Shell (cent->lerp_origin); - V_AddLight (ent.origin, 155, -1.0, -1.0, -1.0); - } - } - else if (effects & EF_TRACKER) - { - CL_TrackerTrail (cent->lerp_origin, ent.origin, 0); - V_AddLight (ent.origin, 200, -1, -1, -1); - } - // RAFAEL - else if (effects & EF_GREENGIB) - { - CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); - } - // RAFAEL - else if (effects & EF_IONRIPPER) - { - CL_IonripperTrail (cent->lerp_origin, ent.origin); - V_AddLight (ent.origin, 100, 1, 0.5, 0.5); - } - // RAFAEL - else if (effects & EF_BLUEHYPERBLASTER) - { - V_AddLight (ent.origin, 200, 0, 0, 1); - } - // RAFAEL - else if (effects & EF_PLASMA) - { - if (effects & EF_ANIM_ALLFAST) - { - CL_BlasterTrail (cent->lerp_origin, ent.origin); - } - V_AddLight (ent.origin, 130, 1, 0.5, 0.5); - } } - VectorCopy (ent.origin, cent->lerp_origin); } } diff --git a/engine/client/cl_fx.c b/engine/client/cl_fx.c index 7a9fe858..055749ce 100644 --- a/engine/client/cl_fx.c +++ b/engine/client/cl_fx.c @@ -373,50 +373,6 @@ void CL_ParseMuzzleFlash (void) dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5; S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0); break; - -// ====================== -// PGM - case MZ_ETF_RIFLE: - dl->color[0] = 0.9;dl->color[1] = 0.7;dl->color[2] = 0; - S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/nail1.wav"), volume, ATTN_NORM, 0); - break; - case MZ_SHOTGUN2: - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0); - break; - case MZ_HEATBEAM: - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - dl->die = cl.time + 100; -// S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__l1a.wav"), volume, ATTN_NORM, 0); - break; - case MZ_BLASTER2: - dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0; - // FIXME - different sound for blaster2 ?? - S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0); - break; - case MZ_TRACKER: - // negative flashes handled the same in gl/soft until CL_AddDLights - dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1; - S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), volume, ATTN_NORM, 0); - break; - case MZ_NUKE1: - dl->color[0] = 1;dl->color[1] = 0;dl->color[2] = 0; - dl->die = cl.time + 100; - break; - case MZ_NUKE2: - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - dl->die = cl.time + 100; - break; - case MZ_NUKE4: - dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1; - dl->die = cl.time + 100; - break; - case MZ_NUKE8: - dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 1; - dl->die = cl.time + 100; - break; -// PGM -// ====================== } } @@ -443,9 +399,9 @@ void CL_ParseMuzzleFlash2 (void) // locate the origin AngleVectors (cl_entities[ent].current.angles, forward, right, NULL); - origin[0] = cl_entities[ent].current.origin[0] + forward[0] * monster_flash_offset[flash_number][0] + right[0] * monster_flash_offset[flash_number][1]; - origin[1] = cl_entities[ent].current.origin[1] + forward[1] * monster_flash_offset[flash_number][0] + right[1] * monster_flash_offset[flash_number][1]; - origin[2] = cl_entities[ent].current.origin[2] + forward[2] * monster_flash_offset[flash_number][0] + right[2] * monster_flash_offset[flash_number][1] + monster_flash_offset[flash_number][2]; + origin[0] = cl_entities[ent].current.origin[0] + forward[0] + right[0]; + origin[1] = cl_entities[ent].current.origin[1] + forward[1] + right[1]; + origin[2] = cl_entities[ent].current.origin[2] + forward[2] + right[2]; dl = CL_AllocDlight (ent); VectorCopy (origin, dl->origin); @@ -509,7 +465,6 @@ void CL_ParseMuzzleFlash2 (void) case MZ2_SUPERTANK_MACHINEGUN_4: case MZ2_SUPERTANK_MACHINEGUN_5: case MZ2_SUPERTANK_MACHINEGUN_6: - case MZ2_TURRET_MACHINEGUN: // PGM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); @@ -522,8 +477,6 @@ void CL_ParseMuzzleFlash2 (void) case MZ2_BOSS2_MACHINEGUN_L3: case MZ2_BOSS2_MACHINEGUN_L4: case MZ2_BOSS2_MACHINEGUN_L5: - case MZ2_CARRIER_MACHINEGUN_L1: // PMM - case MZ2_CARRIER_MACHINEGUN_L2: // PMM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); @@ -539,7 +492,6 @@ void CL_ParseMuzzleFlash2 (void) case MZ2_SOLDIER_BLASTER_6: case MZ2_SOLDIER_BLASTER_7: case MZ2_SOLDIER_BLASTER_8: - case MZ2_TURRET_BLASTER: // PGM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0); break; @@ -612,7 +564,6 @@ void CL_ParseMuzzleFlash2 (void) break; case MZ2_CHICK_ROCKET_1: - case MZ2_TURRET_ROCKET: // PGM dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2; S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0); break; @@ -631,10 +582,6 @@ void CL_ParseMuzzleFlash2 (void) case MZ2_BOSS2_ROCKET_2: case MZ2_BOSS2_ROCKET_3: case MZ2_BOSS2_ROCKET_4: - case MZ2_CARRIER_ROCKET_1: -// case MZ2_CARRIER_ROCKET_2: -// case MZ2_CARRIER_ROCKET_3: -// case MZ2_CARRIER_ROCKET_4: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2; S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0); break; @@ -648,157 +595,8 @@ void CL_ParseMuzzleFlash2 (void) break; case MZ2_GLADIATOR_RAILGUN_1: - // PMM - case MZ2_CARRIER_RAILGUN: - case MZ2_WIDOW_RAIL: - // pmm dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0; break; - -// --- Xian's shit starts --- - case MZ2_MAKRON_BFG: - dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5; - //S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/bfg_fire.wav"), 1, ATTN_NORM, 0); - break; - - case MZ2_MAKRON_BLASTER_1: - case MZ2_MAKRON_BLASTER_2: - case MZ2_MAKRON_BLASTER_3: - case MZ2_MAKRON_BLASTER_4: - case MZ2_MAKRON_BLASTER_5: - case MZ2_MAKRON_BLASTER_6: - case MZ2_MAKRON_BLASTER_7: - case MZ2_MAKRON_BLASTER_8: - case MZ2_MAKRON_BLASTER_9: - case MZ2_MAKRON_BLASTER_10: - case MZ2_MAKRON_BLASTER_11: - case MZ2_MAKRON_BLASTER_12: - case MZ2_MAKRON_BLASTER_13: - case MZ2_MAKRON_BLASTER_14: - case MZ2_MAKRON_BLASTER_15: - case MZ2_MAKRON_BLASTER_16: - case MZ2_MAKRON_BLASTER_17: - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0); - break; - - case MZ2_JORG_MACHINEGUN_L1: - case MZ2_JORG_MACHINEGUN_L2: - case MZ2_JORG_MACHINEGUN_L3: - case MZ2_JORG_MACHINEGUN_L4: - case MZ2_JORG_MACHINEGUN_L5: - case MZ2_JORG_MACHINEGUN_L6: - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - CL_ParticleEffect (origin, vec3_origin, 0, 40); - CL_SmokeAndFlash(origin); - S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfire.wav"), 1, ATTN_NORM, 0); - break; - - case MZ2_JORG_MACHINEGUN_R1: - case MZ2_JORG_MACHINEGUN_R2: - case MZ2_JORG_MACHINEGUN_R3: - case MZ2_JORG_MACHINEGUN_R4: - case MZ2_JORG_MACHINEGUN_R5: - case MZ2_JORG_MACHINEGUN_R6: - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - CL_ParticleEffect (origin, vec3_origin, 0, 40); - CL_SmokeAndFlash(origin); - break; - - case MZ2_JORG_BFG_1: - dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5; - break; - - case MZ2_BOSS2_MACHINEGUN_R1: - case MZ2_BOSS2_MACHINEGUN_R2: - case MZ2_BOSS2_MACHINEGUN_R3: - case MZ2_BOSS2_MACHINEGUN_R4: - case MZ2_BOSS2_MACHINEGUN_R5: - case MZ2_CARRIER_MACHINEGUN_R1: // PMM - case MZ2_CARRIER_MACHINEGUN_R2: // PMM - - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - - CL_ParticleEffect (origin, vec3_origin, 0, 40); - CL_SmokeAndFlash(origin); - break; - -// ====== -// ROGUE - case MZ2_STALKER_BLASTER: - case MZ2_DAEDALUS_BLASTER: - case MZ2_MEDIC_BLASTER_2: - case MZ2_WIDOW_BLASTER: - case MZ2_WIDOW_BLASTER_SWEEP1: - case MZ2_WIDOW_BLASTER_SWEEP2: - case MZ2_WIDOW_BLASTER_SWEEP3: - case MZ2_WIDOW_BLASTER_SWEEP4: - case MZ2_WIDOW_BLASTER_SWEEP5: - case MZ2_WIDOW_BLASTER_SWEEP6: - case MZ2_WIDOW_BLASTER_SWEEP7: - case MZ2_WIDOW_BLASTER_SWEEP8: - case MZ2_WIDOW_BLASTER_SWEEP9: - case MZ2_WIDOW_BLASTER_100: - case MZ2_WIDOW_BLASTER_90: - case MZ2_WIDOW_BLASTER_80: - case MZ2_WIDOW_BLASTER_70: - case MZ2_WIDOW_BLASTER_60: - case MZ2_WIDOW_BLASTER_50: - case MZ2_WIDOW_BLASTER_40: - case MZ2_WIDOW_BLASTER_30: - case MZ2_WIDOW_BLASTER_20: - case MZ2_WIDOW_BLASTER_10: - case MZ2_WIDOW_BLASTER_0: - case MZ2_WIDOW_BLASTER_10L: - case MZ2_WIDOW_BLASTER_20L: - case MZ2_WIDOW_BLASTER_30L: - case MZ2_WIDOW_BLASTER_40L: - case MZ2_WIDOW_BLASTER_50L: - case MZ2_WIDOW_BLASTER_60L: - case MZ2_WIDOW_BLASTER_70L: - case MZ2_WIDOW_RUN_1: - case MZ2_WIDOW_RUN_2: - case MZ2_WIDOW_RUN_3: - case MZ2_WIDOW_RUN_4: - case MZ2_WIDOW_RUN_5: - case MZ2_WIDOW_RUN_6: - case MZ2_WIDOW_RUN_7: - case MZ2_WIDOW_RUN_8: - dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0; - S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0); - break; - - case MZ2_WIDOW_DISRUPTOR: - dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1; - S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), 1, ATTN_NORM, 0); - break; - - case MZ2_WIDOW_PLASMABEAM: - case MZ2_WIDOW2_BEAMER_1: - case MZ2_WIDOW2_BEAMER_2: - case MZ2_WIDOW2_BEAMER_3: - case MZ2_WIDOW2_BEAMER_4: - case MZ2_WIDOW2_BEAMER_5: - case MZ2_WIDOW2_BEAM_SWEEP_1: - case MZ2_WIDOW2_BEAM_SWEEP_2: - case MZ2_WIDOW2_BEAM_SWEEP_3: - case MZ2_WIDOW2_BEAM_SWEEP_4: - case MZ2_WIDOW2_BEAM_SWEEP_5: - case MZ2_WIDOW2_BEAM_SWEEP_6: - case MZ2_WIDOW2_BEAM_SWEEP_7: - case MZ2_WIDOW2_BEAM_SWEEP_8: - case MZ2_WIDOW2_BEAM_SWEEP_9: - case MZ2_WIDOW2_BEAM_SWEEP_10: - case MZ2_WIDOW2_BEAM_SWEEP_11: - dl->radius = 300 + (rand()&100); - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; - dl->die = cl.time + 200; - break; -// ROGUE -// ====== - -// --- Xian's shit ends --- - } } diff --git a/engine/client/cl_newfx.c b/engine/client/cl_newfx.c index 5d753e3c..b3572dd4 100644 --- a/engine/client/cl_newfx.c +++ b/engine/client/cl_newfx.c @@ -775,53 +775,6 @@ void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int color, int count, int m } } -void CL_ParticleSteamEffect2 (cl_sustain_t *self) -//vec3_t org, vec3_t dir, int color, int count, int magnitude) -{ - int i, j; - cparticle_t *p; - float d; - vec3_t r, u; - vec3_t dir; - -// vectoangles2 (dir, angle_dir); -// AngleVectors (angle_dir, f, r, u); - - VectorCopy (self->dir, dir); - MakeNormalVectors (dir, r, u); - - for (i=0 ; icount ; i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->time = cl.time; - p->color = self->color + (rand()&7); - - for (j=0 ; j<3 ; j++) - { - p->org[j] = self->org[j] + self->magnitude*0.1*crand(); -// p->vel[j] = dir[j]*magnitude; - } - VectorScale (dir, self->magnitude, p->vel); - d = crand()*self->magnitude/3; - VectorMA (p->vel, d, r, p->vel); - d = crand()*self->magnitude/3; - VectorMA (p->vel, d, u, p->vel); - - p->accel[0] = p->accel[1] = 0; - p->accel[2] = -PARTICLE_GRAVITY/2; - p->alpha = 1.0; - - p->alphavel = -1.0 / (0.5 + frand()*0.3); - } - self->nextthink += self->thinkinterval; -} - /* =============== CL_TrackerTrail @@ -944,78 +897,6 @@ void CL_MonsterPlasma_Shell(vec3_t origin) } } -void CL_Widowbeamout (cl_sustain_t *self) -{ - vec3_t dir; - int i; - cparticle_t *p; - static int colortable[4] = {2*8,13*8,21*8,18*8}; - float ratio; - - ratio = 1.0 - (((float)self->endtime - (float)cl.time)/2100.0); - - for(i=0;i<300;i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - VectorClear (p->accel); - - p->time = cl.time; - - p->alpha = 1.0; - p->alphavel = INSTANT_PARTICLE; - p->color = colortable[rand()&3]; - - dir[0] = crand(); - dir[1] = crand(); - dir[2] = crand(); - VectorNormalize(dir); - - VectorMA(self->org, (45.0 * ratio), dir, p->org); -// VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org); - } -} - -void CL_Nukeblast (cl_sustain_t *self) -{ - vec3_t dir; - int i; - cparticle_t *p; - static int colortable[4] = {110, 112, 114, 116}; - float ratio; - - ratio = 1.0 - (((float)self->endtime - (float)cl.time)/1000.0); - - for(i=0;i<700;i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - VectorClear (p->accel); - - p->time = cl.time; - - p->alpha = 1.0; - p->alphavel = INSTANT_PARTICLE; - p->color = colortable[rand()&3]; - - dir[0] = crand(); - dir[1] = crand(); - dir[2] = crand(); - VectorNormalize(dir); - - VectorMA(self->org, (200.0 * ratio), dir, p->org); -// VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org); - } -} - void CL_WidowSplash (vec3_t org) { static int colortable[4] = {2*8,13*8,21*8,18*8}; diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index f5ec5aa0..669c2840 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -67,14 +67,6 @@ typedef struct } laser_t; laser_t cl_lasers[MAX_LASERS]; -//ROGUE -cl_sustain_t cl_sustains[MAX_SUSTAINS]; -//ROGUE - -//PGM -extern void CL_TeleportParticles (vec3_t org); -//PGM - void CL_BlasterParticles (vec3_t org, vec3_t dir); void CL_ExplosionParticles (vec3_t org); void CL_BFGExplosionParticles (vec3_t org); @@ -105,13 +97,6 @@ model_t *cl_mod_explo4; model_t *cl_mod_bfg_explo; model_t *cl_mod_plasmaexplo; -//ROGUE -struct sfx_s *cl_sfx_lightning; -struct sfx_s *cl_sfx_disrexp; -model_t *cl_mod_lightning; -model_t *cl_mod_explo4_big; - -//ROGUE /* ================= CL_RegisterTEntSounds @@ -123,7 +108,6 @@ void CL_RegisterTEntSounds (void) char name[MAX_QPATH]; // PMM - version stuff -// Msg ("%s\n", ROGUE_VERSION_STRING); // PMM cl_sfx_ric1 = S_RegisterSound ("world/ric1.wav"); cl_sfx_ric2 = S_RegisterSound ("world/ric2.wav"); @@ -148,15 +132,6 @@ void CL_RegisterTEntSounds (void) sprintf (name, "player/step%i.wav", i+1); cl_sfx_footsteps[i] = S_RegisterSound (name); } - -//PGM - cl_sfx_lightning = S_RegisterSound ("weapons/tesla.wav"); - cl_sfx_disrexp = S_RegisterSound ("weapons/disrupthit.wav"); - // version stuff -// sprintf (name, "weapons/sound%d.wav", ROGUE_VERSION_ID); -// if (name[0] == 'w') -// name[0] = 'W'; -//PGM } /* @@ -178,9 +153,6 @@ void CL_RegisterTEntModels (void) re->RegisterPic ("a_bullets"); re->RegisterPic ("i_health"); re->RegisterPic ("a_grenades"); - - cl_mod_explo4_big = re->RegisterModel ("sprites/s_explo3.spr"); - cl_mod_lightning = re->RegisterModel ("sprites/lgtning.spr"); } /* @@ -193,11 +165,6 @@ void CL_ClearTEnts (void) memset (cl_beams, 0, sizeof(cl_beams)); memset (cl_explosions, 0, sizeof(cl_explosions)); memset (cl_lasers, 0, sizeof(cl_lasers)); - -//ROGUE - memset (cl_playerbeams, 0, sizeof(cl_playerbeams)); - memset (cl_sustains, 0, sizeof(cl_sustains)); -//ROGUE } /* @@ -378,61 +345,6 @@ int CL_ParseBeam2 (model_t *model) return ent; } -// ROGUE -/* -================= -CL_ParsePlayerBeam - - adds to the cl_playerbeam array instead of the cl_beams array -================= -*/ -int CL_ParsePlayerBeam (model_t *model) -{ - int ent; - vec3_t start, end, offset; - beam_t *b; - int i; - - ent = MSG_ReadShort (&net_message); - - MSG_ReadPos (&net_message, start); - MSG_ReadPos (&net_message, end); - MSG_ReadPos (&net_message, offset); - - // override any beam with the same entity - // PMM - For player beams, we only want one per player (entity) so.. - for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++) - { - if (b->entity == ent) - { - b->entity = ent; - b->model = model; - b->endtime = cl.time + 200; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - VectorCopy (offset, b->offset); - return ent; - } - } - -// find a free beam - for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++) - { - if (!b->model || b->endtime < cl.time) - { - b->entity = ent; - b->model = model; - b->endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams - VectorCopy (start, b->start); - VectorCopy (end, b->end); - VectorCopy (offset, b->offset); - return ent; - } - } - Msg ("beam list overflow!\n"); - return ent; -} -//rogue - /* ================= CL_ParseLightning @@ -518,138 +430,6 @@ void CL_ParseLaser (int colors) } } -//============= -//ROGUE -void CL_ParseSteam (void) -{ - vec3_t pos, dir; - int id, i; - int r; - int cnt; - int color; - int magnitude; - cl_sustain_t *s, *free_sustain; - - id = MSG_ReadShort (&net_message); // an id of -1 is an instant effect - if (id != -1) // sustains - { -// Msg ("Sustain effect id %d\n", id); - free_sustain = NULL; - for (i=0, s=cl_sustains; iid == 0) - { - free_sustain = s; - break; - } - } - if (free_sustain) - { - s->id = id; - s->count = MSG_ReadByte (&net_message); - MSG_ReadPos (&net_message, s->org); - MSG_ReadDir (&net_message, s->dir); - r = MSG_ReadByte (&net_message); - s->color = r & 0xff; - s->magnitude = MSG_ReadShort (&net_message); - s->endtime = cl.time + MSG_ReadLong (&net_message); - s->think = CL_ParticleSteamEffect2; - s->thinkinterval = 100; - s->nextthink = cl.time; - } - else - { -// Msg ("No free sustains!\n"); - // FIXME - read the stuff anyway - cnt = MSG_ReadByte (&net_message); - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); - r = MSG_ReadByte (&net_message); - magnitude = MSG_ReadShort (&net_message); - magnitude = MSG_ReadLong (&net_message); // really interval - } - } - else // instant - { - cnt = MSG_ReadByte (&net_message); - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); - r = MSG_ReadByte (&net_message); - magnitude = MSG_ReadShort (&net_message); - color = r & 0xff; - CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude); -// S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); - } -} - -void CL_ParseWidow (void) -{ - vec3_t pos; - int id, i; - cl_sustain_t *s, *free_sustain; - - id = MSG_ReadShort (&net_message); - - free_sustain = NULL; - for (i=0, s=cl_sustains; iid == 0) - { - free_sustain = s; - break; - } - } - if (free_sustain) - { - s->id = id; - MSG_ReadPos (&net_message, s->org); - s->endtime = cl.time + 2100; - s->think = CL_Widowbeamout; - s->thinkinterval = 1; - s->nextthink = cl.time; - } - else // no free sustains - { - // FIXME - read the stuff anyway - MSG_ReadPos (&net_message, pos); - } -} - -void CL_ParseNuke (void) -{ - vec3_t pos; - int i; - cl_sustain_t *s, *free_sustain; - - free_sustain = NULL; - for (i=0, s=cl_sustains; iid == 0) - { - free_sustain = s; - break; - } - } - if (free_sustain) - { - s->id = 21000; - MSG_ReadPos (&net_message, s->org); - s->endtime = cl.time + 1000; - s->think = CL_Nukeblast; - s->thinkinterval = 1; - s->nextthink = cl.time; - } - else // no free sustains - { - // FIXME - read the stuff anyway - MSG_ReadPos (&net_message, pos); - } -} - -//ROGUE -//============= - - /* ================= CL_ParseTEnt @@ -666,7 +446,6 @@ void CL_ParseTEnt (void) int color; int r; int ent; - int magnitude; type = MSG_ReadByte (&net_message); @@ -843,10 +622,8 @@ void CL_ParseTEnt (void) break; case TE_EXPLOSION1: - case TE_EXPLOSION1_BIG: // PMM case TE_ROCKET_EXPLOSION: case TE_ROCKET_EXPLOSION_WATER: - case TE_EXPLOSION1_NP: // PMM MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); @@ -859,13 +636,10 @@ void CL_ParseTEnt (void) ex->lightcolor[1] = 0.5; ex->lightcolor[2] = 0.5; ex->ent.angles[1] = rand() % 360; - if (type != TE_EXPLOSION1_BIG) // PMM - ex->ent.model = cl_mod_explo4; // PMM - else ex->ent.model = cl_mod_explo4_big; + ex->ent.model = cl_mod_explo4; // PMM ex->baseframe = 0; ex->frames = 8; - if ((type != TE_EXPLOSION1_BIG) && (type != TE_EXPLOSION1_NP)) // PMM - CL_ExplosionParticles (pos); // PMM + CL_ExplosionParticles (pos); // PMM if (type == TE_ROCKET_EXPLOSION_WATER) S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0); else @@ -947,71 +721,10 @@ void CL_ParseTEnt (void) CL_ParticleEffect2 (pos, dir, 0xdf, 30); break; - // RAFAEL - case TE_TUNNEL_SPARKS: - cnt = MSG_ReadByte (&net_message); - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); - color = MSG_ReadByte (&net_message); - CL_ParticleEffect3 (pos, dir, color, cnt); - break; - -//============= -//PGM - // PMM -following code integrated for flechette (different color) - case TE_BLASTER2: // green blaster hitting wall - case TE_FLECHETTE: // flechette - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); - - // PMM - if (type == TE_BLASTER2) - CL_BlasterParticles2 (pos, dir, 0xd0); - else - CL_BlasterParticles2 (pos, dir, 0x6f); // 75 - - ex = CL_AllocExplosion (); - VectorCopy (pos, ex->ent.origin); - ex->ent.angles[0] = acos(dir[2])/M_PI*180; - // PMM - fixed to correct for pitch of 0 - if (dir[0]) - ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180; - else if (dir[1] > 0) - ex->ent.angles[1] = 90; - else if (dir[1] < 0) - ex->ent.angles[1] = 270; - else - ex->ent.angles[1] = 0; - - ex->type = ex_misc; - ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT; - - // PMM - if (type == TE_BLASTER2) - ex->ent.skinnum = 1; - else // flechette - ex->ent.skinnum = 2; - - ex->start = cl.frame.servertime - 100; - ex->light = 150; - // PMM - if (type == TE_BLASTER2) - ex->lightcolor[1] = 1; - else // flechette - { - ex->lightcolor[0] = 0.19; - ex->lightcolor[1] = 0.41; - ex->lightcolor[2] = 0.75; - } - ex->ent.model = cl_mod_explode; - ex->frames = 4; - S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); - break; - - - case TE_LIGHTNING: - ent = CL_ParseLightning (cl_mod_lightning); - S_StartSound (NULL, ent, CHAN_WEAPON, cl_sfx_lightning, 1, ATTN_NORM, 0); + case TE_FLASHLIGHT: + MSG_ReadPos(&net_message, pos); + ent = MSG_ReadShort(&net_message); + CL_Flashlight(ent, pos); break; case TE_DEBUGTRAIL: @@ -1020,138 +733,14 @@ void CL_ParseTEnt (void) CL_DebugTrail (pos, pos2); break; - case TE_PLAIN_EXPLOSION: + // RAFAEL + case TE_TUNNEL_SPARKS: + cnt = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, pos); - - ex = CL_AllocExplosion (); - VectorCopy (pos, ex->ent.origin); - ex->type = ex_poly; - ex->ent.flags = RF_FULLBRIGHT; - ex->start = cl.frame.servertime - 100; - ex->light = 350; - ex->lightcolor[0] = 1.0; - ex->lightcolor[1] = 0.5; - ex->lightcolor[2] = 0.5; - ex->ent.angles[1] = rand() % 360; - ex->ent.model = cl_mod_explo4; - ex->baseframe = 0; - ex->frames = 6; - if (type == TE_ROCKET_EXPLOSION_WATER) - S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0); - else - S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0); - break; - - case TE_FLASHLIGHT: - MSG_ReadPos(&net_message, pos); - ent = MSG_ReadShort(&net_message); - CL_Flashlight(ent, pos); - break; - - case TE_FORCEWALL: - MSG_ReadPos(&net_message, pos); - MSG_ReadPos(&net_message, pos2); + MSG_ReadDir (&net_message, dir); color = MSG_ReadByte (&net_message); - CL_ForceWall(pos, pos2, color); + CL_ParticleEffect3 (pos, dir, color, cnt); break; - - case TE_HEATBEAM: - break; - - case TE_MONSTER_HEATBEAM: - break; - - case TE_HEATBEAM_SPARKS: -// cnt = MSG_ReadByte (&net_message); - cnt = 50; - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); -// r = MSG_ReadByte (&net_message); -// magnitude = MSG_ReadShort (&net_message); - r = 8; - magnitude = 60; - color = r & 0xff; - CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude); - S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); - break; - - case TE_HEATBEAM_STEAM: -// cnt = MSG_ReadByte (&net_message); - cnt = 20; - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); -// r = MSG_ReadByte (&net_message); -// magnitude = MSG_ReadShort (&net_message); -// color = r & 0xff; - color = 0xe0; - magnitude = 60; - CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude); - S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); - break; - - case TE_STEAM: - CL_ParseSteam(); - break; - - case TE_BUBBLETRAIL2: -// cnt = MSG_ReadByte (&net_message); - cnt = 8; - MSG_ReadPos (&net_message, pos); - MSG_ReadPos (&net_message, pos2); - CL_BubbleTrail2 (pos, pos2, cnt); - S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); - break; - - case TE_MOREBLOOD: - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); - CL_ParticleEffect (pos, dir, 0xe8, 250); - break; - - case TE_CHAINFIST_SMOKE: - dir[0]=0; dir[1]=0; dir[2]=1; - MSG_ReadPos(&net_message, pos); - CL_ParticleSmokeEffect (pos, dir, 0, 20, 20); - break; - - case TE_ELECTRIC_SPARKS: - MSG_ReadPos (&net_message, pos); - MSG_ReadDir (&net_message, dir); -// CL_ParticleEffect (pos, dir, 109, 40); - CL_ParticleEffect (pos, dir, 0x75, 40); - //FIXME : replace or remove this sound - S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); - break; - - case TE_TRACKER_EXPLOSION: - MSG_ReadPos (&net_message, pos); - CL_ColorFlash (pos, 0, 150, -1, -1, -1); - CL_ColorExplosionParticles (pos, 0, 1); -// CL_Tracker_Explode (pos); - S_StartSound (pos, 0, 0, cl_sfx_disrexp, 1, ATTN_NORM, 0); - break; - - case TE_TELEPORT_EFFECT: - case TE_DBALL_GOAL: - MSG_ReadPos (&net_message, pos); - CL_TeleportParticles (pos); - break; - - case TE_WIDOWBEAMOUT: - CL_ParseWidow (); - break; - - case TE_NUKEBLAST: - CL_ParseNuke (); - break; - - case TE_WIDOWSPLASH: - MSG_ReadPos (&net_message, pos); - CL_WidowSplash (pos); - break; -//PGM -//============== - default: Com_Error (ERR_DROP, "CL_ParseTEnt: bad type"); } @@ -1221,214 +810,18 @@ void CL_AddBeams (void) d = VectorNormalize(dist); memset (&ent, 0, sizeof(ent)); - if (b->model == cl_mod_lightning) - { - model_length = 35.0; - d-= 20.0; // correction so it doesn't end in middle of tesla - } - else - { - model_length = 30.0; - } + model_length = 30.0; steps = ceil(d/model_length); len = (d-model_length)/(steps-1); - // PMM - special case for lightning model .. if the real length is shorter than the model, - // flip it around & draw it from the end to the start. This prevents the model from going - // through the tesla mine (instead it goes through the target) - if ((b->model == cl_mod_lightning) && (d <= model_length)) - { -// Msg ("special case\n"); - VectorCopy (b->end, ent.origin); - // offset to push beam outside of tesla model (negative because dist is from end to start - // for this beam) -// for (j=0 ; j<3 ; j++) -// ent.origin[j] -= dist[j]*10.0; - ent.model = b->model; - ent.flags = RF_FULLBRIGHT; - ent.angles[0] = pitch; - ent.angles[1] = yaw; - ent.angles[2] = rand()%360; - V_AddEntity (&ent); - return; - } while (d > 0) { VectorCopy (org, ent.origin); ent.model = b->model; - if (b->model == cl_mod_lightning) - { - ent.flags = RF_FULLBRIGHT; - ent.angles[0] = -pitch; - ent.angles[1] = yaw + 180.0; - ent.angles[2] = rand()%360; - } - else - { - ent.angles[0] = pitch; - ent.angles[1] = yaw; - ent.angles[2] = rand()%360; - } - -// Msg("B: %d -> %d\n", b->entity, b->dest_entity); - V_AddEntity (&ent); - - for (j=0 ; j<3 ; j++) - org[j] += dist[j]*len; - d -= model_length; - } - } -} - - -/* -// Msg ("Endpoint: %f %f %f\n", b->end[0], b->end[1], b->end[2]); -// Msg ("Pred View Angles: %f %f %f\n", cl.predicted_angles[0], cl.predicted_angles[1], cl.predicted_angles[2]); -// Msg ("Act View Angles: %f %f %f\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2]); -// VectorCopy (cl.predicted_origin, b->start); -// b->start[2] += 22; // adjust for view height -// if (fabs(cl.refdef.vieworg[2] - b->start[2]) >= 10) { -// b->start[2] = cl.refdef.vieworg[2]; -// } - -// Msg ("Time: %d %d %f\n", cl.time, cls.realtime, cls.frametime); -*/ - -extern cvar_t *hand; - -/* -================= -ROGUE - draw player locked beams -CL_AddPlayerBeams -================= -*/ -void CL_AddPlayerBeams (void) -{ - int i,j; - beam_t *b; - vec3_t dist, org; - float d; - entity_t ent; - float yaw, pitch; - float forward; - float len, steps; - float model_length; - - float hand_multiplier; - -//PMM - if (hand) - { - if (hand->value == 2) - hand_multiplier = 0; - else if (hand->value == 1) - hand_multiplier = -1; - else - hand_multiplier = 1; - } - else - { - hand_multiplier = 1; - } -//PMM - -// update beams - for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++) - { - if (!b->model || b->endtime < cl.time) - continue; - - // if coming from the player, update the start position - if (b->entity == cl.playernum+1) // entity 0 is the world - { - VectorCopy (cl.refdef.vieworg, b->start); - b->start[2] -= 22; // adjust for view height - } - VectorAdd (b->start, b->offset, org); - - // calculate pitch and yaw - VectorSubtract (b->end, org, dist); - - if (dist[1] == 0 && dist[0] == 0) - { - yaw = 0; - if (dist[2] > 0) - pitch = 90; - else - pitch = 270; - } - else - { - // PMM - fixed to correct for pitch of 0 - if (dist[0]) - yaw = (atan2(dist[1], dist[0]) * 180 / M_PI); - else if (dist[1] > 0) - yaw = 90; - else - yaw = 270; - if (yaw < 0) - yaw += 360; - - forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]); - pitch = (atan2(dist[2], forward) * -180.0 / M_PI); - if (pitch < 0) - pitch += 360.0; - } - - // add new entities for the beams - d = VectorNormalize(dist); - - memset (&ent, 0, sizeof(ent)); - if (b->model == cl_mod_lightning) - { - model_length = 35.0; - d-= 20.0; // correction so it doesn't end in middle of tesla - } - else - { - model_length = 30.0; - } - steps = ceil(d/model_length); - len = (d-model_length)/(steps-1); - - // PMM - special case for lightning model .. if the real length is shorter than the model, - // flip it around & draw it from the end to the start. This prevents the model from going - // through the tesla mine (instead it goes through the target) - if ((b->model == cl_mod_lightning) && (d <= model_length)) - { -// Msg ("special case\n"); - VectorCopy (b->end, ent.origin); - // offset to push beam outside of tesla model (negative because dist is from end to start - // for this beam) -// for (j=0 ; j<3 ; j++) -// ent.origin[j] -= dist[j]*10.0; - ent.model = b->model; - ent.flags = RF_FULLBRIGHT; ent.angles[0] = pitch; ent.angles[1] = yaw; ent.angles[2] = rand()%360; - V_AddEntity (&ent); - return; - } - while (d > 0) - { - VectorCopy (org, ent.origin); - ent.model = b->model; - if (b->model == cl_mod_lightning) - { - ent.flags = RF_FULLBRIGHT; - ent.angles[0] = -pitch; - ent.angles[1] = yaw + 180.0; - ent.angles[2] = rand()%360; - } - else - { - ent.angles[0] = pitch; - ent.angles[1] = yaw; - ent.angles[2] = rand()%360; - } -// Msg("B: %d -> %d\n", b->entity, b->dest_entity); V_AddEntity (&ent); for (j=0 ; j<3 ; j++) @@ -1558,25 +951,6 @@ void CL_AddLasers (void) } } -/* PMM - CL_Sustains */ -void CL_ProcessSustain () -{ - cl_sustain_t *s; - int i; - - for (i=0, s=cl_sustains; i< MAX_SUSTAINS; i++, s++) - { - if (s->id) - if ((s->endtime >= cl.time) && (cl.time >= s->nextthink)) - { -// Msg ("think %d %d %d\n", cl.time, s->nextthink, s->thinkinterval); - s->think (s); - } - else if (s->endtime < cl.time) - s->id = 0; - } -} - /* ================= CL_AddTEnts @@ -1585,10 +959,6 @@ CL_AddTEnts void CL_AddTEnts (void) { CL_AddBeams (); - // PMM - draw plasma beams - CL_AddPlayerBeams (); CL_AddExplosions (); CL_AddLasers (); - // PMM - set up sustain - CL_ProcessSustain(); } diff --git a/engine/client/client.h b/engine/client/client.h index 99f99389..f3f3c406 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -314,25 +314,6 @@ bool CL_CheckOrDownloadFile (char *filename); void CL_AddNetgraph (void); -//ROGUE -typedef struct cl_sustain -{ - int id; - int type; - int endtime; - int nextthink; - int thinkinterval; - vec3_t org; - vec3_t dir; - int color; - int count; - int magnitude; - void (*think)(struct cl_sustain *self); -} cl_sustain_t; - -#define MAX_SUSTAINS 32 -void CL_ParticleSteamEffect2(cl_sustain_t *self); - void CL_TeleporterParticles (entity_state_t *ent); void CL_ParticleEffect (vec3_t org, vec3_t dir, int color, int count); void CL_ParticleEffect2 (vec3_t org, vec3_t dir, int color, int count); @@ -400,8 +381,6 @@ void CL_Tracker_Shell(vec3_t origin); void CL_MonsterPlasma_Shell(vec3_t origin); void CL_ColorExplosionParticles (vec3_t org, int color, int run); void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude); -void CL_Widowbeamout (cl_sustain_t *self); -void CL_Nukeblast (cl_sustain_t *self); void CL_WidowSplash (vec3_t org); // PGM // ======== diff --git a/engine/common/menu.c b/engine/common/menu.c index 66f98b5d..9db90f7b 100644 --- a/engine/common/menu.c +++ b/engine/common/menu.c @@ -1596,121 +1596,6 @@ static const char *xatcredits[] = 0 }; -static const char *roguecredits[] = -{ - "+QUAKE II MISSION PACK 2: GROUND ZERO", - "+BY", - "+ROGUE ENTERTAINMENT, INC.", - "", - "+PRODUCED BY", - "Jim Molinets", - "", - "+PROGRAMMING", - "Peter Mack", - "Patrick Magruder", - "", - "+LEVEL DESIGN", - "Jim Molinets", - "Cameron Lamprecht", - "Berenger Fish", - "Robert Selitto", - "Steve Tietze", - "Steve Thoms", - "", - "+ART DIRECTION", - "Rich Fleider", - "", - "+ART", - "Rich Fleider", - "Steve Maines", - "Won Choi", - "", - "+ANIMATION SEQUENCES", - "Creat Studios", - "Steve Maines", - "", - "+ADDITIONAL LEVEL DESIGN", - "Rich Fleider", - "Steve Maines", - "Peter Mack", - "", - "+SOUND", - "James Grunke", - "", - "+GROUND ZERO THEME", - "+AND", - "+MUSIC BY", - "Sonic Mayhem", - "", - "+VWEP MODELS", - "Brent \"Hentai\" Dill", - "", - "", - "", - "+SPECIAL THANKS", - "+TO", - "+OUR FRIENDS AT ID SOFTWARE", - "", - "John Carmack", - "John Cash", - "Brian Hook", - "Adrian Carmack", - "Kevin Cloud", - "Paul Steed", - "Tim Willits", - "Christian Antkow", - "Paul Jaquays", - "Brandon James", - "Todd Hollenshead", - "Barrett (Bear) Alexander", - "Katherine Anna Kang", - "Donna Jackson", - "Dave \"Zoid\" Kirsch", - "", - "", - "", - "+THANKS TO ACTIVISION", - "+IN PARTICULAR:", - "", - "Marty Stratton", - "Henk Hartong", - "Mitch Lasky", - "Steve Rosenthal", - "Steve Elwell", - "", - "+AND THE GAME TESTERS", - "", - "The Ranger Clan", - "Dave \"Zoid\" Kirsch", - "Nihilistic Software", - "Robert Duffy", - "", - "And Countless Others", - "", - "", - "", - "Quake II Mission Pack 2: Ground Zero", - "(tm) (C)1998 Id Software, Inc. All", - "Rights Reserved. Developed by Rogue", - "Entertainment, Inc. for Id Software,", - "Inc. Distributed by Activision Inc.", - "under license. Quake(R) is a", - "registered trademark of Id Software,", - "Inc. Quake II Mission Pack 2: Ground", - "Zero(tm), Quake II(tm), the Id", - "Software name, the \"Q II\"(tm) logo", - "and id(tm) logo are trademarks of Id", - "Software, Inc. Activision(R) is a", - "registered trademark of Activision,", - "Inc. Rogue(R) is a registered", - "trademark of Rogue Entertainment,", - "Inc. All other trademarks and trade", - "names are properties of their", - "respective owners.", - 0 -}; - - void M_Credits_MenuDraw( void ) { int i, y; @@ -2354,44 +2239,10 @@ void StartServerActionFunc( void *self ) Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) ); Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) ); Cvar_Set("hostname", s_hostname_field.buffer ); -// Cvar_SetValue ("deathmatch", !s_rules_box.curvalue ); -// Cvar_SetValue ("coop", s_rules_box.curvalue ); - -//PGM - if(s_rules_box.curvalue < 2) - { - Cvar_SetValue ("deathmatch", !s_rules_box.curvalue ); - Cvar_SetValue ("coop", s_rules_box.curvalue ); - Cvar_SetValue ("gamerules", 0 ); - } - else - { - Cvar_SetValue ("deathmatch", 1 ); // deathmatch is always true for rogue games, right? - Cvar_SetValue ("coop", 0 ); // FIXME - this might need to depend on which game we're running - Cvar_SetValue ("gamerules", s_rules_box.curvalue ); - } -//PGM + Cvar_SetValue ("deathmatch", !s_rules_box.curvalue ); + Cvar_SetValue ("coop", s_rules_box.curvalue ); spot = NULL; - if (s_rules_box.curvalue == 1) // PGM - { - if(strcasecmp(startmap, "bunk1") == 0) - spot = "start"; - else if(strcasecmp(startmap, "mintro") == 0) - spot = "start"; - else if(strcasecmp(startmap, "fact1") == 0) - spot = "start"; - else if(strcasecmp(startmap, "power1") == 0) - spot = "pstart"; - else if(strcasecmp(startmap, "biggun") == 0) - spot = "bstart"; - else if(strcasecmp(startmap, "hangar1") == 0) - spot = "unitstart"; - else if(strcasecmp(startmap, "city1") == 0) - spot = "unitstart"; - else if(strcasecmp(startmap, "boss1") == 0) - spot = "bosstart"; - } if (spot) { @@ -2746,13 +2597,6 @@ static menulist_s s_infinite_ammo_box; static menulist_s s_fixed_fov_box; static menulist_s s_quad_drop_box; -//ROGUE -static menulist_s s_no_mines_box; -static menulist_s s_no_nukes_box; -static menulist_s s_stack_double_box; -static menulist_s s_no_spheres_box; -//ROGUE - static void DMFlagCallback( void *self ) { menulist_s *f = ( menulist_s * ) self; diff --git a/engine/engine.dsp b/engine/engine.dsp index 9aaef85f..f9c36faa 100644 --- a/engine/engine.dsp +++ b/engine/engine.dsp @@ -202,10 +202,6 @@ SOURCE=.\common\keys.c # End Source File # Begin Source File -SOURCE=..\server\m_flash.c -# End Source File -# Begin Source File - SOURCE=.\common\md4.c # End Source File # Begin Source File diff --git a/platform/imglib.c b/platform/imglib.c index 84c1d4d5..1778b26a 100644 --- a/platform/imglib.c +++ b/platform/imglib.c @@ -1397,7 +1397,7 @@ loading and unpack to rgba any known image rgbdata_t *FS_LoadImage(const char *filename, char *buffer, int buffsize ) { imageformat_t *format; - char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; + char *suf[6] = {"ft", "bk", "rt", "lf", "up", "dn"}; char path[128], loadname[128], texname[128]; int i, filesize = 0; byte *f; diff --git a/public/const.h b/public/const.h index 3f793363..a1a0f943 100644 --- a/public/const.h +++ b/public/const.h @@ -98,25 +98,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define RF_SHELL_RED 1024 #define RF_SHELL_GREEN 2048 #define RF_SHELL_BLUE 4096 - -//ROGUE #define RF_IR_VISIBLE 0x00008000 // 32768 #define RF_SHELL_DOUBLE 0x00010000 // 65536 #define RF_SHELL_HALF_DAM 0x00020000 #define RF_USE_DISGUISE 0x00040000 -//ROGUE //lazarus #define RF_VAMPIRE 0x00080000 // 524288 // player_state_t->refdef flags #define RDF_UNDERWATER 1 // warp the screen as apropriate -#define RDF_NOWORLDMODEL 2 // used for player configuration screen - -//ROGUE +#define RDF_NOWORLDMODEL 2 // used for player configuration screen #define RDF_IRGOGGLES 4 #define RDF_UVGOGGLES 8 -//ROGUE #define RDF_BLOOM 32 #define RDF_PAIN 64 @@ -412,15 +406,6 @@ typedef struct #define EF_PLASMA 0x01000000 #define EF_TRAP 0x02000000 -//ROGUE -#define EF_TRACKER 0x04000000 -#define EF_DOUBLE 0x08000000 -#define EF_SPHERETRANS 0x10000000 -#define EF_TAGTRAIL 0x20000000 -#define EF_HALF_DAMAGE 0x40000000 -#define EF_TRACKERTRAIL 0x80000000 -//ROGUE - // // muzzle flashes / player effects // @@ -446,19 +431,6 @@ typedef struct #define MZ_PHALANX 18 #define MZ_SILENCED 128 // bit flag ORed with one of the above numbers -//ROGUE -#define MZ_ETF_RIFLE 30 -#define MZ_UNUSED 31 -#define MZ_SHOTGUN2 32 -#define MZ_HEATBEAM 33 -#define MZ_BLASTER2 34 -#define MZ_TRACKER 35 -#define MZ_NUKE1 36 -#define MZ_NUKE2 37 -#define MZ_NUKE4 38 -#define MZ_NUKE8 39 -//ROGUE - // // monster muzzle flashes // @@ -615,83 +587,6 @@ typedef struct #define MZ2_BOSS2_MACHINEGUN_R4 136 #define MZ2_BOSS2_MACHINEGUN_R5 137 -//ROGUE -#define MZ2_CARRIER_MACHINEGUN_L1 138 -#define MZ2_CARRIER_MACHINEGUN_R1 139 -#define MZ2_CARRIER_GRENADE 140 -#define MZ2_TURRET_MACHINEGUN 141 -#define MZ2_TURRET_ROCKET 142 -#define MZ2_TURRET_BLASTER 143 -#define MZ2_STALKER_BLASTER 144 -#define MZ2_DAEDALUS_BLASTER 145 -#define MZ2_MEDIC_BLASTER_2 146 -#define MZ2_CARRIER_RAILGUN 147 -#define MZ2_WIDOW_DISRUPTOR 148 -#define MZ2_WIDOW_BLASTER 149 -#define MZ2_WIDOW_RAIL 150 -#define MZ2_WIDOW_PLASMABEAM 151 // PMM - not used -#define MZ2_CARRIER_MACHINEGUN_L2 152 -#define MZ2_CARRIER_MACHINEGUN_R2 153 -#define MZ2_WIDOW_RAIL_LEFT 154 -#define MZ2_WIDOW_RAIL_RIGHT 155 -#define MZ2_WIDOW_BLASTER_SWEEP1 156 -#define MZ2_WIDOW_BLASTER_SWEEP2 157 -#define MZ2_WIDOW_BLASTER_SWEEP3 158 -#define MZ2_WIDOW_BLASTER_SWEEP4 159 -#define MZ2_WIDOW_BLASTER_SWEEP5 160 -#define MZ2_WIDOW_BLASTER_SWEEP6 161 -#define MZ2_WIDOW_BLASTER_SWEEP7 162 -#define MZ2_WIDOW_BLASTER_SWEEP8 163 -#define MZ2_WIDOW_BLASTER_SWEEP9 164 -#define MZ2_WIDOW_BLASTER_100 165 -#define MZ2_WIDOW_BLASTER_90 166 -#define MZ2_WIDOW_BLASTER_80 167 -#define MZ2_WIDOW_BLASTER_70 168 -#define MZ2_WIDOW_BLASTER_60 169 -#define MZ2_WIDOW_BLASTER_50 170 -#define MZ2_WIDOW_BLASTER_40 171 -#define MZ2_WIDOW_BLASTER_30 172 -#define MZ2_WIDOW_BLASTER_20 173 -#define MZ2_WIDOW_BLASTER_10 174 -#define MZ2_WIDOW_BLASTER_0 175 -#define MZ2_WIDOW_BLASTER_10L 176 -#define MZ2_WIDOW_BLASTER_20L 177 -#define MZ2_WIDOW_BLASTER_30L 178 -#define MZ2_WIDOW_BLASTER_40L 179 -#define MZ2_WIDOW_BLASTER_50L 180 -#define MZ2_WIDOW_BLASTER_60L 181 -#define MZ2_WIDOW_BLASTER_70L 182 -#define MZ2_WIDOW_RUN_1 183 -#define MZ2_WIDOW_RUN_2 184 -#define MZ2_WIDOW_RUN_3 185 -#define MZ2_WIDOW_RUN_4 186 -#define MZ2_WIDOW_RUN_5 187 -#define MZ2_WIDOW_RUN_6 188 -#define MZ2_WIDOW_RUN_7 189 -#define MZ2_WIDOW_RUN_8 190 -#define MZ2_CARRIER_ROCKET_1 191 -#define MZ2_CARRIER_ROCKET_2 192 -#define MZ2_CARRIER_ROCKET_3 193 -#define MZ2_CARRIER_ROCKET_4 194 -#define MZ2_WIDOW2_BEAMER_1 195 -#define MZ2_WIDOW2_BEAMER_2 196 -#define MZ2_WIDOW2_BEAMER_3 197 -#define MZ2_WIDOW2_BEAMER_4 198 -#define MZ2_WIDOW2_BEAMER_5 199 -#define MZ2_WIDOW2_BEAM_SWEEP_1 200 -#define MZ2_WIDOW2_BEAM_SWEEP_2 201 -#define MZ2_WIDOW2_BEAM_SWEEP_3 202 -#define MZ2_WIDOW2_BEAM_SWEEP_4 203 -#define MZ2_WIDOW2_BEAM_SWEEP_5 204 -#define MZ2_WIDOW2_BEAM_SWEEP_6 205 -#define MZ2_WIDOW2_BEAM_SWEEP_7 206 -#define MZ2_WIDOW2_BEAM_SWEEP_8 207 -#define MZ2_WIDOW2_BEAM_SWEEP_9 208 -#define MZ2_WIDOW2_BEAM_SWEEP_10 209 -#define MZ2_WIDOW2_BEAM_SWEEP_11 210 - -// ROGUE - extern vec3_t monster_flash_offset []; @@ -733,34 +628,8 @@ typedef enum TE_BLUEHYPERBLASTER, TE_PLASMA_EXPLOSION, TE_TUNNEL_SPARKS, -//ROGUE - TE_BLASTER2, - TE_RAILTRAIL2, - TE_FLAME, - TE_LIGHTNING, - TE_DEBUGTRAIL, - TE_PLAIN_EXPLOSION, TE_FLASHLIGHT, - TE_FORCEWALL, - TE_HEATBEAM, - TE_MONSTER_HEATBEAM, - TE_STEAM, - TE_BUBBLETRAIL2, - TE_MOREBLOOD, - TE_HEATBEAM_SPARKS, - TE_HEATBEAM_STEAM, - TE_CHAINFIST_SMOKE, - TE_ELECTRIC_SPARKS, - TE_TRACKER_EXPLOSION, - TE_TELEPORT_EFFECT, - TE_DBALL_GOAL, - TE_WIDOWBEAMOUT, - TE_NUKEBLAST, - TE_WIDOWSPLASH, - TE_EXPLOSION1_BIG, - TE_EXPLOSION1_NP, - TE_FLECHETTE -//ROGUE + TE_DEBUGTRAIL, } temp_event_t; #define SPLASH_UNKNOWN 0 @@ -838,46 +707,6 @@ typedef enum // RAFAEL #define DF_QUADFIRE_DROP 0x00010000 // 65536 -//ROGUE -#define DF_NO_MINES 0x00020000 -#define DF_NO_STACK_DOUBLE 0x00040000 -#define DF_NO_NUKES 0x00080000 -#define DF_NO_SPHERES 0x00100000 -//ROGUE - -/* -ROGUE - VERSIONS -1234 08/13/1998 Activision -1235 08/14/1998 Id Software -1236 08/15/1998 Steve Tietze -1237 08/15/1998 Phil Dobranski -1238 08/15/1998 John Sheley -1239 08/17/1998 Barrett Alexander -1230 08/17/1998 Brandon Fish -1245 08/17/1998 Don MacAskill -1246 08/17/1998 David "Zoid" Kirsch -1247 08/17/1998 Manu Smith -1248 08/17/1998 Geoff Scully -1249 08/17/1998 Andy Van Fossen -1240 08/20/1998 Activision Build 2 -1256 08/20/1998 Ranger Clan -1257 08/20/1998 Ensemble Studios -1258 08/21/1998 Robert Duffy -1259 08/21/1998 Stephen Seachord -1250 08/21/1998 Stephen Heaslip -1267 08/21/1998 Samir Sandesara -1268 08/21/1998 Oliver Wyman -1269 08/21/1998 Steven Marchegiano -1260 08/21/1998 Build #2 for Nihilistic -1278 08/21/1998 Build #2 for Ensemble - -9999 08/20/1998 Internal Use -*/ -#define ROGUE_VERSION_ID 1278 - -#define ROGUE_VERSION_STRING "08/21/1998 Beta 2 for Ensemble" - -// ROGUE /* ========================================================== diff --git a/public/ref_server.h b/public/ref_server.h index 8f22948a..b9a84433 100644 --- a/public/ref_server.h +++ b/public/ref_server.h @@ -9,11 +9,6 @@ #define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects #define SVF_DEADMONSTER 0x00000002 // treat as CONTENTS_DEADMONSTER for collision #define SVF_MONSTER 0x00000004 // treat as CONTENTS_MONSTER for collision -//ROGUE -- added for things that are damageable, but not monsters -#define SVF_DAMAGEABLE 0x00000008 -#define SVF_TRIGGER_CAMOWNER 0x00000010 -#define SVF_MUD 0x00000020 -//ROGUE end // edict->solid values diff --git a/public/ref_system.h b/public/ref_system.h index 457feab4..3db59e9b 100644 --- a/public/ref_system.h +++ b/public/ref_system.h @@ -37,12 +37,6 @@ #define SHELL_RG_COLOR 0xDC #define SHELL_RB_COLOR 0x68 #define SHELL_BG_COLOR 0x78 - -//ROGUE -#define SHELL_DOUBLE_COLOR 0xDF // 223 -#define SHELL_HALF_DAM_COLOR 0x90 -#define SHELL_CYAN_COLOR 0x72 -//ROGUE #define SHELL_WHITE_COLOR 0xD7 enum comp_format diff --git a/renderer/gl_local.h b/renderer/gl_local.h index b9160e16..8a8443cc 100644 --- a/renderer/gl_local.h +++ b/renderer/gl_local.h @@ -163,11 +163,11 @@ typedef enum it_cubemap, } imagetype_t; -// texnum supported cubemaps -// 0 = rt or normal image +// texnum cubemap order +// 0 = ft or normal image // 1 = bk -// 2 = lf -// 3 = ft +// 2 = rt +// 3 = lf // 4 = up // 5 = dn diff --git a/renderer/gl_warp.c b/renderer/gl_warp.c index e1e93044..d9c73804 100644 --- a/renderer/gl_warp.c +++ b/renderer/gl_warp.c @@ -540,7 +540,18 @@ void MakeSkyVec (float s, float t, int axis) R_DrawSkyBox ============== */ -int skytexorder[6] = {0,2,1,3,4,5}; +int skytexorder[6] = {4, 5, 1, 0, 2, 3}; //var. 1 + +uint RemapSides[6] = +{ + 0, // ft + 2, // bk + 4, // rt + 5, // lf + 1, // up + 3, // dn +}; + void R_DrawSkyBox (void) { int i; diff --git a/renderer/r_texture.c b/renderer/r_texture.c index 904fda16..6d68bc9d 100644 --- a/renderer/r_texture.c +++ b/renderer/r_texture.c @@ -1587,6 +1587,7 @@ image_t *R_FindImage (char *name, char *buffer, int size, imagetype_t type) return image; } + /* ================ R_LoadImage diff --git a/server/ents/g_camera.c b/server/ents/g_camera.c deleted file mode 100644 index 98415669..00000000 --- a/server/ents/g_camera.c +++ /dev/null @@ -1,399 +0,0 @@ -// g_camera.c (func_monitor) - -#include "g_local.h" - -void camera_off (edict_t *ent) -{ - int i; - - if (!ent->client) - return; - if (!ent->client->spycam) - return; - if(ent->client->spycam->viewer == ent) - ent->client->spycam->viewer = NULL; - - ent->client->spycam->flags &= ~FL_ROBOT; - if(ent->client->spycam->svflags & SVF_MONSTER) - ent->client->spycam->svflags &= ~SVF_NOCLIENT; - VectorCopy(ent->client->camplayer->s.origin,ent->s.origin); - free(ent->client->camplayer->client); - G_FreeEdict (ent->client->camplayer); - - // set angles - ent->movetype = MOVETYPE_WALK; - ent->client->ps.pmove.pm_type = PM_NORMAL; - for (i=0 ; i<3 ; i++) - ent->client->ps.pmove.delta_angles[i] = - ANGLE2SHORT(ent->client->org_viewangles[i] - ent->client->resp.cmd_angles[i]); - VectorCopy(ent->client->org_viewangles, ent->client->resp.cmd_angles); - VectorCopy(ent->client->org_viewangles, ent->s.angles); - VectorCopy(ent->client->org_viewangles, ent->client->ps.viewangles); - VectorCopy(ent->client->org_viewangles, ent->client->v_angle); - - ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); - ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - ent->svflags &= ~SVF_NOCLIENT; - ent->clipmask = MASK_PLAYERSOLID; - ent->solid = SOLID_BBOX; - ent->client->camplayer = NULL; - ent->client->spycam = NULL; - gi.linkentity(ent); - - // if we were previously in third person view, restore it - if(tpp->value) - Cmd_Chasecam_Toggle (ent); - -} - -void faker_animate(edict_t *self) -{ - if(self->s.frame < 0 || self->s.frame > 39) - { - self->s.frame = 0; - } - else - { - self->s.frame++; - if(self->s.frame > 39) - self->s.frame = 0; - } - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} - -void camera_on (edict_t *ent) -{ - gclient_t *cl; - edict_t *faker; - edict_t *monster; - edict_t *camera; - int i; - vec3_t forward, left, up; - - if (!ent->client) - return; - if (!ent->client->spycam) - return; - - // "viewer" can control camera aim (2nd player to come along and use - // camera cannot) - camera = ent->client->spycam; - if(camera->monsterinfo.aiflags & AI_ACTOR) - camera->flags |= FL_ROBOT; - if(!camera->viewer) - camera->viewer = ent; - - // save current viewangles and restore them with camera_off - VectorCopy(ent->client->v_angle,ent->client->org_viewangles); - - // copy over all important player data to fake player - ent->client->camplayer = G_Spawn(); - faker = ent->client->camplayer; - faker->s.frame = ent->s.frame; - VectorCopy (ent->s.origin, faker->s.origin); - VectorCopy (ent->velocity, faker->velocity); - VectorCopy (ent->s.angles, faker->s.angles); - faker->s = ent->s; - faker->takedamage = DAMAGE_AIM; - faker->movetype = MOVETYPE_WALK; - faker->groundentity = ent->groundentity; - faker->viewheight = ent->viewheight; - faker->inuse = true; - faker->classname = "camplayer"; - faker->class_id = ENTITY_CAMPLAYER; - faker->mass = ent->mass; - faker->solid = SOLID_BBOX; - faker->deadflag = DEAD_NO; - faker->clipmask = MASK_PLAYERSOLID; - faker->health = ent->health; - faker->light_level = ent->light_level; - faker->think = faker_animate; - faker->nextthink = level.time + FRAMETIME; - VectorCopy(ent->mins,faker->mins); - VectorCopy(ent->maxs,faker->maxs); - // create a client so you can pick up items/be shot/etc while in camera - cl = (gclient_t *) malloc(sizeof(gclient_t)); - memset(cl,0,sizeof(gclient_t)); - ent->client->camplayer->client = cl; - ent->client->camplayer->target_ent = ent; - gi.linkentity (faker); - - AngleVectors(camera->s.angles,forward,left,up); - - VectorMA(camera->s.origin, camera->move_origin[0],forward,ent->s.origin); - VectorMA(ent->s.origin, -camera->move_origin[1],left, ent->s.origin); - VectorMA(ent->s.origin, camera->move_origin[2],up, ent->s.origin); - - ent->movetype = MOVETYPE_NOCLIP; - ent->clipmask = 0; - ent->solid = SOLID_NOT; - VectorClear(ent->velocity); - ent->client->ps.gunindex = 0; - ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - ent->svflags |= SVF_NOCLIENT; - - // check to see if we're the enemy of any monster. If so, make the - // faker the enemy - for(i=maxclients->value+1, monster=g_edicts+i; iinuse) continue; - if(!(monster->svflags & SVF_MONSTER)) continue; - if(monster->enemy == ent) { - monster->enemy = faker; - FoundTarget(monster); - } - } - - if(ent->client->spycam->viewmessage) - gi.centerprintf(ent,ent->client->spycam->viewmessage); -} - - -edict_t *G_FindNextCamera (edict_t *camera, edict_t *monitor) -{ - edict_t *next; - - if(!monitor->target) return NULL; - - // If we already have a camera that's a monster, make it visible now - if(camera && (camera->svflags & SVF_MONSTER)) - { - camera->svflags &= ~SVF_NOCLIENT; - gi.linkentity(camera); - } - - // First, determine if we're going to use the "count" to get the next camera, - // or just scan through the list of entities. If count for the first camera - // in the map is 0, then we'll just use the map order. - - next = G_Find(NULL,FOFS(targetname),monitor->target); - if(!next) return NULL; - if(!next->count) { - - if(camera) { - next = camera; - next++; - } else - next = g_edicts; - - for ( ; next < &g_edicts[globals.num_edicts] ; next++) - { - if (next == camera) - continue; - if (!next->inuse) - continue; - if (next->deadflag == DEAD_DEAD) - continue; - if (!next->targetname) - continue; - // don't select "inactive" cameras - if ((next->class_id == ENTITY_TURRET_BREACH) && (next->spawnflags & 16)) - continue; - if (!strcasecmp (next->targetname, monitor->target)) - goto found_one; - - } - next = g_edicts; - for ( ; next < camera ; next++) - { - if (next == camera) - continue; - if (!next->inuse) - continue; - if (next->deadflag == DEAD_DEAD) - continue; - if (!next->targetname) - continue; - // don't select "inactive" cameras - if ((next->class_id == ENTITY_TURRET_BREACH) && (next->spawnflags & 16)) - continue; - if (!strcasecmp (next->targetname, monitor->target)) - goto found_one; - } - } else { - int which, start; - - if(camera) { - which = camera->count+1; - if(which > monitor->count) which = 1; - } - else - which = 1; - start = which; - next = g_edicts+1; - while(1) { - if(next->targetname) { - if(!strcasecmp(next->targetname,monitor->target)) { - if(next->count == which) { - if(!next->inuse || (next->deadflag == DEAD_DEAD) || - ((next->class_id == ENTITY_TURRET_BREACH) && (next->spawnflags & 16)) ) - { - next = g_edicts; - which++; - if(which > monitor->count) which=1; - if(which == start) return NULL; - } else - goto found_one; - } - } - } - if(next == &g_edicts[globals.num_edicts-1]) { - next = g_edicts; - which++; - if(which > monitor->count) which = 1; - if(which == start) return NULL; - } - next++; - } - } - return NULL; - -found_one: - if(!(monitor->spawnflags & 32) && (next->svflags & SVF_MONSTER)) - next->svflags |= SVF_NOCLIENT; - return next; -} - -edict_t *G_FindPrevCamera (edict_t *camera, edict_t *monitor) -{ - edict_t *prev; - edict_t *newcamera; - - if(!monitor->target) return NULL; - - // If we already have a camera that's a monster, make it visible now - if(camera && (camera->svflags & SVF_MONSTER)) - { - camera->svflags &= ~SVF_NOCLIENT; - gi.linkentity(camera); - } - - // First, determine if we're going to use the "count" to get the next camera, - // or just scan through the list of entities. If count for the first camera - // in the map is 0, then we'll just use the map order. - - prev = G_Find(NULL,FOFS(targetname),monitor->target); - if(!prev) return NULL; - if(!prev->count) - { - newcamera = NULL; - for (prev = g_edicts ; prev < &g_edicts[globals.num_edicts] ; prev++) - { - if (prev == camera) { - if(newcamera) goto found_one; - continue; - } - if (!prev->inuse) - continue; - if (prev->deadflag == DEAD_DEAD) - continue; - if (!prev->targetname) - continue; - // don't select "inactive" cameras - if ((prev->class_id == ENTITY_TURRET_BREACH) && (prev->spawnflags & 16)) - continue; - if (!strcasecmp (prev->targetname, monitor->target)) - newcamera = prev; - } - goto found_one; - } - else - { - int which, start; - - if(camera) { - which = camera->count-1; - if(which <= 0) which = monitor->count; - } - else - which = monitor->count; - start = which; - prev = g_edicts+1; - while(1) { - if(prev->targetname) { - if(!strcasecmp(prev->targetname,monitor->target)) { - if(prev->count == which) { - if(!prev->inuse || (prev->deadflag == DEAD_DEAD) || - ((prev->class_id == ENTITY_TURRET_BREACH) && (prev->spawnflags & 16))) - { - prev = g_edicts; - which--; - if(which <= 0) which=monitor->count; - if(which == start) return NULL; - } - else - { - newcamera = prev; - goto found_one; - } - } - } - } - if(prev == &g_edicts[globals.num_edicts-1]) { - prev = g_edicts; - which--; - if(which <= 0) which=monitor->count; - if(which == start) return NULL; - } - prev++; - } - } - -found_one: - if(!(monitor->spawnflags & 32) && (newcamera->svflags & SVF_MONSTER)) - newcamera->svflags |= SVF_NOCLIENT; - return newcamera; -} - -void use_camera (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *target; - - if(!activator->client) return; - if(activator->client->spycam) // already using camera - return; - - target = G_FindNextCamera(NULL,self); - if(!target) return; - - // if currently in thirdperson, turn that sucker off - if(tpp->value && activator->client->chasetoggle) - Cmd_Chasecam_Toggle (activator); - - activator->client->spycam = target; - activator->client->monitor = self; - camera_on(activator); -} - -void func_monitor_init (edict_t *self) -{ - edict_t *camera; - - self->count = 0; - camera = NULL; - while( (camera=G_Find(camera,FOFS(targetname),self->target)) != NULL) - self->count++; - if(!self->count) - self->s.effects = 0; // don't animate a func_monitor that has no cameras -} - -void SP_func_monitor (edict_t *self) -{ - if( !self->target ) { - gi.dprintf("func_monitor without a target at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_FUNC_MONITOR; - if (self->spawnflags & 8) - self->s.effects |= EF_ANIM_ALL; - if (self->spawnflags & 16) - self->s.effects |= EF_ANIM_ALLFAST; - gi.setmodel (self, self->model); - self->movetype = MOVETYPE_NONE; - self->solid = SOLID_BSP; - self->use = use_camera; - self->think = func_monitor_init; - self->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(self); -} \ No newline at end of file diff --git a/server/ents/g_crane.c b/server/ents/g_crane.c deleted file mode 100644 index f5bdfb12..00000000 --- a/server/ents/g_crane.c +++ /dev/null @@ -1,1705 +0,0 @@ -#include "g_local.h" - -void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); - -// g_crane.c -// -// Utility functions for manipulating overhead crane -// - -#define STEPSIZE 8 -#define MAX_PICKUP_DISTANCE 64 -#define BUFFER 1 // Bonk buffer -#define CABLE_SEGMENT 32.0 -#define SPOT_SEGMENT 32.0 -#define CARGO_BUFFER 0.125 - -bool box_movestep (edict_t *ent, vec3_t move, bool relink); -void Crane_Move_Begin (edict_t *); - -void Moving_Speaker_Think(edict_t *speaker) -{ - bool moved; - vec3_t offset; - edict_t *owner; - - owner = speaker->owner; - if(!owner) - { - G_FreeEdict(speaker); - return; - } - if(!owner->inuse) - { - G_FreeEdict(speaker); - return; - } - if(speaker->spawnflags & 15) - { - if((speaker->spawnflags & 8) && ( - (!speaker->owner->groundentity) || // not on the ground - (!speaker->owner->activator) || // not "activated" by anything - (!speaker->owner->activator->client) ) // not activated by client - ) { - moved = false; - } else - { - moved = false; - VectorSubtract(speaker->s.origin,owner->s.origin,offset); - if((speaker->spawnflags & 1) && (fabs(offset[0] - speaker->offset[0]) > 0.125) ) - moved = true; - if((speaker->spawnflags & 2) && (fabs(offset[1] - speaker->offset[1]) > 0.125) ) - moved = true; - if((speaker->spawnflags & 4) && (fabs(offset[2] - speaker->offset[2]) > 0.125) ) - moved = true; - } - if(moved) - speaker->s.sound = speaker->owner->noise_index; - else - speaker->s.sound = 0; - } - else - speaker->s.sound = speaker->owner->noise_index; - - VectorAdd(owner->s.origin,speaker->offset,speaker->s.origin); - speaker->nextthink = level.time + FRAMETIME; - gi.linkentity(speaker); -} - -edict_t *CrateOnTop (edict_t *from, edict_t *ent) -{ - float maxdist; - - if (!from) - from = g_edicts; - else - from++; - - for ( ; from < &g_edicts[globals.num_edicts] ; from++) - { - if (from == ent) - continue; - if (!from->inuse) - continue; - if (from->movetype != MOVETYPE_PUSHABLE) - continue; - if (from->absmin[0] >= ent->absmax[0]) continue; - if (from->absmax[0] <= ent->absmin[0]) continue; - if (from->absmin[1] >= ent->absmax[1]) continue; - if (from->absmax[1] <= ent->absmin[1]) continue; - maxdist = VectorLength(ent->velocity)*FRAMETIME + 2.0; - if (fabs(from->absmin[2] - ent->absmax[2]) > maxdist) continue; - return from; - } - - return NULL; -} - -void Cargo_Stop (edict_t *ent) -{ - vec3_t v; - - VectorClear (ent->velocity); - // Sanity check: force cargo to correct elevation - ent->s.origin[2] += ent->crane_hook->absmin[2] - CARGO_BUFFER - ent->absmax[2]; - ent->think = NULL; - ent->nextthink = 0; - ent->gravity = 0.0; - VectorAdd(ent->absmax,ent->absmin,v); - VectorScale(v,0.5,v); - v[2] = ent->absmax[2]; - gi.positioned_sound (v, ent, CHAN_VOICE, gi.soundindex("tank/thud.wav"), 1, 1, 0); - gi.linkentity(ent); - ent->crane_control->busy = false; -} - -void cargo_blocked (edict_t *cargo, edict_t *obstacle ) -{ - vec3_t origin; - - VectorAdd(obstacle->s.origin,obstacle->origin_offset,origin); - cargo->gravity = 1.0; - cargo->movetype = MOVETYPE_PUSHABLE; - cargo->velocity[2] = 0; - box_movestep (cargo, vec3_origin, true); - cargo->crane_control->busy = false; - cargo->crane_hook->crane_cargo = NULL; - cargo->blocked = NULL; - cargo->touch = box_touch; - cargo->nextthink = 0; - gi.linkentity(cargo); -} - -void Cargo_Float_Up (edict_t *cargo) -{ - cargo->velocity[2] += sv_gravity->value * FRAMETIME; - cargo->velocity[0] = cargo->velocity[1] = 0; - if(cargo->absmax[2] + cargo->velocity[2]*FRAMETIME >= - cargo->crane_hook->absmin[2]-CARGO_BUFFER) - { - cargo->attracted = false; - cargo->think = Cargo_Stop; - } - cargo->nextthink = level.time + FRAMETIME; - gi.linkentity(cargo); -} - -void SetCableLength(edict_t *cable) -{ - int frame; - float length; - - length = cable->s.origin[2] - cable->crane_hook->absmax[2]; - frame = (int)(length/CABLE_SEGMENT); - if((frame+1)*CABLE_SEGMENT < length) frame++; - frame = max(0,min(frame,19)); - cable->s.frame = frame; -} - -void SetSpotlightLength(edict_t *hook) -{ - trace_t tr; - vec3_t start, end; - - start[0] = (hook->absmin[0] + hook->absmax[0])/2; - start[1] = (hook->absmin[1] + hook->absmax[1])/2; - start[2] = hook->absmin[2] + 1; - end[0] = start[0]; - end[1] = start[1]; - end[2] = start[2] - 8192; - tr = gi.trace(start,NULL,NULL,end,hook,MASK_SOLID); - hook->crane_light->s.origin[2] = tr.endpos[2] + 1; -} - -void Cable_Think(edict_t *cable) -{ - SetCableLength(cable); - cable->nextthink = level.time + FRAMETIME; - gi.linkentity(cable); -} - -void crane_light_off(edict_t *light) -{ - light->svflags |= SVF_NOCLIENT; -} - -void Crane_Move_Done (edict_t *ent) -{ - if(ent->class_id == ENTITY_CRANE_HOOK) - { - edict_t *cable; - edict_t *light; - // Sanity checks - force hook to correct relative location from hoist... - ent->s.origin[0] = ent->crane_hoist->s.origin[0] + ent->offset[0]; - ent->s.origin[1] = ent->crane_hoist->s.origin[1] + ent->offset[1]; - // ... and force cargo to correct elevation ... - if(ent->crane_cargo) - { - ent->crane_cargo->s.origin[2] += - ent->absmin[2] - CARGO_BUFFER - ent->crane_cargo->absmax[2]; - gi.linkentity(ent->crane_cargo); - } - // ... and finally, stop cable and move to correct position - cable = ent->crane_cable; - VectorClear(cable->velocity); - cable->s.origin[0] = ent->s.origin[0] + cable->offset[0]; - cable->s.origin[1] = ent->s.origin[1] + cable->offset[1]; - SetCableLength(cable); - gi.linkentity(cable); - light = ent->crane_light; - if(light) - { - VectorClear(light->velocity); - light->think = crane_light_off; - light->nextthink = level.time + 1.0; - gi.linkentity(light); - } - } -// Lazarus: ACK! If crate is being carried, it's NOT a MOVETYPE_PUSHABLE!!!! -// if(ent->movetype == MOVETYPE_PUSHABLE) - if(ent->class_id == ENTITY_FUNC_PUSHABLE) - { - edict_t *e; - - ent->s.origin[2] += ent->crane_hook->absmin[2] - CARGO_BUFFER - ent->absmax[2]; - // Check to see if any OTHER crates are stacked on this one. If so, - // adjust their position and velocity as well. - e = NULL; - while ((e = CrateOnTop(e, ent)) != NULL) - { - VectorClear(e->velocity); - e->s.origin[2] += ent->crane_hook->absmin[2] - e->absmin[2]; - gi.linkentity(e); - } - } - VectorClear (ent->velocity); - ent->busy = false; - ent->think = NULL; - ent->nextthink = 0; - gi.linkentity(ent); -} - -void Crane_Stop(edict_t *control) -{ - if(control->crane_beam->crane_onboard_control) - Crane_Move_Done(control->crane_beam->crane_onboard_control); - Crane_Move_Done(control->crane_beam); - Crane_Move_Done(control->crane_hoist); - Crane_Move_Done(control->crane_hook); - if(control->crane_hook->crane_cargo) Crane_Move_Done(control->crane_hook->crane_cargo); -} - -bool Crane_Hook_Bonk(edict_t *hook, int axis, int dir, vec3_t bonk) -{ - float fraction, cargo_fraction; - int i1,i2; - edict_t *cargo; - vec3_t cargo_origin, cargo_bonk, origin, end, forward, start; - vec3_t mins, maxs; - trace_t tr; - - VectorClear(end); - VectorClear(start); - VectorClear(forward); - forward[axis] = (float)dir; - switch (axis) - { - case 0: - // X - i1 = 1; - i2 = 2; - break; - case 1: - // Y - i1 = 0; - i2 = 2; - break; - default: - // Z - i1 = 0; - i2 = 1; - break; - } - cargo = hook->crane_cargo; - VectorAdd(hook->s.origin,hook->origin_offset,origin); - VectorCopy(origin,start); - if(dir > 0) - start[axis] = origin[axis] + hook->size[axis]/2; - else - start[axis] = origin[axis] - hook->size[axis]/2; - fraction = 1.0; - mins[axis] = 0; - mins[i1] = -hook->size[i1]/2; - mins[i2] = -hook->size[i2]/2; - maxs[axis] = 0; - maxs[i1] = hook->size[i1]/2; - maxs[i2] = hook->size[i2]/2; - VectorMA(start,8192,forward,end); - tr = gi.trace(start,mins,maxs,end,cargo,MASK_PLAYERSOLID); - if(tr.fraction < fraction && tr.ent != hook->crane_beam && - tr.ent != hook->crane_hoist && tr.ent != cargo ) - { - VectorCopy(tr.endpos,bonk); - bonk[axis] -= dir*BUFFER; - fraction = tr.fraction; - } else { - VectorCopy(end,bonk); - } - - if(cargo) - { - VectorAdd(cargo->s.origin,cargo->origin_offset,cargo_origin); - VectorCopy(cargo_origin,start); - if(dir > 0) - start[axis] = cargo_origin[axis] + cargo->size[axis]/2; - else - start[axis] = cargo_origin[axis] - cargo->size[axis]/2; - cargo_fraction = 1.0; - mins[axis] = 0; - mins[i1] = -cargo->size[i1]/2+1; - mins[i2] = -cargo->size[i2]/2+1; - maxs[axis] = 0; - maxs[i1] = cargo->size[i1]/2-1; - maxs[i2] = cargo->size[i2]/2-1; - VectorMA(start, 8192, forward, end); - tr=gi.trace(start, mins, maxs, end, cargo, MASK_PLAYERSOLID ); - if(tr.fraction < cargo_fraction && tr.ent != hook->crane_beam && - tr.ent != hook->crane_hoist && tr.ent != hook ) - { - VectorCopy(tr.endpos,cargo_bonk); - cargo_bonk[axis] -= dir*BUFFER; - cargo_fraction = tr.fraction; - } else { - VectorCopy(end,cargo_bonk); - } - if(cargo_fraction < 1) - { - fraction = cargo_fraction; - if(dir > 0) - { - cargo_bonk[axis] += hook->absmax[axis] - cargo->absmax[axis]; - bonk[axis] = min(bonk[axis],cargo_bonk[axis]); - } - else - { - cargo_bonk[axis] += hook->absmin[axis] - cargo->absmin[axis]; - bonk[axis] = max(bonk[axis],cargo_bonk[axis]); - } - } - } - - if(fraction < 1) - return true; - else - return false; -} - -void Crane_blocked (edict_t *self, edict_t *other) -{ - if ( (other->classname) && (other->movetype == MOVETYPE_PUSHABLE)) - { - // treat func_pushable like a world brush - attempt to stop - // crane - // This *shouldn't* be necessary, but I'm a pessimist - Crane_Stop(self->crane_control); - return; - - } - - if (self->crane_control->crane_hook == other) - return; - - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) - { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) - { - // Lazarus: Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } - - if (level.time < self->touch_debounce_time) - return; - - if (!self->dmg) - return; - self->touch_debounce_time = level.time + 0.5; - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); -} - -void Crane_Move_Final (edict_t *ent) -{ - float bonk_distance; - - if(ent->crane_control->activator->client->use) - { - // Use key is still pressed - bonk_distance = ent->crane_control->crane_increment * - (ent->crane_bonk - ent->absmin[ent->crane_dir]); - if(ent->moveinfo.remaining_distance > 0) - bonk_distance -= ent->moveinfo.remaining_distance; - bonk_distance = min(bonk_distance,STEPSIZE); - if(bonk_distance > 0) - { - ent->moveinfo.remaining_distance += bonk_distance; - Crane_Move_Begin(ent); - return; - } - } - - if (ent->moveinfo.remaining_distance == 0) - { - Crane_Move_Done (ent); - return; - } - - VectorScale (ent->moveinfo.dir, ent->moveinfo.remaining_distance / FRAMETIME, ent->velocity); - if(ent->class_id == ENTITY_CRANE_HOOK) - { - VectorCopy(ent->velocity,ent->crane_cable->velocity); - ent->crane_cable->velocity[2] = 0; - gi.linkentity(ent); - if(ent->crane_light != NULL) - { - VectorCopy(ent->velocity,ent->crane_light->velocity); - ent->crane_light->velocity[2] = 0; - gi.linkentity(ent->crane_light); - } - } - ent->think = Crane_Move_Done; - ent->nextthink = level.time + FRAMETIME; - gi.linkentity(ent); -} - -void Crane_Move_Begin (edict_t *ent) -{ - float frames; - - if ((ent->moveinfo.speed * FRAMETIME) >= ent->moveinfo.remaining_distance) - { - Crane_Move_Final (ent); - return; - } - VectorScale (ent->moveinfo.dir, ent->moveinfo.speed, ent->velocity); - frames = floor((ent->moveinfo.remaining_distance / ent->moveinfo.speed) / FRAMETIME); - ent->moveinfo.remaining_distance -= frames * ent->moveinfo.speed * FRAMETIME; - if(ent->class_id == ENTITY_CRANE_HOOK) - { - if((ent->crane_light) && (ent->crane_cargo==NULL)) - { - SetSpotlightLength(ent); - ent->crane_light->svflags &= ~SVF_NOCLIENT; - } - VectorCopy(ent->velocity,ent->crane_cable->velocity); - ent->crane_cable->velocity[2] = 0; - gi.linkentity(ent->crane_cable); - if(ent->crane_light != NULL) - { - VectorCopy(ent->velocity,ent->crane_light->velocity); - ent->crane_light->velocity[2] = 0; - gi.linkentity(ent->crane_light); - } - } - ent->nextthink = level.time + (frames * FRAMETIME); - ent->think = Crane_Move_Final; - ent->blocked = Crane_blocked; - gi.linkentity(ent); -} - -void G_FindCraneParts() -{ - vec3_t dist; - edict_t *cable; - edict_t *control; - edict_t *beam; - edict_t *hoist; - edict_t *hook; - edict_t *light; - edict_t *p1, *p2; - - edict_t *e; - int direction; - int i; - - for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++) - { - if (!e->inuse) - continue; - if (!e->classname) - continue; - if (e->class_id != ENTITY_CRANE_CONTROL) - continue; - - control = e; - beam = G_Find(NULL,FOFS(targetname),control->target); - if(!beam) - { - gi.dprintf("Crane_control with no target\n"); - G_FreeEdict(control); - return; - } - // get path_corner locations to determine movement direction - p1 = G_Find(NULL,FOFS(targetname),beam->pathtarget); - if(!p1->target) - { - gi.dprintf("Only 1 path_corner in pathtarget sequence for crane_beam\n" - "(2 are required)\n"); - G_FreeEdict(control); - G_FreeEdict(beam); - G_FreeEdict(p1); - return; - } - p2 = G_Find(NULL,FOFS(targetname),p1->target); - VectorSubtract(p1->s.origin,p2->s.origin,dist); - if(fabs(dist[0]) > fabs(dist[1])) - { - VectorSet(beam->movedir, 1.0,0.0,0.0); - direction = 0; - if(p1->s.origin[0] < p2->s.origin[0]) - { - VectorCopy(p1->s.origin,beam->pos1); - VectorCopy(p2->s.origin,beam->pos2); - } - else - { - VectorCopy(p2->s.origin,beam->pos1); - VectorCopy(p1->s.origin,beam->pos2); - } - } - else - { - VectorSet(beam->movedir, 0.0,1.0,0.0); - direction = 1; - if(p1->s.origin[1] < p2->s.origin[1]) - { - VectorCopy(p1->s.origin,beam->pos1); - VectorCopy(p2->s.origin,beam->pos2); - } - else - { - VectorCopy(p2->s.origin,beam->pos1); - VectorCopy(p1->s.origin,beam->pos2); - } - } - hoist = G_Find(NULL,FOFS(targetname),beam->target); - if(!hoist) - { - gi.dprintf("Crane_beam with no target\n"); - G_FreeEdict(control); - G_FreeEdict(beam); - return; - } - // get path_corner locations to determine movement direction - p1 = G_Find(NULL,FOFS(targetname),hoist->pathtarget); - if(!p1->target) - { - gi.dprintf("Only 1 path_corner in pathtarget sequence for crane_hoist\n" - "(2 are required)\n"); - G_FreeEdict(control); - G_FreeEdict(beam); - G_FreeEdict(hoist); - G_FreeEdict(p1); - return; - } - p2 = G_Find(NULL,FOFS(targetname),p1->target); - VectorSubtract(p1->s.origin,p2->s.origin,dist); - if(fabs(dist[0]) > fabs(dist[1])) - { - VectorSet(hoist->movedir, 1.0,0.0,0.0); - if(p1->s.origin[0] < p2->s.origin[0]) - { - VectorCopy(p1->s.origin,hoist->pos1); - VectorCopy(p2->s.origin,hoist->pos2); - } - else - { - VectorCopy(p2->s.origin,hoist->pos1); - VectorCopy(p1->s.origin,hoist->pos2); - } - } - else - { - VectorSet(hoist->movedir, 0.0,1.0,0.0); - if(p1->s.origin[1] < p2->s.origin[1]) - { - VectorCopy(p1->s.origin,hoist->pos1); - VectorCopy(p2->s.origin,hoist->pos2); - } - else - { - VectorCopy(p2->s.origin,hoist->pos1); - VectorCopy(p1->s.origin,hoist->pos2); - } - } - - // correct spawnflags for beam and hoist speakers - if(beam->speaker) - { - if(direction) - beam->speaker->spawnflags = 2; - else - beam->speaker->spawnflags = 1; - } - if(hoist->speaker) - { - if(direction) - hoist->speaker->spawnflags = 1; - else - hoist->speaker->spawnflags = 2; - } - - hook = G_Find(NULL,FOFS(targetname),hoist->target); - if(!hook) - { - gi.dprintf("Crane hoist with no target\n"); - G_FreeEdict(control); - G_FreeEdict(beam); - G_FreeEdict(hoist); - return; - } - // Turn on hook ambient sound if control is on - // We use a trick here... since hook by definition cannot - // be moving unless control is on, then with control off - // we set hook speaker spawnflag to require hook to be - // moving to play - if(hook->speaker) - hook->speaker->spawnflags = 1 - (control->spawnflags & 1); - - // Get offset from hook origin to hoist origin, so we can - // correct timing problems - VectorSubtract(hook->s.origin,hoist->s.origin,hook->offset); - - // get path_corner locations to determine movement direction - p1 = G_Find(NULL,FOFS(targetname),hook->pathtarget); - if(!p1->target) - { - gi.dprintf("Only 1 path_corner in pathtarget sequence for crane_hook\n" - "(2 are required)\n"); - G_FreeEdict(control); - G_FreeEdict(beam); - G_FreeEdict(hoist); - G_FreeEdict(hook); - G_FreeEdict(p1); - return; - } - p2 = G_Find(NULL,FOFS(targetname),p1->target); - VectorSet(hook->movedir,0.0,0.0,1.0); - if(p1->s.origin[2] < p2->s.origin[2]) - { - VectorCopy(p1->s.origin,hook->pos1); - VectorCopy(p2->s.origin,hook->pos2); - } - else - { - VectorCopy(p2->s.origin,hook->pos1); - VectorCopy(p1->s.origin,hook->pos2); - } - - control->crane_control = control; - control->crane_beam = beam; - control->crane_hoist = hoist; - control->crane_hook = hook; - if(!beam->crane_control) beam->crane_control = control; - if(control->team) - { - beam->crane_control = control; - if(beam->flags & FL_TEAMSLAVE) - beam->crane_onboard_control = beam->teammaster; - else - beam->crane_onboard_control = beam->teamchain; - } - else - beam->crane_onboard_control = NULL; - beam->crane_hoist = hoist; - beam->crane_hook = hook; - hoist->crane_control = beam->crane_control; - hoist->crane_beam = beam; - hoist->crane_hook = hook; - hook->crane_control = beam->crane_control; - hook->crane_beam = beam; - hook->crane_hoist = hoist; - if(control->spawnflags & 4) - { - beam->dmg = 0; - hoist->dmg = 0; - hook->dmg = 0; - } - - if(hook->crane_cable == NULL) - { - int frame; - float length; - - cable = G_Spawn(); - cable->classname = "crane_cable"; - VectorAdd(hook->absmin,hook->absmax,cable->s.origin); - VectorScale(cable->s.origin,0.5,cable->s.origin); - VectorAdd(cable->s.origin,hook->move_origin,cable->s.origin); - VectorSubtract(cable->s.origin,hook->s.origin,cable->offset); - cable->s.origin[2] = hoist->absmax[2] - 2; - cable->model = "models/cable/tris.md2"; - gi.setmodel(cable,cable->model); - cable->s.skin = 0; - length = hoist->absmax[2]-1 - hook->absmax[2]; - frame = (int)(length/CABLE_SEGMENT); - if((frame+1)*CABLE_SEGMENT < length) frame++; - frame = max(0,min(frame,19)); - cable->s.frame = frame; - cable->solid = SOLID_NOT; - cable->movetype = MOVETYPE_STOP; - VectorSet(cable->mins,-2,-2,length); - VectorSet(cable->maxs, 2, 2,0); - gi.linkentity(cable); - beam->crane_cable = cable; - hoist->crane_cable = cable; - hook->crane_cable = cable; - cable->crane_control = control; - cable->crane_beam = beam; - cable->crane_hoist = hoist; - cable->crane_hook = hook; - } - control->crane_cable = hook->crane_cable; - - if((hook->spawnflags & 1) && (hook->crane_light == NULL)) - { - light = G_Spawn(); - light->s.origin[0] = (hook->absmin[0] + hook->absmax[0])/2; - light->s.origin[1] = (hook->absmin[1] + hook->absmax[1])/2; - light->s.origin[2] = hook->absmin[2] + 8; - VectorSet(light->mins,-32,-32,-512); - VectorSet(light->maxs, 32, 32, 0); - light->solid = SOLID_NOT; - light->movetype = MOVETYPE_NOCLIP; - light->s.effects = EF_SPHERETRANS; - light->s.modelindex = gi.modelindex("sprites/point.spr"); - light->s.effects = EF_HYPERBLASTER; - light->svflags = SVF_NOCLIENT; - VectorSubtract(light->s.origin,hook->s.origin,light->offset); - gi.linkentity(light); - beam->crane_light = light; - hook->crane_light = light; - cable->crane_light = light; - } - control->crane_light = hook->crane_light; - - // If control is NOT onboard, move beam speaker (if any) to end of - // beam closest to control - if(!beam->crane_onboard_control && beam->speaker) { - if(beam->movedir[0] > 0) { - if(control->absmin[1]+control->absmax[1] < beam->absmin[1]+beam->absmax[1]) - beam->speaker->s.origin[1] = beam->absmin[1]; - else - beam->speaker->s.origin[1] = beam->absmax[1]; - } else { - if(control->absmin[0]+control->absmax[0] < beam->absmin[0]+beam->absmax[0]) - beam->speaker->s.origin[0] = beam->absmin[0]; - else - beam->speaker->s.origin[0] = beam->absmax[0]; - } - beam->speaker->s.origin[2] = control->s.origin[2] + 32; - VectorSubtract(beam->speaker->s.origin,beam->s.origin,beam->speaker->offset); - } - } -} - -void Crane_AdjustSpeed(edict_t *ent) -{ - float frames; - - // Adjust speed so that travel time is an integral multiple - // of FRAMETIME - if(ent->moveinfo.remaining_distance > 0) - { - ent->moveinfo.speed = ent->speed; - frames = floor((ent->moveinfo.remaining_distance / ent->moveinfo.speed) / FRAMETIME); - if(frames < 1) frames = 1; - ent->moveinfo.speed = ent->moveinfo.remaining_distance/(frames*FRAMETIME); - } -} - -void crane_control_action(edict_t *control, edict_t *activator, vec3_t point) -{ - float Z; - int dir; - int row, column; - int content; - edict_t *beam, *cable, *cargo, *hoist, *hook; - trace_t tr; - vec3_t center, v; - vec3_t end, forward, start, pt; - vec3_t bonk, mins, maxs; - - if(!(control->spawnflags & 1)) - { - if(control->message) - gi.centerprintf(activator,"%s\n",control->message); - else - gi.centerprintf(activator,"No power\n"); - return; - } - - if(control->busy) return; - - // First make sure player (activator) is on the panel side of the - // control panel - // Also get center point of panel side - switch (control->style) - { - case 0: - if(activator->s.origin[0] > control->absmax[0]) return; - center[0] = control->absmin[0]; - center[1] = (control->absmin[1] + control->absmax[1])/2; - center[2] = (control->absmin[2] + control->absmax[2])/2; - break; - case 1: - if(activator->s.origin[1] > control->absmax[1]) return; - center[0] = (control->absmin[0] + control->absmax[0])/2; - center[1] = control->absmin[1]; - center[2] = (control->absmin[2] + control->absmax[2])/2; - break; - case 2: - if(activator->s.origin[0] < control->absmin[0]) return; - center[0] = control->absmax[0]; - center[1] = (control->absmin[1] + control->absmax[1])/2; - center[2] = (control->absmin[2] + control->absmax[2])/2; - break; - case 3: - if(activator->s.origin[1] < control->absmin[1]) return; - center[0] = (control->absmin[0] + control->absmax[0])/2; - center[1] = control->absmax[1]; - center[2] = (control->absmin[2] + control->absmax[2])/2; - break; - } - // now check distance from player to panel - VectorSubtract(activator->s.origin,center,v); - if(VectorLength(v) > 64) return; - - beam = control->crane_beam; - cable = control->crane_cable; - hoist = control->crane_hoist; - hook = control->crane_hook; - cargo = hook->crane_cargo; - if(cargo) cargo->gravity = 0.0; // reset after making it float up, - // otherwise things get jammed up - control->activator = activator; - - // if any part of crane is currently moving, do nothing. - if(VectorLength(control->velocity) > 0.) return; - if(VectorLength(beam->velocity) > 0.) return; - if(VectorLength(hoist->velocity) > 0.) return; - if(VectorLength(hook->velocity) > 0.) return; - - // now find which row and column of buttons corresponds to "point" - row = (2*(point[2] - control->absmin[2]))/(control->absmax[2]-control->absmin[2]); - if(row < 0) row = 0; - if(row > 1) row = 1; - switch (control->style) - { - case 1: - column = (4*(point[0]-control->absmin[0]))/(control->absmax[0]-control->absmin[0]); - break; - case 2: - column = (4*(point[1]-control->absmin[1]))/(control->absmax[1]-control->absmin[1]); - break; - case 3: - column = (4*(point[0]-control->absmax[0]))/(control->absmin[0]-control->absmax[0]); - break; - default: - column = (4*(point[1]-control->absmax[1]))/(control->absmin[1]-control->absmax[1]); - break; - } - if(column < 0) column = 0; - if(column > 3) column = 3; - - // adjust for controller facing beam movement direction - if( beam->movedir[0] > 0 && (control->style == 0 || control->style == 2)) { - if(column == 0 || column == 1) { - column = 1-column; - row = 1-row; - } - } - if( beam->movedir[1] > 0 && (control->style == 1 || control->style == 3)) { - if(column == 0 || column == 1) { - column = 1-column; - row = 1-row; - } - } - - switch(column) - { - case 0: - //================== - // move hoist - //================== - if(row) - { - // hoist away - if(control->style == 0 || control->style == 1) - control->crane_increment = 1; - else - control->crane_increment = -1; - } - else - { - // hoist toward - if(control->style == 0 || control->style == 1) - control->crane_increment = -1; - else - control->crane_increment = 1; - } - if(hoist->movedir[0] > 0) - { - // hoist travels in X - dir = 0; - if(control->crane_increment > 0) - { - if(Crane_Hook_Bonk(hook,0,1,bonk)) - { - bonk[0] += hoist->absmax[0] - hook->absmax[0]; - hoist->crane_bonk = min(bonk[0],hoist->pos2[0]); - } - else - hoist->crane_bonk = hoist->pos2[0]; - hoist->crane_bonk += hoist->absmin[0] - hoist->absmax[0]; - } - else - { - if(Crane_Hook_Bonk(hook,0,-1,bonk)) - { - bonk[0] += hoist->absmin[0] - hook->absmin[0]; - hoist->crane_bonk = max(bonk[0],hoist->pos1[0]); - } - else - hoist->crane_bonk = hoist->pos1[0]; - } - } - else - { - // travels in Y - dir = 1; - if(control->crane_increment > 0) - { - if(Crane_Hook_Bonk(hook,1,1,bonk)) - { - bonk[1] += hoist->absmax[1] - hook->absmax[1]; - hoist->crane_bonk = min(bonk[1],hoist->pos2[1]); - } - else - hoist->crane_bonk = hoist->pos2[1]; - hoist->crane_bonk += hoist->absmin[1] - hoist->absmax[1]; - - } - else - { - if(Crane_Hook_Bonk(hook,1,-1,bonk)) - { - bonk[1] += hoist->absmin[1] - hook->absmin[1]; - hoist->crane_bonk = max(bonk[1],hoist->pos1[1]); - } - else - hoist->crane_bonk = hoist->pos1[1]; - } - } - hoist->crane_dir = dir; - hoist->moveinfo.remaining_distance = control->crane_increment * - (hoist->crane_bonk - hoist->absmin[dir]); - if(hoist->moveinfo.remaining_distance <= 0) return; - - hoist->moveinfo.remaining_distance = min(hoist->moveinfo.remaining_distance,STEPSIZE); - Crane_AdjustSpeed(hoist); - VectorSet(hoist->moveinfo.dir, - hoist->movedir[0]*control->crane_increment, - hoist->movedir[1]*control->crane_increment, - 0); - hoist->crane_control = control; - - hook->crane_dir = dir; - hook->crane_bonk = hoist->crane_bonk + hook->absmin[dir] - - hoist->absmin[dir]; - hook->crane_control = control; - memcpy(&hook->moveinfo,&hoist->moveinfo,sizeof(moveinfo_t)); - - cable->crane_dir = dir; - cable->crane_bonk = hoist->crane_bonk + cable->absmin[dir] - - hoist->absmin[dir]; - cable->crane_control = control; - memcpy(&cable->moveinfo,&hoist->moveinfo,sizeof(moveinfo_t)); - - if(cargo) - { - cargo->movetype = MOVETYPE_PUSH; - cargo->crane_dir = dir; - cargo->crane_bonk = hoist->crane_bonk + cargo->absmin[dir] - - hoist->absmin[dir]; - cargo->crane_control = control; - memcpy(&cargo->moveinfo,&hoist->moveinfo,sizeof(moveinfo_t)); - } - Crane_Move_Begin(hoist); - Crane_Move_Begin(hook); - if(cargo) Crane_Move_Begin(cargo); - break; - case 1: - //================== - // move beam - //================== - // first re-parent associated speaker, if any - if(beam->speaker && control == beam->crane_onboard_control) - { - beam->speaker->owner = control; - VectorAdd(control->absmin,control->absmax,beam->speaker->s.origin); - VectorScale(beam->speaker->s.origin,0.5,beam->speaker->s.origin); - VectorSubtract(beam->speaker->s.origin,control->s.origin,beam->speaker->offset); - control->noise_index = beam->noise_index; - } - if(row) - { - // left arrow - if(control->style == 0 || control->style == 3) - control->crane_increment = 1; - else - control->crane_increment = -1; - } - else - { - // right arrow - if(control->style == 0 || control->style == 3) - control->crane_increment = -1; - else - control->crane_increment = 1; - } - if(beam->movedir[0] > 0) - { - // travels in X - dir = 0; - if(control->crane_increment > 0) - { - if(Crane_Hook_Bonk(hook,0,1,bonk)) - { - bonk[0] += beam->absmax[0] - hook->absmax[0]; - beam->crane_bonk = min(bonk[0],beam->pos2[0]); - } - else - beam->crane_bonk = beam->pos2[0]; - beam->crane_bonk += beam->absmin[0] - beam->absmax[0]; - } - else - { - if(Crane_Hook_Bonk(hook,0,-1,bonk)) - { - bonk[0] += beam->absmin[0] - hook->absmin[0]; - beam->crane_bonk = max(bonk[0],beam->pos1[0]); - } - else - beam->crane_bonk = beam->pos1[0]; - } - } - else - { - // travels in Y - dir = 1; - if(control->crane_increment > 0) - { - if(Crane_Hook_Bonk(hook,1,1,bonk)) - { - bonk[1] += beam->absmax[1] - hook->absmax[1]; - beam->crane_bonk = min(bonk[1],beam->pos2[1]); - } - else - beam->crane_bonk = beam->pos2[1]; - beam->crane_bonk += beam->absmin[1] - beam->absmax[1]; - } - else - { - if(Crane_Hook_Bonk(hook,1,-1,bonk)) - { - bonk[1] += beam->absmin[1] - hook->absmin[1]; - beam->crane_bonk = max(bonk[1],beam->pos1[1]); - } - else - beam->crane_bonk = beam->pos1[1]; - } - } - beam->crane_dir = dir; - beam->moveinfo.remaining_distance = control->crane_increment * - (beam->crane_bonk - beam->absmin[dir]); -// gi.dprintf("remaining distance = %g\n",beam->moveinfo.remaining_distance); - if(beam->moveinfo.remaining_distance <= 0) return; - beam->moveinfo.remaining_distance = min(beam->moveinfo.remaining_distance,STEPSIZE); - - Crane_AdjustSpeed(beam); - - VectorSet(beam->moveinfo.dir, - beam->movedir[0]*control->crane_increment, - beam->movedir[1]*control->crane_increment, - 0); - beam->crane_control = control; - - hoist->crane_dir = dir; - hoist->crane_bonk = beam->crane_bonk + hoist->absmin[dir] - beam->absmin[dir]; - hoist->crane_control = control; - memcpy(&hoist->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - - hook->crane_dir = dir; - hook->crane_bonk = beam->crane_bonk + hook->absmin[dir] - beam->absmin[dir]; - hook->crane_control = control; - memcpy(&hook->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - - cable->crane_dir = dir; - cable->crane_bonk = beam->crane_bonk + cable->absmin[dir] - - beam->absmin[dir]; - cable->crane_control = control; - memcpy(&cable->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - - if(beam->crane_onboard_control) - { - beam->crane_onboard_control->crane_dir = dir; - beam->crane_onboard_control->crane_bonk = beam->crane_bonk + - beam->crane_onboard_control->absmin[dir] - - beam->absmin[dir]; - beam->crane_onboard_control->crane_control = control; - memcpy(&beam->crane_onboard_control->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - } - - if(cargo) - { - cargo->movetype = MOVETYPE_PUSH; - cargo->crane_dir = dir; - cargo->crane_bonk = beam->crane_bonk + cargo->absmin[dir] - beam->absmin[dir]; - cargo->crane_control = control; - memcpy(&cargo->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - } - Crane_Move_Begin(beam); - Crane_Move_Begin(hoist); - Crane_Move_Begin(hook); - if(beam->crane_onboard_control) - Crane_Move_Begin(beam->crane_onboard_control); - if(cargo) Crane_Move_Begin(cargo); - break; - case 2: - //================== - // hook up/down - //================== - hook->crane_dir = dir = 2; - if(row) - { - // hook up - control->crane_increment = 1; - if(Crane_Hook_Bonk(hook,2,1,bonk)) - hook->crane_bonk = min(bonk[2],hook->pos2[2]); - else - hook->crane_bonk = hook->pos2[2]; - hook->crane_bonk += hook->absmin[2] - hook->absmax[2]; - } - else - { - // hook down - if(cargo) - { - pt[0] = (cargo->absmin[0] + cargo->absmax[0])/2; - pt[1] = (cargo->absmin[1] + cargo->absmax[1])/2; - pt[2] = cargo->absmin[2] - 0.125; - content = gi.pointcontents(pt); - if(content & MASK_SOLID) - { - BeepBeep(activator); - return; - } - } - control->crane_increment = -1; - if(Crane_Hook_Bonk(hook,2,-1,bonk)) - hook->crane_bonk = max(bonk[2],hook->pos1[2]); - else - hook->crane_bonk = hook->pos1[2]; - } - hook->moveinfo.remaining_distance = control->crane_increment * - (hook->crane_bonk - hook->absmin[hook->crane_dir]); - if(hook->moveinfo.remaining_distance <= 0) - { - BeepBeep(activator); - return; - } - hook->moveinfo.remaining_distance = min(hook->moveinfo.remaining_distance,STEPSIZE); - Crane_AdjustSpeed(hook); - VectorSet(hook->moveinfo.dir,0.,0.,(float)(control->crane_increment)); - hook->crane_control = control; - if(cargo) - { - cargo->movetype = MOVETYPE_PUSH; - cargo->crane_dir = dir; - cargo->crane_bonk = hook->crane_bonk + cargo->absmin[dir] - hook->absmin[dir]; - cargo->crane_control = control; - VectorSubtract(cargo->s.origin,hook->s.origin,cargo->offset); - memcpy(&cargo->moveinfo,&hook->moveinfo,sizeof(moveinfo_t)); - } - cable->think = Cable_Think; - cable->nextthink = level.time + FRAMETIME; - - Crane_Move_Begin(hook); - if(cargo) Crane_Move_Begin(cargo); - break; - case 3: - //================== - // hook/unhook - //================== - if(row) - { - // pickup cargo - - if(hook->crane_cargo) - { - // already carrying something - BeepBeep(activator); - return; - } - VectorAdd(hook->absmin,hook->absmax,start); - VectorScale(start,0.5,start); - VectorSet(forward,0.,0.,-1.); - VectorMA(start, 8192, forward, end); - VectorSubtract(hook->absmin,start,mins); - VectorSubtract(hook->absmax,start,maxs); - // 06/03/00 change: Use 1/3 the bounding box to force a better hit - VectorScale(mins,0.3333,mins); - VectorScale(maxs,0.3333,maxs); - // end 06/03/00 change - tr=gi.trace(start, mins, maxs, end, hook, MASK_SOLID); - if((tr.fraction < 1) && (tr.ent) && (tr.ent->classname) && - (tr.ent->movetype == MOVETYPE_PUSHABLE) ) - { - Z = hook->absmin[2] - tr.ent->absmax[2]; - if(Z > MAX_PICKUP_DISTANCE) - { - gi.centerprintf(activator,"Too far\n"); - return; - } - if(CrateOnTop(NULL,tr.ent)) - { - BeepBeep(activator); - gi.dprintf("Too heavy\n"); - return; - } - // run a trace from top of cargo up... if first entity hit is NOT - // the hook, we can't get there from here. - if( Z > 0 ) - { - trace_t tr2; - - VectorMA(tr.ent->mins,0.5,tr.ent->size,start); - start[2] = tr.ent->maxs[2]; - VectorCopy(tr.ent->size,mins); - VectorScale(mins,-0.5,mins); - VectorCopy(tr.ent->size,maxs); - VectorScale(maxs,0.5,maxs); - mins[2] = maxs[2] = 0; - mins[0] += 1; mins[1] += 1; maxs[0] -= 1; maxs[1] -= 1; - VectorCopy(start,end); - end[2] += Z + 1; - tr2=gi.trace(start, mins, maxs, end, hook, MASK_SOLID); - if((tr2.fraction < 1) && tr2.ent && (tr2.ent != hook)) - { - gi.centerprintf(activator,"Blocked!\n"); - return; - } - } - Z -= CARGO_BUFFER; // leave a buffer between hook and cargo - hook->crane_cargo = cargo = tr.ent; - cargo->groundentity = NULL; - cargo->crane_control = control; - cargo->crane_hook = hook; - cargo->movetype = MOVETYPE_PUSH; - cargo->touch = NULL; - // Make cargo float up to the hook - if(Z > 0) - { - control->busy = true; - cargo->attracted = true; - cargo->gravity = 0.0; - cargo->velocity[2] = 0.0; - cargo->think = Cargo_Float_Up; - cargo->blocked = cargo_blocked; - cargo->goal_frame = level.framenum; - cargo->nextthink = level.time + FRAMETIME; - gi.linkentity(cargo); - } - else - { - gi.positioned_sound (start, cargo, CHAN_VOICE, - gi.soundindex("tank/thud.wav"), 1, 1, 0); - } - } - else - BeepBeep(activator); - } - else - { - // drop cargo - - if(hook->crane_cargo) - { - hook->crane_cargo->gravity = 1.0; - hook->crane_cargo->movetype = MOVETYPE_PUSHABLE; - hook->crane_cargo->touch = box_touch; - hook->crane_cargo->crane_control = NULL; - gi.linkentity(hook->crane_cargo); - box_movestep (hook->crane_cargo, vec3_origin, true); - hook->crane_cargo = NULL; - } - else - BeepBeep(activator); - } - } -} - -void Use_Crane_Control (edict_t *ent, edict_t *other, edict_t *activator) -{ - ent->spawnflags ^= 1; - if(ent->crane_hook->speaker) - ent->crane_hook->speaker->spawnflags = 1 - (ent->spawnflags & 1); -} - -void SP_crane_control (edict_t *self) -{ - if (!self->target) - { - gi.dprintf ("crane_control with no target at %s\n", vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_CRANE_CONTROL; - self->classname = "crane_control"; - self->solid = SOLID_BSP; - self->movetype = MOVETYPE_PUSH; - gi.setmodel (self, self->model); - self->use = Use_Crane_Control; - gi.linkentity (self); -} - -void SP_crane_hook (edict_t *self) -{ - vec3_t origin; - edict_t *speaker; - - gi.setmodel (self, self->model); - VectorAdd(self->absmin,self->absmax,origin); - VectorScale(origin,0.5,origin); - - if (!self->targetname) - { - gi.dprintf ("crane_hook with no targetname at %s\n", vtos(origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_CRANE_HOOK; - self->classname = "crane_hook"; - self->solid = SOLID_BSP; - self->movetype = MOVETYPE_PUSH; - if(st.noise) - self->noise_index = gi.soundindex(st.noise); - else - self->noise_index = 0; - if(!self->speed) self->speed = 160; - self->moveinfo.speed = self->speed; - gi.linkentity (self); - - if(self->noise_index && !VectorLength(self->s.origin) ) - { - speaker = G_Spawn(); - speaker->classname = "moving_speaker"; - speaker->s.sound = 0; - speaker->volume = 1; - speaker->attenuation = 1; - speaker->owner = self; - speaker->think = Moving_Speaker_Think; - speaker->nextthink = level.time + 2*FRAMETIME; - speaker->spawnflags = 0; // plays constantly - self->speaker = speaker; - VectorAdd(self->absmin,self->absmax,speaker->s.origin); - VectorScale(speaker->s.origin,0.5,speaker->s.origin); - VectorSubtract(speaker->s.origin,self->s.origin,speaker->offset); - } - -} - - -void SP_crane_hoist (edict_t *self) -{ - vec3_t origin; - edict_t *speaker; - - gi.setmodel (self, self->model); - VectorAdd(self->absmin,self->absmax,origin); - VectorScale(origin,0.5,origin); - - if (!self->targetname) - { - gi.dprintf ("crane_hoist with no targetname at %s\n", vtos(origin)); - G_FreeEdict (self); - return; - } - if (!self->target) - { - gi.dprintf ("crane_hoist with no target at %s\n", vtos(origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_CRANE_HOIST; - self->classname = "crane_hoist"; - self->solid = SOLID_BSP; - self->movetype = MOVETYPE_PUSH; - if(!self->speed) self->speed = 160; - self->moveinfo.speed = self->speed; - if(st.noise) - self->noise_index = gi.soundindex(st.noise); - else - self->noise_index = 0; - - gi.linkentity (self); - - if(self->noise_index && !VectorLength(self->s.origin) ) - { - speaker = G_Spawn(); - speaker->classname = "moving_speaker"; - speaker->s.sound = 0; - speaker->volume = 1; - speaker->attenuation = 1; - speaker->owner = self; - speaker->think = Moving_Speaker_Think; - speaker->nextthink = level.time + 2*FRAMETIME; - speaker->spawnflags = 7; // owner must be moving to play - self->speaker = speaker; - VectorAdd(self->absmin,self->absmax,speaker->s.origin); - VectorScale(speaker->s.origin,0.5,speaker->s.origin); - VectorSubtract(speaker->s.origin,self->s.origin,speaker->offset); - } -} - - -void SP_crane_beam (edict_t *self) -{ - vec3_t origin; - edict_t *speaker; - - gi.setmodel (self, self->model); - VectorAdd(self->absmin,self->absmax,origin); - VectorScale(origin,0.5,origin); - - if (!self->targetname) - { - gi.dprintf ("crane_beam with no targetname at %s\n", vtos(origin)); - G_FreeEdict (self); - return; - } - if (!self->target) - { - gi.dprintf ("crane_beam with no target at %s\n", vtos(origin)); - G_FreeEdict (self); - return; - } - if (!self->pathtarget) - { - gi.dprintf ("crane_beam with no pathtarget at %s\n", vtos(origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_CRANE_BEAM; - self->classname = "crane_beam"; - self->solid = SOLID_BSP; - self->movetype = MOVETYPE_PUSH; - - if(!self->speed) self->speed = 160; - self->moveinfo.speed = self->speed; - if(st.noise) - self->noise_index = gi.soundindex(st.noise); - else - self->noise_index = 0; - - gi.linkentity (self); - - if(self->noise_index && !VectorLength(self->s.origin) ) - { - speaker = G_Spawn(); - speaker->classname = "moving_speaker"; - speaker->s.sound = 0; - speaker->volume = 1; - speaker->attenuation = 1; - speaker->think = Moving_Speaker_Think; - speaker->nextthink = level.time + 2*FRAMETIME; - speaker->spawnflags = 7; // owner must be moving to play - speaker->owner = self; // this will be changed later when we know - // controls are spawned - self->speaker = speaker; - VectorAdd(self->absmin,self->absmax,speaker->s.origin); - VectorScale(speaker->s.origin,0.5,speaker->s.origin); - VectorSubtract(speaker->s.origin,self->s.origin,speaker->offset); - } -} - -//=================================================================================== - -//QUAKED crane_reset - special purpose trigger_relay that calls the associated crane -// to the beam extent closest to the crane_reset. Typically crane_reset is targeted -// by a func_button - -void crane_reset_go (edict_t *temp) -{ - edict_t *control; - control = temp->owner; - Crane_Move_Begin(control->crane_beam); - Crane_Move_Begin(control->crane_hoist); - Crane_Move_Begin(control->crane_hook); - if(control->crane_beam->crane_onboard_control) - Crane_Move_Begin(control->crane_beam->crane_onboard_control); - if(control->crane_hook->crane_cargo) Crane_Move_Begin(control->crane_hook->crane_cargo); - G_FreeEdict(temp); -} - -void crane_reset_use (edict_t *self, edict_t *other, edict_t *activator) -{ - float d1, d2; - int dir; - edict_t *delay; - edict_t *crane; - edict_t *control, *beam, *cable, *cargo, *hoist, *hook; - vec3_t bonk, v1, v2; - - - crane = G_Find (NULL, FOFS(targetname), self->target); - if(!crane) - { - gi.dprintf("Cannot find target of crane_reset at %s\n",vtos(self->s.origin)); - return; - } - control = crane->crane_control; - control->activator = activator; - - if(!(control->spawnflags & 1)) - { - if(control->message) - gi.centerprintf(activator,"%s\n",control->message); - else - gi.centerprintf(activator,"No power\n"); - return; - } - - beam = control->crane_beam; - hoist = control->crane_hoist; - hook = control->crane_hook; - cable = control->crane_cable; - cargo = hook->crane_cargo; - VectorSubtract(beam->pos1,self->s.origin,v1); - VectorSubtract(beam->pos2,self->s.origin,v2); - d1 = VectorLength(v1); - d2 = VectorLength(v2); - - if(d2 < d1) - control->crane_increment = 1; - else - control->crane_increment = -1; - - if(beam->movedir[0] > 0) - { - // travels in X - dir = 0; - if(control->crane_increment > 0) - { - if(Crane_Hook_Bonk(hook,0,1,bonk)) - { - bonk[0] += beam->absmax[0] - hook->absmax[0]; - beam->crane_bonk = min(bonk[0],beam->pos2[0]); - } - else - beam->crane_bonk = beam->pos2[0]; - beam->crane_bonk += beam->absmin[0] - beam->absmax[0]; - } - else - { - if(Crane_Hook_Bonk(hook,0,-1,bonk)) - { - bonk[0] += beam->absmin[0] - hook->absmin[0]; - beam->crane_bonk = max(bonk[0],beam->pos1[0]); - } - else - beam->crane_bonk = beam->pos1[0]; - } - } - else - { - // travels in Y - dir = 1; - if(control->crane_increment > 0) - { - if(Crane_Hook_Bonk(hook,1,1,bonk)) - { - bonk[1] += beam->absmax[1] - hook->absmax[1]; - beam->crane_bonk = min(bonk[1],beam->pos2[1]); - } - else - beam->crane_bonk = beam->pos2[1]; - beam->crane_bonk += beam->absmin[1] - beam->absmax[1]; - } - else - { - if(Crane_Hook_Bonk(hook,1,-1,bonk)) - { - bonk[1] += beam->absmin[1] - hook->absmin[1]; - beam->crane_bonk = max(bonk[1],beam->pos1[1]); - } - else - beam->crane_bonk = beam->pos1[1]; - } - } - - if(beam->speaker && beam->crane_onboard_control) - { - beam->speaker->owner = beam->crane_onboard_control; - VectorAdd(beam->crane_onboard_control->absmin, - beam->crane_onboard_control->absmax, - beam->speaker->s.origin); - VectorScale(beam->speaker->s.origin,0.5,beam->speaker->s.origin); - VectorSubtract(beam->speaker->s.origin, - beam->crane_onboard_control->s.origin,beam->speaker->offset); - beam->speaker->owner->noise_index = beam->noise_index; - } - - beam->crane_dir = dir; - beam->moveinfo.remaining_distance = control->crane_increment * - (beam->crane_bonk - beam->absmin[dir]); - if(beam->moveinfo.remaining_distance <= 0) return; - - Crane_AdjustSpeed(beam); - - VectorSet(beam->moveinfo.dir, - beam->movedir[0]*control->crane_increment, - beam->movedir[1]*control->crane_increment, - 0); - beam->crane_control = control; - - hoist->crane_dir = dir; - hoist->crane_bonk = beam->crane_bonk + hoist->absmin[dir] - beam->absmin[dir]; - hoist->crane_control = control; - memcpy(&hoist->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - - hook->crane_dir = dir; - hook->crane_bonk = beam->crane_bonk + hook->absmin[dir] - beam->absmin[dir]; - hook->crane_control = control; - memcpy(&hook->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - - cable->crane_dir = dir; - cable->crane_bonk = beam->crane_bonk + cable->absmin[dir] - beam->absmin[dir]; - cable->crane_control = control; - memcpy(&cable->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - - if(beam->crane_onboard_control) - { - beam->crane_onboard_control->crane_dir = dir; - beam->crane_onboard_control->crane_bonk = beam->crane_bonk + - beam->crane_onboard_control->absmin[dir] - - beam->absmin[dir]; - beam->crane_onboard_control->crane_control = control; - memcpy(&beam->crane_onboard_control->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - } - - if(cargo) - { - cargo->crane_dir = dir; - cargo->crane_bonk = beam->crane_bonk + cargo->absmin[dir] - beam->absmin[dir]; - cargo->crane_control = control; - memcpy(&cargo->moveinfo,&beam->moveinfo,sizeof(moveinfo_t)); - } - delay = G_Spawn(); - delay->owner = control; - delay->think = crane_reset_go; - delay->nextthink = level.time + FRAMETIME; - gi.linkentity(delay); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_crane_reset (edict_t *self) -{ - if (!self->targetname) - { - gi.dprintf ("crane_reset with no targetname at %s\n", vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - if (!self->target) - { - gi.dprintf ("crane_reset with no target at %s\n", vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_CRANE_RESET; - self->use = crane_reset_use; -} - diff --git a/server/ents/g_fog.c b/server/ents/g_fog.c deleted file mode 100644 index f76aca0b..00000000 --- a/server/ents/g_fog.c +++ /dev/null @@ -1,908 +0,0 @@ -#include "g_local.h" -#include -#define __MSC__ -#include - -#define GR_FOG_TABLE_SIZE 128 - -#define GR_FOG_DISABLE 0x0 -#define GR_FOG_WITH_TABLE 0x2 - -typedef signed long GrChromakeyMode_t; -typedef signed long GrFogMode_t; -typedef unsigned long GrColor_t; -typedef unsigned char GrAlpha_t; -typedef unsigned long GrMipMapId_t; -typedef unsigned char GrFog_t; -typedef void (__stdcall *GrProc)(); - -fog_t gfogs[MAX_FOGS]; - -fog_t trig_fade_fog; -fog_t fade_fog; -fog_t *pfog; - -GrFog_t fogtable[GR_FOG_TABLE_SIZE]; -bool fogtable_generated=false; - -HMODULE hGlide; -HMODULE hOpenGL; - -bool InTriggerFog; -float last_software_frame; -float last_3dfx_frame; -float last_opengl_frame; - -int GLModels[3] = {GL_LINEAR, GL_EXP, GL_EXP2}; - -typedef void (__stdcall *GRBUFFERCLEAR) ( GrColor_t color, GrAlpha_t alpha, unsigned short depth ); -typedef void (__stdcall *GRFOGCOLORVALUE) ( GrColor_t value ); -typedef void (__stdcall *GRFOGMODE) ( GrFogMode_t mode ); -typedef void (__stdcall *GRFOGTABLE) ( GrFog_t fogTable[GR_FOG_TABLE_SIZE] ); -typedef void (__stdcall *GUFOGGENERATEEXP) ( GrFog_t fogTable[GR_FOG_TABLE_SIZE], float density ); -typedef void (__stdcall *GUFOGGENERATEEXP2) ( GrFog_t fogTable[GR_FOG_TABLE_SIZE], float density ); -typedef void (__stdcall *GUFOGGENERATELINEAR) ( GrFog_t fogTable[GR_FOG_TABLE_SIZE], float nearW, float farW ); -GRBUFFERCLEAR Glide_grBufferClear; -GRFOGCOLORVALUE Glide_grFogColorValue; -GRFOGMODE Glide_grFogMode; -GRFOGTABLE Glide_grFogTable; -GUFOGGENERATEEXP Glide_guFogGenerateExp; -GUFOGGENERATEEXP2 Glide_guFogGenerateExp2; -GUFOGGENERATELINEAR Glide_guFogGenerateLinear; - -typedef void (__stdcall *GRCHROMAKEYMODE) ( GrChromakeyMode_t mode ); -typedef void (__stdcall *GRCHROMAKEYVALUE) ( GrColor_t value ); -GRCHROMAKEYMODE Glide_grChromakeyMode; -GRCHROMAKEYVALUE Glide_grChromakeyValue; - -//typedef void (__stdcall *GRCOLORCOMBINE) ( GrCombineFunction_t function, GrCombineFactor_t factor, -// GrCombineLocal_t local, GrCombineOther_t other, -// FxBool invert ); -//typedef void (__stdcall *GRCONSTANTCOLORVALUE) ( GrColor_t value ); -//typedef void (__stdcall *GRDRAWPOINT) ( const GrVertex *pt ); -//GRCOLORCOMBINE Glide_grColorCombine; -//GRCONSTANTCOLORVALUE Glide_grConstantColorValue; -//GRDRAWPOINT Glide_grDrawPoint; - - -typedef void (WINAPI *GLCLEARCOLOR) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -typedef void (WINAPI *GLDISABLE) (GLenum cap); -typedef void (WINAPI *GLENABLE) (GLenum cap); -typedef void (WINAPI *GLFOGF) (GLenum pname, GLfloat param); -typedef void (WINAPI *GLFOGFV) (GLenum pname, const GLfloat *params); -typedef void (WINAPI *GLFOGI) (GLenum pname, GLint param); -typedef void (WINAPI *GLHINT) (GLenum target, GLenum mode); -GLCLEARCOLOR GL_glClearColor; -GLDISABLE GL_glDisable; -GLENABLE GL_glEnable; -GLFOGF GL_glFogf; -GLFOGFV GL_glFogfv; -GLFOGI GL_glFogi; -GLHINT GL_glHint; - -#define FOG_ON 1 -#define FOG_TOGGLE 2 -#define FOG_TURNOFF 4 -#define FOG_STARTOFF 8 - -#define COLOR(r,g,b) ((((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) - -void GlideFogTable(); -void fog_fade (edict_t *self); - -void Fog_Off() -{ - if(deathmatch->value || coop->value) - return; - - if(hOpenGL) GL_glDisable (GL_FOG); -} - -void Fog_ConsoleFog() -{ - // This routine is ONLY called for console fog commands - - if(deathmatch->value || coop->value) - return; - - if(!level.active_fog) return; - - memcpy(&level.fog,&gfogs[0],sizeof(fog_t)); - pfog = &level.fog; - - // Force sensible values for linear: - if(pfog->Model==0 && pfog->Near==0. && pfog->Far==0.) - { - pfog->Near=64; - pfog->Far=1024; - } - GlideFogTable(); -} - -void Cmd_Say_f (edict_t *ent, bool team, bool arg0); -void Cmd_Fog_f(edict_t *ent) -{ - char *cmd; - char *parm; - fog_t *fog; - - fog = &gfogs[0]; - cmd = gi.argv(0); - if(gi.argc() < 2) - parm = NULL; - else - parm = gi.argv(1); - - if (strcasecmp (cmd, "fog_help") == 0 ) - { - gi.dprintf("Fog parameters for console only.\n" - "Use fog_active to see parameters for currently active fog.\n"); - - gi.dprintf("\nUse \"fog [0/1]\" to turn fog off/on (currently %s)\n" - "Current GL driver is %s\n",(level.active_fog > 0 ? "on" : "off"), gl_driver->string); - - gi.dprintf("Fog_Red = red component (0-1)\n" - "Fog_Grn = green component (0-1)\n" - "Fog_Blu = blue component (0-1)\n" - "Fog_Model 0=linear, 1=exponential, 2=exponential squared\n\n" - "Linear parameters:\n" - "Fog_Near = fog start distance (>0 and < Fog_Far)\n" - "Fog_Far = distance where objects are completely obscured\n" - " (<5000 and > Fog_Near)\n" - "Exponential parameters:\n" - "Fog_Density Best results with values < 100\n\n" - "Command without a value will show current setting\n"); - } - else if(strcasecmp (cmd, "fog_active") == 0 ) - { - if(level.active_fog) - { - gi.dprintf("Active fog:\n" - " Color: %f, %f, %f\n" - " Model: %s\n", - level.fog.Color[0],level.fog.Color[1],level.fog.Color[2], - (level.fog.Model==1 ? "Exp" : (level.fog.Model==2 ? "Exp2" : "Linear"))); - if(level.fog.Model) - gi.dprintf("Density: %f\n",level.fog.Density); - else - { - gi.dprintf(" Near: %f\n",level.fog.Near); - gi.dprintf(" Far: %f\n",level.fog.Far); - } - } - else - gi.dprintf("No fogs currently active\n"); - } - else if(strcasecmp (cmd, "fog_stuff") == 0 ) - { - gi.dprintf("active_fog=%d, last_active_fog=%d\n",level.active_fog,level.last_active_fog); - } - else if(strcasecmp (cmd, "fog") == 0 ) - { - if(parm) - { - int on; - on = atoi(parm); - level.active_fog = level.active_target_fog = (on ? 1 : 0); - Fog_ConsoleFog(); - } - gi.dprintf("fog is %s\n",(level.active_fog ? "on" : "off")); - } - else if(strcasecmp (cmd, "Fog_Red") == 0 ) - { - if(!parm) - gi.dprintf("%s = %f\n",cmd,fog->Color[0]); - else - { - level.active_fog = level.active_target_fog = 1; - fog->Color[0] = max(0.0f,min(1.0f,(float)atof(parm))); - fog->GlideColor[0] = (int)(255 * fog->Color[0]); - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_Grn") == 0 ) - { - if(!parm) - gi.dprintf("%s = %f\n",cmd,fog->Color[1]); - else - { - level.active_fog = level.active_target_fog = 1; - fog->Color[1] = max(0.0f,min(1.0f,(float)atof(parm))); - fog->GlideColor[1] = (int)(255 * fog->Color[1]); - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_Blu") == 0 ) - { - if(!parm) - gi.dprintf("%s = %f\n",cmd,fog->Color[2]); - else - { - level.active_fog = level.active_target_fog = 1; - fog->Color[2] = max(0.0f,min(1.0f,(float)atof(parm))); - fog->GlideColor[2] = (int)(255 * fog->Color[2]); - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_Near") == 0 ) - { - if(!parm) - gi.dprintf("%s = %f\n",cmd,fog->Near); - else - { - level.active_fog = level.active_target_fog = 1; - fog->Near = (float)atof(parm); - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_Far") == 0 ) - { - if(!parm) - gi.dprintf("%s = %f\n",cmd,fog->Far); - else - { - level.active_fog = level.active_target_fog = 1; - fog->Far = (float)atof(parm); - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_Model") == 0 ) - { - if(!parm) - gi.dprintf("%s = %d\n0=Linear\n1=Exp\n2=Exp2\n",cmd,fog->Model); - else - { - level.active_fog = level.active_target_fog = 1; -// fog->Model = max(0,min(2,atoi(parm))); - fog->Model = max(0,min(3,atoi(parm))); - if(fog->Model == 3) - fog->GL_Model = GLModels[2]; - else - fog->GL_Model = GLModels[fog->Model]; - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_Density") == 0 ) - { - if(!parm) - gi.dprintf("%s = %f\n",cmd,fog->Density); - else - { - level.active_fog = level.active_target_fog = 1; - fog->Density = fog->Density1 = fog->Density2 = (float)atof(parm); - Fog_ConsoleFog(); - } - } - else if(strcasecmp (cmd, "Fog_List") == 0 ) - { - int i; - - gi.dprintf("level.fogs=%d\n",level.fogs); - gi.dprintf("level.trigger_fogs=%d\n",level.trigger_fogs); - for(i=0; iTrigger ? "true" : "false")); - gi.dprintf("Model=%d, Near=%g, Far=%g, Density=%g\n", - pfog->Model, pfog->Near, pfog->Far, pfog->Density); - gi.dprintf("Color=%g,%g,%g\n",pfog->Color[0],pfog->Color[1],pfog->Color[2]); - gi.dprintf("Targetname=%s\n",(pfog->ent ? pfog->ent->targetname : "no ent")); - } - } - else - Cmd_Say_f (ent, false, true); -} - -/* -void SoftwareFog() -{ - edict_t *player = &g_edicts[1]; - - player->client->fadein = level.framenum - 1; - player->client->fadehold = level.framenum + 2; - player->client->fadeout = 0; - player->client->fadecolor[0] = pfog->Color[0]; - player->client->fadecolor[1] = pfog->Color[1]; - player->client->fadecolor[2] = pfog->Color[2]; - - if(pfog->Model == 0) - player->client->fadealpha = pfog->Far/256.; - else if(pfog->Model == 1) - player->client->fadealpha = pfog->Density/30; - else - player->client->fadealpha = pfog->Density/15; - - if(player->client->fadealpha > 0.9) - player->client->fadealpha = 0.9; - - last_software_frame = level.framenum; - -} -*/ - -void GlideFogTable() -{ - int i; - float density; - float w, dw4; - - if(!hGlide) return; - if(last_software_frame + 10 > level.framenum) return; - if(last_opengl_frame + 10 > level.framenum) return; - - switch(pfog->Model) - { - case 1: - Glide_guFogGenerateExp( fogtable, pfog->Density/10000.f ); - break; - case 2: - Glide_guFogGenerateExp2( fogtable, pfog->Density/10000.f ); - break; - case 3: - // Home-grown EXP4 model - density = pfog->Density/10000.f; - for(i=0; iNear, pfog->Far); - } - fogtable_generated=true; -} - -void GlideFog() -{ - GrColor_t color; - - if(!hGlide) return; - if(last_software_frame + 10 > level.framenum) return; - if(last_opengl_frame + 10 > level.framenum) return; - if(!fogtable_generated) GlideFogTable(); - -// gi.dprintf("Name=%s, Model=%d, Near=%g, Far=%g, Density=%g, Color=%g,%g,%g\n", -// pfog->ent->targetname, pfog->Model,pfog->Near, pfog->Far, pfog->Density, -// pfog->GlideColor[0],pfog->GlideColor[1],pfog->GlideColor[2]); - - Glide_grFogTable( fogtable ); - color = COLOR(pfog->GlideColor[0],pfog->GlideColor[1],pfog->GlideColor[2]); - Glide_grBufferClear( color, (unsigned char)0, (unsigned short)0); - Glide_grFogColorValue( color ); - Glide_grFogMode( GR_FOG_WITH_TABLE ); - - last_3dfx_frame = level.framenum; -} - -void GLFog() -{ - GLfloat fogColor[4]; - if(!hOpenGL) return; - fogColor[0] = pfog->Color[0]; - fogColor[1] = pfog->Color[1]; - fogColor[2] = pfog->Color[2]; - fogColor[3] = 1.0; - GL_glEnable (GL_FOG); // turn on fog, otherwise you won't see any - GL_glClearColor ( fogColor[0], fogColor[1], fogColor[2], fogColor[3]); // Clear the background color to the fog color - GL_glFogi (GL_FOG_MODE, pfog->GL_Model); - GL_glFogfv (GL_FOG_COLOR, fogColor); - if(pfog->GL_Model == GL_LINEAR) - { - GL_glFogf (GL_FOG_START, pfog->Near); - GL_glFogf (GL_FOG_END, pfog->Far); - } - else - GL_glFogf (GL_FOG_DENSITY, pfog->Density/10000.f); - GL_glHint (GL_FOG_HINT, GL_NICEST); - - last_opengl_frame = level.framenum; -} - -void trig_fog_fade (edict_t *self) -{ - float frames; - int index; - - if(!InTriggerFog) - { - self->nextthink = 0; - return; - } - if(level.framenum <= self->goal_frame) - { - index = self->fog_index-1; - frames = self->goal_frame - level.framenum + 1; - if(trig_fade_fog.Model == 0) - { - trig_fade_fog.Near += (gfogs[index].Near - trig_fade_fog.Near)/frames; - trig_fade_fog.Far += (gfogs[index].Far - trig_fade_fog.Far )/frames; - } - else - { - trig_fade_fog.Density += (gfogs[index].Density - trig_fade_fog.Density) /frames; - trig_fade_fog.Density1 += (gfogs[index].Density1 - trig_fade_fog.Density1)/frames; - trig_fade_fog.Density2 += (gfogs[index].Density2 - trig_fade_fog.Density2)/frames; - } - trig_fade_fog.Color[0] += (gfogs[index].Color[0] - trig_fade_fog.Color[0])/frames; - trig_fade_fog.Color[1] += (gfogs[index].Color[1] - trig_fade_fog.Color[1])/frames; - trig_fade_fog.Color[2] += (gfogs[index].Color[2] - trig_fade_fog.Color[2])/frames; - VectorScale(trig_fade_fog.Color,255,trig_fade_fog.GlideColor); - trig_fade_fog.GL_Model = GLModels[trig_fade_fog.Model]; - self->nextthink = level.time + FRAMETIME; - fogtable_generated = false; - gi.linkentity(self); - } -} - -void init_trigger_fog_delay (edict_t *self) -{ - int i; - int index; - edict_t *e; - - index = self->fog_index-1; - - // scan for other trigger_fog's that are currently "thinking", iow - // the trigger_fog has a delay and is ramping. If found, stop the ramp for those fogs - for(i=1, e=g_edicts+i; iinuse) continue; - if(e == self) continue; - if(e->think == trig_fog_fade || e->think == fog_fade) - { - e->think = NULL; - e->nextthink = 0; - gi.linkentity(e); - } - } - - self->spawnflags |= FOG_ON; - if(!level.active_fog) - { - // Fog isn't currently on - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - level.fog.Near = 4999.; - level.fog.Far = 5000.; - level.fog.Density = 0.0; - level.fog.Density1 = 0.0; - level.fog.Density2 = 0.0; - } - VectorCopy(self->fog_color,gfogs[index].Color); - VectorScale(self->fog_color,255,gfogs[index].GlideColor); - gfogs[index].Near = self->fog_near; - gfogs[index].Far = self->fog_far; - gfogs[index].Density = self->fog_density; - gfogs[index].Density1 = self->fog_density; - gfogs[index].Density2 = self->density; - self->goal_frame = level.framenum + self->delay*10 + 1; - self->think = trig_fog_fade; - self->nextthink = level.time + FRAMETIME; - memcpy(&trig_fade_fog,&level.fog,sizeof(fog_t)); - level.active_fog = self->fog_index; -} - -void Fog(vec3_t viewpoint) -{ - edict_t *triggerfog; - edict_t *player = &g_edicts[1]; - - if(deathmatch->value || coop->value) - return; - - InTriggerFog = false; - if(level.trigger_fogs) - { - int i; - int trigger; - trigger=0; - for(i=1; iinuse) continue; - if(!(gfogs[i].ent->spawnflags & FOG_ON)) continue; - if(viewpoint[0] < gfogs[i].ent->absmin[0]) continue; - if(viewpoint[0] > gfogs[i].ent->absmax[0]) continue; - if(viewpoint[1] < gfogs[i].ent->absmin[1]) continue; - if(viewpoint[1] > gfogs[i].ent->absmax[1]) continue; - if(viewpoint[2] < gfogs[i].ent->absmin[2]) continue; - if(viewpoint[2] > gfogs[i].ent->absmax[2]) continue; - trigger = i; - break; - } - if(trigger) - { - InTriggerFog = true; - triggerfog = gfogs[trigger].ent; - - if(level.last_active_fog != trigger+1) - { - if(triggerfog->delay) - init_trigger_fog_delay(triggerfog); - else - memcpy(&level.fog,&gfogs[trigger],sizeof(fog_t)); - level.active_fog = trigger+1; - } - else if(triggerfog->delay) - memcpy(&level.fog,&trig_fade_fog,sizeof(fog_t)); - } - else - { - InTriggerFog = false; - level.active_fog = level.active_target_fog; - // if we are just coming out of a trigger_fog, force - // level.fog to last active target_fog values - if(level.active_fog && level.last_active_fog && gfogs[level.last_active_fog-1].Trigger) - { - edict_t *ent = gfogs[level.active_fog-1].ent; - if(ent && (ent->think == fog_fade)) - ent->think(ent); - else - memcpy(&level.fog,&gfogs[level.active_fog-1],sizeof(fog_t)); - } - } - } - - if(!level.active_fog) { - if(level.last_active_fog) - Fog_Off(); - level.last_active_fog = 0; - return; - } - - pfog = &level.fog; - if(level.last_active_fog != level.active_fog) - fogtable_generated = false; - if((pfog->Density1 != pfog->Density2) && (game.maxclients == 1) && (pfog->Model)) - { - float density; - float dp; - vec3_t vp; - - AngleVectors(player->client->ps.viewangles,vp,0,0); - dp = DotProduct(pfog->Dir,vp) + 1.0; - density = ((pfog->Density1*dp) + (pfog->Density2*(2.0-dp)))/2.; - if(pfog->Density != density) - { - pfog->Density = density; - fogtable_generated = false; - } - } -// if(!fogtable_generated) - { - if(!strcmp(gl_driver->string,"3dfxgl")) - GlideFog(); - else - GLFog(); - } - level.last_active_fog = level.active_fog; -} - -void Fog_Init() -{ - char GL_Lib[64]; - - hGlide = LoadLibrary("glide2x.dll"); - if(hGlide) - { - Glide_grBufferClear = (GRBUFFERCLEAR)GetProcAddress(hGlide,"_grBufferClear@12"); - Glide_grFogColorValue = (GRFOGCOLORVALUE)GetProcAddress(hGlide,"_grFogColorValue@4"); - Glide_grFogMode = (GRFOGMODE)GetProcAddress(hGlide,"_grFogMode@4"); - Glide_grFogTable = (GRFOGTABLE)GetProcAddress(hGlide,"_grFogTable@4"); - Glide_guFogGenerateExp = (GUFOGGENERATEEXP)GetProcAddress(hGlide,"_guFogGenerateExp@8"); - Glide_guFogGenerateExp2 = (GUFOGGENERATEEXP2)GetProcAddress(hGlide,"_guFogGenerateExp2@8"); - Glide_guFogGenerateLinear = (GUFOGGENERATELINEAR)GetProcAddress(hGlide,"_guFogGenerateLinear@12"); - - Glide_grChromakeyMode = (GRCHROMAKEYMODE)GetProcAddress(hGlide,"_grChromakeyMode@4"); - Glide_grChromakeyValue = (GRCHROMAKEYVALUE)GetProcAddress(hGlide,"_grChromakeyValue@4"); - -// Glide_grColorCombine = (GRCOLORCOMBINE)GetProcAddress(hGlide,"_grColorCombine@20"); -// Glide_grConstantColorValue= (GRCONSTANTCOLORVALUE)GetProcAddress(hGlide,"_grConstantColorValue@4"); -// Glide_grDrawPoint = (GRDRAWPOINT)GetProcAddress(hGlide,"_grDrawPoint@4"); - } - - if(gl_driver_fog && strlen(gl_driver_fog->string)) - strcpy(GL_Lib,gl_driver_fog->string); - else - strcpy(GL_Lib,"opengl32"); - strcat(GL_Lib,".dll"); - hOpenGL = LoadLibrary(GL_Lib); - if(hOpenGL) - { - GL_glClearColor = (GLCLEARCOLOR)GetProcAddress(hOpenGL,"glClearColor"); - GL_glDisable = (GLDISABLE)GetProcAddress(hOpenGL,"glDisable"); - GL_glEnable = (GLENABLE)GetProcAddress(hOpenGL,"glEnable"); - GL_glFogf = (GLFOGF)GetProcAddress(hOpenGL,"glFogf"); - GL_glFogfv = (GLFOGFV)GetProcAddress(hOpenGL,"glFogfv"); - GL_glFogi = (GLFOGI)GetProcAddress(hOpenGL,"glFogi"); - GL_glHint = (GLHINT)GetProcAddress(hOpenGL,"glHint"); - } - - gfogs[0].Color[0] = gfogs[0].Color[1] = gfogs[0].Color[2] = 0.5; - gfogs[0].GlideColor[0] = gfogs[0].GlideColor[1] = gfogs[0].GlideColor[2] = 127.; - gfogs[0].Model = 1; - gfogs[0].GL_Model = GLModels[1]; - gfogs[0].Density = 20.; - gfogs[0].Trigger = false; -} - - -void fog_fade (edict_t *self) -{ - float frames; - int index; - - if(level.framenum <= self->goal_frame) - { - index = self->fog_index-1; - frames = self->goal_frame - level.framenum + 1; - if(fade_fog.Model == 0) - { - fade_fog.Near += (gfogs[index].Near - fade_fog.Near)/frames; - fade_fog.Far += (gfogs[index].Far - fade_fog.Far )/frames; - } - else - { - fade_fog.Density += (gfogs[index].Density - fade_fog.Density) /frames; - fade_fog.Density1 += (gfogs[index].Density1 - fade_fog.Density1)/frames; - fade_fog.Density2 += (gfogs[index].Density2 - fade_fog.Density2)/frames; - } - fade_fog.Color[0] += (gfogs[index].Color[0] - fade_fog.Color[0])/frames; - fade_fog.Color[1] += (gfogs[index].Color[1] - fade_fog.Color[1])/frames; - fade_fog.Color[2] += (gfogs[index].Color[2] - fade_fog.Color[2])/frames; - VectorScale(fade_fog.Color,255,fade_fog.GlideColor); - fade_fog.GL_Model = GLModels[fade_fog.Model]; - self->nextthink = level.time + FRAMETIME; - if(!InTriggerFog) - memcpy(&level.fog,&fade_fog,sizeof(fog_t)); - fogtable_generated = false; - gi.linkentity(self); - } - else - { -// if(!(self->spawnflags & FOG_ON)) - if(self->spawnflags & FOG_TURNOFF) - level.active_fog = level.active_target_fog = 0; - } -} - -void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) -{ - int i; - int index; - edict_t *e; - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + self->delay + 1; - } - - if((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) - { - self->spawnflags &= ~FOG_ON; - return; - } - else - self->spawnflags |= FOG_ON; - - index = self->fog_index-1; - - InTriggerFog = false; - - // scan for other target_fog's that are currently "thinking", iow - // the target_fog has a delay and is ramping. If found, stop the ramp for those fogs - for(i=1, e=g_edicts+i; iinuse) continue; - if(e->think == fog_fade) - { - e->nextthink = 0; - gi.linkentity(e); - } - } - - if(self->spawnflags & FOG_TURNOFF) - { - // Fog is "turn off" only - - if( self->delay && level.active_fog ) - { - gfogs[index].Far = 5000.0; - gfogs[index].Near = 4999.0; - gfogs[index].Density = 0.0; - gfogs[index].Density1 = 0.0; - gfogs[index].Density2 = 0.0; - VectorCopy(level.fog.Color,gfogs[index].Color); - VectorScale(level.fog.Color,255,gfogs[index].GlideColor); - self->goal_frame = level.framenum + self->delay*10 + 1; - self->think = fog_fade; - self->nextthink = level.time + FRAMETIME; - level.active_fog = level.active_target_fog = self->fog_index; - memcpy(&fade_fog,&level.fog,sizeof(fog_t)); - } - else - level.active_fog = level.active_target_fog = 0; - } - else - { - if(self->delay) - { - if(!level.active_fog) - { - // Fog isn't currently on - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - level.fog.Near = 4999.; - level.fog.Far = 5000.; - level.fog.Density = 0.0; - level.fog.Density1 = 0.0; - level.fog.Density2 = 0.0; - } - VectorCopy(self->fog_color,gfogs[index].Color); - VectorScale(self->fog_color,255,gfogs[index].GlideColor); - gfogs[index].Near = self->fog_near; - gfogs[index].Far = self->fog_far; - gfogs[index].Density = self->fog_density; - gfogs[index].Density1 = self->fog_density; - gfogs[index].Density2 = self->density; - self->goal_frame = level.framenum + self->delay*10 + 1; - self->think = fog_fade; - self->nextthink = level.time + FRAMETIME; - memcpy(&fade_fog,&level.fog,sizeof(fog_t)); - } else { - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - } - level.active_fog = level.active_target_fog = self->fog_index; - } -} - -void SP_target_fog (edict_t *self) -{ - fog_t *fog; - - if( !allow_fog->value ) - { - G_FreeEdict(self); - return; - } - if(deathmatch->value || coop->value) - { - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_FOG; - - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands - - if(level.fogs >= MAX_FOGS) - { - gi.dprintf("Maximum number of fogs exceeded!\n"); - G_FreeEdict(self); - return; - } - - if( self->delay < 0.) - self->delay = 0.; - - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; - fog->Trigger = false; - fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; - fog->GL_Model = GLModels[fog->Model]; - VectorCopy(self->fog_color,fog->Color); - VectorScale(self->fog_color,255,fog->GlideColor); - if(self->spawnflags & FOG_TURNOFF) { - fog->Near = 4999; - fog->Far = 5000; - fog->Density = 0; - fog->Density1 = 0; - fog->Density2 = 0; - } else { - fog->Near = self->fog_near; - fog->Far = self->fog_far; - fog->Density = self->fog_density; - fog->Density1 = self->fog_density; - if(self->density == 0.) - self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; - } - AngleVectors(self->s.angles,fog->Dir,0,0); - fog->ent = self; - level.fogs++; - self->use = target_fog_use; - gi.linkentity(self); - - if(self->spawnflags & FOG_ON) - { - self->spawnflags &= ~FOG_ON; - target_fog_use(self,NULL,NULL); - } -} - -void trigger_fog_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) - { - self->spawnflags &= ~FOG_ON; - self->count--; - if(!self->count) - { - self->think = G_FreeEdict; - self->nextthink = level.time + FRAMETIME; - } - } - else - { - self->spawnflags |= FOG_ON; - } -} - -void SP_trigger_fog (edict_t *self) -{ - fog_t *fog; - - if( !allow_fog->value ) - { - G_FreeEdict(self); - return; - } - if(deathmatch->value || coop->value) - { - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TRIGGER_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands - - if(level.fogs >= MAX_FOGS) - { - gi.dprintf("Maximum number of fogs exceeded!\n"); - G_FreeEdict(self); - return; - } - - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; - fog->Trigger = true; - fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; - fog->GL_Model = GLModels[fog->Model]; - VectorCopy(self->fog_color,fog->Color); - VectorScale(self->fog_color,255,fog->GlideColor); - if(self->spawnflags & FOG_TURNOFF) { - fog->Near = 4999; - fog->Far = 5000; - fog->Density = 0; - fog->Density1 = 0; - fog->Density2 = 0; - } else { - fog->Near = self->fog_near; - fog->Far = self->fog_far; - fog->Density = self->fog_density; - fog->Density1 = self->fog_density; - if(self->density == 0.) - self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; - } - if(!(self->spawnflags & FOG_STARTOFF)) - self->spawnflags |= FOG_ON; - - AngleVectors(self->s.angles,fog->Dir,0,0); - VectorClear(self->s.angles); - fog->ent = self; - level.fogs++; - level.trigger_fogs++; - self->movetype = MOVETYPE_NONE; - self->svflags |= SVF_NOCLIENT; - self->solid = SOLID_NOT; - gi.setmodel (self, self->model); - gi.linkentity(self); -} \ No newline at end of file diff --git a/server/ents/g_func.c b/server/ents/g_func.c deleted file mode 100644 index b35f2350..00000000 --- a/server/ents/g_func.c +++ /dev/null @@ -1,4450 +0,0 @@ -#include "g_local.h" - -// Lazarus: universal change to all sound-playing pushers. If s.sound is 0, then sound_end is NOT -// played. Only way s.sound might be 0 is if pusher was blocked in physics code, since -// all enitities that have a sound_end also have a sound_middle. - -void bob_init (edict_t *self); - -#define STATE_TOP 0 -#define STATE_BOTTOM 1 -#define STATE_UP 2 -#define STATE_DOWN 3 -#define PLAT_LOW_TRIGGER 1 -#define DOOR_START_OPEN 1 -#define DOOR_REVERSE 2 -#define DOOR_CRUSHER 4 -#define DOOR_NOMONSTER 8 -#define DOOR_TOGGLE 32 -#define DOOR_X_AXIS 64 -#define DOOR_Y_AXIS 128 - -#define SF_DOOR_DESTROY 2048 - -void Move_Done (edict_t *ent); -void train_blocked (edict_t *self, edict_t *other); -void set_child_movement(edict_t *self) -{ - edict_t *e; - edict_t *parent; - vec3_t forward, right, up; - vec3_t angles, amove; - vec3_t offset; - vec3_t delta_angles; - bool is_monster; - - if(!self->inuse) - return; - - e = self->movewith_next; - parent = self; - while(e != NULL) - { -restart: - if(!e->inuse) break; - - VectorSubtract(self->s.angles,e->parent_attach_angles,delta_angles); - AngleVectors(delta_angles,forward,right,up); - VectorNegate(right,right); - - // remove gibbed monsters from the chain - if(e->svflags & SVF_MONSTER) { - if(e->health <= e->gib_health) { - parent->movewith_next = e->movewith_next; - e = e->movewith_next; - if(e) - goto restart; - else - break; - } - is_monster = true; - } else - is_monster = false; - - // For all but func_button and func_door, move origin and match velocities - if( (e->class_id != ENTITY_FUNC_DOOR) && (e->class_id != ENTITY_FUNC_BUTTON)) { - - VectorMA(self->s.origin, e->movewith_offset[0], forward, e->s.origin); - VectorMA(e->s.origin, e->movewith_offset[1], right, e->s.origin); - VectorMA(e->s.origin, e->movewith_offset[2], up, e->s.origin); - VectorCopy(self->velocity,e->velocity); - } - - // If parent is spinning, add appropriate velocities - VectorSubtract(e->s.origin,self->s.origin,offset); - if(self->avelocity[PITCH] != 0) { - e->velocity[2] -= offset[0] * self->avelocity[PITCH] * M_PI / 180; - e->velocity[0] += offset[2] * self->avelocity[PITCH] * M_PI / 180; - } - if(self->avelocity[YAW] != 0) { - e->velocity[0] -= offset[1] * self->avelocity[YAW] * M_PI / 180.; - e->velocity[1] += offset[0] * self->avelocity[YAW] * M_PI / 180.; - } - if(self->avelocity[ROLL] != 0) { - e->velocity[1] -= offset[2] * self->avelocity[ROLL] * M_PI / 180; - e->velocity[2] += offset[1] * self->avelocity[ROLL] * M_PI / 180; - } - - VectorScale(self->avelocity,FRAMETIME,amove); - if(self->turn_rider) { - // Match angular velocities - if(e->class_id == ENTITY_FUNC_ROTATING) { - float cr, sr; - float cy, sy; - cy = cos((e->s.angles[1]-delta_angles[1])*M_PI/180); - sy = sin((e->s.angles[1]-delta_angles[1])*M_PI/180); - cr = cos((e->s.angles[2]-delta_angles[2])*M_PI/180); - sr = sin((e->s.angles[2]-delta_angles[2])*M_PI/180); - if(e->movedir[0] > 0) { - e->s.angles[1] = delta_angles[1]; - } else if(e->movedir[1] > 0) { - e->s.angles[1] += amove[1]; - e->s.angles[2] = delta_angles[2]*cy; - e->s.angles[0] = -delta_angles[2]*sy; - } else if(e->movedir[2] > 0) { - e->s.angles[1] = delta_angles[0]*-sy; - } - } - else if( !is_monster ) - { // Not a monster/actor. We want monsters/actors to be able to turn on - // their own. - if( !e->do_not_rotate ) - { - if( (e->class_id == ENTITY_TURRET_BREACH) || (e->class_id == ENTITY_TURRET_BASE) ) - { - VectorCopy(self->avelocity,e->avelocity); - } - else if(e->class_id == ENTITY_FUNC_DOOR_ROTATING) - { - VectorCopy(self->avelocity,e->avelocity); - VectorCopy(delta_angles,e->pos1); - VectorMA (e->pos1, e->moveinfo.distance, e->movedir, e->pos2); - if(e->moveinfo.state == STATE_TOP) - { - VectorCopy (e->pos2, e->s.angles); - } - else - { - VectorCopy (e->pos1, e->s.angles); - } - VectorCopy (e->s.origin, e->moveinfo.start_origin); - VectorCopy (e->pos1, e->moveinfo.start_angles); - VectorCopy (e->s.origin, e->moveinfo.end_origin); - VectorCopy (e->pos2, e->moveinfo.end_angles); - } - else if(e->solid == SOLID_BSP) - { - // Brush models always start out with angles=0,0,0 (after - // G_SetMoveDir). Use more accuracy here - VectorCopy(self->avelocity,e->avelocity); - VectorCopy(delta_angles,e->s.angles); - } - else if(e->movetype == MOVETYPE_NONE) - { - VectorCopy(self->avelocity,e->avelocity); - VectorCopy(delta_angles,e->s.angles); - } - else - { - // For point entities, best we can do is apply a delta to - // the angles. This may result in foulups if anything - // gets blocked - VectorAdd(e->s.angles,amove,e->s.angles); - } - } - } - } - - // Special cases: - // Func_door/func_button and trigger fields - if( (e->class_id == ENTITY_FUNC_DOOR) || (e->class_id == ENTITY_FUNC_BUTTON) ) - { - - VectorAdd(e->s.angles,e->org_angles,angles); - G_SetMovedir (angles, e->movedir); - VectorMA(self->s.origin, e->movewith_offset[0], forward, e->pos1); - VectorMA(e->pos1, e->movewith_offset[1], right, e->pos1); - VectorMA(e->pos1, e->movewith_offset[2], up, e->pos1); - VectorMA (e->pos1, e->moveinfo.distance, e->movedir, e->pos2); - VectorCopy(e->pos1, e->moveinfo.start_origin); - VectorCopy(e->s.angles, e->moveinfo.start_angles); - VectorCopy(e->pos2, e->moveinfo.end_origin); - VectorCopy(e->s.angles, e->moveinfo.end_angles); - if(e->moveinfo.state == STATE_BOTTOM || e->moveinfo.state == STATE_TOP) - { - // Velocities for door/button movement are handled in normal - // movement routines - VectorCopy(self->velocity,e->velocity); - // Sanity insurance: - if(e->moveinfo.state == STATE_BOTTOM) - { - VectorCopy(e->pos1, e->s.origin); - } - else - { - VectorCopy(e->pos2, e->s.origin); - } - } - } - - if(amove[YAW]) - { - // Cross fingers here... move bounding boxes of doors and buttons - if( (e->class_id == ENTITY_FUNC_DOOR) || - (e->class_id == ENTITY_FUNC_BUTTON) || - (e->solid == SOLID_TRIGGER) ) - { - float ca, sa, yaw; - vec3_t p00, p01, p10, p11; - - // Adjust bounding box for yaw - yaw = e->s.angles[YAW] * M_PI / 180.; - ca = cos(yaw); - sa = sin(yaw); - p00[0] = e->org_mins[0]*ca - e->org_mins[1]*sa; - p00[1] = e->org_mins[1]*ca + e->org_mins[0]*sa; - p01[0] = e->org_mins[0]*ca - e->org_maxs[1]*sa; - p01[1] = e->org_maxs[1]*ca + e->org_mins[0]*sa; - p10[0] = e->org_maxs[0]*ca - e->org_mins[1]*sa; - p10[1] = e->org_mins[1]*ca + e->org_maxs[0]*sa; - p11[0] = e->org_maxs[0]*ca - e->org_maxs[1]*sa; - p11[1] = e->org_maxs[1]*ca + e->org_maxs[0]*sa; - e->mins[0] = p00[0]; - e->mins[0] = min(e->mins[0],p01[0]); - e->mins[0] = min(e->mins[0],p10[0]); - e->mins[0] = min(e->mins[0],p11[0]); - e->mins[1] = p00[1]; - e->mins[1] = min(e->mins[1],p01[1]); - e->mins[1] = min(e->mins[1],p10[1]); - e->mins[1] = min(e->mins[1],p11[1]); - e->maxs[0] = p00[0]; - e->maxs[0] = max(e->maxs[0],p01[0]); - e->maxs[0] = max(e->maxs[0],p10[0]); - e->maxs[0] = max(e->maxs[0],p11[0]); - e->maxs[1] = p00[1]; - e->maxs[1] = max(e->maxs[1],p01[1]); - e->maxs[1] = max(e->maxs[1],p10[1]); - e->maxs[1] = max(e->maxs[1],p11[1]); - } - } - - // FMOD - if(e->class_id == ENTITY_TARGET_PLAYBACK) - FMOD_UpdateSpeakerPos(e); - - e->s.event = self->s.event; - gi.linkentity(e); - parent = e; - e = e->movewith_next; - } -} - -void movewith_update(edict_t *self) -{ - if(self->moveinfo.state == STATE_BOTTOM) { - VectorCopy(self->s.origin,self->pos1); - VectorMA(self->pos1, self->moveinfo.distance, self->movedir, self->pos2); - } else if(self->moveinfo.state == STATE_TOP) { - VectorCopy(self->s.origin,self->pos2); - VectorMA(self->pos2, -self->moveinfo.distance, self->movedir, self->pos1); - } - VectorCopy(self->pos1, self->moveinfo.start_origin); - VectorCopy(self->pos2, self->moveinfo.end_origin); -} - -void spline_calc (edict_t *train, vec3_t p1, vec3_t p2, vec3_t a1, vec3_t a2, float m, vec3_t p, vec3_t a) -{ - /* p1, p2 = origins of path_* ents - a1, a2 = angles from path_* ents - m = decimal position along curve */ - - vec3_t v1, v2; // direction vectors - vec3_t c1, c2; // control-point coords - vec3_t d, v; // temps - float s; // vector scale - // these greatly simplify/speed up equations - // (make sure m is already assigned a value) - float n = 1.0 - m; - float m2 = m * m; - float m3 = m2 * m; - float n2 = n * n; - float n3 = n2 * n; - float mn2_3 = m * n2 * 3; - float m2n_3 = m2 * n * 3; - float mn_2 = m * n * 2; - - // Beziers need two control-points to define the shape of the curve. - // These can be created from the available data. They are offset a - // specific distance from the endpoints (path_*s), in the direction - // of the endpoints' angle vectors (the 2nd control-point is offset in - // the opposite direction). The distance used is a fraction of the total - // distance between the endpoints, ensuring it's scaled proportionally. - // The factor of 0.4 is simply based on experimentation, as a value that - // yields nice even curves. - - AngleVectors(a1, v1, NULL, NULL); - AngleVectors(a2, v2, NULL, NULL); - - VectorSubtract(p2, p1, d); - s = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) * 0.4; - - VectorMA(p1, s, v1, c1); - VectorMA(p2, -s, v2, c2); - - // cubic interpolation of the four points - // gives the position along the curve - p[0] = n3 * p1[0] + mn2_3 * c1[0] + m2n_3 * c2[0] + m3 * p2[0]; - p[1] = n3 * p1[1] + mn2_3 * c1[1] + m2n_3 * c2[1] + m3 * p2[1]; - p[2] = n3 * p1[2] + mn2_3 * c1[2] + m2n_3 * c2[2] + m3 * p2[2]; - - // should be optional: - // first derivative of bezier formula provides direction vector - // along the curve (equation simplified in terms of m & n) - v[0] = (n2 * p1[0] - (n2 - mn_2) * c1[0] - (mn_2 - m2) * c2[0] - m2 * p2[0]) / -s; - v[1] = (n2 * p1[1] - (n2 - mn_2) * c1[1] - (mn_2 - m2) * c2[1] - m2 * p2[1]) / -s; - v[2] = (n2 * p1[2] - (n2 - mn_2) * c1[2] - (mn_2 - m2) * c2[2] - m2 * p2[2]) / -s; - vectoangles2(v, a); - a[ROLL] = a1[ROLL] + m*(a2[ROLL] - a1[ROLL]); -} - -void train_wait (edict_t *self); -void train_spline (edict_t *self) -{ - edict_t *train; - vec3_t p; - vec3_t a; - - train = self->enemy; - if(!train || !train->inuse) - return; - if( (train->from != train->to) && !train->moveinfo.is_blocked && (train->spawnflags & TRAIN_START_ON)) - { - spline_calc (train, train->from->s.origin, train->to->s.origin, - train->from->s.angles, train->to->s.angles, - train->moveinfo.ratio, p, a); - VectorSubtract(p,train->mins,p); - VectorSubtract(p,train->s.origin,train->velocity); - VectorScale(train->velocity,10,train->velocity); - VectorSubtract(a,train->s.angles,train->avelocity); - VectorScale(train->avelocity,10,train->avelocity); - if(train->pitch_speed < 0) - train->avelocity[PITCH] = 0; - if(train->yaw_speed < 0) - train->avelocity[YAW] = 0; - gi.linkentity(train); - train->moveinfo.ratio += train->moveinfo.speed * FRAMETIME / train->moveinfo.distance; - if(train->movewith_next && (train->movewith_next->movewith_ent == train)) - set_child_movement(train); - if(train->moveinfo.ratio >= 1.0) - { - train->moveinfo.endfunc = NULL; - train->think = train_wait; - train->nextthink = level.time + FRAMETIME; - } - } - self->nextthink = level.time + FRAMETIME; -} - -void check_reverse_rotation (edict_t *self, vec3_t point) -{ - vec3_t vec; - vec3_t vnext; - vec_t rotation; - vec_t cross; - - if(!(self->flags & FL_REVERSIBLE)) - return; - - VectorSubtract(point,self->s.origin,vec); - VectorCopy(self->move_origin,vnext); - VectorNormalize(vec); - VectorNormalize(vnext); - - if(self->spawnflags & DOOR_X_AXIS) - { - rotation = self->moveinfo.distance * self->movedir[ROLL]; - cross = vec[1]*vnext[2] - vec[2]*vnext[1]; - } - else if(self->spawnflags & DOOR_Y_AXIS) - { - rotation = self->moveinfo.distance * self->movedir[PITCH]; - cross = vec[2]*vnext[0] - vec[0]*vnext[2]; - } - else - { - rotation = self->moveinfo.distance * self->movedir[YAW]; - cross = vec[0]*vnext[1] - vec[1]*vnext[0]; - } - - if((self->spawnflags & 1) && (DotProduct(vec,vnext) < 0)) - cross = -cross; - - if( (cross < 0) && (rotation > 0) ) - { - VectorNegate (self->movedir, self->movedir); - VectorMA (self->pos1, self->moveinfo.distance, self->movedir, self->pos2); - VectorCopy (self->pos2, self->moveinfo.end_angles); - } - else if((cross > 0) && (rotation < 0)) - { - VectorNegate (self->movedir, self->movedir); - VectorMA (self->pos1, self->moveinfo.distance, self->movedir, self->pos2); - VectorCopy (self->pos2, self->moveinfo.end_angles); - } - -} - -/* -========================================================= - - PLATS - - movement options: - - linear - smooth start, hard stop - smooth start, smooth stop - - start - end - acceleration - speed - deceleration - begin sound - end sound - target fired when reaching end - wait at end - - object characteristics that use move segments - --------------------------------------------- - movetype_push, or movetype_stop - action when touched - action when blocked - action when used - disabled? - auto trigger spawning - - -========================================================= -*/ - -// -// Support routines for movement (changes in origin using velocity) -// - -void Move_Done (edict_t *ent) -{ - VectorClear (ent->velocity); - if(ent->movewith) - VectorCopy(ent->movewith_ent->velocity,ent->velocity); - if(ent->moveinfo.endfunc) - ent->moveinfo.endfunc (ent); - if(ent->movewith_next && (ent->movewith_next->movewith_ent == ent)) - set_child_movement(ent); -} - -void Move_Final (edict_t *ent) -{ - if (ent->moveinfo.remaining_distance == 0 || ent->smooth_movement) - { - Move_Done (ent); - return; - } - - VectorScale (ent->moveinfo.dir, ent->moveinfo.remaining_distance / FRAMETIME, ent->velocity); - - if(ent->movewith) - VectorAdd(ent->movewith_ent->velocity,ent->velocity,ent->velocity); - - ent->think = Move_Done; - ent->nextthink = level.time + FRAMETIME; - if(ent->movewith_next && (ent->movewith_next->movewith_ent == ent)) - set_child_movement(ent); -} - -void Move_Begin (edict_t *ent) -{ - float frames; - - if ((ent->moveinfo.speed * FRAMETIME) >= ent->moveinfo.remaining_distance) - { - Move_Final (ent); - return; - } - VectorScale (ent->moveinfo.dir, ent->moveinfo.speed, ent->velocity); - - if(ent->movewith) - { - VectorAdd(ent->movewith_ent->velocity,ent->velocity,ent->velocity); - ent->moveinfo.remaining_distance -= ent->moveinfo.speed * FRAMETIME; - ent->nextthink = level.time + FRAMETIME; - ent->think = Move_Begin; - } - else - { - //if func_train is moving toward a moving path_corner - if ( (ent->class_id == ENTITY_FUNC_TRAIN) && ent->target_ent->movewith) - { - vec3_t dest; - VectorSubtract (ent->target_ent->s.origin, ent->mins, dest); - VectorCopy (ent->s.origin, ent->moveinfo.start_origin); - VectorCopy (dest, ent->moveinfo.end_origin); - if (ent->spawnflags & TRAIN_ROTATE && !(ent->target_ent->spawnflags & 2)) - { - vec3_t v, angles; - VectorAdd(ent->s.origin,ent->mins,v); - VectorSubtract(ent->target_ent->s.origin,v,v); - vectoangles2(v,angles); - ent->ideal_yaw = angles[YAW]; - ent->ideal_pitch = angles[PITCH]; - if(ent->ideal_pitch < 0) ent->ideal_pitch += 360; - VectorClear(ent->movedir); - ent->movedir[1] = 1.0; - } - VectorSubtract (dest, ent->s.origin, ent->moveinfo.dir); - ent->moveinfo.remaining_distance = VectorNormalize (ent->moveinfo.dir); - VectorScale (ent->moveinfo.dir, ent->moveinfo.speed, ent->velocity); - ent->nextthink = level.time + FRAMETIME; - ent->think = Move_Begin; - } - else - { - frames = floor((ent->moveinfo.remaining_distance / ent->moveinfo.speed) / FRAMETIME); - ent->moveinfo.remaining_distance -= frames * ent->moveinfo.speed * FRAMETIME; - ent->nextthink = level.time + (frames * FRAMETIME); - ent->think = Move_Final; - } - } - if(ent->movewith_next && (ent->movewith_next->movewith_ent == ent)) - set_child_movement(ent); -} - -void Think_AccelMove (edict_t *ent); - -void Move_Calc (edict_t *ent, vec3_t dest, void(*func)(edict_t*)) -{ - VectorClear (ent->velocity); - VectorSubtract (dest, ent->s.origin, ent->moveinfo.dir); - - ent->moveinfo.remaining_distance = VectorNormalize (ent->moveinfo.dir); - ent->moveinfo.endfunc = func; - - if (ent->moveinfo.speed == ent->moveinfo.accel && ent->moveinfo.speed == ent->moveinfo.decel) - { - if (level.current_entity == ((ent->flags & FL_TEAMSLAVE) ? ent->teammaster : ent)) - { - Move_Begin (ent); - } - else if (ent->movewith) { - Move_Begin (ent); - } - else - { - ent->nextthink = level.time + FRAMETIME; - ent->think = Move_Begin; - } - } - else - { - // accelerative - ent->moveinfo.current_speed = 0; - ent->think = Think_AccelMove; - ent->nextthink = level.time + FRAMETIME; - } -} - - -// -// Support routines for angular movement (changes in angle using avelocity) -// - -void AngleMove_Done (edict_t *ent) -{ - VectorClear (ent->avelocity); - if(ent->moveinfo.endfunc) - ent->moveinfo.endfunc (ent); -} - -void AngleMove_Final (edict_t *ent) -{ - vec3_t move; - - if (ent->moveinfo.state == STATE_UP) - { - VectorSubtract (ent->moveinfo.end_angles, ent->s.angles, move); - } - else - { - VectorSubtract (ent->moveinfo.start_angles, ent->s.angles, move); - } - if (VectorCompare (move, vec3_origin)) - { - AngleMove_Done (ent); - return; - } - - VectorScale (move, 1.0/FRAMETIME, ent->avelocity); - ent->think = AngleMove_Done; - ent->nextthink = level.time + FRAMETIME; -} - -void AngleMove_Begin (edict_t *ent) -{ - vec3_t destdelta; - float len; - float traveltime; - float frames; - - // set destdelta to the vector needed to move - if (ent->moveinfo.state == STATE_UP) - { - VectorSubtract (ent->moveinfo.end_angles, ent->s.angles, destdelta); - } - else - { - VectorSubtract (ent->moveinfo.start_angles, ent->s.angles, destdelta); - } - // calculate length of vector - len = VectorLength (destdelta); - - // divide by speed to get time to reach dest - traveltime = len / ent->moveinfo.speed; - - if (traveltime < FRAMETIME) - { - AngleMove_Final (ent); - return; - } - - frames = floor(traveltime / FRAMETIME); - - // scale the destdelta vector by the time spent traveling to get velocity - VectorScale (destdelta, 1.0 / traveltime, ent->avelocity); - // set nextthink to trigger a think when dest is reached - ent->nextthink = level.time + frames * FRAMETIME; - ent->think = AngleMove_Final; -} - -void AngleMove_Calc (edict_t *ent, void(*func)(edict_t*)) -{ - VectorClear (ent->avelocity); - ent->moveinfo.endfunc = func; - if (level.current_entity == ((ent->flags & FL_TEAMSLAVE) ? ent->teammaster : ent)) - { - AngleMove_Begin (ent); - } - else - { - ent->nextthink = level.time + FRAMETIME; - ent->think = AngleMove_Begin; - } -} - - -/* -============== -Think_AccelMove - -The team has completed a frame of movement, so -change the speed for the next frame -============== -*/ -#define AccelerationDistance(target, rate) (target * ((target / rate) + 1) / 2) - -void plat_CalcAcceleratedMove(moveinfo_t *moveinfo) -{ - float accel_dist; - float decel_dist; - - moveinfo->move_speed = moveinfo->speed; - - if (moveinfo->remaining_distance < moveinfo->accel) - { - moveinfo->current_speed = moveinfo->remaining_distance; - return; - } - - accel_dist = AccelerationDistance (moveinfo->speed, moveinfo->accel); - decel_dist = AccelerationDistance (moveinfo->speed, moveinfo->decel); - - if ((moveinfo->remaining_distance - accel_dist - decel_dist) < 0) - { - float f; - - f = (moveinfo->accel + moveinfo->decel) / (moveinfo->accel * moveinfo->decel); - moveinfo->move_speed = (-2 + sqrt(4 - 4 * f * (-2 * moveinfo->remaining_distance))) / (2 * f); - decel_dist = AccelerationDistance (moveinfo->move_speed, moveinfo->decel); - } - - moveinfo->decel_distance = decel_dist; -}; - -void plat_Accelerate (moveinfo_t *moveinfo) -{ - // are we decelerating? - if (moveinfo->remaining_distance <= moveinfo->decel_distance) - { - if (moveinfo->remaining_distance < moveinfo->decel_distance) - { - if (moveinfo->next_speed) - { - moveinfo->current_speed = moveinfo->next_speed; - moveinfo->next_speed = 0; - return; - } - if (moveinfo->current_speed > moveinfo->decel) - moveinfo->current_speed -= moveinfo->decel; - } - return; - } - - // are we at full speed and need to start decelerating during this move? - if (moveinfo->current_speed == moveinfo->move_speed) - if ((moveinfo->remaining_distance - moveinfo->current_speed) < moveinfo->decel_distance) - { - float p1_distance; - float p2_distance; - float distance; - - p1_distance = moveinfo->remaining_distance - moveinfo->decel_distance; - p2_distance = moveinfo->move_speed * (1.0 - (p1_distance / moveinfo->move_speed)); - distance = p1_distance + p2_distance; - moveinfo->current_speed = moveinfo->move_speed; - moveinfo->next_speed = moveinfo->move_speed - moveinfo->decel * (p2_distance / distance); - return; - } - - // are we accelerating? - if (moveinfo->current_speed < moveinfo->speed) - { - float old_speed; - float p1_distance; - float p1_speed; - float p2_distance; - float distance; - - old_speed = moveinfo->current_speed; - - // figure simple acceleration up to move_speed - moveinfo->current_speed += moveinfo->accel; - if (moveinfo->current_speed > moveinfo->speed) - moveinfo->current_speed = moveinfo->speed; - - // are we accelerating throughout this entire move? - if ((moveinfo->remaining_distance - moveinfo->current_speed) >= moveinfo->decel_distance) - return; - - // during this move we will accelrate from current_speed to move_speed - // and cross over the decel_distance; figure the average speed for the - // entire move - p1_distance = moveinfo->remaining_distance - moveinfo->decel_distance; - p1_speed = (old_speed + moveinfo->move_speed) / 2.0; - p2_distance = moveinfo->move_speed * (1.0 - (p1_distance / p1_speed)); - distance = p1_distance + p2_distance; - moveinfo->current_speed = (p1_speed * (p1_distance / distance)) + (moveinfo->move_speed * (p2_distance / distance)); - moveinfo->next_speed = moveinfo->move_speed - moveinfo->decel * (p2_distance / distance); - return; - } - - // we are at constant velocity (move_speed) - return; -}; - -void Think_AccelMove (edict_t *ent) -{ - ent->moveinfo.remaining_distance -= ent->moveinfo.current_speed; - - if (ent->moveinfo.current_speed == 0) // starting or blocked - plat_CalcAcceleratedMove(&ent->moveinfo); - - plat_Accelerate (&ent->moveinfo); - - // will the entire move complete on next frame? - if (ent->moveinfo.remaining_distance <= ent->moveinfo.current_speed) - { - Move_Final (ent); - return; - } - - VectorScale (ent->moveinfo.dir, ent->moveinfo.current_speed*10, ent->velocity); - if(ent->movewith) - VectorAdd(ent->movewith_ent->velocity,ent->velocity,ent->velocity); - ent->nextthink = level.time + FRAMETIME; - ent->think = Think_AccelMove; - - if(ent->movewith_next && (ent->movewith_next->movewith_ent == ent)) - set_child_movement(ent); -} - - -void plat_go_down (edict_t *ent); - -void plat_hit_top (edict_t *ent) -{ - if (!(ent->flags & FL_TEAMSLAVE)) - { - if (ent->s.sound && ent->moveinfo.sound_end) - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, ent->moveinfo.sound_end, 1, ATTN_STATIC, 0); - ent->s.sound = 0; - } - ent->moveinfo.state = STATE_TOP; - - ent->think = plat_go_down; - ent->nextthink = level.time + 3; -} - -void plat_hit_bottom (edict_t *ent) -{ - if (!(ent->flags & FL_TEAMSLAVE)) - { - if (ent->s.sound && ent->moveinfo.sound_end) - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, ent->moveinfo.sound_end, 1, ATTN_STATIC, 0); - ent->s.sound = 0; - } - ent->moveinfo.state = STATE_BOTTOM; -} - -void plat_go_down (edict_t *ent) -{ - if (!(ent->flags & FL_TEAMSLAVE)) - { - if (ent->moveinfo.sound_start) - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); - ent->s.sound = ent->moveinfo.sound_middle; - } - ent->moveinfo.state = STATE_DOWN; - Move_Calc (ent, ent->moveinfo.end_origin, plat_hit_bottom); -} - -void plat_go_up (edict_t *ent) -{ - if (!(ent->flags & FL_TEAMSLAVE)) - { - if (ent->moveinfo.sound_start) - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); - ent->s.sound = ent->moveinfo.sound_middle; - } - ent->moveinfo.state = STATE_UP; - Move_Calc (ent, ent->moveinfo.start_origin, plat_hit_top); -} - -void plat_blocked (edict_t *self, edict_t *other) -{ - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) - { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) - { - // Lazarus: Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } - - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); - - if (self->moveinfo.state == STATE_UP) - plat_go_down (self); - else if (self->moveinfo.state == STATE_DOWN) - plat_go_up (self); -} - - -void Use_Plat (edict_t *ent, edict_t *other, edict_t *activator) -{ - if (ent->think) - return; // already down - plat_go_down (ent); -} - - -void Touch_Plat_Center (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (!other->client) - return; - - if (other->health <= 0) - return; - - ent = ent->enemy; // now point at the plat, not the trigger - if (ent->moveinfo.state == STATE_BOTTOM) - plat_go_up (ent); - else if (ent->moveinfo.state == STATE_TOP) - ent->nextthink = level.time + 1; // the player is still on the plat, so delay going down -} - -void plat_spawn_inside_trigger (edict_t *ent) -{ - edict_t *trigger; - vec3_t tmin, tmax; - -// -// middle trigger -// - trigger = G_Spawn(); - trigger->touch = Touch_Plat_Center; - trigger->movetype = MOVETYPE_NONE; - trigger->solid = SOLID_TRIGGER; - trigger->enemy = ent; - - tmin[0] = ent->mins[0] + 25; - tmin[1] = ent->mins[1] + 25; - tmin[2] = ent->mins[2]; - - tmax[0] = ent->maxs[0] - 25; - tmax[1] = ent->maxs[1] - 25; - tmax[2] = ent->maxs[2] + 8; - - tmin[2] = tmax[2] - (ent->pos1[2] - ent->pos2[2] + st.lip); - - if (ent->spawnflags & PLAT_LOW_TRIGGER) - tmax[2] = tmin[2] + 8; - - if (tmax[0] - tmin[0] <= 0) - { - tmin[0] = (ent->mins[0] + ent->maxs[0]) *0.5; - tmax[0] = tmin[0] + 1; - } - if (tmax[1] - tmin[1] <= 0) - { - tmin[1] = (ent->mins[1] + ent->maxs[1]) *0.5; - tmax[1] = tmin[1] + 1; - } - - VectorCopy (tmin, trigger->mins); - VectorCopy (tmax, trigger->maxs); - - // Lazarus: - trigger->movewith = ent->movewith; - - gi.linkentity (trigger); -} - - -/*QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER -speed default 150 - -Plats are always drawn in the extended position, so they will light correctly. - -If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat. - -"speed" overrides default 200. -"accel" overrides default 500 -"lip" overrides default 8 pixel lip - -If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determoveinfoned by the model's height. - -Set "sounds" to one of the following: -1) base fast -2) chain slow -*/ -void SP_func_plat (edict_t *ent) -{ - ent->class_id = ENTITY_FUNC_PLAT; - - VectorClear (ent->s.angles); - ent->solid = SOLID_BSP; - ent->movetype = MOVETYPE_PUSH; - - gi.setmodel (ent, ent->model); - - ent->blocked = plat_blocked; - - if (!ent->speed) - ent->speed = 20; - else - ent->speed *= 0.1; - - if (!ent->accel) - ent->accel = 5; - else - ent->accel *= 0.1; - - if (!ent->decel) - ent->decel = 5; - else - ent->decel *= 0.1; - - if (!ent->dmg) - ent->dmg = 2; - - if (!st.lip) - st.lip = 8; - - // pos1 is the top position, pos2 is the bottom - VectorCopy (ent->s.origin, ent->pos1); - VectorCopy (ent->s.origin, ent->pos2); - if (st.height) - ent->pos2[2] -= st.height; - else - ent->pos2[2] -= (ent->maxs[2] - ent->mins[2]) - st.lip; - - ent->use = Use_Plat; - - plat_spawn_inside_trigger (ent); // the "start moving" trigger - - if (ent->targetname) - { - ent->moveinfo.state = STATE_UP; - } - else - { - VectorCopy (ent->pos2, ent->s.origin); - gi.linkentity (ent); - ent->moveinfo.state = STATE_BOTTOM; - } - - ent->moveinfo.speed = ent->speed; - ent->moveinfo.accel = ent->accel; - ent->moveinfo.decel = ent->decel; - ent->moveinfo.wait = ent->wait; - VectorCopy (ent->pos1, ent->moveinfo.start_origin); - VectorCopy (ent->s.angles, ent->moveinfo.start_angles); - VectorCopy (ent->pos2, ent->moveinfo.end_origin); - VectorCopy (ent->s.angles, ent->moveinfo.end_angles); - - ent->moveinfo.sound_start = gi.soundindex ("plats/pt1_strt.wav"); - ent->moveinfo.sound_middle = gi.soundindex ("plats/pt1_mid.wav"); - ent->moveinfo.sound_end = gi.soundindex ("plats/pt1_end.wav"); -} - -//==================================================================== - -/*QUAKED func_rotating (0 .5 .8) ? START_ON REVERSE X_AXIS Y_AXIS TOUCH_PAIN STOP ANIMATED ANIMATED_FAST -You need to have an origin brush as part of this entity. The center of that brush will be -the point around which it is rotated. It will rotate around the Z axis by default. You can -check either the X_AXIS or Y_AXIS box to change that. - -"speed" determines how fast it moves; default value is 100. -"dmg" damage to inflict when blocked (2 default) - -REVERSE will cause the it to rotate in the opposite direction. -STOP mean it will stop moving instead of pushing entities -*/ - -void rotating_accel (edict_t *self) -{ - float current_speed; - - current_speed = VectorLength (self->avelocity); - if(current_speed >= (self->speed - self->accel)) // done - { - VectorScale (self->movedir, self->speed, self->avelocity); - G_UseTargets (self, self); - } - else - { - current_speed += self->accel; - VectorScale (self->movedir, current_speed, self->avelocity); - self->think = rotating_accel; - self->nextthink = level.time + FRAMETIME; - } -} - -void rotating_decel (edict_t *self) -{ - float current_speed; - - current_speed = VectorLength (self->avelocity); - if(current_speed <= self->decel) // done - { - VectorClear (self->avelocity); - G_UseTargets (self, self); - self->touch = NULL; - } - else - { - current_speed -= self->decel; - VectorScale (self->movedir, current_speed, self->avelocity); - self->think = rotating_decel; - self->nextthink = level.time + FRAMETIME; - } -} -//PGM - -void rotating_blocked (edict_t *self, edict_t *other) -{ -/* // Lazarus: This was added to do damage to pickup items, but may break - // existing maps. - - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) { - // Lazarus: Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } */ - - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); - -} - -void rotating_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (self->avelocity[0] || self->avelocity[1] || self->avelocity[2]) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); -} - -void rotating_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if (!VectorCompare (self->avelocity, vec3_origin)) - { - self->s.sound = 0; -//PGM - if(self->spawnflags & 8192) // Decelerate - rotating_decel (self); - else - { - VectorClear (self->avelocity); - G_UseTargets (self, self); - self->touch = NULL; - } -//PGM - } - else - { - self->s.sound = self->moveinfo.sound_middle; -//PGM - if(self->spawnflags & 8192) // accelerate - rotating_accel (self); - else - { - VectorScale (self->movedir, self->speed, self->avelocity); - G_UseTargets (self, self); - } - if (self->spawnflags & 16) - self->touch = rotating_touch; -//PGM - } -} - -void SP_func_rotating (edict_t *ent) -{ - ent->class_id = ENTITY_FUNC_ROTATING; - ent->solid = SOLID_BSP; - if (ent->spawnflags & 32) - ent->movetype = MOVETYPE_STOP; - else - ent->movetype = MOVETYPE_PUSH; - - // set the axis of rotation - VectorClear(ent->movedir); - if (ent->spawnflags & 4) - ent->movedir[2] = 1.0; - else if (ent->spawnflags & 8) - ent->movedir[0] = 1.0; - else // Z_AXIS - ent->movedir[1] = 1.0; - - // check for reverse rotation - if (ent->spawnflags & 2) - VectorNegate (ent->movedir, ent->movedir); - - if (!ent->speed) - ent->speed = 100; - - if (!ent->dmg) - ent->dmg = 2; - - // Lazarus: Why was this removed? Dunno, but we're gonna use - // our own sound anyway -// ent->moveinfo.sound_middle = "doors/hydro1.wav"; - if (st.noise) - ent->moveinfo.sound_middle = gi.soundindex (st.noise); - - ent->use = rotating_use; - if (ent->dmg) - ent->blocked = rotating_blocked; - - if (ent->spawnflags & 1) - ent->use (ent, NULL, NULL); - - if (ent->spawnflags & 64) - ent->s.effects |= EF_ANIM_ALL; - if (ent->spawnflags & 128) - ent->s.effects |= EF_ANIM_ALLFAST; - -//PGM - if(ent->spawnflags & 8192) // Accelerate / Decelerate - { - if(!ent->accel) - ent->accel = 1; - else if (ent->accel > ent->speed) - ent->accel = ent->speed; - - if(!ent->decel) - ent->decel = 1; - else if (ent->decel > ent->speed) - ent->decel = ent->speed; - } -//PGM - - gi.setmodel (ent, ent->model); - gi.linkentity (ent); -} - -/* Lazarus: SP_func_rotating_dh is identical to func_rotating, but allows you - to build the model in a separate location (as with func_train, to - get the lighting the way you'd like) then move at runtime to the - origin of the "pathtarget". */ - -void func_rotating_dh_init (edict_t *ent) { - edict_t *new_origin; - - new_origin = G_Find (NULL, FOFS(targetname), ent->pathtarget); - if(new_origin) - VectorCopy(new_origin->s.origin,ent->s.origin); - SP_func_rotating (ent); -} - -void SP_func_rotating_dh (edict_t *ent) -{ - if( !ent->pathtarget ) { - SP_func_rotating(ent); - return; - } - - // Wait a few frames so that we're sure pathtarget has been parsed. - ent->think = func_rotating_dh_init; - ent->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(ent); -} - -/* -====================================================================== - -BUTTONS - -====================================================================== -*/ - -/*QUAKED func_button (0 .5 .8) ? -When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again. - -"angle" determines the opening direction -"target" all entities with a matching targetname will be used -"speed" override the default 40 speed -"wait" override the default 1 second wait (-1 = never return) -"lip" override the default 4 pixel lip remaining at end of move -"health" if set, the button must be killed instead of touched -"sounds" -1) silent -2) steam metal -3) wooden clunk -4) metallic click -5) in-out -*/ - -void button_done (edict_t *self) -{ - self->moveinfo.state = STATE_BOTTOM; - self->s.effects &= ~EF_ANIM23; - self->s.effects |= EF_ANIM01; -} - -void button_return (edict_t *self) -{ - if(self->movewith) - movewith_update(self); - - self->moveinfo.state = STATE_DOWN; - - Move_Calc (self, self->moveinfo.start_origin, button_done); - - self->s.frame = 0; - - if (self->health) - self->takedamage = DAMAGE_YES; -} - -void button_wait (edict_t *self) -{ - self->moveinfo.state = STATE_TOP; - self->s.effects &= ~EF_ANIM01; - self->s.effects |= EF_ANIM23; - - G_UseTargets (self, self->activator); - self->s.frame = 1; - if (self->moveinfo.wait >= 0) - { - self->nextthink = level.time + self->moveinfo.wait; - self->think = button_return; - } -} - -void button_fire (edict_t *self) -{ - if (self->moveinfo.state == STATE_UP || self->moveinfo.state == STATE_TOP) - return; - - if(self->movewith) - movewith_update(self); - self->moveinfo.state = STATE_UP; - if (self->moveinfo.sound_start && !(self->flags & FL_TEAMSLAVE)) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); - Move_Calc (self, self->moveinfo.end_origin, button_wait); -} - -void button_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - button_fire (self); -} - -void button_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - // Lazarus: allow robot actors to touch buttons - if (!other->client && !(other->flags & FL_ROBOT)) - return; - - if (other->health <= 0) - return; - - if((self->spawnflags & 1) && (LookingAt(other,0,NULL,NULL) != self)) - return; - - self->activator = other; - button_fire (self); -} - -void button_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->activator = attacker; - self->health = self->max_health; - self->takedamage = DAMAGE_NO; - button_fire (self); -} - -void SP_func_button (edict_t *ent) -{ - vec3_t abs_movedir; - - ent->class_id = ENTITY_FUNC_BUTTON; - - G_SetMovedir (ent->s.angles, ent->movedir); - - if(ent->movewith) { - ent->movetype = MOVETYPE_PUSH; - ent->blocked = train_blocked; - } else - ent->movetype = MOVETYPE_STOP; - ent->solid = SOLID_BSP; - gi.setmodel (ent, ent->model); - - if (ent->sounds != 1) - ent->moveinfo.sound_start = gi.soundindex ("switches/butn2.wav"); - - if (!ent->speed) - ent->speed = 40; - if (!ent->accel) - ent->accel = ent->speed; - if (!ent->decel) - ent->decel = ent->speed; - - if (!ent->wait) - ent->wait = 3; - if (!st.lip) - st.lip = 4; - - VectorCopy (ent->s.origin, ent->pos1); - abs_movedir[0] = fabs(ent->movedir[0]); - abs_movedir[1] = fabs(ent->movedir[1]); - abs_movedir[2] = fabs(ent->movedir[2]); - ent->moveinfo.distance = abs_movedir[0] * ent->size[0] + abs_movedir[1] * ent->size[1] + abs_movedir[2] * ent->size[2] - st.lip; - VectorMA (ent->pos1, ent->moveinfo.distance, ent->movedir, ent->pos2); - - ent->use = button_use; - ent->s.effects |= EF_ANIM01; - - if (ent->health) - { - ent->max_health = ent->health; - ent->die = button_killed; - ent->takedamage = DAMAGE_YES; - } - else if (! ent->targetname) - ent->touch = button_touch; - - ent->moveinfo.state = STATE_BOTTOM; - - ent->moveinfo.speed = ent->speed; - ent->moveinfo.accel = ent->accel; - ent->moveinfo.decel = ent->decel; - ent->moveinfo.wait = ent->wait; - VectorCopy (ent->pos1, ent->moveinfo.start_origin); - VectorCopy (ent->s.angles, ent->moveinfo.start_angles); - VectorCopy (ent->pos2, ent->moveinfo.end_origin); - VectorCopy (ent->s.angles, ent->moveinfo.end_angles); - - gi.linkentity (ent); -} - -//==================================================================== -// -// SP_func_trainbutton is a button linked to a func_train with the -// "movewith" key. The button itself does NOT move relative to the -// train, but the effect can be simulated with animations and sounds -// -// Spawnflags 1 = can be activated by looking at it and pressing +attack -// 2 = can NOT be activated by touching - must use +attack -// -//==================================================================== -void trainbutton_done (edict_t *self) -{ - self->moveinfo.state = STATE_BOTTOM; - self->s.effects &= ~EF_ANIM23; - self->s.effects |= EF_ANIM01; -} - -void trainbutton_return (edict_t *self) -{ - self->moveinfo.state = STATE_DOWN; - self->s.frame = 0; - self->s.effects &= ~EF_ANIM23; - self->s.effects |= EF_ANIM01; - if (self->health) - self->takedamage = DAMAGE_YES; -} - -void trainbutton_wait (edict_t *self) -{ - self->moveinfo.state = STATE_TOP; - self->s.effects &= ~EF_ANIM01; - self->s.effects |= EF_ANIM23; - - G_UseTargets (self, self->activator); - self->s.frame = 1; - if (self->moveinfo.wait >= 0) - { - self->nextthink = level.time + self->moveinfo.wait; - self->think = trainbutton_return; - } -} -void trainbutton_fire (edict_t *self) -{ - if (self->moveinfo.state == STATE_UP || self->moveinfo.state == STATE_TOP) - return; - self->moveinfo.state = STATE_UP; - if (self->moveinfo.sound_start && !(self->flags & FL_TEAMSLAVE)) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); - trainbutton_wait(self); -} - -void trainbutton_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - trainbutton_fire (self); -} - -void trainbutton_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (!other->client) - return; - - if (other->health <= 0) - return; - - self->activator = other; - trainbutton_fire (self); -} - -void trainbutton_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->activator = attacker; - self->health = self->max_health; - self->takedamage = DAMAGE_NO; - trainbutton_fire (self); -} -void movewith_init (edict_t *ent) -{ - edict_t *e, *child; - - // Unnamed entities can't be movewith parents - if(!ent->targetname) return; - - child = G_Find(NULL,FOFS(movewith),ent->targetname); - e = ent; - while(child) - { - child->movewith_ent = ent; - // Copy parent's current angles to the child. They SHOULD be 0,0,0 at this point - // for all currently supported parents, but ya never know. - VectorCopy(ent->s.angles,child->parent_attach_angles); - if(child->org_movetype < 0) - child->org_movetype = child->movetype; - if(child->movetype != MOVETYPE_NONE) - child->movetype = MOVETYPE_PUSH; - VectorCopy(child->mins,child->org_mins); - VectorCopy(child->maxs,child->org_maxs); - VectorSubtract(child->s.origin,ent->s.origin,child->movewith_offset); - e->movewith_next = child; - e = child; - child = G_Find(child,FOFS(movewith),ent->targetname); - } -} - -void SP_func_trainbutton(edict_t *ent) -{ - if(!ent->movewith) - { - SP_func_button(ent); - ent->class_id = ENTITY_FUNC_TRAINBUTTON; - return; - } - ent->class_id = ENTITY_FUNC_TRAINBUTTON; - G_SetMovedir (ent->s.angles, ent->movedir); - ent->movetype = MOVETYPE_PUSH; - ent->solid = SOLID_BSP; - gi.setmodel (ent, ent->model); - if (ent->sounds != 1) - ent->moveinfo.sound_start = gi.soundindex ("switches/butn2.wav"); - if (!ent->wait) - ent->wait = 3; - ent->use = trainbutton_use; - ent->s.effects |= EF_ANIM01; - ent->blocked = train_blocked; - ent->moveinfo.state = STATE_BOTTOM; - ent->moveinfo.wait = ent->wait; - if (!ent->targetname && !(ent->spawnflags & 2)) - ent->touch = trainbutton_touch; - gi.linkentity (ent); -} -/* -====================================================================== - -DOORS - - spawn a trigger surrounding the entire team unless it is - already targeted by another - -====================================================================== -*/ - -/*QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER NOMONSTER ANIMATED TOGGLE ANIMATED_FAST -TOGGLE wait in both the start and end states for a trigger event. -START_OPEN the door to moves to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors). -NOMONSTER monsters will not trigger this door - -"message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet -"angle" determines the opening direction -"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door. -"health" if set, door must be shot open -"speed" movement speed (100 default) -"wait" wait before returning (3 default, -1 = never return) -"lip" lip remaining at end of move (8 default) -"dmg" damage to inflict when blocked (2 default) -"sounds" -1) silent -2) light -3) medium -4) heavy -*/ - -void door_use_areaportals (edict_t *self, bool open) -{ - edict_t *t = NULL; - - if (!self->target) - return; - - while ((t = G_Find (t, FOFS(targetname), self->target))) - { - if (t->class_id == ENTITY_FUNC_AREAPORTAL) - { - gi.SetAreaPortalState (t->style, open); - } - } -} - -void door_go_down (edict_t *self); - -void swinging_door_reset (edict_t *self) -{ - self->moveinfo.state = STATE_BOTTOM; - self->health = self->max_health; - if(self->die) - self->takedamage = DAMAGE_YES; - VectorCopy (self->pos2, self->pos1); - VectorMA (self->s.angles, self->moveinfo.distance, self->movedir, self->pos2); - VectorCopy (self->pos1, self->moveinfo.start_angles); - VectorCopy (self->pos2, self->moveinfo.end_angles); - vectoangles2(self->move_origin,self->move_origin); - VectorMA(self->move_origin,self->moveinfo.distance,self->movedir,self->move_origin); - AngleVectors(self->move_origin,self->move_origin,NULL,NULL); -} - -void door_hit_top (edict_t *self) -{ - self->do_not_rotate = false; - if (!(self->flags & FL_TEAMSLAVE)) - { - if (self->s.sound && self->moveinfo.sound_end) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, ATTN_STATIC, 0); - self->s.sound = 0; - } - self->moveinfo.state = STATE_TOP; - if(self->flags & FL_REVOLVING) - { - self->think = swinging_door_reset; - if(self->moveinfo.wait > 0) - self->nextthink = level.time + self->moveinfo.wait; - else - self->think(self); - return; - } - if (self->spawnflags & DOOR_TOGGLE) - { - if(self->flags & FL_BOB) - { - self->think = bob_init; - self->nextthink = level.time + FRAMETIME; - } - return; - } - if (self->moveinfo.wait >= 0) - { - self->think = door_go_down; - self->nextthink = level.time + self->moveinfo.wait; - } - else if(self->flags & FL_BOB) - { - self->think = bob_init; - self->nextthink = level.time + FRAMETIME; - } -} - -void door_hit_bottom (edict_t *self) -{ - self->do_not_rotate = false; - if (!(self->flags & FL_TEAMSLAVE)) - { - if (self->s.sound && self->moveinfo.sound_end) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, ATTN_STATIC, 0); - self->s.sound = 0; - } - self->moveinfo.state = STATE_BOTTOM; - door_use_areaportals (self, false); - - if(self->flags & FL_BOB) - { - self->think = bob_init; - self->nextthink = level.time + FRAMETIME; - } -} - -void door_go_down (edict_t *self) -{ - self->do_not_rotate = true; - if (!(self->flags & FL_TEAMSLAVE)) - { - if (self->moveinfo.sound_start) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); - self->s.sound = self->moveinfo.sound_middle; - } - if (self->max_health) - { - self->takedamage = DAMAGE_YES; - self->health = self->max_health; - } - - if (self->class_id == ENTITY_FUNC_DOOR_ROTATING) { - self->moveinfo.state = STATE_DOWN; - AngleMove_Calc (self, door_hit_bottom); - } - else - { - if(self->movewith) - movewith_update(self); - self->moveinfo.state = STATE_DOWN; - Move_Calc (self, self->moveinfo.start_origin, door_hit_bottom); - } -} - -void door_go_up (edict_t *self, edict_t *activator) -{ - self->do_not_rotate = true; - if (self->moveinfo.state == STATE_UP) - return; // already going up - - if (self->moveinfo.state == STATE_TOP) - { // reset top wait time - if (self->moveinfo.wait >= 0) - self->nextthink = level.time + self->moveinfo.wait; - return; - } - - if ((self->flags & FL_REVERSIBLE) && activator) - check_reverse_rotation(self,activator->s.origin); - - if (!(self->flags & FL_TEAMSLAVE)) - { - if (self->moveinfo.sound_start) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); - self->s.sound = self->moveinfo.sound_middle; - } - if (self->class_id == ENTITY_FUNC_DOOR_ROTATING) { - self->moveinfo.state = STATE_UP; - AngleMove_Calc (self, door_hit_top); - } - else - { - if(self->movewith) - movewith_update(self); - self->moveinfo.state = STATE_UP; - Move_Calc (self, self->moveinfo.end_origin, door_hit_top); - } - - G_UseTargets (self, activator); - door_use_areaportals (self, true); -} - -void door_use (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *ent; - - if (self->flags & FL_TEAMSLAVE) - return; - - if (self->spawnflags & DOOR_TOGGLE) - { - if (self->moveinfo.state == STATE_UP || self->moveinfo.state == STATE_TOP) - { - // trigger all paired doors - for (ent = self ; ent ; ent = ent->teamchain) - { - ent->message = NULL; - ent->touch = NULL; - door_go_down (ent); - } - return; - } - } - - // trigger all paired doors - for (ent = self ; ent ; ent = ent->teamchain) - { - ent->message = NULL; - ent->touch = NULL; - door_go_up (ent, activator); - } - - // Lazarus - if(other->client && (world->effects & FX_WORLDSPAWN_ALERTSOUNDS) && (skill->value > 0)) - PlayerNoise(other,other->s.origin,PNOISE_SELF); - -}; - -void Touch_DoorTrigger (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other->health <= 0) - return; - - if (!(other->svflags & SVF_MONSTER) && (!other->client)) - return; - - // Lazarus: allow robots to open NOMONSTER doors - if ((self->owner->spawnflags & DOOR_NOMONSTER) && (other->svflags & SVF_MONSTER) && !(other->flags & FL_ROBOT)) - return; - - if (level.time < self->touch_debounce_time) - return; - self->touch_debounce_time = level.time + 1.0; - - door_use (self->owner, other, other); -} - -void Think_CalcMoveSpeed (edict_t *self) -{ - edict_t *ent; - float min; - float time; - float newspeed; - float ratio; - float dist; - - if (self->flags & FL_TEAMSLAVE) - return; // only the team master does this - - // find the smallest distance any member of the team will be moving - min = fabs(self->moveinfo.distance); - for (ent = self->teamchain; ent; ent = ent->teamchain) - { - dist = fabs(ent->moveinfo.distance); - if (dist < min) - min = dist; - } - - time = min / self->moveinfo.speed; - - // adjust speeds so they will all complete at the same time - for (ent = self; ent; ent = ent->teamchain) - { - newspeed = fabs(ent->moveinfo.distance) / time; - ratio = newspeed / ent->moveinfo.speed; - if (ent->moveinfo.accel == ent->moveinfo.speed) - ent->moveinfo.accel = newspeed; - else - ent->moveinfo.accel *= ratio; - if (ent->moveinfo.decel == ent->moveinfo.speed) - ent->moveinfo.decel = newspeed; - else - ent->moveinfo.decel *= ratio; - ent->moveinfo.speed = newspeed; - } -} - -void Think_SpawnDoorTrigger (edict_t *ent) -{ - edict_t *other; - vec3_t mins, maxs; - int expand; - - if (ent->flags & FL_TEAMSLAVE) - return; // only the team leader spawns a trigger - - VectorCopy (ent->absmin, mins); - VectorCopy (ent->absmax, maxs); - - for (other = ent->teamchain ; other ; other=other->teamchain) - { - AddPointToBounds (other->absmin, mins, maxs); - AddPointToBounds (other->absmax, mins, maxs); - } - - if(ent->movewith) - expand = 16; - else - expand = 60; - - mins[0] -= expand; - mins[1] -= expand; - maxs[0] += expand; - maxs[1] += expand; - - other = G_Spawn (); - VectorCopy (mins, other->mins); - VectorCopy (maxs, other->maxs); - other->owner = ent; - other->solid = SOLID_TRIGGER; - other->movetype = MOVETYPE_NONE; - other->touch = Touch_DoorTrigger; - - gi.linkentity (other); - - // Lazarus movewith - if(ent->movewith) { - other->movewith = ent->movewith; - VectorCopy(ent->s.origin,other->s.origin); - VectorSubtract(other->mins,other->s.origin,other->mins); - VectorSubtract(other->maxs,other->s.origin,other->maxs); - if(ent->movewith_ent) { - // Uh-oh... movewith_init was already called.. no harm in calling it again - movewith_init(ent->movewith_ent); - } - } - - if (ent->spawnflags & DOOR_START_OPEN) - door_use_areaportals (ent, true); - - Think_CalcMoveSpeed (ent); -} - -void door_blocked (edict_t *self, edict_t *other) -{ - edict_t *ent; - - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) { - // Lazarus: Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } - - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); - - if (self->spawnflags & DOOR_CRUSHER) - return; - -// if a door has a negative wait, it would never come back if blocked, -// so let it just squash the object to death real fast - if (self->moveinfo.wait >= 0) { - if (self->moveinfo.state == STATE_DOWN) { - for (ent = self->teammaster ; ent ; ent = ent->teamchain) - door_go_up (ent, ent->activator); - } - else { - for (ent = self->teammaster ; ent ; ent = ent->teamchain) - door_go_down (ent); - } - } -} - -void func_explosive_explode (edict_t *self); -void door_destroyed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - if (self->moveinfo.state == STATE_DOWN || self->moveinfo.state == STATE_BOTTOM) - door_use_areaportals(self,true); - self->dmg = 0; - func_explosive_explode(self); -} - -void door_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - edict_t *ent; - - for (ent = self->teammaster ; ent ; ent = ent->teamchain) - { - ent->health = ent->max_health; - ent->takedamage = DAMAGE_NO; - } - door_use (self->teammaster, attacker, attacker); -} - -void door_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - // Lazarus: Allows robot usage - if (!other->client && !(other->flags & FL_ROBOT)) - return; - - if (level.time < self->touch_debounce_time) - return; - self->touch_debounce_time = level.time + 5.0; - - gi.centerprintf (other, "%s", self->message); - gi.sound (other, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); -} - -void SP_func_door (edict_t *ent) -{ - vec3_t abs_movedir; - - ent->class_id = ENTITY_FUNC_DOOR; - if (ent->sounds != 1) - { - ent->moveinfo.sound_start = gi.soundindex ("doors/dr1_strt.wav"); - ent->moveinfo.sound_middle = gi.soundindex ("doors/dr1_mid.wav"); - ent->moveinfo.sound_end = gi.soundindex ("doors/dr1_end.wav"); - } - - G_SetMovedir (ent->s.angles, ent->movedir); - ent->movetype = MOVETYPE_PUSH; - ent->solid = SOLID_BSP; - gi.setmodel (ent, ent->model); - - ent->blocked = door_blocked; - ent->use = door_use; - - if (!ent->speed) - ent->speed = 100; - if (deathmatch->value) - ent->speed *= 2; - - if (!ent->accel) - ent->accel = ent->speed; - if (!ent->decel) - ent->decel = ent->speed; - - if (!ent->wait) - ent->wait = 3; - if (!st.lip) - st.lip = 8; - if (!ent->dmg) - ent->dmg = 2; - - // calculate second position - VectorCopy (ent->s.origin, ent->pos1); - abs_movedir[0] = fabs(ent->movedir[0]); - abs_movedir[1] = fabs(ent->movedir[1]); - abs_movedir[2] = fabs(ent->movedir[2]); - ent->moveinfo.distance = abs_movedir[0] * ent->size[0] + abs_movedir[1] * ent->size[1] + abs_movedir[2] * ent->size[2] - st.lip; - VectorMA (ent->pos1, ent->moveinfo.distance, ent->movedir, ent->pos2); - - // if it starts open, switch the positions - if (ent->spawnflags & DOOR_START_OPEN) - { - VectorCopy (ent->pos2, ent->s.origin); - VectorCopy (ent->pos1, ent->pos2); - VectorCopy (ent->s.origin, ent->pos1); - } - - ent->moveinfo.state = STATE_BOTTOM; - - if (ent->health > 0) - { - ent->takedamage = DAMAGE_YES; - ent->die = door_killed; - } - else - { - if (ent->health < 0) - { - // Lazarus: negative health means "damage kills me" rather than "damage opens me" - ent->takedamage = DAMAGE_YES; - PrecacheDebris(ent->gib_type); - ent->die = door_destroyed; - ent->health = -ent->health; - } - if (ent->targetname && ent->message) - { - gi.soundindex ("misc/talk.wav"); - ent->touch = door_touch; - } - } - ent->max_health = ent->health; - - ent->moveinfo.speed = ent->speed; - ent->moveinfo.accel = ent->accel; - ent->moveinfo.decel = ent->decel; - ent->moveinfo.wait = ent->wait; - VectorCopy (ent->pos1, ent->moveinfo.start_origin); - VectorCopy (ent->s.angles, ent->moveinfo.start_angles); - VectorCopy (ent->pos2, ent->moveinfo.end_origin); - VectorCopy (ent->s.angles, ent->moveinfo.end_angles); - - if (ent->spawnflags & 16) - ent->s.effects |= EF_ANIM_ALL; - if (ent->spawnflags & 64) - ent->s.effects |= EF_ANIM_ALLFAST; - - // to simplify logic elsewhere, make non-teamed doors into a team of one - if (!ent->team) - ent->teammaster = ent; - - gi.linkentity (ent); - - ent->nextthink = level.time + FRAMETIME; - if ((ent->health > 0) || ent->targetname ) - ent->think = Think_CalcMoveSpeed; - else - ent->think = Think_SpawnDoorTrigger; -} - - -/*QUAKED func_door_rotating (0 .5 .8) ? START_OPEN REVERSE CRUSHER NOMONSTER ANIMATED TOGGLE X_AXIS Y_AXIS -TOGGLE causes the door to wait in both the start and end states for a trigger event. - -START_OPEN the door to moves to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors). -NOMONSTER monsters will not trigger this door - -You need to have an origin brush as part of this entity. The center of that brush will be -the point around which it is rotated. It will rotate around the Z axis by default. You can -check either the X_AXIS or Y_AXIS box to change that. - -"distance" is how many degrees the door will be rotated. -"speed" determines how fast the door moves; default value is 100. - -REVERSE will cause the door to rotate in the opposite direction. - -"message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet -"angle" determines the opening direction -"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door. -"health" if set, door must be shot open -"speed" movement speed (100 default) -"wait" wait before returning (3 default, -1 = never return) -"dmg" damage to inflict when blocked (2 default) -"sounds" -1) silent -2) light -3) medium -4) heavy -*/ - -void SP_func_door_rotating (edict_t *ent) -{ - ent->class_id = ENTITY_FUNC_DOOR_ROTATING; - VectorClear (ent->s.angles); - - // set the axis of rotation - VectorClear(ent->movedir); - if (ent->spawnflags & DOOR_X_AXIS) - ent->movedir[2] = 1.0; - else if (ent->spawnflags & DOOR_Y_AXIS) - ent->movedir[0] = 1.0; - else // Z_AXIS - ent->movedir[1] = 1.0; - - // check for reverse rotation - if (ent->spawnflags & DOOR_REVERSE) - VectorNegate (ent->movedir, ent->movedir); - - if (!st.distance) - { - gi.dprintf("%s at %s with no distance set\n", ent->classname, vtos(ent->s.origin)); - st.distance = 90; - } - - VectorCopy (ent->s.angles, ent->pos1); - VectorMA (ent->s.angles, st.distance, ent->movedir, ent->pos2); - ent->moveinfo.distance = st.distance; - - ent->movetype = MOVETYPE_PUSH; - ent->solid = SOLID_BSP; - gi.setmodel (ent, ent->model); - - ent->blocked = door_blocked; - ent->use = door_use; - - if (!ent->speed) - ent->speed = 100; - if (!ent->accel) - ent->accel = ent->speed; - if (!ent->decel) - ent->decel = ent->speed; - - if (!ent->wait && !(ent->flags & FL_REVOLVING)) // OK for revolving doors to have 0 wait - ent->wait = 3; - if (!ent->dmg) - ent->dmg = 2; - - if (ent->sounds != 1) - { - ent->moveinfo.sound_start = gi.soundindex ("doors/dr1_strt.wav"); - ent->moveinfo.sound_middle = gi.soundindex ("doors/dr1_mid.wav"); - ent->moveinfo.sound_end = gi.soundindex ("doors/dr1_end.wav"); - } - - // if it starts open, switch the positions - if (ent->spawnflags & DOOR_START_OPEN) - { - VectorCopy (ent->pos2, ent->s.angles); - VectorCopy (ent->pos1, ent->pos2); - VectorCopy (ent->s.angles, ent->pos1); - VectorNegate (ent->movedir, ent->movedir); - } - - if (ent->health) - { - ent->takedamage = DAMAGE_YES; - ent->die = door_killed; - ent->max_health = ent->health; - } - else - { - if(ent->health < 0) - { - // Lazarus: negative health means "damage kills me" rather than "damage opens me" - ent->takedamage = DAMAGE_YES; - PrecacheDebris(ent->gib_type); - ent->die = door_destroyed; - ent->health = -ent->health; - ent->max_health = ent->health; - } - if (ent->targetname && ent->message) - { - gi.soundindex ("misc/talk.wav"); - ent->touch = door_touch; - } - } - - ent->moveinfo.state = STATE_BOTTOM; - ent->moveinfo.speed = ent->speed; - ent->moveinfo.accel = ent->accel; - ent->moveinfo.decel = ent->decel; - ent->moveinfo.wait = ent->wait; - VectorCopy (ent->s.origin, ent->moveinfo.start_origin); - VectorCopy (ent->pos1, ent->moveinfo.start_angles); - VectorCopy (ent->s.origin, ent->moveinfo.end_origin); - VectorCopy (ent->pos2, ent->moveinfo.end_angles); - - if (ent->spawnflags & 16) - ent->s.effects |= EF_ANIM_ALL; - - // to simplify logic elsewhere, make non-teamed doors into a team of one - if (!ent->team) - ent->teammaster = ent; - - gi.linkentity (ent); - - ent->nextthink = level.time + FRAMETIME; - if ((ent->health > 0) || ent->targetname) - ent->think = Think_CalcMoveSpeed; - else - ent->think = Think_SpawnDoorTrigger; -} - -/* Lazarus: SP_func_door_rot_dh is identical to func_door_rotating, but allows you - to build the model in a separate location (as with func_train, to - get the lighting the way you'd like) then move at runtime to the - origin of the "pathtarget". */ - -void func_door_rot_dh_init (edict_t *ent) { - edict_t *new_origin; - - new_origin = G_Find (NULL, FOFS(targetname), ent->pathtarget); - if(new_origin) { - VectorCopy(new_origin->s.origin,ent->s.origin); - VectorCopy (ent->s.origin, ent->moveinfo.start_origin); - VectorCopy (ent->s.origin, ent->moveinfo.end_origin); - gi.linkentity(ent); - } - ent->nextthink = level.time + FRAMETIME; - if ((ent->health > 0) || ent->targetname) - ent->think = Think_CalcMoveSpeed; - else - ent->think = Think_SpawnDoorTrigger; -} - -void SP_func_door_rot_dh (edict_t *ent) -{ - SP_func_door_rotating(ent); - if(!ent->pathtarget) return; - - // Wait a few frames so that we're sure pathtarget has been parsed. - ent->think = func_door_rot_dh_init; - ent->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(ent); -} - -/*QUAKED func_water (0 .5 .8) ? START_OPEN MUD -func_water is a moveable water brush. It must be targeted to operate. Use a non-water texture at your own risk. - -START_OPEN causes the water to move to its destination when spawned and operate in reverse. -MUD turns the water to mud - difficult to move through, swallows players - -"angle" determines the opening direction (up or down only) -"speed" movement speed (25 default) -"wait" wait before returning (-1 default, -1 = TOGGLE) -"lip" lip remaining at end of move (0 default) -"sounds" (yes, these need to be changed) -0) no sound -1) water -2) lava -*/ - -void SP_func_water (edict_t *self) -{ - vec3_t abs_movedir; - - self->class_id = ENTITY_FUNC_WATER; - G_SetMovedir (self->s.angles, self->movedir); - self->movetype = MOVETYPE_PUSH; - self->solid = SOLID_BSP; - gi.setmodel (self, self->model); - - if(self->spawnflags & 2) - { - level.mud_puddles++; - self->svflags |= SVF_MUD; - } - - switch (self->sounds) - { - default: - break; - - case 1: // water - self->moveinfo.sound_start = gi.soundindex ("world/mov_watr.wav"); - self->moveinfo.sound_end = gi.soundindex ("world/stp_watr.wav"); - break; - - case 2: // lava - self->moveinfo.sound_start = gi.soundindex ("world/mov_watr.wav"); - self->moveinfo.sound_end = gi.soundindex ("world/stp_watr.wav"); - break; - } - - // calculate second position - VectorCopy (self->s.origin, self->pos1); - abs_movedir[0] = fabs(self->movedir[0]); - abs_movedir[1] = fabs(self->movedir[1]); - abs_movedir[2] = fabs(self->movedir[2]); - self->moveinfo.distance = abs_movedir[0] * self->size[0] + abs_movedir[1] * self->size[1] + abs_movedir[2] * self->size[2] - st.lip; - VectorMA (self->pos1, self->moveinfo.distance, self->movedir, self->pos2); - - // if it starts open, switch the positions - if (self->spawnflags & DOOR_START_OPEN) - { - VectorCopy (self->pos2, self->s.origin); - VectorCopy (self->pos1, self->pos2); - VectorCopy (self->s.origin, self->pos1); - } - - VectorCopy (self->pos1, self->moveinfo.start_origin); - VectorCopy (self->s.angles, self->moveinfo.start_angles); - VectorCopy (self->pos2, self->moveinfo.end_origin); - VectorCopy (self->s.angles, self->moveinfo.end_angles); - - self->moveinfo.state = STATE_BOTTOM; - - if (!self->speed) - self->speed = 25; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed = self->speed; - - if (!self->wait) - self->wait = -1; - self->moveinfo.wait = self->wait; - - self->use = door_use; - - if (self->wait == -1) - self->spawnflags |= DOOR_TOGGLE; - - self->classname = "func_door"; - - gi.linkentity (self); -} - - -/*QUAKED func_train (0 .5 .8) ? START_ON TOGGLE BLOCK_STOPS -Trains are moving platforms that players can ride. -The targets origin specifies the min point of the train at each corner. -The train spawns at the first target it is pointing at. -If the train is the target of a button or trigger, it will not begin moving until activated. -speed default 100 -dmg default 2 -noise looping sound to play when the train is in motion - -*/ -// Lazarus: Added health key to func_train -void train_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - edict_t *e, *next; - - if(self->deathtarget) - { - self->target = self->deathtarget; - G_UseTargets (self, attacker); - } - e = self->movewith_next; - while(e) { - next = e->movewith_next; - e->nextthink = 0; - if(e->takedamage) - T_Damage (e, self, self, vec3_origin, e->s.origin, vec3_origin, 100000, 1, DAMAGE_NO_PROTECTION, MOD_CRUSH); - else if(e->die) - e->die(e,self,self,100000,e->s.origin); - else if(e->solid == SOLID_NOT) - G_FreeEdict(e); - else - BecomeExplosion1 (e); - e = next; - } - BecomeExplosion1 (self); -} - -void train_next (edict_t *self); - -void train_blocked (edict_t *self, edict_t *other) -{ - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) - { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) - { - // Lazarus: Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } - - if (level.time < self->touch_debounce_time) - return; - - if (!self->dmg) - return; - self->touch_debounce_time = level.time + 0.5; - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); -} - -void train_wait (edict_t *self) -{ - if (self->target_ent->pathtarget) - { - char *savetarget; - edict_t *ent; - - ent = self->target_ent; - savetarget = ent->target; - ent->target = ent->pathtarget; - G_UseTargets (ent, self->activator); - ent->target = savetarget; - - // make sure we didn't get killed by a killtarget - if (!self->inuse) - return; - } - - // Lazarus: rotating trains - if(self->target_ent) { - if(self->target_ent->speed) { - self->speed = self->target_ent->speed; - self->moveinfo.speed = self->speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - } - if(self->spawnflags & TRAIN_ROTATE) { - if(self->target_ent->pitch_speed) - self->pitch_speed = self->target_ent->pitch_speed; - if(self->target_ent->yaw_speed) - self->yaw_speed = self->target_ent->yaw_speed; - if(self->target_ent->roll_speed) - self->roll_speed = self->target_ent->roll_speed; - } else if(self->spawnflags & TRAIN_ROTATE_CONSTANT) { - if(self->target_ent->pitch_speed) - self->pitch_speed += self->target_ent->pitch_speed; - if(self->target_ent->yaw_speed) - self->yaw_speed += self->target_ent->yaw_speed; - if(self->target_ent->roll_speed) - self->roll_speed += self->target_ent->roll_speed; - } - } - - if (self->moveinfo.wait) - { - // Spline trains stop rotating when waiting - if(self->spawnflags & TRAIN_SPLINE) - { - VectorClear(self->avelocity); - VectorClear(self->velocity); - if(self->movewith_next && (self->movewith_next->movewith_ent == self)) - set_child_movement(self); - } - - if (self->moveinfo.wait > 0) - { - // Lazarus: turn off animation for stationary trains - self->s.effects &= ~(EF_ANIM_ALL | EF_ANIM_ALLFAST); - self->nextthink = level.time + self->moveinfo.wait; - self->think = train_next; - } - else if (self->spawnflags & TRAIN_TOGGLE) // && wait < 0 - { - train_next (self); - self->spawnflags &= ~TRAIN_START_ON; - VectorClear (self->velocity); - // Lazarus: turn off animation for stationary trains - self->s.effects &= ~(EF_ANIM_ALL | EF_ANIM_ALLFAST); - self->nextthink = 0; - } - - if (!(self->flags & FL_TEAMSLAVE)) - { - if (self->s.sound && self->moveinfo.sound_end) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, ATTN_STATIC, 0); - self->s.sound = 0; - } - } - else - { - train_next (self); - } - -} - -// Rroff's rotating train stuff, with quite a few changes - -void train_yaw (edict_t *self); -void train_spline (edict_t *self); -void train_children_think(edict_t *self) -{ - if(!self->enemy) return; - - if(self->enemy->spawnflags & TRAIN_ROTATE) - { - // The the train was changed from TRAIN_ROTATE_CONSTANT to TRAIN_ROTATE - // by a target_change... get da hell outta here. - self->think = train_yaw; - self->think(self); - return; - } - - if(self->enemy->movewith_next && (self->enemy->movewith_next->movewith_ent == self->enemy)) - { - set_child_movement(self->enemy); - self->nextthink = level.time + FRAMETIME; - } - else if(level.time < 2) - self->nextthink = level.time + FRAMETIME; -} - -void train_yaw (edict_t *self) -{ - float cur_yaw, idl_yaw, cur_pitch, idl_pitch, cur_roll, idl_roll; - float yaw_vel, pitch_vel, roll_vel; - float Dist_1, Dist_2, Distance; - - if(!self->enemy || !self->enemy->inuse) - return; - - if(self->enemy->spawnflags & TRAIN_ROTATE_CONSTANT) - { - // The the train was changed from TRAIN_ROTATE to TRAIN_ROTATE_CONSTANT - // by a target_change... get da hell outta here. - self->think = train_children_think; - self->think(self); - return; - } - - cur_yaw = self->enemy->s.angles[YAW]; - idl_yaw = self->enemy->ideal_yaw; - cur_pitch = self->enemy->s.angles[PITCH]; - idl_pitch = self->enemy->ideal_pitch; - cur_roll = self->enemy->s.angles[ROLL]; - idl_roll = self->enemy->ideal_roll; - -// gi.dprintf("current angles=%g %g %g, ideal angles=%g %g %g\n", -// cur_pitch,cur_yaw,cur_roll,idl_pitch,idl_yaw,idl_roll); - - yaw_vel = self->enemy->yaw_speed; - pitch_vel = self->enemy->pitch_speed; - roll_vel = self->enemy->roll_speed; - - if (cur_yaw == idl_yaw) - self->enemy->avelocity[YAW] = 0; - if (cur_pitch == idl_pitch) - self->enemy->avelocity[PITCH] = 0; - if (cur_roll == idl_roll) - self->enemy->avelocity[ROLL] = 0; - if ((cur_yaw == idl_yaw) && (cur_pitch == idl_pitch) && (cur_roll == idl_roll) ) { - self->nextthink = level.time + FRAMETIME; - if(self->enemy->movewith_next && (self->enemy->movewith_next->movewith_ent == self->enemy)) - set_child_movement(self->enemy); - return; - } - - if (cur_yaw != idl_yaw) { - if (cur_yaw < idl_yaw) - { - Dist_1 = (idl_yaw - cur_yaw)*10; - Dist_2 = ((360 - idl_yaw) + cur_yaw)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - self->enemy->avelocity[YAW] = yaw_vel; - } - else - { - Distance = Dist_2; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - self->enemy->avelocity[YAW] = -yaw_vel; - } - } - else - { - Dist_1 = (cur_yaw - idl_yaw)*10; - Dist_2 = ((360 - cur_yaw) + idl_yaw)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - self->enemy->avelocity[YAW] = -yaw_vel; - } - else - { - Distance = Dist_2; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - self->enemy->avelocity[YAW] = yaw_vel; - } - } - - // gi.dprintf ("train cy: %g iy: %g ys: %g\n", cur_yaw, idl_yaw, self->enemy->avelocity[1]); - - if (self->enemy->s.angles[YAW] < 0) - self->enemy->s.angles[YAW] += 360; - - if (self->enemy->s.angles[YAW] >= 360) - self->enemy->s.angles[YAW] -= 360; - } - - if (cur_pitch != idl_pitch) { - - if (cur_pitch < idl_pitch) - { - Dist_1 = (idl_pitch - cur_pitch)*10; - Dist_2 = ((360 - idl_pitch) + cur_pitch)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - self->enemy->avelocity[PITCH] = pitch_vel; - } - else - { - Distance = Dist_2; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - self->enemy->avelocity[PITCH] = -pitch_vel; - } - } - else - { - Dist_1 = (cur_pitch - idl_pitch)*10; - Dist_2 = ((360 - cur_pitch) + idl_pitch)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - self->enemy->avelocity[PITCH] = -pitch_vel; - } - else - { - Distance = Dist_2; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - self->enemy->avelocity[PITCH] = pitch_vel; - } - } - - if (self->enemy->s.angles[PITCH] < 0) - self->enemy->s.angles[PITCH] += 360; - - if (self->enemy->s.angles[PITCH] >= 360) - self->enemy->s.angles[PITCH] -= 360; - } - - if (cur_roll != idl_roll) { - if (cur_roll < idl_roll) - { - Dist_1 = (idl_roll - cur_roll)*10; - Dist_2 = ((360 - idl_roll) + cur_roll)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < roll_vel) - roll_vel = Distance; - - self->enemy->avelocity[ROLL] = roll_vel; - } - else - { - Distance = Dist_2; - - if (Distance < roll_vel) - roll_vel = Distance; - - self->enemy->avelocity[ROLL] = -roll_vel; - } - } - else - { - Dist_1 = (cur_roll - idl_roll)*10; - Dist_2 = ((360 - cur_roll) + idl_roll)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < roll_vel) - roll_vel = Distance; - - self->enemy->avelocity[ROLL] = -roll_vel; - } - else - { - Distance = Dist_2; - - if (Distance < roll_vel) - roll_vel = Distance; - - self->enemy->avelocity[ROLL] = roll_vel; - } - } - - if (self->enemy->s.angles[ROLL] < 0) - self->enemy->s.angles[ROLL] += 360; - - if (self->enemy->s.angles[ROLL] >= 360) - self->enemy->s.angles[ROLL] -= 360; - } - - if(self->enemy->movewith_next && (self->enemy->movewith_next->movewith_ent == self->enemy)) - set_child_movement(self->enemy); - self->nextthink = level.time + FRAMETIME; -} - -void train_next (edict_t *self) -{ - edict_t *ent; - vec3_t dest; - bool first; - vec3_t angles,v; - - first = true; -again: - if (!self->target) - { -// gi.dprintf ("train_next: no next target\n"); - self->s.sound = 0; - return; - } - - ent = G_PickTarget (self->target); - if (!ent) - { - gi.dprintf ("train_next: bad target %s\n", self->target); - return; - } - - self->target = ent->target; - - // Rroff: path_corners can control train speed - // DHW: This shouldn't go here... we're one path_corner behind. - // Set speed before train_next is called - /*if(ent->speed) - self->speed = ent->speed; - self->moveinfo.speed = self->speed; */ - - // check for a teleport path_corner - if (ent->spawnflags & 1) - { - if (!first) - { - gi.dprintf ("connected teleport path_corners, see %s at %s\n", ent->classname, vtos(ent->s.origin)); - return; - } - first = false; - VectorSubtract (ent->s.origin, self->mins, self->s.origin); - VectorCopy (self->s.origin, self->s.old_origin); - self->s.event = EV_OTHER_TELEPORT; - gi.linkentity (self); - if(self->movewith_next && (self->movewith_next->movewith_ent == self)) - set_child_movement(self); - goto again; - } - - self->moveinfo.wait = ent->wait; - self->target_ent = ent; - - if (!(self->flags & FL_TEAMSLAVE)) - { - if (self->moveinfo.sound_start) - gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); - self->s.sound = self->moveinfo.sound_middle; - } - - VectorSubtract (ent->s.origin, self->mins, dest); - self->moveinfo.state = STATE_TOP; - VectorCopy (self->s.origin, self->moveinfo.start_origin); - VectorCopy (dest, self->moveinfo.end_origin); - - if(self->spawnflags & TRAIN_SPLINE) - { - float speed; - int frames; - - self->from = self->to; - self->to = ent; - self->moveinfo.ratio = 0.0; - - VectorSubtract(dest,self->s.origin,v); - self->moveinfo.distance = VectorLength(v); - frames = (int)(10 * self->moveinfo.distance/self->speed); - if(frames < 1) frames = 1; - speed = (10*self->moveinfo.distance)/(float)frames; - self->moveinfo.speed = speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - } - - // Rroff rotating - if (self->spawnflags & TRAIN_ROTATE && !(ent->spawnflags & 2)) - { - // Lazarus: No no no :-). This is measuring from the center - // of the func_train to the path_corner. Should - // be path_corner to path_corner. - //VectorSubtract (ent->s.origin, self->s.origin, v); - VectorAdd(self->s.origin,self->mins,v); - VectorSubtract(ent->s.origin,v,v); - vectoangles2(v,angles); - self->ideal_yaw = angles[YAW]; - self->ideal_pitch = angles[PITCH]; - if(self->ideal_pitch < 0) self->ideal_pitch += 360; - self->ideal_roll = ent->roll; - - VectorClear(self->movedir); - self->movedir[1] = 1.0; - - } - /* Lazarus: We don't want to do this... this would give an - // instantaneous change in pitch and roll and look - // pretty goofy. Instead we'll set the new ideal_pitch - // to the path_corner's angles[PITCH], and move to that - // angle at pitch_speed. Roll changes? Can't do it (yet) - if (ent->count) - if (ent->count >= 0 && ent->count <= 360) - self->s.angles[PITCH] = ent->count; - - if (ent->sounds) - if (ent->sounds >= 0 && ent->sounds <= 360) - self->s.angles[ROLL] = ent->sounds; - */ - // end Rroff - - // Lazarus: - if(self->spawnflags & TRAIN_ROTATE_CONSTANT) - { - self->avelocity[PITCH] = self->pitch_speed; - self->avelocity[YAW] = self->yaw_speed; - self->avelocity[ROLL] = self->roll_speed; - } - - Move_Calc (self, dest, train_wait); - self->spawnflags |= TRAIN_START_ON; -} - -void train_resume (edict_t *self) -{ - edict_t *ent; - vec3_t dest; - - ent = self->target_ent; - - VectorSubtract (ent->s.origin, self->mins, dest); - self->moveinfo.state = STATE_TOP; - VectorCopy (self->s.origin, self->moveinfo.start_origin); - VectorCopy (dest, self->moveinfo.end_origin); - Move_Calc (self, dest, train_wait); - self->spawnflags |= TRAIN_START_ON; - // Lazarus: - if(self->spawnflags & TRAIN_ROTATE_CONSTANT) - { - self->avelocity[PITCH] = self->pitch_speed; - self->avelocity[YAW] = self->yaw_speed; - self->avelocity[ROLL] = self->roll_speed; - } -} - -void func_train_find (edict_t *self) -{ - edict_t *ent; - - if (!self->target) - { - gi.dprintf ("train_find: no target\n"); - return; - } - ent = G_PickTarget (self->target); - if (!ent) - { - gi.dprintf ("train_find: target %s not found\n", self->target); - return; - } - - // Lazarus: trains can change speed at path_corners - if(ent->speed) { - self->speed = ent->speed; - self->moveinfo.speed = self->speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - } - if(ent->pitch_speed) - self->pitch_speed = ent->pitch_speed; - if(ent->yaw_speed) - self->yaw_speed = ent->yaw_speed; - if(ent->roll_speed) - self->roll_speed = ent->roll_speed; - - // Lazarus: spline stuff - self->from = self->to = ent; - // end spline stuff - - self->target = ent->target; - - if( self->spawnflags & TRAIN_ROTATE ) - ent->think = train_yaw; - else if (self->spawnflags & TRAIN_SPLINE ) - ent->think = train_spline; - else - ent->think = train_children_think; - ent->enemy = self; - ent->nextthink = level.time + FRAMETIME; - - VectorSubtract(ent->s.origin, self->mins, self->s.origin); - gi.linkentity (self); - - // if not triggered, start immediately - if (!self->targetname) - self->spawnflags |= TRAIN_START_ON; - - if (self->spawnflags & TRAIN_START_ON) - { - // Lazarus: animated trains - if (self->spawnflags & TRAIN_ANIMATE) - self->s.effects |= EF_ANIM_ALL; - else if (self->spawnflags & TRAIN_ANIMATE_FAST) - self->s.effects |= EF_ANIM_ALLFAST; - - self->nextthink = level.time + FRAMETIME; - self->think = train_next; - self->activator = self; - } -} - -void train_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - - if (self->spawnflags & TRAIN_START_ON) - { - if (!(self->spawnflags & TRAIN_TOGGLE)) - return; - self->spawnflags &= ~TRAIN_START_ON; - VectorClear (self->velocity); - VectorClear (self->avelocity); - self->s.effects &= ~(EF_ANIM_ALL | EF_ANIM_ALLFAST); - self->nextthink = 0; - } - else - { - if (self->spawnflags & TRAIN_ANIMATE) - self->s.effects |= EF_ANIM_ALL; - else if (self->spawnflags & TRAIN_ANIMATE_FAST) - self->s.effects |= EF_ANIM_ALLFAST; - - if(self->spawnflags & TRAIN_SPLINE) - { - // Back up a step - self->moveinfo.ratio -= self->moveinfo.speed * FRAMETIME / self->moveinfo.distance; - if(self->moveinfo.ratio < 0.) - self->moveinfo.ratio = 0.; - } - - if (self->target_ent) - train_resume(self); - else - train_next(self); - } -} - -void SP_func_train (edict_t *self) -{ - self->class_id = ENTITY_FUNC_TRAIN; - - self->movetype = MOVETYPE_PUSH; - - if( (self->spawnflags & (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT)) == (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT)) - { - self->spawnflags &= ~(TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT); - self->spawnflags |= TRAIN_SPLINE; - } - - VectorClear (self->s.angles); - self->blocked = train_blocked; - if (self->spawnflags & TRAIN_BLOCK_STOPS) - self->dmg = 0; - else - { - if (!self->dmg) - self->dmg = 100; - } - self->solid = SOLID_BSP; - gi.setmodel (self, self->model); - - if (st.noise) - self->moveinfo.sound_middle = gi.soundindex (st.noise); - - if (!self->speed) - self->speed = 100; - - // Lazarus: Do NOT set default values for rotational speeds - if they're 0, then they're 0. - - self->moveinfo.speed = self->speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - - self->use = train_use; - - // Lazarus: damageable - if (self->health) { - self->die = train_die; - self->takedamage = DAMAGE_YES; - } else { - self->die = NULL; - self->takedamage = DAMAGE_NO; - } - - gi.linkentity (self); - if (self->target) - { - // start trains on the second frame, to make sure their targets have had - // a chance to spawn - self->nextthink = level.time + FRAMETIME; - self->think = func_train_find; - } - else - { - gi.dprintf ("func_train without a target at %s\n", vtos(self->absmin)); - } - - // Lazarus: TRAIN_SMOOTH forces trains to go directly to Move_Done from - // Move_Final rather than slowing down (if necessary) for one - // frame. - if (self->spawnflags & TRAIN_SMOOTH) - self->smooth_movement = true; - else - self->smooth_movement = false; - - // Lazarus: make noise field work w/o origin brush - // ver. 1.3 change - do this for ALL trains -// if(st.noise && !VectorLength(self->s.origin) ) - if(st.noise) - { - edict_t *speaker; - - self->noise_index = self->moveinfo.sound_middle; - self->moveinfo.sound_middle = 0; - speaker = G_Spawn(); - speaker->classname = "moving_speaker"; - speaker->s.sound = 0; - speaker->volume = 1; - speaker->attenuation = 1; - speaker->owner = self; - speaker->think = Moving_Speaker_Think; - speaker->nextthink = level.time + 2*FRAMETIME; - speaker->spawnflags = 7; // owner must be moving to play - self->speaker = speaker; - if(VectorLength(self->s.origin)) - { - VectorCopy(self->s.origin,speaker->s.origin); - } - else - { - VectorAdd(self->absmin,self->absmax,speaker->s.origin); - VectorScale(speaker->s.origin,0.5,speaker->s.origin); - } - VectorSubtract(speaker->s.origin,self->s.origin,speaker->offset); - } - -} - - -/*QUAKED trigger_elevator (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) -*/ -void trigger_elevator_use (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *target; - - if (self->movetarget->nextthink) - { -// gi.dprintf("elevator busy\n"); - return; - } - - if (!other->pathtarget) - { - gi.dprintf("elevator used with no pathtarget\n"); - return; - } - - target = G_PickTarget (other->pathtarget); - if (!target) - { - gi.dprintf("elevator used with bad pathtarget: %s\n", other->pathtarget); - return; - } - - self->movetarget->target_ent = target; - train_resume (self->movetarget); -} - -void trigger_elevator_init (edict_t *self) -{ - if (!self->target) - { - gi.dprintf("trigger_elevator has no target\n"); - return; - } - self->movetarget = G_PickTarget (self->target); - if (!self->movetarget) - { - gi.dprintf("trigger_elevator unable to find target %s\n", self->target); - return; - } - if (self->movetarget->class_id != ENTITY_FUNC_TRAIN) - { - gi.dprintf("trigger_elevator target %s is not a train\n", self->target); - return; - } - - self->use = trigger_elevator_use; - self->svflags = SVF_NOCLIENT; - -} - -void SP_trigger_elevator (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_ELEVATOR; - self->think = trigger_elevator_init; - self->nextthink = level.time + FRAMETIME; -} - - -/*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON -"wait" base time between triggering all targets, default is 1 -"random" wait variance, default is 0 - -so, the basic time between firing is a random time between -(wait - random) and (wait + random) - -"delay" delay before first firing when turned on, default is 0 - -"pausetime" additional delay used only the very first time - and only if spawned with START_ON - -These can used but not touched. -*/ -void func_timer_think (edict_t *self) -{ - G_UseTargets (self, self->activator); - self->nextthink = level.time + self->wait + crandom() * self->random; -} - -void func_timer_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - - // if on, turn it off - if (self->nextthink) - { - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } else { - self->nextthink = 0; - } - return; - } - - // turn it on - if (self->delay) - self->nextthink = level.time + self->delay; - else - func_timer_think (self); -} - -void SP_func_timer (edict_t *self) -{ - self->class_id = ENTITY_FUNC_TIMER; - if (!self->wait) - self->wait = 1.0; - - self->use = func_timer_use; - self->think = func_timer_think; - - if (self->random >= self->wait) - { - self->random = self->wait - FRAMETIME; - gi.dprintf("func_timer at %s has random >= wait\n", vtos(self->s.origin)); - } - - if (self->spawnflags & 1) - { - self->nextthink = level.time + 1.0 + st.pausetime + self->delay + self->wait + crandom() * self->random; - self->activator = self; - } - - self->svflags = SVF_NOCLIENT; -} - - -/*QUAKED func_conveyor (0 .5 .8) ? START_ON TOGGLE -Conveyors are stationary brushes that move what's on them. -The brush should be have a surface with at least one current content enabled. -speed default 100 - -Lazarus: Pretty much gutted this whole thing, which never came close to -working in the original game. Movement is handled in g_phys.c in the applicable -physics routines - search in g_phys.c for MOVETYPE_CONVEYOR. -*/ - -void func_conveyor_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->spawnflags & 1) - { - self->spawnflags &= ~1; - self->solid = SOLID_NOT; - self->svflags |= SVF_NOCLIENT; - } - else - { - self->spawnflags |= 1; - self->solid = SOLID_BSP; - self->svflags &= ~SVF_NOCLIENT; - KillBox (self); - } - gi.linkentity(self); - - if (!(self->spawnflags & 2)) - self->use = NULL; -} - -void SP_func_conveyor (edict_t *self) -{ - self->class_id = ENTITY_FUNC_CONVEYOR; - if (!self->speed) - self->speed = 100; - - self->use = func_conveyor_use; - gi.setmodel (self, self->model); - - // Lazarus changes: - self->movetype = MOVETYPE_CONVEYOR; - G_SetMovedir(self->s.angles,self->movedir); - if(self->spawnflags & 1) - self->solid = SOLID_BSP; - else { - self->solid = SOLID_NOT; - self->svflags |= SVF_NOCLIENT; - } - - gi.linkentity (self); -} - - -/*QUAKED func_door_secret (0 .5 .8) ? always_shoot 1st_left 1st_down -A secret door. Slide back and then to the side. - -open_once doors never closes -1st_left 1st move is left of arrow -1st_down 1st move is down from arrow -always_shoot door is shootebale even if targeted - -"angle" determines the direction -"dmg" damage to inflic when blocked (default 2) -"wait" how long to hold in the open position (default 5, -1 means hold) -*/ - -#define SECRET_ALWAYS_SHOOT 1 -#define SECRET_1ST_LEFT 2 -#define SECRET_1ST_DOWN 4 - -void door_secret_move1 (edict_t *self); -void door_secret_move2 (edict_t *self); -void door_secret_move3 (edict_t *self); -void door_secret_move4 (edict_t *self); -void door_secret_move5 (edict_t *self); -void door_secret_move6 (edict_t *self); -void door_secret_done (edict_t *self); - -void door_secret_use (edict_t *self, edict_t *other, edict_t *activator) -{ - // make sure we're not already moving - if (!VectorCompare(self->s.origin, vec3_origin)) - return; - - Move_Calc (self, self->pos1, door_secret_move1); - door_use_areaportals (self, true); -} - -void door_secret_move1 (edict_t *self) -{ - self->nextthink = level.time + 1.0; - self->think = door_secret_move2; -} - -void door_secret_move2 (edict_t *self) -{ - Move_Calc (self, self->pos2, door_secret_move3); -} - -void door_secret_move3 (edict_t *self) -{ - if (self->wait == -1) - return; - self->nextthink = level.time + self->wait; - self->think = door_secret_move4; -} - -void door_secret_move4 (edict_t *self) -{ - Move_Calc (self, self->pos1, door_secret_move5); -} - -void door_secret_move5 (edict_t *self) -{ - self->nextthink = level.time + 1.0; - self->think = door_secret_move6; -} - -void door_secret_move6 (edict_t *self) -{ - Move_Calc (self, vec3_origin, door_secret_done); -} - -void door_secret_done (edict_t *self) -{ - if (!(self->targetname) || (self->spawnflags & SECRET_ALWAYS_SHOOT)) - { - self->health = 0; - self->takedamage = DAMAGE_YES; - } - door_use_areaportals (self, false); -} - -void door_secret_blocked (edict_t *self, edict_t *other) -{ - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) - { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) - { - // Lazarus: Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } - - if (level.time < self->touch_debounce_time) - return; - self->touch_debounce_time = level.time + 0.5; - - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); -} - -void door_secret_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->takedamage = DAMAGE_NO; - door_secret_use (self, attacker, attacker); -} - -void SP_func_door_secret (edict_t *ent) -{ - vec3_t forward, right, up; - float side; - float width; - float length; - - ent->class_id = ENTITY_FUNC_DOOR_SECRET; - ent->moveinfo.sound_start = gi.soundindex ("doors/dr1_strt.wav"); - ent->moveinfo.sound_middle = gi.soundindex ("doors/dr1_mid.wav"); - ent->moveinfo.sound_end = gi.soundindex ("doors/dr1_end.wav"); - - ent->movetype = MOVETYPE_PUSH; - ent->solid = SOLID_BSP; - gi.setmodel (ent, ent->model); - - ent->blocked = door_secret_blocked; - ent->use = door_secret_use; - - if (!(ent->targetname) || (ent->spawnflags & SECRET_ALWAYS_SHOOT)) - { - ent->health = 0; - ent->takedamage = DAMAGE_YES; - ent->die = door_secret_die; - } - - if (!ent->dmg) - ent->dmg = 2; - - if (!ent->wait) - ent->wait = 5; - - ent->moveinfo.accel = - ent->moveinfo.decel = - ent->moveinfo.speed = 50; - - // calculate positions - AngleVectors (ent->s.angles, forward, right, up); - VectorClear (ent->s.angles); - side = 1.0 - (ent->spawnflags & SECRET_1ST_LEFT); - if (ent->spawnflags & SECRET_1ST_DOWN) - width = fabs(DotProduct(up, ent->size)); - else - width = fabs(DotProduct(right, ent->size)); - length = fabs(DotProduct(forward, ent->size)); - if (ent->spawnflags & SECRET_1ST_DOWN) - VectorMA (ent->s.origin, -1 * width, up, ent->pos1); - else - VectorMA (ent->s.origin, side * width, right, ent->pos1); - VectorMA (ent->pos1, length, forward, ent->pos2); - - if (ent->health) - { - ent->takedamage = DAMAGE_YES; - ent->die = door_killed; - ent->max_health = ent->health; - } - else if (ent->targetname && ent->message) - { - gi.soundindex ("misc/talk.wav"); - ent->touch = door_touch; - } - - ent->classname = "func_door"; - - gi.linkentity (ent); -} - - -/*QUAKED func_killbox (1 0 0) ? -Kills everything inside when fired, irrespective of protection. -*/ -void use_killbox (edict_t *self, edict_t *other, edict_t *activator) -{ - KillBox (self); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_func_killbox (edict_t *ent) -{ - ent->class_id = ENTITY_FUNC_KILLBOX; - gi.setmodel (ent, ent->model); - ent->use = use_killbox; - ent->svflags = SVF_NOCLIENT; -} -//=================================================================== -// LAZARUS additions -//=================================================================== -// -// func_pushable -// Moveable crate. Similar to misc_explobox, but: -// 1) Uses a brush model rather than a .md2 model. Model can be ANY -// shape, but the func_pushable uses the bounding box to determine -// whether it is being touched or not, so cubes are generally best. -// 2) Can be pushed off a ledge and damaged by falling -// 3) Default dmg = 0 (no fireball) and health = 0 (indestructible) -// 4) Plays a sound when moving -// -// targetname - If triggered, pushable object self-destructs, throwing -// debris chunks and (if dmg>0) exploding -// health - Damage sustained by object before it "dies". On death, -// object throws debris and (if dmg>0) explodes. func_pushable -// can be damaged by shooting (inapplicable in Tremor) or -// by falling damage or by being crushed by a func_door, -// func_train, etc. Set health=0 for a func_pushable that -// cannot be damaged by falling or weapon fire. Set health=-1 -// for func_pushable that will block MOVETYPE_PUSH entities -// (func_door, etc.) -// dmg - Radius damage due to object explosion. Set to 0 for -// no fireball -// mass - Weight of the object. Heavier objects are harder to push. -// Default = 400. -// sounds - Sound played when moved. -// 0 = none -// 1 = tank/thud.wav -// 2 = weapons/rg_hum.wav -// 3 = weapons/rockfly.wav -// -// SF=1 - Trigger spawn. Func_pushable is invisible and non-solid until triggered. -// 2 - No knockback. Not moved by weapon fire (invulnerable func_pushables aren't -// affected by weapon fire in either case) -// -//============= -// box_movestep -// -// Similar to SV_movestep in monster code, but handles falling -// objects, and doesn't balk at water/lava/slime -//============= -// -bool box_movestep (edict_t *ent, vec3_t move, bool relink) -{ - vec3_t oldorg, neworg, end; - trace_t trace; - float stepsize; - - vec3_t maxs, mins, origin; - -// try the move - VectorAdd (ent->s.origin, ent->origin_offset, origin); - VectorCopy (origin, oldorg); - VectorAdd (origin, move, neworg); - VectorCopy (ent->size, maxs); - VectorScale (maxs, 0.5, maxs); - VectorNegate (maxs, mins); - - -// push down from a step height above the wished position - stepsize = 1; - - neworg[2] += stepsize; - VectorCopy (neworg, end); - end[2] -= stepsize*2; - - trace = gi.trace (neworg, mins, maxs, end, ent, MASK_MONSTERSOLID); - - if (trace.allsolid) - return false; - - if (trace.startsolid) - { - neworg[2] -= stepsize; - trace = gi.trace (neworg, mins, maxs, end, ent, MASK_MONSTERSOLID); - if (trace.allsolid || trace.startsolid) - return false; - } - - if (trace.fraction == 1) - { - // if box had the ground pulled out, go ahead and fall - VectorAdd (ent->s.origin, move, ent->s.origin); - if (relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - ent->groundentity = NULL; - return true; - } - - VectorCopy (trace.endpos, origin); - VectorSubtract (origin, ent->origin_offset, ent->s.origin); - - ent->groundentity = trace.ent; - ent->groundentity_linkcount = trace.ent->linkcount; - -// the move is ok - if (relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - return true; -} - -void box_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - if(self->deathtarget) - { - self->target = self->deathtarget; - if(self->activator) - G_UseTargets (self, self->activator); - else - G_UseTargets (self, attacker); - self->target = NULL; - } - func_explosive_die (self, inflictor, attacker, damage, point); -} - -void box_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - box_die(self, self, other, self->health, vec3_origin); -} - -// -//=============== -//box_walkmove -// similar to M_walkmove, but: -// 1) works with entities not on the ground -// 2) calls moving box-specific box_movestep, which allows -// boxes to fall -//=============== -// - -bool box_walkmove (edict_t *ent, float yaw, float dist) -{ - vec3_t move; - - if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) - return false; - - yaw = yaw*M_PI*2 / 360; - - move[0] = cos(yaw)*dist; - move[1] = sin(yaw)*dist; - move[2] = 0; - - return box_movestep(ent, move, true); -} - -void box_water_friction(edict_t *ent) -{ - int i; - float speed, newspeed, control; - - if (!(ent->flags & FL_SWIM)) return; // should not be here - if (ent->waterlevel==0) return; // likewise - if (ent->crane_control) return; // currently under control of a crane - if ((ent->velocity[0]==0) && (ent->velocity[1]==0)) - { - ent->nextthink = 0; - return; - } - for(i=0; i<2; i++) - { - if(ent->velocity[i] != 0) - { - speed = fabs(ent->velocity[i]); - control = speed < 100 ? 100 : speed; - newspeed = speed - (FRAMETIME * control * ent->waterlevel); - if (newspeed < 0) - newspeed = 0; - newspeed /= speed; - ent->velocity[i] *= newspeed; - } - } - ent->nextthink = level.time + FRAMETIME; - gi.linkentity(ent); -} - -edict_t *CrateOnTop (edict_t *from, edict_t *ent); -void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - float e; // coefficient of restitution - float m; - float ratio; - float v11, v12, v21, v22; - int axis; - vec3_t v1, v2, v; - vec3_t origin; - edict_t *bottom, *top; - - // if other is another func_pushable, AND self is in - // water, move in proportion to relative masses - if (other->movetype == MOVETYPE_PUSHABLE) - { - int damage; - float delta; - float vslide; - vec3_t dir, impact_v; - - // Check for impact damage first - if(self->health > 0) { - VectorSubtract(other->velocity,self->velocity,impact_v); - delta = VectorLength(impact_v); - delta = delta*delta*0.0001; - if (delta > 30) - { - damage = (float)(other->mass)/(float)(self->mass) * ( (delta-30)/2 ); - if (damage > 0) - { - VectorSubtract(self->s.origin,other->s.origin,dir); - VectorNormalize(dir); - T_Damage (self, other, other, dir, self->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING); - if(self->health <= 0) return; - } - } - } - if(self->waterlevel==0) return; - - // 06/03/00 change: If either func_pushable is currently being moved - // by crane, bail out. - if(self->crane_control) return; - if(other->crane_control) return; - - // Since func_pushables have a bounding box, impact will ALWAYS be on one of the - // planes of the bounding box. The "plane" argument isn't always used, but since - // all entities involved use a parallelepiped bounding box we can rely on offsets - // to centers to figure out which side the impact is on. - VectorAdd (self->absmax,self->absmin,v1); - VectorScale(v1,0.5,v1); - VectorAdd (other->absmax,other->absmin,v2); - VectorScale(v2,0.5,v2); - VectorSubtract(v1,v2,v); - VectorNormalize(v); - axis = 0; - if(fabs(v[1]) > fabs(v[axis])) axis = 1; - if(fabs(v[2]) > fabs(v[axis])) axis = 2; - - e = 0.5; // coefficient of restitution - m = (float)(other->mass)/(float)(self->mass); - v11 = self->velocity[axis]; - v21 = other->velocity[axis]; - v22 = ( e*(v11-v21) + v11 + m*v21 ) / (1.0 + m); - v12 = v22 + e*(v21-v11); - self->velocity[axis] = v12; - other->velocity[axis] = v22; - - // Assuming frictionless surfaces, momentum of crate is conserved in - // other two directions (so velocity doesn't change)... BUT we want - // to get the bottom crate out from underneath the other one, - // so we're gonna be a little "creative" - if(axis==2) { - if(v[2] > 0) - { - bottom = other; - top = self; - VectorNegate(v,v); - } else { - bottom = self; - top = other; - } - v[2] = 0; - VectorNormalize(v); - if(!VectorLength(v)) { - v[0] = crandom(); - v[1] = sqrt(1.0 - v[0]*v[0]); - } - vslide = 10; - if(fabs(bottom->velocity[0]) < 50) - bottom->velocity[0] += v[0] * vslide; - if(fabs(bottom->velocity[1]) < 50) - bottom->velocity[1] += v[1] * vslide; - top->velocity[0] = -bottom->velocity[0]/2; - top->velocity[1] = -bottom->velocity[1]/2; - other->think = box_water_friction; - other->nextthink = level.time + 0.2; - gi.linkentity(other); - self->think = box_water_friction; - self->nextthink = level.time + 0.2; - } else { - // Frictionless horizontal motion for 1 second - self->think = box_water_friction; - self->nextthink = level.time + 1.0; - } - - // Override oldvelocity - VectorCopy(self->velocity,self->oldvelocity); - gi.linkentity(self); - return; - } - // if other is a monster or a player and box is on other's head and moving down, - // do impact damage - VectorAdd(self->s.origin,self->origin_offset,origin); - if( other->client || (other->svflags & SVF_MONSTER) ) - { - VectorAdd (self->absmax,self->absmin,v1); - VectorScale(v1,0.5,v1); - VectorSubtract(v1,other->s.origin,v); - VectorNormalize(v); - axis = 0; - if(fabs(v[1]) > fabs(v[axis])) axis = 1; - if(fabs(v[2]) > fabs(v[axis])) axis = 2; - if(axis == 2 && v[axis] > 0) { - v11 = VectorLength(self->velocity); - VectorCopy(self->velocity,v); - VectorNormalize(v); - if(!other->groundentity) { - other->velocity[2] = self->velocity[2]; - gi.linkentity(other); - } else if((v11 > 0) && (v[2] < -0.7)) { - int damage; - float delta; - vec3_t dir, impact_v; - VectorSubtract(other->velocity,self->velocity,impact_v); - delta = VectorLength(impact_v); - delta = delta*delta*0.001; - damage = (float)(self->mass)/(float)(other->mass) * delta; - // always do some minimum amount of damage, or we get boxes on - // heads, which looks awfully damn odd - damage = max(2,damage); - VectorSubtract(self->s.origin,other->s.origin,dir); - VectorNormalize(dir); - T_Damage (other, self, self, dir, other->s.origin, vec3_origin, damage, 0, 0, MOD_CRUSH); - self->bounce_me = 1; - return; - } - } else if( (other->groundentity == self) && (self->velocity[2] > 0)) { - self->bounce_me = 2; - other->velocity[2] = self->velocity[2]; - gi.linkentity(other); - return; - } - } - - // if not a player return - if (!other->client) return; - - // if func_pushable is on ground and has a mass > 1000, go away - if (self->groundentity && self->mass > 1000) return; - - // if player not pressing use key, do nothing - if (!other->client->use) { - if(self->activator == other) self->activator = NULL; - return; - } - - // if player in contact with this func_pushable is already pushing - // something else, return - if ((other->client->push != NULL) && (other->client->push != self)) { - if(self->activator == other) self->activator = NULL; - return; - } - - // if another player got here first, he maintains control - if (self->activator) { - if (self->activator->client) { - if (self->activator != other) { - return; - } - } - } - - VectorAdd (self->absmax,self->absmin,v1); - VectorScale(v1,0.5,v1); - - // if func_pushable isn't in front of pusher, do nothing - if (!point_infront(other,v1)) { - if(self->activator == other) self->activator = NULL; - return; - } - - // if player isn't on solid ground AND object isn't in water, - // OR if player is standing on this box, do nothing - if ( ((!other->groundentity) && (self->waterlevel==0)) || (other->groundentity == self) ) { - if(self->activator == other) self->activator = NULL; - return; - } - - // if this box has another box stacked on top, balk - if( CrateOnTop (NULL, self) ) { - if(self->activator == other) self->activator = NULL; - return; - } - - // Give object a little nudge to give us some clearance - VectorSubtract (v1, other->s.origin, v); - box_walkmove (self, vectoyaw(v), 4); - // Now get the offset from the player to the object, - // and preserve that offset in ClientThink by shifting - // object as needed. - VectorSubtract(other->s.origin,self->s.origin,self->offset); - self->offset[2] = 0; - self->activator = other; - other->client->push = self; - ratio = (float)other->mass / (float)self->mass; - other->client->maxvelocity = 20. * ratio; - if(tpp_auto->value && !other->client->chasetoggle) - Cmd_Chasecam_Toggle(other); - -} - -void func_pushable_spawn (edict_t *self, edict_t *other, edict_t *activator) -{ - self->solid = SOLID_BSP; - self->movetype = MOVETYPE_PUSHABLE; - self->svflags &= ~SVF_NOCLIENT; - self->use = box_use; - self->clipmask = MASK_PLAYERSOLID|MASK_MONSTERSOLID; - self->touch = box_touch; -} - -void SP_func_pushable (edict_t *self) -{ -// vec3_t border = {2,2,2}; - vec3_t border = {1,1,1}; - - self->class_id = ENTITY_FUNC_PUSHABLE; - PrecacheDebris(self->gib_type); - - gi.setmodel (self, self->model); - - /* Game places a 2 unit border around brush model absmin and absmax */ - VectorAdd(self->mins,border,self->mins); - VectorSubtract(self->maxs,border,self->maxs); - VectorAdd(self->absmin,border,self->absmin); - VectorSubtract(self->absmax,border,self->absmax); - - if (!self->mass) - self->mass = 400; - - self->flags = FL_SWIM; - - if (self->health > 0) - { - self->die = box_die; - self->takedamage = DAMAGE_YES; - } - else - { - self->die = NULL; - self->takedamage = DAMAGE_NO; - } - - if (self->spawnflags & 2) - { - // trigger spawn - self->solid = SOLID_NOT; - self->movetype = MOVETYPE_NONE; - self->use = func_pushable_spawn; - self->svflags |= SVF_NOCLIENT; - } else { - self->solid = SOLID_BSP; - self->movetype = MOVETYPE_PUSHABLE; - self->use = box_use; - self->clipmask = MASK_PLAYERSOLID|MASK_MONSTERSOLID; - self->touch = box_touch; - self->think = M_droptofloor; - self->nextthink = level.time + 2 * FRAMETIME; - } - - if (self->spawnflags & 4) - self->flags |= FL_NO_KNOCKBACK; - - switch (self->sounds) - { - case 1: - self->noise_index = gi.soundindex ("tank/thud.wav"); - break; - case 2: - self->noise_index = gi.soundindex ("weapons/rg_hum.wav"); - break; - case 3: - self->noise_index = gi.soundindex ("weapons/rockfly.wav"); - break; - } - - if(self->sounds && !VectorLength(self->s.origin) ) - { - edict_t *speaker; - - speaker = G_Spawn(); - speaker->classname = "moving_speaker"; - speaker->s.sound = 0; - speaker->volume = 1; - speaker->attenuation = 1; - speaker->owner = self; - speaker->think = Moving_Speaker_Think; - speaker->nextthink = level.time + 2*FRAMETIME; - speaker->spawnflags = 11; // owner must be moving and on ground to play - self->speaker = speaker; - VectorAdd(self->absmin,self->absmax,speaker->s.origin); - VectorScale(speaker->s.origin,0.5,speaker->s.origin); - VectorSubtract(speaker->s.origin,self->s.origin,speaker->offset); - } - - // Move up 1 unit so that func_pushable sitting directly on a func_train - // won't block it's movement (since train has a 1 unit border) - self->s.origin[2] += 1; - gi.linkentity (self); -} - -// -// Bobbing water - identical to func_water, but bobs up and down with -// amplitude specified by "bob" value and duration of one cycle specified by -// "duration" -// -void bob_think (edict_t *self) -{ - float delta; - int time = self->duration*10; - float t1, t0, z0, z1; - - t0 = self->bobframe%time; - t1 = (self->bobframe+1)%time; - - z0 = sin(2*M_PI*t0/time); - z1 = sin(2*M_PI*t1/time); - delta = self->bob/2 * (z1-z0); - self->velocity[2] = delta/FRAMETIME; - self->nextthink = level.time + FRAMETIME; - self->bobframe = (self->bobframe+1)%time; - gi.linkentity(self); -} - -void bob_init (edict_t *self) -{ - self->bobframe = 0; - self->think = bob_think; - self->nextthink = level.time + FRAMETIME; -} -void SP_func_bobbingwater(edict_t *self) -{ - vec3_t abs_movedir; - - self->class_id = ENTITY_FUNC_BOBBINGWATER; - G_SetMovedir (self->s.angles, self->movedir); - self->movetype = MOVETYPE_PUSH; - self->solid = SOLID_BSP; - gi.setmodel (self, self->model); - - if(self->spawnflags & 2) - { - level.mud_puddles++; - self->svflags |= SVF_MUD; - } - - switch (self->sounds) - { - default: - break; - - case 1: // water - self->moveinfo.sound_start = gi.soundindex ("world/mov_watr.wav"); - self->moveinfo.sound_end = gi.soundindex ("world/stp_watr.wav"); - break; - - case 2: // lava - self->moveinfo.sound_start = gi.soundindex ("world/mov_watr.wav"); - self->moveinfo.sound_end = gi.soundindex ("world/stp_watr.wav"); - break; - } - - // calculate second position - VectorCopy (self->s.origin, self->pos1); - abs_movedir[0] = fabs(self->movedir[0]); - abs_movedir[1] = fabs(self->movedir[1]); - abs_movedir[2] = fabs(self->movedir[2]); - self->moveinfo.distance = abs_movedir[0] * self->size[0] + abs_movedir[1] * self->size[1] + abs_movedir[2] * self->size[2] - st.lip; - VectorMA (self->pos1, self->moveinfo.distance, self->movedir, self->pos2); - - // if it starts open, switch the positions - if (self->spawnflags & DOOR_START_OPEN) - { - VectorCopy (self->pos2, self->s.origin); - VectorCopy (self->pos1, self->pos2); - VectorCopy (self->s.origin, self->pos1); - } - - VectorCopy (self->pos1, self->moveinfo.start_origin); - VectorCopy (self->s.angles, self->moveinfo.start_angles); - VectorCopy (self->pos2, self->moveinfo.end_origin); - VectorCopy (self->s.angles, self->moveinfo.end_angles); - - self->moveinfo.state = STATE_BOTTOM; - - if (!self->speed) - self->speed = 25; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed = self->speed; - - if (!self->wait) - self->wait = -1; - self->moveinfo.wait = self->wait; - - self->use = door_use; - - if (self->wait == -1) - self->spawnflags |= DOOR_TOGGLE; - - self->classname = "func_door"; - self->flags |= FL_BOB; - - if(!self->bob) self->bob = 16; - if(!self->duration) self->duration = 8; - self->think = bob_init; - self->nextthink = level.time + FRAMETIME; - gi.linkentity (self); -} - -// -// func_pivot - works like a see-saw -// -void pivot_blocked (edict_t *self, edict_t *other) -{ - VectorCopy(vec3_origin,self->avelocity); - gi.linkentity(self); -} - -void pivot_stop(edict_t *ent) -{ - VectorClear(ent->avelocity); - gi.linkentity(ent); -} - -void pivot_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - float time; - vec3_t offset; - vec3_t avelocity; - vec3_t delta; - - if(!other->mass) return; // other is weightless - if(!other->groundentity) return; // other is in air - if(other->groundentity != ent) return; // other is not standing on ent - - VectorSubtract(ent->s.origin,other->s.origin,offset); - offset[2] = 0.; // z offset is irrelevant - VectorCopy(ent->avelocity,avelocity); - if(ent->spawnflags & 1) - { - avelocity[PITCH] = -other->mass*offset[0]/400; -// if(avelocity[PITCH] = ent->avelocity[PITCH]) return; - if(offset[0] > 0) - ent->move_angles[PITCH] = ent->pos2[PITCH]; - else - ent->move_angles[PITCH] = ent->pos1[PITCH]; - VectorSubtract(ent->move_angles,ent->s.angles,delta); - time = delta[PITCH]/avelocity[PITCH]; - } - else - { - avelocity[ROLL] = other->mass*offset[1]/400; -// if(avelocity[ROLL] = ent->avelocity[ROLL]) return; - if(offset[1] > 0) - ent->move_angles[ROLL] = ent->pos1[ROLL]; - else - ent->move_angles[ROLL] = ent->pos2[ROLL]; - VectorSubtract(ent->move_angles,ent->s.angles,delta); - time = delta[ROLL]/avelocity[ROLL]; - } - gi.dprintf("time=%f, v=%f %f %f\n",time,avelocity[0],avelocity[1],avelocity[2]); - if(time > 0) - { - VectorCopy(avelocity,ent->avelocity); - ent->think = pivot_stop; - ent->nextthink = level.time + time; - gi.linkentity(ent); - } - else - { - VectorClear(ent->avelocity); - ent->nextthink = 0; - } -} -void pivot_init (edict_t *ent) -{ - float zmin; - trace_t tr; - vec3_t start, end; - - VectorClear(ent->pos1); - VectorClear(ent->pos2); - if(ent->spawnflags & 1) - { - end[0] = start[0] = ent->absmin[0]; - end[1] = start[1] = (ent->absmin[1]+ent->absmax[1])/2; - start[2] = ent->absmin[2]; - end[2] = ent->absmin[2] - (ent->s.origin[0]-ent->absmin[0]); - tr=gi.trace(start,NULL,NULL,end,ent,MASK_SOLID); - if(tr.fraction < 1.0) - zmin = tr.endpos[2]; - else - zmin = end[2]; - ent->pos2[PITCH] = asin((ent->absmin[2]-zmin)/(ent->s.origin[0]-ent->absmin[0])); - - end[0] = start[0] = ent->absmax[0]; - end[2] = ent->absmin[2] - (ent->absmax[0]-ent->s.origin[0]); - tr=gi.trace(start,NULL,NULL,end,ent,MASK_SOLID); - if(tr.fraction < 1.0) - zmin = tr.endpos[2]; - else - zmin = end[2]; - ent->pos1[PITCH] = asin((ent->absmin[2]-zmin)/(ent->absmax[0]-ent->s.origin[0])); - - ent->pos1[PITCH] *= 180/M_PI; - ent->pos2[PITCH] *= -180/M_PI; - } - else - { - end[0] = start[0] = (ent->absmin[0]+ent->absmax[0])/2; - end[1] = start[1] = ent->absmin[1]; - start[2] = ent->absmin[2]; - end[2] = ent->absmin[2] - (ent->s.origin[1]-ent->absmin[1]); - tr=gi.trace(start,NULL,NULL,end,ent,MASK_SOLID); - if(tr.fraction < 1.0) - zmin = tr.endpos[2]; - else - zmin = end[2]; - ent->pos1[ROLL] = asin((ent->absmin[2]-zmin)/(ent->s.origin[1]-ent->absmin[1])); - - end[1] = start[1] = ent->absmax[1]; - end[2] = ent->absmin[2] - (ent->absmax[1]-ent->s.origin[1]); - tr=gi.trace(start,NULL,NULL,end,ent,MASK_SOLID); - if(tr.fraction < 1.0) - zmin = tr.endpos[2]; - else - zmin = end[2]; - ent->pos2[ROLL] = asin((ent->absmin[2]-zmin)/(ent->absmax[1]-ent->s.origin[1])); - - ent->pos1[ROLL] *= 180/M_PI; - ent->pos2[ROLL] *= -180/M_PI; - } - - VectorClear(ent->move_angles); - gi.linkentity(ent); -} - -void SP_func_pivot (edict_t *ent) -{ - ent->class_id = ENTITY_FUNC_PIVOT; - ent->solid = SOLID_BSP; - ent->movetype = MOVETYPE_PUSH; - - if (!ent->speed) - ent->speed = 100; - if (!ent->dmg) - ent->dmg = 2; - - ent->touch = pivot_touch; - ent->blocked = pivot_blocked; - ent->gravity = 0; - ent->think = pivot_init; - ent->nextthink = level.time + FRAMETIME; - gi.setmodel (ent, ent->model); - gi.linkentity (ent); -} - -// ================================================== - -#define FWALL_START_ON 1 - -void force_wall_think(edict_t *self) -{ - if(!self->wait) - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_FORCEWALL); - WRITE_COORD (self->pos1); - WRITE_COORD (self->pos2); - WRITE_BYTE (self->style); - MESSAGE_SEND (MSG_PVS, self->offset, NULL); - } - - self->think = force_wall_think; - self->nextthink = level.time + FRAMETIME; -} - -void func_force_wall_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (!other->takedamage) - return; - if (self->timestamp > level.time) - return; - self->timestamp = level.time + FRAMETIME; - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_SPLASH); -} - -void force_wall_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if(!self->wait) - { - self->wait = 1; - self->think = NULL; - self->nextthink = 0; - self->solid = SOLID_NOT; - self->touch = NULL; - gi.linkentity( self ); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - - } - else - { - self->wait = 0; - self->think = force_wall_think; - self->nextthink = level.time + 0.1; - self->solid = SOLID_BSP; - if(self->dmg) - self->touch = func_force_wall_touch; - KillBox(self); // Is this appropriate? - gi.linkentity (self); - } -} - -/*QUAKED func_force_wall (1 0 1) ? start_on -A vertical particle force wall. Turns on and solid when triggered. -If someone is in the force wall when it turns on, they're telefragged. - -start_on - forcewall begins activated. triggering will turn it off. -style - color of particles to use. - 208: green, 240: red, 241: blue, 224: orange -*/ -void SP_func_force_wall(edict_t *ent) -{ - ent->class_id = ENTITY_FUNC_FORCE_WALL; - gi.setmodel (ent, ent->model); - - ent->offset[0] = (ent->absmax[0] + ent->absmin[0]) / 2; - ent->offset[1] = (ent->absmax[1] + ent->absmin[1]) / 2; - ent->offset[2] = (ent->absmax[2] + ent->absmin[2]) / 2; - - ent->pos1[2] = ent->absmax[2]; - ent->pos2[2] = ent->absmax[2]; - if(ent->size[0] > ent->size[1]) - { - ent->pos1[0] = ent->absmin[0]; - ent->pos2[0] = ent->absmax[0]; - ent->pos1[1] = ent->offset[1]; - ent->pos2[1] = ent->offset[1]; - } - else - { - ent->pos1[0] = ent->offset[0]; - ent->pos2[0] = ent->offset[0]; - ent->pos1[1] = ent->absmin[1]; - ent->pos2[1] = ent->absmax[1]; - } - - if(!ent->style) - ent->style = 208; - - ent->movetype = MOVETYPE_NONE; - - if(ent->spawnflags & FWALL_START_ON) - { - ent->solid = SOLID_BSP; - if(ent->dmg) - ent->touch = func_force_wall_touch; - ent->think = force_wall_think; - ent->nextthink = level.time + FRAMETIME; - ent->wait = 0; - } - else { - ent->wait = 1; - ent->solid = SOLID_NOT; - } - - ent->use = force_wall_use; - - ent->svflags = SVF_NOCLIENT; - - gi.linkentity(ent); -} - -// -// func_door_swinging is identical to func_door_rotating, but will always open AWAY -// from whoever opens it. If opened by a trigger the normal func_door_rotating rotation -// is used. -// -void swinging_door_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - edict_t *ent; - edict_t *master; - - for (ent = self->teammaster ; ent ; ent = ent->teamchain) - { - ent->health = ent->max_health; - ent->takedamage = DAMAGE_NO; - } - master = self->teammaster; - - if (master->spawnflags & DOOR_TOGGLE) - { - if (master->moveinfo.state == STATE_UP || master->moveinfo.state == STATE_TOP) - { - // trigger all paired doors - for (ent = master ; ent ; ent = ent->teamchain) - { - ent->message = NULL; - ent->touch = NULL; - door_go_down (ent); - } - return; - } - } - - // trigger all paired doors - for (ent = master ; ent ; ent = ent->teamchain) - { - ent->message = NULL; - ent->touch = NULL; - ent->do_not_rotate = true; - if (ent->moveinfo.state == STATE_UP) - continue; // already going up - if (ent->moveinfo.state == STATE_TOP) - { // reset top wait time - if (ent->moveinfo.wait >= 0) - ent->nextthink = level.time + ent->moveinfo.wait; - return; - } - check_reverse_rotation(ent,point); - if (!(ent->flags & FL_TEAMSLAVE)) - { - if (ent->moveinfo.sound_start) - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); - ent->s.sound = ent->moveinfo.sound_middle; - } - ent->moveinfo.state = STATE_UP; - AngleMove_Calc (ent, door_hit_top); - G_UseTargets (ent, attacker); - door_use_areaportals (ent, true); - } -} - -void func_door_swinging_init (edict_t *self) -{ - edict_t *new_origin; - edict_t *follow; - - follow = G_Find (NULL, FOFS(targetname), self->followtarget); - if(!follow) - { - gi.dprintf("func_door_swinging at %s, followtarget not found\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - VectorSubtract(follow->s.origin,self->s.origin,self->move_origin); - VectorNormalize(self->move_origin); - G_FreeEdict(follow); - if(self->pathtarget) - { - new_origin = G_Find (NULL, FOFS(targetname), self->pathtarget); - if(new_origin) - { - VectorCopy (new_origin->s.origin,self->s.origin); - VectorCopy (self->s.origin, self->moveinfo.start_origin); - VectorCopy (self->s.origin, self->moveinfo.end_origin); - gi.linkentity(self); - } - } - self->nextthink = level.time + FRAMETIME; - if ((self->health > 0) || self->targetname) - self->think = Think_CalcMoveSpeed; - else - self->think = Think_SpawnDoorTrigger; -} -void SP_func_door_swinging (edict_t *self) -{ - int pivot; - - pivot = self->spawnflags & 1; // 1 means "start open" for normal doors, so turn it - self->spawnflags &= ~1; // off temporarily until normal door initialization - // is done - - if(self->spawnflags & DOOR_REVERSE) - { - self->spawnflags &= ~DOOR_REVERSE; - self->flags |= FL_REVOLVING; - } - if(!self->followtarget) - { - gi.dprintf("func_door_swinging with no followtarget at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - SP_func_door_rotating (self); - self->spawnflags |= pivot; - if( pivot && (self->health > 0) ) - self->die = swinging_door_killed; - - self->flags |= FL_REVERSIBLE; - strcpy(self->classname,"func_door_rotating"); - - // Wait a few frames so that we're sure pathtarget has been parsed. - self->think = func_door_swinging_init; - self->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(self); -} \ No newline at end of file diff --git a/server/ents/g_lights.c b/server/ents/g_lights.c deleted file mode 100644 index 6480bfd4..00000000 --- a/server/ents/g_lights.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "g_local.h" -//========================================================== - -void Lights() -{ - if (lights->value) - { - // 0 normal - gi.configstring(CS_LIGHTS+0, "m"); - // 1 FLICKER (first variety) - gi.configstring(CS_LIGHTS+1, "mmnmmommommnonmmonqnmmo"); - // 2 SLOW STRONG PULSE - gi.configstring(CS_LIGHTS+2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); - // 3 CANDLE (first variety) - gi.configstring(CS_LIGHTS+3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); - // 4 FAST STROBE - gi.configstring(CS_LIGHTS+4, "mamamamamama"); - // 5 GENTLE PULSE 1 - gi.configstring(CS_LIGHTS+5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj"); - // 6 FLICKER (second variety) - gi.configstring(CS_LIGHTS+6, "nmonqnmomnmomomno"); - // 7 CANDLE (second variety) - gi.configstring(CS_LIGHTS+7, "mmmaaaabcdefgmmmmaaaammmaamm"); - // 8 CANDLE (third variety) - gi.configstring(CS_LIGHTS+8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); - // 9 SLOW STROBE (fourth variety) - gi.configstring(CS_LIGHTS+9, "aaaaaaaazzzzzzzz"); - // 10 FLUORESCENT FLICKER - gi.configstring(CS_LIGHTS+10, "mmamammmmammamamaaamammma"); - // 11 SLOW PULSE NOT FADE TO BLACK - gi.configstring(CS_LIGHTS+11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); - } - else - { - // 0 normal - gi.configstring(CS_LIGHTS+0, lightsmin->string); - // 1 FLICKER (first variety) - gi.configstring(CS_LIGHTS+1, lightsmin->string); - // 2 SLOW STRONG PULSE - gi.configstring(CS_LIGHTS+2, lightsmin->string); - // 3 CANDLE (first variety) - gi.configstring(CS_LIGHTS+3, lightsmin->string); - // 4 FAST STROBE - gi.configstring(CS_LIGHTS+4, lightsmin->string); - // 5 GENTLE PULSE 1 - gi.configstring(CS_LIGHTS+5, lightsmin->string); - // 6 FLICKER (second variety) - gi.configstring(CS_LIGHTS+6, lightsmin->string); - // 7 CANDLE (second variety) - gi.configstring(CS_LIGHTS+7, lightsmin->string); - // 8 CANDLE (third variety) - gi.configstring(CS_LIGHTS+8, lightsmin->string); - // 9 SLOW STROBE (fourth variety) - gi.configstring(CS_LIGHTS+9, lightsmin->string); - // 10 FLUORESCENT FLICKER - gi.configstring(CS_LIGHTS+10,lightsmin->string); - // 11 SLOW PULSE NOT FADE TO BLACK - gi.configstring(CS_LIGHTS+11,lightsmin->string); - } -} - -void ToggleLights() -{ - lights->value = !lights->value; - Lights(); -} - -void target_lightswitch_toggle (edict_t *self) -{ - ToggleLights(); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void use_target_lightswitch (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - - if (!self->delay) - { - target_lightswitch_toggle (self); - return; - } - - self->think = target_lightswitch_toggle; - self->nextthink = level.time + self->delay; -} - -void SP_target_lightswitch (edict_t *self) -{ - int i; - edict_t *e; - char lightvalue[2]; - - self->class_id = ENTITY_TARGET_LIGHTSWITCH; - // ensure this is the only target_lightswitch in the map - for(i=1, e=g_edicts+i; iinuse) continue; - if(!e->classname) continue; - if(e==self) continue; - if(e->class_id == ENTITY_TARGET_LIGHTSWITCH) - { - gi.dprintf("Only one target_lightswitch per map is allowed.\n"); - G_FreeEdict(self); - return; - } - } - if(!self->message) - lightvalue[0] = 'a'; - else - lightvalue[0] = self->message[0]; - lightvalue[1] = 0; - gi.cvar_forceset("lightsmin", lightvalue); - self->use = use_target_lightswitch; - self->svflags = SVF_NOCLIENT; - if(self->spawnflags & 1) - { - self->think = target_lightswitch_toggle; - self->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(self); - } -} - diff --git a/server/ents/g_lock.c b/server/ents/g_lock.c deleted file mode 100644 index 0e2517c2..00000000 --- a/server/ents/g_lock.c +++ /dev/null @@ -1,264 +0,0 @@ -#include "g_local.h" - -//===================================================== - -void SP_target_lock_digit (edict_t *self) -{ - self->class_id = ENTITY_TARGET_LOCK_DIGIT; - self->movetype = MOVETYPE_PUSH; - gi.setmodel (self, self->model); - self->solid = SOLID_BSP; - self->s.frame = 12; - gi.linkentity (self); -} - - -void target_lock_use (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *e; - int n; - char current[16]; - char *copy_message; - - memset(current,0,16); - - for (e = self->teammaster; e; e = e->teamchain) - { - if (!e->count) - continue; - n = e->count - 1; - current[n] = '0' + e->s.frame; - } - if(strcmp(current,self->key_message)==0) - { - copy_message = self->message; - self->message = NULL; - G_UseTargets(self,activator); - self->message = copy_message; - } - else - { - if(self->message) gi.centerprintf(activator,self->message); - if(self->pathtarget) { - e = G_Find(NULL,FOFS(targetname),self->pathtarget); - if(e) e->use(e,other,activator); - } - else { - BeepBeep(activator); - } - } -} - -void lock_digit_increment (edict_t *digit, edict_t *activator) -{ - if(digit->s.frame == 9) - digit->s.frame = 0; - else - digit->s.frame++; -} - -void lock_initialize (edict_t *lock) -{ - edict_t *e; - int n, l; - int numdigits; - char c; - - if(lock->spawnflags & 1 && strlen(game.lock_code) != 0) - { - strcpy(lock->key_message,game.lock_code); - return; - } - // Maximum of 8 digits in combination - l = min(strlen(lock->key_message),8); - numdigits = 0; - for (e = lock->teammaster; e; e = e->teamchain) - { - if (!e->count) - continue; - numdigits = max(numdigits,e->count); - n = e->count - 1; - if (n > l) - { - e->s.frame = 12; - continue; - } - - c = lock->key_message[n]; - if (c >= '0' && c <= '9') - e->s.frame = c - '0'; - else - e->s.frame = 0; - } - // Now generate a random number as the lock combination - srand(time(NULL)); - n = random(); - n = random(); - n = random(); - for(n=0; nkey_message[n] = '0' + (int)(random() * 9.99); - lock->key_message[numdigits] = '\0'; - - strcpy(game.lock_code,lock->key_message); - game.lock_revealed = 0; -} - -void SP_target_lock (edict_t *self) -{ - if (game.lock_hud && (self->spawnflags & 2)) - { - gi.dprintf("Map contains multiple target_locks and HUD is set.\n"); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_LOCK; - if (self->spawnflags & 2) game.lock_hud = true; - if (!self->key_message) - self->key_message = "00000000"; - self->use = target_lock_use; - self->think = lock_initialize; - self->nextthink = level.time + 1.0; - gi.linkentity(self); -} - -// -// target_lock_code reveals the lock combination to the -// target_lock specified in it's target field, or in global -// game data for crosslevel locks -// -void lock_code_use (edict_t *self, edict_t *other, edict_t *activator) -{ - int i, L; - char message[64]; - if(self->spawnflags & 1) - { - if(!strlen(game.lock_code)) - { - gi.dprintf("Lock has not been properly initialized.\n"); - return; - } - sprintf(message,"Lock combination is %s",game.lock_code); - Do_Text_Display(activator, 0, message); - L = strlen(game.lock_code); - for(i=0; itarget); - if(!lock) - gi.dprintf("Target of target_lock_code does not exist\n"); - else - { - sprintf(message,"Lock combination is %s",game.lock_code); - Do_Text_Display(activator, 0, message); - L = min(8,strlen(lock->key_message)); - for(i=0; itarget && !(self->spawnflags & 1)) - { - gi.dprintf("non-crosslevel target_lock_code w/o target\n"); - G_FreeEdict(self); - } - self->class_id = ENTITY_TARGET_LOCK_CODE; - self->use = lock_code_use; -} - -void lock_clue_use (edict_t *self, edict_t *other, edict_t *activator) -{ - int i, L; - if(self->spawnflags & 1) - { - if(!strlen(game.lock_code)) - { - gi.dprintf("Lock has not been properly initialized.\n"); - return; - } - L = strlen(game.lock_code); - for(i=0; imessage[i] != '?') game.lock_revealed |= 1<target); - if(!lock) - gi.dprintf("Target of target_lock_clue does not exist\n"); - else - { - L = min(8,strlen(lock->key_message)); - for(i=0; imessage[i] != '?') game.lock_revealed |= 1<team) - return; - - unrevealed_count = 0; - for (e = self->teammaster; e; e = e->teamchain) - { - if (!e->count) - continue; - n = e->count - 1; - if(game.lock_revealed & 1<s.frame = game.lock_code[n] - '0'; - else - { - e->s.frame++; // spin unknown digits - if(e->s.frame > 9) e->s.frame = 0; - unrevealed_count++; - } - } - if(unrevealed_count) - { - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); - } -} -void lock_clue_initialize(edict_t *self) -{ - // Randomize the revealed digits so spinning display doesn't - // show the same numbers across the board. - - edict_t *e; - if(self->team) - { - for (e = self->teammaster; e; e = e->teamchain) - { - if (!e->count) - continue; - e->s.frame = (int)(random() * 9.99); - } - } - self->think = lock_clue_think; - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} -void SP_target_lock_clue (edict_t *self) -{ - if(!self->target && !(self->spawnflags & 1)) - { - gi.dprintf("non-crosslevel target_lock_clue w/o target\n"); - G_FreeEdict(self); - } - self->class_id = ENTITY_TARGET_LOCK_CLUE; - self->use = lock_clue_use; - self->think = lock_clue_initialize; - self->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(self); -} diff --git a/server/ents/g_model.c b/server/ents/g_model.c deleted file mode 100644 index ce9ec02c..00000000 --- a/server/ents/g_model.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "g_local.h" -// -// mappack stuff by mr. ed, modified extensively for Tremor by dwh -// - -//Spawns a user defined model, you can specify whether its solid, if so how big the box is, and apply nearly -//any effect to the entity. -// -// PLAYER set this if you want to use a player model -// -// Note : These flags override any frame settings you may have enterered -// ANIM01 cycle between frames 0 and 1 at 2 hz -// ANIM23 cycle between frames 2 and 3 at 2 hz -// ANIM_ALL cycle through all frames at 2hz -// ANIM_ALLFAST cycle through all frames at 10hz -// -// START_OFF Start inactive, when triggered display the model -// TOGGLE Start active, when triggered become inactive -// NO_MODEL Don't use a model. Usefull for placeing particle effects and -// dynamic lights on their own -// -// "usermodel" = The model to load (models/ is already coded) -// "startframe" = The starting frame : default 0 -// "userframes" = The number of frames you want to display after startframe -// "solidstate" = 1 : SOLID_NOT - not solid at all -// 2 : SOLID_BBOX - solid and affected by gravity -// 3 : NO DROP - solid but not affected by gravity -// 4 : SOLID_NOT, but affect by gravity -// -// NOTE : if you want the model to be solid then you must enter vector values into the following fields : -// "bleft" = the point that is at the bottom left of the models bounding box in a model editor -// "tright" = the point that is at the top left of the models bounding box in a model editor -// - -#define TOGGLE 2 -#define PLAYER_MODEL 8 -#define NO_MODEL 16 -#define ANIM_ONCE 32 - -void model_spawn_use (edict_t *self, edict_t *other, edict_t *activator); -void modelspawn_think (edict_t *self) -{ - self->s.frame++; - if (self->s.frame >= self->framenumbers) - { - self->s.frame = self->startframe; - if(self->spawnflags & ANIM_ONCE) - { - model_spawn_use(self,world,world); - return; - } - } - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} - -void model_spawn_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->delay) //we started off - { - self->svflags &= ~SVF_NOCLIENT; - self->delay = 0; - if(self->framenumbers > 1) - { - self->think = modelspawn_think; - self->nextthink = level.time + FRAMETIME; - } - self->s.sound = self->noise_index; - } - else //we started active - { - self->svflags |= SVF_NOCLIENT; - self->delay = 1; - self->use = model_spawn_use; - self->think = NULL; - self->nextthink = 0; - self->s.sound = 0; - } -} - -void model_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - edict_t *e, *next; - - e = self->movewith_next; - while(e) { - next = e->movewith_next; - if(e->solid == SOLID_NOT) { - e->nextthink = 0; - G_FreeEdict(e); - } else - BecomeExplosion1 (e); - e = next; - } - - BecomeExplosion1(self); -} - -#define ANIM_MASK (EF_ANIM01|EF_ANIM23|EF_ANIM_ALL|EF_ANIM_ALLFAST) - -void SP_model_spawn (edict_t *ent) -{ - char modelname[256]; - - //paranoia checks - if ((!ent->usermodel) && !(ent->spawnflags & NO_MODEL) && !(ent->spawnflags & PLAYER_MODEL)) - { - gi.dprintf("%s without a model at %s\n", ent->classname, vtos(ent->s.origin)); - G_FreeEdict(ent); - return; - } - ent->class_id = ENTITY_MODEL_SPAWN; - - switch (ent->solidstate) - { - case 1 : ent->solid = SOLID_NOT; ent->movetype = MOVETYPE_NONE; break; - case 2 : ent->solid = SOLID_BBOX; ent->movetype = MOVETYPE_TOSS; break; - case 3 : ent->solid = SOLID_BBOX; ent->movetype = MOVETYPE_NONE; break; - case 4 : ent->solid = SOLID_NOT; ent->movetype = MOVETYPE_TOSS; break; - default: ent->solid = SOLID_NOT; ent->movetype = MOVETYPE_NONE; break; - } - if (ent->solid != SOLID_NOT ) { - if (ent->health > 0) { - ent->die = model_die; - ent->takedamage = DAMAGE_YES; - } - } - - switch (ent->style) - { - case 1 : ent->s.effects |= EF_ANIM01; break; - case 2 : ent->s.effects |= EF_ANIM23; break; - case 3 : ent->s.effects |= EF_ANIM_ALL; break; - case 4 : ent->s.effects |= EF_ANIM_ALLFAST; break; - } - - // DWH: Rather than use one value (renderfx) we use the - // actual values for effects and renderfx. All may - // be combined. - ent->s.effects |= ent->effects; - ent->s.renderfx |= ent->renderfx; - - if (ent->startframe < 0) - ent->startframe = 0; - if (!ent->framenumbers) - ent->framenumbers = 1; - // Change framenumbers to last frame to play - ent->framenumbers += ent->startframe; - - if (ent->bleft) - { - VectorCopy (ent->bleft, ent->mins); - } - else - { - if (ent->solid != SOLID_NOT) - { - gi.dprintf("%s solid with no bleft vector at %s\n", ent->classname, vtos(ent->s.origin)); - ent->solid = SOLID_NOT; - } - } - - if (ent->tright) - { - VectorCopy (ent->tright, ent->maxs); - } - else - { - if (ent->solid != SOLID_NOT) - { - gi.dprintf("%s solid with no tright vector at %s\n", ent->classname, vtos(ent->s.origin)); - ent->solid = SOLID_NOT; - } - } - -// if(ent->movewith && (ent->solid == SOLID_BBOX)) - if(ent->movewith) - ent->movetype = MOVETYPE_PUSH; - - if (ent->solid != SOLID_NOT) - ent->clipmask = CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER; - - if (ent->spawnflags & NO_MODEL) - { // For rendering effects to work, we MUST use a model - ent->s.modelindex = gi.modelindex ("sprites/point.spr"); - ent->movetype = MOVETYPE_NOCLIP; - } - else - { - if (ent->spawnflags & PLAYER_MODEL) { - if(!ent->usermodel || !strlen(ent->usermodel)) - ent->s.modelindex = MAX_MODELS-1; - else - { - if(strstr(ent->usermodel,"tris.md2")) - sprintf(modelname,"players/%s", ent->usermodel); - else - sprintf(modelname,"players/%s/tris.md2", ent->usermodel); - ent->s.modelindex = gi.modelindex(modelname); - } - } - else - { - if(strstr(ent->usermodel,".spr")) - sprintf(modelname, "sprites/%s", ent->usermodel); - else - sprintf(modelname, "models/%s", ent->usermodel); - ent->s.modelindex = gi.modelindex (modelname); - } - ent->s.frame = ent->startframe; - } - - if (st.noise) - ent->noise_index = gi.soundindex (st.noise); - ent->s.sound = ent->noise_index; - - if (ent->spawnflags & ANIM_ONCE) - ent->spawnflags |= TOGGLE; - - if (ent->spawnflags & TOGGLE) - { - ent->delay = 0; - ent->use = model_spawn_use; - } - - if(!(ent->s.effects & ANIM_MASK) && (ent->framenumbers > 1)) - { - ent->think = modelspawn_think; - ent->nextthink = level.time + 2*FRAMETIME; - } - gi.linkentity (ent); -} diff --git a/server/ents/g_mtrain.c b/server/ents/g_mtrain.c deleted file mode 100644 index 0f19711b..00000000 --- a/server/ents/g_mtrain.c +++ /dev/null @@ -1,136 +0,0 @@ -#include "g_local.h" - -void func_train_find (edict_t *self); -void SP_model_spawn (edict_t *ent); -void train_blocked (edict_t *self, edict_t *other); -void train_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); -void train_use (edict_t *self, edict_t *other, edict_t *activator); - -#define TRAIN_START_ON 1 -#define TRAIN_TOGGLE 2 -#define TRAIN_BLOCK_STOPS 4 -#define PLAYER_MODEL 8 -#define NO_MODEL 16 -#define MTRAIN_ROTATE 32 -#define MTRAIN_ROTATE_CONSTANT 64 -#define TRAIN_SMOOTH 128 - -void model_train_animator(edict_t *animator) -{ - edict_t *train; - - train = animator->owner; - if(!train || !train->inuse) - { - G_FreeEdict(animator); - return; - } - if(train->class_id != ENTITY_MODEL_TRAIN) - { - G_FreeEdict(animator); - return; - } - animator->nextthink = level.time + FRAMETIME; - if(VectorLength(train->velocity) == 0) - return; - train->s.frame++; - if (train->s.frame >= train->framenumbers) - train->s.frame = train->startframe; - gi.linkentity(train); -} - -void SP_model_train (edict_t *self) -{ - SP_model_spawn (self); - self->class_id = ENTITY_MODEL_TRAIN; - // Reset s.sound, which SP_model_spawn may have turned on - self->moveinfo.sound_middle = self->s.sound; - self->s.sound = 0; - - if(!self->inuse) return; - - // Reset some things from SP_model_spawn - self->delay = 0; - self->think = NULL; - self->nextthink = 0; - if (self->health) - { - self->die = train_die; - self->takedamage = DAMAGE_YES; - } - - if(self->framenumbers > self->startframe+1) - { - edict_t *animator; - animator = G_Spawn(); - animator->owner = self; - animator->think = model_train_animator; - animator->nextthink = level.time + FRAMETIME; - } - self->s.frame = self->startframe; - self->movetype = MOVETYPE_PUSH; - - // Really gross stuff here... translate model_spawn spawnflags - // to func_train spawnflags. PLAYER_MODEL and NO_MODEL have - // already been checked in SP_model_spawn and are never re-used, - // so it's OK to overwrite those. - if(self->spawnflags & MTRAIN_ROTATE) - { - self->spawnflags &= ~MTRAIN_ROTATE; - self->spawnflags |= TRAIN_ROTATE; - } - if(self->spawnflags & MTRAIN_ROTATE_CONSTANT) - { - self->spawnflags &= ~MTRAIN_ROTATE_CONSTANT; - self->spawnflags |= TRAIN_ROTATE_CONSTANT; - } - if( (self->spawnflags & (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT)) == (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT)) - { - self->spawnflags &= ~(TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT); - self->spawnflags |= TRAIN_SPLINE; - } - if(self->style == 3) - self->spawnflags |= TRAIN_ANIMATE; // 32 - if(self->style == 4) - self->spawnflags |= TRAIN_ANIMATE_FAST; // 64 - - // TRAIN_SMOOTH forces trains to go directly to Move_Done from - // Move_Final rather than slowing down (if necessary) for one - // frame. - if (self->spawnflags & TRAIN_SMOOTH) - self->smooth_movement = true; - else - self->smooth_movement = false; - - self->blocked = train_blocked; - if (self->spawnflags & TRAIN_BLOCK_STOPS) - self->dmg = 0; - else - { - if (!self->dmg) - self->dmg = 100; - } - - if (!self->speed) - self->speed = 100; - - self->moveinfo.speed = self->speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - - self->use = train_use; - - gi.linkentity (self); - - if (self->target) - { - // start trains on the second frame, to make sure their targets have had - // a chance to spawn - self->nextthink = level.time + FRAMETIME; - self->think = func_train_find; - } - else - { - gi.dprintf ("model_train without a target at %s\n", vtos(self->absmin)); - } - -} diff --git a/server/ents/g_pendulum.c b/server/ents/g_pendulum.c deleted file mode 100644 index 7b9f0872..00000000 --- a/server/ents/g_pendulum.c +++ /dev/null @@ -1,601 +0,0 @@ -#include "g_local.h" - -//==================================================================== - -/* FUNC_PENDULUM - -SF 1 = START_ON - 2 = STOP_AT_TOP - 8 = SLOW (internal use only, used to slow a pendulum to a stop after - being blocked) - 16= STOPPING (internal use only, set when a STOP_AT_TOP pendulum is triggered off) - -radius = length of pendulum, used for motion equation (not impact) -distance = total arc that pendulum moves through, must be < 360 -move_origin = vector from origin to c.g. of pendulum, used for impact -mass = mass of pendulum, used for knockback of func_pushables (not players/monsters) -*/ - -#define SF_PENDULUM_STARTON 1 -#define SF_PENDULUM_STOP_AT_TOP 2 -#define SF_PENDULUM_SLOW 8 -#define SF_PENDULUM_STOPPING 16 - -void box_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); -void pendulum_blocked (edict_t *self, edict_t *other) -{ - trace_t trace; - vec3_t angles; - vec3_t forward, left, up; - vec3_t dir; - vec3_t f1, l1, u1; - vec3_t point; - vec3_t origin; - vec3_t new_velocity; - vec3_t new_origin; - float speed; - int damage; - - // Since this routine is called in response to being blocked, - // the current s.angles is for the LAST frame, not the proposed - // angles for the current frame. Since we're basically overriding - // normal physics here, go ahead and move to new location. This - // means that later on we have to move blocker NOW rather than - // relying on its velocity to get it out of the way. - // BUT... trouble is doing this with players ends up giving - // goofy direction in some cases. For players/monsters, use old - // angles but STILL move 'em out of the way immediately - if(other->client || (other->svflags & SVF_MONSTER)) - { - VectorCopy(self->s.angles,angles); - } - else - { - VectorMA(self->s.angles,FRAMETIME,self->avelocity,angles); - } - AngleVectors(angles,forward,left,up); - - speed = fabs(self->avelocity[ROLL]) * M_PI / 180. * self->radius; - if( (level.time > self->touch_debounce_time) && (speed > 200) ) - { - damage = (int)( self->dmg * (speed-200)/100 ); - self->touch_debounce_time = level.time + 0.5; - } - else - damage = 0; - - VectorAdd(other->s.origin,other->origin_offset,origin); - VectorCopy(left,dir); - if(self->avelocity[ROLL] > 0) - VectorNegate(dir,dir); - - VectorScale(forward,self->move_origin[0],f1); - VectorScale(left,-self->move_origin[1],l1); - VectorScale(up,self->move_origin[2],u1); - VectorAdd(self->s.origin,f1,point); - VectorAdd(point,l1,point); - VectorAdd(point,u1,point); - VectorSubtract(origin,point,point); - VectorNormalize(point); - - if(other->client || (other->svflags & SVF_MONSTER)) - { - if((point[2] < -0.7) && other->groundentity) - { - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, DAMAGE_NO_PROTECTION, MOD_CRUSH); - return; - } - - dir[2] = max(1.0,fabs(dir[2])); - VectorNormalize(dir); - // Normal kickback takes too long to take effect and allows embedment. Move - // the blocker NOW. - // Give a minimum speed so we can get the poor fool out of the way - speed = max(100,speed); - VectorScale(dir,speed,new_velocity); - VectorMA(other->s.origin,FRAMETIME,new_velocity,new_origin); - other->solid = SOLID_NOT; - gi.linkentity(other); - trace = gi.trace(other->s.origin,other->mins,other->maxs,new_origin,self,other->clipmask); - VectorCopy(trace.endpos,other->s.origin); - VectorCopy(new_velocity,other->velocity); - other->solid = SOLID_BBOX; - gi.linkentity(other); - T_Damage (other, self, self, dir, other->s.origin, vec3_origin, damage, 0, 0, MOD_CRUSH); - } - else if(other->solid == SOLID_BSP) - { - // Other is most likely a func_pushable, since almost all other bmodels aren't - // clipped to MOVETYPE_PUSH - - vec3_t org, mins, maxs; - vec3_t vn2; - bool block; - float e=self->attenuation; // coefficient of restitution - float m=(float)(other->mass)/(float)(self->mass); - float v11 = speed; - float v21; // Initial speed of other in the impact direction - float v12, v22; - float new_rspeed; - float sgor, time, wave; - - if(v11 >= 100) - gi.sound (self, 0, self->noise_index, 1, 1, 0); - - // If other is on the ground, push it UP regardless of dir - if(other->groundentity) - dir[2] = max(1.0,fabs(dir[2])); - VectorNormalize(dir); - - // If pendulum hits crate from above and crate is on the ground, - // destroy the crate. This may not be realistic, but there's really - // no other way since if we stop the pendulum we'd then have to - // continously monitor whether the crate moved away or not. - if((point[2] < -0.7) && (other->velocity[2] == 0)) - { - box_die (other, self, self, 100000, point); - return; - } - if(e > 0) - { - v21 = VectorLength(other->velocity); - if(v21 > 0) - { - VectorCopy(other->velocity,vn2); - VectorNormalize(vn2); - v21 *= DotProduct(dir,vn2); - } - - v22 = ( e*(v11-v21) + v11 + m*v21 ) / (1.0 + m); - v12 = v22 + e*(v21-v11); -// gi.dprintf("v11=%g, v21=%g, v12=%g, v22=%g\n",v11,v21,v12,v22); -// gi.dprintf("av[ROLL]=%g, roll=%g\n",self->avelocity[ROLL],angles[ROLL]); - } - else - { - v12 = v11; - if(other->mass > self->mass) - { - block = true; - VectorClear(self->avelocity); - gi.linkentity(self); - goto deadstop; - } - else - v22 = v11 * (float)self->mass/(float)other->mass; - } - VectorScale(dir,v22,new_velocity); - - if(v12 < 0) - { - // Reverse rotation. - new_rspeed = fabs(v12) / (M_PI / 180. * self->radius); - if(self->avelocity[ROLL] > 0) - self->avelocity[ROLL] = -new_rspeed; - else - self->avelocity[ROLL] = new_rspeed; - } - else - { - // Continuing to move in same direction, though slower. - new_rspeed = v12 / (M_PI / 180. * self->radius); - if(self->avelocity[ROLL] > 0) - self->avelocity[ROLL] = new_rspeed; - else - self->avelocity[ROLL] = -new_rspeed; - } - sgor = sqrt( (float)sv_gravity->value / self->radius ); - wave = fabs( self->avelocity[ROLL] / (angles[ROLL] * sgor) ); - wave = atan(wave); - if(self->avelocity[ROLL] >= 0) - { - if(angles[ROLL] > 0) - wave = M_PI - wave; - } - else - { - if(angles[ROLL] > 0) - wave = M_PI + wave; - else - wave = 2*M_PI - wave; - } - time = wave/sgor; - self->startframe = level.framenum - time*10.; - self->moveinfo.start_angles[ROLL] = -fabs(angles[ROLL] / cos(wave)); - - // Now we know the new pendulum velocity and crate velocity, *assuming* - // nothing else is in the way. Now check to see if crate hits anything - // else. - - VectorAdd(other->s.origin,other->origin_offset,org); - VectorMA(org,FRAMETIME,new_velocity,new_origin); - - // Temporarily make crate nonsolid so we can ignore pendulum in our trace - // (rather than crate) - other->solid = SOLID_NOT; - gi.linkentity(other); - VectorSubtract(other->mins,other->origin_offset,mins); - VectorSubtract(other->maxs,other->origin_offset,maxs); - trace = gi.trace (org, mins, maxs, new_origin, self, other->clipmask); - // restore solidity of crate - other->solid = SOLID_BSP; - if(trace.startsolid) - { - // Things are completely fouled up. Nuke other and go away. - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - if (other) - BecomeExplosion1 (other); - return; - } - else if(trace.fraction < 1.0) - { - vec3_t vec; - float dist; - VectorSubtract(trace.endpos,org,vec); - dist = VectorLength(vec); - - if( (trace.ent->client) || (trace.ent->flags & SVF_MONSTER)) - { - float delta=FRAMETIME*VectorLength(new_velocity); - - // If a player or monster is in the way of the crate, AND - // the pendulum speed is > 100, throw 'em out of the way. - // If pendulum tangential speed is < 100, give up. - if(speed < 100) - block = true; - else - { - if(dist < delta) - { - VectorScale(new_velocity,1.25,trace.ent->velocity); - VectorMA(trace.ent->s.origin,FRAMETIME,trace.ent->velocity,trace.ent->s.origin); - gi.linkentity(trace.ent); - } - block = false; - } - } - else - { - if(dist < speed*FRAMETIME) - { - block = true; - VectorScale(vec,10.,other->velocity); - VectorMA(other->s.origin,FRAMETIME,other->velocity,other->s.origin); - } - else - block = false; - } - } - else - block = false; - - if(!block) - { - VectorCopy(new_velocity,other->velocity); - VectorMA(other->s.origin,FRAMETIME,other->velocity,other->s.origin); - } - gi.linkentity(other); - - // Final checks: - // 1) If pendulum after-impact speed is < 100, that's too damn slow. - // Lie and say it's blocked - // 2) If not blocked, in its new position test for intersection - // of crate and pendulum. If they intersect, then most likely pendulum is - // moving VERY slowly and we need to reverse direction NOW to prevent - // embedment. - if(!block) - { - if(fabs(v12) < 100) - block = true; - else - { - VectorAdd(other->s.origin,other->origin_offset,org); - trace = gi.trace(org,mins,maxs,org,other,MASK_SOLID); - if(trace.startsolid) - block = true; - } - } -deadstop: - T_Damage (other, self, self, dir, other->s.origin, vec3_origin, damage, 0, 0, MOD_CRUSH); - if( block ) - { - // Then this sucker will still be in the way. Reverse rotation, slow, or stop - if(fabs(angles[ROLL]) > 2) - { - if(abs(angles[ROLL]) < 10) - self->spawnflags |= SF_PENDULUM_SLOW; - self->moveinfo.start_angles[ROLL] = angles[ROLL]; - VectorClear(self->avelocity); - self->startframe = 0; - } - else - { - self->spawnflags &= ~SF_PENDULUM_STARTON; - self->moveinfo.start_angles[ROLL] = 0; - VectorClear(self->s.angles); - VectorClear(self->avelocity); - } - gi.linkentity(self); - } - else if((fabs(self->avelocity[ROLL]) < 10) && (fabs(self->s.angles[ROLL]) < 10)) - { - self->spawnflags |= SF_PENDULUM_SLOW; - self->moveinfo.start_angles[ROLL] = angles[ROLL]; - VectorClear(self->avelocity); - self->startframe = 0; - } - } - else - { - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) - BecomeExplosion1 (other); - } -} - -void pendulum_rotate (edict_t *self) -{ - float this_angle; - float wave; - float sgor; - - if(!(self->spawnflags & SF_PENDULUM_STARTON)) - return; - - if(self->spawnflags & SF_PENDULUM_SLOW) - { - if(self->startframe == 0) - { - // Then we just started moving again after being blocked - self->avelocity[ROLL] = -self->s.angles[ROLL]; - self->startframe = level.framenum; - } - else - { - float next_angle; - - next_angle = self->s.angles[ROLL] + self->avelocity[ROLL]*FRAMETIME; - if( (next_angle >= 0 && self->s.angles[ROLL] < 0) || - (next_angle <= 0 && self->s.angles[ROLL] > 0) ) - { - VectorClear(self->s.angles); - VectorClear(self->avelocity); - gi.linkentity(self); - return; - } - } - self->nextthink = level.time + FRAMETIME; - } - else - { - float old_velocity = self->avelocity[ROLL]; - - if(!self->startframe) - self->startframe = level.framenum; - - sgor = sqrt( (float)sv_gravity->value / self->radius ); - wave = sgor * (level.framenum - self->startframe) * 0.1; - this_angle = self->moveinfo.start_angles[ROLL] * cos(wave); - self->avelocity[ROLL] = -self->moveinfo.start_angles[ROLL] * sgor * sin(wave); - if( (self->spawnflags & SF_PENDULUM_STOPPING) && (cos(wave) > 0.0)) - { - if( ((old_velocity > 0) && (self->avelocity[ROLL] <= 0)) || - ((old_velocity < 0) && (self->avelocity[ROLL] >= 0)) ) - { - self->spawnflags &= ~SF_PENDULUM_STARTON; - VectorClear(self->avelocity); - self->nextthink = 0; - gi.linkentity(self); - return; - } - } - self->s.angles[ROLL] = this_angle; - self->nextthink = level.time + FRAMETIME; - } - gi.linkentity(self); -} - -void pendulum_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->spawnflags & SF_PENDULUM_STARTON) - { - if(self->spawnflags & SF_PENDULUM_STOP_AT_TOP) - { - self->spawnflags |= SF_PENDULUM_STOPPING; - } - else - { - VectorClear(self->avelocity); - self->spawnflags &= ~SF_PENDULUM_STARTON; - gi.linkentity(self); - } - } - else - { - self->spawnflags |= SF_PENDULUM_STARTON; - self->spawnflags &= ~SF_PENDULUM_STOPPING; - self->think = pendulum_rotate; - - if(self->delay > 0) - { - float delay; - delay = self->delay * 2.0 * M_PI * sqrt(self->radius/(float)sv_gravity->value); - delay = 0.1 * (int)(10*delay); - self->nextthink = level.time + delay; - self->startframe = level.framenum + delay*10; - if(!(self->spawnflags & SF_PENDULUM_STOP_AT_TOP)) - self->delay = 0; - } - else - { - if(self->s.angles[ROLL] == self->moveinfo.start_angles[ROLL]) - self->startframe = level.framenum; - else - { - float t; - t = acos (self->s.angles[ROLL] / self->moveinfo.start_angles[ROLL]); - t /= sqrt((float)sv_gravity->value / self->radius); - self->startframe = level.framenum - t*10; - } - self->think(self); - } - } -} - -void pendulum_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - // Mostly copied from func_explosive_explode. We can't use that function because - // the origin is a bit different. - - vec3_t origin; - vec3_t forward, left, up; - vec3_t chunkorigin; - vec3_t size; - int count; - int mass; - - // Particles originate from business end of pendulum - AngleVectors(self->s.angles,forward,left,up); - VectorScale(forward,self->move_origin[0],forward); - VectorScale(left,-self->move_origin[1],left); - VectorScale(up,self->move_origin[2],up); - VectorAdd(self->s.origin,forward,origin); - VectorAdd(origin,left,origin); - VectorAdd(origin,up,origin); - - self->mass *= 2; - self->takedamage = DAMAGE_NO; - - VectorSubtract (origin, self->enemy->s.origin, self->velocity); - VectorNormalize (self->velocity); - VectorScale (self->velocity, 150, self->velocity); - - // start chunks towards the center - VectorSet(size, 0, 0, 0); - VectorScale (size, 0.5, size); - - mass = self->mass; - if (!mass) - mass = 75; - - // big chunks - if (mass >= 100) - { - count = mass / 100; - if (count > 8) - count = 8; - while(count--) - { - chunkorigin[0] = origin[0] + crandom() * size[0]; - chunkorigin[1] = origin[1] + crandom() * size[1]; - chunkorigin[2] = origin[2] + crandom() * size[2]; - ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin, 0, 0); - } - } - - // small chunks - count = mass / 25; - if (count > 16) - count = 16; - while(count--) - { - chunkorigin[0] = origin[0] + crandom() * size[0]; - chunkorigin[1] = origin[1] + crandom() * size[1]; - chunkorigin[2] = origin[2] + crandom() * size[2]; - ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin, 0, 0); - } - G_FreeEdict (self); -} - -void SP_func_pendulum (edict_t *ent) -{ - float max_speed; - - ent->class_id = ENTITY_FUNC_PENDULUM; - ent->solid = SOLID_BSP; - ent->movetype = MOVETYPE_PENDULUM; - if(!st.distance) - ent->moveinfo.distance = 90; - else - ent->moveinfo.distance = st.distance; - - if(st.noise) - ent->noise_index = gi.soundindex(st.noise); - else - ent->noise_index = gi.soundindex("world/land.wav"); - - if(ent->moveinfo.distance >= 360) - { - gi.dprintf("func_pendulum distance must be < 360\n"); - ent->moveinfo.distance = 359.; - } - - if (!ent->speed) - ent->speed = 100; - if (!ent->radius) - ent->radius = 100; - if (!ent->mass) - ent->mass = 200; - if (st.phase > 0) - ent->delay = st.phase; - else - ent->delay = 0; - if(ent->delay > 1.0) - ent->delay -= (int)(ent->delay); - - // Coefficient of restitution - default = 0.5, must be <= 1.0 - if(ent->attenuation == 0.0) - ent->attenuation = 0.5; - else if(ent->attenuation > 1.0) - ent->attenuation = 1.0; - - if (!ent->dmg) - ent->dmg = 5; - // This is the damage delivered by the pendulum at max speed. Convert to - // a damage scale used in our damage equation. - max_speed = ent->moveinfo.distance/2 * M_PI / 180. * sqrt((float)sv_gravity->value * ent->radius ); - if(max_speed <= 200.) - ent->dmg = 0; - else - { - float dmg; - dmg = (float)(ent->dmg) * 100. / (max_speed - 200.); - ent->dmg = (int)(dmg - 0.5) + 1; - } - if(ent->health > 0) - { - ent->die = pendulum_die; - ent->takedamage = DAMAGE_YES; - } - - ent->blocked = pendulum_blocked; -// ent->touch = pendulum_touch; - - if(!ent->accel) - ent->accel = 1; - else if (ent->accel > ent->speed) - ent->accel = ent->speed; - - if(!ent->decel) - ent->decel = 1; - else if (ent->decel > ent->speed) - ent->decel = ent->speed; - - gi.setmodel (ent, ent->model); - - ent->s.angles[ROLL] = ent->moveinfo.distance/2; - ent->moveinfo.start_angles[ROLL] = ent->s.angles[ROLL]; - if(ent->spawnflags & SF_PENDULUM_STARTON) - { - ent->think = pendulum_rotate; - ent->nextthink = level.time + FRAMETIME; - } - else - { - ent->use = pendulum_use; - } - gi.linkentity (ent); - -} - diff --git a/server/ents/g_reflect.c b/server/ents/g_reflect.c deleted file mode 100644 index 2de3e5ed..00000000 --- a/server/ents/g_reflect.c +++ /dev/null @@ -1,493 +0,0 @@ -#include "g_local.h" - -/* Func_reflect is adopted from psychospaz' original floor reflection code. See - psychospaz' stuff at http://modscape.telefragged.com - - Chief differences: - 1) The obvious - reflections work in 6 directions, not just the floor. - 2) Uses a new entity rather than automatically doing reflections based on surface - or content properties of the floor. - 3) Most TE_ effects are reflected, in addition to entities. This requires calls to - the appropriate ReflectXXXXX routine in several places scattered around the code. - 4) Roll angle is correct. - - You can have up to 16 func_reflects in one map. To increase that number change - MAX_MIRRORS below. The only reason to use a static limit is that the func_reflect - entity addresses get copied to g_mirror, which makes searching for func_reflects - much easier. -*/ - -#define MAX_MIRRORS 16 -edict_t *g_mirror[MAX_MIRRORS]; - -#define SF_REFLECT_OFF 1 -#define SF_REFLECT_TOGGLE 2 - -void ReflectExplosion (int type, vec3_t origin) -{ - int m; - edict_t *mirror; - vec3_t org; - - if(!level.num_reflectors) - return; - - for(m=0; minuse) - continue; - if(mirror->spawnflags & SF_REFLECT_OFF) - continue; - - // Don't reflect explosions (other than BFG) from floor or ceiling, - // 'cuz there's no way to do it right - if((mirror->style <= 1) && (type != TE_BFG_EXPLOSION) && (type != TE_BFG_BIGEXPLOSION)) - continue; - - VectorCopy(origin,org); - switch(mirror->style) - { - case 0: org[2] = 2*mirror->absmax[2] - origin[2] + mirror->moveinfo.distance - 2; break; - case 1: org[2] = 2*mirror->absmin[2] - origin[2] - mirror->moveinfo.distance + 2; break; - case 2: org[0] = 2*mirror->absmin[0] - origin[0] + mirror->moveinfo.distance + 2; break; - case 3: org[0] = 2*mirror->absmax[0] - origin[0] - mirror->moveinfo.distance - 2; break; - case 4: org[1] = 2*mirror->absmin[1] - origin[1] + mirror->moveinfo.distance + 2; break; - case 5: org[1] = 2*mirror->absmax[1] - origin[1] - mirror->moveinfo.distance - 2; break; - } - if(org[0] < mirror->absmin[0]) continue; - if(org[0] > mirror->absmax[0]) continue; - if(org[1] < mirror->absmin[1]) continue; - if(org[1] > mirror->absmax[1]) continue; - if(org[2] < mirror->absmin[2]) continue; - if(org[2] > mirror->absmax[2]) continue; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (type); - WRITE_COORD (org); - MESSAGE_SEND (MSG_PHS, org, NULL); - } -} - -void ReflectTrail (int type, vec3_t start, vec3_t end) -{ - int m; - edict_t *mirror; - vec3_t p1, p2; - - if(!level.num_reflectors) - return; - - for(m=0; minuse) - continue; - if(mirror->spawnflags & SF_REFLECT_OFF) - continue; - - VectorCopy(start,p1); - VectorCopy(end, p2); - switch(mirror->style) - { - case 0: - p1[2] = 2*mirror->absmax[2] - start[2] + mirror->moveinfo.distance + 2; - p2[2] = 2*mirror->absmax[2] - end[2] + mirror->moveinfo.distance + 2; - break; - case 1: - p1[2] = 2*mirror->absmin[2] - start[2] - mirror->moveinfo.distance - 2; - p2[2] = 2*mirror->absmin[2] - end[2] - mirror->moveinfo.distance - 2; - break; - case 2: - p1[0] = 2*mirror->absmin[0] - start[0] + mirror->moveinfo.distance + 2; - p2[0] = 2*mirror->absmin[0] - end[0] + mirror->moveinfo.distance + 2; - break; - case 3: - p1[0] = 2*mirror->absmax[0] - start[0] - mirror->moveinfo.distance - 2; - p2[0] = 2*mirror->absmax[0] - end[0] - mirror->moveinfo.distance - 2; - break; - case 4: - p1[1] = 2*mirror->absmin[1] - start[1] + mirror->moveinfo.distance + 2; - p2[1] = 2*mirror->absmin[1] - end[1] + mirror->moveinfo.distance + 2; - break; - case 5: - p1[1] = 2*mirror->absmax[1] - start[1] - mirror->moveinfo.distance - 2; - p2[1] = 2*mirror->absmax[1] - end[1] - mirror->moveinfo.distance - 2; - break; - } - if(p1[0] < mirror->absmin[0]) continue; - if(p1[0] > mirror->absmax[0]) continue; - if(p1[1] < mirror->absmin[1]) continue; - if(p1[1] > mirror->absmax[1]) continue; - if(p1[2] < mirror->absmin[2]) continue; - if(p1[2] > mirror->absmax[2]) continue; - - // If p1 is within func_reflect, we assume p2 is also. If map is constructed - // properly this should always be true. - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (type); - WRITE_COORD (p1); - WRITE_COORD (p2); - MESSAGE_SEND (MSG_PHS, p1, NULL); - } -} - -void ReflectSteam (vec3_t origin,vec3_t movedir,int count,int sounds,int speed, int wait, int nextid) -{ - int m; - edict_t *mirror; - vec3_t org, dir; - - if(!level.num_reflectors) - return; - - for(m=0; minuse) - continue; - if(mirror->spawnflags & SF_REFLECT_OFF) - continue; - - VectorCopy(origin,org); - VectorCopy(movedir,dir); - switch(mirror->style) - { - case 0: - org[2] = 2*mirror->absmax[2] - origin[2] + mirror->moveinfo.distance + 2; - dir[2] = -dir[2]; - break; - case 1: - org[2] = 2*mirror->absmin[2] - origin[2] - mirror->moveinfo.distance - 2; - dir[2] = -dir[2]; - break; - case 2: - org[0] = 2*mirror->absmin[0] - origin[0] + mirror->moveinfo.distance + 2; - dir[0] = -dir[0]; - break; - case 3: - org[0] = 2*mirror->absmax[0] - origin[0] - mirror->moveinfo.distance - 2; - dir[0] = -dir[0]; - break; - case 4: - org[1] = 2*mirror->absmin[1] - origin[1] + mirror->moveinfo.distance + 2; - dir[1] = -dir[1]; - break; - case 5: - org[1] = 2*mirror->absmax[1] - origin[1] - mirror->moveinfo.distance - 2; - dir[1] = -dir[1]; - break; - } - if(org[0] < mirror->absmin[0]) continue; - if(org[0] > mirror->absmax[0]) continue; - if(org[1] < mirror->absmin[1]) continue; - if(org[1] > mirror->absmax[1]) continue; - if(org[2] < mirror->absmin[2]) continue; - if(org[2] > mirror->absmax[2]) continue; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_STEAM); - WRITE_SHORT (nextid); - WRITE_BYTE (count); - WRITE_COORD (org); - WRITE_DIR (dir); - WRITE_BYTE (sounds&0xff); - WRITE_SHORT (speed); - WRITE_LONG (wait); - MESSAGE_SEND (MSG_PHS, org, NULL); - } -} - -void ReflectSparks (int type,vec3_t origin,vec3_t movedir) -{ - int m; - edict_t *mirror; - vec3_t org, dir; - - if(!level.num_reflectors) - return; - - for(m=0; minuse) - continue; - if(mirror->spawnflags & SF_REFLECT_OFF) - continue; - // Don't reflect in floor or ceiling because sparks are affected by - // gravity - if(mirror->style <= 1) - continue; - - VectorCopy(origin,org); - VectorCopy(movedir,dir); - switch(mirror->style) - { - case 0: - org[2] = 2*mirror->absmax[2] - origin[2] + mirror->moveinfo.distance + 2; - dir[2] = -dir[2]; - break; - case 1: - org[2] = 2*mirror->absmin[2] - origin[2] - mirror->moveinfo.distance - 2; - dir[2] = -dir[2]; - break; - case 2: - org[0] = 2*mirror->absmin[0] - origin[0] + mirror->moveinfo.distance + 2; - dir[0] = -dir[0]; - break; - case 3: - org[0] = 2*mirror->absmax[0] - origin[0] - mirror->moveinfo.distance - 2; - dir[0] = -dir[0]; - break; - case 4: - org[1] = 2*mirror->absmin[1] - origin[1] + mirror->moveinfo.distance + 2; - dir[1] = -dir[1]; - break; - case 5: - org[1] = 2*mirror->absmax[1] - origin[1] - mirror->moveinfo.distance - 2; - dir[1] = -dir[1]; - break; - } - if(org[0] < mirror->absmin[0]) continue; - if(org[0] > mirror->absmax[0]) continue; - if(org[1] < mirror->absmin[1]) continue; - if(org[1] > mirror->absmax[1]) continue; - if(org[2] < mirror->absmin[2]) continue; - if(org[2] > mirror->absmax[2]) continue; - - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(type); - WRITE_COORD(org); - if(type != TE_CHAINFIST_SMOKE) - { - WRITE_DIR(dir); - } - MESSAGE_SEND(MSG_PHS, org, NULL); - - } -} - -void DeleteReflection (edict_t *ent, int index) -{ - edict_t *r; - - if(index < 0) - { - int i; - for(i=0; i<6; i++) - { - r = ent->reflection[i]; - if(r) - { - if(r->client) - free(r->client); - memset (r, 0, sizeof(*r)); - r->classname = "freed"; - r->freetime = level.time; - r->inuse = false; - } - ent->reflection[i] = NULL; - } - } - else - { - r = ent->reflection[index]; - if(r) - { - if(r->client) - free(r->client); - memset (r, 0, sizeof(*r)); - r->classname = "freed"; - r->freetime = level.time; - r->inuse = false; - ent->reflection[index] = NULL; - } - } -} - -void AddReflection (edict_t *ent) -{ - gclient_t *cl; - edict_t *mirror; - float roll; - int i, m; - bool is_reflected; - vec3_t forward; - vec3_t org, oldorg; - - for(i=0; i<6; i++) - { - is_reflected = false; - for(m=0; minuse) - continue; - if(mirror->spawnflags & SF_REFLECT_OFF) - continue; - if(mirror->style != i) - continue; - VectorCopy(ent->s.origin,org); - switch(i) - { - case 0: org[2] = 2*mirror->absmax[2] - ent->s.origin[2] - mirror->moveinfo.distance - 2; break; - case 1: org[2] = 2*mirror->absmin[2] - ent->s.origin[2] + mirror->moveinfo.distance + 2; break; - case 2: org[0] = 2*mirror->absmin[0] - ent->s.origin[0] + mirror->moveinfo.distance + 2; break; - case 3: org[0] = 2*mirror->absmax[0] - ent->s.origin[0] - mirror->moveinfo.distance - 2; break; - case 4: org[1] = 2*mirror->absmin[1] - ent->s.origin[1] + mirror->moveinfo.distance + 2; break; - case 5: org[1] = 2*mirror->absmax[1] - ent->s.origin[1] - mirror->moveinfo.distance - 2; break; - } - if(org[0] < mirror->absmin[0]) continue; - if(org[0] > mirror->absmax[0]) continue; - if(org[1] < mirror->absmin[1]) continue; - if(org[1] > mirror->absmax[1]) continue; - if(org[2] < mirror->absmin[2]) continue; - if(org[2] > mirror->absmax[2]) continue; - is_reflected = true; - } - if(is_reflected) - { - if (!ent->reflection[i]) - { - ent->reflection[i] = G_Spawn(); - ent->reflection[i]->owner = ent; - ent->reflection[i]->activator = mirror; - - if(ent->s.effects & EF_ROTATE) - { - ent->s.effects &= ~EF_ROTATE; - gi.linkentity(ent); - } - ent->reflection[i]->movetype = MOVETYPE_NONE; - ent->reflection[i]->solid = SOLID_NOT; - ent->reflection[i]->classname = "reflection"; - ent->reflection[i]->flags = FL_REFLECT; - ent->reflection[i]->takedamage = DAMAGE_NO; - } - if (ent->client && !ent->reflection[i]->client) - { - cl = (gclient_t *)malloc(sizeof(gclient_t)); - ent->reflection[i]->client = cl; - } - if (ent->client && ent->reflection[i]->client) - { -// Lazarus: Hmm.. this crashes when loading saved game. -// Not sure what use pers is anyhow? -// ent->reflection[i]->client->pers = ent->client->pers; - ent->reflection[i]->s = ent->s; - } - ent->reflection[i]->s.number = ent->reflection[i] - g_edicts; - ent->reflection[i]->s.modelindex = ent->s.modelindex; - ent->reflection[i]->s.weaponmodel = ent->s.weaponmodel; - ent->reflection[i]->s.body = ent->s.body; - ent->reflection[i]->s.sequence = ent->s.sequence; - ent->reflection[i]->s.skin = ent->s.skin; - ent->reflection[i]->s.frame = ent->s.frame; - ent->reflection[i]->s.renderfx = ent->s.renderfx; - ent->reflection[i]->s.effects = ent->s.effects; - ent->reflection[i]->s.renderfx &= ~RF_IR_VISIBLE; - - VectorCopy (ent->s.angles, ent->reflection[i]->s.angles); - switch(i) - { - case 0: - case 1: - ent->reflection[i]->s.angles[PITCH]+=180; - ent->reflection[i]->s.angles[YAW] +=180; - ent->reflection[i]->s.angles[ROLL] =360-ent->reflection[i]->s.angles[ROLL]; - break; - case 2: - case 3: - AngleVectors(ent->reflection[i]->s.angles,forward,NULL,NULL); - roll = ent->reflection[i]->s.angles[ROLL]; - forward[0] = -forward[0]; - vectoangles(forward,ent->reflection[i]->s.angles); - if((ent->s.angles[PITCH] > 90) && (ent->s.angles[PITCH] < 270)) - { - ent->reflection[i]->s.angles[YAW] += 180; - ent->reflection[i]->s.angles[PITCH] = 180-ent->reflection[i]->s.angles[PITCH]; - } - ent->reflection[i]->s.angles[ROLL] = 360-roll; - break; - case 4: - case 5: - AngleVectors(ent->reflection[i]->s.angles,forward,NULL,NULL); - roll = ent->reflection[i]->s.angles[ROLL]; - forward[1] = -forward[1]; - vectoangles(forward,ent->reflection[i]->s.angles); - if((ent->s.angles[PITCH] > 90) && (ent->s.angles[PITCH] < 270)) - { - ent->reflection[i]->s.angles[YAW] += 180; - ent->reflection[i]->s.angles[PITCH] = 180-ent->reflection[i]->s.angles[PITCH]; - } - ent->reflection[i]->s.angles[ROLL] = 360-roll; - } - - // Move player floor reflections down an additional bit so that their - // feet don't poke through the floor when looking down. - if(ent->client && i==0) - org[2] -= 4; - - VectorCopy (ent->reflection[i]->s.origin,oldorg); - VectorCopy (org, ent->reflection[i]->s.origin); - if(ent->s.renderfx & RF_BEAM) - { - vec3_t delta; - - VectorSubtract(ent->reflection[i]->s.origin,ent->s.origin,delta); - VectorAdd(ent->s.old_origin,delta,ent->reflection[i]->s.old_origin); - } - else - { -// VectorCopy(oldorg, ent->reflection[i]->s.old_origin); - VectorCopy(org,ent->reflection[i]->s.old_origin); - } - - gi.linkentity (ent->reflection[i]); - } - else if (ent->reflection[i]) - { - DeleteReflection(ent,i); - } - } -} - -void use_func_reflect (edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->spawnflags & SF_REFLECT_OFF) - { - // was off, turn it on - self->spawnflags &= ~SF_REFLECT_OFF; - } - else - { - // was on, turn it off - self->spawnflags |= SF_REFLECT_OFF; - } - if (!(self->spawnflags & SF_REFLECT_TOGGLE)) - self->use = NULL; -} - -void SP_func_reflect (edict_t *self) -{ - if(level.num_reflectors >= MAX_MIRRORS) - { - gi.dprintf("Max number of func_reflect's (%d) exceeded.\n",MAX_MIRRORS); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_FUNC_REFLECT; - gi.setmodel (self, self->model); - self->svflags = SVF_NOCLIENT; - g_mirror[level.num_reflectors] = self; - if(!st.lip) - st.lip = 2; - self->moveinfo.distance = st.lip; - self->use = use_func_reflect; - level.num_reflectors++; -} diff --git a/server/ents/g_target.c b/server/ents/g_target.c deleted file mode 100644 index 2f2e6b7a..00000000 --- a/server/ents/g_target.c +++ /dev/null @@ -1,4208 +0,0 @@ -#include "g_local.h" - -#define IF_VISIBLE 8 -#define SEEK_PLAYER 128 - - -/*QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8) -Fire an origin based temp entity event to the clients. -"style" type byte -*/ -void Use_Target_Tent (edict_t *self, edict_t *other, edict_t *activator) -{ - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (self->style); - WRITE_COORD (self->s.origin); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - -} - -void SP_target_temp_entity (edict_t *ent) -{ - ent->class_id = ENTITY_TARGET_TEMP_ENTITY; - ent->use = Use_Target_Tent; -} - - -//========================================================== - -//========================================================== - -/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable changelevel -"noise" wav file to play -"attenuation" -DWH --2 = only played (full volume) for player who triggered the target_speaker -end DWH - --1 = none, send to whole level - 1 = normal fighting sounds - 2 = idle sound level - 3 = ambient sound level -"volume" 0.0 to 1.0 - -Normal sounds play each time the target is used. The reliable flag can be set for crucial voiceovers. - -Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off. -Multiple identical looping sounds will just increase volume without any speed cost. - -Changelevel spawnflag added for Lazarus. This should ONLY be applied in the code, -and is an indication that the "message" key contains the noise. -*/ -void Use_Target_Speaker (edict_t *ent, edict_t *other, edict_t *activator) -{ - int chan; - - if (ent->spawnflags & 3) - { // looping sound toggles - if (ent->s.sound) { - ent->s.sound = 0; // turn it off - ent->nextthink = 0; - } - else - ent->s.sound = ent->noise_index; // start it - } - else - { - if(ent->attenuation == -2) { - if(ent->spawnflags & 4) - chan = CHAN_VOICE|CHAN_RELIABLE; - else - chan = CHAN_VOICE; - gi.sound (activator, chan, ent->noise_index, 1, ATTN_NORM, 0); - } - else - { // normal sound - if (ent->spawnflags & 4) - chan = CHAN_VOICE|CHAN_RELIABLE; - else - chan = CHAN_VOICE; - // use a positioned_sound, because this entity won't normally be - // sent to any clients because it is invisible - gi.positioned_sound (ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0); - } - - ent->count--; - if(!ent->count) { - ent->think = G_FreeEdict; - ent->nextthink = level.time + 1; - } - } -} - -void SP_target_speaker (edict_t *ent) -{ - if(!(ent->spawnflags & 8)) - { - if(!st.noise) - { - gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin)); - G_FreeEdict(ent); - return; - } - // DWH: Use "message" key to store noise for speakers that change levels - // via trigger_transition - if (!strstr (st.noise, ".wav")) - { - ent->message = TagMalloc(strlen(st.noise)+5,TAG_LEVEL); - sprintf(ent->message,"%s.wav", st.noise); - } - else - { - ent->message = TagMalloc(strlen(st.noise)+1,TAG_LEVEL); - strcpy(ent->message,st.noise); - } - } - ent->class_id = ENTITY_TARGET_SPEAKER; - ent->noise_index = gi.soundindex (ent->message); - ent->spawnflags &= ~8; - - if (!ent->volume) - ent->volume = 1.0; - - if (!ent->attenuation) - ent->attenuation = 1.0; - else if (ent->attenuation == -1) // use -1 so 0 defaults to 1 - ent->attenuation = 0; - - // check for prestarted looping sound - if (ent->spawnflags & 1) - ent->s.sound = ent->noise_index; - - ent->use = Use_Target_Speaker; - - // must link the entity so we get areas and clusters so - // the server can determine who to send updates to - gi.linkentity (ent); -} - - -//========================================================== - -void Use_Target_Help (edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->message) - { - if (self->spawnflags & 1) - strncpy (game.helpmessage1, self->message, sizeof(game.helpmessage2)-1); - else - strncpy (game.helpmessage2, self->message, sizeof(game.helpmessage1)-1); - } - - game.helpchanged++; - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -/*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1 -When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars. -*/ -void SP_target_help(edict_t *ent) -{ - if (deathmatch->value) - { // auto-remove for deathmatch - G_FreeEdict (ent); - return; - } - ent->class_id = ENTITY_TARGET_HELP; - - // Lazarus: we allow blank message if world->effects is "help=pic only" - if (!ent->message && !(world->effects & FX_WORLDSPAWN_NOHELP)) - { - gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin)); - G_FreeEdict (ent); - return; - } - ent->use = Use_Target_Help; -} - -//========================================================== - -/*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8) -Counts a secret found. -These are single use targets. - -Lazarus: -DISABLED SF=1 - -*/ -void use_target_secret (edict_t *ent, edict_t *other, edict_t *activator) -{ - if(ent->spawnflags & 1) - { - ent->spawnflags &= ~1; - level.total_secrets++; - return; - } - gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); - - level.found_secrets++; - - G_UseTargets (ent, activator); - G_FreeEdict (ent); -} - -void SP_target_secret (edict_t *ent) -{ - if (deathmatch->value) - { // auto-remove for deathmatch - G_FreeEdict (ent); - return; - } - ent->class_id = ENTITY_TARGET_SECRET; - ent->use = use_target_secret; - if (!st.noise) - st.noise = "misc/secret.wav"; - ent->noise_index = gi.soundindex (st.noise); - ent->svflags = SVF_NOCLIENT; - - if(!(ent->spawnflags & 1)) - level.total_secrets++; - - // map bug hack - if (!strcasecmp(level.mapname, "mine3") && ent->s.origin[0] == 280 && ent->s.origin[1] == -2048 && ent->s.origin[2] == -624) - ent->message = "You have found a secret area."; -} - -//========================================================== - -/*QUAKED target_goal (1 0 1) (-8 -8 -8) (8 8 8) -Counts a goal completed. -These are single use targets. - -Lazarus: -DISABLED SF=1 - -*/ -void use_target_goal (edict_t *ent, edict_t *other, edict_t *activator) -{ - if(ent->spawnflags & 1) - { - ent->spawnflags &= ~1; - level.total_goals++; - return; - } - gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); - - level.found_goals++; - - if (level.found_goals == level.total_goals) - gi.configstring (CS_CDTRACK, "0"); - - G_UseTargets (ent, activator); - G_FreeEdict (ent); -} - -void SP_target_goal (edict_t *ent) -{ - if (deathmatch->value) - { // auto-remove for deathmatch - G_FreeEdict (ent); - return; - } - ent->class_id = ENTITY_TARGET_GOAL; - ent->use = use_target_goal; - if (!st.noise) - st.noise = "misc/secret.wav"; - ent->noise_index = gi.soundindex (st.noise); - ent->svflags = SVF_NOCLIENT; - - if(!(ent->spawnflags & 1)) - level.total_goals++; -} - -//========================================================== - - -/*QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8) -Spawns an explosion temporary entity when used. - -"delay" wait this long before going off -"dmg" how much radius damage should be done, defaults to 0 -*/ -void target_explosion_explode (edict_t *self) -{ - float save; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_EXPLOSION1); - WRITE_COORD (self->s.origin); - MESSAGE_SEND (MSG_PHS, self->s.origin, NULL); - - if(level.num_reflectors) - ReflectExplosion (TE_EXPLOSION1,self->s.origin); - - T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE, -0.5); - - save = self->delay; - self->delay = 0; - G_UseTargets (self, self->activator); - self->delay = save; - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void use_target_explosion (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - - if (!self->delay) - { - target_explosion_explode (self); - return; - } - - self->think = target_explosion_explode; - self->nextthink = level.time + self->delay; -} - -void SP_target_explosion (edict_t *ent) -{ - ent->class_id = ENTITY_TARGET_EXPLOSION; - ent->use = use_target_explosion; - ent->svflags = SVF_NOCLIENT; -} - - -//========================================================== - -/*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) -Changes level to "map" when fired - -Lazarus spawnflags: - 1 CLEAR_INVENTORY: Removes all pickups other than weapons, restore health to 100 - 2 LANDMARK: If set, player position when spawning in the next map will be at the - same offset from the info_player_start as his current position relative - to the target_changelevel. Velocity, angles, and crouch state will be - preserved across maps. - 4 NO_GUN Sets cl_gun 0 and crosshair 0 for the next map/demo only - 8 EASY Sets skill 0 for next map -16 NORMAL Sets skill 1 for next map -32 HARD Sets skill 2 for next map -64 NIGHTMARE Sets skill 3 for next map -*/ -void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *transition; - extern int nostatus; - - if (level.intermissiontime) - return; // already activated - - if (!deathmatch->value && !coop->value) - { - if (g_edicts[1].health <= 0) - return; - } - - // if noexit, do a ton of damage to other - if (deathmatch->value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != world) - { - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); - return; - } - - FMOD_Stop(); - - // if multiplayer, let everyone know who hit the exit - if (deathmatch->value) - { - if (activator && activator->client) - gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); - } - - if (activator->client) - { - if(activator->client->chasetoggle) - { - ChasecamRemove (activator, OPTION_OFF); - activator->client->pers.chasetoggle = 1; - } - else - activator->client->pers.chasetoggle = 0; - - if(!activator->vehicle) - activator->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - } - - // if going to a new unit, clear cross triggers - if (strstr(self->map, "*")) - { - game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); - game.lock_code[0] = 0; - game.lock_revealed = 0; - game.lock_hud = 0; - game.transition_ents = 0; - if(activator->client) - { - activator->client->pers.spawn_landmark = false; - activator->client->pers.spawn_levelchange = false; - } - } - else - { - if(self->spawnflags & 2 && activator->client) - { - activator->client->pers.spawn_landmark = true; - VectorSubtract(activator->s.origin,self->s.origin, - activator->client->pers.spawn_offset); - VectorCopy(activator->velocity,activator->client->pers.spawn_velocity); - VectorCopy(activator->s.angles,activator->client->pers.spawn_angles); - activator->client->pers.spawn_angles[ROLL] = 0; - VectorCopy(activator->client->ps.viewangles,activator->client->pers.spawn_viewangles); - activator->client->pers.spawn_pm_flags = activator->client->ps.pmove.pm_flags; - if(self->s.angles[YAW]) - { - vec3_t angles; - vec3_t forward, right, v; - - angles[PITCH] = angles[ROLL] = 0.; - angles[YAW] = self->s.angles[YAW]; - AngleVectors(angles,forward,right,NULL); - VectorNegate(right,right); - VectorCopy(activator->client->pers.spawn_offset,v); - G_ProjectSource (vec3_origin, - v, forward, right, - activator->client->pers.spawn_offset); - VectorCopy(activator->client->pers.spawn_velocity,v); - G_ProjectSource (vec3_origin, - v, forward, right, - activator->client->pers.spawn_velocity); - activator->client->pers.spawn_angles[YAW] += angles[YAW]; - activator->client->pers.spawn_viewangles[YAW] += angles[YAW]; - } - } - else - { - activator->client->pers.spawn_landmark = false; - } - - if((self->spawnflags & 4) && activator->client && !deathmatch->value && !coop->value) - { - nostatus = 1; - stuffcmd(activator,"cl_gun 0;crosshair 0\n"); - activator->client->pers.hand = 2; - } - - activator->client->pers.spawn_levelchange = true; - activator->client->pers.spawn_gunframe = activator->client->ps.gunframe; - activator->client->pers.spawn_modelframe = activator->s.frame; - activator->client->pers.spawn_anim_end = activator->client->anim_end; - } - - if(level.next_skill > 0) - { - gi.cvar_forceset("skill", va("%d",level.next_skill-1)); - level.next_skill = 0; // reset - } - else if(self->spawnflags & 8) - gi.cvar_forceset("skill", "0"); - else if(self->spawnflags & 16) - gi.cvar_forceset("skill", "1"); - else if(self->spawnflags & 32) - gi.cvar_forceset("skill", "2"); - else if(self->spawnflags & 64) - gi.cvar_forceset("skill", "3"); - - if(self->spawnflags & 1) - { - int n; - if(activator && activator->client) - { - for (n = 0; n < MAX_ITEMS; n++) - { - // Keep blaster - if (!(itemlist[n].flags & IT_WEAPON) || itemlist[n].weapmodel != WEAP_BLASTER ) - activator->client->pers.inventory[n] = 0; - } - // Switch to blaster - if ( activator->client->pers.inventory[ITEM_INDEX(FindItem("blaster"))] ) - activator->client->newweapon = FindItem ("blaster"); - else - activator->client->newweapon = FindItem ("No Weapon"); - ChangeWeapon(activator); - activator->client->pers.health = activator->health = 100; - } - } - game.transition_ents = 0; - if(self->spawnflags & 2 && activator->client) - { - transition = G_Find(NULL,FOFS(classname),"trigger_transition"); - while(transition) - { - if(!strcasecmp(transition->targetname,self->targetname)) - { - game.transition_ents = trigger_transition_ents(self,transition); - break; - } - transition = G_Find(transition,FOFS(classname),"trigger_transition"); - } - } - BeginIntermission (self); -} - -void SP_target_changelevel (edict_t *ent) -{ - if (!ent->map) - { - gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin)); - G_FreeEdict (ent); - return; - } - ent->class_id = ENTITY_TARGET_CHANGELEVEL; - - if ((deathmatch->value || coop->value) && (ent->spawnflags & 2)) - { - gi.dprintf("target_changelevel at %s\nLANDMARK only valid in single-player\n", - vtos(ent->s.origin)); - ent->spawnflags &= ~2; - } - // ugly hack because *SOMEBODY* screwed up their map - if((strcasecmp(level.mapname, "fact1") == 0) && (strcasecmp(ent->map, "fact3") == 0)) - ent->map = "fact3$secret1"; - - ent->use = use_target_changelevel; - ent->svflags = SVF_NOCLIENT; -} - - -//========================================================== - -/*QUAKED target_splash (1 0 0) (-8 -8 -8) (8 8 8) -Creates a particle splash effect when used. - -Set "sounds" to one of the following: - 1) sparks - 2) blue water - 3) brown water - 4) slime - 5) lava - 6) blood - -"count" how many pixels in the splash -"dmg" if set, does a radius damage at this location when it splashes - useful for lava/sparks -*/ - - -void use_target_splash (edict_t *self, edict_t *other, edict_t *activator) -{ - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_SPLASH); - WRITE_BYTE (self->count); - WRITE_COORD (self->s.origin); - WRITE_DIR (self->movedir); - WRITE_BYTE (self->sounds); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - if (self->dmg) - T_RadiusDamage (self, activator, self->dmg, NULL, self->dmg+40, MOD_SPLASH, -0.5); -} - -void SP_target_splash (edict_t *self) -{ - self->class_id = ENTITY_TARGET_SPLASH; - self->use = use_target_splash; - G_SetMovedir (self->s.angles, self->movedir); - if (!self->count) - self->count = 32; - self->svflags = SVF_NOCLIENT; -} - -//========================================================== - -/*QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8) -Set target to the type of entity you want spawned. -Useful for spawning monsters and gibs in the factory levels. - -For monsters: - Set direction to the facing you want it to have. - -For gibs: - Set direction if you want it moving and - speed how fast it should be moving otherwise it - will just be dropped -*/ -void ED_CallSpawn (edict_t *ent); - -void use_target_spawner (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *ent; - - ent = G_Spawn(); - ent->classname = self->target; - VectorCopy (self->s.origin, ent->s.origin); - VectorCopy (self->s.angles, ent->s.angles); - ED_CallSpawn (ent); - gi.unlinkentity (ent); - KillBox (ent); - gi.linkentity (ent); - if (self->speed) - VectorCopy (self->movedir, ent->velocity); - - self->count--; - if(!self->count) - { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - -} - - -void SP_target_spawner (edict_t *self) -{ - self->class_id = ENTITY_TARGET_SPAWNER; - self->use = use_target_spawner; - self->svflags = SVF_NOCLIENT; - if (self->speed) - { - G_SetMovedir (self->s.angles, self->movedir); - VectorScale (self->movedir, self->speed, self->movedir); - } -} - -//========================================================== - -/*QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS -Fires a blaster bolt in the set direction when triggered. - -dmg default is 15 -speed default is 1000 -*/ - -/* Lazarus: -sounds - weapon choice -0 = blaster -1 = railgun -2 = rocket -3 = bfg -4 = homing rocket -5 = machinegun -6 = grenade -*/ - -void use_target_blaster (edict_t *self, edict_t *other, edict_t *activator) -{ - vec3_t movedir, start, target; - int effect; - - VectorCopy(self->s.origin,start); - if (self->enemy) - { - if(self->sounds == 6) - { - if(!AimGrenade (self, start, self->enemy->s.origin, self->speed, movedir)) - return; - } - else - { - VectorMA(self->enemy->absmin,0.5,self->enemy->size,target); - VectorSubtract(target,start,movedir); - VectorNormalize(movedir); - } - } else - VectorCopy(self->movedir,movedir); - - if (self->spawnflags & 2) - effect = 0; - else if (self->spawnflags & 1) - effect = EF_HYPERBLASTER; - else - effect = EF_BLASTER; - - // Lazarus: weapon choices - if(self->sounds == 1) - { - fire_rail (self, start, movedir, self->dmg, 0); - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (self-g_edicts); - WRITE_BYTE (MZ_RAILGUN); - MESSAGE_SEND (MSG_PVS, start, NULL); - } - else if(self->sounds == 2) - { - fire_rocket(self, start, movedir, self->dmg, self->speed, self->dmg, self->dmg, NULL); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); - } - else if(self->sounds == 3) - { - fire_bfg(self, start, movedir, self->dmg, self->speed, self->dmg); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/laser2.wav"), 1, ATTN_NORM, 0); - } - else if(self->sounds == 4) - { - fire_rocket(self, start, movedir, self->dmg, self->speed, self->dmg, self->dmg, self->enemy); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); - } - else if(self->sounds == 5) - { - fire_bullet(self, start, movedir, self->dmg, 2, 0, 0, MOD_TARGET_BLASTER); - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_CHAINFIST_SMOKE); - WRITE_COORD(start); - MESSAGE_SEND(MSG_PVS, start, NULL); - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex(va("weapons/machgf%db.wav",rand() % 5 + 1)),1,ATTN_NORM,0); - } - else if(self->sounds == 6) - { - fire_grenade(self, start, movedir, self->dmg, self->speed, 2.5, self->dmg+40); - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (MZ2_GUNNER_GRENADE_1); - MESSAGE_SEND (MSG_PVS, start, NULL); - } - else - { - fire_blaster (self, start, movedir, self->dmg, self->speed, effect, MOD_TARGET_BLASTER); - gi.sound (self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); - } -} - -void target_blaster_think (edict_t *self) -{ - edict_t *ent; - edict_t *player; - trace_t tr; - vec3_t target; - int i; - - if(self->spawnflags & SEEK_PLAYER) { - // this takes precedence over everything else - - // If we are currently targeting a non-player, reset and look for - // a player - if (self->enemy && !self->enemy->client) - self->enemy = NULL; - - // Is currently targeted player alive and not using notarget? - if (self->enemy) { - if(self->enemy->flags & FL_NOTARGET) - self->enemy = NULL; - else if(!self->enemy->inuse || self->enemy->health < 0) - self->enemy = NULL; - } - - // We have a live not-notarget player as target. If IF_VISIBLE is - // set, see if we can see him - if (self->enemy && (self->spawnflags & IF_VISIBLE) ) { - VectorMA(self->enemy->absmin,0.5,self->enemy->size,target); - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target,self,MASK_OPAQUE); - if(tr.fraction != 1.0) - self->enemy = NULL; - } - - // If we STILL have an enemy, then he must be a good player target. Frag him - if (self->enemy) { - use_target_blaster(self,self,self); - if(self->wait) - self->nextthink = level.time + self->wait; - return; - } - - // Find a player - note that we search the entire entity list so we'll - // also hit on func_monitor-viewing fake players - for(i=1, player=g_edicts+1; ienemy; i++, player++) { - if(!player->inuse) continue; - if(!player->client) continue; - if(player->svflags & SVF_NOCLIENT) continue; - if(player->health >= 0 && !(player->flags & FL_NOTARGET) ) { - if(self->spawnflags & IF_VISIBLE) { - // player must be seen to shoot - VectorMA(player->s.origin,0.5,player->size,target); - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target,self,MASK_OPAQUE); - if(tr.fraction == 1.0) - self->enemy = player; - } else { - // we don't care whether he can be seen - self->enemy = player; - } - } - } - // If we have an enemy, shoot - if (self->enemy) { - use_target_blaster(self,self,self); - if(self->wait) - self->nextthink = level.time + self->wait; - return; - } - } - - // If we get to this point, then either SEEK_PLAYER wasn't set or we couldn't find - // a live, notarget player. - - if (self->target) { - if (!(self->spawnflags & IF_VISIBLE)) { - // have a target, don't care whether it's visible; cannot be a gibbed monster - self->enemy = NULL; - ent = G_Find (NULL, FOFS(targetname), self->target); - while(ent && !self->enemy) { - // if target is not a monster, we're done - if( !(ent->svflags & SVF_MONSTER)) { - self->enemy = ent; - break; - } - ent = G_Find(ent, FOFS(targetname), self->target); - } - } else { - // has a target, but must be visible and not a monster - self->enemy = NULL; - ent = G_Find (NULL, FOFS(targetname), self->target); - while(ent && !self->enemy) { - // if the target isn't a monster, we don't care whether - // it can be seen or not. - if( !(ent->svflags & SVF_MONSTER) ) { - self->enemy = ent; - break; - } - if( ent->health > ent->gib_health) - { - // Not a gibbed monster - VectorMA(ent->absmin,0.5,ent->size,target); - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target,self,MASK_OPAQUE); - if(tr.fraction == 1.0) - { - self->enemy = ent; - break; - } - } - ent = G_Find(ent, FOFS(targetname), self->target); - } - } - } - if(self->enemy || !(self->spawnflags & IF_VISIBLE) ) { - use_target_blaster(self,self,self); - if(self->wait) - self->nextthink = level.time + self->wait; - } else if(self->wait) - self->nextthink = level.time + FRAMETIME; -} - -void find_target_blaster_target(edict_t *self, edict_t *other, edict_t *activator) -{ - target_blaster_think(self); -} - -void toggle_target_blaster (edict_t *self, edict_t *other, edict_t *activator) -{ - // used for target_blasters with a "wait" value - - self->activator = activator; - if (self->spawnflags & 4) { - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - else - { - self->spawnflags &= ~4; - self->nextthink = 0; - } - } else { - self->spawnflags |= 4; - self->think (self); - } -} - -void target_blaster_init (edict_t *self) -{ - if(self->target) { - edict_t *ent; - ent = G_Find (NULL, FOFS(targetname), self->target); - if(!ent) - gi.dprintf("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); - self->enemy = ent; - } -} -void SP_target_blaster (edict_t *self) -{ - self->class_id = ENTITY_TARGET_BLASTER; - G_SetMovedir (self->s.angles, self->movedir); - self->noise_index = gi.soundindex ("weapons/laser2.wav"); - - if (!self->dmg) - self->dmg = 15; - if (!self->speed) - self->speed = 1000; - - // If SEEK_PLAYER is not set and there's no target, then - // IF_VISIBLE is meaningless - if (!(self->spawnflags & 128) && !self->target) - self->spawnflags &= ~16; - - if (self->wait) { - // toggled target_blaster - self->use = toggle_target_blaster; - self->enemy = NULL; // for now - self->think = target_blaster_think; - if(self->spawnflags & 4) - self->nextthink = level.time + 1; - else - self->nextthink = 0; - } else if(self->target || (self->spawnflags & SEEK_PLAYER)) { - self->use = find_target_blaster_target; - if(self->target) { - self->think = target_blaster_init; - self->nextthink = level.time + 2*FRAMETIME; - } - } else { - // normal targeted target_blaster - self->use = use_target_blaster; - } - - gi.linkentity(self); - self->svflags = SVF_NOCLIENT; -} - - -//========================================================== - -/*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 -Once this trigger is touched/used, any trigger_crosslevel_target with the same trigger number is automatically used when a level is started within the same unit. It is OK to check multiple triggers. Message, delay, target, and killtarget also work. -*/ -void trigger_crosslevel_trigger_use (edict_t *self, edict_t *other, edict_t *activator) -{ - game.serverflags |= self->spawnflags; - // DWH: By most editors, the trigger should be able to fire targets. Added - // the following line: - G_UseTargets (self, activator); - G_FreeEdict (self); -} - -void SP_target_crosslevel_trigger (edict_t *self) -{ - self->class_id = ENTITY_TARGET_CROSSLEVEL_TRIGGER; - self->svflags = SVF_NOCLIENT; - self->use = trigger_crosslevel_trigger_use; -} - -/*QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 -Triggered by a trigger_crosslevel elsewhere within a unit. If multiple triggers are checked, all must be true. Delay, target and -killtarget also work. - -"delay" delay before using targets if the trigger has been activated (default 1) -*/ -void target_crosslevel_target_think (edict_t *self) -{ - if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags)) - { - G_UseTargets (self, self); - G_FreeEdict (self); - } -} - -void SP_target_crosslevel_target (edict_t *self) -{ - self->class_id = ENTITY_TARGET_CROSSLEVEL_TARGET; - if (! self->delay) - self->delay = 1; - self->svflags = SVF_NOCLIENT; - - self->think = target_crosslevel_target_think; - self->nextthink = level.time + self->delay; -} - -//========================================================== - -/*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT -When triggered, fires a laser. You can either set a target -or a direction. -*/ - -// DWH - player-seeking laser stuff -void target_laser_ps_think (edict_t *self) -{ - edict_t *ignore; - edict_t *player; - trace_t tr; - vec3_t start; - vec3_t end; - vec3_t point; - vec3_t last_movedir; - vec3_t target; - int count; - int i; - - if( self->wait > 0) { - if( level.time >= self->starttime ) { - self->starttime = level.time + self->wait; - self->endtime = level.time + self->delay; - } - else if( level.time >= self->endtime ) { - self->nextthink = level.time + FRAMETIME; - return; - } - } - - if (self->spawnflags & 0x80000000) - count = 8; // spark count - else - count = 4; - - if (self->enemy) { - if(self->enemy->flags & FL_NOTARGET || (self->enemy->health < self->enemy->gib_health) ) - self->enemy = NULL; - else { - // first make sure laser can see the center of the enemy - VectorMA(self->enemy->absmin,0.5,self->enemy->size,target); - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target,self,MASK_OPAQUE); - if(tr.fraction != 1.0) - self->enemy = NULL; - } - } - if (!self->enemy) { - // find a player - as with target_blaster, search entire entity list so - // we'll pick up fake players representing camera-viewers - for(i=1, player=g_edicts+1; ienemy; i++, player++) { - if(!player->inuse) continue; - if(!player->client) continue; - if(player->svflags & SVF_NOCLIENT) continue; - if((player->health >= player->gib_health) && !(player->flags & FL_NOTARGET) ) { - VectorMA(player->absmin,0.5,player->size,target); - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target,self,MASK_OPAQUE); - if(tr.fraction == 1.0) { - self->enemy = player; - self->spawnflags |= 0x80000001; - count = 8; - } - } - } - } - if (!self->enemy) { - self->svflags |= SVF_NOCLIENT; - self->nextthink = level.time + FRAMETIME; - return; - } - - self->svflags &= ~SVF_NOCLIENT; - VectorCopy (self->movedir, last_movedir); - VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point); - VectorSubtract (point, self->s.origin, self->movedir); - VectorNormalize (self->movedir); - if (!VectorCompare(self->movedir, last_movedir)) - self->spawnflags |= 0x80000000; - - ignore = self; - VectorCopy (self->s.origin, start); - VectorMA (start, 2048, self->movedir, end); - while(1) - { - tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); - - if (!tr.ent) - break; - - // hurt it if we can - if (tr.ent->takedamage && !self->style) - { - if(!(tr.ent->flags & FL_IMMUNE_LASER) && (self->dmg > 0) ) - T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); - else if(self->dmg < 0) - { - tr.ent->health -= self->dmg; - if(tr.ent->health > tr.ent->max_health) - tr.ent->health = tr.ent->max_health; - } - } - - // if we hit something that's not a monster or player or is immune to lasers, we're done - if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) - { - if ((self->spawnflags & 0x80000000) && (self->style != 3)) - { - self->spawnflags &= ~0x80000000; - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_LASER_SPARKS); - WRITE_BYTE (count); - WRITE_COORD (tr.endpos); - WRITE_DIR (tr.plane.normal); - WRITE_BYTE (self->s.skin); - MESSAGE_SEND (MSG_PVS, tr.endpos, NULL); - } - break; - } - - ignore = tr.ent; - VectorCopy (tr.endpos, start); - } - VectorCopy (tr.endpos, self->s.old_origin); - self->nextthink = level.time + FRAMETIME; -} - -void target_laser_ps_on (edict_t *self) -{ - if (!self->activator) - self->activator = self; - self->spawnflags |= 0x80000001; -// self->svflags &= ~SVF_NOCLIENT; - if(self->wait > 0) { - self->starttime = level.time + self->wait; - self->endtime = level.time + self->delay; - } - target_laser_ps_think (self); -} - -void target_laser_ps_off (edict_t *self) -{ - self->spawnflags &= ~1; - self->svflags |= SVF_NOCLIENT; - self->nextthink = 0; -} - -void target_laser_ps_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - if (self->spawnflags & 1) { - target_laser_ps_off (self); - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - } - else - target_laser_ps_on (self); -} - -void target_laser_think (edict_t *self) -{ - edict_t *ignore; - vec3_t start; - vec3_t end; - trace_t tr; - vec3_t point; - vec3_t last_movedir; - int count; - - // DWH - if( self->wait > 0) { - // pulsed laser - if( level.time >= self->starttime ) { - self->starttime = level.time + self->wait; - self->endtime = level.time + self->delay; - } - else if( level.time >= self->endtime ) { - self->nextthink = level.time + FRAMETIME; - return; - } - } - // end DWH - - if (self->spawnflags & 0x80000000) - count = 8; - else - count = 4; - - if (self->enemy) - { - VectorCopy (self->movedir, last_movedir); - VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point); - VectorSubtract (point, self->s.origin, self->movedir); - VectorNormalize (self->movedir); - if (!VectorCompare(self->movedir, last_movedir)) - self->spawnflags |= 0x80000000; - } - - ignore = self; - VectorCopy (self->s.origin, start); - VectorMA (start, 2048, self->movedir, end); - while(1) - { - tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); - - if (!tr.ent) - break; - - // hurt it if we can - if (tr.ent->takedamage && !self->style) - { - if(!(tr.ent->flags & FL_IMMUNE_LASER) && (self->dmg > 0)) - T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); - else if(self->dmg < 0) - { - tr.ent->health -= self->dmg; - if(tr.ent->health > tr.ent->max_health) - tr.ent->health = tr.ent->max_health; - } - } - - // if we hit something that's not a monster or player or is immune to lasers, we're done - if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client) ) - { - if ((self->spawnflags & 0x80000000) && (self->style != 3)) - { - self->spawnflags &= ~0x80000000; - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_LASER_SPARKS); - WRITE_BYTE (count); - WRITE_COORD (tr.endpos); - WRITE_DIR (tr.plane.normal); - WRITE_BYTE (self->s.skin); - MESSAGE_SEND (MSG_PVS, tr.endpos, NULL); - } - break; - } - - ignore = tr.ent; - VectorCopy (tr.endpos, start); - } - - VectorCopy (tr.endpos, self->s.old_origin); - - self->nextthink = level.time + FRAMETIME; -} - -void target_laser_on (edict_t *self) -{ - if(self->wait > 0) { - self->starttime = level.time + self->wait; - self->endtime = level.time + self->delay; - } - if (!self->activator) - self->activator = self; - self->spawnflags |= 0x80000001; - self->svflags &= ~SVF_NOCLIENT; - target_laser_think (self); -} - -void target_laser_off (edict_t *self) -{ - self->spawnflags &= ~1; - self->svflags |= SVF_NOCLIENT; - self->nextthink = 0; -} - -void target_laser_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->activator = activator; - if (self->spawnflags & 1) { - target_laser_off (self); - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - } - else - target_laser_on (self); -} - -void target_laser_start (edict_t *self) -{ - edict_t *ent; - - self->movetype = MOVETYPE_NONE; - self->solid = SOLID_NOT; - self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT; - self->s.modelindex = 1; // must be non-zero - - // set the beam diameter - if (self->mass > 1) - self->s.frame = self->mass; - else if(self->spawnflags & 64) - self->s.frame = 16; - else self->s.frame = 4; - - // color will be loaded from xash sprite info - - if (!self->dmg) self->dmg = 1; - VectorSet (self->mins, -8, -8, -8); - VectorSet (self->maxs, 8, 8, 8); - - // DWH - - // pulsed laser - if(self->wait > 0) { - if(self->delay >= self->wait) { - gi.dprintf("target_laser at %s, delay must be < wait.\n", - vtos(self->s.origin)); - self->wait = 0; - } else if(self->delay == 0.) { - gi.dprintf("target_laser at %s, wait > 0 but delay = 0\n", - vtos(self->s.origin)); - self->wait = 0; - } - } - - if (self->spawnflags & 128) { - // player-seeking laser - self->enemy = NULL; - self->use = target_laser_ps_use; - self->think = target_laser_ps_think; - gi.linkentity(self); - if(self->spawnflags & 1) - target_laser_ps_on(self); - else - target_laser_ps_off(self); - return; - } - // end DWH - - if (!self->enemy) - { - if (self->target) - { - ent = G_Find (NULL, FOFS(targetname), self->target); - if (!ent) - gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); - self->enemy = ent; - } - else - { - G_SetMovedir (self->s.angles, self->movedir); - } - } - self->use = target_laser_use; - self->think = target_laser_think; - - gi.linkentity (self); - - if (self->spawnflags & 1) - target_laser_on (self); - else - target_laser_off (self); -} - -void SP_target_laser (edict_t *self) -{ - self->class_id = ENTITY_TARGET_LASER; - // let everything else get spawned before we start firing - self->think = target_laser_start; - self->nextthink = level.time + 1; -} - -//========================================================== - -/*QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE -speed How many seconds the ramping will take -message two letters; starting lightlevel and ending lightlevel -*/ - -#define LIGHTRAMP_TOGGLE 1 -#define LIGHTRAMP_CUSTOM 2 -#define LIGHTRAMP_LOOP 4 -#define LIGHTRAMP_ACTIVE 128 - -void target_lightramp_think (edict_t *self) -{ - char style[2]; - - if(self->spawnflags & LIGHTRAMP_CUSTOM) { - if(self->movedir[2] > 0) - style[0] = self->message[(int)self->movedir[0]]; - else - style[0] = self->message[(int)(self->movedir[1]-self->movedir[0])]; - self->movedir[0]++; - } else { - style[0] = 'a' + self->movedir[0] + (level.time - self->timestamp) / FRAMETIME * self->movedir[2]; - } - style[1] = 0; - gi.configstring (CS_LIGHTS+self->enemy->style, style); - - if(self->spawnflags & LIGHTRAMP_CUSTOM) { - if((self->movedir[0] <= self->movedir[1]) || - ((self->spawnflags & LIGHTRAMP_LOOP) && (self->spawnflags & LIGHTRAMP_ACTIVE)) ) { - self->nextthink = level.time + FRAMETIME; - if(self->movedir[0] > self->movedir[1]) { - self->movedir[0] = 0; - if(self->spawnflags & LIGHTRAMP_TOGGLE) - self->movedir[2] *= -1; - } - } else { - self->movedir[0] = 0; - if (self->spawnflags & LIGHTRAMP_TOGGLE) - self->movedir[2] *= -1; - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - } - } else { - if ( (level.time - self->timestamp) < self->speed) { - self->nextthink = level.time + FRAMETIME; - } else if (self->spawnflags & LIGHTRAMP_TOGGLE) { - char temp; - - temp = self->movedir[0]; - self->movedir[0] = self->movedir[1]; - self->movedir[1] = temp; - self->movedir[2] *= -1; - if( (self->spawnflags & LIGHTRAMP_LOOP) && (self->spawnflags & LIGHTRAMP_ACTIVE) ) { - self->timestamp = level.time; - self->nextthink = level.time + FRAMETIME; - } - } else if ((self->spawnflags & LIGHTRAMP_LOOP) && (self->spawnflags & LIGHTRAMP_ACTIVE)) { - // Not toggled, looping. Start sequence over - self->timestamp = level.time; - self->nextthink = level.time + FRAMETIME; - } else { - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - } - } -} - -void target_lightramp_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->spawnflags & LIGHTRAMP_LOOP) { - if(self->spawnflags & LIGHTRAMP_ACTIVE) { - self->spawnflags &= ~LIGHTRAMP_ACTIVE; // already on, turn it off - target_lightramp_think(self); - return; - } else { - self->spawnflags |= LIGHTRAMP_ACTIVE; - } - } - - if (!self->enemy) - { - edict_t *e; - - // check all the targets - e = NULL; - while (1) - { - e = G_Find (e, FOFS(targetname), self->target); - if (!e) - break; - if (e->class_id != ENTITY_LIGHT) - { - gi.dprintf("%s at %s ", self->classname, vtos(self->s.origin)); - gi.dprintf("target %s (%s at %s) is not a light\n", self->target, e->classname, vtos(e->s.origin)); - } - else - { - self->enemy = e; - } - } - - if (!self->enemy) - { - gi.dprintf("%s target %s not found at %s\n", self->classname, self->target, vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - } - - self->timestamp = level.time; - target_lightramp_think (self); -} - -void SP_target_lightramp (edict_t *self) -{ - // DWH: CUSTOM spawnflag allows custom light switching, speed is ignored - if (self->spawnflags & LIGHTRAMP_CUSTOM) { - if (!self->message || strlen(self->message) < 2) { - gi.dprintf("custom target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - } else { - if (!self->message || strlen(self->message) != 2 || self->message[0] < 'a' || self->message[0] > 'z' || self->message[1] < 'a' || self->message[1] > 'z' || self->message[0] == self->message[1]) - { - gi.dprintf("target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - } - - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - - if (!self->target) - { - gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_TARGET_LIGHTRAMP; - self->svflags |= SVF_NOCLIENT; - self->use = target_lightramp_use; - self->think = target_lightramp_think; - - if(self->spawnflags & LIGHTRAMP_CUSTOM) { - self->movedir[0] = 0; // index into message - self->movedir[1] = strlen(self->message)-1; // position of last character - self->movedir[2] = 1; // direction = start->end - } else { - self->movedir[0] = self->message[0] - 'a'; - self->movedir[1] = self->message[1] - 'a'; - self->movedir[2] = (self->movedir[1] - self->movedir[0]) / (self->speed / FRAMETIME); - } - - self->spawnflags &= ~LIGHTRAMP_ACTIVE; // not currently on -} - -//========================================================== - -/*QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) -When triggered, this initiates a level-wide earthquake. -All players and monsters are affected. -"speed" severity of the quake (default:200) -"count" duration of the quake (default:5) -*/ - -void target_earthquake_think (edict_t *self) -{ - int i; - edict_t *e; - - if (self->last_move_time < level.time) - { - gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->noise_index, 1.0, ATTN_NONE, 0); - self->last_move_time = level.time + 0.5; - } - - for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++) - { - if (!e->inuse) - continue; - if (!e->client) - continue; - if (!e->groundentity) - continue; - // Lazarus: special case for tracktrain riders - - // earthquakes hurt 'em too bad, so don't shake 'em - if ((e->groundentity->flags & FL_TRACKTRAIN) && (e->groundentity->moveinfo.state)) - continue; - e->groundentity = NULL; - e->velocity[0] += crandom()* 150; - e->velocity[1] += crandom()* 150; - e->velocity[2] = self->speed * (100.0 / e->mass); - } - - if (level.time < self->timestamp) - self->nextthink = level.time + FRAMETIME; -} - -void target_earthquake_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->timestamp = level.time + self->count; - self->nextthink = level.time + FRAMETIME; - self->activator = activator; - self->last_move_time = 0; -} - -void SP_target_earthquake (edict_t *self) -{ - self->class_id = ENTITY_TARGET_EARTHQUAKE; - if (!self->targetname) - gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin)); - - if (!self->count) - self->count = 5; - - if (!self->speed) - self->speed = 200; - - self->svflags |= SVF_NOCLIENT; - self->think = target_earthquake_think; - self->use = target_earthquake_use; - - self->noise_index = gi.soundindex ("world/quake.wav"); -} - -// DWH -// -// Tremor stuff follows -// -// -// target_locator can be used to move entities to a random selection -// from a series of path_corners. Move takes place at level start ONLY. -// -void target_locator_init(edict_t *self) -{ - int num_points=0; - int i, N, nummoves; - bool looped; - edict_t *tgt0, *tgtlast, *target, *next; - edict_t *move; - - move = NULL; - move = G_Find(move,FOFS(targetname),self->target); - - if(!move) - { - gi.dprintf("Target of target_locator (%s) not found.\n", - self->target); - G_FreeEdict(self); - return; - } - target = G_Find(NULL,FOFS(targetname),self->pathtarget); - if(!target) - { - gi.dprintf("Pathtarget of target_locator (%s) not found.\n", - self->pathtarget); - G_FreeEdict(self); - return; - } - - srand(time(NULL)); - tgt0 = target; - next = NULL; - target->spawnflags &= 0x7FFE; - while(next != tgt0) - { - if(target->target) - { - next = G_Find(NULL,FOFS(targetname),target->target); - if((!next) || (next==tgt0)) tgtlast = target; - if(!next) - { - gi.dprintf("Target %s of path_corner at %s not found.\n", - target->target,vtos(target->s.origin)); - break; - } - target = next; - target->spawnflags &= 0x7FFE; - num_points++; - } - else - { - next = tgt0; - tgtlast = target; - } - } - if(!num_points) num_points=1; - - nummoves = 1; - while(move) - { - if(nummoves > num_points) break; // more targets than path_corners - - N = rand() % num_points; - i = 0; - next = tgt0; - looped = false; - while(i<=N) - { - target = next; - if(!(target->spawnflags & 1)) i++; - if(target==tgtlast) - { - // We've looped thru all path_corners, but not - // reached the target number yet. This can only - // happen in the case of multiple targets. Use the - // next available path_corner. - looped = true; - } - if(looped && !(target->spawnflags & 1)) i = N+1; - next = G_Find(NULL,FOFS(targetname),target->target); - } - target->spawnflags |= 1; - - // Assumptions here: SOLID_BSP entities are assumed to be brush models, - // all others are point ents - if(move->solid == SOLID_BSP) - { - vec3_t origin; - VectorAdd(move->absmin,move->absmax,origin); - VectorScale(origin,0.5,origin); - VectorSubtract(target->s.origin,origin,move->s.origin); - } - else { - VectorCopy(target->s.origin,move->s.origin); - VectorCopy(target->s.angles,move->s.angles); - } - M_droptofloor(move); - gi.linkentity(move); - move = G_Find(move,FOFS(targetname),self->target); - nummoves++; - } - // All done, go away - G_FreeEdict(self); -} -void SP_target_locator(edict_t *self) -{ - if(!self->target) - { - gi.dprintf("target_locator w/o target at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - if(!self->pathtarget) - { - gi.dprintf("target_locator w/o pathtarget at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_LOCATOR; - self->think = target_locator_init; - self->nextthink = level.time + 2*FRAMETIME; - gi.linkentity(self); -} - -// -// TARGET_ANGER -// -// target Monster(s) to make angry -// killtarget Entity to get angry at -// pathtarget Entity to run to -// Spawnflags: -// HOLD (16) Stand in place -// BRUTAL (32) Gib killtarget - -void use_target_anger(edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *kill_me, *movetarget; - edict_t *t; - vec3_t vec; - float dist, best_dist; - edict_t *best_target; - - if(self->pathtarget) - movetarget = G_PickTarget(self->pathtarget); - else - movetarget = NULL; - - if (self->target) - { - t = NULL; - while ((t = G_Find (t, FOFS(targetname), self->target))) - { - if (t == self) - { - gi.dprintf ("WARNING: entity used itself.\n"); - } - else - { - if (t->use) - { - if (t->health < 0) - return; - if(self->movedir[2] > 0) - { - t->velocity[0] = self->movedir[0] * self->speed; - t->velocity[1] = self->movedir[1] * self->speed; - if (t->groundentity) - { - t->groundentity = NULL; - t->velocity[2] = self->movedir[2]; - if(t->monsterinfo.aiflags & AI_ACTOR) - gi.sound (self, CHAN_VOICE, t->actor_sound_index[0], 1, ATTN_NORM, 0); - } - } - if(self->killtarget) - { - kill_me = G_Find(NULL, FOFS(targetname), self->killtarget); - if(kill_me) - { - best_dist = 9000.; - best_target = NULL; - if(kill_me->health > 0) - { - VectorSubtract(kill_me->s.origin,t->s.origin,vec); - best_dist = VectorLength(vec); - best_target = kill_me; - } - while(kill_me) - { - kill_me = G_Find(kill_me, FOFS(targetname), self->killtarget); - if(!kill_me) - break; - if(!kill_me->inuse) - continue; - if(kill_me->health <= 0) - continue; - VectorSubtract(kill_me->s.origin,t->s.origin,vec); - dist = VectorLength(vec); - if(dist < best_dist) - { - best_dist = dist; - best_target = kill_me; - } - } - kill_me = best_target; - } - } - if(kill_me) - { - // Make whatever a "good guy" so the monster will try to kill it! - kill_me->monsterinfo.aiflags |= AI_GOOD_GUY; - t->enemy = t->goalentity = kill_me; - t->monsterinfo.aiflags |= AI_TARGET_ANGER; - if(movetarget) - t->movetarget = movetarget; - FoundTarget (t); - } - else - { - t->monsterinfo.pausetime = 0; - t->goalentity = t->movetarget = movetarget; - } - - if ((self->spawnflags & 16) && !(t->flags & (FL_SWIM|FL_FLY))) - { - t->monsterinfo.pausetime = level.time + 100000000; - t->monsterinfo.aiflags |= AI_STAND_GROUND; - t->monsterinfo.stand (t); - } - if (self->spawnflags & 32) - t->monsterinfo.aiflags |= AI_BRUTAL; - } - } - if (!self->inuse) - { - gi.dprintf("entity was removed while using targets\n"); - return; - } - } - } - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - -} - -void SP_target_anger(edict_t *self) -{ - if(deathmatch->value) { - G_FreeEdict(self); - return; - } - if(!self->target) { - gi.dprintf("target_anger with no target set at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - if(!self->killtarget && !self->pathtarget) { - gi.dprintf("target_anger with no killtarget or\npathtarget set at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_ANGER; - // pathtarget is incompatible with HOLD SF - if(self->pathtarget && (self->spawnflags & 16)) - { - gi.dprintf("target anger at %s,\npathtarget is incompatible with HOLD\n", - vtos(self->s.origin)); - self->spawnflags &= ~16; - } - - G_SetMovedir (self->s.angles, self->movedir); - self->movedir[2] = st.height; - self->use = use_target_anger; -} - -// target_monsterbattle serves the same purpose as target_anger, but -// ends up turning a dmgteam group of monsters against another dmgteam - -void use_target_monsterbattle(edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *grouch, *grouchmate; - edict_t *target, *targetmate; - - grouch = G_Find(NULL,FOFS(targetname),self->target); - if(!grouch) return; - if(!grouch->inuse) return; - target = G_Find(NULL,FOFS(targetname),self->killtarget); - if(!target) return; - if(!target->inuse) return; - if(grouch->dmgteam) { - grouchmate = G_Find(NULL,FOFS(dmgteam),grouch->dmgteam); - while(grouchmate) { - grouchmate->monsterinfo.aiflags |= AI_FREEFORALL; - grouchmate = G_Find(grouchmate,FOFS(dmgteam),grouch->dmgteam); - } - } - if(target->dmgteam) { - targetmate = G_Find(NULL,FOFS(dmgteam),target->dmgteam); - while(targetmate) { - targetmate->monsterinfo.aiflags |= AI_FREEFORALL; - targetmate = G_Find(targetmate,FOFS(dmgteam),target->dmgteam); - } - } - grouch->enemy = target; - grouch->monsterinfo.aiflags |= AI_TARGET_ANGER; - FoundTarget(grouch); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} -void SP_target_monsterbattle(edict_t *self) -{ - if(deathmatch->value) { - G_FreeEdict(self); - return; - } - if(!self->target) { - gi.dprintf("target_monsterbattle with no target set at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - if(!self->killtarget) { - gi.dprintf("target_monsterbattle with no killtarget set at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_MONSTERBATTLE; - self->use = use_target_monsterbattle; -} - -/*==================================================================================== - TARGET_ROCKS -======================================================================================*/ -void directed_debris_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - G_FreeEdict (self); -} -void FadeDieThink(edict_t *); -void ThrowRock (edict_t *self, char *modelname, float speed, vec3_t origin, vec3_t size, int mass) -{ - edict_t *chunk; - vec_t var = speed/5; - - chunk = G_Spawn(); - VectorCopy (origin, chunk->s.origin); - gi.setmodel (chunk, modelname); - VectorCopy(size,chunk->maxs); - VectorScale(chunk->maxs,0.5,chunk->maxs); - VectorNegate(chunk->maxs,chunk->mins); - chunk->velocity[0] = speed * self->movedir[0] + var * crandom(); - chunk->velocity[1] = speed * self->movedir[1] + var * crandom(); - chunk->velocity[2] = speed * self->movedir[2] + var * crandom(); - chunk->movetype = MOVETYPE_DEBRIS; - chunk->attenuation = 0.5; - chunk->solid = SOLID_NOT; - chunk->avelocity[0] = random()*600; - chunk->avelocity[1] = random()*600; - chunk->avelocity[2] = random()*600; - chunk->think = FadeDieThink; - chunk->nextthink = level.time + 15 + random()*5; - chunk->s.frame = 0; - chunk->flags = 0; - chunk->classname = "debris"; - chunk->takedamage = DAMAGE_YES; - chunk->die = directed_debris_die; - chunk->mass = mass; - gi.linkentity (chunk); -} - -void use_target_rocks (edict_t *self, edict_t *other, edict_t *activator) -{ - vec3_t chunkorigin; - vec3_t size, source; - vec_t mass; - int count; - char modelname[64]; - - VectorSet(source,8,8,8); - mass = self->mass; - // big chunks - if (mass >= 100) - { - sprintf(modelname,"models/objects/rock%d/tris.md2",self->style*2+1); - count = mass / 100; - if (count > 16) - count = 16; - VectorSet(size,8,8,8); - while(count--) - { - chunkorigin[0] = self->s.origin[0] + crandom() * source[0]; - chunkorigin[1] = self->s.origin[1] + crandom() * source[1]; - chunkorigin[2] = self->s.origin[2] + crandom() * source[2]; - ThrowRock (self, modelname, self->speed, chunkorigin, size, 100); - } - } - // small chunks - count = mass / 25; - sprintf(modelname,"models/objects/rock%d/tris.md2",self->style*2+2); - if (count > 16) - count = 16; - VectorSet(size,4,4,4); - while(count--) - { - chunkorigin[0] = self->s.origin[0] + crandom() * source[0]; - chunkorigin[1] = self->s.origin[1] + crandom() * source[1]; - chunkorigin[2] = self->s.origin[2] + crandom() * source[2]; - ThrowRock (self, modelname, self->speed, chunkorigin, size, 25); - } - if (self->dmg) - T_RadiusDamage (self, activator, self->dmg, NULL, self->dmg+40, MOD_SPLASH, -0.5); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - -} - -void SP_target_rocks (edict_t *self) -{ - self->class_id = ENTITY_TARGET_ROCKS; - gi.modelindex ("models/objects/rock1/tris.md2"); - gi.modelindex ("models/objects/rock2/tris.md2"); - if(!self->speed) - self->speed = 400; - if (!self->mass) - self->mass = 500; - self->use = use_target_rocks; - G_SetMovedir (self->s.angles, self->movedir); - self->svflags = SVF_NOCLIENT; -} - -/*==================================================================================== - TARGET_ROTATION -======================================================================================*/ - -void use_target_rotation (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *target; - int i, pick; - char *p1, *p2; - char targetname[256]; - - if(self->spawnflags & 2) { - // random pick - pick = self->sounds * random(); - if(pick == self->sounds) pick--; - } else { - pick = self->mass; - if(pick == self->sounds) { - if(self->spawnflags & 1) // no loop - return; - else - pick = 0; - } - self->mass = pick+1; - } - p1 = self->target; - p2 = targetname; - memset(targetname,0,sizeof(targetname)); - // skip over pick commas - for(i=0; iinuse && target->use) - target->use(target,other,activator); - target = G_Find(target,FOFS(targetname),targetname); - } - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_target_rotation (edict_t *self) -{ - char *p; - - if(!self->target) { - gi.dprintf("target_rotation without a target at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_ROTATION; - if( (self->spawnflags & 3) == 3) { - gi.dprintf("target_rotation at %s: NO_LOOP and RANDOM are mutually exclusive.\n"); - self->spawnflags = 2; - } - self->use = use_target_rotation; - self->svflags = SVF_NOCLIENT; - self->mass = 0; // index of currently selected target - self->sounds = 0; // number of comma-delimited targets in target string - p = self->target; - while( (p = strstr(p,",")) != NULL) { - self->sounds++; - p++; - } - self->sounds++; -} - -/*==================================================================================== - TARGET_EFFECT -======================================================================================*/ - -/* Unknowns or not supported -TE_FLAME, 32 Rogue flamethrower, never implemented -TE_FORCEWALL, 37 ?? -*/ - -//========================================================================= -/* Spawns an effect at the entity origin - TE_FLASHLIGHT 36 -*/ -void target_effect_at (edict_t *self, edict_t *activator) -{ - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (self->style); - WRITE_COORD (self->s.origin); - WRITE_SHORT (self - g_edicts); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); -} -/* Poor man's target_steam - TE_STEAM 40 -*/ -void target_effect_steam (edict_t *self, edict_t *activator) -{ - static int nextid; - int wait; - - if(self->wait) - wait = self->wait*1000; - else - wait = 0; - - if (nextid > 20000) - nextid = nextid %20000; - nextid++; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (self->style); - WRITE_SHORT (nextid); - WRITE_BYTE (self->count); - WRITE_COORD (self->s.origin); - WRITE_DIR (self->movedir); - WRITE_BYTE (self->sounds&0xff); - WRITE_SHORT ( (int)(self->speed) ); - WRITE_LONG ( (int)(wait) ); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - - if(level.num_reflectors) - ReflectSteam (self->s.origin,self->movedir,self->count,self->sounds,(int)(self->speed),wait,nextid); -} - -//========================================================================= -/* -Spawns (style) Splash with (count) particles of (sounds) color at (origin) -moving in (movedir) direction. - - TE_SPLASH 10 Randomly shaded shower of particles - TE_LASER_SPARKS 15 Splash particles obey gravity - TE_WELDING_SPARKS 25 Splash particles with flash of light at {origin} -*/ -//========================================================================= -void target_effect_splash (edict_t *self, edict_t *activator) -{ - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(self->style); - WRITE_BYTE(self->count); - WRITE_COORD(self->s.origin); - WRITE_DIR(self->movedir); - WRITE_BYTE(self->sounds); - MESSAGE_SEND(MSG_PVS, self->s.origin, NULL); -} - -//====================================================== -/* -Spawns a trail of (type) from (start) to (end) and Broadcasts to all -in Potentially Visible Set from vector (origin) - - TE_RAILTRAIL 3 Spawns a blue spiral trail filled with white smoke - TE_BUBBLETRAIL 11 Spawns a trail of bubbles - TE_PARASITE_ATTACK 16 - TE_MEDIC_CABLE_ATTACK 19 - TE_BFG_LASER 23 Spawns a green laser - TE_GRAPPLE_CABLE 24 - TE_RAILTRAIL2 31 NOT IMPLEMENTED IN ENGINE - TE_DEBUGTRAIL 34 - TE_HEATBEAM, 38 Requires Rogue model - TE_MONSTER_HEATBEAM, 39 Requires Rogue model - TE_BUBBLETRAIL2 41 -*/ -//====================================================== -void target_effect_trail (edict_t *self, edict_t *activator) -{ - edict_t *target; - - if(!self->target) return; - target = G_Find(NULL,FOFS(targetname),self->target); - if(!target) return; - - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(self->style); - if((self->style == TE_PARASITE_ATTACK) || (self->style==TE_MEDIC_CABLE_ATTACK) || (self->style == TE_HEATBEAM) || (self->style==TE_MONSTER_HEATBEAM) || (self->style == TE_GRAPPLE_CABLE)) - { - WRITE_SHORT(self-g_edicts); - } - WRITE_COORD(self->s.origin); - WRITE_COORD(target->s.origin); - if(self->style == TE_GRAPPLE_CABLE) - { - WRITE_COORD(vec3_origin); - } - MESSAGE_SEND(MSG_PVS, self->s.origin, NULL); - - if(level.num_reflectors) - { - if((self->style == TE_RAILTRAIL) || (self->style == TE_BUBBLETRAIL) || (self->style == TE_BFG_LASER) || (self->style == TE_DEBUGTRAIL) || (self->style == TE_BUBBLETRAIL2)) - ReflectTrail(self->style,self->s.origin,target->s.origin); - } -} -//=========================================================================== -/* TE_LIGHTNING 33 Lightning bolt - - Similar but slightly different syntax to trail stuff */ -void target_effect_lightning(edict_t *self, edict_t *activator) -{ - edict_t *target; - - if(!self->target) return; - target = G_Find(NULL,FOFS(targetname),self->target); - if(!target) return; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (self->style); - WRITE_SHORT (target - g_edicts); // destination entity - WRITE_SHORT (self - g_edicts); // source entity - WRITE_COORD (target->s.origin); - WRITE_COORD (self->s.origin); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); -} -//=========================================================================== -/* -Spawns sparks of (type) from (start) in direction of (movdir) and -Broadcasts to all in Potentially Visible Set from vector (origin) - - TE_GUNSHOT 0 Spawns a grey splash of particles, with a bullet puff - TE_BLOOD 1 Spawns a spurt of red blood - TE_BLASTER 2 Spawns a blaster sparks - TE_SHOTGUN 4 Spawns a small grey splash of spark particles, with a bullet puff - TE_SPARKS 9 Spawns a red/gold splash of spark particles - TE_SCREEN_SPARKS 12 Spawns a large green/white splash of sparks - TE_SHIELD_SPARKS 13 Spawns a large blue/violet splash of sparks - TE_BULLET_SPARKS 14 Same as TE_SPARKS, with a bullet puff and richochet sound - TE_GREENBLOOD 26 Spurt of green (actually kinda yellow) blood - TE_BLUEHYPERBLASTER 27 NOT IMPLEMENTED - TE_BLASTER2 30 Green/white sparks with a yellow/white flash - TE_MOREBLOOD 42 - TE_HEATBEAM_SPARKS 43 - TE_HEATBEAM_STEAM 44 - TE_CHAINFIST_SMOKE 45 - TE_ELECTRIC_SPARKS 46 - TE_FLECHETTE 55 -*/ -//====================================================== -void target_effect_sparks (edict_t *self, edict_t *activator) -{ - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(self->style); - WRITE_COORD(self->s.origin); - if(self->style != TE_CHAINFIST_SMOKE) - WRITE_DIR(self->movedir); - MESSAGE_SEND(MSG_PVS, self->s.origin, NULL); - - if(level.num_reflectors) - ReflectSparks(self->style,self->s.origin,self->movedir); -} - -//====================================================== -/* -Spawns a (type) effect at (start} and Broadcasts to all in the -Potentially Hearable set from vector (origin) - - TE_EXPLOSION1 5 airburst - TE_EXPLOSION2 6 ground burst - TE_ROCKET_EXPLOSION 7 rocket explosion - TE_GRENADE_EXPLOSION 8 grenade explosion - TE_ROCKET_EXPLOSION_WATER 17 underwater rocket explosion - TE_GRENADE_EXPLOSION_WATER 18 underwater grenade explosion - TE_BFG_EXPLOSION 20 BFG explosion sprite - TE_BFG_BIGEXPLOSION 21 BFG particle explosion - TE_BOSSTPORT 22 - TE_PLASMA_EXPLOSION 28 - TE_PLAIN_EXPLOSION 35 - TE_TRACKER_EXPLOSION 47 - TE_TELEPORT_EFFECT 48 - TE_DBALL_GOAL 49 Identical to TE_TELEPORT_EFFECT? - TE_NUKEBLAST 51 - TE_WIDOWSPLASH 52 - TE_EXPLOSION1_BIG 53 Works, but requires Rogue models/objects/r_explode2 - TE_EXPLOSION1_NP 54 -*/ -//============================================================================== -void target_effect_explosion (edict_t *self, edict_t *activator) -{ - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(self->style); - WRITE_COORD(self->s.origin); - MESSAGE_SEND(MSG_PHS, self->s.origin, NULL); - - if (level.num_reflectors) - ReflectExplosion (self->style, self->s.origin); - -} -//=============================================================================== -/* TE_TUNNEL_SPARKS 29 - Similar to other splash effects, but Xatrix does some funky things with - the origin so we'll do the same */ - -void target_effect_tunnel_sparks (edict_t *self, edict_t *activator) -{ - vec3_t origin; - int i; - - VectorCopy(self->s.origin,origin); - for (i = 0; i < self->count; i++) - { - origin[2] += (self->speed * 0.01) * (i + random()); - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (self->style); - WRITE_BYTE (1); - WRITE_COORD (origin); - WRITE_DIR (vec3_origin); - WRITE_BYTE (self->sounds + (rand()&7)); // color - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - } -} -//=============================================================================== -/* TE_WIDOWBEAMOUT 50 -*/ -void target_effect_widowbeam(edict_t *self, edict_t *activator) -{ - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_WIDOWBEAMOUT); - WRITE_SHORT (20001); - WRITE_COORD (self->s.origin); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); -} -//=============================================================================== - -void target_effect_use(edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->spawnflags & 1) { - // currently looped on - turn it off - self->spawnflags &= ~1; - self->spawnflags |= 2; - self->nextthink = 0; - return; - } - if(self->spawnflags & 2) { - // currently looped off - turn it on - self->spawnflags &= ~2; - self->spawnflags |= 1; - self->nextthink = level.time + self->wait; - } - if(self->spawnflags & 4) { - // "if_moving" set. If movewith target isn't moving, - // don't play - edict_t *mover; - if(!self->movewith) return; - mover = G_Find(NULL,FOFS(targetname),self->movewith); - if(!mover) return; - if(!VectorLength(mover->velocity)) return; - } - self->play(self,activator); -} -void target_effect_think(edict_t *self) -{ - self->play(self,NULL); - self->nextthink = level.time + self->wait; -} -//=============================================================================== -void SP_target_effect (edict_t *self) -{ - self->class_id = ENTITY_TARGET_EFFECT; - if(self->movewith) - self->movetype = MOVETYPE_PUSH; - else - self->movetype = MOVETYPE_NONE; - - switch (self->style ) { - case TE_FLASHLIGHT: - self->play = target_effect_at; - break; - case TE_STEAM: - self->play = target_effect_steam; - G_SetMovedir (self->s.angles, self->movedir); - if(!self->count) - self->count = 32; - if(!self->sounds) - self->sounds = 8; - if(!self->speed) - self->speed = 75; - break; - case TE_SPLASH: - case TE_LASER_SPARKS: - case TE_WELDING_SPARKS: - self->play = target_effect_splash; - G_SetMovedir (self->s.angles, self->movedir); - if(!self->count) - self->count = 32; - break; - case TE_RAILTRAIL: - case TE_BUBBLETRAIL: - case TE_PARASITE_ATTACK: - case TE_MEDIC_CABLE_ATTACK: - case TE_BFG_LASER: - case TE_GRAPPLE_CABLE: - case TE_DEBUGTRAIL: - case TE_HEATBEAM: - case TE_MONSTER_HEATBEAM: - case TE_BUBBLETRAIL2: - if(!self->target) { - gi.dprintf("%s at %s with style=%d needs a target\n",self->classname,vtos(self->s.origin),self->style); - G_FreeEdict(self); - } else - self->play = target_effect_trail; - break; - case TE_LIGHTNING: - if(!self->target) { - gi.dprintf("%s at %s with style=%d needs a target\n",self->classname,vtos(self->s.origin),self->style); - G_FreeEdict(self); - } else - self->play = target_effect_lightning; - break; - case TE_GUNSHOT: - case TE_BLOOD: - case TE_BLASTER: - case TE_SHOTGUN: - case TE_SPARKS: - case TE_SCREEN_SPARKS: - case TE_SHIELD_SPARKS: - case TE_BULLET_SPARKS: - case TE_GREENBLOOD: - case TE_BLASTER2: - case TE_MOREBLOOD: - case TE_HEATBEAM_SPARKS: - case TE_HEATBEAM_STEAM: - case TE_CHAINFIST_SMOKE: - case TE_ELECTRIC_SPARKS: - case TE_FLECHETTE: - self->play = target_effect_sparks; - G_SetMovedir (self->s.angles, self->movedir); - break; - case TE_EXPLOSION1: - case TE_EXPLOSION2: - case TE_ROCKET_EXPLOSION: - case TE_GRENADE_EXPLOSION: - case TE_ROCKET_EXPLOSION_WATER: - case TE_GRENADE_EXPLOSION_WATER: - case TE_BFG_EXPLOSION: - case TE_BFG_BIGEXPLOSION: - case TE_BOSSTPORT: - case TE_PLASMA_EXPLOSION: - case TE_PLAIN_EXPLOSION: - case TE_TRACKER_EXPLOSION: - case TE_TELEPORT_EFFECT: - case TE_DBALL_GOAL: - case TE_NUKEBLAST: - case TE_WIDOWSPLASH: - case TE_EXPLOSION1_BIG: - case TE_EXPLOSION1_NP: - self->play = target_effect_explosion; - break; - case TE_TUNNEL_SPARKS: - if(!self->count) - self->count = 32; - if(!self->sounds) - self->sounds = 116; // Light blue, same color used by Xatrix - self->play = target_effect_tunnel_sparks; - break; - case TE_WIDOWBEAMOUT: - self->play = target_effect_widowbeam; - G_SetMovedir (self->s.angles, self->movedir); - break; - default: - gi.dprintf("%s at %s: bad style %d\n",self->classname,vtos(self->s.origin),self->style); - } - self->use = target_effect_use; - self->think = target_effect_think; - if(self->spawnflags & 1) - self->nextthink = level.time + 1; - -} - -/*===================================================================================== - TARGET_ATTRACTOR - pulls target entity towards its origin - target - Targetname of entity to attract. Ignored if PLAYER spawnflag is set - pathtarget - Entity or entities to "use" when distance criteria is met. - speed - Minimum speed to pull target with. Must use a value > sv_gravity/10 - to overcome gravity when pulling up. - distance - When target is within "distance" units of target_attractor, attraction - is shut off. Use a value < 0 to hold target in place. 0 will be reset - to 1. - sounds - effect to use. ONLY VALID for PLAYER or MONSTER, not target. If sounds - is non-zero, SINGLE_TARGET and SIGHT are automatically set - 0 = none - 1 = medic cable - 2 = green laser - - Spawnflags: 1 - START_ON - 2 - PLAYER (attract player, ignore "target" - 4 - NO_GRAVITY - turns off gravity for target. W/O this flag you'll - get an annoying jitter when pulling players up. - 8 - MONSTER - attract ALL monsters, ignore "target" - 16 - SIGHT - must have LOS to target to attract it - 32 - SINGLE_TARGET - will select best target - 64 - PATHTARGET_FIRE - used internally only -=======================================================================================*/ -#define ATTRACTOR_ON 1 -#define ATTRACTOR_PLAYER 2 -#define ATTRACTOR_NO_GRAVITY 4 -#define ATTRACTOR_MONSTER 8 -#define ATTRACTOR_SIGHT 16 -#define ATTRACTOR_SINGLE 32 -#define ATTRACTOR_PATHTARGET 64 - -void target_attractor_think_single(edict_t *self) -{ - edict_t *ent, *target, *previous_target; - trace_t tr; - vec3_t dir, targ_org; - vec_t dist, speed; - vec_t best_dist; - vec3_t forward, right; - int i; - int num_targets = 0; - - if(!self->spawnflags & ATTRACTOR_ON) return; - - previous_target = self->target_ent; - target = NULL; - best_dist = 8192; - - if(self->spawnflags & ATTRACTOR_PLAYER) { - for(i=1, ent=&g_edicts[i]; i<=game.maxclients; i++, ent++) { - if(!ent->inuse) continue; - if(ent->health <= 0) continue; - num_targets++; - VectorSubtract(self->s.origin,ent->s.origin,dir); - dist = VectorLength(dir); - if(dist > self->moveinfo.distance) continue; - if(self->spawnflags & ATTRACTOR_SIGHT) { - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,ent->s.origin,NULL,MASK_OPAQUE | MASK_SHOT); - if(tr.ent != ent) continue; - } - if(dist < best_dist) { - best_dist = dist; - target = ent; - } - } - } - if(self->spawnflags & ATTRACTOR_MONSTER) { - for(i=1, ent=&g_edicts[i]; i<=globals.num_edicts; i++, ent++) { - if(!ent->inuse) continue; - if(ent->health <= 0) continue; - if(!(ent->svflags & SVF_MONSTER)) continue; - num_targets++; - VectorSubtract(self->s.origin,ent->s.origin,dir); - dist = VectorLength(dir); - if(dist > self->moveinfo.distance) continue; - if(self->spawnflags & ATTRACTOR_SIGHT) { - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,ent->s.origin,NULL,MASK_OPAQUE | MASK_SHOT); - if(tr.ent != ent) continue; - } - if(dist < best_dist) { - best_dist = dist; - target = ent; - } - } - } - if(!(self->spawnflags & (ATTRACTOR_PLAYER | ATTRACTOR_MONSTER))) { - ent = G_Find(NULL,FOFS(targetname),self->target); - while(ent) { - if(!ent->inuse) continue; - num_targets++; - VectorAdd(ent->s.origin,ent->origin_offset,targ_org); - VectorSubtract(self->s.origin,targ_org,dir); - dist = VectorLength(dir); - if(dist > self->moveinfo.distance) continue; - if(self->spawnflags & ATTRACTOR_SIGHT) { - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,targ_org,NULL,MASK_OPAQUE | MASK_SHOT); - if(tr.ent != ent) continue; - } - if(dist < best_dist) { - best_dist = dist; - target = ent; - } - ent = G_Find(ent,FOFS(targetname),self->target); - } - } - self->target_ent = target; - if(!target) { - if(num_targets > 0) self->nextthink = level.time + FRAMETIME; - return; - } - - if(target != previous_target) - self->moveinfo.speed = 0; - - if(self->moveinfo.speed != self->speed) { - if(self->speed > 0) - self->moveinfo.speed = min(self->speed, self->moveinfo.speed + self->accel); - else - self->moveinfo.speed = max(self->speed, self->moveinfo.speed + self->accel); - } - - VectorAdd(target->s.origin,target->origin_offset,targ_org); - VectorSubtract(self->s.origin,targ_org,dir); - dist = VectorLength(dir); - if(readout->value) gi.dprintf("distance=%g, pull speed=%g\n",dist,self->moveinfo.speed); - - if((self->pathtarget) && (self->spawnflags & ATTRACTOR_PATHTARGET)) - { - if(dist == 0) { - // fire pathtarget when close - ent = G_Find(NULL,FOFS(targetname),self->pathtarget); - while(ent) { - if(ent->use) - ent->use(ent,self,self); - ent = G_Find(ent,FOFS(targetname),self->pathtarget); - } - self->spawnflags &= ~ATTRACTOR_PATHTARGET; - } - } - VectorNormalize(dir); - speed = VectorNormalize(target->velocity); - speed = max(fabs(self->moveinfo.speed),speed); - if(self->moveinfo.speed < 0) speed = -speed; - if(speed > dist*10) { - speed = dist*10; - VectorScale(dir,speed,target->velocity); - // if NO_GRAVITY is NOT set, and target would normally be affected by gravity, - // counteract gravity during the last move - if( !(self->spawnflags & ATTRACTOR_NO_GRAVITY) ) { - if( (target->movetype == MOVETYPE_BOUNCE ) || - (target->movetype == MOVETYPE_PUSHABLE) || - (target->movetype == MOVETYPE_STEP ) || - (target->movetype == MOVETYPE_TOSS ) || - (target->movetype == MOVETYPE_DEBRIS ) ) { - target->velocity[2] += target->gravity * sv_gravity->value * FRAMETIME; - } - } - } else - VectorScale(dir,speed,target->velocity); - // Add attractor velocity in case it's a movewith deal - VectorAdd(target->velocity,self->velocity,target->velocity); - if(target->client) { - float scale; - if(target->groundentity || target->waterlevel > 1) { - if(target->groundentity) - scale = 0.75; - else - scale = 0.375; - // Players - add movement stuff so he MAY be able to escape - AngleVectors (target->client->v_angle, forward, right, NULL); - for (i=0 ; i<3 ; i++) - target->velocity[i] += scale * forward[i] * target->client->ucmd.forwardmove + - scale * right[i] * target->client->ucmd.sidemove; - target->velocity[2] += scale * target->client->ucmd.upmove; - } - } - // If target is on the ground and attractor is overhead, give 'em a little nudge. - // This is only really necessary for players - if(target->groundentity && (self->s.origin[2] > target->absmax[2])) { - target->s.origin[2] += 1; - target->groundentity = NULL; - } - - if(self->sounds) { - vec3_t new_origin; - - if(target->client) - { - VectorCopy(target->s.origin,new_origin); - } - else - { - VectorMA(targ_org,FRAMETIME,target->velocity,new_origin); - } - - switch(self->sounds) - { - case 1: - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_MEDIC_CABLE_ATTACK); - WRITE_SHORT(self-g_edicts); - WRITE_COORD(self->s.origin); - WRITE_COORD(new_origin); - MESSAGE_SEND(MSG_PVS, self->s.origin, NULL); - break; - case 2: - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_BFG_LASER); - WRITE_COORD(self->s.origin); - WRITE_COORD(new_origin); - MESSAGE_SEND(MSG_PVS, self->s.origin, NULL); - } - } - - - if(self->spawnflags & ATTRACTOR_NO_GRAVITY) - target->gravity_debounce_time = level.time + 2*FRAMETIME; - gi.linkentity(target); - - if(!num_targets) { - // shut 'er down - self->spawnflags &= ~ATTRACTOR_ON; - } else { - self->nextthink = level.time + FRAMETIME; - } -} - -void target_attractor_think(edict_t *self) -{ - edict_t *ent, *target; - trace_t tr; - vec3_t dir, targ_org; - vec_t dist, speed; - vec3_t forward, right; - int i; - int ent_start; - int num_targets = 0; - - if(!self->spawnflags & ATTRACTOR_ON) return; - - if(self->moveinfo.speed != self->speed) { - if(self->speed > 0) - self->moveinfo.speed = min(self->speed, self->moveinfo.speed + self->accel); - else - self->moveinfo.speed = max(self->speed, self->moveinfo.speed + self->accel); - } - - target = NULL; - ent_start = 1; - while(true) - { - if(self->spawnflags & (ATTRACTOR_PLAYER || ATTRACTOR_MONSTER)) - { - target = NULL; - for(i=ent_start, ent=&g_edicts[ent_start];ispawnflags & ATTRACTOR_PLAYER) && ent->client && ent->inuse) - { - target = ent; - ent_start = i+1; - continue; - } - if((self->spawnflags & ATTRACTOR_MONSTER) && (ent->svflags & SVF_MONSTER) && (ent->inuse)) - { - target = ent; - ent_start = i+1; - } - } - } else - target = G_Find(target,FOFS(targetname),self->target); - if(!target) break; - if(!target->inuse) continue; - if( ((target->client) || (target->svflags & SVF_MONSTER)) && (target->health <= 0)) continue; - num_targets++; - - VectorAdd(target->s.origin,target->origin_offset,targ_org); - VectorSubtract(self->s.origin,targ_org,dir); - dist = VectorLength(dir); - - if(self->spawnflags & ATTRACTOR_SIGHT) { - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target->s.origin,NULL,MASK_OPAQUE | MASK_SHOT); - if(tr.ent != target) continue; - } - - if(readout->value) gi.dprintf("distance=%g, pull speed=%g\n",dist,self->moveinfo.speed); - if(dist > self->moveinfo.distance) - continue; - - if((self->pathtarget) && (self->spawnflags & ATTRACTOR_PATHTARGET)) - { - if(dist == 0) { - // fire pathtarget when close - ent = G_Find(NULL,FOFS(targetname),self->pathtarget); - while(ent) { - if(ent->use) - ent->use(ent,self,self); - ent = G_Find(ent,FOFS(targetname),self->pathtarget); - } - self->spawnflags &= ~ATTRACTOR_PATHTARGET; - } - } - VectorNormalize(dir); - speed = VectorNormalize(target->velocity); - speed = max(fabs(self->moveinfo.speed),speed); - if(self->moveinfo.speed < 0) speed = -speed; - if(speed > dist*10) { - speed = dist*10; - VectorScale(dir,speed,target->velocity); - // if NO_GRAVITY is NOT set, and target would normally be affected by gravity, - // counteract gravity during the last move - if( !(self->spawnflags & ATTRACTOR_NO_GRAVITY) ) { - if( (target->movetype == MOVETYPE_BOUNCE ) || - (target->movetype == MOVETYPE_PUSHABLE) || - (target->movetype == MOVETYPE_STEP ) || - (target->movetype == MOVETYPE_TOSS ) || - (target->movetype == MOVETYPE_DEBRIS ) ) { - target->velocity[2] += target->gravity * sv_gravity->value * FRAMETIME; - } - } - } else - VectorScale(dir,speed,target->velocity); - // Add attractor velocity in case it's a movewith deal - VectorAdd(target->velocity,self->velocity,target->velocity); - if(target->client) { - float scale; - if(target->groundentity || target->waterlevel > 1) { - if(target->groundentity) - scale = 0.75; - else - scale = 0.375; - // Players - add movement stuff so he MAY be able to escape - AngleVectors (target->client->v_angle, forward, right, NULL); - for (i=0 ; i<3 ; i++) - target->velocity[i] += scale * forward[i] * target->client->ucmd.forwardmove + - scale * right[i] * target->client->ucmd.sidemove; - target->velocity[2] += scale * target->client->ucmd.upmove; - } - } - // If target is on the ground and attractor is overhead, give 'em a little nudge. - // This is only really necessary for players - if(target->groundentity && (self->s.origin[2] > target->absmax[2])) { - target->s.origin[2] += 1; - target->groundentity = NULL; - } - if(self->spawnflags & ATTRACTOR_NO_GRAVITY) - target->gravity_debounce_time = level.time + 2*FRAMETIME; - gi.linkentity(target); - } - if(!num_targets) { - // shut 'er down - self->spawnflags &= ~ATTRACTOR_ON; - } else { - self->nextthink = level.time + FRAMETIME; - } -} - -void use_target_attractor(edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->spawnflags & ATTRACTOR_ON) { - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - else - { - self->spawnflags &= ~ATTRACTOR_ON; - self->s.sound = 0; - self->target_ent = NULL; - self->nextthink = 0; - } - } else { - self->spawnflags |= (ATTRACTOR_ON + ATTRACTOR_PATHTARGET); - self->s.sound = self->noise_index; - if(self->spawnflags & ATTRACTOR_SINGLE) - self->think = target_attractor_think_single; - else - self->think = target_attractor_think; - self->moveinfo.speed = 0; - gi.linkentity(self); - self->think(self); - } -} - -void SP_target_attractor(edict_t *self) -{ - if(!self->target && !(self->spawnflags & ATTRACTOR_PLAYER) && - !(self->spawnflags & ATTRACTOR_MONSTER)) { - gi.dprintf("target_attractor without a target at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_ATTRACTOR; - if(self->sounds) { -// if((self->spawnflags & ATTRACTOR_PLAYER) || (self->spawnflags & ATTRACTOR_MONSTER)) { - self->spawnflags |= (ATTRACTOR_SIGHT | ATTRACTOR_SINGLE); -// } else { -// gi.dprintf("Target_attractor sounds key is only valid\n" -// "for PLAYER or MONSTER. Setting sounds=0\n"); -// } - } - if(st.distance) - self->moveinfo.distance = st.distance; - else - self->moveinfo.distance = 8192; - - self->solid = SOLID_NOT; - if(self->movewith) - self->movetype = MOVETYPE_PUSH; - else - self->movetype = MOVETYPE_NONE; - self->use = use_target_attractor; - - if(st.noise) - self->noise_index = gi.soundindex(st.noise); - else - self->noise_index = 0; - - if(!self->speed) - self->speed = 100; - - if(!self->accel) - self->accel = self->speed; - else { - self->accel *= 0.1; - if(self->accel > self->speed) - self->accel = self->speed; - } - - if(self->spawnflags & ATTRACTOR_ON) { - if(self->spawnflags & ATTRACTOR_SINGLE) - self->think = target_attractor_think_single; - else - self->think = target_attractor_think; - if(self->sounds) - self->nextthink = level.time + 2*FRAMETIME; - else - self->think(self); - } -} - -/*=================================================================== - TARGET_CD - Play the CD track specified by the "sounds" value, looping the - track "dmg" times. This does NOT override player's option to - disable CD music, and of course does nothing if a music CD is not - in place. If "dmg" is not specified, track is looped cd_loopcount - (default=4) times. -===================================================================*/ -void use_target_CD (edict_t *self, edict_t *other, edict_t *activator) -{ - gi.configstring (CS_CDTRACK, va("%d",self->sounds)); - if((self->dmg > 0) && (!deathmatch->value) && (!coop->value)) - stuffcmd(&g_edicts[1],va("cd_loopcount %d\n",self->dmg)); - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_target_CD (edict_t *self) -{ - self->class_id = ENTITY_TARGET_CD; - self->use = use_target_CD; - if(!self->dmg) - self->dmg = lazarus_cd_loop->value; - gi.linkentity(self); -} -/*=================================================================== - TARGET_MONITOR - Move the player's viewpoint to the target_monitor origin, - gives the target_monitor angles to the player, and freezes him - for "wait" seconds (default=3). If wait < 0, target_monitor - must be targeted a second time to free the player. -===================================================================*/ -#define SF_MONITOR_CHASECAM 1 -#define SF_MONITOR_EYEBALL 2 // Same as CHASECAM, but viewpoint is at the target - // entity's viewheight, and target entity is made - // invisible while in use - -void target_monitor_off (edict_t *self) -{ - int i; - edict_t *faker; - edict_t *player; - - player = self->child; - if(!player) return; - - if(self->spawnflags & SF_MONITOR_EYEBALL) - { - if(self->target_ent) - self->target_ent->svflags &= ~SVF_NOCLIENT; - } - faker = player->client->camplayer; - VectorCopy(faker->s.origin,player->s.origin); - free(faker->client); - G_FreeEdict (faker); - player->client->ps.pmove.origin[0] = player->s.origin[0]*8; - player->client->ps.pmove.origin[1] = player->s.origin[1]*8; - player->client->ps.pmove.origin[2] = player->s.origin[2]*8; - for (i=0 ; i<3 ; i++) - player->client->ps.pmove.delta_angles[i] = - ANGLE2SHORT(player->client->org_viewangles[i] - player->client->resp.cmd_angles[i]); - VectorCopy(player->client->org_viewangles, player->client->resp.cmd_angles); - VectorCopy(player->client->org_viewangles, player->s.angles); - VectorCopy(player->client->org_viewangles, player->client->ps.viewangles); - VectorCopy(player->client->org_viewangles, player->client->v_angle); - - player->client->ps.gunindex = gi.modelindex(player->client->pers.weapon->view_model); - player->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - player->client->ps.pmove.pm_type = PM_NORMAL; - player->svflags &= ~SVF_NOCLIENT; - player->clipmask = MASK_PLAYERSOLID; - player->solid = SOLID_BBOX; - player->viewheight = 22; - player->client->camplayer = NULL; - player->target_ent = NULL; - gi.unlinkentity(player); - KillBox(player); - gi.linkentity(player); - - if(self->noise_index) - gi.sound (player, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); - - // if we were previously in third person view, restore it - if(tpp->value) - Cmd_Chasecam_Toggle (player); - - self->child = NULL; - gi.linkentity(self); - - self->count--; - if(!self->count) { - self->use = NULL; - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void target_monitor_move (edict_t *self) -{ - // "chase cam" - trace_t trace; - vec3_t forward, o, goal; - - if(!self->target_ent || !self->target_ent->inuse) - { - if(self->wait) - { - self->think = target_monitor_off; - self->nextthink = self->monsterinfo.attack_finished; - } - return; - } - - if( (self->monsterinfo.attack_finished > 0) && - (level.time > self->monsterinfo.attack_finished)) - { - target_monitor_off(self); - return; - } - - AngleVectors(self->target_ent->s.angles,forward,NULL,NULL); - VectorMA(self->target_ent->s.origin, -self->moveinfo.distance, forward, o); - - o[2] += self->viewheight; - - VectorSubtract(o,self->s.origin,o); - VectorMA(self->s.origin,0.2,o,o); - - trace = gi.trace(self->target_ent->s.origin, NULL, NULL, o, self, MASK_SOLID); - VectorCopy(trace.endpos, goal); - VectorMA(goal, 2, forward, goal); - - // pad for floors and ceilings - VectorCopy(goal, o); - o[2] += 6; - trace = gi.trace(goal, NULL, NULL, o, self, MASK_SOLID); - if (trace.fraction < 1) { - VectorCopy(trace.endpos, goal); - goal[2] -= 6; - } - - VectorCopy(goal, o); - o[2] -= 6; - trace = gi.trace(goal, NULL, NULL, o, self, MASK_SOLID); - if (trace.fraction < 1) { - VectorCopy(trace.endpos, goal); - goal[2] += 6; - } - - VectorCopy(goal, self->s.origin); - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} -void use_target_monitor (edict_t *self, edict_t *other, edict_t *activator) -{ - int i; - edict_t *faker; - edict_t *monster; - gclient_t *cl; - - if(!activator->client) - return; - - if(self->child) - { - if(self->wait < 0) - target_monitor_off(self); - return; - } - - if(self->target) - self->target_ent = G_Find(NULL,FOFS(targetname),self->target); - - // if this is a CHASE_CAM target_monitor and the target no longer - // exists, remove this target_monitor and exit - if(self->spawnflags & SF_MONITOR_CHASECAM) - { - if(!self->target_ent || !self->target_ent->inuse) - { - G_FreeEdict(self); - return; - } - } - // save current viewangles - VectorCopy(activator->client->v_angle,activator->client->org_viewangles); - - // create a fake player to stand in real player's position - faker = activator->client->camplayer = G_Spawn(); - faker->s.frame = activator->s.frame; - VectorCopy (activator->s.origin, faker->s.origin); - VectorCopy (activator->velocity, faker->velocity); - VectorCopy (activator->s.angles, faker->s.angles); - faker->s = activator->s; - faker->takedamage = DAMAGE_NO; // so monsters won't attack - faker->flags |= FL_NOTARGET; // ... just to make sure -// faker->movetype = MOVETYPE_WALK; - faker->movetype = MOVETYPE_TOSS; - faker->groundentity = activator->groundentity; - faker->viewheight = activator->viewheight; - faker->inuse = true; - faker->classname = "camplayer"; - faker->class_id = ENTITY_CAMPLAYER; - faker->mass = activator->mass; - faker->solid = SOLID_BBOX; - faker->deadflag = DEAD_NO; - faker->clipmask = MASK_PLAYERSOLID; - faker->health = 100000; // invulnerable - faker->light_level = activator->light_level; - faker->think = faker_animate; - faker->nextthink = level.time + FRAMETIME; - VectorCopy(activator->mins,faker->mins); - VectorCopy(activator->maxs,faker->maxs); - // create a client so you can pick up items/be shot/etc while in camera - cl = (gclient_t *) malloc(sizeof(gclient_t)); - faker->client = cl; - faker->target_ent = activator; - gi.linkentity (faker); - - if(self->target_ent && self->target_ent->inuse) - { - if(self->spawnflags & SF_MONITOR_EYEBALL) - { - VectorCopy(self->target_ent->s.angles,activator->client->ps.viewangles); - } - else - { - vec3_t dir; - VectorSubtract(self->target_ent->s.origin,self->s.origin,dir); - vectoangles(dir,activator->client->ps.viewangles); - } - } - else - VectorCopy (self->s.angles, activator->client->ps.viewangles); - - VectorCopy (self->s.origin, activator->s.origin); - activator->client->ps.pmove.origin[0] = self->s.origin[0]*8; - activator->client->ps.pmove.origin[1] = self->s.origin[1]*8; - activator->client->ps.pmove.origin[2] = self->s.origin[2]*8; - activator->client->ps.pmove.pm_type = PM_FREEZE; - activator->svflags |= SVF_NOCLIENT; - activator->solid = SOLID_NOT; - activator->viewheight = 0; - if(activator->client->chasetoggle) - { - Cmd_Chasecam_Toggle (activator); - activator->client->pers.chasetoggle = 1; - } - else - activator->client->pers.chasetoggle = 0; - activator->clipmask = 0; - VectorClear(activator->velocity); - activator->client->ps.gunindex = 0; - activator->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - gi.linkentity(activator); - - gi.unlinkentity(faker); - KillBox(faker); - gi.linkentity(faker); - - // check to see if player is the enemy of any monster. - for(i=maxclients->value+1, monster=g_edicts+i; iinuse) continue; - if(!(monster->svflags & SVF_MONSTER)) continue; - if(monster->enemy == activator) - { - monster->enemy = NULL; - monster->oldenemy = NULL; - if(monster->goalentity == activator) - monster->goalentity = NULL; - if(monster->movetarget == activator) - monster->movetarget = NULL; - monster->monsterinfo.attack_finished = level.time + 1; - FindTarget(monster); - } - } - - activator->target_ent = self; - self->child = activator; - - if(self->noise_index) - gi.sound (activator, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); - - if(self->spawnflags & SF_MONITOR_CHASECAM) - { - if(self->wait > 0) - self->monsterinfo.attack_finished = level.time + self->wait; - else - self->monsterinfo.attack_finished = 0; - - if(self->spawnflags & SF_MONITOR_EYEBALL) - { - self->viewheight = self->target_ent->viewheight; - self->target_ent->svflags |= SVF_NOCLIENT; - } - VectorCopy(self->target_ent->s.origin,self->s.origin); - self->think = target_monitor_move; - self->think(self); - } - else if(self->wait > 0) - { - self->think = target_monitor_off; - self->nextthink = level.time + self->wait; - } -} - -void SP_target_monitor (edict_t *self) -{ - char buffer[MAX_QPATH]; - - self->class_id = ENTITY_TARGET_MONITOR; - if(!self->wait) - self->wait = 3; - self->use = use_target_monitor; - self->movetype = MOVETYPE_NOCLIP; - if(st.noise) - { - if (!strstr (st.noise, ".wav")) - sprintf (buffer, "%s.wav", st.noise); - else - strncpy (buffer, st.noise, sizeof(buffer)); - self->noise_index = gi.soundindex (buffer); - } - - if(self->spawnflags & SF_MONITOR_EYEBALL) - self->spawnflags |= SF_MONITOR_CHASECAM; - - if(self->spawnflags & SF_MONITOR_CHASECAM) - { // chase cam - if(self->spawnflags & SF_MONITOR_EYEBALL) - { - self->moveinfo.distance = 0; - self->viewheight = 0; - } - else - { - if(st.distance) - self->moveinfo.distance = st.distance; - else - self->moveinfo.distance = 128; - - if(st.height) - self->viewheight = st.height; - else - self->viewheight = 16; - } - - // MUST have target - if(!self->target) - { - gi.dprintf("CHASECAM target_monitor with no target at %s\n",vtos(self->s.origin)); - self->spawnflags &= ~(SF_MONITOR_CHASECAM | SF_MONITOR_EYEBALL); - } - else if(self->movewith) - { - gi.dprintf("CHASECAM target_monitor cannot use 'movewith'\n"); - self->spawnflags &= ~(SF_MONITOR_CHASECAM | SF_MONITOR_EYEBALL); - } - } - - gi.linkentity(self); -} - -/*==================================================================================== - TARGET_ANIMATION causes the target entity to use the animation frames - "startframe" through "startframe" + "framenumbers" - 1. - - Spawnflags: - ACTIVATOR = 1 - target_animation acts on it's activator rather than - it's target - - "message" - specifies allowable classname to animate. This prevents - animating entities with inapplicable frame numbers -=====================================================================================*/ -void target_animate (edict_t *ent) -{ - if( (ent->s.frame < ent->monsterinfo.currentmove->firstframe) || - (ent->s.frame >= ent->monsterinfo.currentmove->lastframe ) ) - { - if(ent->monsterinfo.currentmove->endfunc) - { - ent->think = ent->monsterinfo.currentmove->endfunc; - ent->nextthink = level.time + FRAMETIME; - } - else if(ent->svflags & SVF_MONSTER) - { - // Hopefully we don't get here, but if we DO then we definitely - // need for monsters/actors to turn their brains back on. - ent->think = monster_think; - ent->nextthink = level.time + FRAMETIME; - } - else - { - ent->think = NULL; - ent->nextthink = 0; - } - ent->monsterinfo.currentmove = ent->monsterinfo.savemove; - return; - } - ent->s.frame++; - ent->nextthink = level.time + FRAMETIME; - gi.linkentity(ent); -} - -void target_animation_use (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *target = NULL; - - if(level.time < self->touch_debounce_time) - return; - if(self->spawnflags & 1) - { - if(activator && activator->client) - return; - if(self->message && strcasecmp(self->message, activator->classname)) - return; - if(!self->target) - target = activator; - } - if(!target) - { - if(!self->target) - return; - target = G_Find(NULL,FOFS(targetname),self->target); - if(!target) - return; - } - // Don't allow target to be animated if ALREADY under influence of - // another target_animation - if(target->think == target_animate) - return; - self->monsterinfo.currentmove->firstframe = self->startframe; - self->monsterinfo.currentmove->lastframe = self->startframe + self->framenumbers - 1; - self->monsterinfo.currentmove->frame = NULL; - self->monsterinfo.currentmove->endfunc = target->think; - target->s.frame = self->startframe; - target->think = target_animate; - target->monsterinfo.savemove = target->monsterinfo.currentmove; - target->monsterinfo.currentmove = self->monsterinfo.currentmove; - target->nextthink = level.time + FRAMETIME; - gi.linkentity(target); - - self->count--; - if(!self->count) - G_FreeEdict(self); - else - self->touch_debounce_time = level.time + (self->framenumbers+1)*FRAMETIME; -} - -void SP_target_animation (edict_t *self) -{ - mmove_t *move; - if(!self->target && !(self->spawnflags & 1)) - { - gi.dprintf("target_animation w/o a target at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - } - self->class_id = ENTITY_TARGET_ANIMATION; - switch(self->sounds) - { - case 1: - // actor jump - self->startframe = 66; - self->framenumbers = 6; - break; - case 2: - // actor flip - self->startframe = 72; - self->framenumbers = 12; - break; - case 3: - // actor salute - self->startframe = 84; - self->framenumbers = 11; - break; - case 4: - // actor taunt - self->startframe = 95; - self->framenumbers = 17; - break; - case 5: - // actor wave - self->startframe = 112; - self->framenumbers = 11; - break; - case 6: - // actor point - self->startframe = 123; - self->framenumbers = 12; - break; - default: - if(!self->framenumbers) - self->framenumbers = 1; - } - self->use = target_animation_use; - move = TagMalloc(sizeof(mmove_t), TAG_LEVEL); - self->monsterinfo.currentmove = move; -} -/*=================================================================================== - TARGET_FAILURE - Halts the game, fades the screen to black and displays - a message explaining to the player how he screwed up. - Optionally plays a sound. -====================================================================================*/ -void target_failure_wipe (edict_t *self) -{ - edict_t *player; - - player = &g_edicts[1]; // Gotta be, since this is SP only - if(player->client->textdisplay) Text_Close(player); -} - -void target_failure_player_die (edict_t *player) -{ - int n; - - // player_die w/o... umm... dying - - if (player->client->chasetoggle) - { - ChasecamRemove (player, OPTION_OFF); - player->client->pers.chasetoggle = 1; - } - else - player->client->pers.chasetoggle = 0; - player->client->pers.spawn_landmark = false; // paranoia check - player->client->pers.spawn_levelchange = false; - player->client->zooming = 0; - player->client->zoomed = false; - SetSensitivities(player,true); - if(player->client->spycam) - camera_off(player); - VectorClear (player->avelocity); - player->takedamage = DAMAGE_NO; - player->movetype = MOVETYPE_NONE; - player->s.weaponmodel = 0; // remove linked weapon model - player->s.sound = 0; - player->client->weapon_sound = 0; - player->svflags |= SVF_DEADMONSTER; - player->client->respawn_time = level.time + 1.0; - player->client->ps.gunindex = 0; - // clear inventory - for (n = 0; n < game.num_items; n++) - { - player->client->pers.inventory[n] = 0; - } - // remove powerups - player->client->quad_framenum = 0; - player->client->invincible_framenum = 0; - player->client->breather_framenum = 0; - player->client->enviro_framenum = 0; - player->flags &= ~FL_POWER_ARMOR; - player->client->flashlight = false; - player->deadflag = DEAD_FROZEN; - gi.linkentity (player); -} -void target_failure_think (edict_t *self) -{ - target_failure_player_die(self->target_ent); - self->target_ent = NULL; - self->think = target_failure_wipe; - self->nextthink = level.time + 10; -} - -void target_failure_fade_lights (edict_t *self) -{ - char lightvalue[2]; - char values[] = "abcdefghijklm"; - - lightvalue[0] = values[self->flags]; - lightvalue[1] = 0; - gi.configstring(CS_LIGHTS+0, lightvalue); - if(self->flags) - { - self->flags--; - self->nextthink = level.time + 0.2; - } - else - { - target_failure_player_die(self->target_ent); - self->target_ent = NULL; - self->think = target_failure_wipe; - self->nextthink = level.time + 10; - } -} - -void Use_Target_Text(edict_t *self, edict_t *other, edict_t *activator); -void use_target_failure (edict_t *self, edict_t *other, edict_t *activator) -{ - if(!activator->client) - return; - - if(self->target_ent) - return; - - if(strlen(self->message)) - Use_Target_Text(self,other,activator); - - if(self->noise_index) - gi.sound (activator, CHAN_VOICE|CHAN_RELIABLE, self->noise_index, 1, ATTN_NORM, 0); - - self->target_ent = activator; - activator->client->fadestart= level.framenum; - activator->client->fadein = level.framenum + 40; - activator->client->fadehold = activator->client->fadein + 100000; - activator->client->fadeout = 0; - activator->client->fadecolor[0] = 0; - activator->client->fadecolor[1] = 0; - activator->client->fadecolor[2] = 0; - activator->client->fadealpha = 1.0; - self->think = target_failure_think; - self->nextthink = level.time + 4; - activator->deadflag = DEAD_FROZEN; - gi.linkentity(activator); -} - -void SP_target_failure (edict_t *self) -{ - if (deathmatch->value || coop->value) - { // SP only - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_TARGET_FAILURE; - self->use = use_target_failure; - if (st.noise) - self->noise_index = gi.soundindex(st.noise); -} - -/*===================================================================================== - TARGET_CHANGE - copies selected fields to target. - Target value should be of the form "entitytotarget,new target value". - All other keys are replacements for the targeted entity, NOT the - target_change. -======================================================================================*/ -void use_target_change (edict_t *self, edict_t *other, edict_t *activator) -{ - char *buffer; - char *target; - char *newtarget; - int L; - int newteams=0; - edict_t *target_ent; - - if(!self->target) - return; - L = strlen(self->target); - buffer = (char *)malloc(L+1); - strcpy(buffer,self->target); - newtarget = strstr(buffer,","); - if(newtarget) - { - *newtarget = 0; - newtarget++; - } - target = buffer; - target_ent = G_Find(NULL,FOFS(targetname),target); - while(target_ent) - { - if(newtarget && strlen(newtarget)) - target_ent->target = G_CopyString(newtarget); - if(self->newtargetname && strlen(self->newtargetname)) - target_ent->targetname = G_CopyString(self->newtargetname); - if(self->team && strlen(self->team)) - { - target_ent->team = G_CopyString(self->team); - newteams++; - } - if(VectorLength(self->s.angles)) - { - VectorCopy (self->s.angles, target_ent->s.angles); - if(target_ent->solid == SOLID_BSP) - G_SetMovedir (target_ent->s.angles, target_ent->movedir); - } - if(self->deathtarget && strlen(self->deathtarget)) - target_ent->deathtarget = G_CopyString(self->deathtarget); - if(self->pathtarget && strlen(self->pathtarget)) - target_ent->pathtarget = G_CopyString(self->pathtarget); - if(self->killtarget && strlen(self->killtarget)) - target_ent->killtarget = G_CopyString(self->killtarget); - if(self->message && strlen(self->message)) - target_ent->message = G_CopyString(self->message); - if(self->delay > 0) - target_ent->delay = self->delay; - if(self->dmg > 0) - target_ent->dmg = self->dmg; - if(self->health > 0) - target_ent->health = self->health; - if(self->mass > 0) - target_ent->mass = self->mass; - if(self->pitch_speed > 0) - target_ent->pitch_speed = self->pitch_speed; - if(self->random > 0) - target_ent->random = self->random; - if(self->roll_speed > 0) - target_ent->roll_speed = self->roll_speed; - if(self->wait > 0) - target_ent->wait = self->wait; - if(self->yaw_speed > 0) - target_ent->yaw_speed = self->yaw_speed; - if(self->noise_index) - { - if(target_ent->s.sound == target_ent->noise_index) - target_ent->s.sound = target_ent->noise_index = self->noise_index; - else - target_ent->noise_index = self->noise_index; - } - if(self->spawnflags) - { - target_ent->spawnflags = self->spawnflags; - // special cases: - if(target_ent->class_id == ENTITY_MODEL_TRAIN) - { - if(target_ent->spawnflags & 32) - { - target_ent->spawnflags &= ~32; - target_ent->spawnflags |= 8; - } - if(target_ent->spawnflags & 64) - { - target_ent->spawnflags &= ~64; - target_ent->spawnflags |= 16; - } - } - } - gi.linkentity(target_ent); - target_ent = G_Find(target_ent,FOFS(targetname),target); - } - free(buffer); - if(newteams) - G_FindTeams(); -} - -void SP_target_change (edict_t *self) -{ - self->class_id = ENTITY_TARGET_CHANGE; - self->use = use_target_change; - if(st.noise) - self->noise_index = gi.soundindex(st.noise); -} - -/*==================================================================================== - TARGET_MOVEWITH - sets an entity to "movewith" it's pathtarget (or remove - that setting if DETACH (=1) is set) -======================================================================================*/ - -void movewith_detach (edict_t *child) -{ - edict_t *e; - edict_t *parent=NULL; - int i; - - for(i=1; imovewith_next == child) parent=e; - } - if(parent) parent->movewith_next = child->movewith_next; - - child->movewith_next = NULL; - child->movewith = NULL; - child->movetype = child->org_movetype; - // if monster, give 'em a small vertical boost - if(child->svflags & SVF_MONSTER) - child->s.origin[2] += 2; - gi.linkentity(child); -} - -void use_target_movewith (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *target; - - if(!self->target) - return; - target = G_Find(NULL,FOFS(targetname),self->target); - - if(self->spawnflags & 1) - { - // Detach - while(target) - { - if(target->movewith_ent) - movewith_detach(target); - target = G_Find(target,FOFS(targetname),self->target); - } - } - else - { - // Attach - edict_t *parent; - edict_t *e; - edict_t *previous; - - parent = G_Find(NULL,FOFS(targetname),self->pathtarget); - if(!parent || !parent->inuse) - return; - while(target) - { - if(!target->movewith_ent || (target->movewith_ent != parent) ) - { - if(target->movewith_ent) - movewith_detach(target); - - target->movewith_ent = parent; - VectorCopy(parent->s.angles,target->parent_attach_angles); - if(target->org_movetype < 0) - target->org_movetype = target->movetype; - if(target->movetype != MOVETYPE_NONE) - target->movetype = MOVETYPE_PUSH; - VectorCopy(target->mins,target->org_mins); - VectorCopy(target->maxs,target->org_maxs); - VectorSubtract(target->s.origin,parent->s.origin,target->movewith_offset); - e = parent->movewith_next; - previous = parent; - while(e) - { - previous = e; - e = previous->movewith_next; - } - previous->movewith_next = target; - gi.linkentity(target); - } - target = G_Find(target,FOFS(targetname),self->target); - } - } - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_target_movewith (edict_t *self) -{ - if(!self->target) - { - gi.dprintf("target_movewith with no target\n"); - G_FreeEdict(self); - return; - } - if(!(self->spawnflags & 1) && !self->pathtarget) - { - gi.dprintf("target_movewith w/o DETACH and no pathtarget\n"); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_MOVEWITH; - self->use = use_target_movewith; -} - -/*==================================================================================== - TARGET_SET_EFFECT - sets s.effects and/or s.renderfx for targeted entity - Style - 0 = Copy - 1 = NOT - 2 = XOR (toggle) -======================================================================================*/ - -void use_target_set_effect (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *target; - - target = G_Find(NULL,FOFS(targetname),self->target); - while(target) - { - if(self->style == 1) - { - target->s.effects &= ~self->effects; - target->s.renderfx &= ~self->renderfx; - } - else if(self->style == 2) - { - target->s.effects ^= self->effects; - target->s.renderfx ^= self->renderfx; - } - else - { - target->s.effects = self->effects; - target->s.renderfx = self->renderfx; - } - gi.linkentity(target); - target = G_Find(target,FOFS(targetname),self->target); - } -} - -void SP_target_set_effect (edict_t *self) -{ - if(!self->target) - { - gi.dprintf("target_set_effect w/o a target at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_SET_EFFECT; - self->use = use_target_set_effect; -} - -/*============================================================================= - TARGET_SKY - uses the "skyname" string as parameter to "skyname" console command. - Best used in areas where player cannot see the sky, of course. - - NOTE: Tried using a START_ON spawnflag, but it ends up being meaningless. - If we don't delay use_target_sky a bit at level start, we get - "SZ_GetSpace: overflow without allowoverflow set", and if we use - a sufficient delay to get around the error then the original sky - is visible before the switch. -=============================================================================*/ -void use_target_sky (edict_t *self, edict_t *other, edict_t *activator) -{ - gi.configstring(CS_SKY,self->pathtarget); - stuffcmd(&g_edicts[1],va("sky %s\n",self->pathtarget)); - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_target_sky (edict_t *self) -{ - if(!st.sky || !*st.sky) - { - gi.dprintf("Target_sky with no sky string at %s\n",vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_SKY; - self->pathtarget = TagMalloc(strlen(st.sky)+1,TAG_LEVEL); - strcpy(self->pathtarget,st.sky); - self->use = use_target_sky; -} - -/*============================================================================= - TARGET_FADE fades the screen to a color - color = R,G,B components of fade color, 0-1 - alpha = opacity of fade. 0=no effect, 1=solid color - fadein = time in seconds from trigger until full alpha - fadeout = time in seconds after fadein+holdtime from full alpha to clear screen - holdtime = time to hold the effect at full alpha value. -1 = permanent -=============================================================================*/ -void use_target_fade (edict_t *self, edict_t *other, edict_t *activator) -{ - if(!activator->client) - return; - - activator->client->fadestart= level.framenum; - activator->client->fadein = level.framenum + self->fadein*10; - activator->client->fadehold = activator->client->fadein + self->holdtime*10; - activator->client->fadeout = activator->client->fadehold + self->fadeout*10; - activator->client->fadecolor[0] = self->color[0]; - activator->client->fadecolor[1] = self->color[1]; - activator->client->fadecolor[2] = self->color[2]; - activator->client->fadealpha = self->alpha; - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_target_fade (edict_t *self) -{ - self->class_id = ENTITY_TARGET_FADE; - self->use = use_target_fade; - if(self->fadein < 0) - self->fadein = 0; - if(self->holdtime < 0) - { - self->count = 1; - self->holdtime = 10000; - } - if(self->fadeout < 0) - self->fadeout = 0; -} - -/*============================================================================= - TARGET_CLONE - Spawns a new entity, using model and other parameters of source entity. - - source - targetname of source entity for model - newtargetname - targetname to assign to spawned entity - target - target to assign to spawned entity - count - number of spawner uses before being freed - Spawnflags - 1 = START_ON -=============================================================================*/ -void button_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); -void Think_CalcMoveSpeed (edict_t *self); -void Think_SpawnDoorTrigger (edict_t *ent); -void func_train_find (edict_t *self); -void clone (edict_t *self, edict_t *other, edict_t *activator) -{ - edict_t *parent; - edict_t *child; - int newteams=0; - - parent = G_Find(NULL,FOFS(targetname),self->source); - if(!parent) - return; - child = G_Spawn(); - child->classname = TagMalloc(strlen(parent->classname)+1,TAG_LEVEL); - strcpy(child->classname,parent->classname); - child->class_id = parent->class_id; - child->s.modelindex = parent->s.modelindex; - VectorCopy(self->s.origin,child->s.origin); - child->svflags = parent->svflags; - VectorCopy(parent->mins,child->mins); - VectorCopy(parent->maxs,child->maxs); - VectorCopy(parent->size,child->size); - - if(self->newtargetname && strlen(self->newtargetname)) - child->targetname = G_CopyString(self->newtargetname); - if(self->team && strlen(self->team)) - { - child->team = G_CopyString(self->team); - newteams++; - } - if(self->target && strlen(self->target)) - child->target = G_CopyString(self->target); - - if(parent->deathtarget && strlen(parent->deathtarget)) - child->deathtarget = G_CopyString(parent->deathtarget); - if(parent->destroytarget && strlen(parent->destroytarget)) - child->destroytarget = G_CopyString(parent->destroytarget); - if(parent->killtarget && strlen(parent->killtarget)) - child->killtarget = G_CopyString(parent->killtarget); - - child->solid = parent->solid; - child->clipmask = parent->clipmask; - child->movetype = parent->movetype; - child->mass = parent->mass; - child->health = parent->health; - child->max_health = parent->max_health; - child->takedamage = parent->takedamage; - child->dmg = parent->dmg; - child->sounds = parent->sounds; - child->speed = parent->speed; - child->accel = parent->accel; - child->decel = parent->decel; - child->gib_type = parent->gib_type; - child->noise_index = parent->noise_index; - child->noise_index2 = parent->noise_index2; - child->wait = parent->wait; - child->delay = parent->delay; - child->random = parent->random; - child->style = parent->style; - child->flags = parent->flags; - child->blocked = parent->blocked; - child->touch = parent->touch; - child->use = parent->use; - child->pain = parent->pain; - child->die = parent->die; - child->s.effects = parent->s.effects; - child->s.skin = parent->s.skin; - child->item = parent->item; - child->moveinfo.sound_start = parent->moveinfo.sound_start; - child->moveinfo.sound_middle = parent->moveinfo.sound_middle; - child->moveinfo.sound_end = parent->moveinfo.sound_end; - VectorCopy(parent->movedir,child->movedir); - VectorCopy(self->s.angles, child->s.angles); - if(VectorLength(child->s.angles) != 0) - { - if(child->s.angles[YAW] == 90 || child->s.angles[YAW] == 270) - { - // We're correct for these angles, not even gonna bother with others - vec_t temp; - temp = child->size[0]; - child->size[0] = child->size[1]; - child->size[1] = temp; - temp = child->mins[0]; - if(child->s.angles[YAW] == 90) - { - child->mins[0] = -child->maxs[1]; - child->maxs[1] = child->maxs[0]; - child->maxs[0] = -child->mins[1]; - child->mins[1] = temp; - } - else - { - child->mins[0] = child->mins[1]; - child->mins[1] = -child->maxs[0]; - child->maxs[0] = child->maxs[1]; - child->maxs[1] = -temp; - } - } - vectoangles(child->movedir,child->movedir); - child->movedir[PITCH] += child->s.angles[PITCH]; - child->movedir[YAW] += child->s.angles[YAW]; - child->movedir[ROLL] += child->s.angles[ROLL]; - if(child->movedir[PITCH] > 360) child->movedir[PITCH] -= 360; - if(child->movedir[YAW] > 360) child->movedir[YAW] -= 360; - if(child->movedir[ROLL] > 360) child->movedir[ROLL] -= 360; - AngleVectors(child->movedir,child->movedir,NULL,NULL); - } - VectorAdd(child->s.origin,child->mins,child->absmin); - VectorAdd(child->s.origin,child->maxs,child->absmax); - - child->spawnflags = parent->spawnflags; - // classname-specific stuff - if(child->class_id == ENTITY_FUNC_BUTTON) - { - VectorCopy(child->s.origin,child->pos1); - child->moveinfo.distance = parent->moveinfo.distance; - VectorMA(child->pos1, child->moveinfo.distance, child->movedir, child->pos2); - child->moveinfo.state = 1; - child->moveinfo.speed = child->speed; - child->moveinfo.accel = child->accel; - child->moveinfo.decel = child->decel; - child->moveinfo.wait = child->wait; - VectorCopy(child->pos1, child->moveinfo.start_origin); - VectorCopy(child->s.angles, child->moveinfo.start_angles); - VectorCopy(child->pos2, child->moveinfo.end_origin); - VectorCopy(child->s.angles, child->moveinfo.end_angles); - if(!child->targetname) - child->touch = button_touch; - } - else if(child->class_id == ENTITY_FUNC_DOOR) - { - VectorCopy(child->s.origin,child->pos1); - child->moveinfo.distance = parent->moveinfo.distance; - VectorMA(child->pos1, child->moveinfo.distance, child->movedir, child->pos2); - child->moveinfo.state = 1; - child->moveinfo.speed = child->speed; - child->moveinfo.accel = child->accel; - child->moveinfo.decel = child->decel; - child->moveinfo.wait = child->wait; - VectorCopy(child->pos1, child->moveinfo.start_origin); - VectorCopy(child->s.angles, child->moveinfo.start_angles); - VectorCopy(child->pos2, child->moveinfo.end_origin); - VectorCopy(child->s.angles, child->moveinfo.end_angles); - if(child->health || child->targetname) - child->think = Think_CalcMoveSpeed; - else - child->think = Think_SpawnDoorTrigger; - child->nextthink = level.time + FRAMETIME; - } - else if(child->class_id == ENTITY_FUNC_DOOR_ROTATING) - { - VectorClear(child->s.angles); - VectorCopy(parent->s.angles,child->s.angles); - VectorCopy(parent->pos1, child->pos1); - VectorCopy(parent->pos2, child->pos2); - child->moveinfo.distance = parent->moveinfo.distance; - child->moveinfo.state = 1; - child->moveinfo.speed = child->speed; - child->moveinfo.accel = child->accel; - child->moveinfo.decel = child->decel; - child->moveinfo.wait = child->wait; - VectorCopy(child->s.origin, child->moveinfo.start_origin); - VectorCopy(child->pos1, child->moveinfo.start_angles); - VectorCopy(child->s.origin, child->moveinfo.end_origin); - VectorCopy(child->pos2, child->moveinfo.end_angles); - if(child->health || child->targetname) - child->think = Think_CalcMoveSpeed; - else - child->think = Think_SpawnDoorTrigger; - child->nextthink = level.time + FRAMETIME; - } - else if(child->class_id == ENTITY_FUNC_ROTATING) - { - VectorClear(child->s.angles); - if (child->spawnflags & 1) - child->use (child, NULL, NULL); - } - else if(child->class_id == ENTITY_FUNC_TRAIN) - { - VectorClear(self->s.angles); - child->smooth_movement = parent->smooth_movement; - child->pitch_speed = parent->pitch_speed; - child->yaw_speed = parent->yaw_speed; - child->roll_speed = parent->roll_speed; - child->moveinfo.speed = child->speed; - child->moveinfo.accel = child->moveinfo.decel = child->moveinfo.speed; - child->think = func_train_find; - child->nextthink = level.time + FRAMETIME; - if(child->moveinfo.sound_middle || parent->noise_index) - { - edict_t *speaker; - if(child->moveinfo.sound_middle) - child->noise_index = child->moveinfo.sound_middle; - else - child->noise_index = parent->noise_index; - child->moveinfo.sound_middle = 0; - speaker = G_Spawn(); - speaker->classname = "moving_speaker"; - speaker->s.sound = 0; - speaker->volume = 1; - speaker->attenuation = 1; - speaker->owner = child; - speaker->think = Moving_Speaker_Think; - speaker->nextthink = level.time + 2*FRAMETIME; - speaker->spawnflags = 7; // owner must be moving to play - child->speaker = speaker; - if(VectorLength(child->s.origin)) - { - VectorCopy(child->s.origin,speaker->s.origin); - } - else - { - VectorAdd(child->absmin,child->absmax,speaker->s.origin); - VectorScale(speaker->s.origin,0.5,speaker->s.origin); - } - VectorSubtract(speaker->s.origin,child->s.origin,speaker->offset); - } - } - gi.unlinkentity(child); - KillBox(child); - gi.linkentity(child); - if(self->s.angles[YAW] != 0) - { - VectorAdd(child->s.origin,child->mins,child->absmin); - VectorAdd(child->s.origin,child->maxs,child->absmax); - } - self->count--; - if(!self->count) - G_FreeEdict(self); - if(newteams) - G_FindTeams(); -} - -void target_clone_starton (edict_t *self) -{ - self->use(self,NULL,NULL); -} - -void SP_target_clone (edict_t *self) -{ - self->class_id = ENTITY_TARGET_CLONE; - if(!self->source) - { - gi.dprintf("%s with no source at %s\n", - self->classname,vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - self->use = clone; - if(self->spawnflags & 1) - { - self->think = target_clone_starton; - self->nextthink = level.time + 2; - } -} - -void use_target_skill (edict_t *self, edict_t *other, edict_t *activator) -{ - level.next_skill = self->style + 1; - self->count--; - if(!self->count) - G_FreeEdict(self); -} - -void SP_target_skill (edict_t *self) -{ - self->class_id = ENTITY_TARGET_SKILL; - self->use = use_target_skill; -} \ No newline at end of file diff --git a/server/ents/g_thing.c b/server/ents/g_thing.c deleted file mode 100644 index ded90b60..00000000 --- a/server/ents/g_thing.c +++ /dev/null @@ -1,307 +0,0 @@ -#include "g_local.h" - -bool has_valid_enemy (edict_t *self); -void HuntTarget (edict_t *self); - -edict_t *SpawnThing() -{ - edict_t *thing; - thing = G_Spawn(); - thing->classname = TagMalloc(6,TAG_LEVEL); - strcpy(thing->classname,"thing"); - return thing; -} - -void thing_restore_leader (edict_t *self) -{ - edict_t *monster; - monster = self->target_ent; - if(!monster || !monster->inuse) - { - G_FreeEdict(self); - return; - } - if(monster->monsterinfo.old_leader && monster->monsterinfo.old_leader->inuse) - { - if(VectorCompare(monster->monsterinfo.old_leader->s.origin,self->move_origin)) - { - self->nextthink = level.time + 0.5; - return; - } - monster->monsterinfo.leader = monster->monsterinfo.old_leader; - monster->monsterinfo.old_leader = NULL; - monster->movetarget = monster->goalentity = monster->monsterinfo.leader; - } - else - { - monster->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; - } - monster->vehicle = NULL; - monster->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_SEEK_COVER | AI_EVADE_GRENADE); - gi.linkentity(monster); - G_FreeEdict(self); -} -void thing_think (edict_t *self) -{ - vec3_t vec; - vec_t dist; - edict_t *monster; - - monster = self->target_ent; - if(level.time <= self->touch_debounce_time) - { - if(monster && monster->inuse) - { - if(monster->movetarget == self) - { - if(monster->health > 0) - { - if(monster->monsterinfo.aiflags & AI_SEEK_ENEMY) - { - if(monster->enemy && monster->enemy->inuse) - { - if(visible(monster,monster->enemy)) - { - monster->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_SEEK_ENEMY); - monster->movetarget = monster->goalentity = monster->enemy; - VectorSubtract (monster->enemy->s.origin, monster->s.origin, vec); - monster->ideal_yaw = vectoyaw(vec); - G_FreeEdict(self); - return; - } - } - } - VectorSubtract(monster->s.origin,self->s.origin,vec); - vec[2] = 0; - dist = VectorLength(vec); - if(dist >= monster->size[0]) - { - self->nextthink = level.time + FRAMETIME; - return; - } - } - } - } - } - if(!monster || !monster->inuse || (monster->health <= 0)) - { - G_FreeEdict(self); - return; - } - if(monster->goalentity == self) - monster->goalentity = NULL; - if(monster->movetarget == self) - monster->movetarget = NULL; - if(monster->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - monster->monsterinfo.leader = NULL; - if(monster->monsterinfo.old_leader && monster->monsterinfo.old_leader->inuse) - { - monster->monsterinfo.pausetime = level.time + 2; - monster->monsterinfo.stand(monster); - VectorCopy(monster->monsterinfo.old_leader->s.origin,self->move_origin); - self->nextthink = level.time + 2; - self->think = thing_restore_leader; - gi.linkentity(monster); - return; - } - else - { - monster->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; - } - } - if(monster->monsterinfo.aiflags & AI_CHICKEN) - { - monster->monsterinfo.stand(monster); - monster->monsterinfo.aiflags |= AI_STAND_GROUND; - monster->monsterinfo.pausetime = level.time + 100000; - } - monster->vehicle = NULL; - monster->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_SEEK_COVER | AI_EVADE_GRENADE | AI_SEEK_ENEMY); - - G_FreeEdict(self); - if (has_valid_enemy(monster)) - { - monster->monsterinfo.pausetime = 0; - monster->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - monster->goalentity = monster->enemy; - if (visible(monster, monster->enemy)) - { - FoundTarget (monster); - return; - } - HuntTarget (monster); - return; - } - monster->enemy = NULL; - monster->monsterinfo.pausetime = level.time + 100000000; - monster->monsterinfo.stand (monster); -} - -void thing_think_pause(edict_t *self) -{ - edict_t *monster; - if(level.time > self->touch_debounce_time) - { - thing_think(self); - return; - } - monster = self->target_ent; - if(!monster || !monster->inuse) - { - G_FreeEdict(self); - return; - } - if(has_valid_enemy(monster)) - { - vec3_t dir; - vec3_t angles; - - if(visible(monster->enemy,monster)) - { - self->touch_debounce_time = 0; - thing_think(self); - return; - } - VectorSubtract(monster->enemy->s.origin,monster->s.origin,dir); - VectorNormalize(dir); - vectoangles(dir,angles); - monster->ideal_yaw = angles[YAW]; - M_ChangeYaw(monster); - } - self->nextthink = level.time + FRAMETIME; -} - -void thing_grenade_boom (edict_t *self) -{ - edict_t *monster; - - monster = self->target_ent; - G_FreeEdict(self); - if(!monster || !monster->inuse || (monster->health <= 0)) - return; - monster->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE | AI_STAND_GROUND); - monster->monsterinfo.pausetime = 0; - if(monster->enemy) - monster->monsterinfo.run(monster); -} - -void thing_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if(self->target_ent != other) - return; - if(other->health <= 0) - { - G_FreeEdict(self); - return; - } - self->touch = NULL; - if( self->target_ent->monsterinfo.aiflags & AI_SEEK_COVER ) - { - edict_t *monster; - // For monster/actor seeking cover after firing, - // pause a random bit before resuming attack - self->touch_debounce_time = level.time + random()*6.; - monster = self->target_ent; - monster->monsterinfo.stand(monster); - monster->monsterinfo.pausetime = self->touch_debounce_time; - self->think = thing_think_pause; - self->think(self); - return; - } - if( self->target_ent->monsterinfo.aiflags & AI_EVADE_GRENADE ) - { - edict_t *grenade = other->next_grenade; - - if(other->goalentity == self) - other->goalentity = NULL; - if(other->movetarget == self) - other->movetarget = NULL; - other->vehicle = NULL; - if(grenade) - { - // make sure this is still a grenade - if(grenade->inuse) - { - if((grenade->class_id != ENTITY_GRENADE) && (grenade->class_id != ENTITY_HANDGRENADE)) - other->next_grenade = grenade = NULL; - } - else - other->next_grenade = grenade = NULL; - } - if(grenade) - { - if(self->touch_debounce_time > level.time) - { - other->monsterinfo.pausetime = self->touch_debounce_time + 0.1; - other->monsterinfo.aiflags |= AI_STAND_GROUND; - other->monsterinfo.stand(other); - } - else - other->monsterinfo.pausetime = 0; - - other->enemy = grenade->owner; - if (has_valid_enemy(other)) - { - other->goalentity = other->enemy; - if (visible(other, other->enemy)) - FoundTarget (other); - else - HuntTarget (other); - } - else - { - other->enemy = NULL; - other->monsterinfo.stand (other); - } - if(other->monsterinfo.pausetime > 0) - { - self->think = thing_grenade_boom; - self->nextthink = other->monsterinfo.pausetime; - return; - } - other->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE); - } - else if (has_valid_enemy(other)) - { - other->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE); - other->goalentity = other->enemy; - if (visible(other, other->enemy)) - FoundTarget (other); - else - HuntTarget (other); - } - else - { - other->enemy = NULL; - other->monsterinfo.pausetime = level.time + 100000000; - other->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE); - other->monsterinfo.stand (other); - } - G_FreeEdict(self); - return; - } - self->touch_debounce_time = 0; - thing_think(self); -} - -void SP_thing (edict_t *self) -{ - self->class_id = ENTITY_THING; - self->solid = SOLID_TRIGGER; - VectorSet(self->mins,-4,-4,-4); - VectorSet(self->maxs, 4, 4, 4); - self->movetype = MOVETYPE_NONE; - self->monsterinfo.aiflags |= AI_GOOD_GUY; - self->svflags |= SVF_MONSTER; - self->health = 1000; - self->takedamage = DAMAGE_NO; - if(developer->value) { - gi.setmodel (self, "models/items/c_head/tris.md2"); - self->s.effects |= EF_BLASTER; - } - self->touch = thing_touch; - self->think = thing_think; - self->nextthink = level.time + 2; - gi.linkentity(self); -} diff --git a/server/ents/g_tracktrain.c b/server/ents/g_tracktrain.c deleted file mode 100644 index 4dfcfd18..00000000 --- a/server/ents/g_tracktrain.c +++ /dev/null @@ -1,2021 +0,0 @@ -#include "g_local.h" - -#define RFAST -3 -#define RMEDIUM -2 -#define RSLOW -1 -#define STOP 0 -#define SLOW 1 -#define MEDIUM 2 -#define FAST 3 - -// func_tracktrain spawnflags -#define SF_TRACKTRAIN_NOPITCH 0x0001 // pitch angle doesn't change with track pitch -#define SF_TRACKTRAIN_NOCONTROL 0x0002 // no player control -#define SF_TRACKTRAIN_ONEWAY 0x0004 // cannot back up -#define SF_TRACKTRAIN_OTHERMAP 0x0008 // "parent" train resides in another map -#define SF_TRACKTRAIN_NOHUD 0x0010 // do not display speed on HUD -#define SF_TRACKTRAIN_INDICATOR 0x0020 // train has an animated speed indicator -#define SF_TRACKTRAIN_ANIMATED 0x0040 // normal animation -#define SF_TRACKTRAIN_STARTOFF 0x0080 // starts disabled -#define SF_TRACKTRAIN_DISABLED 0x1000 // internal use only -#define SF_TRACKTRAIN_ROLLSPEED 0x2000 // internal use only - roll is a function of speed -#define SF_TRACKTRAIN_SLOWSTOP 0x4000 // internal use only - train slows to stop after driver death -#define SF_TRACKTRAIN_ANIMMASK (SF_TRACKTRAIN_INDICATOR | SF_TRACKTRAIN_ANIMATED) -// path_track spawnflags -#define SF_PATH_ALTPATH 0x0001 // branch point -#define SF_PATH_DISABLED 0x0002 -#define SF_PATH_FIREONCE 0x0004 // pathtarget fired only once -#define SF_PATH_DISABLE_TRAIN 0x0008 // player loses control of train -#define SF_PATH_ABS_SPEED 0x0010 // speed modifier is absolute rather than a multiplier - -void tracktrain_next (edict_t *self); -void tracktrain_reach_dest (edict_t *self); - -/*============================================================================= - -Utility functions shamelessly ripped from HL source - -===============================================================================*/ -float UTIL_AngleMod(float a) -{ - if (a < 0) - { - a = a + 360 * ((int)(a / 360) + 1); - } - else if (a >= 360) - { - a = a - 360 * ((int)(a / 360)); - } - // a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); - return a; -} - -float UTIL_ApproachAngle( float target, float value, float speed ) -{ - float delta; - - target = UTIL_AngleMod( target ); - value = UTIL_AngleMod( target ); - - delta = target - value; - - // Speed is assumed to be positive - if ( speed < 0 ) - speed = -speed; - - if ( delta < -180 ) - delta += 360; - else if ( delta > 180 ) - delta -= 360; - - if ( delta > speed ) - value += speed; - else if ( delta < -speed ) - value -= speed; - else - value = target; - - return value; -} - - -float UTIL_AngleDistance( float next, float cur ) -{ - float delta = next - cur; - - if ( delta < -180 ) - delta += 360; - else if ( delta > 180 ) - delta -= 360; - - return delta; -} - -/*============================================================================= - -PATH_TRACK - -target: next path_track -target2: alternate path -speed: new tracktrain speed -pathtarget: entity to trigger when touched -deathtarget: entity to trigger at dead end - -==============================================================================*/ - -void path_track_use (edict_t *self, edict_t *other, edict_t *activator) -{ - char *temp; - - if(self->spawnflags & SF_PATH_ALTPATH) - { - temp = self->target; - self->target = self->target2; - self->target2 = temp; - } - else - { - // toggle enabled/disabled - self->spawnflags ^= SF_PATH_DISABLED; - } -} - -void SP_path_track (edict_t *self) -{ - if (!self->targetname) - { - gi.dprintf ("%s with no targetname at %s\n", self->classname,vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_PATH_TRACK; - self->solid = SOLID_TRIGGER; - self->use = path_track_use; - VectorSet (self->mins, -8, -8, -8); - VectorSet (self->maxs, 8, 8, 8); - self->svflags |= SVF_NOCLIENT; - if(!self->count) self->count = -1; - gi.linkentity (self); -} - -/* ============================================================ - -FUNC_TRACKCHANGE - -height = Travel altitude (viewheight) -distance = Rotation amount, degrees (moveinfo.distance) -target = Name of train -pathtarget = Top path_track -combattarget = Bottom path_track -speed = Move/Rotate speed - -=============================================================*/ - -#define STATE_TOP 0 -#define STATE_MOVEDOWN 1 -#define STATE_BOTTOM 2 -#define STATE_MOVEUP 3 - -#define SF_TRACK_ACTIVATETRAIN 0x0001 -#define SF_TRACK_STARTBOTTOM 0x0008 -#define SF_TRACK_XAXIS 0x0040 -#define SF_TRACK_YAXIS 0x0080 - - -void trackchange_done (edict_t *self) -{ - edict_t *train = self->target_ent; - - VectorClear(self->velocity); - VectorClear(self->avelocity); - if (self->s.sound && self->moveinfo.sound_end) - gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->moveinfo.sound_end, 1, ATTN_NORM, 0); - self->s.sound = 0; - - if(train) - { - VectorClear(train->velocity); - VectorClear(train->avelocity); - train->spawnflags &= ~SF_TRACKTRAIN_DISABLED; - if(self->spawnflags & SF_TRACK_ACTIVATETRAIN) - { - train->moveinfo.state = train->moveinfo.prevstate; - if(train->moveinfo.state && (train->sounds > 0)) - train->s.sound = gi.soundindex(va("%sspeed%d.wav",train->source,abs(train->moveinfo.state))); - train->moveinfo.next_speed = train->moveinfo.state * train->moveinfo.speed/3; - } - else - { // A little redundant, but clear - train->moveinfo.state = STOP; - train->moveinfo.next_speed = 0; - } - if(self->moveinfo.state == STATE_MOVEUP) - train->target = self->pathtarget; - else - train->target = self->combattarget; - train->target_ent = G_PickTarget(train->target); - // If map is constructed properly, train - // SHOULD be at the target path_track now. But - // physics may have caused lift to outrun train, - // so force it: - VectorCopy(train->target_ent->s.origin,train->s.origin); - train->s.origin[2] += train->viewheight; - gi.linkentity(train); - tracktrain_next(train); - } - if(self->moveinfo.state == STATE_MOVEDOWN) - self->moveinfo.state = STATE_BOTTOM; - else - self->moveinfo.state = STATE_TOP; - gi.linkentity(self); -} - -void trackchange_use (edict_t *self, edict_t *other, edict_t *activator) -{ - float time, tt, tr; - float tspeed, rspeed; - - if((self->moveinfo.state != STATE_TOP) && (self->moveinfo.state != STATE_BOTTOM)) - { - // already moving - return; - } - - if(self->target) - { - edict_t *track; - - self->target_ent = G_PickTarget(self->target); - if(self->target_ent) - { - // Make sure this sucker is at the path_track it's supposed to - // be at - if(self->moveinfo.state == STATE_BOTTOM) - track = G_PickTarget(self->combattarget); - else - track = G_PickTarget(self->pathtarget); - if(!track || (self->target_ent->target_ent != track)) - self->target_ent = NULL; - else - { - vec3_t v; - VectorSubtract(track->s.origin,self->target_ent->s.origin,v); - if(VectorLength(v) > self->target_ent->moveinfo.distance) - self->target_ent = NULL; - } - } - } - else - self->target_ent = NULL; - - if(self->target_ent) - self->target_ent->s.sound = 0; - - // Adjust speed so that "distance" rotation and "height" movement are achieved - // simultaneously. - tt = fabs(self->viewheight) / self->speed; - tr = fabs(self->moveinfo.distance) / self->speed; - time = max(tt,tr); - time = 0.1 * ((int)(10.*time-0.5)+1); - tspeed = -self->viewheight / time; - rspeed = self->moveinfo.distance / time; - if(self->moveinfo.state == STATE_BOTTOM) - { - tspeed = -tspeed; - rspeed = -rspeed; - } - VectorClear(self->velocity); - VectorClear(self->avelocity); - if (self->spawnflags & SF_TRACK_XAXIS) - self->velocity[0] = tspeed; - else if (self->spawnflags & SF_TRACK_YAXIS) - self->velocity[1] = tspeed; - else - self->velocity[2] = tspeed; - - VectorScale(self->movedir,rspeed,self->avelocity); - - if(self->target_ent) - { - VectorCopy(self->velocity,self->target_ent->velocity); - VectorCopy(self->avelocity,self->target_ent->avelocity); - self->target_ent->spawnflags |= SF_TRACKTRAIN_DISABLED; - gi.linkentity(self->target_ent); - } - - if(self->moveinfo.state == STATE_TOP) - self->moveinfo.state = STATE_MOVEDOWN; - else - self->moveinfo.state = STATE_MOVEUP; - - if (self->moveinfo.sound_start) - gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->moveinfo.sound_start, 1, ATTN_NORM, 0); - self->s.sound = self->moveinfo.sound_middle; - - self->think = trackchange_done; - self->nextthink = level.time + time; - gi.linkentity(self); -} - -void SP_func_trackchange (edict_t *self) -{ - self->class_id = ENTITY_FUNC_TRACKCHANGE; - self->movetype = MOVETYPE_PUSH; - VectorClear (self->s.angles); - - // set the axis of rotation - VectorClear(self->movedir); - if (self->spawnflags & SF_TRACK_XAXIS) - self->movedir[2] = 1.0; - else if (self->spawnflags & SF_TRACK_YAXIS) - self->movedir[0] = 1.0; - else // Z_AXIS - self->movedir[1] = 1.0; - - // Rotation - self->moveinfo.distance = st.distance; - - // Travel height - self->viewheight = st.height; - - // Max rotation/translation speed - if(!self->speed) - self->speed = 100; - - VectorCopy(self->s.origin,self->pos1); - VectorCopy(self->pos1,self->pos2); - if (self->spawnflags & SF_TRACK_XAXIS) - self->pos2[0] -= self->viewheight; - else if (self->spawnflags & SF_TRACK_YAXIS) - self->pos2[1] -= self->viewheight; - else - self->pos2[2] -= self->viewheight; - - self->solid = SOLID_BSP; - gi.setmodel (self, self->model); - self->use = trackchange_use; - - // bottom starters: - if(self->spawnflags & SF_TRACK_STARTBOTTOM) - { - vec3_t temp; - VectorCopy(self->pos1,temp); - VectorCopy(self->pos2,self->pos1); - VectorCopy(temp,self->pos2); - VectorCopy(self->pos1,self->s.origin); - VectorMA(self->s.angles,self->moveinfo.distance,self->movedir,self->s.angles); - self->moveinfo.state = STATE_BOTTOM; - } - else - self->moveinfo.state = STATE_TOP; - - self->moveinfo.sound_start = gi.soundindex ("plats/pt1_strt.wav"); - self->moveinfo.sound_middle = gi.soundindex ("plats/pt1_mid.wav"); - self->moveinfo.sound_end = gi.soundindex ("plats/pt1_end.wav"); - - gi.linkentity(self); - -} - - -/*===================================================================================== -func_tracktrain - -target first path_track stop -dmg damage applied to blocker -speed max. speed, default=64 -sounds currently unused -distance wheelbase, determines turn rate. default=50 -height height of origin above path_tracks, default=4 -roll roll angle while turning, default=0 -*/ -void tracktrain_think (edict_t *self); -void tracktrain_drive (edict_t *train, edict_t *other ) -{ - vec3_t angles, offset; - vec3_t f1, l1, u1; - vec3_t forward, left; - - if (!(other->svflags & SVF_MONSTER)) - return; - - if(train->spawnflags & (SF_TRACKTRAIN_NOCONTROL | SF_TRACKTRAIN_STARTOFF)) - return; - - // See if monster is in driving position - VectorCopy(train->s.angles,angles); - VectorNegate(angles,angles); - AngleVectors(angles,f1,l1,u1); - - VectorSubtract(other->s.origin,train->s.origin,offset); - VectorScale(f1, offset[0],f1); - VectorScale(l1,-offset[1],l1); - VectorScale(u1, offset[2],u1); - VectorCopy(f1,offset); - VectorAdd(offset,l1,offset); - VectorAdd(offset,u1,offset); - - // Relax the constraints on driving position just a bit for monsters - - if(offset[0] < train->bleft[0] - 16) - return; - if(offset[1] < train->bleft[1] - 16) - return; - if(offset[2] < train->bleft[2] - 16) - return; - if(offset[0] > train->tright[0] + 16) - return; - if(offset[1] > train->tright[1] + 16) - return; - if(offset[2] > train->tright[2] + 16) - return; - - train->owner = other; - other->vehicle = train; - - // Store the offset and later keep driver at same relative position - // (with height adjustments for pitch) - AngleVectors(train->s.angles, forward, left, NULL); - VectorSubtract(other->s.origin,train->s.origin,train->offset); - VectorScale(forward,train->offset[0],f1); - VectorScale(left,train->offset[1],l1); - VectorCopy(f1,train->offset); - VectorAdd(train->offset,l1,train->offset); - train->offset[1] = -train->offset[1]; - train->offset[2] = other->s.origin[2] - train->s.origin[2]; - gi.linkentity(other); - gi.linkentity(train); - - other->monsterinfo.pausetime = level.time + 100000000; - other->monsterinfo.aiflags |= AI_STAND_GROUND; - other->monsterinfo.stand (other); - - train->moveinfo.state = FAST; - train->moveinfo.next_speed = train->moveinfo.speed; - if(train->sounds) - train->s.sound = gi.soundindex(va("%sspeed%d.wav",train->source,abs(train->moveinfo.state))); - else - train->s.sound = 0; - train->think = tracktrain_think; - train->think(train); - -} - -void tracktrain_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - if(self->deathtarget) - { - self->target = self->deathtarget; - G_UseTargets (self, attacker); - } - BecomeExplosion1 (self); -} - -void tracktrain_disengage (edict_t *train) -{ - edict_t *driver; - - driver = train->owner; - if(!driver) return; - - if(driver->client) - { - vec3_t forward, left, up, f1, l1, u1; - - driver->movetype = MOVETYPE_WALK; - AngleVectors(train->s.angles, forward, left, up); - VectorScale(forward,train->offset[0],f1); - VectorScale(left,-train->offset[1],l1); - VectorScale(up,train->offset[2],u1); - VectorAdd(train->s.origin,f1,driver->s.origin); - VectorAdd(driver->s.origin,l1,driver->s.origin); - VectorAdd(driver->s.origin,u1,driver->s.origin); - driver->s.origin[2] += 16 * ( fabs(up[0]) + fabs(up[1]) ); - VectorCopy(train->velocity,driver->velocity); - driver->client->vehicle_framenum = level.framenum; - // turn ON client side prediction for this player - driver->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - } - else - { - if(train->moveinfo.state != STOP) - { - train->spawnflags |= SF_TRACKTRAIN_SLOWSTOP; - train->moveinfo.state = STOP; - train->moveinfo.next_speed = 0; - train->s.sound = gi.soundindex(va("%sspeed1.wav",train->source)); - } - - driver->movetype = MOVETYPE_STEP; - if(driver->health > 0) - { - VectorCopy(train->velocity,driver->velocity); - } - else - { - VectorClear(driver->velocity); - } - driver->monsterinfo.pausetime = 0; - driver->monsterinfo.aiflags &= ~AI_STAND_GROUND; - } - gi.linkentity (driver); - - train->owner = NULL; - driver->vehicle = NULL; -} - -void tracktrain_hide (edict_t *self) -{ - self->solid = SOLID_NOT; - self->svflags |= SVF_NOCLIENT; - gi.linkentity(self); -} - -void tracktrain_think (edict_t *self) -{ - float distance, speed, time; - float yaw, pitch; - vec3_t forward, left, up, f1, l1, u1, v; - int i; - edict_t *ent; - - if(self->spawnflags & SF_TRACKTRAIN_OTHERMAP) - { - if( (self->spawnflags & SF_TRACKTRAIN_INDICATOR) && !(self->spawnflags & SF_TRACKTRAIN_ANIMATED)) - self->s.frame = 6; - else - self->s.effects &= ~(EF_ANIM_ALL | EF_ANIM_ALLFAST); - self->spawnflags |= SF_TRACKTRAIN_DISABLED; - self->think = tracktrain_hide; - self->nextthink = level.time + FRAMETIME; - VectorClear(self->velocity); - VectorClear(self->avelocity); - self->moveinfo.state = self->moveinfo.prevstate = STOP; - self->s.sound = 0; - self->moveinfo.current_speed = 0; - self->owner = NULL; - gi.linkentity(self); - return; - } - - self->nextthink = level.time + FRAMETIME; - - if(!self->owner && (self->spawnflags & SF_TRACKTRAIN_DISABLED)) - return; - - if(self->spawnflags & SF_TRACKTRAIN_ANIMATED) - { - if(self->moveinfo.state) - { - if(self->spawnflags & SF_TRACKTRAIN_INDICATOR) - self->s.effects |= EF_ANIM_ALLFAST; - else - self->s.effects |= EF_ANIM_ALL; - } - else - self->s.effects &= ~(EF_ANIM_ALL | EF_ANIM_ALLFAST); - } - else if(self->spawnflags & SF_TRACKTRAIN_INDICATOR) - { - if((self->moveinfo.state == STOP) && !self->owner) - { - if(self->spawnflags & SF_TRACKTRAIN_STARTOFF) - self->s.frame = 14; - else - self->s.frame = 6; - } - else if((level.framenum % 5) == 0) - self->s.frame = (self->moveinfo.state - RFAST)*2 + (1 - (self->s.frame % 2)); - } - - AngleVectors(self->s.angles, forward, left, up); - - if(!(self->spawnflags & SF_TRACKTRAIN_DISABLED)) - { - VectorCopy(self->velocity,v); - speed = VectorLength(v); - if(self->moveinfo.state < STOP) - speed = -speed; - self->moveinfo.current_speed = speed; - if(self->moveinfo.state != STOP) - self->moveinfo.prevstate = self->moveinfo.state; - } - - if (self->owner) - { - edict_t *driver = self->owner; - - // ... then we have a driver - if ((driver->health <= 0) || (driver->movetype == MOVETYPE_NOCLIP)) - { - tracktrain_disengage(self); - return; - } - if (driver->client) - { - if (driver->client->use) - { - // if he's pressing the use key, and he didn't just - // get on or off, disengage - if(level.framenum - driver->client->vehicle_framenum > 2) - { - VectorCopy(self->velocity,driver->velocity); - tracktrain_disengage(self); - return; - } - } - if ( (driver->client->ucmd.sidemove < -199) || (driver->client->ucmd.sidemove > 199) || (driver->client->ucmd.upmove > 0) ) - { - VectorCopy(self->velocity,driver->velocity); - tracktrain_disengage(self); - return; - } - } - if (!(self->spawnflags & SF_TRACKTRAIN_DISABLED)) - { - if (driver->client) - { - if ((driver->client->ucmd.forwardmove > -199) && (driver->client->ucmd.forwardmove < 199)) - self->moveinfo.wait = 0; - else if(!self->moveinfo.wait) - { - if(driver->client->ucmd.forwardmove > 0) - { - if(self->moveinfo.state < FAST) - { - self->moveinfo.state++; - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - self->moveinfo.wait = 1; - if((self->spawnflags & SF_TRACKTRAIN_ANIMMASK) == SF_TRACKTRAIN_INDICATOR) - self->s.frame = (self->moveinfo.state - RFAST)*2 + (1 - (self->s.frame % 2)); - if(self->moveinfo.state && (self->sounds > 0)) - self->s.sound = gi.soundindex(va("%sspeed%d.wav",self->source,abs(self->moveinfo.state))); - else - self->s.sound = 0; - } - } - else - { - if( (self->moveinfo.state > STOP) || - ((self->moveinfo.state > RFAST) && !(self->spawnflags & SF_TRACKTRAIN_ONEWAY))) - { - self->moveinfo.state--; - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - self->moveinfo.wait = 1; - if((self->spawnflags & SF_TRACKTRAIN_ANIMMASK) == SF_TRACKTRAIN_INDICATOR) - self->s.frame = (self->moveinfo.state - RFAST)*2 + (1 - (self->s.frame % 2)); - if(self->moveinfo.state && (self->sounds > 0)) - self->s.sound = gi.soundindex(va("%sspeed%d.wav",self->source,abs(self->moveinfo.state))); - else - self->s.sound = 0; - } - } - } - } - else - { - // Driver is monster. - if(driver->enemy && driver->enemy->inuse) - { - bool vis; - - vis = visible(driver,driver->enemy); - - if(vis) - self->monsterinfo.search_time = 0; - - if(self->monsterinfo.search_time == 0) - { - float dot, r; - vec3_t vec; - - if(vis) - { - VectorSubtract(driver->enemy->s.origin,driver->s.origin,vec); - } - else - { - VectorSubtract(driver->monsterinfo.last_sighting,driver->s.origin,vec); - } - r = VectorNormalize(vec); - dot = DotProduct(vec,forward); - if((r > 2000) && (dot < 0)) - { - self->moveinfo.state = -self->moveinfo.state; - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - self->monsterinfo.search_time = level.time; - tracktrain_next(self); - return; - } - } - } - } - // Check for change in direction - if( self->moveinfo.prevstate < STOP && self->moveinfo.state > STOP ) - { - self->moveinfo.prevstate = self->moveinfo.state; - tracktrain_next(self); - return; - } - else if(self->moveinfo.prevstate > STOP && self->moveinfo.state < STOP) - { - self->moveinfo.prevstate = self->moveinfo.state; - tracktrain_next(self); - return; - } - - if(self->moveinfo.current_speed < self->moveinfo.next_speed) - { - speed = self->moveinfo.current_speed + self->moveinfo.accel/10; - if(speed > self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - else if(self->moveinfo.current_speed > self->moveinfo.next_speed) - { - speed = self->moveinfo.current_speed - self->moveinfo.decel/10; - if(speed < self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - - VectorSubtract(self->moveinfo.end_origin,self->s.origin,v); - distance = VectorLength(v); - if(speed != 0) - { - time = distance/fabs(speed); - time = 0.1 * ((int)(10*time - 0.5)+1); - if( (time > 0) && (distance > 0) ) - speed = distance/time; - } - else - time = 100000; - VectorNormalize(v); - VectorScale(v,fabs(speed),self->velocity); - - // gi.dprintf("distance to %s=%g, time=%g\n", - // self->target_ent->targetname,distance,time); - - gi.linkentity(self); - } - - // Set driver velocity, position, and angles - VectorCopy(self->velocity,driver->velocity); - - VectorScale(forward,self->offset[0],f1); - VectorScale(left,-self->offset[1],l1); - VectorScale(up,self->offset[2],u1); - VectorAdd(self->s.origin,f1,driver->s.origin); - VectorAdd(driver->s.origin,l1,driver->s.origin); - VectorAdd(driver->s.origin,u1,driver->s.origin); - driver->s.origin[2] += 16 * ( fabs(up[0]) + fabs(up[1]) ); - - yaw = self->avelocity[YAW]*FRAMETIME; - if(yaw != 0) - { - driver->s.angles[YAW] += yaw; - if(driver->client) - { - driver->client->ps.pmove.delta_angles[YAW] += ANGLE2SHORT(yaw); - driver->client->ps.viewangles[YAW] += yaw; - } - } - pitch = self->avelocity[PITCH]*FRAMETIME; - if(pitch != 0) - { - float delta_yaw; - - delta_yaw = driver->s.angles[YAW] - self->s.angles[YAW]; - delta_yaw *= M_PI / 180.; - pitch *= cos(delta_yaw); - if(driver->client) - { - driver->client->ps.pmove.delta_angles[PITCH] += ANGLE2SHORT(pitch); - driver->client->ps.viewangles[PITCH] += pitch; - } - } - if((self->moveinfo.state != STOP) || (yaw != 0) || (pitch != 0)) - if(driver->client) - driver->client->ps.pmove.pm_type = PM_FREEZE; - - gi.linkentity(driver); - - } - else if(self->spawnflags & (SF_TRACKTRAIN_NOCONTROL | SF_TRACKTRAIN_STARTOFF)) - { - // No driver, either can't be controlled or is "off" - - if (!(self->spawnflags & SF_TRACKTRAIN_DISABLED)) - { - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - - if(self->moveinfo.current_speed < self->moveinfo.next_speed) - { - speed = self->moveinfo.current_speed + self->moveinfo.accel/10; - if(speed > self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - else if(self->moveinfo.current_speed > self->moveinfo.next_speed) - { - speed = self->moveinfo.current_speed - self->moveinfo.decel/10; - if(speed < self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - - if(speed != 0) - { - VectorSubtract(self->moveinfo.end_origin,self->s.origin,v); - distance = VectorLength(v); - time = distance/fabs(speed); - time = 0.1 * ((int)(10*time - 0.5)+1); - if( (time > 0) && (distance > 0) ) - speed = distance/time; - VectorNormalize(v); - VectorScale(v,fabs(speed),self->velocity); - gi.linkentity(self); - } - - if( !(self->spawnflags & SF_TRACKTRAIN_NOCONTROL) && - (self->spawnflags & SF_TRACKTRAIN_STARTOFF) && - self->viewmessage ) - { - vec3_t angles, offset; - - // Check for player entering bleft/tright field of train - VectorCopy(self->s.angles,angles); - VectorNegate(angles,angles); - AngleVectors(angles,f1,l1,u1); - for (i=1, ent=&g_edicts[1] ; i<=maxclients->value ; i++, ent++) - { - if (!ent->inuse) continue; - if (ent->movetype == MOVETYPE_NOCLIP) continue; - VectorSubtract(ent->s.origin,self->s.origin,offset); - VectorScale(f1, offset[0],f1); - VectorScale(l1,-offset[1],l1); - VectorScale(u1, offset[2],u1); - VectorCopy(f1,offset); - VectorAdd(offset,l1,offset); - VectorAdd(offset,u1,offset); - if(offset[0] < self->bleft[0]) - continue; - if(offset[1] < self->bleft[1]) - continue; - if(offset[2] < self->bleft[2]) - continue; - if(offset[0] > self->tright[0]) - continue; - if(offset[1] > self->tright[1]) - continue; - if(offset[2] > self->tright[2]) - continue; - - gi.centerprintf(ent,"%s",self->viewmessage); - self->viewmessage = NULL; - } - } - - if(!speed) - { - if(self->viewmessage) - time = 100000; - else - { - VectorClear(self->avelocity); - VectorClear(self->avelocity); - self->nextthink = 0; - if(self->movewith_next && (self->movewith_next->movewith_ent == self)) - set_child_movement(self); - gi.linkentity(self); - return; - } - } - } - } - else - { - // - // No driver, CAN be controlled and isn't currently turned off - // - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - if(self->moveinfo.current_speed < self->moveinfo.next_speed) - { - if(self->spawnflags & SF_TRACKTRAIN_SLOWSTOP) - speed = self->moveinfo.current_speed + self->moveinfo.accel/25; - else - speed = self->moveinfo.current_speed + self->moveinfo.accel/10; - if(speed > self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - else if(self->moveinfo.current_speed > self->moveinfo.next_speed) - { - if(self->spawnflags & SF_TRACKTRAIN_SLOWSTOP) - speed = self->moveinfo.current_speed - self->moveinfo.decel/25; - else - speed = self->moveinfo.current_speed - self->moveinfo.decel/10; - if(speed < self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - - if( speed != 0 ) - { - VectorSubtract(self->moveinfo.end_origin,self->s.origin,v); - distance = VectorNormalize(v); - time = distance/fabs(speed); - time = 0.1 * ((int)(10*time - 0.5)+1); - if( (time > 0) && (distance > 0) ) - speed = distance/time; - VectorScale(v,fabs(speed),self->velocity); - gi.linkentity(self); - } - else if(self->moveinfo.current_speed != 0) - { - VectorClear(self->velocity); - self->s.sound = 0; - gi.linkentity(self); - time = 100000; - } - else - { - self->spawnflags &= ~SF_TRACKTRAIN_SLOWSTOP; - time = 100000; - } - - if(!(self->spawnflags & SF_TRACKTRAIN_NOCONTROL)) - { - vec3_t angles, offset; - - // Check if a player is in driving position (monsters handled elsewhere) - - VectorCopy(self->s.angles,angles); - VectorNegate(angles,angles); - AngleVectors(angles,f1,l1,u1); - - // find a player - for (i=1, ent=&g_edicts[1] ; i<=maxclients->value ; i++, ent++) { - if (!ent->inuse) continue; - if (ent->movetype == MOVETYPE_NOCLIP) continue; - if (!ent->client->use && !self->message) continue; - if (level.framenum - ent->client->vehicle_framenum <= 2) continue; - - VectorSubtract(ent->s.origin,self->s.origin,offset); - VectorScale(f1, offset[0],f1); - VectorScale(l1,-offset[1],l1); - VectorScale(u1, offset[2],u1); - VectorCopy(f1,offset); - VectorAdd(offset,l1,offset); - VectorAdd(offset,u1,offset); -// gi.dprintf("offset=%g %g %g\n",offset[0],offset[1],offset[2]); - if(offset[0] < self->bleft[0]) - continue; - if(offset[1] < self->bleft[1]) - continue; - if(offset[2] < self->bleft[2]) - continue; - if(offset[0] > self->tright[0]) - continue; - if(offset[1] > self->tright[1]) - continue; - if(offset[2] > self->tright[2]) - continue; - - if(self->message) - { - gi.centerprintf(ent,"%s",self->message); - self->message = NULL; - } - if (!ent->client->use) continue; - - // Got a driver! - ent->client->vehicle_framenum = level.framenum; - self->owner = ent; - ent->vehicle = self; - // turn off client side prediction for this player - ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - - // Store the offset and later keep driver at same relative position - // (with height adjustments for pitch) - VectorSubtract(ent->s.origin,self->s.origin,self->offset); - VectorScale(forward,self->offset[0],f1); - VectorScale(left,self->offset[1],l1); - VectorCopy(f1,self->offset); - VectorAdd(self->offset,l1,self->offset); - self->offset[1] = -self->offset[1]; - self->offset[2] = ent->s.origin[2] - self->s.origin[2]; - gi.linkentity(ent); - self->moveinfo.wait = 1; - gi.linkentity(self); - } - } - } - if(self->movewith_next && (self->movewith_next->movewith_ent == self)) - set_child_movement(self); - - if( (time < 1.5*FRAMETIME) && !(self->spawnflags & SF_TRACKTRAIN_DISABLED)) - self->think = tracktrain_reach_dest; -} - -void tracktrain_blocked (edict_t *self, edict_t *other) -{ - vec3_t dir; - int knockback; - - // Correct owner's velocity - if (self->owner) - { - edict_t *driver = self->owner; - vec3_t forward, left, up; - vec3_t f1, l1, u1; - VectorCopy(self->velocity, driver->velocity); - AngleVectors(self->s.angles,forward,left,up); - VectorScale(forward,self->offset[0],f1); - VectorScale(left,-self->offset[1],l1); - VectorScale(up,self->offset[2],u1); - VectorAdd(self->s.origin,f1,driver->s.origin); - VectorAdd(driver->s.origin,l1,driver->s.origin); - VectorAdd(driver->s.origin,u1,driver->s.origin); - driver->s.origin[2] += 16 * ( fabs(up[0]) + fabs(up[1]) ); - gi.linkentity(driver); - } - VectorSubtract(other->s.origin,self->s.origin,dir); - dir[2] += 16; - VectorNormalize(dir); - if (!(other->svflags & SVF_MONSTER) && (!other->client) ) - { - // give it a chance to go away on it's own terms (like gibs) - T_Damage (other, self, self, dir, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - // if it's still there, nuke it - if (other) - { - // Some of our ents don't have origin near the model - vec3_t save; - VectorCopy(other->s.origin,save); - VectorMA (other->absmin, 0.5, other->size, other->s.origin); - BecomeExplosion1 (other); - } - return; - } - - if (level.time < self->touch_debounce_time) - return; - - if (!self->dmg) - return; - - if(other->client && (other->groundentity == self)) - { - // Don't cream riders who've become embedded - just do minor damage - // and *maybe* help them get unstuck by pushing them up. - knockback = 2; - VectorSet(dir,0,0,1); - T_Damage (other, self, self, dir, other->s.origin, vec3_origin, 1, knockback, 0, MOD_CRUSH); - } - else - { - knockback = (int)(fabs(self->moveinfo.current_speed) * other->mass / 300.); - T_Damage (other, self, self, dir, other->s.origin, vec3_origin, self->dmg, knockback, 0, MOD_CRUSH); - } - self->touch_debounce_time = level.time + 0.5; -} - -void tracktrain_reach_dest (edict_t *self) -{ - edict_t *path = self->target_ent; - - if (path && path->pathtarget) - { - char *savetarget; - - savetarget = path->target; - path->target = path->pathtarget; - if(self->owner) - G_UseTargets (path, self->owner); - else - G_UseTargets (path, self); - path->target = savetarget; - - // make sure we didn't get killed by a killtarget - if (!self->inuse) - return; - if(path->spawnflags & SF_PATH_FIREONCE) - path->pathtarget = NULL; - } - - if(path && (path->spawnflags & SF_PATH_DISABLE_TRAIN)) - { - self->spawnflags |= SF_TRACKTRAIN_NOCONTROL; - if(self->owner) - tracktrain_disengage(self); - } - if(path && path->speed) - { - if(path->spawnflags & SF_PATH_ABS_SPEED) - { - self->moveinfo.speed = path->speed; - self->moveinfo.next_speed = self->moveinfo.speed; - self->moveinfo.state = (self->moveinfo.state >= STOP ? FAST : RFAST); - } - else - { - self->moveinfo.speed = path->speed * self->speed; - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - } - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - } - tracktrain_next (self); -} - -bool is_backing_up (edict_t *train) -{ - vec3_t forward, v_norm; - - VectorCopy(train->velocity,v_norm); - VectorNormalize(v_norm); - AngleVectors(train->s.angles,forward,NULL,NULL); - if(DotProduct(forward,v_norm) < 0.) - return true; - else - return false; -} - -edict_t *NextPathTrack(edict_t *train, edict_t *path) -{ - edict_t *next=NULL; - vec3_t forward; - vec3_t to_next; - bool in_reverse; - - AngleVectors(train->s.angles,forward,NULL,NULL); - - if( (train->moveinfo.prevstate < STOP && train->moveinfo.state > STOP) || - (train->moveinfo.prevstate > STOP && train->moveinfo.state < STOP) ) - { - next = path->prevpath; - if(next) - { - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - if((train->moveinfo.state > STOP) && (DotProduct(forward,to_next) < 0)) - next = NULL; - else if((train->moveinfo.state < STOP) && (DotProduct(forward,to_next) > 0)) - next = NULL; - else - { - next->prevpath = path; - return next; - } - } - } - - if(train->moveinfo.state == STOP) - { - if(is_backing_up(train)) - in_reverse = true; - else - in_reverse = false; - } - else - in_reverse = (train->moveinfo.state < STOP ? true : false); - - if(in_reverse) - { - if(path->spawnflags & SF_PATH_ALTPATH) - { - next = G_PickTarget (path->target); - if(next) - { - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - if(DotProduct(forward,to_next) > 0) - next = NULL; - } - } - - if(!next) - { - next = path->prevpath; - - if(next) - { - // Ensure we don't flipflop - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - if(DotProduct(forward,to_next) > 0) - next = NULL; - } - - if(!next) - { - // Find path_track whose target or target2 is set to - // the current path_track - edict_t *e; - int i; - for(i=maxclients->value; iinuse) - continue; - if(e==path) - continue; - if(!e->classname) - continue; - if(e->class_id != ENTITY_PATH_TRACK) - continue; - if(e->target && !strcasecmp(e->target,path->targetname)) - { - next = e; - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - if(DotProduct(forward,to_next) > 0) - next = NULL; -// else -// path->prevpath = next; - } - if(!next && e->target2 && !strcasecmp(e->target2,path->targetname)) - { - next = e; - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - if(DotProduct(forward,to_next) > 0) - next = NULL; -// else -// path->prevpath = next; - } - } - } - - if (!next) - { - float dot; - - // Finally, check this path_track's target and target2 - if(path->target) - { - next = G_PickTarget (path->target); - if(next) - { - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - dot = DotProduct(forward,to_next); - if(dot > 0) - next = NULL; - } - } - if(path->target2 && !(path->spawnflags & SF_PATH_ALTPATH)) - { - edict_t *next2; - float dot2; - - next2 = G_PickTarget (path->target2); - if( next2 == path ) - next2 = NULL; - - if(next2) - { - VectorSubtract(next2->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - dot2 = DotProduct(forward,to_next); - if(dot2 > 0) - next2 = NULL; - else if(!next) - { - next = next2; - next2 = NULL; - } - } - - if((next && next2) && (dot2 < dot)) - next = next2; - } - } - } - } - else // Moving forward - { - float dot; - - if(path->target) - { - next = G_PickTarget (path->target); - if(next) - { - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - dot = DotProduct(forward,to_next); - if(dot < 0) - next = NULL; - } - } - if(path->target2 && !(path->spawnflags & SF_PATH_ALTPATH)) - { - edict_t *next2; - float dot2; - - next2 = G_PickTarget (path->target2); - if( next2 == path ) - next2 = NULL; - - if(next2) - { - VectorSubtract(next2->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - dot2 = DotProduct(forward,to_next); - if(dot2 < 0) - next2 = NULL; - else if(!next) - { - next = next2; - next2 = NULL; - } - } - - if((next && next2) && (dot2 > dot)) - next = next2; - } - if(next == path) - next = NULL; - - if(!next) - { // Check for path_tracks that target (or target2) this path_track. - edict_t *e; - int i; - for(i=maxclients->value; iinuse) - continue; - if(e==path) - continue; - if(!e->classname) - continue; - if(e->class_id != ENTITY_PATH_TRACK) - continue; - if(e->target && !strcasecmp(e->target,path->targetname)) - { - next = e; - VectorSubtract(next->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - dot = DotProduct(forward,to_next); - if(dot < 0) - next = NULL; - } - if(e->target2 && !strcasecmp(e->target2,path->targetname)) - { - edict_t *next2; - float dot2; - - next2 = e; - VectorSubtract(next2->s.origin,path->s.origin,to_next); - VectorNormalize(to_next); - dot2 = DotProduct(forward,to_next); - if(dot2 < 0) - next2 = NULL; - else if(!next) - { - next = next2; - next2 = NULL; - } - if((next && next2) && (dot2 > dot)) - next = next2; - } - } - } -// if(next) -// next->prevpath = path; - - } - if(developer->value) - gi.dprintf("prev=%s, current=%s, next=%s\n", - (path->prevpath ? path->prevpath->targetname : "nada"), - path->targetname, - (next ? next->targetname : "nada")); - - if(next) - next->prevpath = path; - return next; -} - -void LookAhead( edict_t *train, vec3_t point, float dist ) -{ - float originalDist = dist; - float length; - vec3_t v; - edict_t *path; - int n=0; - - path = train->target_ent; - if(!path || dist < 0) - return; - - while ( dist > 0 ) - { - n++; - if(n>20) - { - gi.dprintf("WTF??? n=%d\n",n); - return; - } - - VectorSubtract(path->s.origin,point,v); - length = VectorLength(v); - if(length >= dist) - { - VectorMA(point,dist/length,v,point); - return; - } - dist -= length; - VectorCopy(path->s.origin,point); - - // Don't go past a switch -/* if(path->spawnflags & SF_PATH_ALTPATH) - { - return; - } */ - path = NextPathTrack(train,path); - if(!path) - return; - } -} - -void train_angles(edict_t *train) -{ - vec3_t v, angles; - - VectorCopy(train->s.origin,v); - v[2] -= train->viewheight; - LookAhead(train,v,train->moveinfo.distance); - v[2] += train->viewheight; - VectorSubtract (v, train->s.origin, v); - if( (train->moveinfo.state < STOP) || (train->moveinfo.state==STOP && is_backing_up(train)) ) - VectorNegate(v,v); - -// gi.dprintf("v = %g, %g, %g\n",v[0],v[1],v[2]); - - if(VectorLength(v)) - { - vectoangles2(v,angles); - train->ideal_yaw = angles[YAW]; - train->ideal_pitch = angles[PITCH]; - if(train->ideal_pitch < 0) train->ideal_pitch += 360; - } - else - { - train->ideal_pitch = train->s.angles[PITCH]; - train->ideal_yaw = train->s.angles[YAW]; - } - - // determine angular velocitys from wheelbase and target angles - -// gi.dprintf("tracktrain_next: target_ent=%s, ideal_yaw=%g, ideal_pitch=%g\n", -// (train->target_ent ? train->target_ent->targetname : "none"), -// train->ideal_yaw, train->ideal_pitch); - - angles[PITCH] = train->ideal_pitch - train->s.angles[PITCH]; - angles[YAW] = train->ideal_yaw - train->s.angles[YAW]; - AnglesNormalize(angles); - - // If yaw angle is > 90, we're about to flipflop (there's no way ideal_yaw - // can be more than 90 because the path_track selection code doesn't - // allow that - if( (angles[YAW] > 90) || (angles[YAW] < -90) ) - { - angles[YAW] += 180; - if(angles[PITCH] != 0) - angles[PITCH] += 180; - AnglesNormalize(angles); - } - train->pitch_speed = fabs(angles[PITCH])*10; - train->yaw_speed = fabs(angles[YAW])*10; -} - -void tracktrain_turn (edict_t *self) -{ - edict_t *train; - float cur_yaw, idl_yaw, cur_pitch, idl_pitch; - float yaw_vel, pitch_vel; - float Dist_1, Dist_2, Distance; - float new_speed; - - train = self->enemy; - if(!train || !train->inuse) - return; - - self->nextthink = level.time + FRAMETIME; - - if(train->spawnflags & (SF_TRACKTRAIN_DISABLED | SF_TRACKTRAIN_OTHERMAP)) - return; - - // Train doesn't turn if at a complete stop - if((train->velocity[0]==0.) && (train->velocity[1]==0.) && (train->velocity[2]==0.)) - { - VectorClear(train->avelocity); - gi.linkentity(train); - return; - } - - train_angles(train); - - cur_yaw = train->s.angles[YAW]; - idl_yaw = train->ideal_yaw; - cur_pitch = train->s.angles[PITCH]; - idl_pitch = train->ideal_pitch; - -// gi.dprintf("current angles=%g %g, ideal angles=%g %g\n", -// cur_pitch,cur_yaw,idl_pitch,idl_yaw); - - yaw_vel = train->yaw_speed; - pitch_vel = train->pitch_speed; - - if (train->spawnflags & SF_TRACKTRAIN_NOPITCH) - idl_pitch = cur_pitch; - - if (cur_yaw == idl_yaw) - train->avelocity[YAW] = 0; - else - { - if (cur_yaw < idl_yaw) - { - Dist_1 = (idl_yaw - cur_yaw)*10; - Dist_2 = ((360 - idl_yaw) + cur_yaw)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - new_speed = yaw_vel; - } - else - { - Distance = Dist_2; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - new_speed = -yaw_vel; - } - } - else - { - Dist_1 = (cur_yaw - idl_yaw)*10; - Dist_2 = ((360 - cur_yaw) + idl_yaw)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - new_speed = -yaw_vel; - } - else - { - Distance = Dist_2; - - if (Distance < yaw_vel) - yaw_vel = Distance; - - new_speed = yaw_vel; - } - } - train->avelocity[YAW] = new_speed; - -// if(developer->value) -// gi.dprintf ("current yaw: %g ideal yaw: %g yaw speed: %g\n", cur_yaw, idl_yaw, self->enemy->avelocity[1]); - - if (train->s.angles[YAW] < 0) - train->s.angles[YAW] += 360; - - if (train->s.angles[YAW] >= 360) - train->s.angles[YAW] -= 360; - } - - if ( train->roll != 0 ) - { - float roll; - - if(train->moveinfo.state < STOP) - roll = -train->roll; - else - roll = train->roll; - - if(train->spawnflags & SF_TRACKTRAIN_ROLLSPEED) - roll *= VectorLength(train->velocity)/train->moveinfo.speed; - - if ( train->avelocity[YAW] < -5 ) - train->avelocity[ROLL] = UTIL_AngleDistance( UTIL_ApproachAngle( -roll, train->s.angles[ROLL], roll*2 ), train->s.angles[ROLL]); - else if ( train->avelocity[YAW] > 5 ) - train->avelocity[ROLL] = UTIL_AngleDistance( UTIL_ApproachAngle( roll, train->s.angles[ROLL], roll*2 ), train->s.angles[ROLL]); - else - train->avelocity[ROLL] = UTIL_AngleDistance( UTIL_ApproachAngle( 0, train->s.angles[ROLL], roll*4 ), train->s.angles[ROLL]) * 4; - } - - if (cur_pitch == idl_pitch) - train->avelocity[PITCH] = 0; - else - { - if (cur_pitch < idl_pitch) - { - Dist_1 = (idl_pitch - cur_pitch)*10; - Dist_2 = ((360 - idl_pitch) + cur_pitch)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - new_speed = pitch_vel; - } - else - { - Distance = Dist_2; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - new_speed = -pitch_vel; - } - } - else - { - Dist_1 = (cur_pitch - idl_pitch)*10; - Dist_2 = ((360 - cur_pitch) + idl_pitch)*10; - - if (Dist_1 < Dist_2) - { - Distance = Dist_1; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - new_speed = -pitch_vel; - } - else - { - Distance = Dist_2; - - if (Distance < pitch_vel) - pitch_vel = Distance; - - new_speed = pitch_vel; - } - } - train->avelocity[PITCH] = new_speed; - - if (train->s.angles[PITCH] < 0) - train->s.angles[PITCH] += 360; - - if (train->s.angles[PITCH] >= 360) - train->s.angles[PITCH] -= 360; - } - gi.linkentity(train); - -} - - -void tracktrain_next (edict_t *self) -{ - edict_t *ent=NULL; - vec3_t dest; - - if (!self->target_ent) - { - self->s.sound = 0; - return; - } - - ent = NextPathTrack(self,self->target_ent); - - if(ent && (ent->spawnflags & SF_PATH_DISABLED)) - ent = NULL; - - if(!ent) - { - // Dead end - if(self->owner && (self->owner->svflags & SVF_MONSTER) && !self->target_ent->deathtarget ) - { - // For monster drivers, immediately reverse course at - // dead ends (but NOT at dead ends that have a "deathtarget", - // which is usually an indication of a trackchange - self->moveinfo.prevstate = self->moveinfo.state; - self->moveinfo.state = -self->moveinfo.state; - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - self->think = tracktrain_think; - self->think(self); - self->monsterinfo.search_time = level.time; - return; - } - - VectorClear(self->velocity); - VectorClear(self->avelocity); - self->moveinfo.prevstate = self->moveinfo.state; - self->moveinfo.state = STOP; - self->s.sound = 0; - self->moveinfo.current_speed = 0; - self->moveinfo.next_speed = 0; - gi.linkentity(self); - if(self->owner) - { - VectorClear(self->owner->velocity); - gi.linkentity(self->owner); - } - if(self->target_ent->deathtarget) - { - char *temp; - temp = self->target_ent->target; - self->target_ent->target = self->target_ent->deathtarget; - G_UseTargets(self->target_ent,self); - self->target_ent->target = temp; - } - self->think = tracktrain_think; - self->think(self); - return; - } - - self->target_ent = ent; - self->target = ent->targetname; - - VectorCopy (ent->s.origin, dest); - dest[2] += self->viewheight; - VectorCopy (dest, self->moveinfo.end_origin); - - train_angles(self); - - if(!(self->spawnflags & SF_TRACKTRAIN_NOCONTROL) || !(self->spawnflags & SF_TRACKTRAIN_STARTOFF)) - { - self->think = tracktrain_think; - self->think(self); - } -} - -void func_tracktrain_find (edict_t *self) -{ - edict_t *ent; - edict_t *next; - vec3_t vec; - - if (!self->target) - { - gi.dprintf ("tracktrain_find: no target\n"); - return; - } - ent = G_PickTarget (self->target); - if (!ent) - { - gi.dprintf ("tracktrain_find: target %s not found\n", self->target); - return; - } - - if(ent->speed) { - self->moveinfo.speed = ent->speed * self->speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - self->moveinfo.next_speed = self->moveinfo.state * self->moveinfo.speed/3; - } - - self->target_ent = ent; - - // Get angles to next path_track - next = G_PickTarget (ent->target); - if (!next) - { - gi.dprintf ("tracktrain_find: next target %s not found\n", ent->target); - return; - } - VectorSubtract (next->s.origin, ent->s.origin, vec); - vectoangles2(vec,self->s.angles); - - ent->think = tracktrain_turn; - ent->enemy = self; - ent->nextthink = level.time + FRAMETIME; - - VectorCopy (ent->s.origin, self->s.origin); - self->s.origin[2] += self->viewheight; - - if (self->spawnflags & SF_TRACKTRAIN_OTHERMAP) - { - self->solid = SOLID_NOT; - self->svflags |= SVF_NOCLIENT; - self->spawnflags |= SF_TRACKTRAIN_DISABLED; - self->nextthink = 0; - } - else - { - self->nextthink = level.time + FRAMETIME; - self->think = tracktrain_next; - } - gi.linkentity (self); -} - -void tracktrain_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->spawnflags & SF_TRACKTRAIN_STARTOFF) - { - if(self->spawnflags & SF_TRACKTRAIN_NOCONTROL) - { - self->moveinfo.state = FAST; - self->moveinfo.next_speed = self->moveinfo.speed; - if(self->sounds) - self->s.sound = gi.soundindex(va("%sspeed%d.wav",self->source,abs(self->moveinfo.state))); - else - self->s.sound = 0; - } - self->spawnflags &= ~SF_TRACKTRAIN_STARTOFF; - self->think = tracktrain_think; - self->think(self); - } - else - { - if(self->owner) - tracktrain_disengage(self); - self->moveinfo.state = STOP; - self->moveinfo.next_speed = 0; - self->s.sound = 0; - self->think = NULL; - self->nextthink = 0; - self->spawnflags |= SF_TRACKTRAIN_STARTOFF; - } -} - -void SP_func_tracktrain (edict_t *self) -{ - self->class_id = ENTITY_FUNC_TRACKTRAIN; - self->movetype = MOVETYPE_PUSH; - self->flags |= FL_TRACKTRAIN; - - VectorClear (self->s.angles); - self->blocked = tracktrain_blocked; - if (!self->dmg) - self->dmg = 100; - // Wheelbase determines angular velocities - if(st.distance) - self->moveinfo.distance = st.distance; - else - self->moveinfo.distance = 50; - - // Origin rides by "height" above path_tracks - if(st.height) - self->viewheight = st.height; - else - self->viewheight = 4; - - // Default mass for collisions: - self->mass = 2000; - - // Driving position - if( (VectorLength(self->bleft) == 0) && (VectorLength(self->tright) == 0)) - { - VectorSet(self->bleft,-8,-8,-8); - VectorSet(self->tright,8,8,8); - } - VectorAdd(self->bleft,self->tright,self->move_origin); - VectorScale(self->move_origin,0.5,self->move_origin); - - self->solid = SOLID_BSP; - gi.setmodel (self, self->model); - - if (!self->speed) - self->speed = 100; - - self->moveinfo.speed = self->speed; - self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; - - if (self->roll_speed) - { - self->roll = self->roll_speed; - self->roll_speed = 0; - self->spawnflags |= SF_TRACKTRAIN_ROLLSPEED; - } - - if (self->health) { - self->die = tracktrain_die; - self->takedamage = DAMAGE_YES; - } else { - self->die = NULL; - self->takedamage = DAMAGE_NO; - } - - self->spawnflags &= ~SF_TRACKTRAIN_DISABLED; // insurance - if(self->spawnflags & SF_TRACKTRAIN_NOCONTROL) - self->spawnflags |= SF_TRACKTRAIN_STARTOFF; - - self->use = tracktrain_use; - self->moveinfo.current_speed = 0; - self->moveinfo.state = STOP; - self->moveinfo.prevstate = STOP+1; // Assumed, so that initial reverse works correctly - self->s.sound = 0; - self->turn_rider = 1; - VectorClear(self->s.angles); - - if (self->target) - { - self->nextthink = level.time + FRAMETIME; - self->think = func_tracktrain_find; - } - else if(!(self->spawnflags & SF_TRACKTRAIN_OTHERMAP)) - { - gi.dprintf ("func_tracktrain without a target at %s\n", vtos(self->absmin)); - G_FreeEdict(self); - return; - } - - if(!self->sounds) - self->sounds = 1; - if(self->sounds > 0) - { - if(self->sounds > 9) - self->sounds = 9; - self->source = TagMalloc(10,TAG_LEVEL); - sprintf(self->source,"train/%d/",self->sounds); - gi.soundindex(va("%sspeed1.wav",self->source)); - gi.soundindex(va("%sspeed2.wav",self->source)); - gi.soundindex(va("%sspeed3.wav",self->source)); - } - - gi.linkentity (self); - -} - -void find_tracktrain (edict_t *self) -{ - edict_t *train; - bool train_found=false; - vec3_t forward; - - // This gives game a chance to put player in place before - // restarting train - if(!g_edicts[1].linkcount) - { - self->nextthink = level.time + FRAMETIME; - return; - } - - train = G_Find(NULL,FOFS(targetname),self->targetname); - while(train && !train_found) - { - if(train->class_id == ENTITY_FUNC_TRACKTRAIN) - train_found = true; - else - train = G_Find(train,FOFS(targetname),self->targetname); - } - if(!train_found) - { - gi.dprintf("find_tracktrain: no matching func_tracktrain with targetname=%s\n", - self->targetname); - G_FreeEdict(self); - return; - } - train->solid = SOLID_BSP; - train->svflags &= ~SVF_NOCLIENT; - train->spawnflags = self->spawnflags; - train->spawnflags &= ~(SF_TRACKTRAIN_OTHERMAP | SF_TRACKTRAIN_DISABLED); - VectorCopy(self->s.origin,train->s.origin); - VectorCopy(self->s.angles,train->s.angles); - VectorCopy(self->bleft, train->bleft); - VectorCopy(self->tright, train->tright); - VectorClear(train->avelocity); - train->viewheight = self->viewheight; - train->speed = self->speed; - train->moveinfo.distance = self->radius; - train->moveinfo.accel = train->moveinfo.decel = train->moveinfo.speed = train->speed; - train->moveinfo.state = train->moveinfo.prevstate = self->count; - train->sounds = self->sounds; - if(train->sounds > 0) - { - train->source = TagMalloc(10,TAG_LEVEL); - sprintf(train->source,"train/%d/",train->sounds); - } - if(train->moveinfo.state && (train->sounds > 0)) - train->s.sound = gi.soundindex(va("%sspeed%d.wav",train->source,abs(train->moveinfo.state))); - else - train->s.sound = 0; - train->moveinfo.next_speed = train->moveinfo.state * train->moveinfo.speed/3; - // Assume train was already at it's "next_speed" when the level change occurred - AngleVectors(train->s.angles,forward,NULL,NULL); - VectorScale(forward,train->moveinfo.next_speed,train->velocity); - // Force a wait before taking player input - train->moveinfo.wait = 1; - - if(self->style && (self->style <= game.maxclients) && &g_edicts[self->style].inuse) - { - train->owner = &g_edicts[self->style]; - train->owner->vehicle = train; - if(train->owner->client) - { - train->owner->client->vehicle_framenum = level.framenum; - train->owner->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - } - VectorCopy(self->offset,train->offset); - } - else - train->owner = NULL; - - gi.linkentity(train); - if(self->target) - { - vec3_t dest; - - train->target = self->target; - train->target_ent = G_Find(NULL,FOFS(targetname),train->target); - VectorCopy (train->target_ent->s.origin, dest); - dest[2] += train->viewheight; - VectorCopy (dest, train->moveinfo.end_origin); - train_angles(train); - if(!(train->spawnflags & SF_TRACKTRAIN_NOCONTROL) || !(train->spawnflags & SF_TRACKTRAIN_STARTOFF)) - { - train->think = tracktrain_think; - train->think(train); - } - } - else - gi.dprintf("info_train_start with no target\n"); - - G_FreeEdict(self); -} - -void SP_info_train_start (edict_t *self) -{ - if(!self->targetname) - { - gi.dprintf("crosslevel train with no targetname\n"); - G_FreeEdict(self); - } - self->class_id = ENTITY_INFO_TRAIN_START; - self->think = find_tracktrain; - self->nextthink = level.time + 1; -} diff --git a/server/ents/g_trigger.c b/server/ents/g_trigger.c deleted file mode 100644 index fb43ea1c..00000000 --- a/server/ents/g_trigger.c +++ /dev/null @@ -1,2063 +0,0 @@ -#include "g_local.h" - -#define TRIGGER_MONSTER 1 -#define TRIGGER_NOT_PLAYER 2 -#define TRIGGER_START_OFF 4 -#define TRIGGER_NEED_USE 8 -#define TRIGGER_CAMOWNER 16 -#define TRIGGER_LOOKTARGET 32 -#define TRIGGER_TARGET_OFF 64 - -void InitTrigger (edict_t *self) -{ - if (!VectorCompare (self->s.angles, vec3_origin)) - G_SetMovedir (self->s.angles, self->movedir); - - self->solid = SOLID_TRIGGER; - self->movetype = MOVETYPE_NONE; - gi.setmodel (self, self->model); - self->svflags = SVF_NOCLIENT; -} - - -// the wait time has passed, so set back up for another activation -void multi_wait (edict_t *ent) -{ - ent->nextthink = 0; -} - - -// the trigger was just activated -// ent->activator should be set to the activator so it can be held through a delay -// so wait for the delay time before firing -void multi_trigger (edict_t *ent) -{ - if (ent->nextthink) - return; // already been triggered - - G_UseTargets (ent, ent->activator); - - if (ent->wait > 0) - { - ent->think = multi_wait; - ent->nextthink = level.time + ent->wait; - } - else - { // we can't just remove (self) here, because this is a touch function - // called while looping through area links... - ent->touch = NULL; - ent->nextthink = level.time + FRAMETIME; - ent->think = G_FreeEdict; - } -} - -void Use_Multi (edict_t *ent, edict_t *other, edict_t *activator) -{ - ent->activator = activator; - multi_trigger (ent); -} - -void Touch_Multi (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if(other->client || (other->flags & FL_ROBOT)) - { - if (self->spawnflags & TRIGGER_NOT_PLAYER) - return; - } - else if (other->svflags & SVF_MONSTER) - { - if (!(self->spawnflags & TRIGGER_MONSTER)) - return; - } - else - return; - - if( (self->spawnflags & TRIGGER_CAMOWNER) && (!other->client || !other->client->spycam)) - return; - - if (!VectorCompare(self->movedir, vec3_origin)) - { - vec3_t forward; - - AngleVectors(other->s.angles, forward, NULL, NULL); - if (DotProduct(forward, self->movedir) < 0) - return; - } - - self->activator = other; - multi_trigger (self); -} - -/*QUAKED trigger_multiple (.5 .5 .5) ? MONSTER NOT_PLAYER TRIGGERED -Variable sized repeatable trigger. Must be targeted at one or more entities. -If "delay" is set, the trigger waits some time after activating before firing. -"wait" : Seconds between triggerings. (.2 default) -sounds -1) secret -2) beep beep -3) large switch -4) -set "message" to text string -*/ -void trigger_enable (edict_t *self, edict_t *other, edict_t *activator) -{ - self->solid = SOLID_TRIGGER; - self->use = Use_Multi; - gi.linkentity (self); -} - -void SP_trigger_multiple (edict_t *ent) -{ - ent->class_id = ENTITY_TRIGGER_MULTIPLE; - if (ent->sounds == 1) - ent->noise_index = gi.soundindex ("misc/secret.wav"); - else if (ent->sounds == 2) - ent->noise_index = gi.soundindex ("misc/talk.wav"); - else if (ent->sounds == 3) -// DWH - should be silent -// ent->noise_index = gi.soundindex ("misc/trigger1.wav"); - ent->noise_index = -1; - - if (!ent->wait) - ent->wait = 0.2; - ent->touch = Touch_Multi; - ent->movetype = MOVETYPE_NONE; - ent->svflags |= SVF_NOCLIENT; - - if (ent->spawnflags & TRIGGER_CAMOWNER) - ent->svflags |= SVF_TRIGGER_CAMOWNER; - - if (ent->spawnflags & TRIGGER_START_OFF) - { - ent->solid = SOLID_NOT; - ent->use = trigger_enable; - } - else - { - ent->solid = SOLID_TRIGGER; - ent->use = Use_Multi; - } - - if (!VectorCompare(ent->s.angles, vec3_origin)) - G_SetMovedir (ent->s.angles, ent->movedir); - - gi.setmodel (ent, ent->model); - gi.linkentity (ent); -} - - -/*QUAKED trigger_once (.5 .5 .5) ? x x TRIGGERED -Triggers once, then removes itself. -You must set the key "target" to the name of another object in the level that has a matching "targetname". - -If TRIGGERED, this trigger must be triggered before it is live. - -sounds - 1) secret - 2) beep beep - 3) large switch - 4) - -"message" string to be displayed when triggered -*/ - -void SP_trigger_once(edict_t *ent) -{ - // make old maps work because I messed up on flag assignments here - // triggered was on bit 1 when it should have been on bit 4 - if (ent->spawnflags & 1) - { - vec3_t v; - - VectorMA (ent->mins, 0.5, ent->size, v); - ent->spawnflags &= ~1; - ent->spawnflags |= TRIGGER_START_OFF; - gi.dprintf("fixed TRIGGERED flag on %s at %s\n", ent->classname, vtos(v)); - } - - ent->wait = -1; - SP_trigger_multiple (ent); - ent->class_id = ENTITY_TRIGGER_ONCE; -} - -/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) -This fixed size trigger cannot be touched, it can only be fired by other events. -*/ -void trigger_relay_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + FRAMETIME; - } - G_UseTargets (self, activator); -} - -void SP_trigger_relay (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_RELAY; -// DWH - gives trigger_relay same message-displaying, sound-playing capabilities -// as trigger_multiple and trigger_once - if (self->sounds == 1) - self->noise_index = gi.soundindex ("misc/secret.wav"); - else if (self->sounds == 2) - self->noise_index = gi.soundindex ("misc/talk.wav"); - else if (self->sounds == 3) - self->noise_index = -1; - if(!self->count) self->count=-1; -// end DWH - - self->use = trigger_relay_use; -} - - -/* -============================================================================== - -trigger_key - -Lazarus editions: -Spawnflags -1 = Multi-use. If set, item is required EVERY time trigger_key is targeted -2 = Keep key. If set, player doesn't give up the key when trigger_key is used. -4 = Silent. If set, neither the "You need" message and sound nor keyuse.wav - are played. This is useful for trigger_keys used only to remove items from - the player. - -Lazarus also removes non-multi-use trigger_keys once used, to free up space in -the edicts array. - -============================================================================== -*/ - -/*QUAKED trigger_key (.5 .5 .5) (-8 -8 -8) (8 8 8) -A relay trigger that only fires it's targets if player has the proper key. -Use "item" to specify the required key, for example "key_data_cd" -*/ -void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator) -{ - int index; - - if (!self->item) - return; - if (!activator->client) - return; - - index = ITEM_INDEX(self->item); - if (!activator->client->pers.inventory[index]) - { - if (level.time < self->touch_debounce_time) - return; - self->touch_debounce_time = level.time + 5.0; - if(!(self->spawnflags & 4)) - { - gi.centerprintf (activator, "You need the %s", self->item->pickup_name); - gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/keytry.wav"), 1, ATTN_NORM, 0); - } - return; - } - - if(!(self->spawnflags & 4)) - gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/keyuse.wav"), 1, ATTN_NORM, 0); - if (coop->value) - { - int player; - edict_t *ent; - - if (strcmp(self->item->classname, "key_power_cube") == 0) - { - int cube; - - for (cube = 0; cube < 8; cube++) - if (activator->client->pers.power_cubes & (1 << cube)) - break; - for (player = 1; player <= game.maxclients; player++) - { - ent = &g_edicts[player]; - if (!ent->inuse) - continue; - if (!ent->client) - continue; - // DWH: keep key - if (!(self->spawnflags & 2)) { - if (ent->client->pers.power_cubes & (1 << cube)) - { - ent->client->pers.inventory[index]--; - ent->client->pers.power_cubes &= ~(1 << cube); - } - } - } - } - else - { - for (player = 1; player <= game.maxclients; player++) - { - ent = &g_edicts[player]; - if (!ent->inuse) - continue; - if (!ent->client) - continue; - // DWH: keep key - if(!(self->spawnflags & 2)) - ent->client->pers.inventory[index] = 0; - } - } - } - // DWH: keep key - else if(!(self->spawnflags & 2)) - { - activator->client->pers.inventory[index]--; - } - - G_UseTargets (self, activator); - - // DWH - multi-use - if(!(self->spawnflags & 1)) { - self->use = NULL; - self->think = G_FreeEdict; - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); - } -} - -void SP_trigger_key (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_KEY; - if (!st.item) - { - gi.dprintf("no key item for trigger_key at %s\n", vtos(self->s.origin)); - return; - } - self->item = FindItemByClassname (st.item); - - if (!self->item) - { - gi.dprintf("item %s not found for trigger_key at %s\n", st.item, vtos(self->s.origin)); - return; - } - - if (!self->target) - { - gi.dprintf("%s at %s has no target\n", self->classname, vtos(self->s.origin)); - return; - } - - gi.soundindex ("misc/keytry.wav"); - gi.soundindex ("misc/keyuse.wav"); - - self->use = trigger_key_use; -} - - -/* -============================================================================== - -trigger_counter - -============================================================================== -*/ - -/*QUAKED trigger_counter (.5 .5 .5) ? nomessage -Acts as an intermediary for an action that takes multiple inputs. - -If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished. - -After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself. -*/ - -void trigger_counter_use(edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->count == 0) { - G_FreeEdict(self); // DWH - return; - } - - self->count--; - - if (self->count) - { - if (! (self->spawnflags & 1)) - { - gi.centerprintf(activator, "%i more to go...", self->count); - gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); - } - return; - } - - if (! (self->spawnflags & 1)) - { - gi.centerprintf(activator, "Sequence completed!"); - gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); - } - self->activator = activator; - multi_trigger (self); - // DWH - if (self->count == 0) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } -} - -void SP_trigger_counter (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_COUNTER; - self->wait = -1; - if (!self->count) - self->count = 2; - - self->use = trigger_counter_use; -} - - -/* -============================================================================== - -trigger_always - -============================================================================== -*/ - -/*QUAKED trigger_always (.5 .5 .5) (-8 -8 -8) (8 8 8) -This trigger will always fire. It is activated by the world. -*/ -void SP_trigger_always (edict_t *ent) -{ - ent->class_id = ENTITY_TRIGGER_ALWAYS; - // we must have some delay to make sure our use targets are present - if (ent->delay < 0.2) - ent->delay = 0.2; - G_UseTargets(ent, ent); -} - - -/* -============================================================================== - -trigger_push - -============================================================================== -*/ - -#define PUSH_ONCE 1 - -static int windsound; - -void trigger_push_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other->class_id == ENTITY_GRENADE) - { - VectorScale (self->movedir, self->speed * 10, other->velocity); - } -// Lazarus - else if (other->movetype == MOVETYPE_PUSHABLE) - { - vec3_t v; - VectorScale (self->movedir, self->speed * 2000 / (float)(other->mass), v); - VectorAdd(other->velocity,v,other->velocity); - } - else if (other->health > 0) - { - VectorScale (self->movedir, self->speed * 10, other->velocity); - if (other->client) - { - // don't take falling damage immediately from this - VectorCopy (other->velocity, other->client->oldvelocity); - if (other->fly_sound_debounce_time < level.time) - { - other->fly_sound_debounce_time = level.time + 1.5; - if(self->spawnflags & 2) { - if(self->noise_index) - gi.sound(other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0); - } else - gi.sound (other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0); - } - } - } - if (self->spawnflags & PUSH_ONCE) - G_FreeEdict (self); -} - - -/*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE CUSTOM_SOUND -Pushes the player -"speed" defaults to 1000 -*/ -void SP_trigger_push (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_PUSH; - InitTrigger (self); - // DWH: Custom (or no) sound - if(self->spawnflags & 2) { - if(st.noise) - self->noise_index = gi.soundindex(st.noise); - else - self->noise_index = 0; - } else { - windsound = gi.soundindex ("misc/windfly.wav"); - } - self->touch = trigger_push_touch; - if (!self->speed) - self->speed = 1000; - - gi.linkentity (self); -} - - -/* -============================================================================== - -trigger_hurt - -============================================================================== -*/ - -/*QUAKED trigger_hurt (.5 .5 .5) ? START_OFF TOGGLE SILENT NO_PROTECTION SLOW -Any entity that touches this will be hurt. - -It does dmg points of damage each server frame -"dmg" default 5 (whole numbers only) */ - -#define SF_HURT_START_OFF 1 -#define SF_HURT_TOGGLE 2 -#define SF_HURT_SILENT 4 // supresses playing the sound -#define SF_HURT_NO_PROTECTION 8 // *nothing* stops the damage -#define SF_HURT_SLOW 16 // changes the damage rate to once per second -#define SF_HURT_NOGIB 32 // Lazarus: won't gib entity -#define SF_HURT_ENVIRONMENT 64 // Lazarus: environment suit protects from damage - -void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); -void hurt_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->solid == SOLID_NOT) - { - int i, num; - edict_t *touch[MAX_EDICTS], *hurtme; - - self->solid = SOLID_TRIGGER; - // Lazaurs: Add check for non-moving (i.e. idle monsters) within trigger_hurt - // at first activation - num = gi.BoxEdicts (self->absmin, self->absmax, touch, MAX_EDICTS, AREA_SOLID); - for (i=0 ; isolid = SOLID_NOT; - gi.linkentity (self); - - if (!(self->spawnflags & SF_HURT_TOGGLE)) - self->use = NULL; -} - - -void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - int dflags; - - if (!other->takedamage) - return; - - if (self->timestamp > level.time) - return; - - // DWH - don't "heal" other if he's at max_health - if ( (self->dmg < 0) && (other->health >= other->max_health)) - return; - - if (self->spawnflags & SF_HURT_SLOW) - self->timestamp = level.time + 1; - else - self->timestamp = level.time + FRAMETIME; - - if (!(self->spawnflags & SF_HURT_SILENT)) - { - // DWH - Original code would fail to play a sound for - // SF=16 unless player just HAPPENED to hit - // trigger_hurt at framenum = an integral number of - // full seconds. - if ( ((level.framenum % 10) == 0 ) || (self->spawnflags & SF_HURT_SLOW) ) - gi.sound (other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0); - } - - if (self->spawnflags & SF_HURT_NO_PROTECTION) - dflags = DAMAGE_NO_PROTECTION; - else - dflags = 0; - // Lazarus: healing, no gib, and environment suit protection - if (self->dmg > 0) - { - int damage = self->dmg; - - if(self->spawnflags & SF_HURT_NOGIB) - { - if(skill->value > 0) - damage = min(damage, other->health - other->gib_health - 1); - else - damage = min(damage, 2*(other->health - other->gib_health - 1)); - - if(damage < 0) - damage = 0; - } - - if (other->client && (self->spawnflags & SF_HURT_ENVIRONMENT) && (other->client->enviro_framenum > level.framenum)) - damage = 0; - - if(damage > 0) - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, damage, self->dmg, dflags, MOD_TRIGGER_HURT); - } - else - { - other->health -= self->dmg; - if(other->health > other->max_health) - other->health = other->max_health; - } -} - -void SP_trigger_hurt (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_HURT; - InitTrigger (self); - - self->touch = hurt_touch; - - if (!self->dmg) - self->dmg = 5; - - // DWH - play different sound for healing - if (self->dmg > 0) - self->noise_index = gi.soundindex ("world/electro.wav"); - else - self->noise_index = gi.soundindex ("items/s_health.wav"); - - if (self->spawnflags & SF_HURT_START_OFF) - self->solid = SOLID_NOT; - else - self->solid = SOLID_TRIGGER; - - if (self->spawnflags & SF_HURT_TOGGLE) - self->use = hurt_use; - - gi.linkentity (self); -} - - -/* -============================================================================== - -trigger_gravity - -============================================================================== -*/ - -/*QUAKED trigger_gravity (.5 .5 .5) ? -Changes the touching entites gravity to -the value of "gravity". 1.0 is standard -gravity for the level. -*/ - -void trigger_gravity_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - other->gravity = self->gravity; -} - -void SP_trigger_gravity (edict_t *self) -{ - if (st.gravity == 0) - { - gi.dprintf("trigger_gravity without gravity set at %s\n", vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - - self->class_id = ENTITY_TRIGGER_GRAVITY; - InitTrigger (self); - self->gravity = atoi(st.gravity); - self->touch = trigger_gravity_touch; -} - - -/* -============================================================================== - -trigger_monsterjump - -============================================================================== -*/ - -/*QUAKED trigger_monsterjump (.5 .5 .5) ? -Walking monsters that touch this will jump in the direction of the trigger's angle -"speed" default to 200, the speed thrown forward -"height" default to 200, the speed thrown upwards -*/ - -void trigger_monsterjump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other->flags & (FL_FLY | FL_SWIM) ) - return; - if (other->svflags & SVF_DEADMONSTER) - return; - if ( !(other->svflags & SVF_MONSTER)) - return; - -// set XY even if not on ground, so the jump will clear lips - other->velocity[0] = self->movedir[0] * self->speed; - other->velocity[1] = self->movedir[1] * self->speed; - - if (!other->groundentity) - return; - - other->groundentity = NULL; - other->velocity[2] = self->movedir[2]; -} - -void SP_trigger_monsterjump (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_MONSTERJUMP; - if (!self->speed) - self->speed = 200; - if (!st.height) - st.height = 200; - if (self->s.angles[YAW] == 0) - self->s.angles[YAW] = 360; - InitTrigger (self); - self->touch = trigger_monsterjump_touch; - self->movedir[2] = st.height; -} - -//=============================================================== -// DWH additions -//=============================================================== - -/*QUAKED tremor_trigger_multiple (.5 .5 .5) ? MONSTER NOT_PLAYER TRIGGERED -Variable sized repeatable trigger. Must be targeted at one or more entities. -If "delay" is set, the trigger waits some time after activating before firing. -"wait" : Seconds between triggerings. (.2 default) -Same as trigger_multiple, but toggles on/off when targeted. - -sounds -1) secret -2) beep beep -3) large switch -4) -set "message" to text string -*/ - -void tremor_trigger_enable (edict_t *self, edict_t *other, edict_t *activator); -void Use_tremor_Multi (edict_t *self, edict_t *other, edict_t *activator) -{ - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - else - { - self->use = tremor_trigger_enable; - self->solid = SOLID_NOT; - gi.linkentity(self); - } -} - -void tremor_trigger_enable (edict_t *self, edict_t *other, edict_t *activator) -{ - self->solid = SOLID_TRIGGER; - self->use = Use_tremor_Multi; - gi.linkentity (self); -} - -void SP_tremor_trigger_multiple (edict_t *ent) -{ - ent->class_id = ENTITY_TREMOR_TRIGGER_MULTIPLE; - if (ent->sounds == 1) - ent->noise_index = gi.soundindex ("misc/secret.wav"); - else if (ent->sounds == 2) - ent->noise_index = gi.soundindex ("misc/talk.wav"); - else if (ent->sounds == 3) -// DWH - should be silent -// ent->noise_index = gi.soundindex ("misc/trigger1.wav"); - ent->noise_index = -1; - - if (!ent->wait) - ent->wait = 0.2; - ent->touch = Touch_Multi; - ent->movetype = MOVETYPE_NONE; - ent->svflags |= SVF_NOCLIENT; - - if (ent->spawnflags & TRIGGER_CAMOWNER) - ent->svflags |= SVF_TRIGGER_CAMOWNER; - - if (ent->spawnflags & TRIGGER_START_OFF) - { - ent->solid = SOLID_NOT; - ent->use = tremor_trigger_enable; - } - else - { - ent->solid = SOLID_TRIGGER; - ent->use = Use_tremor_Multi; - } - - if (!VectorCompare(ent->s.angles, vec3_origin)) - G_SetMovedir (ent->s.angles, ent->movedir); - - gi.setmodel (ent, ent->model); - gi.linkentity (ent); -} - -//========================================================================================= -// TRIGGER_MASS - triggers its targets when touched by any entity with mass >= mass value -// of trigger -//========================================================================================= -void trigger_mass_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if(other->mass < self->mass) return; - self->activator = other; - multi_trigger (self); -} - -void SP_trigger_mass (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_MASS; - // Fires its target if touched by an entity weighing at least - // self->mass - if (self->sounds == 1) - self->noise_index = gi.soundindex ("misc/secret.wav"); - else if (self->sounds == 2) - self->noise_index = gi.soundindex ("misc/talk.wav"); - else if (self->sounds == 3) -// DWH - should be silent -// self->noise_index = gi.soundindex ("misc/trigger1.wav"); - self->noise_index = -1; - - if(!self->wait) self->wait = 0.2; - self->touch = trigger_mass_touch; - self->movetype = MOVETYPE_NONE; - self->svflags |= SVF_NOCLIENT; - if(self->spawnflags & TRIGGER_START_OFF) - { - self->solid = SOLID_NOT; - self->use = trigger_enable; - } - else - { - self->solid = SOLID_TRIGGER; - self->use = Use_Multi; - } - if(!self->mass) - self->mass = 100; - gi.setmodel (self, self->model); - gi.linkentity (self); -} -//======================================================================================= -// TRIGGER_INSIDE - triggers its targets when the bounding box for its pathtarget is -// completely inside the trigger field -//======================================================================================= -void trigger_inside_think (edict_t *self) -{ - int i, num; - edict_t *touch[MAX_EDICTS], *hit; - - num = gi.BoxEdicts (self->absmin, self->absmax, touch, MAX_EDICTS, AREA_SOLID); - for (i=0 ; iinuse) continue; - if (!hit->targetname) continue; - if (stricmp(self->pathtarget, hit->targetname)) continue; - // must be COMPLETELY inside - if (hit->absmin[0] < self->absmin[0]) continue; - if (hit->absmin[1] < self->absmin[1]) continue; - if (hit->absmin[2] < self->absmin[2]) continue; - if (hit->absmax[0] > self->absmax[0]) continue; - if (hit->absmax[1] > self->absmax[1]) continue; - if (hit->absmax[2] > self->absmax[2]) continue; - G_UseTargets (self, hit); - if (self->wait > 0) - self->nextthink = level.time + self->wait; - else - { - self->nextthink = level.time + FRAMETIME; - self->think = G_FreeEdict; - } - gi.linkentity(self); - return; - } - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} -void SP_trigger_inside (edict_t *self) -{ - vec3_t v; - - self->class_id = ENTITY_TRIGGER_INSIDE; - VectorMA (self->mins, 0.5, self->size, v); - if(!self->target) - { - gi.dprintf("trigger_inside with no target at %s.\n",vtos(v)); - G_FreeEdict(self); - return; - } - if(!self->pathtarget) - { - gi.dprintf("trigger_inside with no pathtarget at %s.\n",vtos(v)); - G_FreeEdict(self); - return; - } - self->movetype = MOVETYPE_NONE; - self->svflags |= SVF_NOCLIENT; - self->solid = SOLID_TRIGGER; - if(!self->wait) self->wait = 0.2; - gi.setmodel (self,self->model); - self->think = trigger_inside_think; - self->nextthink = level.time + 1.0; - gi.linkentity(self); -} -//================================================================================== -// TRIGGER_SCALES - coupled with target_characters, displays the weight of all -// entities that are "standing on" the trigger. -//================================================================================== -float weight_on_top(edict_t *ent) -{ - float weight; - int i; - edict_t *e; - weight = 0.0; - for(i=1, e=g_edicts+i; iinuse) continue; - if(e->groundentity == ent) - { - weight += e->mass; - weight += weight_on_top(e); - } - } - return weight; -} - -void trigger_scales_think (edict_t *self) -{ - float f, fx, fy; - int i, num; - int weight; - edict_t *e, *touch[MAX_EDICTS], *hit; - - num = gi.BoxEdicts (self->absmin, self->absmax, touch, MAX_EDICTS, AREA_SOLID); - weight = 0; - for (i=0 ; iinuse) continue; - if (!hit->mass) continue; - fx = fy = 0.0; - if(hit->absmin[0] < self->absmin[0]) - fx += (self->absmin[0] - hit->absmin[0])/hit->size[0]; - if(hit->absmax[0] > self->absmax[0]) - fx += (hit->absmax[0] - self->absmax[0])/hit->size[0]; - if(hit->absmin[1] < self->absmin[1]) - fy += (self->absmin[1] - hit->absmin[1])/hit->size[1]; - if(hit->absmax[1] > self->absmax[1]) - fy += (hit->absmax[1] - self->absmax[1])/hit->size[1]; - f = (1.0 - fx - fy + fx*fy); - if(f > 0) weight += f * hit->mass; - weight += f*weight_on_top(hit); - } - if(weight != self->mass) - { - self->mass = weight; - for (e = self->teammaster; e; e = e->teamchain) - { - if (!e->count) - continue; - num = e->count; - if(weight < pow(10,num-1)) - e->s.frame = 12; - else - e->s.frame = ( weight % (int)pow(10,num) ) / ( pow(10,num-1) ); - } - } - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} - -void SP_trigger_scales (edict_t *self) -{ - vec3_t v; - - self->class_id = ENTITY_TRIGGER_SCALES; - VectorMA (self->mins, 0.5, self->size, v); - if(!self->team) - { - gi.dprintf("trigger_scales with no team at %s.\n",vtos(v)); - G_FreeEdict(self); - return; - } - self->movetype = MOVETYPE_NONE; - self->svflags |= SVF_NOCLIENT; - self->solid = SOLID_TRIGGER; - gi.setmodel (self,self->model); - self->think = trigger_scales_think; - self->nextthink = level.time + 1.0; - self->mass = 0; - gi.linkentity(self); -} -//====================================================================================== -// TRIGGER_BBOX - Exactly like a tremor_trigger_multiple, but uses bleft, tright fields -// to define extents of trigger field rather than a brush model. This -// helps lower the total brush model count, which in turn helps head off -// Index Overflow errors. -//====================================================================================== -void trigger_bbox_reset (edict_t *self) -{ - self->takedamage = DAMAGE_YES; - self->health = self->max_health; - gi.linkentity(self); -} - -void trigger_bbox_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->activator = attacker; - self->takedamage = DAMAGE_NO; - G_UseTargets (self, self->activator); - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + self->delay + FRAMETIME; - return; - } - if (self->wait >= 0) - { - self->nextthink = level.time + self->wait; - self->think = trigger_bbox_reset; - } - gi.linkentity(self); -} - -void trigger_bbox_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if(self->nextthink) - return; // already "touched" and waiting - if((other->client) && (self->spawnflags & 2)) - return; - if((other->svflags & SVF_MONSTER) && !(self->spawnflags & 1)) - return; - if(!other->client && !(other->svflags & SVF_MONSTER)) - return; - if(other->client && other->client->spycam && !(self->svflags & SVF_TRIGGER_CAMOWNER)) - return; - if((self->svflags & SVF_TRIGGER_CAMOWNER) && (!other->client || !other->client->spycam)) - return; - self->activator = other; - G_UseTargets(self,self->activator); - if(self->wait > 0) - { - self->count--; - if(!self->count) - { - self->think = G_FreeEdict; - self->nextthink = level.time + FRAMETIME; - } - else - { - self->think = multi_wait; - self->nextthink = level.time + self->wait; - } - } - else - { - self->think = G_FreeEdict; - self->nextthink = level.time + FRAMETIME; - } -} -void trigger_bbox_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - else - { - if(self->solid == SOLID_NOT) - { - if(self->max_health > 0) - { - self->solid = SOLID_BBOX; - self->touch = NULL; - } - else - { - self->solid = SOLID_TRIGGER; - self->touch = trigger_bbox_touch; - } - } - else - self->solid = SOLID_NOT; - gi.linkentity(self); - } -} - -void SP_trigger_bbox (edict_t *ent) -{ - ent->class_id = ENTITY_TRIGGER_BBOX; - if (ent->sounds == 1) - ent->noise_index = gi.soundindex ("misc/secret.wav"); - else if (ent->sounds == 2) - ent->noise_index = gi.soundindex ("misc/talk.wav"); - else if (ent->sounds == 3) - ent->noise_index = -1; - - if (!ent->wait) - ent->wait = 0.2; - - ent->movetype = MOVETYPE_NONE; - if (ent->spawnflags & TRIGGER_CAMOWNER) - ent->svflags |= SVF_TRIGGER_CAMOWNER; - - if ( (!VectorLength(ent->bleft)) && (!VectorLength(ent->tright)) ) { - VectorSet(ent->bleft,-16,-16,-16); - VectorSet(ent->tright,16, 16, 16); - } - VectorCopy(ent->bleft,ent->mins); - VectorCopy(ent->tright,ent->maxs); - - ent->max_health = ent->health; - if(ent->health > 0) - { - ent->svflags |= SVF_DEADMONSTER; - ent->die = trigger_bbox_die; - ent->takedamage = DAMAGE_YES; - } - else - ent->svflags |= SVF_NOCLIENT; - - if (ent->spawnflags & TRIGGER_START_OFF) - ent->solid = SOLID_NOT; - else - { - if(ent->health) - { - ent->solid = SOLID_BBOX; - ent->touch = NULL; - } - else - { - ent->solid = SOLID_TRIGGER; - ent->touch = trigger_bbox_touch; - } - } - ent->use = trigger_bbox_use; - gi.linkentity (ent); -} - -//============================================================================================ -// TRIGGER_LOOK -// Serves the same function as trigger_multiple, but: -// 1) Is only usable by players -// 2) Player must be looking at a point within bleft-tright of the origin of the trigger_look -// 3) If USE spawnflag (=8) is set, player must be pressing +use to trigger - -void trigger_look_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - trace_t tr; - vec_t dist; - vec3_t dir, forward, left, up, end, start; - - if(!other->client) - return; - - if (self->nextthink) - return; // already been triggered - - if( (self->spawnflags & TRIGGER_NEED_USE) && !(other->client->use)) - return; - - if( (self->spawnflags & TRIGGER_CAMOWNER) && !other->client->spycam) - return; - - if( self->spawnflags & 32 ) - { - // Then trigger only fires if looking at TARGET, not trigger bbox - edict_t *target; - int num_triggered=0; - edict_t *what; - vec3_t endpos; - - target = G_Find(NULL,FOFS(targetname),self->target); - while(target && !num_triggered) - { - what = LookingAt(other,0,endpos,NULL); - if(target->inuse && (LookingAt(other,0,NULL,NULL) == target)) - { - num_triggered++; - self->activator = other; - G_UseTarget (self, other, target); - } - else - target = G_Find(target,FOFS(targetname),self->target); - } - if(!num_triggered) - return; - } - else - { - if(other->client->spycam) - { - vec3_t f1, l1, u1; - - AngleVectors(other->client->spycam->s.angles, forward, left, up); - VectorScale(forward, other->client->spycam->move_origin[0],f1); - VectorScale(left, -other->client->spycam->move_origin[1],l1); - VectorScale(up, other->client->spycam->move_origin[2],u1); - VectorAdd(other->client->spycam->s.origin,f1,start); - VectorAdd(start,l1,start); - VectorAdd(start,u1,start); - } - else - { - AngleVectors(other->client->v_angle, forward, NULL, NULL); - VectorCopy(other->s.origin,start); - start[2] += other->viewheight; - } - VectorSubtract(self->s.origin,start,dir); - dist = VectorLength(dir); - VectorMA(start,dist,forward,end); - - tr = gi.trace(start,vec3_origin,vec3_origin,end,other,MASK_OPAQUE); - - // See if we're looking at origin, within bleft, tright - // FIXME: The following is more or less accurate if the - // bleft-tright box is roughly a cube. If it's considerably - // longer in one direction we'll get false misses. - - if(end[0] < self->s.origin[0] + self->bleft[0]) - return; - if(end[1] < self->s.origin[1] + self->bleft[1]) - return; - if(end[2] < self->s.origin[2] + self->bleft[2]) - return; - if(end[0] > self->s.origin[0] + self->tright[0]) - return; - if(end[1] > self->s.origin[1] + self->tright[1]) - return; - if(end[2] > self->s.origin[2] + self->tright[2]) - return; - - self->activator = other; - G_UseTargets (self, other); - } - - if (self->wait > 0) - { - self->think = multi_wait; - self->nextthink = level.time + self->wait; - } - else - { // we can't just remove (self) here, because this is a touch function - // called while looping through area links... - self->touch = NULL; - self->nextthink = level.time + FRAMETIME; - self->think = G_FreeEdict; - } - -} - -void trigger_look_enable (edict_t *self, edict_t *other, edict_t *activator); -void trigger_look_disable (edict_t *self, edict_t *other, edict_t *activator) -{ - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - else - { - self->solid = SOLID_NOT; - self->use = trigger_look_enable; - gi.linkentity (self); - } -} - -void trigger_look_enable (edict_t *self, edict_t *other, edict_t *activator) -{ - self->solid = SOLID_TRIGGER; - self->use = trigger_look_disable; - gi.linkentity (self); -} - -void SP_trigger_look (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_LOOK; - if (self->sounds == 1) - self->noise_index = gi.soundindex ("misc/secret.wav"); - else if (self->sounds == 2) - self->noise_index = gi.soundindex ("misc/talk.wav"); - else if (self->sounds == 3) - self->noise_index = -1; - - if (!self->wait) - self->wait = 0.2; - - if (self->spawnflags & TRIGGER_START_OFF) - { - self->solid = SOLID_NOT; - self->use = trigger_look_enable; - } - else - { - self->solid = SOLID_TRIGGER; - self->use = trigger_look_disable; - } - - self->movetype = MOVETYPE_NONE; - gi.setmodel (self, self->model); - self->svflags = SVF_NOCLIENT; - - if (self->spawnflags & TRIGGER_CAMOWNER) - self->svflags |= SVF_TRIGGER_CAMOWNER; - - if( (VectorLength(self->bleft) == 0) && (VectorLength(self->tright) == 0)) { - VectorSet(self->bleft,-16,-16,-16); - VectorSet(self->tright,16,16,16); - } - self->touch = trigger_look_touch; -} - -void trigger_speaker_think (edict_t *self) -{ - int i; - edict_t *touching; - edict_t *player; - - touching = NULL; - for (i = 1; i <= maxclients->value && !touching; i++) { - player = &g_edicts[i]; - if(!player->inuse) continue; - if(player->s.origin[0] < self->s.origin[0] + self->bleft[0]) continue; - if(player->s.origin[1] < self->s.origin[1] + self->bleft[1]) continue; - if(player->s.origin[2] < self->s.origin[2] + self->bleft[2]) continue; - if(player->s.origin[0] > self->s.origin[0] + self->tright[0]) continue; - if(player->s.origin[1] > self->s.origin[1] + self->tright[1]) continue; - if(player->s.origin[2] > self->s.origin[2] + self->tright[2]) continue; - touching = player; - } - if(touching) - gi.sound (touching, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); - self->nextthink = level.time + FRAMETIME; -} - -void trigger_speaker_enable (edict_t *self, edict_t *other, edict_t *activator); -void trigger_speaker_disable (edict_t *self, edict_t *other, edict_t *activator) -{ - self->use = trigger_speaker_enable; - self->think = NULL; - self->nextthink = 0; -} - -void trigger_speaker_enable (edict_t *self, edict_t *other, edict_t *activator) -{ - self->use = trigger_speaker_disable; - self->think = trigger_speaker_think; - self->think(self); -} - -void SP_trigger_speaker (edict_t *self) -{ - char buffer[MAX_QPATH]; - - self->class_id = ENTITY_TRIGGER_SPEAKER; - if(!st.noise) - { - gi.dprintf("trigger_speaker with no noise set at %s\n", vtos(self->s.origin)); - return; - } - if (!strstr (st.noise, ".wav")) - sprintf (buffer, "%s.wav", st.noise); - else - strncpy (buffer, st.noise, sizeof(buffer)); - self->noise_index = gi.soundindex (buffer); - - if(self->spawnflags & 1) { - self->use = trigger_speaker_disable; - self->think = trigger_speaker_think; - self->nextthink = level.time + FRAMETIME; - } else { - self->use = trigger_speaker_enable; - } - - if ( (!VectorLength(self->bleft)) && (!VectorLength(self->tright)) ) { - VectorSet(self->bleft,-16,-16,-16); - VectorSet(self->tright,16, 16, 16); - } - - -} - -//============================================================================== -// trigger_transition is a HL-like box that defines what entities will be -// moved from one map to another when a target_changelevel with the same -// targetname is fired. Brush models may NOT be moved. -//============================================================================== -void WriteEdict (file_t *f, edict_t *ent); - -bool HasSpawnFunction(edict_t *ent) -{ - spawn_t *s; - gitem_t *item; - int i; - - if(!ent->classname) - return false; - - // check item spawn functions - for (i=0,item=itemlist ; iclassname) - continue; - if (!strcmp(item->classname, ent->classname)) - return true; - } - // check normal spawn functions - for (s=spawns ; s->name ; s++) - { - if (!strcmp(s->name, ent->classname)) - return true; - } - return false; -} -void WriteTransitionEdict (file_t *f, edict_t *changelevel, edict_t *ent) -{ - byte *temp; - edict_t e; - field_t *field; - void *p; - - memcpy(&e,ent,sizeof(edict_t)); - if ( (e.class_id == ENTITY_TARGET_LASER) || - (e.class_id == ENTITY_TARGET_BLASTER) ) - vectoangles(e.movedir,e.s.angles); - - if (e.class_id == ENTITY_TARGET_SPEAKER) - e.spawnflags |= 8; // indicates that "message" contains noise - - if(changelevel->s.angles[YAW]) - { - vec3_t angles; - vec3_t forward, right, v; - vec3_t spawn_offset; - - VectorSubtract(e.s.origin,changelevel->s.origin,spawn_offset); - angles[PITCH] = angles[ROLL] = 0.; - angles[YAW] = changelevel->s.angles[YAW]; - AngleVectors(angles,forward,right,NULL); - VectorNegate(right,right); - VectorCopy(spawn_offset,v); - G_ProjectSource (vec3_origin, v, forward, right, spawn_offset); - VectorCopy(spawn_offset,e.s.origin); - VectorCopy(e.velocity,v); - G_ProjectSource (vec3_origin, v, forward, right, e.velocity); - e.s.angles[YAW] += angles[YAW]; - } - else - { - VectorSubtract(e.s.origin,changelevel->s.origin,e.s.origin); - } - // wipe out all edict_t and function members, since - // they won't be valid in the next map and might otherwise - // cause.... umm... big crash - temp = (byte *)&e; - for (field=fields ; field->name ; field++) - { - if((field->type == F_EDICT) || (field->type == F_FUNCTION)) - { - p = (void *)(temp + field->ofs); - *(edict_t **)p = NULL; - } - } - // Clean out a few more things - e.s.number = 0; - memset (&e.moveinfo, 0,sizeof(moveinfo_t)); - memset (&e.area, 0, sizeof(e.area)); - e.linkcount = 0; - e.nextthink = 0; - e.groundentity_linkcount = 0; - e.s.modelindex = 0; - e.s.weaponmodel = 0; - e.noise_index = 0; - // If the ent is a live bad guy monster, remove him from the total - // monster count. He'll be added back in in the new map. - if((e.svflags & SVF_MONSTER) && !(e.monsterinfo.aiflags & AI_GOOD_GUY)) - { - if(e.health > 0) - level.total_monsters--; - else - e.max_health = -1; - } - // Enemy isn't preserved... let's try a new flag for - // single-player only that tells monster to find - // the player again at startup - if(!coop->value && !deathmatch->value) - { - if(ent->enemy == &g_edicts[1] && ent->health > 0) - e.monsterinfo.aiflags = AI_RESPAWN_FINDPLAYER; - } - if(e.classname && - ( !strcasecmp(e.classname,"misc_actor") || strstr(e.classname,"monster_") ) && - (e.health <= e.gib_health) ) - { - e.classname = "gibhead"; - e.class_id = ENTITY_GIBHEAD; - } - WriteEdict(f,&e); -} - -entlist_t DoNotMove[] = { - {"crane_reset"}, - {"func_clock"}, - {"func_timer"}, - {"hint_path"}, - {"info_player_coop"}, - {"info_player_deathmatch"}, - {"info_player_intermission"}, - {"info_player_start"}, - {"light"}, - {"light_mine1"}, - {"light_mine2"}, - {"misc_strogg_ship"}, - {"misc_viper"}, - {"misc_viper_bomb"}, - {"model_train"}, - {"path_corner"}, - {"path_track"}, - {"point_combat"}, - {"target_actor"}, - {"target_changelevel"}, - {"target_character"}, - {"target_crosslevel_target"}, - {"target_crosslevel_trigger"}, - {"target_goal"}, - {"target_help"}, - {"target_lightramp"}, - {"target_locator"}, - {"target_lock"}, - {"target_lock_clue"}, - {"target_lock_code"}, - {"target_lock_digit"}, - {"target_rotation"}, - {"target_secret"}, - {"target_string"}, - {"trigger_always"}, - {"trigger_counter"}, - {"trigger_elevator"}, - {"trigger_key"}, - {"trigger_relay"}, - {"turret_driver"}, - {NULL}}; - -void trans_ent_filename (char *filename) -{ - GameDirRelativePath("save/trans.ent",filename); -} - -int trigger_transition_ents (edict_t *changelevel, edict_t *self) -{ - char t_file[_MAX_PATH]; - int i, j; - int total=0; - bool nogo; - edict_t *ent; - entlist_t *p; - file_t *f; - - trans_ent_filename(t_file); - f = gi.Fs.Open(t_file,"wb"); - if(!f) - { - gi.dprintf("Error opening %s for writing\n",t_file); - return 0; - } - // First scan entities for brush models that SHOULD change levels, e.g. func_tracktrain, - // which had better have a partner train in the next map... or we'll bitch loudly - for(i=game.maxclients+1; iinuse) continue; - if(ent->solid != SOLID_BSP) continue; - if(ent->s.origin[0] > self->maxs[0]) continue; - if(ent->s.origin[1] > self->maxs[1]) continue; - if(ent->s.origin[2] > self->maxs[2]) continue; - if(ent->s.origin[0] < self->mins[0]) continue; - if(ent->s.origin[1] < self->mins[1]) continue; - if(ent->s.origin[2] < self->mins[2]) continue; - if( (ent->class_id == ENTITY_FUNC_TRACKTRAIN) && !(ent->spawnflags & 8) && ent->targetname) - { - edict_t *e; - - e = G_Spawn(); - e->classname = TagMalloc(17,TAG_LEVEL); - strcpy(e->classname,"info_train_start"); - e->targetname = TagMalloc(strlen(ent->targetname)+1,TAG_LEVEL); - strcpy(e->targetname,ent->targetname); - e->target = TagMalloc(strlen(ent->target)+1,TAG_LEVEL); - strcpy(e->target,ent->target); - e->spawnflags = ent->spawnflags; - VectorCopy(ent->s.origin,e->s.origin); - VectorCopy(ent->s.angles,e->s.angles); - VectorCopy(ent->offset, e->offset); - VectorCopy(ent->bleft, e->bleft); - VectorCopy(ent->tright, e->tright); - e->sounds = ent->sounds; - e->viewheight = ent->viewheight; - e->speed = ent->moveinfo.speed; - // misuse/abuse a couple of entries to copy moveinfo stuff: - e->count = ent->moveinfo.state; - e->radius = ent->moveinfo.distance; - e->solid = SOLID_NOT; - e->svflags |= SVF_NOCLIENT; - if(ent->owner) - e->style = ent->owner - g_edicts; - else - e->style = 0; - gi.linkentity(e); - - ent->owner = NULL; - ent->spawnflags |= 24; // SF_TRACKTRAIN_OTHERMAP | SF_TRACKTRAIN_DISABLED - VectorClear(ent->velocity); - VectorClear(ent->avelocity); - ent->moveinfo.state = ent->moveinfo.prevstate = 0; // STOP - gi.linkentity(ent); - } - } - - for(i=game.maxclients+1; iid = 0; - if(!ent->inuse) continue; - // Pass up owned entities not owned by the player on this pass... - // get 'em next pass so we'll know whether owner is in our list - if(ent->owner && !ent->owner->client) continue; - if(ent->movewith) continue; - if(ent->s.origin[0] > self->maxs[0]) continue; - if(ent->s.origin[1] > self->maxs[1]) continue; - if(ent->s.origin[2] > self->maxs[2]) continue; - if(ent->s.origin[0] < self->mins[0]) continue; - if(ent->s.origin[1] < self->mins[1]) continue; - if(ent->s.origin[2] < self->mins[2]) continue; - if(ent->solid == SOLID_BSP) continue; - if((ent->solid == SOLID_TRIGGER) && !FindItemByClassname(ent->classname)) continue; - // Do not under any circumstances move these entities: - for(p=DoNotMove, nogo=false; p->name && !nogo; p++) - if(!strcasecmp(ent->classname,p->name)) - nogo = true; - if(nogo) continue; - if(!HasSpawnFunction(ent)) continue; - total++; - ent->id = total; - if(ent->owner) - ent->owner_id = -(ent->owner - g_edicts); - else - ent->owner_id = 0; - WriteTransitionEdict(f,changelevel,ent); - gi.unlinkentity(ent); - ent->inuse = false; - } - // Repeat, ONLY for ents owned by non-players - for(i=game.maxclients+1; iinuse) continue; - if(!ent->owner) continue; - if(ent->owner->client) continue; - if(ent->movewith) continue; - if(ent->solid == SOLID_BSP) continue; - if((ent->solid == SOLID_TRIGGER) && !FindItemByClassname(ent->classname)) continue; - // Do not under any circumstances move these entities: - for(p=DoNotMove, nogo=false; p->name && !nogo; p++) - if(!strcasecmp(ent->classname,p->name)) - nogo = true; - if(nogo) continue; - if(!HasSpawnFunction(ent)) continue; - if(ent->s.origin[0] > self->maxs[0]) continue; - if(ent->s.origin[1] > self->maxs[1]) continue; - if(ent->s.origin[2] > self->maxs[2]) continue; - if(ent->s.origin[0] < self->mins[0]) continue; - if(ent->s.origin[1] < self->mins[1]) continue; - if(ent->s.origin[2] < self->mins[2]) continue; - ent->owner_id = 0; - for(j=game.maxclients+1; jowner_id; j++) - { - if(ent->owner == &g_edicts[j]) - ent->owner_id = g_edicts[j].id; - } - if(!ent->owner_id) continue; - total++; - ent->id = total; - WriteTransitionEdict(f,changelevel,ent); - gi.unlinkentity(ent); - ent->inuse = false; - } - - gi.Fs.Close(f); - return total; -} - -void SP_trigger_transition (edict_t *self) -{ - if(!self->targetname) - { - gi.dprintf("trigger_transition w/o a targetname\n"); - G_FreeEdict(self); - } - self->class_id = ENTITY_TRIGGER_TRANSITION; - self->solid = SOLID_NOT; - self->movetype = MOVETYPE_NONE; - gi.setmodel (self, self->model); - self->svflags = SVF_NOCLIENT; -} - -// *************************** -// TRIGGER_DISGUISE - straight from Rogue MP -// *************************** - -/*QUAKED trigger_disguise (.5 .5 .5) ? TOGGLE START_ON REMOVE -Anything passing through this trigger when it is active will -be marked as disguised. - -TOGGLE - field is turned off and on when used. -START_ON - field is active when spawned. -REMOVE - field removes the disguise -*/ - -void trigger_disguise_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other->client) - { - if(self->spawnflags & 4) - other->flags &= ~FL_DISGUISED; - else - other->flags |= FL_DISGUISED; - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + FRAMETIME; - } - } -} - -void trigger_disguise_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->solid == SOLID_NOT) - self->solid = SOLID_TRIGGER; - else - self->solid = SOLID_NOT; - - gi.linkentity(self); -} - -void SP_trigger_disguise (edict_t *self) -{ - self->class_id = ENTITY_TRIGGER_DISGUISE; - if(self->spawnflags & 2) - self->solid = SOLID_TRIGGER; - else - self->solid = SOLID_NOT; - - self->touch = trigger_disguise_touch; - self->use = trigger_disguise_use; - self->movetype = MOVETYPE_NONE; - self->svflags = SVF_NOCLIENT; - - gi.setmodel (self, self->model); - gi.linkentity(self); - -} - -/* ============================================================================ - TRIGGER_SWITCH - - Identical to trigger_multiple in just about every way, except that - it only turns entities ON if they're currently OFF (default operation) or - OFF if they're currently ON and TRIGGER_TARGET_OFF spawnflag is set. - -==============================================================================*/ - -void trigger_switch_usetargets (edict_t *ent, edict_t *activator); -void trigger_switch_delay (edict_t *ent) -{ - trigger_switch_usetargets (ent, ent->activator); - G_FreeEdict (ent); -} - -void trigger_switch_usetargets (edict_t *ent, edict_t *activator) -{ - edict_t *t; - -// -// check for a delay -// - if (ent->delay) - { - // create a temp object to fire at a later time - t = G_Spawn(); - t->classname = "DelayedUse"; - t->nextthink = level.time + ent->delay; - t->think = trigger_switch_delay; - t->activator = activator; - if (!activator) - gi.dprintf ("Delay with no activator\n"); - t->message = ent->message; - t->target = ent->target; - t->killtarget = ent->killtarget; - t->noise_index = ent->noise_index; - return; - } - - -// -// print the message -// - if ((ent->message) && !(activator->svflags & SVF_MONSTER)) - { -// Lazarus - change so that noise_index < 0 means no sound - gi.centerprintf (activator, "%s", ent->message); - if (ent->noise_index > 0) - gi.sound (activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0); - else if (ent->noise_index == 0) - gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); - } - -// -// kill killtargets -// - if (ent->killtarget) - { - t = NULL; - while ((t = G_Find (t, FOFS(targetname), ent->killtarget))) - { - // Lazarus: remove LIVE killtargeted monsters from total_monsters - if((t->svflags & SVF_MONSTER) && (t->deadflag == DEAD_NO)) - { - if(!t->dmgteam || strcmp(t->dmgteam,"player")) - if(!(t->monsterinfo.aiflags & AI_GOOD_GUY)) - level.total_monsters--; - } - // and decrement secret count if target_secret is removed - else if(t->class_id == ENTITY_TARGET_SECRET) - level.total_secrets--; - // same deal with target_goal, but also turn off CD music if applicable - else if(t->class_id == ENTITY_TARGET_GOAL) - { - level.total_goals--; - if (level.found_goals >= level.total_goals) - gi.configstring (CS_CDTRACK, "0"); - } - G_FreeEdict (t); - if (!ent->inuse) - { - gi.dprintf("entity was removed while using killtargets\n"); - return; - } - } - } - -// -// fire targets -// - if (ent->target) - { - int on; - - t = NULL; - while ((t = G_Find (t, FOFS(targetname), ent->target))) - { - if (t == ent) - { - gi.dprintf ("WARNING: Entity used itself.\n"); - } - else if(t->use) - { - on = 0; - switch(t->class_id) - { - case ENTITY_FUNC_CONVEYOR: - case ENTITY_FUNC_FORCE_WALL: - case ENTITY_FUNC_WALL: - if(t->solid == SOLID_BSP) - on=1; - break; - case ENTITY_FUNC_PENDULUM: - case ENTITY_FUNC_TRAIN: - case ENTITY_MISC_STROGG_SHIP: - case ENTITY_MISC_VIPER: - case ENTITY_MODEL_TRAIN: - case ENTITY_TARGET_ATTRACTOR: - case ENTITY_TARGET_FOG: - case ENTITY_TARGET_FOUNTAIN: - case ENTITY_TARGET_LASER: - case ENTITY_TARGET_PRECIPITATION: - if(t->spawnflags & 1) - on=1; - break; - case ENTITY_FUNC_REFLECT: - if(!(t->spawnflags & 1)) - on=1; - break; - case ENTITY_FUNC_ROTATING: - on = VectorCompare (t->avelocity, vec3_origin); - break; - case ENTITY_FUNC_TIMER: - if(t->nextthink) - on=1; - break; - case ENTITY_FUNC_TRACKTRAIN: - if(!(t->spawnflags & 128)) - on=1; - break; - case ENTITY_MODEL_TURRET: - case ENTITY_TURRET_BREACH: - if(t->spawnflags & 16) - on=1; - break; - case ENTITY_TARGET_EFFECT: - if(t->spawnflags & 3) - { - if(t->spawnflags & 1) - on=1; - } - else - on = -1; - break; - case ENTITY_TARGET_SPEAKER: - if(t->spawnflags & 3) - { - if(t->s.sound) - on=1; - } - else - on=-1; - break; - default: - on=-1; - } - - - if(ent->spawnflags & TRIGGER_TARGET_OFF) - { - // Only use target if it is currently ON - if(on==1) - t->use (t, ent, activator); - } - else if(on==0) - { - // Only use target if it is currently OFF - t->use (t, ent, activator); - } - } - if (!ent->inuse) - { - gi.dprintf("entity was removed while using targets\n"); - return; - } - } - } -} - -void trigger_switch (edict_t *ent) -{ - if (ent->nextthink) - return; // already been triggered - - trigger_switch_usetargets (ent, ent->activator); - - if (ent->wait > 0) - { - ent->think = multi_wait; - ent->nextthink = level.time + ent->wait; - } - else - { // we can't just remove (self) here, because this is a touch function - // called while looping through area links... - ent->touch = NULL; - ent->nextthink = level.time + FRAMETIME; - ent->think = G_FreeEdict; - } -} - -void touch_trigger_switch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if(other->client || (other->flags & FL_ROBOT)) - { - if (self->spawnflags & TRIGGER_NOT_PLAYER) - return; - } - else if (other->svflags & SVF_MONSTER) - { - if (!(self->spawnflags & TRIGGER_MONSTER)) - return; - } - else - return; - - if( (self->spawnflags & TRIGGER_CAMOWNER) && (!other->client || !other->client->spycam)) - return; - - if (!VectorCompare(self->movedir, vec3_origin)) - { - vec3_t forward; - - AngleVectors(other->s.angles, forward, NULL, NULL); - if (DotProduct(forward, self->movedir) < 0) - return; - } - - self->activator = other; - trigger_switch (self); -} - -void use_trigger_switch (edict_t *ent, edict_t *other, edict_t *activator) -{ - ent->activator = activator; - trigger_switch (ent); -} - -void SP_trigger_switch (edict_t *ent) -{ - ent->class_id = ENTITY_TRIGGER_SWITCH; - if (ent->sounds == 1) - ent->noise_index = gi.soundindex ("misc/secret.wav"); - else if (ent->sounds == 2) - ent->noise_index = gi.soundindex ("misc/talk.wav"); - else if (ent->sounds == 3) - ent->noise_index = -1; - - if (!ent->wait) - ent->wait = 0.2; - ent->touch = touch_trigger_switch; - ent->movetype = MOVETYPE_NONE; - ent->svflags |= SVF_NOCLIENT; - - if (ent->spawnflags & TRIGGER_CAMOWNER) - ent->svflags |= SVF_TRIGGER_CAMOWNER; - - if (ent->spawnflags & TRIGGER_START_OFF) - { - ent->solid = SOLID_NOT; - ent->use = trigger_enable; - } - else - { - ent->solid = SOLID_TRIGGER; - ent->use = use_trigger_switch; - } - - if (!VectorCompare(ent->s.angles, vec3_origin)) - G_SetMovedir (ent->s.angles, ent->movedir); - - gi.setmodel (ent, ent->model); - gi.linkentity (ent); -} - -// end DWH diff --git a/server/ents/g_turret.c b/server/ents/g_turret.c deleted file mode 100644 index b2ec4eef..00000000 --- a/server/ents/g_turret.c +++ /dev/null @@ -1,1479 +0,0 @@ -// g_turret.c - -#include "g_local.h" - -#define SF_TURRETDRIVER_REMOTE_DRIVER 1 -#define SF_TURRET_PLAYER_CONTROLLABLE 1 -#define SF_TURRET_TRIGGER_SPAWN 2 -#define SF_TURRET_TRACKING 4 -#define SF_TURRET_GOODGUY 8 -#define SF_TURRET_INACTIVE 16 -#define SF_TURRET_MD2 32 - -void NoAmmoWeaponChange (edict_t *ent); - -#define TURRET_GRENADE_SPEED 800 - -// DWH - Added TurretTarget to scan the player's view for a damageable target. -// Used with homing rockets -edict_t *TurretTarget(edict_t *self) -{ - float bd, d; - int i; - edict_t *who, *best; - trace_t tr; - vec3_t dir, end, forward, right, up, start; - - AngleVectors(self->s.angles, forward, right, up); - VectorMA(self->s.origin, self->move_origin[0], forward, start); - VectorMA(start, self->move_origin[1], right, start); - VectorMA(start, self->move_origin[2], up, start); - VectorMA(start, 8192, forward, end); - - /* Check for aiming directly at a damageable entity */ - tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT); - if ((tr.ent->takedamage != DAMAGE_NO) && (tr.ent->solid != SOLID_NOT)) - return tr.ent; - - /* Check for damageable entity within a tolerance of view angle */ - bd = 0; - best = NULL; - for (i=1, who=g_edicts+1; iinuse) - continue; - if (who->takedamage == DAMAGE_NO) - continue; - if (who->solid == SOLID_NOT) - continue; - VectorMA(who->absmin,0.5,who->size,end); - tr = gi.trace (start, vec3_origin, vec3_origin, end, self, MASK_OPAQUE); - if(tr.fraction < 1.0) - continue; - VectorSubtract(end, self->s.origin, dir); - VectorNormalize(dir); - d = DotProduct(forward, dir); - if (d > bd) { - bd = d; - best = who; - } - } - if (bd > 0.90) - return best; - - return NULL; -} -// end DWH - -void turret_blocked(edict_t *self, edict_t *other) -{ - edict_t *attacker; - edict_t *ent; - edict_t *master; - - if (other == world) { - // world brush - stop - self->avelocity[YAW] = 0; - if (self->team) { - for (ent = self->teammaster; ent; ent = ent->teamchain) - ent->avelocity[YAW] = 0; - } - if(self->owner) - self->owner->avelocity[YAW] = 0; - gi.linkentity(self); - } - - if (other->takedamage) - { - vec3_t dir; - VectorSubtract(other->s.origin,self->s.origin,dir); - VectorNormalize(dir); - - if (self->teammaster) - master = self->teammaster; - else - master = self; - - if (self->teammaster) { - if (self->teammaster->owner) - attacker = self->teammaster->owner; - else - attacker = self->teammaster; - } else if(self->owner) { - attacker = self->owner; - } else { - attacker = self; - } - // give a big kickback to help prevent getting stuck - T_Damage (other, self, attacker, dir, other->s.origin, vec3_origin, master->dmg, 50, 0, MOD_CRUSH); - } - if (!(other->svflags & SVF_MONSTER) && (!other->client)) - { - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - - if (other) - BecomeExplosion1 (other); - return; - } -} - -void turret_breach_fire (edict_t *self) -{ - edict_t *owner; - vec3_t forward, right, up; - vec3_t start; - int damage; - int speed; - - AngleVectors (self->s.angles, forward, right, up); - VectorMA (self->s.origin, self->move_origin[0], forward, start); - VectorMA (start, self->move_origin[1], right, start); - VectorMA (start, self->move_origin[2], up, start); - - speed = 550 + 50 * skill->value; - - // DWH: automated turrets have no driver, so use self - if(self->owner && !(self->owner->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER)) - owner = self->owner; - else - owner = self; - /* - ed - self->teammaster->owner causes quake 2 to crash when the player uses BUTTON_SHOOT - its been changed to self->owner incase anything weird happens. - */ - - //FIXME : only use the normal damages if self->owner (turret_driver) doesn't have one - - if(self->delay < level.time) - { - switch (self->sounds) - { - case 1: // railgun - { - damage = 150; - fire_rail (owner, start, forward, damage, 0); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/railgf1a.wav"), 1, ATTN_NORM, 0); - - //ed - muzzleflash ? on a turret ? Yeah baby - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (self-g_edicts); - WRITE_BYTE (MZ_RAILGUN); - MESSAGE_SEND (MSG_PVS, start, NULL); - - self->delay = level.time + self->wait; - - break; - } - case 2: // rocket - { - damage = 100 + random() * 50; - fire_rocket (owner, start, forward, damage, speed, 150, damage, NULL); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); - - self->delay = level.time + self->wait; - - break; - } - case 3: // BFG - { - damage = 500; - fire_bfg (owner, start, forward, damage, speed, 1000); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/laser2.wav"), 1, ATTN_NORM, 0); - - self->delay = level.time + self->wait; - - break; - } - case 4: // Homing rockets - { - damage = 100 + random() * 50; - if(owner->target_ent == self || owner == self) { - // monster-controlled or automated turret - fire_rocket (owner, start, forward, damage, speed, 150, damage, owner->enemy); - } else if(self->spawnflags & SF_TURRET_PLAYER_CONTROLLABLE) { - // what is player aiming at? - edict_t *target; - target = TurretTarget(self); - fire_rocket (owner, start, forward, damage, speed, 150, damage, target); - } else { - // shouldn't be possible to get here - fire_rocket (owner, start, forward, damage, speed, 150, damage, NULL); - } - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); - - self->delay = level.time + self->wait; - - break; - } - case 5: // Machinegun - { - // "wait" = damage for machinegun - default = 2 - fire_bullet (owner, start, forward, self->wait, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (self-g_edicts); - WRITE_BYTE (MZ_MACHINEGUN); - MESSAGE_SEND (MSG_PVS, start, NULL); - self->delay = level.time; // No delay on machinegun - break; - } - case 6: // Hyperblaster - { - fire_blaster (owner, start, forward, self->wait, 1000, EF_HYPERBLASTER, true); - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/hyprbf1a.wav"),1,ATTN_NORM,0); - self->delay = level.time; // No delay - break; - } - case 7: // Grenade launcher - { - fire_grenade (owner, start, forward, 50, self->fog_far, 2.5, 90); - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (MZ2_GUNNER_GRENADE_1); - MESSAGE_SEND (MSG_PVS, start, NULL); - self->delay = level.time + self->wait; - break; - } - default: - { - damage = 100; - fire_rocket (owner, start, forward, damage, speed, 150, damage, NULL); - gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); - - self->delay = level.time + self->wait; - - break; - } - } - } -} - -void turret_disengage (edict_t *self) -{ - int i; - edict_t *ent; - vec3_t forward; - - // level the gun - self->move_angles[0] = 0; - - ent = self->owner; - - //ed - to keep remove tracking of the entity - ent->turret = NULL; - - // throw them back from turret - AngleVectors(self->s.angles, forward, NULL, NULL); - VectorScale(forward, -300, forward); - forward[2] = forward[2] + 150; - if (forward[2] < 80) - forward[2] = 80; - - for (i=0; i<3; i++) - ent->velocity[i] = forward[i]; - - ent->s.origin[2] = ent->s.origin[2] + 1; - ent->movetype = MOVETYPE_WALK; - ent->gravity = 1; - - ent->flags &= ~FL_TURRET_OWNER; - - // turn ON client side prediction for this player - ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - - gi.linkentity (ent); - - self->owner = NULL; -} -void turret_turn (edict_t *self) -{ - vec3_t current_angles; - vec3_t delta; - bool yaw_restrict; - - VectorCopy (self->s.angles, current_angles); - AnglesNormalize(current_angles); - - if(self->viewer && self->viewer->client) - { - gclient_t *client = self->viewer->client; - - if( (client->old_owner_angles[0] != client->ucmd.angles[0]) || - (client->old_owner_angles[1] != client->ucmd.angles[1]) ) - { - // Give game a bit of time to catch up after player - // causes ucmd pitch angle to roll over... otherwise - // we'll hit on the above test even though player - // hasn't hit +lookup/+lookdown - float delta; - delta = level.time - self->touch_debounce_time; - if( delta < 0 || delta > 1.0) - { - float delta_angle; - float fastest = self->speed * FRAMETIME; - - delta_angle = SHORT2ANGLE(client->ucmd.angles[0]-client->old_owner_angles[0]); - if(delta_angle < -180) - delta_angle += 360; - if(delta_angle > 180) - delta_angle -= 360; - if(delta_angle > fastest) - delta_angle = fastest; - if(delta_angle < -fastest) - delta_angle = -fastest; - self->move_angles[0] += delta_angle; - - delta_angle = SHORT2ANGLE(client->ucmd.angles[1]-client->old_owner_angles[1]); - if(delta_angle < -180) - delta_angle += 360; - if(delta_angle > 180) - delta_angle -= 360; - if(delta_angle > fastest) - delta_angle = fastest; - if(delta_angle < -fastest) - delta_angle = -fastest; - self->move_angles[1] += delta_angle; - - client->old_owner_angles[0] = client->ucmd.angles[0]; - client->old_owner_angles[1] = client->ucmd.angles[1]; - } - self->touch_debounce_time = level.time + 5.0; - } - } - -//======= - AnglesNormalize(self->move_angles); - - // clamp angles to mins & maxs - if (self->move_angles[PITCH] > self->pos1[PITCH]) - self->move_angles[PITCH] = self->pos1[PITCH]; - else if (self->move_angles[PITCH] < self->pos2[PITCH]) - self->move_angles[PITCH] = self->pos2[PITCH]; - - // Lazarus: Special case - if there are no constraints on YAW, don't - // adjust angle - if (self->pos1[YAW] != 0 || self->pos2[YAW] != 360) - yaw_restrict = true; - else - yaw_restrict = false; - - if ( yaw_restrict ) { - float yaw_range; - float yaw_base; - yaw_range = self->pos2[YAW] - self->pos1[YAW]; - if(yaw_range < 0) - yaw_range += 360; - yaw_base = self->move_angles[YAW] - self->pos1[YAW]; - if(yaw_base < 0) - yaw_base += 360; - if (yaw_base > yaw_range) - { - float dmin, dmax; - - dmin = fabs(self->pos1[YAW] - self->move_angles[YAW]); - if (dmin < 0 ) - dmin += 360; - else if (dmin > 360) - dmin -= 360; - dmax = fabs(self->pos2[YAW] - self->move_angles[YAW]); - if (dmax < 0) - dmax += 360; - else if (dmax > 360) - dmax -= 360; - if (fabs(dmin) < fabs(dmax)) - self->move_angles[YAW] = self->pos1[YAW]; - else - self->move_angles[YAW] = self->pos2[YAW]; - } - } - - VectorSubtract (self->move_angles, current_angles, delta); - if (delta[0] < -180) - delta[0] += 360; - else if (delta[0] > 180) - delta[0] -= 360; - if (delta[1] < -180) - delta[1] += 360; - else if (delta[1] > 180) - delta[1] -= 360; - delta[2] = 0; - -// gi.dprintf("move=%g, current=%g, delta=%g, pos1=%g, pos2=%g\n", -// self->move_angles[PITCH],current_angles[PITCH],delta[PITCH],self->pos1[PITCH],self->pos2[PITCH]); - - VectorScale (delta, 1.0/FRAMETIME, delta); - if (delta[0] > self->speed) - delta[0] = self->speed; - if (delta[0] < -self->speed) - delta[0] = -self->speed; - if (delta[1] > self->speed) - delta[1] = self->speed; - if (delta[1] < -self->speed) - delta[1] = -self->speed; - VectorCopy (delta, self->avelocity); - - if (self->team) { - edict_t *ent; - for (ent = self->teammaster; ent; ent = ent->teamchain) - { - ent->avelocity[1] = self->avelocity[1]; - if(ent->solid == SOLID_NOT) - ent->avelocity[0] = self->avelocity[0]; - } - } -} - -void turret_breach_think (edict_t *self) -{ - edict_t *ent; - edict_t *victim; - trace_t tr; - vec3_t dir, angles; - vec3_t target; - bool remote_monster; - bool yaw_restrict; - float yaw_r, yaw_0; - int i; - - turret_turn(self); - yaw_r = self->pos2[YAW] - self->pos1[YAW]; - if(yaw_r < 0) - yaw_r += 360; - - if (self->pos1[YAW] != 0 || self->pos2[YAW] != 360) - yaw_restrict = true; - else - yaw_restrict = false; - - self->nextthink = level.time + FRAMETIME; - - if(self->deadflag == DEAD_DEAD) return; - - if ( (self->owner) && (self->owner->target_ent == self) && - (self->owner->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER)) - remote_monster = true; - else - remote_monster = false; - - if (self->owner || self->viewer) { - if( !(self->spawnflags & SF_TURRET_MD2)) - { - self->s.effects &= ~EF_ANIM23; - self->s.effects |= EF_ANIM01; - } - self->do_not_rotate = true; - } else { - if( !(self->spawnflags & SF_TURRET_MD2)) - { - self->s.effects &= ~EF_ANIM01; - self->s.effects |= EF_ANIM23; - } - self->do_not_rotate = false; - } - if (self->team) { - for (ent = self->teammaster; ent; ent = ent->teamchain) { - if(ent != self->owner) - { - if(ent->solid != SOLID_NOT) - ent->s.effects = self->s.effects; - ent->do_not_rotate = self->do_not_rotate; - } - } - } - - // if we have a driver, adjust his velocities - if (self->owner && !remote_monster) - { - if (self->owner->target_ent == self) - { - float angle; - float diff; - float target_z; - vec3_t dir; - - // angular is easy, just copy ours - self->owner->avelocity[0] = self->avelocity[0]; - self->owner->avelocity[1] = self->avelocity[1]; - - // x & y - angle = self->s.angles[1] + self->owner->move_origin[1]; - angle *= (M_PI*2 / 360); - target[0] = SnapToEights(self->s.origin[0] + cos(angle) * self->owner->move_origin[0]); - target[1] = SnapToEights(self->s.origin[1] + sin(angle) * self->owner->move_origin[0]); - target[2] = self->owner->s.origin[2]; - - VectorSubtract (target, self->owner->s.origin, dir); - self->owner->velocity[0] = dir[0] * 1.0 / FRAMETIME; - self->owner->velocity[1] = dir[1] * 1.0 / FRAMETIME; - - // z - angle = self->s.angles[PITCH] * (M_PI*2 / 360); - target_z = SnapToEights(self->s.origin[2] + self->owner->move_origin[0] * tan(angle) + self->owner->move_origin[2]); - - diff = target_z - self->owner->s.origin[2]; - self->owner->velocity[2] = diff * 1.0 / FRAMETIME; - - if (self->spawnflags & 65536) - { - turret_breach_fire (self); - self->spawnflags &= ~65536; - } - return; - } - else if(self->spawnflags & SF_TURRET_PLAYER_CONTROLLABLE) - { // a player is controlling the turret, move towards view angles - vec3_t target, forward; - - for (i=0; i<3; i++) - self->move_angles[i] = self->owner->client->v_angle[i]; - - // FIXME: do a tracebox from up and behind towards the turret, to try and keep them from - // getting stuck inside the rotating turret - // x & y - AngleVectors(self->s.angles, forward, NULL, NULL); - VectorScale(forward, 32, forward); - VectorSubtract(self->s.origin, forward, target); - - VectorAdd(target, tv(0,0,8), self->owner->s.origin); - - gi.linkentity(self->owner); - - if (self->owner->client->ps.pmove.velocity[2] > 15) - turret_disengage(self); - } - } - else if((self->spawnflags & SF_TURRET_PLAYER_CONTROLLABLE) && !remote_monster) - { // check if a player has mounted the turret - - int i; - edict_t *ent; - vec3_t target, forward; - vec3_t dir; - - // find a player - ent = &g_edicts[0]; - ent++; - for (i=0 ; ivalue ; i++, ent++) - { - if (!ent->inuse) - continue; - if (ent->solid == SOLID_NOT) - continue; - - // determine distance from turret seat location - - // x & y - AngleVectors(self->s.angles, forward, NULL, NULL); - VectorScale(forward, 32, forward); - VectorSubtract(self->s.origin, forward, target); - - VectorSubtract (target, ent->s.origin, dir); - if (fabs(dir[2]) < 64) - dir[2] = 0; - - if (VectorLength(dir) < 16) - { // player has taken control of turret - self->owner = ent; - ent->movetype = MOVETYPE_PUSH; // don't let them move, or they'll get stuck - ent->gravity = 0; - - //ed - to keep track of the entity - ent->turret = self; - - // turn off client side prediction for this player - ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - - gi.linkentity(ent); - - //ed - set the flag on the client so that when they shoot the - // turret shoots instead of "using" it - ent->flags |= FL_TURRET_OWNER; - } - } - } - if ((self->spawnflags & SF_TURRET_TRACKING) && ((!self->owner) || remote_monster)) { - // TRACK - automated turret - float reaction_time; - vec3_t f, forward, right, up, start, t_start; - edict_t *gomer; - float best_dist = 8192; - float dist; - - if(self->viewer && level.time < self->touch_debounce_time) - return; - - AngleVectors(self->s.angles, forward, right, up); - VectorMA(self->s.origin,self->move_origin[0],forward,start); - VectorMA(start, self->move_origin[1],right, start); - VectorMA(start, self->move_origin[2],up, start); - - self->oldenemy = self->enemy; - - if(self->enemy) { - // check that current enemy is valid. if so, find - // distance. don't switch enemies unless another - // monster is at least 100 units closer to the camera - if(self->enemy->inuse) { - if((self->enemy->health > self->enemy->gib_health) && - !(self->enemy->svflags & SVF_NOCLIENT) && - !(self->enemy->flags & FL_NOTARGET) ) { - if(gi.inPVS(self->s.origin,self->enemy->s.origin)) { - VectorMA(self->enemy->absmin,0.5,self->enemy->size,target); - VectorSubtract(target,self->s.origin,dir); - vectoangles(dir,angles); - AnglesNormalize(angles); - if ( yaw_restrict ) - { - yaw_0 = angles[YAW] - self->pos1[YAW]; - if(yaw_0 < 0) - yaw_0 += 360; - } - if( (angles[PITCH] > self->pos1[PITCH]) || (angles[PITCH] < self->pos2[PITCH]) || - ( yaw_restrict && (yaw_0 > yaw_r) ) ) { - self->enemy = NULL; - } else { - VectorCopy(self->s.origin,t_start); - VectorCopy(dir,f); - VectorNormalize(f); - VectorMA(t_start,self->teammaster->base_radius,f,t_start); - tr = gi.trace(t_start,vec3_origin,vec3_origin,target,self,MASK_SHOT); - if(tr.ent == self->enemy) { - VectorSubtract(target,self->s.origin,dir); - best_dist = VectorLength(dir) - 100; - } else - self->enemy = NULL; - } - } else { - self->enemy = NULL; - } - } else - self->enemy = NULL; - } else - self->enemy = NULL; - } - - // for GOODGUY weapon-firing turrets, if current enemy is a player or GOODGUY monster, - // reset best_dist so that bad monsters will be selected if found, regardless of distance. - if( (self->enemy) && (self->sounds >= 0) && (self->spawnflags & SF_TURRET_GOODGUY)) { - if((self->enemy->client) || (self->enemy->monsterinfo.aiflags & AI_GOOD_GUY)) - best_dist = 8192; - } - - // hunt for monster - if(!remote_monster) { - for(i=maxclients->value+1; ienemy) continue; // no need to re-check this guy - if(!gomer->inuse) continue; - if(!(gomer->svflags & SVF_MONSTER)) continue; - if(gomer->health < gomer->gib_health) continue; - if(gomer->svflags & SVF_NOCLIENT) continue; - if(!gi.inPVS(self->s.origin,gomer->s.origin)) continue; - VectorMA(gomer->absmin,0.5,gomer->size,target); - VectorCopy(self->s.origin,t_start); - VectorSubtract(target,self->s.origin,dir); - VectorCopy(dir,f); - VectorNormalize(f); - VectorMA(t_start,self->teammaster->base_radius,f,t_start); - tr = gi.trace(t_start,vec3_origin,vec3_origin,target,self,MASK_SHOT); - if(tr.ent == gomer) { - vectoangles(dir,angles); - AnglesNormalize(angles); - if ( yaw_restrict ) - { - yaw_0 = angles[YAW] - self->pos1[YAW]; - if(yaw_0 < 0) - yaw_0 += 360; - } - if( (angles[PITCH] <= self->pos1[PITCH]) && (angles[PITCH] >= self->pos2[PITCH]) && - ( !yaw_restrict || (yaw_0 <= yaw_r) ) - ) { - dist = VectorLength(dir); - if(dist < best_dist) { - self->enemy = gomer; - best_dist = dist; - } - } - } - } - } - // for weapon-firing turrets, if GOODGUY is set and we already have an enemy, we're - // done. - if( (self->sounds >= 0) && (self->spawnflags & SF_TURRET_GOODGUY) && self->enemy) - goto good_enemy; - - // for non-GOODGUY weapon-firing turrets, reset best_dist so that players will - // ALWAYS be selected if found - if( (self->sounds >= 0) && !(self->spawnflags & SF_TURRET_GOODGUY)) - best_dist = 8192; - - // hunt for closest player - hunt ALL entities since - // we want to view fake players using camera - for(i=1; iinuse) continue; - if(!gomer->client) continue; - if(gomer->svflags & SVF_NOCLIENT) continue; - if(gomer->health < gomer->gib_health) continue; - if(gomer->flags & FL_NOTARGET) continue; - if(!gi.inPVS(self->s.origin,gomer->s.origin)) continue; - VectorMA(gomer->absmin,0.5,gomer->size,target); - - VectorCopy(self->s.origin,t_start); - VectorSubtract(target,self->s.origin,dir); - VectorCopy(dir,f); - VectorNormalize(f); - VectorMA(t_start,self->teammaster->base_radius,f,t_start); - tr = gi.trace(t_start,vec3_origin,vec3_origin,target,self,MASK_SHOT); - if(tr.ent == gomer) { - vectoangles(dir,angles); - AnglesNormalize(angles); - if ( yaw_restrict ) - { - yaw_0 = angles[YAW] - self->pos1[YAW]; - if(yaw_0 < 0) - yaw_0 += 360; - } - if( (angles[PITCH] <= self->pos1[PITCH]) && (angles[PITCH] >= self->pos2[PITCH]) && - ( !yaw_restrict || (yaw_0 <= yaw_r) ) ) { - dist = VectorLength(dir); - if(dist < best_dist) { - self->enemy = gomer; - best_dist = dist; - } - } - } - } - -good_enemy: - if(self->enemy) - { - if(self->enemy != self->oldenemy) { - self->monsterinfo.trail_time = level.time; - self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; - } - VectorCopy (self->enemy->s.origin, target); - if(self->enemy->deadflag) - target[2] -= 16; - if(skill->value >= 2) - { - VectorMA(target,FRAMETIME,self->enemy->velocity,target); - -/* May add some variant of this for skill 3 later. For now, the following is virtually - indistinguishable from skill 2 for most normal setups. Trouble is, it is sometimes - EASIER than skill 2. - - if(skill->value > 2) - { - float t; - VectorSubtract(target,self->s.origin,dir); - VectorNormalize(dir); - vectoangles(dir,dir); - VectorSubtract(dir,self->s.angles,dir); - AnglesNormalize(dir); - dir[2] = max( fabs(dir[0]), fabs(dir[1]) ); - if(dir[2] > 0) - { - t = dir[2]/self->speed; - VectorMA(target,t,self->enemy->velocity,target); - } - } */ - } - if(self->sounds == 7) - { - if(!AimGrenade (self, start, target, self->fog_far, dir)) - { - // Can't get a grenade to target. Correct yaw but - // not pitch - - vec_t pitch = self->move_angles[PITCH]; - vectoangles (dir, self->move_angles); - self->move_angles[PITCH] = pitch; - if(skill->value > 0) - turret_turn(self); - return; - } - } - else - VectorSubtract (target, self->s.origin, dir); - VectorNormalize(dir); - vectoangles (dir, self->move_angles); - // decide if we should shoot - victim = NULL; - if(self->spawnflags & SF_TURRET_GOODGUY) - { - if((self->enemy->svflags & SVF_MONSTER) && !(self->enemy->monsterinfo.aiflags & AI_GOOD_GUY)) - victim = self->enemy; - } - else - { - if(self->enemy->client) - victim = self->enemy; - } - if(victim && self->sounds >= 0 && DotProduct(forward,dir) > 0.99) - { - // never automatically fire a turret remotely controlled by - // a player - if(!self->viewer || (self->viewer && !self->viewer->client)) - { - // don't fire rockets or homing rockets if remote turret_driver is - // too close to target - if(remote_monster) - { - vec3_t range; - vec_t r; - VectorSubtract(self->enemy->s.origin,self->owner->s.origin,range); - r = VectorLength(range); - if(r < 128) return; - } - if (level.time < self->monsterinfo.attack_finished) - { - if(skill->value > 0) - turret_turn(self); - return; - } - if(self->sounds == 5 || self->sounds == 6) - reaction_time = 0; - else - reaction_time = max(0., 0.5*(2-skill->value)); - if ((level.time - self->monsterinfo.trail_time) < reaction_time) - { - if(skill->value > 0) - turret_turn(self); - return; - } - self->monsterinfo.attack_finished = level.time + reaction_time; - if(self->sounds != 5 && self->sounds != 6) - self->monsterinfo.attack_finished += self->wait; - turret_breach_fire(self); - if(skill->value > 0) - turret_turn(self); - } - } - else - { - if(skill->value > 0) - turret_turn(self); - } - } - } - // If turret has no enemy and isn't controlled by a player or monster, - // check for "followtarget" - if ((!self->enemy) && ((!self->owner) || remote_monster)) - { - if(self->followtarget) - { - self->enemy = G_Find(NULL,FOFS(targetname),self->followtarget); - if(self->enemy) - { - VectorMA (self->enemy->absmin, 0.5, self->enemy->size, target); - VectorSubtract (target, self->s.origin, dir); - vectoangles (dir, self->move_angles); - if(skill->value > 0) - turret_turn(self); - } - } - } -} - -void turret_breach_finish_init (edict_t *self) -{ - // get and save info for muzzle location - if (!self->target) - { - gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin)); - } - else - { - self->target_ent = G_PickTarget (self->target); - if(!self->target_ent) - { - gi.dprintf("%s at %s, target %s does not exist\n", - self->classname,vtos(self->s.origin),self->target); - G_FreeEdict(self); - return; - } - VectorSubtract (self->target_ent->s.origin, self->s.origin, self->move_origin); - G_FreeEdict(self->target_ent); - } - - if (!self->team) - self->teammaster = self; - self->teammaster->dmg = self->dmg; - - if(!(self->spawnflags & (SF_TURRET_TRIGGER_SPAWN | SF_TURRET_GOODGUY | SF_TURRET_INACTIVE) )) { - self->think = turret_breach_think; - self->think (self); - } - else - { - self->think = NULL; - self->nextthink = 0; - } -} - -void turret_die_temp_think(edict_t *self) -{ - edict_t *target; - target = G_Find(NULL,FOFS(targetname),self->destroytarget); - while(target) { - if(target && target->use) - target->use(target,self->target_ent,self->target_ent); - target = G_Find(target,FOFS(targetname),self->destroytarget); - } - G_FreeEdict(self); -} - -void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); -void SP_monster_infantry (edict_t *self); -void monster_start_go(edict_t *self); -void turret_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int i; - edict_t *ent; - edict_t *player; - - // ensure turret_base stops rotating - if (self->team) { - for (ent = self->teammaster; ent; ent = ent->teamchain) { - if(ent != self) { - ent->avelocity[1] = 0; - gi.linkentity(ent); - } - } - } - - if(self->deadflag != DEAD_DEAD) { - - // if turret has a driver, kill him too unless he's a "remote" driver - if(self->owner && (self->owner->target_ent == self)) { - if(self->owner->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER) { - // remote driver - remove and replace with normal infantry - edict_t *monster; - monster = self->owner->child; - if(monster) { - monster->health = self->owner->health; - monster->enemy = self->owner->enemy; - G_FreeEdict(self->owner); - monster->solid = SOLID_BBOX; - monster->movetype = MOVETYPE_STEP; - monster->svflags &= ~SVF_NOCLIENT; - monster_start_go (monster); - gi.linkentity (monster); - if(monster->enemy) FoundTarget(monster); - } - } else { - T_Damage(self->owner, inflictor, attacker, vec3_origin, self->owner->s.origin, vec3_origin, 100000, 1, 0, 0); - } - } - // if turret is being used as a camera by a player, turn camera off for that player - for(i=0,player=g_edicts+1; ivalue; i++, player++) { - if(player->client && player->client->spycam == self) - camera_off(player); - } - if(self->deathtarget) { - edict_t *target; - target = G_Find(NULL,FOFS(targetname),self->deathtarget); - while(target) { - if(target && target->use) - target->use(target,attacker,attacker); - target = G_Find(target,FOFS(targetname),self->deathtarget); - } - } - } - if(self->health <= self->gib_health) { - if(self->destroytarget) { - if(self->deadflag == DEAD_DEAD) { - // we were already dead, so deathtarget has been fired - edict_t *target; - target = G_Find(NULL,FOFS(targetname),self->destroytarget); - while(target) { - if(target && target->use) - target->use(target,attacker,attacker); - target = G_Find(target,FOFS(targetname),self->destroytarget); - } - } else { - // we were killed and gibbed in the same frame. postpone - // destroytarget just a bit - edict_t *temp; - temp = G_Spawn(); - temp->solid = SOLID_NOT; - temp->svflags = SVF_NOCLIENT; - temp->think = turret_die_temp_think; - temp->nextthink = level.time + 2*FRAMETIME; - temp->destroytarget = self->destroytarget; - temp->target_ent = attacker; - gi.linkentity(temp); - } - self->nextthink = 0; - gi.linkentity(self); - } - if(self->dmg > 0) - BecomeExplosion1(self); - else - G_FreeEdict(self); - return; - } - if(self->deadflag == DEAD_DEAD) - return; - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - // slow turret down and level it... or for MD2 turrets set to minpitch - self->speed /= 4; - if(self->spawnflags & SF_TURRET_MD2) - self->move_angles[0] = self->pos1[0]; - else - self->move_angles[0] = 0; -} -void toggle_turret_breach (edict_t *self, edict_t *other, edict_t *activator) -{ - if(!(self->spawnflags & SF_TURRET_INACTIVE)) - { - self->spawnflags |= SF_TURRET_INACTIVE; - VectorCopy(self->s.angles,self->move_angles); - if (self->team) { - edict_t *ent; - for (ent = self->teammaster; ent; ent = ent->teamchain) - { - VectorClear(ent->avelocity); - gi.linkentity(ent); - } - } - self->think = NULL; - self->nextthink = 0; - } - else - { - self->spawnflags &= ~SF_TURRET_INACTIVE; - self->think = turret_breach_think; - self->nextthink = level.time + FRAMETIME; - } -} - -void use_turret_breach (edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->spawnflags & SF_TURRET_TRIGGER_SPAWN) - { - self->spawnflags &= ~SF_TURRET_TRIGGER_SPAWN; - self->svflags &= ~SVF_NOCLIENT; - if(self->spawnflags & SF_TURRET_MD2) - self->solid = SOLID_BBOX; - else - self->solid = SOLID_BSP; - self->think = turret_breach_think; - self->think(self); - } -} -void turret_breach_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - // This added for Lazarus to help prevent player from becoming stuck when - // jumping onto a TRACK turret. - - // We only care about TRACK turrets. For monster controlled turrets the angles - // should of course be controlled by the monster. - if(!(self->spawnflags & SF_TURRET_TRACKING)) - return; - // We only care about players... everybody else knows better than to - // get tangled up with turret :-) - if(!other->client) - return; - // Do nothing for turrets that already have an enemy - if(self->enemy) - return; - if( (other->client) && (other->absmin[2] > self->s.origin[2]) ) { - if( fabs(self->s.angles[PITCH] - self->pos1[PITCH]) < - fabs(self->s.angles[PITCH] - self->pos2[PITCH]) ) - self->move_angles[PITCH] = self->pos2[PITCH]; - else - self->move_angles[PITCH] = self->pos1[PITCH]; - - if( fabs(self->s.angles[YAW] - self->pos1[YAW]) < - fabs(self->s.angles[YAW] - self->pos2[YAW]) ) - self->move_angles[YAW] = self->pos2[YAW]; - else - self->move_angles[YAW] = self->pos1[YAW]; - } -} - -void SP_turret_breach (edict_t *self) -{ - self->class_id = ENTITY_TURRET_BREACH; - // Good guy turrets shoot at monsters, not players. Turn TRACK on if it ain't already - if(self->spawnflags & SF_TURRET_GOODGUY) - self->spawnflags |= (SF_TURRET_TRACKING | SF_TURRET_INACTIVE); - - if (self->spawnflags & SF_TURRET_MD2) - { - char modelname[256]; - if (!self->usermodel) - { - gi.dprintf("%s w/o a model and MD2 spawnflag set at %s\n", - self->classname,vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - sprintf(modelname, "models/%s", self->usermodel); - self->s.modelindex = gi.modelindex (modelname); - - if ( (VectorLength(self->bleft) == 0) && - (VectorLength(self->tright) == 0) ) - { - VectorSet(self->bleft,-16,-16,-16); - VectorSet(self->tright,16, 16, 16); - } - VectorCopy(self->bleft,self->mins); - VectorCopy(self->tright,self->maxs); - - if (self->spawnflags & SF_TURRET_TRIGGER_SPAWN) - { - self->svflags |= SVF_NOCLIENT; - self->solid = SOLID_NOT; - self->use = use_turret_breach; - } - else - { - self->solid = SOLID_BBOX; - if(self->spawnflags & SF_TURRET_TRACKING) - self->use = toggle_turret_breach; - } - } - else - { - if (self->spawnflags & SF_TURRET_TRIGGER_SPAWN) - { - self->svflags |= SVF_NOCLIENT; - self->solid = SOLID_NOT; - self->use = use_turret_breach; - } - else - { - self->solid = SOLID_BSP; - if(self->spawnflags & SF_TURRET_TRACKING) - self->use = toggle_turret_breach; - } - gi.setmodel (self, self->model); - } - self->movetype = MOVETYPE_PUSH; - - // grenade speed. Yes I know this is a misuse of this. Sue me. - if (st.distance) - self->fog_far = st.distance; - else - self->fog_far = TURRET_GRENADE_SPEED; - - if (!self->speed) - self->speed = 50; - if (!self->dmg) - self->dmg = 10; - - if (!st.minpitch) - st.minpitch = -30; - if (!st.maxpitch) - st.maxpitch = 30; - if (!st.maxyaw) - st.maxyaw = 360; - - if (!self->wait) - self->wait = 2.0; - - if(self->health) { - self->die = turret_die; - self->takedamage = DAMAGE_YES; - } else { - self->die = NULL; - self->takedamage = DAMAGE_NO; - } - // Added touch routine to help prevent player from getting stuck after - // jumping on turret barrel - self->touch = turret_breach_touch; - - self->pos1[PITCH] = -1 * st.minpitch; - self->pos1[YAW] = st.minyaw; - self->pos2[PITCH] = -1 * st.maxpitch; - self->pos2[YAW] = st.maxyaw; - - if(self->pos1[YAW] < 0) - self->pos1[YAW] += 360; - if(self->pos2[YAW] < 0) - self->pos2[YAW] += 360; - - self->ideal_yaw = self->s.angles[YAW]; - self->move_angles[YAW] = self->ideal_yaw; - - self->blocked = turret_blocked; - - self->think = turret_breach_finish_init; - self->nextthink = level.time + FRAMETIME; - - // Lazarus: Added so monsters will attack turrets that - // fire at them - self->monsterinfo.aiflags |= AI_GOOD_GUY; - - gi.linkentity (self); -} - -void SP_model_turret(edict_t *self) -{ - self->spawnflags |= SF_TURRET_MD2; - SP_turret_breach(self); - self->class_id = ENTITY_MODEL_TURRET; -} - -/*QUAKED turret_base (0 0 0) ? -This portion of the turret changes yaw only. -MUST be teamed with a turret_breach. -*/ - -void turret_base_finish(edict_t *self) -{ - vec_t radius; - - if(self->team) { - // should ALWAYS have a team, but we're being pessimistic here - radius = (self->maxs[0] - self->mins[0])*(self->maxs[0] - self->mins[0]) + - (self->maxs[1] - self->mins[1])*(self->maxs[1] - self->mins[1]) + - (self->maxs[2] - self->mins[2])*(self->maxs[2] - self->mins[2]); - self->teammaster->base_radius = sqrt(radius); - } -} - -void use_turret_base(edict_t *self, edict_t *other, edict_t *activator) -{ - self->svflags &= ~SVF_NOCLIENT; - self->solid = SOLID_BSP; -} -void SP_turret_base (edict_t *self) -{ - self->class_id = ENTITY_TURRET_BASE; - if(self->spawnflags & SF_TURRET_TRIGGER_SPAWN) { - self->svflags |= SVF_NOCLIENT; - self->solid = SOLID_NOT; - self->use = use_turret_base; - } else - self->solid = SOLID_BSP; - - self->movetype = MOVETYPE_PUSH; - gi.setmodel (self, self->model); - self->blocked = turret_blocked; - - // DWH - self->s.angles[PITCH] = self->s.angles[ROLL] = 0; - self->think = turret_base_finish; - self->nextthink = level.time + FRAMETIME; - gi.linkentity (self); -} - - -/*QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32) -Must NOT be on the team with the rest of the turret parts. -Instead it must target the turret_breach. -*/ - -void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage); -void infantry_stand (edict_t *self); -void monster_use (edict_t *self, edict_t *other, edict_t *activator); - -void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - edict_t *ent; - - if(self->target_ent->inuse) { - - // level the gun - self->target_ent->move_angles[0] = 0; - - if(self->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER) - // "remote" driver... turn off TRACK for turret - self->target_ent->spawnflags &= ~SF_TURRET_TRACKING; - else { - // remove the driver from the end of the team chain - for (ent = self->target_ent->teammaster; ent->teamchain != self; ent = ent->teamchain) - ; - ent->teamchain = NULL; - self->teammaster = NULL; - self->flags &= ~FL_TEAMSLAVE; - self->target_ent->teammaster->owner = NULL; - } - self->target_ent->owner = NULL; - } - infantry_die (self, inflictor, attacker, damage); -} - -void turret_driver_think (edict_t *self) -{ - vec3_t target; - vec3_t dir; - float reaction_time; - - self->nextthink = level.time + FRAMETIME; - - //ed - yaay, turrets will kill monsters and stuff now. - if (self->enemy && (!self->enemy->inuse || self->enemy->health <= 0)) - self->enemy = NULL; - - if (!self->enemy) - { - if (!FindTarget (self)) - return; - self->monsterinfo.trail_time = level.time; - self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; - } - else - { - if (visible (self, self->enemy)) - { - if (self->monsterinfo.aiflags & AI_LOST_SIGHT) - { - self->monsterinfo.trail_time = level.time; - self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; - } - } - else - { - self->monsterinfo.aiflags |= AI_LOST_SIGHT; - return; - } - } - - // let the turret know where we want it to aim - VectorCopy (self->enemy->s.origin, target); - target[2] += self->enemy->viewheight; - VectorSubtract (target, self->target_ent->s.origin, dir); - if(self->target_ent->sounds == 7) - { - // grenade launcher - if(!AimGrenade (self->target_ent, self->target_ent->s.origin, target, self->target_ent->fog_far, dir)) - { - vectoangles (dir, self->target_ent->move_angles); - return; - } - } - vectoangles (dir, self->target_ent->move_angles); - - // decide if we should shoot - if (level.time < self->monsterinfo.attack_finished) - return; - - if(self->target_ent->sounds==5 || self->target_ent->sounds==6) - reaction_time = 0.; - else - reaction_time = max(0., (2-skill->value)); - if ((level.time - self->monsterinfo.trail_time) < reaction_time) - return; - - if(self->target_ent->sounds==5 || self->target_ent->sounds==6) - self->monsterinfo.attack_finished = level.time + FRAMETIME; - else - self->monsterinfo.attack_finished = level.time + reaction_time + 1.0; - self->target_ent->spawnflags |= 65536; -} - -void turret_driver_link (edict_t *self) -{ - vec3_t vec; - edict_t *ent; - - self->target_ent = G_PickTarget (self->target); - self->target_ent->owner = self; - - // DWH: We no longer require turret_breach to be teamed with a turret_base UNLESS - // there's a turret_driver - if (!self->target_ent->team) { - gi.dprintf("turret_driver at %s targets a no-team turret_breach\n", - vtos(self->s.origin)); - G_FreeEdict(self); - return; - } - // DWH: REMOTE (=1) drivers aren't part of the turret team, and don't think - // (the turret_breach thinks for them) - if(!(self->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER)) { - self->think = turret_driver_think; - self->nextthink = level.time + FRAMETIME; - self->target_ent->teammaster->owner = self; - VectorCopy (self->target_ent->s.angles, self->s.angles); - } - - vec[0] = self->target_ent->s.origin[0] - self->s.origin[0]; - vec[1] = self->target_ent->s.origin[1] - self->s.origin[1]; - vec[2] = 0; - self->move_origin[0] = VectorLength(vec); - - VectorSubtract (self->s.origin, self->target_ent->s.origin, vec); - vectoangles (vec, vec); - AnglesNormalize(vec); - self->move_origin[1] = vec[1]; - - self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2]; - - // add the driver to the end of the team chain - // DWH: REMOTE (=1) drivers don't move with turret, and the turret tracks - // players - if(self->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER) - self->target_ent->spawnflags |= SF_TURRET_TRACKING; - else { - for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain) - ; - ent->teamchain = self; - self->teammaster = self->target_ent->teammaster; - self->flags |= FL_TEAMSLAVE; - } -} - -void SP_turret_driver (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TURRET_DRIVER; - self->movetype = MOVETYPE_PUSH; - self->solid = SOLID_BBOX; - self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - - self->health = 100; - self->gib_health = 0; - self->mass = 200; - self->viewheight = 24; - - self->die = turret_driver_die; - self->monsterinfo.stand = infantry_stand; - - self->flags |= FL_NO_KNOCKBACK; - - level.total_monsters++; - - self->svflags |= SVF_MONSTER; - self->s.renderfx |= RF_FRAMELERP; - self->takedamage = DAMAGE_AIM; - self->use = monster_use; - self->clipmask = MASK_MONSTERSOLID; - VectorCopy (self->s.origin, self->s.old_origin); - self->monsterinfo.aiflags |= AI_STAND_GROUND|AI_DUCKED; - - if (st.item) - { - self->item = FindItemByClassname (st.item); - if (!self->item) - gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item); - } - - self->think = turret_driver_link; - self->nextthink = level.time + FRAMETIME; - - if(self->spawnflags & SF_TURRETDRIVER_REMOTE_DRIVER) { - // remote turret driver - go ahead and create his "real" infantry replacement - // NOW so the switch won't be so time-consuming - edict_t *infantry; - infantry = G_Spawn(); - infantry->spawnflags = SF_TURRET_TRIGGER_SPAWN; - VectorCopy(self->s.angles,infantry->s.angles); - VectorCopy(self->s.origin,infantry->s.origin); - infantry->s.origin[2] += 1.0; - infantry->health = self->health; - SP_monster_infantry(infantry); - self->child = infantry; - } - gi.linkentity (self); -} - diff --git a/server/ents/g_vehicle.c b/server/ents/g_vehicle.c deleted file mode 100644 index 9d122e03..00000000 --- a/server/ents/g_vehicle.c +++ /dev/null @@ -1,457 +0,0 @@ -#include "g_local.h" - -#define RFAST -3 -#define RMEDIUM -2 -#define RSLOW -1 -#define STOP 0 -#define SLOW 1 -#define MEDIUM 2 -#define FAST 3 - -#define VEHICLE_BLOCK_STOPS 4 - -void func_vehicle_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - vec3_t origin; - vec3_t chunkorigin; - vec3_t size; - int count; - int mass; - - if(self->deathtarget) - { - self->target = self->deathtarget; - G_UseTargets (self, attacker); - } - - // bmodel origins are (0 0 0), we need to adjust that here - VectorScale (self->size, 0.5, size); - VectorAdd (self->absmin, size, origin); - VectorCopy (origin, self->s.origin); - - self->takedamage = DAMAGE_NO; - - if (self->dmg) - T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE, -0.5); - - VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity); - VectorNormalize (self->velocity); - VectorScale (self->velocity, 150, self->velocity); - - // start chunks towards the center - VectorScale (size, 0.5, size); - - mass = self->mass; - - // big chunks - if (mass >= 100) - { - count = mass / 100; - if (count > 8) - count = 8; - while(count--) - { - chunkorigin[0] = origin[0] + crandom() * size[0]; - chunkorigin[1] = origin[1] + crandom() * size[1]; - chunkorigin[2] = origin[2] + crandom() * size[2]; - ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin, 0, 0); - } - } - - // small chunks - count = mass / 25; - if (count > 16) - count = 16; - while(count--) - { - chunkorigin[0] = origin[0] + crandom() * size[0]; - chunkorigin[1] = origin[1] + crandom() * size[1]; - chunkorigin[2] = origin[2] + crandom() * size[2]; - ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin, 0, 0); - } - - if (self->dmg) - BecomeExplosion1 (self); - else - G_FreeEdict (self); -} - -void vehicle_blocked (edict_t *self, edict_t *other) -{ - edict_t *attacker; - - if((self->spawnflags & VEHICLE_BLOCK_STOPS) || (other == world)) - { - VectorClear(self->velocity); - VectorClear(self->avelocity); - self->moveinfo.current_speed = 0; - gi.linkentity(self); - return; - } - if (other->takedamage) - { - if (self->teammaster->owner) - attacker = self->teammaster->owner; - else - attacker = self->owner; - T_Damage (other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH); - } - else - { - VectorClear(self->velocity); - VectorClear(self->avelocity); - self->moveinfo.current_speed = 0; - self->moveinfo.state = STOP; - gi.linkentity(self); - } - - if (!(other->svflags & SVF_MONSTER) && (!other->client)) - { - T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); - - if (other) - BecomeExplosion1 (other); - return; - } -} - -// Not needed, because collisions are effectively prevented by the vehicle physics in -// g_phys.c. -void vehicle_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - vec3_t dir, v; - vec3_t new_origin, new_velocity; - vec_t points; - vec_t vspeed, mspeed; - vec_t knockback; - vec3_t end; - trace_t tr; - - if (other == world || (self->spawnflags & VEHICLE_BLOCK_STOPS) ) - { - VectorClear(self->velocity); - VectorClear(self->avelocity); - self->moveinfo.current_speed = 0; - gi.linkentity(self); - } - if (!self->owner) return; // if vehicle isn't being driven, it can't hurt anybody - if (other == self->owner) return; // can't hurt the driver - if (other->takedamage == DAMAGE_NO) return; - // we damage func_explosives elsewhere. About all that's left to hurt are - // players and monsters - if (!other->client && !(other->svflags & SVF_MONSTER)) return; - vspeed = VectorLength(self->velocity); - if(!vspeed) return; - VectorSubtract(other->s.origin,self->s.origin,dir); - dir[2] = 0; - VectorNormalize(dir); - VectorCopy(self->velocity,v); - VectorNormalize(v); - // damage and knockback are proportional to square of velocity * mass of vehicle. - // Lessee... with a mass=2000 vehicle traveling 400 units/sec, give 100 points - // damage and a velocity of 160 to a 200 mass monster. - vspeed *= DotProduct(dir,v); - mspeed = VectorLength(other->velocity) * DotProduct(dir,v); - vspeed -= mspeed; - if(vspeed <= 0.) return; - // for speed < 200, don't do damage but move monster - if(vspeed < 200) { - if(other->mass > self->mass) vspeed *= self->mass/other->mass; - VectorMA(other->velocity,vspeed,dir,new_velocity); - VectorMA(other->s.origin,FRAMETIME,new_velocity,new_origin); - new_origin[2] += 2; - // if the move would place the monster in a solid, make him go splat - VectorCopy(new_origin,end); - end[2] -= 1; - tr = gi.trace(new_origin,other->mins,other->maxs,end,self,CONTENTS_SOLID); - if(tr.startsolid) - // splat - T_Damage (other, self, self->owner, dir, self->s.origin, vec3_origin, - other->health - other->gib_health + 1, 0, 0, MOD_VEHICLE); - - else - { - // go ahead and move the bastard - VectorCopy(new_velocity,other->velocity); - VectorCopy(new_origin,other->s.origin); - gi.linkentity(other); - } - return; - } - if (other->damage_debounce_time > level.time) return; - other->damage_debounce_time = level.time + 0.2; - points = 100. * (self->mass/2000 * vspeed*vspeed/160000); - // knockback takes too long to take effect. If we can move him w/o throwing him - // into a solid, do so NOW - dir[2] = 0.2; // make knockback slightly upward - VectorMA(other->velocity,vspeed,dir,new_velocity); - VectorMA(other->s.origin,FRAMETIME,new_velocity,new_origin); - if(gi.pointcontents(new_origin) & CONTENTS_SOLID) - knockback = (160./500.) * 200. * (self->mass/2000 * vspeed*vspeed/160000); - else { - knockback = 0; - VectorCopy(new_velocity,other->velocity); - VectorCopy(new_origin, other->s.origin); - } - T_Damage (other, self, self->owner, dir, self->s.origin, vec3_origin, - (int)points, (int)knockback, 0, MOD_VEHICLE); - gi.linkentity(other); -} - - -void vehicle_disengage (edict_t *vehicle) -{ - edict_t *driver; - vec3_t forward, left, f1, l1; - - driver = vehicle->owner; - if(!driver) return; - - AngleVectors(vehicle->s.angles, forward, left, NULL); - VectorCopy(vehicle->velocity,driver->velocity); - VectorScale(forward,vehicle->move_origin[0],f1); - VectorScale(left,-vehicle->move_origin[1],l1); - VectorAdd(vehicle->s.origin,f1,driver->s.origin); - VectorAdd(driver->s.origin,l1,driver->s.origin); - driver->s.origin[2] += vehicle->move_origin[2]; - - driver->vehicle = NULL; - driver->client->vehicle_framenum = level.framenum; - driver->movetype = MOVETYPE_WALK; - driver->gravity = 1; - // turn ON client side prediction for this player - driver->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - vehicle->s.sound = 0; - gi.linkentity (driver); - vehicle->owner = NULL; -} - -void vehicle_think (edict_t *self) -{ - float aspeed, speed, newspeed; - vec3_t forward, left, f1, l1, v; - - self->nextthink = level.time + FRAMETIME; - - VectorCopy(self->oldvelocity,v); - v[2] = 0; - speed = VectorLength(v); - if(speed > 0) - self->s.effects |= EF_ANIM_ALL; - else - self->s.effects &= ~EF_ANIM_ALL; - AngleVectors(self->s.angles, forward, left, NULL); - if(DotProduct(forward,self->oldvelocity) < 0) speed = -speed; - self->moveinfo.current_speed = speed; - - if (self->owner) - { - // ... then we have a driver - if (self->owner->health <= 0) - { - vehicle_disengage(self); - return; - } - if (self->owner->client->use) - { - // if he's pressing the use key, and he didn't just - // get on or off, disengage - if(level.framenum - self->owner->client->vehicle_framenum > 2) - { - VectorCopy(self->velocity,self->oldvelocity); - vehicle_disengage(self); - return; - } - } - if (self->owner->client->ucmd.forwardmove != 0 && level.time > self->moveinfo.wait) - { - if(self->owner->client->ucmd.forwardmove > 0) - { - if(self->moveinfo.state < FAST) - { - self->moveinfo.state++; - self->moveinfo.next_speed = self->moveinfo.state * self->speed/3; - self->moveinfo.wait = level.time + FRAMETIME; - } - } - else - { - if(self->moveinfo.state > RFAST) - { - self->moveinfo.state--; - self->moveinfo.next_speed = self->moveinfo.state * self->speed/3; - self->moveinfo.wait = level.time + FRAMETIME; - } - } - } - if(self->moveinfo.current_speed < self->moveinfo.next_speed) - { - speed = self->moveinfo.current_speed + self->accel/10; - if(speed > self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - else if(self->moveinfo.current_speed > self->moveinfo.next_speed) - { - speed = self->moveinfo.current_speed - self->decel/10; - if(speed < self->moveinfo.next_speed) speed = self->moveinfo.next_speed; - } - VectorScale(forward,speed,self->velocity); - if (self->owner->client->ucmd.sidemove != 0 && speed != 0 ) - { - aspeed = 180.*speed/(M_PI*self->radius); - if(self->owner->client->ucmd.sidemove > 0) aspeed = -aspeed; - self->avelocity[1] = aspeed; - } - else - self->avelocity[1] = 0; - - if(speed != 0) - self->s.sound = self->noise_index; - else - self->s.sound = self->noise_index2; - - gi.linkentity(self); - - // Copy velocities and set position of driver - VectorCopy(self->velocity,self->owner->velocity); - VectorScale(forward,self->move_origin[0],f1); - VectorScale(left,-self->move_origin[1],l1); - VectorAdd(self->s.origin,f1,self->owner->s.origin); - VectorAdd(self->owner->s.origin,l1,self->owner->s.origin); - self->owner->s.origin[2] += self->move_origin[2]; - // If moving, turn driver - if(speed != 0) - { - float yaw; - yaw = self->avelocity[1]*FRAMETIME; - self->owner->s.angles[YAW] += yaw; - self->owner->client->ps.pmove.delta_angles[YAW] += ANGLE2SHORT(yaw); - self->owner->client->ps.pmove.pm_type = PM_FREEZE; - } - VectorCopy(self->velocity,self->oldvelocity); - gi.linkentity(self->owner); - } - else - { - int i; - edict_t *ent; - vec3_t dir, drive; - // - // No driver - // - // if vehicle has stopped, drop it to ground. - // otherwise slow it down - if(speed==0) - { - if(!self->groundentity) - SV_AddGravity (self); - } - else - { - // no driver... slow to an eventual stop in no more than 5 sec. - self->moveinfo.next_speed = 0; - self->moveinfo.state = STOP; - if(speed > 0) - newspeed = max(0.,speed - self->speed/50); - else - newspeed = min(0.,speed + self->speed/50); - VectorScale(forward,newspeed,self->velocity); - VectorScale(self->avelocity,newspeed/speed,self->avelocity); - VectorCopy(self->velocity,self->oldvelocity); - gi.linkentity(self); - } - - // check if a player has mounted the vehicle - // first get driving position - VectorScale(forward,self->move_origin[0],f1); - VectorScale(left,-self->move_origin[1],l1); - VectorAdd(self->s.origin,f1,drive); - VectorAdd(drive,l1,drive); - drive[2] += self->move_origin[2]; - // find a player - for (i=1, ent=&g_edicts[1] ; i<=maxclients->value ; i++, ent++) { - if (!ent->inuse) continue; - if (ent->movetype == MOVETYPE_NOCLIP) continue; - if (!ent->client->use) continue; - if (level.framenum - ent->client->vehicle_framenum <= 2) continue; - - // determine distance from vehicle "move_origin" - VectorSubtract(drive,ent->s.origin,dir); - if (fabs(dir[2]) < 64) - dir[2] = 0; - - if (VectorLength(dir) < 16) { - ent->client->vehicle_framenum = level.framenum; - // player has taken control of vehicle - // move vehicle up slightly to avoid roundoff collisions - self->s.origin[2] += 1; - gi.linkentity(self); - - if(self->message) - gi.centerprintf(ent,self->message); - self->owner = ent; - ent->movetype = MOVETYPE_PUSH; - ent->gravity = 0; - ent->vehicle = self; - // turn off client side prediction for this player - ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - // force a good driving position - VectorCopy(drive,self->owner->s.origin); - gi.linkentity(ent); - // vehicle idle noise - self->s.sound = self->noise_index2; - // reset wait time so we can start accelerating - self->moveinfo.wait = 0; - } - } - } - if(self->movewith_next && (self->movewith_next->movewith_ent == self)) - set_child_movement(self); -} - -void turn_vehicle (edict_t *self) -{ - self->s.angles[YAW] = self->ideal_yaw; - gi.linkentity(self); - self->prethink = NULL; -} -void SP_func_vehicle (edict_t *self) -{ - self->class_id = ENTITY_FUNC_VEHICLE; - self->ideal_yaw = self->s.angles[YAW]; - VectorClear (self->s.angles); - self->solid = SOLID_BSP; - gi.setmodel (self, self->model); - - self->movetype = MOVETYPE_VEHICLE; - - if (!self->speed) - self->speed = 200; - if (!self->accel) - self->accel = self->speed; // accelerates to full speed in 1 second (approximate). - if (!self->decel) - self->decel = self->accel; - if (!self->mass) - self->mass = 2000; - if (!self->radius) - self->radius = 256; - self->blocked = vehicle_blocked; - self->touch = vehicle_touch; - self->think = vehicle_think; - self->nextthink = level.time + FRAMETIME; - self->noise_index = gi.soundindex("engine/engine.wav"); - self->noise_index2 = gi.soundindex("engine/idle.wav"); - VectorClear(self->velocity); - VectorClear(self->avelocity); - self->moveinfo.current_speed = 0; - self->moveinfo.state = STOP; - gi.linkentity (self); - VectorCopy(self->size,self->org_size); - - if (self->ideal_yaw != 0) - self->prethink = turn_vehicle; - if (self->health) { - self->die = func_vehicle_explode; - self->takedamage = DAMAGE_YES; - } else - self->takedamage = DAMAGE_NO; -} diff --git a/server/ents/g_weapon.c b/server/ents/g_weapon.c deleted file mode 100644 index 9abaa8d8..00000000 --- a/server/ents/g_weapon.c +++ /dev/null @@ -1,1608 +0,0 @@ -#include "g_local.h" - - -/* -================= -check_dodge - -This is a support routine used when a client is firing -a non-instant attack weapon. It checks to see if a -monster's dodge function should be called. -================= -*/ -static void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed) -{ - vec3_t end; - vec3_t v; - trace_t tr; - float eta; - - // easy mode only ducks one quarter the time - if (skill->value == 0) - { - if (random() > 0.25) - return; - } - VectorMA (start, 8192, dir, end); - tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); - if ((tr.ent) && (tr.ent->svflags & SVF_MONSTER) && (tr.ent->health > 0) && (tr.ent->monsterinfo.dodge) && infront(tr.ent, self)) - { - VectorSubtract (tr.endpos, start, v); - eta = (VectorLength(v) - tr.ent->maxs[0]) / speed; - tr.ent->monsterinfo.dodge (tr.ent, self, eta); - } -} - - -/* -================= -fire_hit - -Used for all impact (hit/punch/slash) attacks -================= -*/ -bool fire_hit (edict_t *self, vec3_t aim, int damage, int kick) -{ - trace_t tr; - vec3_t forward, right, up; - vec3_t v; - vec3_t point; - float range; - vec3_t dir; - - // Lazarus: Paranoia check - if(!self->enemy) - return false; - - //see if enemy is in range - VectorSubtract (self->enemy->s.origin, self->s.origin, dir); - range = VectorLength(dir); - if (range > aim[0]) - return false; - - if (aim[1] > self->mins[0] && aim[1] < self->maxs[0]) - { - // the hit is straight on so back the range up to the edge of their bbox - range -= self->enemy->maxs[0]; - } - else - { - // this is a side hit so adjust the "right" value out to the edge of their bbox - if (aim[1] < 0) - aim[1] = self->enemy->mins[0]; - else - aim[1] = self->enemy->maxs[0]; - } - - VectorMA (self->s.origin, range, dir, point); - - tr = gi.trace (self->s.origin, NULL, NULL, point, self, MASK_SHOT); - if (tr.fraction < 1) - { - if (!tr.ent->takedamage) - return false; - // if it will hit any client/monster then hit the one we wanted to hit - if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) - tr.ent = self->enemy; - } - - AngleVectors(self->s.angles, forward, right, up); - VectorMA (self->s.origin, range, forward, point); - VectorMA (point, aim[1], right, point); - VectorMA (point, aim[2], up, point); - VectorSubtract (point, self->enemy->s.origin, dir); - - // do the damage - T_Damage (tr.ent, self, self, dir, point, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, MOD_HIT); - - if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) - return false; - - // do our special form of knockback here - VectorMA (self->enemy->absmin, 0.5, self->enemy->size, v); - VectorSubtract (v, point, v); - VectorNormalize (v); - VectorMA (self->enemy->velocity, kick, v, self->enemy->velocity); - if (self->enemy->velocity[2] > 0) - self->enemy->groundentity = NULL; - return true; -} - - -/* -================= -fire_lead - -This is an internal support routine used for bullet/pellet based weapons. -================= -*/ -static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod) -{ - trace_t tr; - vec3_t dir; - vec3_t forward, right, up; - vec3_t end; - float r; - float u; - vec3_t water_start; - bool water = false; - int content_mask = MASK_SHOT | MASK_WATER; - - tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT); - if (!(tr.fraction < 1.0)) - { - vectoangles (aimdir, dir); - AngleVectors (dir, forward, right, up); - - r = crandom()*hspread; - u = crandom()*vspread; - VectorMA (start, 8192, forward, end); - VectorMA (end, r, right, end); - VectorMA (end, u, up, end); - - if (gi.pointcontents (start) & MASK_WATER) - { - water = true; - VectorCopy (start, water_start); - content_mask &= ~MASK_WATER; - } - - tr = gi.trace (start, NULL, NULL, end, self, content_mask); - - // see if we hit water - if (tr.contents & MASK_WATER) - { - int color; - - water = true; - VectorCopy (tr.endpos, water_start); - - if (!VectorCompare (start, tr.endpos)) - { - if (tr.ent->svflags & SVF_MUD) - color = SPLASH_BROWN_WATER; - else if (tr.contents & CONTENTS_WATER) - { - if (strcmp(tr.surface->name, "*brwater") == 0) - color = SPLASH_BROWN_WATER; - else - color = SPLASH_BLUE_WATER; - } - else if (tr.contents & CONTENTS_SLIME) - color = SPLASH_SLIME; - else if (tr.contents & CONTENTS_LAVA) - color = SPLASH_LAVA; - else - color = SPLASH_UNKNOWN; - - if (color != SPLASH_UNKNOWN) - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_SPLASH); - WRITE_BYTE (8); - WRITE_COORD (tr.endpos); - WRITE_DIR (tr.plane.normal); - WRITE_BYTE (color); - MESSAGE_SEND (MSG_PVS, tr.endpos, NULL); - } - - // change bullet's course when it enters water - VectorSubtract (end, start, dir); - vectoangles (dir, dir); - AngleVectors (dir, forward, right, up); - r = crandom()*hspread*2; - u = crandom()*vspread*2; - VectorMA (water_start, 8192, forward, end); - VectorMA (end, r, right, end); - VectorMA (end, u, up, end); - } - - // re-trace ignoring water this time - tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT); - } - } - - // send gun puff / flash - if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) - { - if (tr.fraction < 1.0) - { - if (tr.ent->takedamage) - { - T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod); - } - else - { - if (strncmp (tr.surface->name, "skyname", 3) != 0) - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (te_impact); - WRITE_COORD (tr.endpos); - WRITE_DIR (tr.plane.normal); - MESSAGE_SEND (MSG_PVS, tr.endpos, NULL); - - if(level.num_reflectors) - ReflectSparks(te_impact,tr.endpos,tr.plane.normal); - - if (self->client) - PlayerNoise(self, tr.endpos, PNOISE_IMPACT); - } - } - } - } - - // if went through water, determine where the end and make a bubble trail - if (water) - { - vec3_t pos; - - VectorSubtract (tr.endpos, water_start, dir); - VectorNormalize (dir); - VectorMA (tr.endpos, -2, dir, pos); - if (gi.pointcontents (pos) & MASK_WATER) - { - VectorCopy (pos, tr.endpos); - } - else - { - tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER); - } - VectorAdd (water_start, tr.endpos, pos); - VectorScale (pos, 0.5, pos); - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_BUBBLETRAIL); - WRITE_COORD (water_start); - WRITE_COORD (tr.endpos); - MESSAGE_SEND (MSG_PVS, pos, NULL); - } -} - - -/* -================= -fire_bullet - -Fires a single round. Used for machinegun and chaingun. Would be fine for -pistols, rifles, etc.... -================= -*/ -void fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod) -{ - fire_lead (self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod); -} - - -/* -================= -fire_shotgun - -Shoots shotgun pellets. Used by shotgun and super shotgun. -================= -*/ -void fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod) -{ - int i; - - for (i = 0; i < count; i++) - fire_lead (self, start, aimdir, damage, kick, TE_SHOTGUN, hspread, vspread, mod); -} - - -/* -================= -fire_blaster - -Fires a single blaster bolt. Used by the blaster and hyper blaster. -================= -*/ -void blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - int mod; - - if (other == self->owner) - return; - - if (surf && (surf->flags & SURF_SKY)) - { - G_FreeEdict (self); - return; - } - - if (self->owner->client) - PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); - - if (other->takedamage) - { - if (self->spawnflags & 1) - mod = MOD_HYPERBLASTER; - else - mod = MOD_BLASTER; - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); - } - else - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_BLASTER); - WRITE_COORD (self->s.origin); - if (!plane) WRITE_DIR (vec3_origin); - else WRITE_DIR (plane->normal); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - - if(level.num_reflectors) - { - if(!plane) - ReflectSparks(TE_BLASTER,self->s.origin,vec3_origin); - else - ReflectSparks(TE_BLASTER,self->s.origin,plane->normal); - } - } - - G_FreeEdict (self); -} - -void fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, bool hyper) -{ - edict_t *bolt; - trace_t tr; - - VectorNormalize (dir); - - bolt = G_Spawn(); - bolt->svflags = SVF_DEADMONSTER; - // yes, I know it looks weird that projectiles are deadmonsters - // what this means is that when prediction is used against the object - // (blaster/hyperblaster shots), the player won't be solid clipped against - // the object. Right now trying to run into a firing hyperblaster - // is very jerky since you are predicted 'against' the shots. - VectorCopy (start, bolt->s.origin); - VectorCopy (start, bolt->s.old_origin); - vectoangles (dir, bolt->s.angles); - VectorScale (dir, speed, bolt->velocity); - bolt->movetype = MOVETYPE_FLYMISSILE; - bolt->clipmask = MASK_SHOT; - bolt->solid = SOLID_BBOX; - bolt->s.effects |= effect; - VectorClear (bolt->mins); - VectorClear (bolt->maxs); - bolt->s.modelindex = gi.modelindex ("models/shell9mm.mdl"); - bolt->s.sound = gi.soundindex ("misc/lasfly.wav"); - bolt->owner = self; - bolt->touch = blaster_touch; - bolt->nextthink = level.time + 2; - bolt->think = G_FreeEdict; - bolt->dmg = damage; - bolt->classname = "bolt"; - if (hyper) - bolt->spawnflags = 1; - - if(level.num_reflectors) - AddReflection(bolt); - - gi.linkentity (bolt); - - if (self->client) - check_dodge (self, bolt->s.origin, dir, speed); - - tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); - if (tr.fraction < 1.0) - { - VectorMA (bolt->s.origin, -10, dir, bolt->s.origin); - bolt->touch (bolt, tr.ent, NULL, NULL); - } - -} - -// SP_bolt should ONLY be used for blaster/hyperblaster bolts that have -// changed maps via trigger_transition. It should NOT be used for map -// entities. -void bolt_delayed_start (edict_t *bolt) -{ - if(g_edicts[1].linkcount) - { - VectorScale(bolt->movedir,bolt->moveinfo.speed,bolt->velocity); - bolt->nextthink = level.time + 2; - bolt->think = G_FreeEdict; - gi.linkentity(bolt); - } - else - bolt->nextthink = level.time + FRAMETIME; -} -void SP_bolt (edict_t *bolt) -{ - bolt->class_id = ENTITY_BOLT; - bolt->s.modelindex = gi.modelindex ("models/shell9mm.mdl"); - bolt->s.sound = gi.soundindex ("misc/lasfly.wav"); - bolt->touch = blaster_touch; - VectorCopy(bolt->velocity,bolt->movedir); - VectorNormalize(bolt->movedir); - bolt->moveinfo.speed = VectorLength(bolt->velocity); - VectorClear(bolt->velocity); - bolt->think = bolt_delayed_start; - bolt->nextthink = level.time + FRAMETIME; - gi.linkentity(bolt); -} -/* -================= -fire_grenade -================= -*/ - -// Lazarus additions: next_grenade and prev_grenade linked lists facilitate checking -// for grenades near monsters, so that monsters can evade w/o bogging down the game - -void Grenade_Evade (edict_t *monster) -{ - edict_t *grenade; - vec3_t grenade_vec; - float grenade_dist, best_r, best_yaw, r; - float yaw; - int i; - vec3_t forward; - vec3_t pos, best_pos; - trace_t tr; - - // We assume on entry here that monster is alive and that he's not already - // AI_CHASE_THING - grenade = world->next_grenade; - while(grenade) - { - // we only care about grenades on the ground - if(grenade->inuse && grenade->groundentity) - { - // if it ain't in the PVS, it can't hurt us (I think?) - if(gi.inPVS(grenade->s.origin,monster->s.origin)) - { - VectorSubtract(grenade->s.origin,monster->s.origin,grenade_vec); - grenade_dist = VectorNormalize(grenade_vec); - if(grenade_dist <= grenade->dmg_radius) - break; - } - } - grenade = grenade->next_grenade; - } - if(!grenade) - return; - // Find best escape route. - best_r = 9999; - for(i=0; i<8; i++) - { - yaw = anglemod( i*45 ); - forward[0] = cos( DEG2RAD(yaw) ); - forward[1] = sin( DEG2RAD(yaw) ); - forward[2] = 0; - // Estimate of required distance to run. This is conservative. - r = grenade->dmg_radius + grenade_dist*DotProduct(forward,grenade_vec) + monster->size[0] + 16; - if( r < best_r ) - { - VectorMA(monster->s.origin,r,forward,pos); - tr = gi.trace(monster->s.origin,monster->mins,monster->maxs,pos,monster,MASK_MONSTERSOLID); - if(tr.fraction < 1.0) - continue; - best_r = r; - best_yaw = yaw; - VectorCopy(tr.endpos,best_pos); - } - } - if(best_r < 9000) - { - edict_t *thing = SpawnThing(); - VectorCopy(best_pos,thing->s.origin); - thing->touch_debounce_time = grenade->nextthink; - thing->target_ent = monster; - ED_CallSpawn(thing); - monster->ideal_yaw = best_yaw; - monster->movetarget = monster->goalentity = thing; - monster->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - monster->monsterinfo.aiflags |= (AI_CHASE_THING | AI_EVADE_GRENADE); - monster->monsterinfo.run(monster); - monster->next_grenade = grenade; - } -} - -static void Grenade_Add_To_Chain (edict_t *grenade) -{ - edict_t *ancestor; - - ancestor = world; - while(ancestor->next_grenade && ancestor->next_grenade->inuse) - ancestor = ancestor->next_grenade; - ancestor->next_grenade = grenade; - grenade->prev_grenade = ancestor; -} - -static void Grenade_Remove_From_Chain (edict_t *grenade) -{ - if(grenade->prev_grenade) - { - // "prev_grenade" should always be valid for other than player-thrown - // grenades that explode in player's hand - grenade->prev_grenade->next_grenade = grenade->next_grenade; - if(grenade->next_grenade) - grenade->next_grenade->prev_grenade = grenade->prev_grenade; - } -} - -static void Grenade_Explode (edict_t *ent) -{ - vec3_t origin; - int mod; - int type; - - Grenade_Remove_From_Chain(ent); - - if (ent->owner && ent->owner->client) - PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); - - //FIXME: if we are onground then raise our Z just a bit since we are a point? - if (ent->enemy) - { - float points; - vec3_t v; - vec3_t dir; - - VectorAdd (ent->enemy->mins, ent->enemy->maxs, v); - VectorMA (ent->enemy->s.origin, 0.5, v, v); - VectorSubtract (ent->s.origin, v, v); - points = ent->dmg - 0.5 * VectorLength (v); - VectorSubtract (ent->enemy->s.origin, ent->s.origin, dir); - if (ent->spawnflags & 1) - mod = MOD_HANDGRENADE; - else - mod = MOD_GRENADE; - T_Damage (ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); - } - - if (ent->spawnflags & 2) - mod = MOD_HELD_GRENADE; - else if (ent->spawnflags & 1) - mod = MOD_HG_SPLASH; - else - mod = MOD_G_SPLASH; - T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod, -0.5); - - VectorMA (ent->s.origin, -0.02, ent->velocity, origin); - MESSAGE_BEGIN (svc_temp_entity); - if (ent->waterlevel) - { - if (ent->groundentity) type = TE_GRENADE_EXPLOSION_WATER; - else type = TE_ROCKET_EXPLOSION_WATER; - } - else - { - if (ent->groundentity) type = TE_GRENADE_EXPLOSION; - else type = TE_ROCKET_EXPLOSION; - } - WRITE_BYTE (type); - WRITE_COORD (origin); - MESSAGE_SEND (MSG_PHS, ent->s.origin, NULL); - - if(level.num_reflectors) - ReflectExplosion (type,origin); - - G_FreeEdict (ent); -} - -static void Grenade_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other == ent->owner) - return; - - if (surf && (surf->flags & SURF_SKY)) - { - Grenade_Remove_From_Chain (ent); - G_FreeEdict (ent); - return; - } - - if (!other->takedamage) - { - if (ent->spawnflags & 1) - { - if (random() > 0.5) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); - else - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); - } - else - { - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/grenlb1b.wav"), 1, ATTN_NORM, 0); - } - return; - } - - ent->enemy = other; - Grenade_Explode (ent); -} - -void fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius) -{ - edict_t *grenade; - vec3_t dir; - vec3_t forward, right, up; - - vectoangles (aimdir, dir); - AngleVectors (dir, forward, right, up); - - grenade = G_Spawn(); - VectorCopy (start, grenade->s.origin); - VectorScale (aimdir, speed, grenade->velocity); - // Lazarus - keep same vertical boost for players, but monsters do a better job - // of calculating aim direction, so throw that out - if(self->client) - VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); - else - VectorMA (grenade->velocity, crandom() * 10.0, up, grenade->velocity); - - VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity); - // Lazarus: Add owner velocity -// VectorAdd (grenade->velocity, self->velocity, grenade->velocity); - // NO. This is too unrealistic. Instead, if owner is riding a moving entity, - // add velocity of the thing he's riding - if(self->groundentity) - VectorAdd (grenade->velocity, self->groundentity->velocity, grenade->velocity); - - - VectorSet (grenade->avelocity, 300, 300, 300); - grenade->movetype = MOVETYPE_BOUNCE; - grenade->clipmask = MASK_SHOT; - grenade->solid = SOLID_BBOX; - grenade->s.effects |= EF_GRENADE; - VectorClear (grenade->mins); - VectorClear (grenade->maxs); - grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2"); - grenade->owner = self; - grenade->touch = Grenade_Touch; - grenade->nextthink = level.time + timer; - grenade->think = Grenade_Explode; - grenade->dmg = damage; - grenade->dmg_radius = damage_radius; - grenade->classname = "grenade"; - grenade->class_id = ENTITY_GRENADE; - - Grenade_Add_To_Chain (grenade); - - gi.linkentity (grenade); -} - -void fire_grenade2 (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, bool held) -{ - edict_t *grenade; - vec3_t dir; - vec3_t forward, right, up; - - vectoangles (aimdir, dir); - AngleVectors (dir, forward, right, up); - - grenade = G_Spawn(); - VectorCopy (start, grenade->s.origin); - VectorScale (aimdir, speed, grenade->velocity); - VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); - VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity); - - // Lazarus: Add owner velocity -// VectorAdd (grenade->velocity, self->velocity, grenade->velocity); - // NO. This is too unrealistic. Instead, if owner is riding a moving entity, - // add velocity of the thing he's riding - if(self->groundentity) - VectorAdd (grenade->velocity, self->groundentity->velocity, grenade->velocity); - - VectorSet (grenade->avelocity, 300, 300, 300); - grenade->movetype = MOVETYPE_BOUNCE; - grenade->clipmask = MASK_SHOT; - grenade->solid = SOLID_BBOX; - grenade->s.effects |= EF_GRENADE; - VectorClear (grenade->mins); - VectorClear (grenade->maxs); - grenade->s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2"); - grenade->owner = self; - grenade->touch = Grenade_Touch; - grenade->nextthink = level.time + timer; - grenade->think = Grenade_Explode; - grenade->dmg = damage; - grenade->dmg_radius = damage_radius; - grenade->classname = "hgrenade"; - grenade->class_id = ENTITY_HANDGRENADE; - if (held) - grenade->spawnflags = 3; - else - grenade->spawnflags = 1; - grenade->s.sound = gi.soundindex("weapons/hgrenc1b.wav"); - - if (timer <= 0.0) - Grenade_Explode (grenade); - else - { - gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/hgrent1a.wav"), 1, ATTN_NORM, 0); - Grenade_Add_To_Chain (grenade); - gi.linkentity (grenade); - } -} - -// NOTE: SP_grenade and SP_handgrenade should ONLY be used to spawn grenades that change -// maps via a trigger_transition. They should NOT be used for map entities - -void grenade_delayed_start (edict_t *grenade) -{ - if(g_edicts[1].linkcount) - { - VectorScale(grenade->movedir,grenade->moveinfo.speed,grenade->velocity); - grenade->movetype = MOVETYPE_BOUNCE; - grenade->nextthink = level.time + 2.5; - grenade->think = Grenade_Explode; - gi.linkentity(grenade); - } - else - grenade->nextthink = level.time + FRAMETIME; -} - -void SP_grenade (edict_t *grenade) -{ - grenade->class_id = ENTITY_GRENADE; - grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2"); - grenade->touch = Grenade_Touch; - - // For SP, freeze grenade until player spawns in - if(game.maxclients == 1) - { - grenade->movetype = MOVETYPE_NONE; - VectorCopy(grenade->velocity,grenade->movedir); - VectorNormalize(grenade->movedir); - grenade->moveinfo.speed = VectorLength(grenade->velocity); - VectorClear(grenade->velocity); - grenade->think = grenade_delayed_start; - grenade->nextthink = level.time + FRAMETIME; - } - else - { - grenade->movetype = MOVETYPE_BOUNCE; - grenade->nextthink = level.time + 2.5; - grenade->think = Grenade_Explode; - } - gi.linkentity (grenade); - -} -void handgrenade_delayed_start (edict_t *grenade) -{ - if(g_edicts[1].linkcount) - { - VectorScale(grenade->movedir,grenade->moveinfo.speed,grenade->velocity); - grenade->movetype = MOVETYPE_BOUNCE; - grenade->nextthink = level.time + 2.5; - grenade->think = Grenade_Explode; - if(grenade->owner) - gi.sound (grenade->owner, CHAN_WEAPON, gi.soundindex ("weapons/hgrent1a.wav"), 1, ATTN_NORM, 0); - gi.linkentity(grenade); - } - else - grenade->nextthink = level.time + FRAMETIME; -} - -void SP_handgrenade (edict_t *grenade) -{ - grenade->class_id = ENTITY_HANDGRENADE; - grenade->s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2"); - grenade->touch = Grenade_Touch; - - // For SP, freeze grenade until player spawns in - if(game.maxclients == 1) - { - grenade->movetype = MOVETYPE_NONE; - VectorCopy(grenade->velocity,grenade->movedir); - VectorNormalize(grenade->movedir); - grenade->moveinfo.speed = VectorLength(grenade->velocity); - VectorClear(grenade->velocity); - grenade->think = handgrenade_delayed_start; - grenade->nextthink = level.time + FRAMETIME; - } - else - { - grenade->movetype = MOVETYPE_BOUNCE; - grenade->nextthink = level.time + 2.5; - grenade->think = Grenade_Explode; - } - gi.linkentity (grenade); - -} - -// Lazarus: homing rocket -void homing_think (edict_t *self) -{ - trace_t tr; - vec3_t dir, target; - vec_t speed; - - if(level.time > self->endtime) - { - if (self->owner->client && (self->owner->client->homing_rocket == self)) - self->owner->client->homing_rocket = NULL; - BecomeExplosion1(self); - return; - } - if(self->enemy && self->enemy->inuse) - { - VectorMA(self->enemy->absmin,0.5,self->enemy->size,target); - tr = gi.trace(self->s.origin,vec3_origin,vec3_origin,target,self,MASK_OPAQUE); - if(tr.fraction == 1) - { - // target in view; apply correction - VectorSubtract(target, self->s.origin, dir); - VectorNormalize(dir); - if(self->enemy->client) - VectorScale(dir, 0.8+0.1*skill->value, dir); - else - VectorScale(dir, 1.0, dir); // 0=no correction, 1=turn on a dime - VectorAdd(dir, self->movedir, dir); - VectorNormalize(dir); - VectorCopy(dir, self->movedir); - vectoangles(dir, self->s.angles); - speed = VectorLength(self->velocity); - VectorScale(dir, speed, self->velocity); - - if(level.time >= self->starttime && self->starttime > 0) - { - if(level.time > self->owner->fly_sound_debounce_time) - { - // this prevents multiple lockon sounds resulting from - // monsters firing multiple rockets in quick succession - if(self->enemy->client) - gi.sound (self->enemy, CHAN_AUTO, gi.soundindex ("weapons/homing/lockon.wav"), 1, ATTN_NORM, 0); - self->owner->fly_sound_debounce_time = level.time + 2.0; - } - self->starttime = 0; - } - } - } - self->nextthink = level.time + FRAMETIME; -} - -/* -================= -fire_rocket -================= -*/ -// Lazarus: Rocket_Evade tells monsters to get da hell outta da way - -void Rocket_Evade (edict_t *rocket, vec3_t dir, float speed) -{ - float rocket_dist, best_r, best_yaw, dist, r; - float time; - float dot; - float yaw; - int i; - edict_t *ent=NULL; - trace_t tr; - vec3_t hitpoint; - vec3_t forward, pos, best_pos; - vec3_t rocket_vec, vec; - - // Find out what rocket will hit, assuming everything remains static - VectorMA(rocket->s.origin,8192,dir,rocket_vec); - tr = gi.trace(rocket->s.origin,rocket->mins,rocket->maxs,rocket_vec,rocket,MASK_SHOT); - VectorCopy(tr.endpos,hitpoint); - VectorSubtract(hitpoint,rocket->s.origin,vec); - dist = VectorLength(vec); - time = dist / speed; - - while ((ent = findradius(ent, hitpoint, rocket->dmg_radius)) != NULL) - { - if (!ent->inuse) - continue; - if (!(ent->svflags & SVF_MONSTER)) - continue; - if (!ent->takedamage) - continue; - if (ent->health <= 0) - continue; - if (!ent->monsterinfo.run) // takes care of turret_driver - continue; - if (rocket->owner == ent) - continue; - - VectorSubtract(hitpoint,ent->s.origin,rocket_vec); - rocket_dist = VectorNormalize(rocket_vec); - - // Not much hope in evading if distance is < 1K or so. - if(rocket_dist < 1024) - continue; - - // Find best escape route. - best_r = 9999; - for(i=0; i<8; i++) - { - yaw = anglemod( i*45 ); - forward[0] = cos( DEG2RAD(yaw) ); - forward[1] = sin( DEG2RAD(yaw) ); - forward[2] = 0; - dot = DotProduct(forward,dir); - if((dot > 0.96) || (dot < -0.96)) - continue; - // Estimate of required distance to run. This is conservative. - r = rocket->dmg_radius + rocket_dist*DotProduct(forward,rocket_vec) + ent->size[0] + 16; - if( r < best_r ) - { - VectorMA(ent->s.origin,r,forward,pos); - tr = gi.trace(ent->s.origin,ent->mins,ent->maxs,pos,ent,MASK_MONSTERSOLID); - if(tr.fraction < 1.0) - continue; - best_r = r; - best_yaw = yaw; - VectorCopy(tr.endpos,best_pos); - } - } - if(best_r < 9000) - { - edict_t *thing = SpawnThing(); - VectorCopy(best_pos,thing->s.origin); - thing->touch_debounce_time = level.time + time; - thing->target_ent = ent; - ED_CallSpawn(thing); - ent->ideal_yaw = best_yaw; - ent->movetarget = ent->goalentity = thing; - ent->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - ent->monsterinfo.aiflags |= (AI_CHASE_THING | AI_EVADE_GRENADE); - ent->monsterinfo.run(ent); - } - } -} - - -void rocket_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - vec3_t origin; - int n; - int type; - - if (other == ent->owner) - return; - - if (ent->owner->client && (ent->owner->client->homing_rocket == ent)) - ent->owner->client->homing_rocket = NULL; - - if (surf && (surf->flags & SURF_SKY)) - { - G_FreeEdict (ent); - return; - } - - if (ent->owner && ent->owner->client) - PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); - - // calculate position for the explosion entity - VectorMA (ent->s.origin, -0.02, ent->velocity, origin); - - if (other->takedamage) - { - T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_ROCKET); - } - else - { - // don't throw any debris in net games - if (!deathmatch->value && !coop->value) - { - if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) - { - n = rand() % 5; - while(n--) - ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin, 0, 0); - } - } - } - - // Lazarus: bad monsters have a large damage radius - if (ent->owner && (ent->owner->svflags & SVF_MONSTER) && !(ent->owner->monsterinfo.aiflags & AI_GOOD_GUY)) - T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius + 17.5*skill->value, MOD_R_SPLASH, -2.0/(4.0+skill->value) ); - else - T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_R_SPLASH, -0.5); - - MESSAGE_BEGIN (svc_temp_entity); - if (ent->waterlevel) type = TE_ROCKET_EXPLOSION_WATER; - else type = TE_ROCKET_EXPLOSION; - WRITE_BYTE (type); - WRITE_COORD (origin); - MESSAGE_SEND (MSG_PHS, ent->s.origin, NULL); - - if(level.num_reflectors) - ReflectExplosion(type,origin); - - G_FreeEdict (ent); -} - -static void rocket_explode (edict_t *ent) -{ - vec3_t origin; - int type; - - if (ent->owner->client) - PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); - - // calculate position for the explosion entity - VectorMA (ent->s.origin, -0.02, ent->velocity, origin); - - T_RadiusDamage(ent, ent->owner, ent->radius_dmg, NULL, ent->dmg_radius, MOD_R_SPLASH, -0.5); - - MESSAGE_BEGIN (svc_temp_entity); - if (ent->waterlevel) type = TE_ROCKET_EXPLOSION_WATER; - else type = TE_ROCKET_EXPLOSION; - WRITE_BYTE (type); - WRITE_COORD (origin); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - if(level.num_reflectors) - ReflectExplosion(type,origin); - - G_FreeEdict (ent); -} -static void rocket_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->takedamage = DAMAGE_NO; - self->nextthink = level.time + FRAMETIME; - self->think = rocket_explode; -} - -void fire_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage, edict_t *home_target) -{ - edict_t *rocket; - - rocket = G_Spawn(); - VectorCopy (start, rocket->s.origin); - VectorCopy (dir, rocket->movedir); - vectoangles (dir, rocket->s.angles); - VectorScale (dir, speed, rocket->velocity); - // Lazarus: add shooter's lateral velocity - if(rocket_strafe->value) - { - vec3_t right, up; - vec3_t lateral_speed; - - AngleVectors(self->s.angles,NULL,right,up); - VectorCopy(self->velocity,lateral_speed); - lateral_speed[0] *= fabs(right[0]); - lateral_speed[1] *= fabs(right[1]); - lateral_speed[2] *= fabs(up[2]); - VectorAdd(rocket->velocity,lateral_speed,rocket->velocity); - } - - rocket->movetype = MOVETYPE_FLYMISSILE; - rocket->clipmask = MASK_SHOT; - rocket->solid = SOLID_BBOX; - rocket->s.effects |= EF_ROCKET; - VectorClear (rocket->mins); - VectorClear (rocket->maxs); - if (home_target) - rocket->s.modelindex = gi.modelindex ("models/objects/hrocket/tris.md2"); - else - rocket->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); - rocket->owner = self; - rocket->touch = rocket_touch; - rocket->dmg = damage; - rocket->radius_dmg = radius_damage; - rocket->dmg_radius = damage_radius; - rocket->s.sound = gi.soundindex ("weapons/rockfly.wav"); - - if (home_target) - { - // homers are shootable - VectorSet(rocket->mins, -10, -3, 0); - VectorSet(rocket->maxs, 10, 3, 6); - rocket->mass = 10; - rocket->health = 5; - rocket->die = rocket_die; - rocket->takedamage = DAMAGE_YES; - rocket->monsterinfo.aiflags = AI_NOSTEP; - - rocket->enemy = home_target; - rocket->classname = "homing rocket"; - rocket->nextthink = level.time + FRAMETIME; - rocket->think = homing_think; - rocket->starttime = level.time + 0.3; // play homing sound on 3rd frame - rocket->endtime = level.time + 8000/speed; - - if (self->client) - { - self->client->homing_rocket = rocket; -// check_dodge (self, rocket->s.origin, dir, speed); - } - Rocket_Evade (rocket, dir, speed); - } - else - { - rocket->classname = "rocket"; - rocket->nextthink = level.time + 8000/speed; - rocket->think = G_FreeEdict; - Rocket_Evade (rocket, dir, speed); - } - - if(level.num_reflectors) - AddReflection(rocket); - - gi.linkentity (rocket); -} - -// NOTE: SP_rocket should ONLY be used to spawn rockets that change maps -// via a trigger_transition. It should NOT be used for map entities - -void rocket_delayed_start (edict_t *rocket) -{ - if(g_edicts[1].linkcount) - { - VectorScale(rocket->movedir,rocket->moveinfo.speed,rocket->velocity); - rocket->nextthink = level.time + 8000/rocket->moveinfo.speed; - rocket->think = G_FreeEdict; - gi.linkentity(rocket); - } - else - rocket->nextthink = level.time + FRAMETIME; -} - -void SP_rocket (edict_t *rocket) -{ - vec3_t dir; - - rocket->class_id = ENTITY_ROCKET; - rocket->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); - rocket->s.sound = gi.soundindex ("weapons/rockfly.wav"); - rocket->touch = rocket_touch; - AngleVectors(rocket->s.angles,dir,NULL,NULL); - VectorCopy (dir, rocket->movedir); - rocket->moveinfo.speed = VectorLength(rocket->velocity); - if(rocket->moveinfo.speed <= 0) - rocket->moveinfo.speed = 650; - - // For SP, freeze rocket until player spawns in - if(game.maxclients == 1) - { - VectorClear(rocket->velocity); - rocket->think = rocket_delayed_start; - rocket->nextthink = level.time + FRAMETIME; - } - else - { - rocket->think = G_FreeEdict; - rocket->nextthink = level.time + 8000/rocket->moveinfo.speed; - } - gi.linkentity (rocket); -} - -/* -================= -fire_rail -================= -*/ -void fire_rail (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick) -{ - vec3_t from; - vec3_t end; - trace_t tr; - edict_t *ignore; - int mask; - bool water; - - VectorMA (start, 8192, aimdir, end); - VectorCopy (start, from); - ignore = self; - water = false; - mask = MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA; - while (ignore) - { - tr = gi.trace (from, NULL, NULL, end, ignore, mask); - - if (tr.contents & (CONTENTS_SLIME|CONTENTS_LAVA)) - { - mask &= ~(CONTENTS_SLIME|CONTENTS_LAVA); - water = true; - } - else - { - //ZOID--added so rail goes through SOLID_BBOX entities (gibs, etc) - if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client) || - (tr.ent->solid == SOLID_BBOX)) - ignore = tr.ent; - else - ignore = NULL; - - if ((tr.ent != self) && (tr.ent->takedamage)) - T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_RAILGUN); - } - - VectorCopy (tr.endpos, from); - } - - // send gun puff / flash - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_RAILTRAIL); - WRITE_COORD (start); - WRITE_COORD (tr.endpos); - MESSAGE_SEND (MSG_PHS, self->s.origin, NULL); - - if (level.num_reflectors) - ReflectTrail(TE_RAILTRAIL,start,tr.endpos); - - if (water) - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_RAILTRAIL); - WRITE_COORD (start); - WRITE_COORD (tr.endpos); - MESSAGE_SEND (MSG_PHS, tr.endpos, NULL); - } - - if (self->client) - PlayerNoise(self, tr.endpos, PNOISE_IMPACT); -} - - -/* -================= -fire_bfg -================= -*/ -void bfg_explode (edict_t *self) -{ - edict_t *ent; - float points; - vec3_t v; - float dist; - - if (self->s.frame == 0) - { - // the BFG effect - ent = NULL; - while ((ent = findradius(ent, self->s.origin, self->dmg_radius)) != NULL) - { - if (!ent->takedamage) continue; - if (ent == self->owner) continue; - if (!CanDamage (ent, self)) continue; - if (!CanDamage (ent, self->owner)) continue; - - VectorAdd (ent->mins, ent->maxs, v); - VectorMA (ent->s.origin, 0.5, v, v); - VectorSubtract (self->s.origin, v, v); - dist = VectorLength(v); - points = self->radius_dmg * (1.0 - sqrt(dist/self->dmg_radius)); - if (ent == self->owner) points = points * 0.5; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_BFG_EXPLOSION); - WRITE_COORD (ent->s.origin); - MESSAGE_SEND (MSG_PHS, ent->s.origin, NULL); - - if(level.num_reflectors) - ReflectExplosion(TE_BFG_EXPLOSION,ent->s.origin); - - T_Damage (ent, self, self->owner, self->velocity, ent->s.origin, vec3_origin, (int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT); - } - } - - self->nextthink = level.time + FRAMETIME; - self->s.frame++; - if (self->s.frame == 5) - self->think = G_FreeEdict; -} - -void bfg_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other == self->owner) - return; - - if (surf && (surf->flags & SURF_SKY)) - { - G_FreeEdict (self); - return; - } - - if (self->owner->client) - PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); - - // core explosion - prevents firing it into the wall/floor - if (other->takedamage) - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, 200, 0, 0, MOD_BFG_BLAST); - T_RadiusDamage(self, self->owner, 200, other, 100, MOD_BFG_BLAST, -0.5); - - gi.sound (self, CHAN_VOICE, gi.soundindex ("weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0); - self->solid = SOLID_NOT; - self->touch = NULL; - VectorMA (self->s.origin, -1 * FRAMETIME, self->velocity, self->s.origin); - VectorClear (self->velocity); - self->s.modelindex = gi.modelindex ("sprites/s_bfg3.spr"); - self->s.frame = 0; - self->s.sound = 0; - self->s.effects &= ~EF_ANIM_ALLFAST; - self->think = bfg_explode; - self->nextthink = level.time + FRAMETIME; - self->enemy = other; - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_BFG_BIGEXPLOSION); - WRITE_COORD (self->s.origin); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - - if(level.num_reflectors) - ReflectExplosion(TE_BFG_BIGEXPLOSION,self->s.origin); -} - - -void bfg_think (edict_t *self) -{ - edict_t *ent; - edict_t *ignore; - vec3_t point; - vec3_t dir; - vec3_t start; - vec3_t end; - int dmg; - trace_t tr; - - if (deathmatch->value) - dmg = 5; - else - dmg = 10; - - ent = NULL; - while ((ent = findradius(ent, self->s.origin, 256)) != NULL) - { - if (ent == self) - continue; - - if (ent == self->owner) - continue; - - if (!ent->takedamage) - continue; - - if (!(ent->svflags & SVF_MONSTER) && (!ent->client) && (ent->class_id != ENTITY_MISC_EXPLOBOX)) - continue; - - VectorMA (ent->absmin, 0.5, ent->size, point); - - VectorSubtract (point, self->s.origin, dir); - VectorNormalize (dir); - - ignore = self; - VectorCopy (self->s.origin, start); - VectorMA (start, 2048, dir, end); - while(1) - { - tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); - - if (!tr.ent) - break; - - // hurt it if we can - if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER) && (tr.ent != self->owner)) - T_Damage (tr.ent, self, self->owner, dir, tr.endpos, vec3_origin, dmg, 1, DAMAGE_ENERGY, MOD_BFG_LASER); - - // if we hit something that's not a monster or player we're done - if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_LASER_SPARKS); - WRITE_BYTE (4); - WRITE_COORD (tr.endpos); - WRITE_DIR (tr.plane.normal); - WRITE_BYTE (self->s.skin); - MESSAGE_SEND (MSG_PVS, tr.endpos, NULL); - break; - } - - ignore = tr.ent; - VectorCopy (tr.endpos, start); - } - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_BFG_LASER); - WRITE_COORD (self->s.origin); - WRITE_COORD (tr.endpos); - MESSAGE_SEND (MSG_PHS, self->s.origin, NULL); - - if(level.num_reflectors) - ReflectTrail(TE_BFG_LASER,self->s.origin,tr.endpos); - } - - self->nextthink = level.time + FRAMETIME; -} - - -void fire_bfg (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius) -{ - edict_t *bfg; - - bfg = G_Spawn(); - VectorCopy (start, bfg->s.origin); - VectorCopy (dir, bfg->movedir); - vectoangles (dir, bfg->s.angles); - VectorScale (dir, speed, bfg->velocity); - bfg->movetype = MOVETYPE_FLYMISSILE; - bfg->clipmask = MASK_SHOT; - bfg->solid = SOLID_BBOX; - bfg->s.effects |= EF_BFG | EF_ANIM_ALLFAST; - VectorClear (bfg->mins); - VectorClear (bfg->maxs); - bfg->s.modelindex = gi.modelindex ("sprites/s_bfg1.spr"); - bfg->owner = self; - bfg->touch = bfg_touch; - bfg->nextthink = level.time + 8000/speed; - bfg->think = G_FreeEdict; - bfg->radius_dmg = damage; - bfg->dmg_radius = damage_radius; - bfg->classname = "bfg blast"; - bfg->s.sound = gi.soundindex ("weapons/bfg__l1a.wav"); - - bfg->think = bfg_think; - bfg->nextthink = level.time + FRAMETIME; - bfg->teammaster = bfg; - bfg->teamchain = NULL; - - if (self->client) - check_dodge (self, bfg->s.origin, dir, speed); - - gi.linkentity (bfg); -} -//========================================================================================== -// -// AimGrenade finds the correct aim vector to get a grenade from start to target at initial -// velocity = speed. Returns false if grenade can't make it to target. -// -//========================================================================================== -bool AimGrenade (edict_t *self, vec3_t start, vec3_t target, vec_t speed, vec3_t aim) -{ - vec3_t angles, forward, right, up; - vec3_t from_origin, from_muzzle; - vec3_t aim_point; - vec_t xo, yo; - vec_t x; - float cosa, t, vx, y; - float drop; - float last_error, v_error; - int i; - vec3_t last_aim; - - VectorCopy(target,aim_point); - VectorSubtract(aim_point,self->s.origin,from_origin); - VectorSubtract(aim_point, start, from_muzzle); - - if(self->svflags & SVF_MONSTER) - { - VectorCopy(from_muzzle,aim); - VectorNormalize(aim); - yo = from_muzzle[2]; - xo = sqrt(from_muzzle[0]*from_muzzle[0] + from_muzzle[1]*from_muzzle[1]); - } - else - { - VectorCopy(from_origin,aim); - VectorNormalize(aim); - yo = from_origin[2]; - xo = sqrt(from_origin[0]*from_origin[0] + from_origin[1]*from_origin[1]); - } - - // If resulting aim vector is looking straight up or straight down, we're - // done. Actually now that I write this down and think about it... should - // probably check straight up to make sure grenade will actually reach the - // target. - if( (aim[2] == 1.0) || (aim[2] == -1.0)) - return true; - - // horizontal distance to target from muzzle - x = sqrt( from_muzzle[0]*from_muzzle[0] + from_muzzle[1]*from_muzzle[1]); - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - // constant horizontal velocity (since grenades don't have drag) - vx = speed * cosa; - // time to reach target x - t = x/vx; - // if flight time is less than one frame, no way grenade will drop much, - // shoot the sucker now. - if(t < FRAMETIME) - return true; - // in that time, grenade will drop this much: - drop = 0.5*sv_gravity->value*t*t; - y = speed*aim[2]*t - drop; - v_error = target[2] - start[2] - y; - - // if we're fairly close and we'll hit target at current angle, - // no need for all this, just shoot it - if( (x < 128) && (fabs(v_error) < 16) ) - return true; - - last_error = 100000.; - VectorCopy(aim,last_aim); - - // Unfortunately there is no closed-form solution for this problem, - // so we creep up on an answer and balk if it takes more than - // 10 iterations to converge to the tolerance we'll accept. - for(i=0; i<10 && fabs(v_error) > 4 && fabs(v_error) < fabs(last_error); i++) - { - last_error = v_error; - aim[2] = cosa * (yo + drop)/xo; - VectorNormalize(aim); - if(!(self->svflags & SVF_MONSTER)) - { - vectoangles(aim,angles); - AngleVectors(angles, forward, right, up); - G_ProjectSource2(self->s.origin,self->move_origin,forward,right,up,start); - VectorSubtract(aim_point,start,from_muzzle); - x = sqrt(from_muzzle[0]*from_muzzle[0] + from_muzzle[1]*from_muzzle[1]); - } - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = speed * cosa; - t = x/vx; - drop = 0.5*sv_gravity->value*t*t; - y = speed*aim[2]*t - drop; - v_error = target[2] - start[2] - y; - if(fabs(v_error) < fabs(last_error)) - VectorCopy(aim,last_aim); - } - - if(i >= 10 || v_error > 64) - return false; - if(fabs(v_error) > fabs(last_error)) - { - VectorCopy(last_aim,aim); - if(!(self->svflags & SVF_MONSTER)) - { - vectoangles(aim,angles); - AngleVectors(angles, forward, right, up); - G_ProjectSource2(self->s.origin,self->move_origin,forward,right,up,start); - VectorSubtract(aim_point,start,from_muzzle); - } - } - - // Sanity check... if launcher is at the same elevation or a bit above the - // target entity, check to make sure he won't bounce grenades off the - // top of a doorway or other obstruction. If he WOULD do that, then figure out - // the max elevation angle that will get the grenade through the door, and - // hope we get a good bounce. - if( (start[2] - target[2] < 160) && - (start[2] - target[2] > -16) ) - { - trace_t tr; - vec3_t dist; - - tr = gi.trace(start,vec3_origin,vec3_origin,aim_point,self,MASK_SOLID); - if( (tr.fraction < 1.0) && (!self->enemy || (tr.ent != self->enemy) )) { - // OK... the aim vector hit a solid, but would the grenade actually hit? - int contents; - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = speed * cosa; - VectorSubtract(tr.endpos,start,dist); - dist[2] = 0; - x = VectorLength(dist); - t = x/vx; - drop = 0.5*sv_gravity->value*t*(t+FRAMETIME); - tr.endpos[2] -= drop; - // move just a bit in the aim direction - tr.endpos[0] += aim[0]; - tr.endpos[1] += aim[1]; - contents = gi.pointcontents(tr.endpos); - while((contents & MASK_SOLID) && (aim_point[2] > target[2])) { - aim_point[2] -= 8.0; - VectorSubtract(aim_point,self->s.origin,from_origin); - VectorCopy(from_origin,aim); - VectorNormalize(aim); - if(!(self->svflags & SVF_MONSTER)) - { - vectoangles(aim,angles); - AngleVectors(angles, forward, right, up); - G_ProjectSource2(self->s.origin,self->move_origin,forward,right,up,start); - VectorSubtract(aim_point,start,from_muzzle); - } - tr = gi.trace(start,vec3_origin,vec3_origin,aim_point,self,MASK_SOLID); - if(tr.fraction < 1.0) { - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = speed * cosa; - VectorSubtract(tr.endpos,start,dist); - dist[2] = 0; - x = VectorLength(dist); - t = x/vx; - drop = 0.5*sv_gravity->value*t*(t+FRAMETIME); - tr.endpos[2] -= drop; - tr.endpos[0] += aim[0]; - tr.endpos[1] += aim[1]; - contents = gi.pointcontents(tr.endpos); - } - } - } - } - return true; -} - diff --git a/server/ents/g_wes.c b/server/ents/g_wes.c deleted file mode 100644 index 134c3c8a..00000000 --- a/server/ents/g_wes.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "g_local.h" - -#ifdef WESQ2 - -void SP_misc_tank(edict_t *self) -{ - gi.modelindex ("models/objects/debris1/tris.md2"); - gi.modelindex ("models/objects/debris2/tris.md2"); - gi.modelindex ("models/objects/debris3/tris.md2"); - - self->solid = SOLID_BBOX; - self->movetype = MOVETYPE_NONE; - if(!self->mass) - self->mass = 50; - if(!self->health) - self->health = 10; - if(!self->dmg) - self->dmg = 20; - self->die = barrel_delay; - self->takedamage = DAMAGE_YES; - self->think = M_droptofloor; - self->nextthink = level.time + 2 * FRAMETIME; - gi.linkentity (self); -} - -void SP_misc_tank1 (edict_t *self) -{ - self->model = "models/objects/tank1/tris.md2"; - self->s.modelindex = gi.modelindex (self->model); - VectorSet (self->mins, -16, -16, 0); - VectorSet (self->maxs, 16, 16, 62); - SP_misc_tank(self); -} -void SP_misc_tank2 (edict_t *self) -{ - self->model = "models/objects/tank2/tris.md2"; - self->s.modelindex = gi.modelindex (self->model); - VectorSet (self->mins, -48, -48, 0); - VectorSet (self->maxs, 48, 48, 185); - SP_misc_tank(self); -} -void SP_misc_ladder (edict_t *self) -{ - self->model = "models/objects/ladder/tris.md2"; - self->s.modelindex = gi.modelindex (self->model); - VectorSet (self->mins,-16,-16, 0); - VectorSet (self->maxs, 16, 16,192); - self->solid = SOLID_BBOX; - self->movetype = MOVETYPE_NONE; - self->think = M_droptofloor; - self->nextthink= level.time + 2 * FRAMETIME; - self->clipmask = MASK_PLAYERSOLID | CONTENTS_LADDER; - gi.linkentity(self); - -} - -void bomb_think (edict_t *self) -{ - vec3_t spark_origin; - vec3_t movedir; - - VectorCopy(self->s.origin,spark_origin); - spark_origin[2] += 16; - VectorSet(movedir,0,0,1); - - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_SPARKS); - gi.WritePosition (spark_origin); - gi.WriteDir (movedir); - gi.multicast (self->s.origin, MULTICAST_PVS); - self->nextthink = level.time + FRAMETIME; -} - -void SP_misc_bomb(edict_t *self) -{ - gi.modelindex ("models/objects/debris1/tris.md2"); - gi.modelindex ("models/objects/debris2/tris.md2"); - gi.modelindex ("models/objects/debris3/tris.md2"); - - self->model = "models/objects/boom/tris.md2"; - self->s.modelindex = gi.modelindex (self->model); - VectorSet (self->mins, -12, -12, -12); - VectorSet (self->maxs, 12, 12, 14); - self->solid = SOLID_BBOX; - self->movetype = MOVETYPE_NONE; - if(!self->health) - self->health = 10; - if(!self->dmg) - self->dmg = 20; - self->die = barrel_delay; - self->takedamage = DAMAGE_YES; - self->think = bomb_think; - self->nextthink = level.time + 2*FRAMETIME; - gi.linkentity (self); -} - -#endif diff --git a/server/global/g_cmds.c b/server/g_cmds.c similarity index 67% rename from server/global/g_cmds.c rename to server/g_cmds.c index 77cd9cb0..26a951cd 100644 --- a/server/global/g_cmds.c +++ b/server/g_cmds.c @@ -335,91 +335,6 @@ void SaveEntProps(edict_t *e, file_t *f) e->monsterinfo.power_armor_power,e->monsterinfo.min_range); } -void ShiftItem(edict_t *ent, int direction) -{ - vec3_t end, forward, start; - vec3_t move; - - edict_t *target; - - if(!ent->client) return; - - target = LookingAt(ent,0,NULL,NULL); - if(!target) return; - - ent->client->shift_dir = direction; - - VectorClear(move); - VectorCopy(ent->s.origin,start); - VectorAdd(target->s.origin,target->origin_offset,end); - VectorSubtract(end,start,forward); - VectorNormalize(forward); - VectorScale(forward,shift_distance->value,forward); - if(direction & 1) - { - if(fabs(forward[0]) > fabs(forward[1])) - move[1] += forward[0]; - else - move[0] -= forward[1]; - } - if(direction & 2) - { - if(fabs(forward[0]) > fabs(forward[1])) - move[1] -= forward[0]; - else - move[0] += forward[1]; - } - if(direction & 4) - { - if(fabs(forward[0]) > fabs(forward[1])) - move[0] += forward[0]; - else - move[1] += forward[1]; - } - if(direction & 8) - { - if(fabs(forward[0]) > fabs(forward[1])) - move[0] -= forward[0]; - else - move[1] -= forward[1]; - } - if(direction & 16) - move[2] += shift_distance->value; - - if(direction & 32) - move[2] -= shift_distance->value; - - if(direction & 64) { - if( target->movetype == MOVETYPE_TOSS || - target->movetype == MOVETYPE_BOUNCE || - target->movetype == MOVETYPE_STEP || - target->movetype == MOVETYPE_PUSHABLE || - target->movetype == MOVETYPE_DEBRIS ) { - M_droptofloor(target); - } - } - - if(direction & 128) { - target->s.angles[PITCH] += rotate_distance->value; - if(target->s.angles[PITCH] > 360) target->s.angles[PITCH] -= 360; - if(target->s.angles[PITCH] < 0) target->s.angles[PITCH] += 360; - } - if(direction & 256) { - target->s.angles[YAW] += rotate_distance->value; - if(target->s.angles[YAW] > 360) target->s.angles[YAW] -= 360; - if(target->s.angles[YAW] < 0) target->s.angles[YAW] += 360; - } - if(direction & 512) { - target->s.angles[ROLL] += rotate_distance->value; - if(target->s.angles[ROLL] > 360) target->s.angles[ROLL] -= 360; - if(target->s.angles[ROLL] < 0) target->s.angles[ROLL] += 360; - } - - VectorAdd(target->s.origin,move,target->s.origin); - if(!(direction & 64)) target->gravity_debounce_time = level.time + 1.0; - gi.linkentity(target); -} - char *ClientTeam (edict_t *ent) { char *p; @@ -470,15 +385,10 @@ void SelectNextItem (edict_t *ent, int itflags) cl = ent->client; - if (cl->menu) { + if (cl->menu) + { PMenu_Next(ent); return; - } else if (cl->textdisplay) { - Text_Next (ent); - return; - } else if (cl->chase_target) { - ChaseNext(ent); - return; } // scan for the next valid one @@ -508,15 +418,10 @@ void SelectPrevItem (edict_t *ent, int itflags) cl = ent->client; - if (cl->menu) { + if (cl->menu) + { PMenu_Prev(ent); return; - } else if (cl->textdisplay) { - Text_Prev (ent); - return; - } else if (cl->chase_target) { - ChasePrev(ent); - return; } // scan for the next valid one @@ -577,34 +482,6 @@ void Cmd_Give_f (edict_t *ent) name = gi.args(); - if(!strcasecmp(name,"jetpack")) - { - if(!developer->value) - { - gi.cprintf(ent, PRINT_HIGH, "Jetpack not available via give cheat\n"); - return; - } - else - { - gitem_t *fuel; - fuel = FindItem("fuel"); - Add_Ammo(ent,fuel,500); - } - - } - if(!developer->value) - { - if( !strcasecmp(name,"flashlight") || - !strcasecmp(name,"fuel") || - !strcasecmp(name,"homing missiles") || - !strcasecmp(name,"stasis generator") ) - { - - gi.cprintf(ent, PRINT_HIGH, "%s not available via give cheat\n",name); - return; - } - } - if (strcasecmp(name, "all") == 0) give_all = true; else @@ -874,29 +751,6 @@ void Cmd_Use_f (edict_t *ent) return; } index = ITEM_INDEX(it); -#ifdef JETPACK_MOD - if(!stricmp(s,"jetpack")) - { - // Special case - turns on/off - if(!ent->client->jetpack) - { - if(ent->waterlevel > 0) - return; - if(!ent->client->pers.inventory[index]) - { - gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", s); - return; - } - else if(ent->client->pers.inventory[fuel_index] <= 0) - { - gi.cprintf(ent, PRINT_HIGH, "No fuel for: %s\n", s); - return; - } - } - it->use(ent,it); - return; - } -#endif if (!stricmp(s,"stasis generator")) { // Special case - turn freeze off if already on @@ -968,15 +822,9 @@ void Cmd_Inven_f (edict_t *ent) cl->showscores = false; cl->showhelp = false; - if (cl->menu) { - PMenu_Close(ent); - ent->client->update_chase = true; - return; - } - - if (cl->textdisplay) + if (cl->menu) { - Text_Close(ent); + PMenu_Close(ent); return; } @@ -994,8 +842,6 @@ void Cmd_Inven_f (edict_t *ent) // Don't show "No Weapon" or "Homing Missile Launcher" in inventory if((i == noweapon_index) || (i == hml_index)) WRITE_SHORT (0); - else if((i == fuel_index) && (ent->client->jetpack_infinite)) - WRITE_SHORT (0); else WRITE_SHORT (cl->pers.inventory[i]); } MESSAGE_SEND(MSG_ONE_R, NULL, ent ); @@ -1029,23 +875,6 @@ void Cmd_InvUse_f (edict_t *ent) gi.cprintf (ent, PRINT_HIGH, "Item is not usable.\n"); return; } - -#ifdef JETPACK_MOD - if(!stricmp(it->classname,"item_jetpack")) - { - if(!ent->client->jetpack) - { - if(ent->waterlevel > 0) - return; - if(ent->client->pers.inventory[fuel_index] <= 0) - { - gi.cprintf(ent, PRINT_HIGH, "No fuel for jetpack\n" ); - return; - } - } - } -#endif - it->use (ent, it); } @@ -1202,9 +1031,6 @@ void Cmd_PutAway_f (edict_t *ent) if (ent->client->menu) PMenu_Close(ent); - if (ent->client->textdisplay) - Text_Close(ent); - ent->client->update_chase = true; } @@ -1633,62 +1459,8 @@ void Cmd_attack2_f(edict_t *ent, bool bOn) } } -void decoy_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - BecomeExplosion1(self); -} - -void decoy_think(edict_t *self) -{ - if(self->s.frame < 0 || self->s.frame > 39) - { - self->s.frame = 0; - } - else - { - self->s.frame++; - if(self->s.frame > 39) - self->s.frame = 0; - } - - // Every 2 seconds, make visible monsters mad at me - if(level.framenum % 20 == 0) - { - edict_t *e; - int i; - - for(i=game.maxclients+1; iinuse) - continue; - if(!(e->svflags & SVF_MONSTER)) - continue; - if(e->monsterinfo.aiflags & AI_GOOD_GUY) - continue; - if(!visible(e,self)) - continue; - if(e->enemy == self) - continue; - e->enemy = e->goalentity = self; - e->monsterinfo.aiflags |= AI_TARGET_ANGER; - FoundTarget (e); - } - } - - self->nextthink = level.time + FRAMETIME; - gi.linkentity(self); -} - void forcewall_think(edict_t *self) { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_FORCEWALL); - WRITE_COORD (self->pos1); - WRITE_COORD (self->pos2); - WRITE_BYTE (self->style); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - self->nextthink = level.time + FRAMETIME; } @@ -1784,322 +1556,11 @@ void ForcewallOff(edict_t *player) G_FreeEdict(tr.ent); } -#ifdef WESQ2 - -void DeleteItem(edict_t *ent) -{ - edict_t *target; - - target = LookingAt(ent,LOOKAT_NOWORLD,NULL,NULL); - if(!target) return; - if(target->my_spawn != 0) - { - SpawnedItem[target->my_spawn-1].classname[0] = 0; - if(target->my_spawn == NumSpawnedItems) - NumSpawnedItems--; - } - G_FreeEdict(target); - -} -/* -================= -GetEntFilename -================= -*/ -void GetEntFilename(char *filename) -{ - cvar_t *game; - game = gi.cvar("game", "", CVAR_SERVERINFO| CVAR_LATCH); - strcpy(filename,game->string); - strcat(filename,"/maps/"); - strcat(filename,level.mapname); - strcat(filename,".ent"); -} - -/* -================= -SaveItems -Saves items spawned with "spawn" console command to a file with same name -as map and ".ent" extension. This file is read by SpawnEntities the next -time the map is run. -================= -*/ -void SaveItems() -{ - file_t *f; - char filename[256]; - int i; - int count; - - if(NumSpawnedItems == 0) return; - - GetEntFilename(filename); - f = gi.fopen(filename,"w", true, false); - count = 0; - for(i=0; i= 512) thickness = 0.; - return thickness; -} -/* -============================== -GetMaterialPropertyFromTexture -============================== -*/ -void GetMaterialPropertyFromTexture(char *texture,char *matl) -{ - if(!texture) - strcpy(matl,"Unknown material"); - else if(strstr(texture,"con") != NULL) - strcpy(matl,"concrete"); - else if(strstr(texture,"wood") != NULL) - strcpy(matl,"wood"); - else if(!strcasecmp(texture,"smd/gray")) - strcpy(matl,"light metal"); - else if(strstr(texture,"corr") != NULL) - strcpy(matl,"corrugated metal"); - else if(strstr(texture,"met") != NULL) - strcpy(matl,"steel"); - else if(strstr(texture,"rock") != NULL) - strcpy(matl,"solid rock"); - else if((strstr(texture,"wnd") != NULL) || (strstr(texture,"wind") != NULL)) - strcpy(matl,"unbreakable window"); - else - sprintf(matl,"Unknown material, texture=%s",texture); -} - - -/* -================================= -Cmd_Identify_f -identifies brush/entity looked at -================================= -*/ -void Cmd_Identify_f (edict_t *ent) -{ - extern vec3_t MOVEDIR_UP; - extern vec3_t MOVEDIR_DOWN; - char matl[64]; - char message[1024]; - char append[256]; - trace_t tr; - vec3_t end, forward, start; - vec_t thickness; - - if (ent->client->textdisplay) - Text_Close(ent); - - VectorCopy(ent->s.origin,start); - start[2] += ent->viewheight; - AngleVectors(ent->client->v_angle, forward, NULL, NULL); - VectorMA(start, 8192, forward, end); - tr = gi.trace (start, NULL, NULL, end, ent, MASK_SHOT); - if (tr.fraction == 1.0) - { - // too far away - gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); - return; - } - else if(!tr.ent) - { - // no hit - gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); - return; - } - else if(strcasecmp(tr.ent->classname,"worldspawn")) - { - // not a world brush - thickness = FindThickness(tr); - if(tr.ent->datafile) - Do_Text_Display(ent,1,tr.ent->datafile); - else - { - GetMaterialPropertyFromTexture(tr.surface->name,matl); - if(!strcasecmp(tr.ent->classname,"func_door_rotating")) - { - int axis; - - axis = 1; - if(tr.ent->spawnflags & 64) axis = 2; - if(tr.ent->spawnflags & 128) axis = 0; - // Don't even try to report door width for doors not parallel to x or y - if(tr.plane.normal[0] == 0) - { - sprintf(message,"%s-hand door\nmaterial = %s\n" - "thickness = %i inches\nwidth = %i inches\nheight = %i inches", - (tr.ent->pos2[axis] > 0 ? "Right" : "Left"), matl, - (int)thickness, - (int)(tr.ent->absmax[0]-tr.ent->absmin[0]), - (int)(tr.ent->absmax[2]-tr.ent->absmin[2])); - } - else if(tr.plane.normal[1] == 0) - { - sprintf(message,"%s-hand door\nmaterial = %s\n" - "thickness = %i inches\nwidth = %i inches\nheight = %i inches", - (tr.ent->pos2[axis] > 0 ? "Right" : "Left"), matl, - (int)thickness, - (int)(tr.ent->absmax[1]-tr.ent->absmin[1]), - (int)(tr.ent->absmax[2]-tr.ent->absmin[2])); - } - else - { - sprintf(message,"%s-hand door\nmaterial = %s\n" - "thickness = %i inches\nheight = %i inches", - (tr.ent->pos2[axis] > 0 ? "Right" : "Left"), matl, - (int)thickness,(int)(tr.ent->absmax[2]-tr.ent->absmin[2])); - } - } - else if(!strcasecmp(tr.ent->classname,"func_door")) - { - char direction[16]; - - if(VectorCompare(tr.ent->movedir,MOVEDIR_UP)) - strcpy(direction,"up"); - else if(VectorCompare(tr.ent->movedir,MOVEDIR_DOWN)) - strcpy(direction,"down"); - else - { - vec_t dot; - dot = DotProduct(tr.plane.normal,tr.ent->movedir); - if(dot > 0) - strcpy(direction,"to right"); - else if(dot < 0) - strcpy(direction,"to left"); - else - { - vec3_t cross; - CrossProduct(tr.plane.normal,tr.ent->movedir,cross); - if(cross[2] > 0) - strcpy(direction,"to right"); - else - strcpy(direction,"to left"); - } - } - sprintf(message,"sliding door, opens %s\n" - "material = %s\nthickness = %i inches\n", - direction,matl,(int)thickness); - if(tr.plane.normal[0] == 0) - { - sprintf(append,"width = %i inches\n", - (int)(tr.ent->absmax[0]-tr.ent->absmin[0])); - strcat(message,append); - } - else if(tr.plane.normal[1] == 0) - { - sprintf(append,"width = %i inches\n", - (int)(tr.ent->absmax[1]-tr.ent->absmin[1])); - strcat(message,append); - } - sprintf(append,"height = %i inches\n", - (int)(tr.ent->absmax[2]-tr.ent->absmin[2])); - strcat(message,append); - } - else if(!strcasecmp(tr.ent->classname,"func_explosive")) - { - if(tr.contents & CONTENTS_TRANSLUCENT) - sprintf(message,"Breakable window\n"); - else - sprintf(message,"Breakable/Explodable object\n", - "damage when broken = %d\n",tr.ent->dmg); - sprintf(append,"thickness = %i inches\n",(int)thickness); - strcat(message,append); - } - else if(!strcasecmp(tr.ent->classname,"func_pushable")) - sprintf(message,"Pushable crate\nweight = %d lb",tr.ent->mass); - else if(!strcasecmp(tr.ent->classname,"misc_bomb")) - sprintf(message,"%d lb charge\n",tr.ent->mass); - else if(!strcasecmp(tr.ent->classname,"misc_tank1")) - strcpy(message,"200 gallon tank\n"); - else if(!strcasecmp(tr.ent->classname,"misc_tank2")) - strcpy(message,"5000 gallon tank\n"); - else - { - strcpy(message,tr.ent->classname); - } - Do_Text_Display(ent,2,message); - } - return; - } - - GetMaterialPropertyFromTexture(tr.surface->name,matl); - - thickness = FindThickness(tr); - - if(thickness > 0.) - sprintf(message,"%s\nthickness = %g inches\n",matl,thickness); - else - sprintf(message,"%s\nunknown thickness\n",matl); - - Do_Text_Display(ent, 2, message); -} -#endif - /* ================= ClientCommand ================= */ -void Restart_FMOD(edict_t *self) -{ - FMOD_Init(); - G_FreeEdict(self); -} void ClientCommand (edict_t *ent) { char *cmd; @@ -2195,19 +1656,6 @@ void ClientCommand (edict_t *ent) #endif #endif - // ==================== fog stuff ========================= - else if (developer->value && !strcasecmp(cmd,"fog")) - Cmd_Fog_f(ent); - else if (developer->value && !strncasecmp(cmd, "fog_", 4)) - Cmd_Fog_f(ent); - // ================ end fog stuff ========================= - - // tpp - else if (strcasecmp (cmd, "thirdperson") == 0) { - Cmd_Chasecam_Toggle (ent); - tpp->value = ent->client->chasetoggle; - } - // alternate attack mode else if (!strcasecmp(cmd,"attack2_off")) Cmd_attack2_f(ent,false); @@ -2216,7 +1664,7 @@ void ClientCommand (edict_t *ent) // zoom else if (!strcasecmp(cmd, "zoomin")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(ent->client->ps.fov > 5) { if(cl_gun->value) stuffcmd(ent,"cl_gun 0\n"); @@ -2227,7 +1675,7 @@ void ClientCommand (edict_t *ent) } } else if (!strcasecmp(cmd, "zoomout")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(ent->client->ps.fov < ent->client->original_fov) { if(cl_gun->value) stuffcmd(ent,"cl_gun 0\n"); @@ -2238,7 +1686,7 @@ void ClientCommand (edict_t *ent) } } else if (!strcasecmp(cmd, "zoom")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(!parm) { gi.dprintf("syntax: zoom [0/1] (0=off, 1=on)\n"); } else if(!atoi(parm)) { @@ -2258,7 +1706,7 @@ void ClientCommand (edict_t *ent) } } else if (!strcasecmp(cmd, "zoomoff")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(ent->client->zoomed && !ent->client->zooming) { ent->client->ps.fov = ent->client->original_fov; ent->client->zooming = 0; @@ -2268,7 +1716,7 @@ void ClientCommand (edict_t *ent) } } else if (!strcasecmp(cmd, "zoomon")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(!ent->client->zoomed && !ent->client->zooming) { ent->client->ps.fov = zoomsnap->value; ent->client->pers.hand = 2; @@ -2281,7 +1729,7 @@ void ClientCommand (edict_t *ent) } } else if (!strcasecmp(cmd, "zoominstop")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(ent->client->zooming > 0) { ent->client->zooming = 0; if(ent->client->ps.fov == ent->client->original_fov) { @@ -2295,7 +1743,7 @@ void ClientCommand (edict_t *ent) } } else if (!strcasecmp(cmd, "zoomoutstop")) { - if(!deathmatch->value && !coop->value && !ent->client->chasetoggle) { + if(!deathmatch->value && !coop->value) { if(ent->client->zooming < 0) { ent->client->zooming = 0; if(ent->client->ps.fov == ent->client->original_fov) { @@ -2399,38 +1847,6 @@ void ClientCommand (edict_t *ent) gi.dprintf("syntax: entlist \n"); } } - else if(!strcasecmp(cmd, "playsound")) - { - vec3_t pos = {0, 0, 0}; - vec3_t vel = {0, 0, 0}; - if(s_primary->value) - { - gi.dprintf("target_playback requires s_primary be set to 0.\n" - "At the console type:\n" - "s_primary 0;sound_restart\n"); - return; - } - if(parm) - { - edict_t *temp; - - strlwr(parm); - temp = G_Spawn(); - temp->message = parm; - temp->volume = 255; - - if( strstr(parm,".mod") || - strstr(parm,".s3m") || - strstr(parm,".xm") || - strstr(parm,".mid") ) - temp->spawnflags |= 8; - - FMOD_PlaySound(temp); - G_FreeEdict(temp); - } - else - gi.dprintf("syntax: playsound , path relative to gamedir\n"); - } else if(!strcasecmp(cmd, "properties")) { if(parm) { @@ -2453,22 +1869,6 @@ void ClientCommand (edict_t *ent) gi.dprintf("syntax: properties \n"); } } - else if(!strcasecmp(cmd,"go")) - { - edict_t *viewing; - float range; - - viewing = LookingAt(ent,0,NULL,&range); - if(range > 512) - return; - if(!(viewing->monsterinfo.aiflags & AI_ACTOR)) - return; - if(viewing->enemy) - return; - if(!(viewing->monsterinfo.aiflags & AI_FOLLOW_LEADER)) - return; - actor_moveit(ent,viewing); - } else if(!strcasecmp(cmd,"hud")) { if(parm) @@ -2546,26 +1946,10 @@ void ClientCommand (edict_t *ent) gi.dprintf("syntax: whereis \n"); } - else if(!strcasecmp(cmd,"sound_restart")) - { - // replacement for snd_restart to get around DirectSound/FMOD problem - edict_t *temp; - FMOD_Shutdown(); - stuffcmd(ent,"snd_restart\n"); - temp = G_Spawn(); - temp->think = Restart_FMOD; - temp->nextthink = level.time + 2; - } - -#ifdef WESQ2 - else { -#else // debugging/developer stuff - else if(developer->value) { -#endif - if (!strcasecmp(cmd,"lightswitch")) - ToggleLights(); - else if (!strcasecmp(cmd,"bbox")) + else if(developer->value) + { + if (!strcasecmp(cmd,"bbox")) Cmd_Bbox_f (ent); else if(!strcasecmp(cmd,"forcewall")) { @@ -2580,12 +1964,7 @@ void ClientCommand (edict_t *ent) if(level.freeze) level.freeze = false; else - { - if(ent->client->jetpack) - gi.dprintf("Cannot use freeze while using jetpack\n"); - else - level.freeze = true; - } + level.freeze = true; } else if (strcasecmp (cmd, "goto") == 0) { @@ -2659,45 +2038,7 @@ void ClientCommand (edict_t *ent) if(!count) gi.dprintf("None found\n"); } - else if (!strcasecmp(cmd,"hint_test")) - { - edict_t *viewing; - int result; - viewing = LookingAt(ent,LOOKAT_MD2,NULL,NULL); - if(!viewing) - return; - if(viewing->monsterinfo.aiflags & AI_HINT_TEST) - { - viewing->monsterinfo.aiflags &= ~AI_HINT_TEST; - gi.dprintf("%s (%s): Back to my normal self now.\n", - viewing->classname,viewing->targetname); - return; - } - if(!(viewing->svflags & SVF_MONSTER)) - gi.dprintf("hint_test is only valid for monsters and actors.\n"); - result = HintTestStart(viewing); - switch(result) - { - case -1: - gi.dprintf("%s (%s): I cannot see any hint_paths from here.\n"); - break; - case 0: - gi.dprintf("This map does not contain hint_paths.\n"); - break; - case 1: - gi.dprintf("%s (%s) searching for hint_path %s at %s. %s\n", - viewing->classname, (viewing->targetname ? viewing->targetname : ""), - (viewing->movetarget->targetname ? viewing->movetarget->targetname : ""), - vtos(viewing->movetarget->s.origin), - visible(viewing,viewing->movetarget) ? "I see it." : "I don't see it."); - break; - default: gi.dprintf("Unknown error\n"); - } - } else if (!strcasecmp(cmd,"id")) { -#ifdef WESQ2 - Cmd_Identify_f(ent); -#else edict_t *viewing; vec3_t origin; float range; @@ -2711,72 +2052,6 @@ void ClientCommand (edict_t *ent) gi.dprintf("absmin,absmax,size=%s, %s, %s, range=%g\n",vtos(viewing->absmin),vtos(viewing->absmax),vtos(viewing->size),range); gi.dprintf("groundentity=%s\n",(viewing->groundentity ? viewing->groundentity->classname : "NULL")); gi.dprintf("movedir=%g %g %g",viewing->movedir[0],viewing->movedir[1],viewing->movedir[2]); -#endif - } - else if (!strcasecmp(cmd, "item_left")) - ShiftItem(ent,1); - else if (!strcasecmp(cmd, "item_right")) - ShiftItem(ent,2); - else if (!strcasecmp(cmd, "item_forward")) - ShiftItem(ent,4); - else if (!strcasecmp(cmd, "item_back")) - ShiftItem(ent,8); - else if (!strcasecmp(cmd, "item_up")) - ShiftItem(ent,16); - else if (!strcasecmp(cmd, "item_down")) - ShiftItem(ent,32); - else if (!strcasecmp(cmd, "item_drop")) - ShiftItem(ent,64); - else if (!strcasecmp(cmd, "item_pitch")) - ShiftItem(ent,128); - else if (!strcasecmp(cmd, "item_yaw")) - ShiftItem(ent,256); - else if (!strcasecmp(cmd, "item_roll")) - ShiftItem(ent,512); - else if (!strcasecmp(cmd, "item_release")) - ent->client->shift_dir = 0; -#ifdef WESQ2 - else if (!strcasecmp(cmd, "delete_item")) - DeleteItem(ent); - else if (!strcasecmp(cmd, "save_items")) - SaveItems(); -#endif - else if(!strcasecmp(cmd,"medic_test")) - { - extern int medic_test; - if(parm) - medic_test = atoi(parm); - else if(medic_test) - medic_test = 0; - else - medic_test = 1; - gi.dprintf("medic_test is %s\n",(medic_test ? "on" : "off")); - } - else if (strstr(cmd, "muzzle")) { - edict_t *viewing; - viewing = LookingAt(ent,0,NULL,NULL); - if(!viewing) - return; - if(!viewing->classname) - return; - if(!(viewing->monsterinfo.aiflags & AI_ACTOR)) - return; - if(gi.argc() < 2) - { - gi.dprintf("Muzzle offset=%g, %g, %g\n", - viewing->muzzle[0],viewing->muzzle[1],viewing->muzzle[2]); - } - else - { - if(!strcasecmp(cmd,"muzzlex")) - viewing->muzzle[0] = atof(gi.argv(1)); - else if(!strcasecmp(cmd,"muzzley")) - viewing->muzzle[1] = atof(gi.argv(1)); - else if(!strcasecmp(cmd,"muzzlez")) - viewing->muzzle[2] = atof(gi.argv(1)); - else - gi.dprintf("Syntax: muzzle[x|y|z] \n"); - } } else if(!strcasecmp(cmd,"range")) { @@ -2821,16 +2096,6 @@ void ClientCommand (edict_t *ent) { edict_t *e; vec3_t forward; -#ifdef WESQ2 - int iSpawn; - - iSpawn = SpawnSlot(); - if(iSpawn >= MAX_SPAWNED_ITEMS) - { - gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); - return; - } -#endif if(!parm) { gi.dprintf("syntax: spawn \n"); @@ -2843,67 +2108,6 @@ void ClientCommand (edict_t *ent) VectorMA(ent->s.origin,128,forward,e->s.origin); e->s.angles[YAW] = ent->s.angles[YAW]; ED_CallSpawn(e); -#ifdef WESQ2 - e->my_spawn = iSpawn+1; - strcpy(SpawnedItem[iSpawn].classname,e->classname); - VectorCopy(e->s.origin,SpawnedItem[iSpawn].origin); - SpawnedItem[iSpawn].angle = e->s.angles[1]; - if(iSpawn == NumSpawnedItems) NumSpawnedItems++; -#endif - } - else if(!strcasecmp(cmd,"spawngoodguy")) - { - edict_t *e; - vec3_t forward; - - if(gi.argc() < 3) - { - gi.dprintf("syntax: spawngoodguy \n"); - return; - } - e = G_Spawn(); - e->classname = TagMalloc(12,TAG_LEVEL); - strcpy(e->classname,"misc_actor"); - e->usermodel = gi.argv(1); - e->sounds = atoi(gi.argv(2)); - e->spawnflags = SF_MONSTER_GOODGUY; - AngleVectors(ent->client->v_angle,forward,NULL,NULL); - VectorMA(ent->s.origin,128,forward,e->s.origin); - e->s.origin[2] = max(e->s.origin[2],ent->s.origin[2] + 8); - e->s.angles[YAW] = ent->s.angles[YAW]; - ED_CallSpawn(e); - actor_files(); - } - else if(!strcasecmp(cmd,"spawnself")) - { - edict_t *decoy; - vec3_t forward; - - decoy = G_Spawn(); - decoy->classname = "fakeplayer"; - memcpy(&decoy->s,&ent->s,sizeof(entity_state_t)); - decoy->s.number = decoy-g_edicts; - decoy->s.frame = ent->s.frame; - AngleVectors(ent->client->v_angle,forward,NULL,NULL); - VectorMA(ent->s.origin,64,forward,decoy->s.origin); - decoy->s.angles[YAW] = ent->s.angles[YAW]; - decoy->takedamage = DAMAGE_AIM; - decoy->flags = (ent->flags & FL_NOTARGET); - decoy->movetype = MOVETYPE_TOSS; - decoy->viewheight = ent->viewheight; - decoy->mass = ent->mass; - decoy->solid = SOLID_BBOX; - decoy->deadflag = DEAD_NO; - decoy->clipmask = MASK_PLAYERSOLID; - decoy->health = ent->health; - decoy->light_level = ent->light_level; - decoy->think = decoy_think; - decoy->monsterinfo.aiflags = AI_GOOD_GUY; - decoy->die = decoy_die; - decoy->nextthink = level.time + FRAMETIME; - VectorCopy(ent->mins,decoy->mins); - VectorCopy(ent->maxs,decoy->maxs); - gi.linkentity (decoy); } else if (!strcasecmp(cmd,"stepleft")) { vec3_t left; @@ -2912,33 +2116,12 @@ void ClientCommand (edict_t *ent) VectorMA(ent->s.origin,4,left,ent->s.origin); gi.linkentity(ent); } - else if (!strcasecmp(cmd,"switch")) { - extern mmove_t actor_move_switch; - edict_t *viewing; - - viewing = LookingAt(ent,0,NULL,NULL); - if(!viewing) - return; - if(!(viewing->monsterinfo.aiflags & AI_ACTOR)) - { - gi.dprintf("Must be a misc_actor\n"); - return; - } - viewing->monsterinfo.currentmove = &actor_move_switch; - } else if(!strcasecmp(cmd,"texture")) { trace_t tr; vec3_t forward, start, end; - if(ent->client->chasetoggle) - { - VectorCopy(ent->client->chasecam->s.origin,start); - } - else - { - VectorCopy(ent->s.origin, start); - start[2] += ent->viewheight; - } + VectorCopy(ent->s.origin, start); + start[2] += ent->viewheight; AngleVectors(ent->client->v_angle, forward, NULL, NULL); VectorMA(start, 8192, forward, end); tr = gi.trace(start,NULL,NULL,end,ent,MASK_ALL); @@ -2973,10 +2156,4 @@ void ClientCommand (edict_t *ent) Cmd_Say_f (ent, false, true); } // end debugging stuff - -#ifndef WESQ2 - else // anything that doesn't match a command will be a chat - Cmd_Say_f (ent, false, true); -#endif - } diff --git a/server/ents/g_items.c b/server/g_items.c similarity index 64% rename from server/ents/g_items.c rename to server/g_items.c index 042be40f..b65987cc 100644 --- a/server/ents/g_items.c +++ b/server/g_items.c @@ -6,17 +6,7 @@ void Use_Weapon (edict_t *ent, gitem_t *inv); void Drop_Weapon (edict_t *ent, gitem_t *inv); void Weapon_Blaster (edict_t *ent); -void Weapon_Shotgun (edict_t *ent); -void Weapon_SuperShotgun (edict_t *ent); -void Weapon_Machinegun (edict_t *ent); -void Weapon_Chaingun (edict_t *ent); void Weapon_HyperBlaster (edict_t *ent); -void Weapon_RocketLauncher (edict_t *ent); -void Weapon_Grenade (edict_t *ent); -void Weapon_GrenadeLauncher (edict_t *ent); -void Weapon_Railgun (edict_t *ent); -void Weapon_BFG (edict_t *ent); -void Weapon_HomingMissileLauncher (edict_t *ent); void Weapon_Null(edict_t *ent); gitem_armor_t jacketarmor_info = { 25, 50, .30, .00, ARMOR_JACKET}; @@ -61,9 +51,6 @@ void item_die(edict_t *self,edict_t *inflictor, edict_t *attacker, int damage, v WRITE_COORD (self->s.origin); MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - if (level.num_reflectors) - ReflectExplosion (TE_EXPLOSION1, self->s.origin); - if (!(self->spawnflags & DROPPED_ITEM) && (deathmatch->value)) SetRespawn (self, 30); else @@ -908,8 +895,6 @@ void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf if (!taken) return; - DeleteReflection(ent,-1); - if (!((coop->value) && (ent->item->flags & IT_STAY_COOP)) || (ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) { if (ent->flags & FL_RESPAWN) @@ -1074,10 +1059,7 @@ void droptofloor (edict_t *ent) } else ent->solid = SOLID_TRIGGER; - // Lazarus: - if(ent->movewith) - ent->movetype = MOVETYPE_PUSH; - else if(ent->spawnflags & NO_DROPTOFLOOR) + if(ent->spawnflags & NO_DROPTOFLOOR) ent->movetype = MOVETYPE_NONE; else ent->movetype = MOVETYPE_TOSS; @@ -1313,156 +1295,11 @@ gitem_t itemlist[] = NULL }, // leave index 0 alone - // - // ARMOR - // - -/*QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_armor_body", - Pickup_Armor, - NULL, - NULL, - NULL, - "misc/ar1_pkup.wav", - "models/items/armor/body/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_bodyarmor", -/* pickup */ "Body Armor", -/* width */ 3, - 0, - NULL, - IT_ARMOR, - 0, - &bodyarmor_info, - ARMOR_BODY, -/* precache */ "" - }, - -/*QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_armor_combat", - Pickup_Armor, - NULL, - NULL, - NULL, - "misc/ar1_pkup.wav", - "models/items/armor/combat/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_combatarmor", -/* pickup */ "Combat Armor", -/* width */ 3, - 0, - NULL, - IT_ARMOR, - 0, - &combatarmor_info, - ARMOR_COMBAT, -/* precache */ "" - }, - -/*QUAKED item_armor_jacket (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_armor_jacket", - Pickup_Armor, - NULL, - NULL, - NULL, - "misc/ar1_pkup.wav", - "models/items/armor/jacket/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_jacketarmor", -/* pickup */ "Jacket Armor", -/* width */ 3, - 0, - NULL, - IT_ARMOR, - 0, - &jacketarmor_info, - ARMOR_JACKET, -/* precache */ "" - }, - -/*QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_armor_shard", - Pickup_Armor, - NULL, - NULL, - NULL, - "misc/ar2_pkup.wav", - "models/items/armor/shard/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_jacketarmor", -/* pickup */ "Armor Shard", -/* width */ 3, - 0, - NULL, - IT_ARMOR, - 0, - NULL, - ARMOR_SHARD, -/* precache */ "" - }, - - -/*QUAKED item_power_screen (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_power_screen", - Pickup_PowerArmor, - Use_PowerArmor, - Drop_PowerArmor, - NULL, - "misc/ar3_pkup.wav", - "models/items/armor/screen/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_powerscreen", -/* pickup */ "Power Screen", -/* width */ 0, - 60, - NULL, - IT_ARMOR, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED item_power_shield (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_power_shield", - Pickup_PowerArmor, - Use_PowerArmor, - Drop_PowerArmor, - NULL, - "misc/ar3_pkup.wav", - "models/items/armor/shield/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_powershield", -/* pickup */ "Power Shield", -/* width */ 0, - 60, - NULL, - IT_ARMOR, - 0, - NULL, - 0, -/* precache */ "misc/power2.wav misc/power1.wav" - }, - -#ifdef FLASHLIGHT_MOD -#if FLASHLIGHT_USE != POWERUP_USE_ITEM { "item_flashlight", Pickup_Powerup, Use_Flashlight, - Drop_General, + Drop_General, NULL, "items/pkup.wav", "models/items/f_light/tris.md2", EF_ROTATE, @@ -1478,9 +1315,6 @@ gitem_t itemlist[] = 0, "" }, -#endif -#endif - // // WEAPONS // @@ -1507,260 +1341,6 @@ gitem_t itemlist[] = 0, "weapons/blastf1a.wav misc/lasfly.wav" }, - -/*QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_shotgun", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_Shotgun, - "misc/w_pkup.wav", - "models/weapons/g_shotg/tris.md2", EF_ROTATE, - "models/weapons/v_shotg/tris.md2", -/* icon */ "w_shotgun", -/* pickup */ "Shotgun", - 0, - 1, - "Shells", - IT_WEAPON|IT_STAY_COOP, - WEAP_SHOTGUN, - NULL, - 0, -/* precache */ "weapons/shotgf1b.wav weapons/shotgr1b.wav" - }, - -/*QUAKED weapon_supershotgun (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_supershotgun", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_SuperShotgun, - "misc/w_pkup.wav", - "models/weapons/g_shotg2/tris.md2", EF_ROTATE, - "models/weapons/v_shotg2/tris.md2", -/* icon */ "w_sshotgun", -/* pickup */ "Super Shotgun", - 0, - 2, - "Shells", - IT_WEAPON|IT_STAY_COOP, - WEAP_SUPERSHOTGUN, - NULL, - 0, -/* precache */ "weapons/sshotf1b.wav" - }, - -/*QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_machinegun", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_Machinegun, - "misc/w_pkup.wav", - "models/weapons/g_machn/tris.md2", EF_ROTATE, - "models/weapons/v_machn/tris.md2", -/* icon */ "w_machinegun", -/* pickup */ "Machinegun", - 0, - 1, - "Bullets", - IT_WEAPON|IT_STAY_COOP, - WEAP_MACHINEGUN, - NULL, - 0, -/* precache */ "weapons/machgf1b.wav weapons/machgf2b.wav weapons/machgf3b.wav weapons/machgf4b.wav weapons/machgf5b.wav" - }, - -/*QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_chaingun", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_Chaingun, - "misc/w_pkup.wav", - "models/weapons/g_chain/tris.md2", EF_ROTATE, - "models/weapons/v_chain/tris.md2", -/* icon */ "w_chaingun", -/* pickup */ "Chaingun", - 0, - 1, - "Bullets", - IT_WEAPON|IT_STAY_COOP, - WEAP_CHAINGUN, - NULL, - 0, -/* precache */ "weapons/chngnu1a.wav weapons/chngnl1a.wav weapons/machgf3b.wav` weapons/chngnd1a.wav" - }, - -/*QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_grenades", - Pickup_Ammo, - Use_Weapon, - Drop_Ammo, - Weapon_Grenade, - "misc/am_pkup.wav", - "models/items/ammo/grenades/medium/tris.md2", 0, - "models/weapons/v_handgr/tris.md2", -/* icon */ "a_grenades", -/* pickup */ "Grenades", -/* width */ 3, - 5, - "grenades", - IT_AMMO|IT_WEAPON, - WEAP_GRENADES, - NULL, - AMMO_GRENADES, -/* precache */ "weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav " - }, - -/*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_grenadelauncher", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_GrenadeLauncher, - "misc/w_pkup.wav", - "models/weapons/g_launch/tris.md2", EF_ROTATE, - "models/weapons/v_launch/tris.md2", -/* icon */ "w_glauncher", -/* pickup */ "Grenade Launcher", - 0, - 1, - "Grenades", - IT_WEAPON|IT_STAY_COOP, - WEAP_GRENADELAUNCHER, - NULL, - 0, -/* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav" - }, - -/*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_rocketlauncher", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_RocketLauncher, - "misc/w_pkup.wav", - "models/weapons/g_rocket/tris.md2", EF_ROTATE, - "models/weapons/v_rocket/tris.md2", -/* icon */ "w_rlauncher", -/* pickup */ "Rocket Launcher", - 0, - 1, - "Rockets", - IT_WEAPON|IT_STAY_COOP, - WEAP_ROCKETLAUNCHER, - NULL, - 0, -/* precache */ "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2" - }, - -/*QUAKED weapon_hyperblaster (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_hyperblaster", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_HyperBlaster, - "misc/w_pkup.wav", - "models/weapons/g_hyperb/tris.md2", EF_ROTATE, - "models/weapons/v_hyperb/tris.md2", -/* icon */ "w_hyperblaster", -/* pickup */ "HyperBlaster", - 0, - 1, - "Cells", - IT_WEAPON|IT_STAY_COOP, - WEAP_HYPERBLASTER, - NULL, - 0, -/* precache */ "weapons/hyprbu1a.wav weapons/hyprbl1a.wav weapons/hyprbf1a.wav weapons/hyprbd1a.wav misc/lasfly.wav" - }, - -/*QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_railgun", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_Railgun, - "misc/w_pkup.wav", - "models/weapons/g_rail/tris.md2", EF_ROTATE, - "models/weapons/v_rail/tris.md2", -/* icon */ "w_railgun", -/* pickup */ "Railgun", - 0, - 1, - "Slugs", - IT_WEAPON|IT_STAY_COOP, - WEAP_RAILGUN, - NULL, - 0, -/* precache */ "weapons/rg_hum.wav" - }, - -/*QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_bfg", - Pickup_Weapon, - Use_Weapon, - Drop_Weapon, - Weapon_BFG, - "misc/w_pkup.wav", - "models/weapons/g_bfg/tris.md2", EF_ROTATE, - "models/weapons/v_bfg/tris.md2", -/* icon */ "w_bfg", -/* pickup */ "BFG10K", - 0, - 50, - "Cells", - IT_WEAPON|IT_STAY_COOP, - WEAP_BFG, - NULL, - 0, -/* precache */ "sprites/s_bfg1.spr sprites/s_bfg2.spr sprites/s_bfg3.spr weapons/bfg__f1y.wav weapons/bfg__l1a.wav weapons/bfg__x1b.wav weapons/bfg_hum.wav" - }, - -/*QUAKED weapon_hml (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "weapon_hml", - NULL, - Use_Weapon, - NULL, - Weapon_HomingMissileLauncher, - NULL, - NULL, EF_ROTATE, - "models/weapons/v_homing/tris.md2", -/* icon */ NULL, -/* pickup */ "Homing Missile Launcher", - 0, - 1, - "homing missiles", - IT_WEAPON|IT_STAY_COOP, - WEAP_ROCKETLAUNCHER, - NULL, - 0, -/* precache */ "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2" - }, - // Lazarus: No weapon - we HAVE to have a weapon { "weapon_null", @@ -1782,408 +1362,6 @@ gitem_t itemlist[] = 0, "" }, - - // - // AMMO ITEMS - // - -/*QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_shells", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/shells/medium/tris.md2", 0, - NULL, -/* icon */ "a_shells", -/* pickup */ "Shells", -/* width */ 3, - 10, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_SHELLS, -/* precache */ "" - }, - -/*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_bullets", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/bullets/medium/tris.md2", 0, - NULL, -/* icon */ "a_bullets", -/* pickup */ "Bullets", -/* width */ 3, - 50, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_BULLETS, -/* precache */ "" - }, - -/*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_cells", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/cells/medium/tris.md2", 0, - NULL, -/* icon */ "a_cells", -/* pickup */ "Cells", -/* width */ 3, - 50, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_CELLS, -/* precache */ "" - }, - -/*QUAKED ammo_fuel (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_fuel", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/fuel/medium/tris.md2", 0, - NULL, -/* icon */ "a_fuel", -/* pickup */ "fuel", -/* width */ 4, - 500, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_FUEL, -/* precache */ "" - }, - - -/*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_rockets", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/rockets/medium/tris.md2", 0, - NULL, -/* icon */ "a_rockets", -/* pickup */ "Rockets", -/* width */ 3, - 5, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_ROCKETS, -/* precache */ "" - }, - -/*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_slugs", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/slugs/medium/tris.md2", 0, - NULL, -/* icon */ "a_slugs", -/* pickup */ "Slugs", -/* width */ 3, - 10, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_SLUGS, -/* precache */ "" - }, - -/*QUAKED ammo_homing_missiles (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "ammo_homing_missiles", - Pickup_Ammo, - NULL, - Drop_Ammo, - NULL, - "misc/am_pkup.wav", - "models/items/ammo/homing/medium/tris.md2", 0, - NULL, -/* icon */ "a_homing", -/* pickup */ "homing missiles", -/* width */ 3, - 5, - NULL, - IT_AMMO, - 0, - NULL, - AMMO_HOMING_MISSILES, -/* precache */ "" - }, - - // - // POWERUP ITEMS - // -/*QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_quad", - Pickup_Powerup, - Use_Quad, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/quaddama/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_quad", -/* pickup */ "Quad Damage", -/* width */ 2, - 60, - NULL, - IT_POWERUP, - 0, - NULL, - 0, -/* precache */ "items/damage.wav items/damage2.wav items/damage3.wav" - }, - -/*QUAKED item_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_invulnerability", - Pickup_Powerup, - Use_Invulnerability, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/invulner/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_invulnerability", -/* pickup */ "Invulnerability", -/* width */ 2, - 300, - NULL, - IT_POWERUP, - 0, - NULL, - 0, -/* precache */ "items/protect.wav items/protect2.wav items/protect4.wav" - }, - -/*QUAKED item_silencer (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_silencer", - Pickup_Powerup, - Use_Silencer, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/silencer/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_silencer", -/* pickup */ "Silencer", -/* width */ 2, - 60, - NULL, - IT_POWERUP, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED item_breather (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_breather", - Pickup_Powerup, - Use_Breather, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/breather/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_rebreather", -/* pickup */ "Rebreather", -/* width */ 2, - 60, - NULL, - IT_STAY_COOP|IT_POWERUP, - 0, - NULL, - 0, -/* precache */ "items/airout.wav" - }, - -/*QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_enviro", - Pickup_Powerup, - Use_Envirosuit, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/enviro/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_envirosuit", -/* pickup */ "Environment Suit", -/* width */ 2, - 60, - NULL, - IT_STAY_COOP|IT_POWERUP, - 0, - NULL, - 0, -/* precache */ "items/airout.wav" - }, - -/*QUAKED item_ancient_head (.3 .3 1) (-16 -16 -16) (16 16 16) -Special item that gives +2 to maximum health -*/ - { - "item_ancient_head", - Pickup_AncientHead, - NULL, - NULL, - NULL, - "items/pkup.wav", - "models/items/c_head/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_fixme", -/* pickup */ "Ancient Head", -/* width */ 2, - 60, - NULL, - 0, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED item_adrenaline (.3 .3 1) (-16 -16 -16) (16 16 16) -gives +1 to maximum health -*/ - { - "item_adrenaline", - Pickup_Adrenaline, - NULL, - NULL, - NULL, - "items/pkup.wav", - "models/items/adrenal/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_adrenaline", -/* pickup */ "Adrenaline", -/* width */ 2, - 60, - NULL, - 0, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED item_bandolier (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_bandolier", - Pickup_Bandolier, - NULL, - NULL, - NULL, - "items/pkup.wav", - "models/items/band/tris.md2", EF_ROTATE, - NULL, -/* icon */ "p_bandolier", -/* pickup */ "Bandolier", -/* width */ 2, - 60, - NULL, - 0, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED item_pack (.3 .3 1) (-16 -16 -16) (16 16 16) -*/ - { - "item_pack", - Pickup_Pack, - NULL, - NULL, - NULL, - "items/pkup.wav", - "models/items/pack/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_pack", -/* pickup */ "Ammo Pack", -/* width */ 2, - 180, - NULL, - 0, - 0, - NULL, - 0, -/* precache */ "" - }, - -#ifdef JETPACK_MOD - { - "item_jetpack", - Pickup_Powerup, - Use_Jet, - Drop_Jetpack, - NULL, - "items/pkup.wav", - "models/items/jet/tris.md2", EF_ROTATE, - NULL, - "p_jet", - "Jetpack", - 2, - 600, - "fuel", - IT_POWERUP, - 0, - NULL, - 0, - "jetpack/activate.wav jetpack/rev1.wav jetpack/revrun.wav jetpack/running.wav jetpack/shutdown.wav jetpack/stutter.wav" - }, -#endif - { "item_freeze", Pickup_Powerup, @@ -2204,249 +1382,6 @@ gives +1 to maximum health 0, "items/stasis_start.wav items/stasis.wav items/stasis_stop.wav" }, - // - // KEYS - // -/*QUAKED key_data_cd (0 .5 .8) (-16 -16 -16) (16 16 16) -key for computer centers -*/ - { - "key_data_cd", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/data_cd/tris.md2", EF_ROTATE, - NULL, - "k_datacd", - "Data CD", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_power_cube (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN NO_TOUCH -warehouse circuits -*/ - { - "key_power_cube", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/power/tris.md2", EF_ROTATE, - NULL, - "k_powercube", - "Power Cube", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_pyramid (0 .5 .8) (-16 -16 -16) (16 16 16) -key for the entrance of jail3 -*/ - { - "key_pyramid", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/pyramid/tris.md2", EF_ROTATE, - NULL, - "k_pyramid", - "Pyramid Key", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_data_spinner (0 .5 .8) (-16 -16 -16) (16 16 16) -key for the city computer -*/ - { - "key_data_spinner", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/spinner/tris.md2", EF_ROTATE, - NULL, - "k_dataspin", - "Data Spinner", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_pass (0 .5 .8) (-16 -16 -16) (16 16 16) -security pass for the security level -*/ - { - "key_pass", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/pass/tris.md2", EF_ROTATE, - NULL, - "k_security", - "Security Pass", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_blue_key (0 .5 .8) (-16 -16 -16) (16 16 16) -normal door key - blue -*/ - { - "key_blue_key", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/key/tris.md2", EF_ROTATE, - NULL, - "k_bluekey", - "Blue Key", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_red_key (0 .5 .8) (-16 -16 -16) (16 16 16) -normal door key - red -*/ - { - "key_red_key", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/red_key/tris.md2", EF_ROTATE, - NULL, - "k_redkey", - "Red Key", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_commander_head (0 .5 .8) (-16 -16 -16) (16 16 16) -tank commander's head -*/ - { - "key_commander_head", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/monsters/commandr/head/tris.md2", EF_GIB, - NULL, -/* icon */ "k_comhead", -/* pickup */ "Commander's Head", -/* width */ 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, - -/*QUAKED key_airstrike_target (0 .5 .8) (-16 -16 -16) (16 16 16) -tank commander's head -*/ - { - "key_airstrike_target", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/target/tris.md2", EF_ROTATE, - NULL, -/* icon */ "i_airstrike", -/* pickup */ "Airstrike Marker", -/* width */ 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, -/* precache */ "" - }, -/* - { - NULL, - Pickup_Health, - NULL, - NULL, - NULL, - "items/pkup.wav", - NULL, 0, - NULL, - "i_health", - "Health", - 3, - 0, - NULL, - 0, - 0, - NULL, - 0, - "items/s_health.wav items/n_health.wav items/l_health.wav items/m_health.wav" - }, -*/ - // Lazarus: Dunno what adding actual health models might end up fouling up, but - // we'll give it a try for now. This will allow monsters to give up health. - { "item_health_small", Pickup_Health, @@ -2467,7 +1402,6 @@ tank commander's head HEALTH_IGNORE_MAX, "items/s_health.wav" }, - { "item_health", Pickup_Health, @@ -2488,50 +1422,6 @@ tank commander's head 0, "items/n_health.wav" }, - - { - "item_health_large", - Pickup_Health, - NULL, - NULL, - NULL, - "items/l_health.wav", - "models/items/healing/large/tris.md2", 0, - NULL, - "i_health", - "Health", - 3, - 25, - NULL, - 0, - 0, - NULL, - 0, - "items/l_health.wav" - }, - - { - "item_health_mega", - Pickup_Health, - NULL, - NULL, - NULL, - "items/m_health.wav", - "models/items/mega_h/tris.md2", 0, - NULL, - "i_health", - "Health", - 3, - 100, - NULL, - 0, - 0, - NULL, - HEALTH_IGNORE_MAX | HEALTH_TIMED, - "items/m_health.wav" - }, - - // end of list marker {NULL} }; @@ -2723,11 +1613,6 @@ void Use_Jet ( edict_t *ent, gitem_t *item ) // Lazarus: Stasis field generator void Use_Stasis ( edict_t *ent, gitem_t *item ) { - if(ent->client->jetpack) - { - gi.dprintf("Cannot use stasis generator while using jetpack\n"); - return; - } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem (ent); level.freeze = true; diff --git a/server/g_local.h b/server/g_local.h index 9aeeb8bc..6dc75726 100644 --- a/server/g_local.h +++ b/server/g_local.h @@ -22,8 +22,6 @@ #include "ref_system.h" #include "ref_server.h" #include "p_menu.h" -#include "p_text.h" -#define JETPACK_MOD // the "gameversion" client command will print this plus compile date #define GAMEVERSION "xash" @@ -89,9 +87,6 @@ network messaging manager //================================================================== -// Lazarus: When visibility is reduced below this level, aiming accuracy suffers: -#define FOG_CANSEEGOOD 0.12 - // view pitching times #define DAMAGE_TIME 0.5 #define FALL_TIME 0.3 @@ -119,7 +114,6 @@ network messaging manager #define FL_NO_KNOCKBACK 0x00000800 #define FL_POWER_ARMOR 0x00001000 // power armor (if any) is active #define FL_BOB 0x00002000 // Lazarus: Used for bobbing water -#define FL_TURRET_OWNER 0x00004000 // Lazarus: player on turret and controlling it #define FL_TRACKTRAIN 0x00008000 #define FL_DISGUISED 0x00020000 // entity is in disguise, monsters will not recognize. @@ -128,7 +122,6 @@ network messaging manager #define FL_REVERSIBLE 0x00080000 // Lazarus: used for reversible func_door_rotating #define FL_REVOLVING 0x00100000 // Lazarus revolving door #define FL_ROBOT 0x00200000 // Player-controlled robot or monster. Relax yaw constraints -#define FL_REFLECT 0x00400000 // Reflection entity #define FL_RESPAWN 0x80000000 // used for item respawning @@ -190,13 +183,6 @@ typedef enum #define AI_COMBAT_POINT 0x00001000 #define AI_MEDIC 0x00002000 #define AI_RESURRECTING 0x00004000 -//ROGUE (Lazarus: Eliminate many inapplicable Rogue AI flags to make room for more) -#define AI_TARGET_ANGER 0x00008000 -#define AI_HINT_PATH 0x00010000 -#define AI_BLOCKED 0x00020000 // used by blocked_checkattack: set to say I'm attacking while blocked - // (prevents run-attacks) -//ROGUE -// Lazarus: #define AI_ACTOR 0x00040000 // Is this a misc_actor? #define AI_FOLLOW_LEADER 0x00080000 // misc_actor only #define AI_TWO_GUNS 0x00100000 // misc_actor only - nothing to do with AI really, @@ -207,7 +193,6 @@ typedef enum #define AI_FREEFORALL 0x00400000 // Set by target_monsterbattle, lets dmgteam monsters // attack monsters on opposion dmgteam #define AI_RANGE_PAUSE 0x00800000 -#define AI_CHASE_THING 0x01000000 #define AI_SEEK_COVER 0x02000000 #define AI_CHICKEN 0x04000000 #define AI_MEDIC_PATROL 0x08000000 @@ -363,23 +348,6 @@ typedef struct bool autosaved; } game_locals_t; -struct fog_s -{ - bool Trigger; - int Model; - float Near; - float Far; - float Density; - float Density1; - float Density2; - vec3_t Dir; - int GL_Model; - vec3_t Color; - vec3_t GlideColor; - edict_t *ent; -}; -typedef struct fog_s fog_t; - // // this structure is cleared as each map is entered // it is read/written to the level.sav file for savegames @@ -425,18 +393,6 @@ typedef struct int power_cubes; // ugly necessity for coop - // ROGUE - edict_t *disguise_violator; - int disguise_violation_framenum; - // ROGUE - - // Lazarus - int fogs; - int trigger_fogs; - int active_target_fog; - int active_fog; - int last_active_fog; - fog_t fog; int flashlight_cost; // cost/10 seconds for flashlight int mud_puddles; int num_3D_sounds; @@ -444,7 +400,6 @@ typedef struct bool freeze; int freezeframes; int next_skill; - int num_reflectors; } level_locals_t; @@ -562,40 +517,6 @@ typedef struct int power_armor_type; int power_armor_power; -//ROGUE - bool (*blocked)(edict_t *self, float dist); - float last_hint_time; // last time the monster checked for hintpaths. - edict_t *goal_hint; // which hint_path we're trying to get to - int medicTries; - edict_t *badMedic1, *badMedic2; // these medics have declared this monster "unhealable" - edict_t *healer; // this is who is healing this monster - void (*duck)(edict_t *self, float eta); - void (*unduck)(edict_t *self); - void (*sidestep)(edict_t *self); - // while abort_duck would be nice, only monsters which duck but don't sidestep would use it .. only the brain - // not really worth it. sidestep is an implied abort_duck -// void (*abort_duck)(edict_t *self); - float base_height; - float next_duck_time; - float duck_wait_time; - edict_t *last_player_enemy; - // blindfire stuff .. the boolean says whether the monster will do it, and blind_fire_time is the timing - // (set in the monster) of the next shot - bool blindfire; // will the monster blindfire? - float blind_fire_delay; - vec3_t blind_fire_target; - // used by the spawners to not spawn too much and keep track of #s of monsters spawned - int monster_slots; - int monster_used; - edict_t *commander; - // powerup timers, used by widow, our friend - float quad_framenum; - float invincible_framenum; - float double_framenum; - edict_t *leader; - edict_t *old_leader; -//ROGUE -//Lazarus float min_range; // Monsters stop chasing enemy at this distance float max_range; // Monsters won't notice or attack targets farther than this float ideal_range[2]; // Ideal low and high range from target, weapon-specific @@ -605,17 +526,10 @@ typedef struct float rangetime; int chicken_framenum; int pathdir; // Up/down a hint_path chain flag for medic - float visibility; // Ratio of visibility (it's a fog thang) + float visibility; // Ratio of visibility -//end Lazarus } monsterinfo_t; -// ROGUE -// this determines how long to wait after a duck to duck again. this needs to be longer than -// the time after the monster_duck_up in all of the animation sequences -#define DUCK_INTERVAL 0.5 -// ROGUE - extern game_locals_t game; extern level_locals_t level; extern game_import_t gi; @@ -735,7 +649,6 @@ extern cvar_t *actorjump; extern cvar_t *actorscram; extern cvar_t *alert_sounds; extern cvar_t *allow_download; -extern cvar_t *allow_fog; // Set to 0 for no fog extern cvar_t *bounce_bounce; extern cvar_t *bounce_minv; extern cvar_t *cd_loopcount; @@ -743,14 +656,10 @@ extern cvar_t *cl_gun; extern cvar_t *corpse_fade; extern cvar_t *corpse_fadetime; extern cvar_t *crosshair; -extern cvar_t *crossh; extern cvar_t *developer; -extern cvar_t *fmod_nomusic; -extern cvar_t *footstep_sounds; extern cvar_t *fov; extern cvar_t *gl_clear; -extern cvar_t *gl_driver; -extern cvar_t *gl_driver_fog; // Name of dll to load for Default OpenGL mode +extern cvar_t *gl_driver; extern cvar_t *hand; extern cvar_t *jetpack_weenie; extern cvar_t *joy_pitchsensitivity; @@ -764,12 +673,9 @@ extern cvar_t *lazarus_joyp; extern cvar_t *lazarus_joyy; extern cvar_t *lazarus_pitch; extern cvar_t *lazarus_yaw; -extern cvar_t *lights; -extern cvar_t *lightsmin; extern cvar_t *m_pitch; extern cvar_t *m_yaw; extern cvar_t *monsterjump; -extern cvar_t *packet_fmod_playback; extern cvar_t *player_vampire; extern cvar_t *readout; extern cvar_t *rocket_strafe; @@ -777,8 +683,6 @@ extern cvar_t *rotate_distance; extern cvar_t *s_primary; extern cvar_t *shift_distance; extern cvar_t *sv_maxgibs; -extern cvar_t *tpp; // third person perspective -extern cvar_t *tpp_auto; extern cvar_t *turn_rider; extern cvar_t *zoomrate; extern cvar_t *zoomsnap; @@ -867,23 +771,6 @@ int range (edict_t *self, edict_t *other); bool visible (edict_t *self, edict_t *other); bool ai_chicken (edict_t *ent, edict_t *badguy); // -// g_camera.c -// -void use_camera(edict_t *ent, edict_t *other, edict_t *activator); -void camera_on(edict_t *ent); -void camera_off(edict_t *ent); -void faker_animate(edict_t *self); -edict_t *G_FindNextCamera (edict_t *camera, edict_t *monitor); -edict_t *G_FindPrevCamera (edict_t *camera, edict_t *monitor); - -// -// g_chase.c -// -void UpdateChaseCam(edict_t *ent); -void ChaseNext(edict_t *ent); -void ChasePrev(edict_t *ent); -void GetChaseTarget(edict_t *ent); -// // g_combat.c // bool OnSameTeam (edict_t *ent1, edict_t *ent2); @@ -891,11 +778,6 @@ bool CanDamage (edict_t *targ, edict_t *inflictor); void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod); void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod, double dmg_slope); void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); -//ROGUE -//void T_RadiusNukeDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod); -//void T_RadiusClassDamage (edict_t *inflictor, edict_t *attacker, float damage, char *ignoreClass, float radius, int mod); -void cleanupHealTarget (edict_t *ent); -//ROGUE // damage flags #define DAMAGE_RADIUS 0x00000001 // damage was indirect @@ -918,43 +800,7 @@ void cleanupHealTarget (edict_t *ent); void Cmd_Help_f (edict_t *ent); void Cmd_Score_f (edict_t *ent); void Use_Flashlight(edict_t *ent,gitem_t *item); -void SetSensitivities(edict_t *ent,bool reset); -void ShiftItem(edict_t *ent, int direction); -// -// g_crane.c -// -void G_FindCraneParts(); -void crane_control_action(edict_t *crane, edict_t *activator, vec3_t point); -void Moving_Speaker_Think(edict_t *ent); -// -// g_fog.c -// -#define MAX_FOGS 16 -extern fog_t gfogs[MAX_FOGS]; -void Cmd_Fog_f(edict_t *ent); -void Fog_Init(); -void Fog(vec3_t viewpoint); -void Fog_Off(); -void Fog_SetFogParms(); -// -// g_func.c -// -#define TRAIN_START_ON 1 -#define TRAIN_TOGGLE 2 -#define TRAIN_BLOCK_STOPS 4 -#define TRAIN_ROTATE 8 -#define TRAIN_ROTATE_CONSTANT 16 -#define TRAIN_ROTATE_MASK (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT) -#define TRAIN_ANIMATE 32 -#define TRAIN_ANIMATE_FAST 64 -#define TRAIN_SMOOTH 128 -#define TRAIN_SPLINE 4096 - -bool box_walkmove (edict_t *ent, float yaw, float dist); -void button_use (edict_t *self, edict_t *other, edict_t *activator); -void trainbutton_use (edict_t *self, edict_t *other, edict_t *activator); -void movewith_init (edict_t *self); -void set_child_movement(edict_t *self); +void ClientCommand (edict_t *ent); // // g_items.c // @@ -974,26 +820,6 @@ int PowerArmorType (edict_t *ent); gitem_t *GetItemByIndex (int index); bool Add_Ammo (edict_t *ent, gitem_t *item, int count); void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf); - -#ifdef JETPACK_MOD -void Use_Jet (edict_t *ent, gitem_t *item); - -// -// g_jetpack.c -// -void Jet_ApplyJet( edict_t *ent, usercmd_t *ucmd ); -bool Jet_AvoidGround( edict_t *ent ); -void Jet_BecomeExplosion( edict_t *ent, int damage ); -#endif -// -// g_lights.c -// -void Lights(); -void ToggleLights(); -// -// g_lock.c -// -void lock_digit_increment (edict_t *digit, edict_t *activator); // // g_main.c // @@ -1048,6 +874,7 @@ void M_FlyCheck (edict_t *self); void M_FliesOff (edict_t *self); void M_FliesOn (edict_t *self); void M_CheckGround (edict_t *ent); +bool M_walkmove (edict_t *ent, float yaw, float dist); bool M_SetDeath (edict_t *ent,mmove_t **moves); int PatchMonsterModel (char *model); // @@ -1060,31 +887,6 @@ int PatchPlayerModels (char *modelname); void SV_AddGravity (edict_t *ent); void G_RunEntity (edict_t *ent); // -// g_reflect.c -// -void AddReflection (edict_t *ent); -void DeleteReflection (edict_t *ent, int index); -void ReflectExplosion (int type, vec3_t origin); -void ReflectSparks (int type, vec3_t origin, vec3_t movedir); -void ReflectSteam (vec3_t origin,vec3_t movedir,int count,int sounds,int speed, int wait, int nextid); -void ReflectTrail (int type, vec3_t start, vec3_t end); -// -// g_sound.c (interface to FMOD) -// -bool FMOD_IsPlaying(edict_t *ent); -void FMOD_Shutdown(); -void FMOD_Stop(); -void FMOD_StopSound(edict_t *ent, bool free); -int FMOD_PlaySound(edict_t *ent); -void FMOD_UpdateListenerPos(); -void FMOD_UpdateSpeakerPos(edict_t *speaker); -bool FMOD_Init(); -void FootStep(edict_t *ent); -void PlayFootstep(edict_t *ent, footstep_t index); -extern bool qFMOD_Footsteps; -void target_playback_delayed_restart (edict_t *ent); -void target_playback_delayed_start (edict_t *ent); -// // g_spawn.c // void ED_CallSpawn (edict_t *ent); @@ -1102,15 +904,6 @@ bool SV_FilterPacket (char *from); // edict_t *SpawnThing(); // -// g_tracktrain.c -// -void tracktrain_disengage (edict_t *train); -// -// g_turret.c -// -void turret_breach_fire(edict_t *ent); -void turret_disengage (edict_t *ent); -// // g_trigger.c // typedef struct @@ -1148,80 +941,6 @@ float AtLeast(float x, float dx); edict_t *LookingAt(edict_t *ent, int filter, vec3_t endpos, float *range); void GameDirRelativePath(char *filename, char *output); void G_UseTarget (edict_t *ent, edict_t *activator, edict_t *target); -//ROGUE -void G_ProjectSource2 (vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t up, vec3_t result); -float vectoyaw2 (vec3_t vec); -void vectoangles2 (vec3_t vec, vec3_t angles); -edict_t *findradius2 (edict_t *from, vec3_t org, float rad); -//ROGUE - -// -// g_weapon.c -// -void ThrowDebris (edict_t *self, char *modelname, float speed, vec3_t origin, int skin, int effects); -bool fire_hit (edict_t *self, vec3_t aim, int damage, int kick); -void fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod); -void fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod); -void fire_blaster (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int effect, bool hyper); -void fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius); -void fire_grenade2 (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, bool held); -void fire_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage, edict_t *home_target); -void fire_rail (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick); -void fire_bfg (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius); -bool AimGrenade (edict_t *launcher, vec3_t start, vec3_t target, vec_t speed, vec3_t aim); -void Grenade_Evade (edict_t *monster); -// -// m_actor.c -// -void actor_attack (edict_t *actor); -void actor_files (); -void actor_fire (edict_t *actor); -void actor_jump (edict_t *actor); -void actor_moveit (edict_t *player, edict_t *actor); -void actor_run (edict_t *actor); -void actor_run_back (edict_t *actor); -void actor_salute (edict_t *actor); -void actor_stand (edict_t *actor); -void actor_walk (edict_t *actor); -void actor_walk_back (edict_t *actor); -mmove_t actor_move_crouch; -mmove_t actor_move_crouchwalk; -mmove_t actor_move_crouchwalk_back; -mmove_t actor_move_run; -mmove_t actor_move_run_back; -mmove_t actor_move_run_bad; -mmove_t actor_move_stand; -mmove_t actor_move_walk; -mmove_t actor_move_walk_back; -// -// m_medic.c -// -#define MEDIC_MIN_DISTANCE 32 -#define MEDIC_MAX_HEAL_DISTANCE 400 -#define MEDIC_TRY_TIME 10.0 - -void abortHeal (edict_t *ent,bool mark); -void medic_NextPatrolPoint(edict_t *ent,edict_t *hintpath); -edict_t *medic_FindDeadMonster (edict_t *ent); -void medic_StopPatrolling(edict_t *ent); -// -// m_move.c -// -bool M_CheckBottom (edict_t *ent); -bool M_walkmove (edict_t *ent, float yaw, float dist); -void M_MoveToGoal (edict_t *ent, float dist); -void M_ChangeYaw (edict_t *ent); -// tpp -// -// p_chase.c -// -#define OPTION_OFF 0 -#define OPTION_BACKGROUND 1 -void CheckChasecam_Viewent (edict_t *ent); -void Cmd_Chasecam_Toggle (edict_t *ent); -void ChasecamRemove (edict_t *ent, int opt); -void ChasecamStart (edict_t *ent); -// end tpp // // p_client.c // @@ -1240,23 +959,9 @@ void ClientBeginServerFrame (edict_t *ent); void MoveClientToIntermission (edict_t *client); void G_SetStats (edict_t *ent); void G_SetSpectatorStats (edict_t *ent); -void G_CheckChaseStats (edict_t *ent); void ValidateSelectedItem (edict_t *ent); void DeathmatchScoreboardMessage (edict_t *client, edict_t *killer); // -// p_text.c -// -void Do_Text_Display(edict_t *activator, int flags, char *message); -// -// p_trail.c -// -void PlayerTrail_Init (void); -void PlayerTrail_Add (vec3_t spot); -void PlayerTrail_New (vec3_t spot); -edict_t *PlayerTrail_PickFirst (edict_t *self); -edict_t *PlayerTrail_PickNext (edict_t *self); -edict_t *PlayerTrail_LastSpot (void); -// // p_view.c // void ClientEndServerFrame (edict_t *ent); @@ -1267,36 +972,6 @@ void PlayerNoise(edict_t *who, vec3_t where, int type); void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result); void kick_attack (edict_t *ent); -// ROGUE -// -// g_newai.c -// -#define MAX_HINT_CHAINS 100 -extern int hint_paths_present; -extern edict_t *hint_path_start[MAX_HINT_CHAINS]; -extern int num_hint_paths; - -bool blocked_checkshot (edict_t *self, float shotChance); -bool blocked_checkplat (edict_t *self, float dist); -bool blocked_checkjump (edict_t *self, float dist, float maxDown, float maxUp); -bool blocked_checknewenemy (edict_t *self); -bool monsterlost_checkhint (edict_t *self); -bool inback (edict_t *self, edict_t *other); -float realrange (edict_t *self, edict_t *other); -edict_t *SpawnBadArea(vec3_t mins, vec3_t maxs, float lifespan, edict_t *owner); -edict_t *CheckForBadArea(edict_t *ent); -void InitHintPaths (void); -void PredictAim (edict_t *target, vec3_t start, float bolt_speed, bool eye_height, float offset, vec3_t aimdir, vec3_t aimpoint); -bool below (edict_t *self, edict_t *other); -void drawbbox (edict_t *self); -bool has_valid_enemy (edict_t *self); -void hintpath_stop (edict_t *self); -edict_t * PickCoopTarget (edict_t *self); -int CountPlayers (void); -void monster_jump_start (edict_t *self); -bool monster_jump_finished (edict_t *self); -// END ROGUE - //============================================================================ // client_t->anim_priority @@ -1349,9 +1024,6 @@ typedef struct int helpchanged; bool spectator; // client is a spectator - // tpp - int chasetoggle; - // end tpp bool spawn_landmark; bool spawn_levelchange; vec3_t spawn_offset; @@ -1374,9 +1046,6 @@ typedef struct vec3_t cmd_angles; // angles sent over in the last command bool spectator; // client is a spectator - // tpp - int chasetoggle; - // end tpp } client_respawn_t; // this structure is cleared on each PutClientInServer(), @@ -1463,20 +1132,8 @@ struct gclient_s float respawn_time; // can respawn when time > this - edict_t *chase_target; // player we are chasing - bool update_chase; // need to update chase info? - usercmd_t ucmd; // Lazarus: Copied for convenience in ClientThink - // tpp - int chasetoggle; - edict_t *chasecam; - edict_t *oldplayer; - int use; // indicates whether +use key is pressed - int zoom; - int delayedstart; - // end tpp - // TREMOR func_pushable stuff float maxvelocity; // Used when pushing func_pushable edict_t *push; @@ -1489,7 +1146,6 @@ struct gclient_s bool inmenu; // in menu int menutimer; pmenuhnd_t *menu; // current menu - texthnd_t *textdisplay; // currently displayed text char *whatsit; // security camera @@ -1530,17 +1186,6 @@ struct gclient_s int jumping; // 0 or 1, used for jumpkick edict_t *homing_rocket; // used to limit firing frequency -#ifdef JETPACK_MOD - bool jetpack; - float jetpack_framenum; - float jetpack_nextthink; - bool jetpack_thrusting; - bool jetpack_infinite; - float jetpack_start_thrust; - float jetpack_last_thrust; - float jetpack_activation; - float jetpack_roll; -#endif }; #define NUM_ACTOR_SOUNDS 13 @@ -1722,11 +1367,6 @@ struct edict_s // various Lazarus additions follow: - edict_t *turret; // player-controlled turret - edict_t *child; // "real" infantry guy, child of remote turret_driver - vec_t base_radius; // Lazarus: used to project "viewpoint" of TRACK turret - // out past base - //ed - for the sprite/model spawner char *usermodel; int startframe; @@ -1740,12 +1380,6 @@ struct edict_s vec3_t bleft; vec3_t tright; - // tpp - int chasedist1; - int chasedist2; - edict_t *crosshair; - // end tpp - // item identification char *datafile; @@ -1786,31 +1420,9 @@ struct edict_s float radius; vec3_t org_size; // Initial size of the vehicle bounding box, - vec3_t fog_color; - int fog_model; - float fog_near; - float fog_far; - float fog_density; - int fog_index; - int fogclip; // only used by worldspawn to indicate whether gl_clear - // should be forced to a good value for fog obscuration - // of HOM - - edict_t *movewith_next; - char *movewith; - edict_t *movewith_ent; - vec3_t movewith_offset; - vec3_t parent_attach_angles; - bool do_not_rotate; - // monster AI char *dmgteam; - // turret - char *destroytarget; - char *viewmessage; - char *followtarget; - // spycam edict_t *viewer; @@ -1867,10 +1479,6 @@ struct edict_s edict_t *next_grenade; // Used to build a list of active grenades edict_t *prev_grenade; - // FMOD - int *stream; // Actually a FSOUND_STREAM * or FMUSIC_MODULE * - int channel; - // gib type - specifies folder where gib models are found. int gib_type; int blood_type; @@ -1879,29 +1487,6 @@ struct edict_s // actor muzzle flash edict_t *flash; - - // Psychospaz reflections - edict_t *reflection[6]; - -//========= -//ROGUE - int plat2flags; -// vec3_t offset; used by Lazarus - vec3_t gravityVector; - edict_t *bad_area; - edict_t *hint_chain; - edict_t *monster_hint_chain; - edict_t *target_hint_chain; - int hint_chain_id; - // FIXME - debug help! - float lastMoveTime; -//ROGUE -//========= - -#ifdef WESQ2 - int my_spawn; -#endif - }; #define LOOKAT_NOBRUSHMODELS 1 @@ -1917,38 +1502,4 @@ struct edict_s #define FLASHLIGHT_MOD #define FLASHLIGHT_USE POWERUP_NEW_ENT #define FLASHLIGHT_DRAIN 60 -#define FLASHLIGHT_ITEM "Cells" - -#ifdef WESQ2 -// tunnel code stuff -#define MAX_SPAWNED_ITEMS 100 -extern int NumSpawnedItems; -typedef struct { - char classname[64]; - vec3_t origin; - vec_t angle; -} SPAWNED_ITEM; -extern SPAWNED_ITEM SpawnedItem[MAX_SPAWNED_ITEMS]; - -typedef struct { - vec3_t loc; - float pressure; - float temperature; -} PRESSURE_TEMP; - -typedef struct { - vec3_t loc; - float weight; - float delay; -} EXPLOSIVE; - -extern int gNumTargets; -extern int gNumCharges; -extern float gTargetSpacing; -extern PRESSURE_TEMP *PT; -extern EXPLOSIVE *TNT; -extern vec3_t gWorld; - -#define DAMAGE_PER_POUND 5 - -#endif +#define FLASHLIGHT_ITEM "Cells" \ No newline at end of file diff --git a/server/global/g_main.c b/server/g_main.c similarity index 82% rename from server/global/g_main.c rename to server/g_main.c index 81a65557..bdc7576a 100644 --- a/server/global/g_main.c +++ b/server/g_main.c @@ -62,7 +62,6 @@ cvar_t *actorjump; cvar_t *actorscram; cvar_t *alert_sounds; cvar_t *allow_download; -cvar_t *allow_fog; // Set to 0 for no fog cvar_t *bounce_bounce; cvar_t *bounce_minv; cvar_t *cd_loopcount; @@ -71,12 +70,10 @@ cvar_t *corpse_fade; cvar_t *corpse_fadetime; cvar_t *crosshair; cvar_t *developer; -cvar_t *fmod_nomusic; cvar_t *footstep_sounds; cvar_t *fov; cvar_t *gl_clear; cvar_t *gl_driver; -cvar_t *gl_driver_fog; cvar_t *hand; cvar_t *jetpack_weenie; cvar_t *joy_pitchsensitivity; @@ -90,12 +87,9 @@ cvar_t *lazarus_joyp; cvar_t *lazarus_joyy; cvar_t *lazarus_pitch; cvar_t *lazarus_yaw; -cvar_t *lights; -cvar_t *lightsmin; cvar_t *m_pitch; cvar_t *m_yaw; cvar_t *monsterjump; -cvar_t *packet_fmod_playback; cvar_t *player_vampire; cvar_t *readout; cvar_t *rocket_strafe; @@ -113,7 +107,6 @@ bool ClientConnect (edict_t *ent, char *userinfo); void ClientUserinfoChanged (edict_t *ent, char *userinfo); void ClientDisconnect (edict_t *ent); void ClientBegin (edict_t *ent); -void ClientCommand (edict_t *ent); void RunEntity (edict_t *ent); void WriteLump (dsavehdr_t *hdr, file_t *f, int lumpnum, bool autosave); void ReadLump (byte *base, lump_t *l, int lumpnum); @@ -131,10 +124,6 @@ void ShutdownGame (void) gi.cvar_forceset("cd_loopcount", va("%d",lazarus_cd_loop->value)); gi.cvar_forceset("gl_clear", va("%d", lazarus_gl_clear->value)); } - // Lazarus: Turn off fog if it's on - if(!dedicated->value) Fog_Off(); - // and shut down FMOD - FMOD_Shutdown(); //free main memory pools Mem_FreePool(&zone_level); @@ -205,9 +194,6 @@ game_export_t DLLEXPORT *ServerAPI (game_import_t *import) globals.edict_size = sizeof(edict_t); gl_driver = gi.cvar ("gl_driver", "", 0); - gl_driver_fog = gi.cvar ("gl_driver_fog", "opengl32", CVAR_NOSET | CVAR_ARCHIVE); - - Fog_Init(); developer = gi.cvar("developer", "0", CVAR_SERVERINFO); readout = gi.cvar("readout", "0", CVAR_SERVERINFO); @@ -243,38 +229,6 @@ void ClientEndServerFrames (void) continue; ClientEndServerFrame (ent); } - - //reflection stuff -- modified from psychospaz' original code - if (level.num_reflectors) - { - ent = &g_edicts[0]; - for (i=0 ; iinuse) - continue; - if (!ent->s.modelindex) - continue; -// if (ent->s.effects & EF_ROTATE) -// continue; - if (ent->flags & FL_REFLECT) - continue; - if (!ent->client && (ent->svflags & SVF_NOCLIENT)) - continue; - if (ent->client && !ent->client->chasetoggle && (ent->svflags & SVF_NOCLIENT)) - continue; - if (ent->svflags&SVF_MONSTER && ent->solid!=SOLID_BBOX) - continue; - if ( (ent->solid == SOLID_BSP) && (ent->movetype != MOVETYPE_PUSHABLE)) - continue; - if (ent->client && ent->client->resp.spectator) - continue; - if (ent->client && player_vampire->value) - continue; - if (ent->s.renderfx & RF_VAMPIRE) - continue; - AddReflection(ent); - } - } } /* @@ -479,11 +433,7 @@ void G_RunFrame (void) level.time = level.framenum*FRAMETIME; - // choose a client for monsters to target this frame - AI_SetSightClient (); - // exit intermissions - if (level.exitintermission) { ExitLevel (); @@ -523,10 +473,6 @@ void G_RunFrame (void) G_RunEntity (ent); } - // FMOD stuff: - if ( (level.num_3D_sounds > 0) && (game.maxclients == 1)) - FMOD_UpdateListenerPos(); - // see if it is time to end a deathmatch CheckDMRules (); diff --git a/server/ents/g_misc.c b/server/g_misc.c similarity index 84% rename from server/ents/g_misc.c rename to server/g_misc.c index 10dbac28..bb502ce3 100644 --- a/server/ents/g_misc.c +++ b/server/g_misc.c @@ -17,13 +17,12 @@ int lastgibframe=0; void FadeThink(edict_t *ent) { ent->count++; - if (ent->count==2) + if (ent->count == 2) { G_FreeEdict(ent); return; } - ent->s.effects |= EF_SPHERETRANS; - ent->nextthink=level.time+0.5; + ent->nextthink=level.time + 0.5; gi.linkentity(ent); } void FadeDieThink (edict_t *ent) @@ -280,8 +279,6 @@ void ThrowHead (edict_t *self, char *gibname, int damage, int type) VectorClear (self->mins); VectorClear (self->maxs); - DeleteReflection(self,-1); - strcpy(modelname,gibname); p = strstr(modelname,"models/objects/gibs/"); if(p && self->gib_type) @@ -335,19 +332,6 @@ void ThrowHead (edict_t *self, char *gibname, int damage, int type) self->think = FadeDieThink; self->nextthink = level.time + 8 + random()*10; - // Lazarus: If head owner was part of a movewith chain, - // remove from the chain and repair the chain - // if necessary - if(self->movewith) { - edict_t *e; - edict_t *parent=NULL; - int i; - for(i=1; imovewith_next == self) parent=e; - } - if(parent) parent->movewith_next = self->movewith_next; - } gi.linkentity (self); } @@ -497,9 +481,6 @@ void BecomeExplosion1 (edict_t *self) WRITE_COORD (self->s.origin); MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - if (level.num_reflectors) - ReflectExplosion (TE_EXPLOSION1, self->s.origin); - G_FreeEdict (self); } @@ -511,9 +492,6 @@ void BecomeExplosion2 (edict_t *self) WRITE_COORD (self->s.origin); MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - if (level.num_reflectors) - ReflectExplosion (TE_EXPLOSION2, self->s.origin); - G_FreeEdict (self); } @@ -621,7 +599,6 @@ Makes this the target of a monster and it will head here when first activated before going after the activator. If hold is selected, it will stay here. */ -void tracktrain_drive(edict_t *train, edict_t *other); void point_combat_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { edict_t *activator; @@ -664,30 +641,20 @@ void point_combat_touch (edict_t *self, edict_t *other, cplane_t *plane, csurfac if (self->pathtarget) { - if (self->spawnflags & 2) - { - edict_t *train; - train = G_PickTarget(self->pathtarget); - if(train) - tracktrain_drive(train,other); - } - else - { - char *savetarget; + char *savetarget; - savetarget = self->target; - self->target = self->pathtarget; - if (other->enemy && other->enemy->client) - activator = other->enemy; - else if (other->oldenemy && other->oldenemy->client) - activator = other->oldenemy; - else if (other->activator && other->activator->client) - activator = other->activator; - else - activator = other; - G_UseTargets (self, activator); - self->target = savetarget; - } + savetarget = self->target; + self->target = self->pathtarget; + if (other->enemy && other->enemy->client) + activator = other->enemy; + else if (other->oldenemy && other->oldenemy->client) + activator = other->oldenemy; + else if (other->activator && other->activator->client) + activator = other->activator; + else + activator = other; + G_UseTargets (self, activator); + self->target = savetarget; } } @@ -1048,7 +1015,7 @@ void func_explosive_explode (edict_t *self) switch(self->gib_type) { case GIB_METAL: ThrowDebris (self, "models/gibs/metal.mdl", 2, chunkorigin, r, 0); break; - case GIB_GLASS: ThrowDebris (self, "models/gibs/glass.mdl", 2, chunkorigin, r, EF_SPHERETRANS); break; + case GIB_GLASS: ThrowDebris (self, "models/gibs/glass.mdl", 2, chunkorigin, r, 0); break; case GIB_BARREL: ThrowDebris (self, "models/gibs/barrelgib.mdl", 2, chunkorigin, r, 0); break; case GIB_CRATE: ThrowDebris (self, "models/gibs/wood.mdl", 2, chunkorigin, r, 0); break; case GIB_ROCK: ThrowDebris (self, "models/gibs/rock.mdl", 2, chunkorigin, r, 0); break; @@ -1676,7 +1643,6 @@ void misc_deadsoldier_flieson(edict_t *self) self->s.sound = gi.soundindex ("infantry/inflies1.wav"); } -int PatchDeadSoldier (); void SP_misc_deadsoldier (edict_t *ent) { if (deathmatch->value) @@ -1718,120 +1684,10 @@ void SP_misc_deadsoldier (edict_t *ent) ent->die = misc_deadsoldier_die; ent->monsterinfo.aiflags |= AI_GOOD_GUY; - if(ent->style) - { - PatchDeadSoldier(); - ent->s.skin = ent->style; - } ent->common_name = "Dead Marine"; gi.linkentity (ent); } -/*QUAKED misc_viper (1 .5 0) (-16 -16 0) (16 16 32) -This is the Viper for the flyby bombing. -It is trigger_spawned, so you must have something use it for it to show up. -There must be a path for it to follow once it is activated. - -"speed" How fast the Viper should fly -*/ - -extern void train_use (edict_t *self, edict_t *other, edict_t *activator); -extern void func_train_find (edict_t *self); - -void viper_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point ) -{ - edict_t *e, *next; - - if(self->deathtarget) - { - self->target = self->deathtarget; - G_UseTargets (self, attacker); - } - - e = self->movewith_next; - while(e) { - next = e->movewith_next; - if(e->solid == SOLID_NOT) { - e->nextthink = 0; - G_FreeEdict(e); - } else - BecomeExplosion1 (e); - e = next; - } - - self->enemy = inflictor; - self->activator = attacker; - func_explosive_explode (self); -} - -void misc_viper_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->svflags &= ~SVF_NOCLIENT; - self->use = train_use; - train_use (self, other, activator); -} - -void SP_misc_viper (edict_t *ent) -{ - if (!ent->target) - { - gi.dprintf ("misc_viper without a target at %s\n", vtos(ent->absmin)); - G_FreeEdict (ent); - return; - } - - ent->class_id = ENTITY_MISC_VIPER; - if (!ent->speed) - ent->speed = 300; - - ent->movetype = MOVETYPE_PUSH; - ent->s.modelindex = gi.modelindex ("models/ships/viper/tris.md2"); - - // Lazarus - allow ship to be destroyed if positive health value - if(ent->health > 0) - { - ent->solid = SOLID_BBOX; - VectorSet (ent->mins, -32, -24, -12); - VectorSet (ent->maxs, 32, 24, 16); - ent->takedamage = DAMAGE_YES; - ent->die = viper_die; - if(!ent->dmg) - ent->dmg = 200; - if(!ent->mass) - ent->mass = 800; - } - else - { - ent->solid = SOLID_NOT; - VectorSet (ent->mins, -16, -16, 0); - VectorSet (ent->maxs, 16, 16, 32); - } - - // Lazarus - TRAIN_SMOOTH forces trains to go directly to Move_Done from - // Move_Final rather than slowing down (if necessary) for one - // frame. - if (ent->spawnflags & TRAIN_SMOOTH) - ent->smooth_movement = true; - else - ent->smooth_movement = false; - - ent->think = func_train_find; - ent->nextthink = level.time + FRAMETIME; - - if(ent->spawnflags & TRAIN_START_ON) - ent->use = train_use; - else - { - ent->use = misc_viper_use; - ent->svflags |= SVF_NOCLIENT; - } - ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed; - - ent->common_name = "Viper"; - gi.linkentity (ent); -} - - /*QUAKED misc_bigviper (1 .5 0) (-176 -120 -24) (176 120 72) This is a large stationary viper as seen in Paul's intro */ @@ -1870,9 +1726,6 @@ void misc_viper_bomb_touch (edict_t *self, edict_t *other, cplane_t *plane, csur WRITE_COORD (self->s.origin); MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - if (level.num_reflectors) - ReflectExplosion (TE_EXPLOSION2, self->s.origin); - self->svflags |= SVF_NOCLIENT; self->solid = SOLID_NOT; self->use = misc_viper_bomb_use; @@ -1994,85 +1847,6 @@ void SP_misc_viper_bomb (edict_t *self) gi.linkentity (self); } - -/*QUAKED misc_strogg_ship (1 .5 0) (-16 -16 0) (16 16 32) -This is a Storgg ship for the flybys. -It is trigger_spawned, so you must have something use it for it to show up. -There must be a path for it to follow once it is activated. - -"speed" How fast it should fly -*/ - -extern void train_use (edict_t *self, edict_t *other, edict_t *activator); -extern void func_train_find (edict_t *self); - -void misc_strogg_ship_use (edict_t *self, edict_t *other, edict_t *activator) -{ - self->svflags &= ~SVF_NOCLIENT; - self->use = train_use; - train_use (self, other, activator); -} - -void SP_misc_strogg_ship (edict_t *ent) -{ - if (!ent->target) - { - gi.dprintf ("%s without a target at %s\n", ent->classname, vtos(ent->absmin)); - G_FreeEdict (ent); - return; - } - - ent->class_id = ENTITY_MISC_STROGG_SHIP; - if (!ent->speed) - ent->speed = 300; - - ent->movetype = MOVETYPE_PUSH; - ent->s.modelindex = gi.modelindex ("models/ships/strogg1/tris.md2"); - // Lazarus - allow ship to be destroyed if positive health value - if(ent->health > 0) - { - ent->solid = SOLID_BBOX; - VectorSet (ent->mins, -58, -60, -40); - VectorSet (ent->maxs, 72, 60, 38); - ent->takedamage = DAMAGE_YES; - ent->die = viper_die; - if(!ent->dmg) - ent->dmg = 200; - if(!ent->mass) - ent->mass = 1200; - } - else - { - ent->solid = SOLID_NOT; - VectorSet (ent->mins, -16, -16, 0); - VectorSet (ent->maxs, 16, 16, 32); - } - - // Lazarus - TRAIN_SMOOTH forces trains to go directly to Move_Done from - // Move_Final rather than slowing down (if necessary) for one - // frame. - if (ent->spawnflags & TRAIN_SMOOTH) - ent->smooth_movement = true; - else - ent->smooth_movement = false; - - ent->think = func_train_find; - ent->nextthink = level.time + FRAMETIME; - - if(ent->spawnflags & TRAIN_START_ON) - ent->use = train_use; - else - { - ent->use = misc_strogg_ship_use; - ent->svflags |= SVF_NOCLIENT; - } - ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed; - - ent->common_name = "Strogg Ship"; - gi.linkentity (ent); -} - - /*QUAKED misc_satellite_dish (1 .5 0) (-64 -64 0) (64 64 128) */ @@ -2452,9 +2226,35 @@ void SP_func_clock (edict_t *self) trigger_transition with same name as teleporter can be used to teleport multiple non-player entities ================================================================== */ +bool HasSpawnFunction(edict_t *ent) +{ + spawn_t *s; + gitem_t *item; + int i; + + if(!ent->classname) + return false; + + // check item spawn functions + for (i=0,item=itemlist ; iclassname) + continue; + if (!strcmp(item->classname, ent->classname)) + return true; + } + // check normal spawn functions + for (s=spawns ; s->name ; s++) + { + if (!strcmp(s->name, ent->classname)) + return true; + } + return false; +} + void teleport_transition_ents (edict_t *transition, edict_t *teleporter, edict_t *destination) { - extern entlist_t DoNotMove; + entlist_t DoNotMove; int i, j; int total=0; bool nogo=false; @@ -2480,7 +2280,6 @@ void teleport_transition_ents (edict_t *transition, edict_t *teleporter, edict_t // Pass up owned entities not owned by the player on this pass... // get 'em next pass so we'll know whether owner is in our list if(ent->owner && !ent->owner->client) continue; - if(ent->movewith) continue; if(ent->solid == SOLID_BSP) continue; if((ent->solid == SOLID_TRIGGER) && !FindItemByClassname(ent->classname)) continue; // Do not under any circumstances move these entities: @@ -2527,7 +2326,6 @@ void teleport_transition_ents (edict_t *transition, edict_t *teleporter, edict_t if(!ent->inuse) continue; if(!ent->owner) continue; if(ent->owner->client) continue; - if(ent->movewith) continue; if(ent->solid == SOLID_BSP) continue; if((ent->solid == SOLID_TRIGGER) && !FindItemByClassname(ent->classname)) continue; // Do not under any circumstances move these entities: @@ -2667,13 +2465,6 @@ void teleporter_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_ vec3_t origin; VectorMA(self->mins,0.5,self->size,origin); - if(!(self->spawnflags & 16)) - { - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_TELEPORT_EFFECT); - WRITE_COORD(origin); - MESSAGE_SEND(MSG_PHS, origin, NULL); - } gi.positioned_sound(origin,self,CHAN_AUTO,self->noise_index,1,1,0); } other->s.event = EV_PLAYER_TELEPORT; @@ -2802,8 +2593,6 @@ void SP_misc_teleporter (edict_t *ent) trig->solid = SOLID_TRIGGER; trig->target = ent->target; trig->owner = ent; - // Lazarus - trig->movewith = ent->movewith; VectorCopy (ent->s.origin, trig->s.origin); VectorSet (trig->mins, -8, -8, 8); VectorSet (trig->maxs, 8, 8, 24); @@ -2898,10 +2687,7 @@ void SP_misc_light (edict_t *self) { self->class_id = ENTITY_MISC_LIGHT; self->use = misc_light_use; - if(self->movewith) - self->movetype = MOVETYPE_PUSH; - else - self->movetype = MOVETYPE_NONE; + self->movetype = MOVETYPE_NONE; self->think = misc_light_think; if (!(self->spawnflags & START_OFF)) self->nextthink = level.time + 2*FRAMETIME; @@ -2927,20 +2713,13 @@ TARGET_PRECIPITATION void drop_add_to_chain(edict_t *drop) { edict_t *owner = drop->owner; - edict_t *parent; if(!owner || !owner->inuse || !(owner->spawnflags & SF_WEATHER_STARTON)) { G_FreeEdict(drop); return; } - parent = owner; - while(parent->child) - parent = parent->child; - parent->child = drop; - drop->child = NULL; drop->svflags |= SVF_NOCLIENT; - drop->s.effects &= ~EF_SPHERETRANS; drop->s.renderfx &= ~RF_TRANSLUCENT; VectorClear(drop->velocity); VectorClear(drop->avelocity); @@ -2965,7 +2744,6 @@ void leaf_fade2(edict_t *ent) ent->count++; if (ent->count == 1) { - ent->s.effects |= EF_SPHERETRANS; ent->nextthink=level.time+0.5; gi.linkentity(ent); } @@ -3006,40 +2784,29 @@ void spawn_precipitation(edict_t *self, vec3_t org, vec3_t dir, float speed) { edict_t *drop; - if(self->child) + drop = G_Spawn(); + if(self->style == STYLE_WEATHER_BIGRAIN) + drop->s.modelindex = gi.modelindex ("models/objects/drop/heavy.md2"); + else if(self->style == STYLE_WEATHER_SNOW) + drop->s.modelindex = gi.modelindex ("models/objects/snow/tris.md2"); + else if(self->style == STYLE_WEATHER_LEAF) { - // Then we already have a currently unused, invisible drop available - drop = self->child; - self->child = drop->child; - drop->child = NULL; - drop->svflags &= ~SVF_NOCLIENT; - drop->groundentity = NULL; - } - else - { - drop = G_Spawn(); - if(self->style == STYLE_WEATHER_BIGRAIN) - drop->s.modelindex = gi.modelindex ("models/objects/drop/heavy.md2"); - else if(self->style == STYLE_WEATHER_SNOW) - drop->s.modelindex = gi.modelindex ("models/objects/snow/tris.md2"); - else if(self->style == STYLE_WEATHER_LEAF) - { - float r=random(); - if(r < 0.33) - drop->s.modelindex = gi.modelindex ("models/objects/leaf1/tris.md2"); - else if(r < 0.66) - drop->s.modelindex = gi.modelindex ("models/objects/leaf2/tris.md2"); - else - drop->s.modelindex = gi.modelindex ("models/objects/leaf3/tris.md2"); - VectorSet(drop->mins,-1,-1,-1); - VectorSet(drop->maxs, 1, 1, 1); - } - else if(self->style == STYLE_WEATHER_USER) - drop->s.modelindex = gi.modelindex(self->usermodel); + float r=random(); + if(r < 0.33) + drop->s.modelindex = gi.modelindex ("models/objects/leaf1/tris.md2"); + else if(r < 0.66) + drop->s.modelindex = gi.modelindex ("models/objects/leaf2/tris.md2"); else - drop->s.modelindex = gi.modelindex ("models/objects/drop/tris.md2"); - drop->classname = "rain drop"; + drop->s.modelindex = gi.modelindex ("models/objects/leaf3/tris.md2"); + VectorSet(drop->mins,-1,-1,-1); + VectorSet(drop->maxs, 1, 1, 1); } + else if(self->style == STYLE_WEATHER_USER) + drop->s.modelindex = gi.modelindex(self->usermodel); + else + drop->s.modelindex = gi.modelindex ("models/objects/drop/tris.md2"); + drop->classname = "rain drop"; + if(self->gravity > 0. || self->attenuation > 0 ) drop->movetype = MOVETYPE_DEBRIS; else @@ -3087,7 +2854,6 @@ void spawn_precipitation(edict_t *self, vec3_t org, vec3_t dir, float speed) } else { - drop->s.effects |= EF_SPHERETRANS; drop->avelocity[YAW] = self->yaw_speed; } if(self->spawnflags & SF_WEATHER_START_FADE) @@ -3169,18 +2935,6 @@ void target_precipitation_use (edict_t *ent, edict_t *other, edict_t *activator) // already on; turn it off ent->nextthink = 0; ent->spawnflags &= ~SF_WEATHER_STARTON; - if(ent->child) - { - edict_t *child, *parent; - child = ent->child; - ent->child = NULL; - while(child) - { - parent = child; - child = parent->child; - G_FreeEdict(parent); - } - } } else { @@ -3377,18 +3131,6 @@ void target_fountain_use (edict_t *ent, edict_t *other, edict_t *activator) // already on; turn it off ent->nextthink = 0; ent->spawnflags &= ~SF_WEATHER_STARTON; - if(ent->child) - { - edict_t *child, *parent; - child = ent->child; - ent->child = NULL; - while(child) - { - parent = child; - child = parent->child; - G_FreeEdict(parent); - } - } } else { @@ -3477,110 +3219,6 @@ void SP_target_fountain (edict_t *ent) gi.linkentity (ent); } -// -/*============================================================================= - -MISC_DEADSOLDIER MODEL PATCH - -==============================================================================*/ - -#define NUM_SKINS 16 -#define MAX_SKINNAME 64 -#define DEADSOLDIER_MODEL "models/deadbods/dude/tris.md2" - -#include -#include "pak.h" - -int PatchDeadSoldier () -{ - cvar_t *gamedir; - char skins[NUM_SKINS][MAX_SKINNAME]; // skin entries - char outfilename[MAX_OSPATH]; - int j; - file_t *infile; - file_t *outfile; - dmdl_t model; // model header - byte *data; // model data - int datasize; // model data size (bytes) - int newoffset; // model data offset (after skins) - - // get game (moddir) name - gamedir = gi.cvar("game", "", 0); - if (!*gamedir->string) return 0; // we're in baseq2 - - if (gi.Fs.FileExists(DEADSOLDIER_MODEL)) - return 0; - - for (j = 0; j < NUM_SKINS; j++) - memset (skins[j], 0, MAX_SKINNAME); - - sprintf (skins[0], "models/deadbods/dude/dead1.pcx"); - sprintf (skins[1], "players/male/cipher.pcx"); - sprintf (skins[2], "players/male/claymore.pcx"); - sprintf (skins[3], "players/male/flak.pcx"); - sprintf (skins[4], "players/male/grunt.pcx"); - sprintf (skins[5], "players/male/howitzer.pcx"); - sprintf (skins[6], "players/male/major.pcx"); - sprintf (skins[7], "players/male/nightops.pcx"); - sprintf (skins[8], "players/male/pointman.pcx"); - sprintf (skins[9], "players/male/psycho.pcx"); - sprintf (skins[10], "players/male/rampage.pcx"); - sprintf (skins[11], "players/male/razor.pcx"); - sprintf (skins[12], "players/male/recon.pcx"); - sprintf (skins[13], "players/male/scout.pcx"); - sprintf (skins[14], "players/male/sniper.pcx"); - sprintf (skins[15], "players/male/viper.pcx"); - - - // load original model - if ( !(infile = gi.Fs.Open (DEADSOLDIER_MODEL, "rb")) ) - { - gi.dprintf("PatchDeadSoldier: Could not find %s\n",DEADSOLDIER_MODEL); - return 0; - } - else - { - gi.Fs.Read (infile, &model, sizeof (dmdl_t)); - - datasize = model.ofs_end - model.ofs_skins; - if ( !(data = malloc (datasize)) ) // make sure freed locally - { - gi.dprintf ("PatchMonsterModel: Could not allocate memory for model\n"); - return 0; - } - gi.Fs.Read (infile, data, sizeof (byte) * datasize); - gi.Fs.Close (infile); - } - - // update model info - model.num_skins = NUM_SKINS; - - // Already had 1 skin, so new offset doesn't include that one - newoffset = (model.num_skins-1) * MAX_SKINNAME; - model.ofs_st += newoffset; - model.ofs_tris += newoffset; - model.ofs_frames += newoffset; - model.ofs_glcmds += newoffset; - model.ofs_end += newoffset; - - if (!(outfile = gi.Fs.Open (DEADSOLDIER_MODEL, "wb")) ) - { - // file couldn't be created for some other reason - gi.dprintf ("PatchDeadSoldier: Could not save %s\n", outfilename); - free (data); - return 0; - } - - gi.Fs.Write (outfile, &model, sizeof (dmdl_t)); - gi.Fs.Write (outfile, skins, sizeof (char)*(model.num_skins*MAX_SKINNAME)); - data += MAX_SKINNAME; - gi.Fs.Write (outfile, data, sizeof (byte)*datasize); - - gi.Fs.Close (outfile); - gi.dprintf ("PatchDeadSoldier: Saved %s\n", outfilename); - free (data); - return 1; -} void PrecacheDebris(int type) { diff --git a/server/global/g_phys.c b/server/g_phys.c similarity index 78% rename from server/global/g_phys.c rename to server/g_phys.c index 0acaaf28..e457f37b 100644 --- a/server/global/g_phys.c +++ b/server/g_phys.c @@ -23,6 +23,534 @@ solid_edge items only clip against bsp models. */ +#define STEPSIZE 18 + +/* +============= +M_CheckBottom + +Returns false if any part of the bottom of the entity is off an edge that +is not a staircase. + +============= +*/ +int c_yes, c_no; + +bool M_CheckBottom (edict_t *ent) +{ + vec3_t mins, maxs, start, stop; + trace_t trace; + int x, y; + float mid, bottom; + + VectorAdd (ent->s.origin, ent->mins, mins); + VectorAdd (ent->s.origin, ent->maxs, maxs); + +// if all of the points under the corners are solid world, don't bother +// with the tougher checks +// the corners must be within 16 of the midpoint + start[2] = mins[2] - 1; + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = x ? maxs[0] : mins[0]; + start[1] = y ? maxs[1] : mins[1]; + if (gi.pointcontents (start) != CONTENTS_SOLID) + goto realcheck; + } + + c_yes++; + return true; // we got out easy + +realcheck: + c_no++; +// +// check it for real... +// + start[2] = mins[2]; + +// the midpoint must be within 16 of the bottom + start[0] = stop[0] = (mins[0] + maxs[0])*0.5; + start[1] = stop[1] = (mins[1] + maxs[1])*0.5; + stop[2] = start[2] - 2*STEPSIZE; + trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); + + if (trace.fraction == 1.0) + return false; + mid = bottom = trace.endpos[2]; + +// the corners must be within 16 of the midpoint + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = stop[0] = x ? maxs[0] : mins[0]; + start[1] = stop[1] = y ? maxs[1] : mins[1]; + + trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); + + if (trace.fraction != 1.0 && trace.endpos[2] > bottom) + bottom = trace.endpos[2]; + if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) + return false; + } + + c_yes++; + return true; +} + +/* +============= +SV_movestep + +Called by monster program code. +The move will be adjusted for slopes and stairs, but if the move isn't +possible, no move is done, false is returned, and +pr_global_struct->trace_normal is set to the normal of the blocking wall +============= +*/ +//FIXME since we need to test end position contents here, can we avoid doing +//it again later in catagorize position? +bool SV_movestep (edict_t *ent, vec3_t move, bool relink) +{ + float dz; + vec3_t oldorg, neworg, end; + trace_t trace; + int i; + float stepsize; + float jumpheight; + vec3_t test; + int contents; + + bool canjump; + float d1, d2; + int jump; // 1=jump up, -1=jump down + vec3_t forward, up; + vec3_t dir; + vec_t dist; + edict_t *target; + + // try the move + VectorCopy (ent->s.origin, oldorg); + VectorAdd (ent->s.origin, move, neworg); + + AngleVectors(ent->s.angles,forward,NULL,up); + if(ent->enemy) + target = ent->enemy; + else if(ent->movetarget) + target = ent->movetarget; + else + target = NULL; + + // flying monsters don't step up + if ( ent->flags & (FL_SWIM | FL_FLY) ) + { + // try one move with vertical motion, then one without + for (i=0 ; i<2 ; i++) + { + VectorAdd (ent->s.origin, move, neworg); + if (i == 0 && ent->enemy) + { + if (!ent->goalentity) + ent->goalentity = ent->enemy; + dz = ent->s.origin[2] - ent->goalentity->s.origin[2]; + if (ent->goalentity->client) + { + if (dz > 40) + neworg[2] -= 8; + if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2))) + if (dz < 30) + neworg[2] += 8; + } + else + { + if (dz > 8) + neworg[2] -= 8; + else if (dz > 0) + neworg[2] -= dz; + else if (dz < -8) + neworg[2] += 8; + else + neworg[2] += dz; + } + } + trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID); + + // fly monsters don't enter water voluntarily + if (ent->flags & FL_FLY) + { + if (!ent->waterlevel) + { + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + if (contents & MASK_WATER) + return false; + } + } + + // swim monsters don't exit water voluntarily + if (ent->flags & FL_SWIM) + { + if (ent->waterlevel < 2) + { + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + if (!(contents & MASK_WATER)) + return false; + } + } + + if (trace.fraction == 1) + { + VectorCopy (trace.endpos, ent->s.origin); + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + return true; + } + + if (!ent->enemy) + break; + } + + return false; + } + + // push down from a step height above the wished position + if (!(ent->monsterinfo.aiflags & AI_NOSTEP)) + stepsize = STEPSIZE; + else + stepsize = 1; + + neworg[2] += stepsize; + VectorCopy (neworg, end); + end[2] -= stepsize*2; + + trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); + + // Determine whether monster is capable of and/or should jump + jump = 0; + if((ent->monsterinfo.jump) && !(ent->monsterinfo.aiflags & AI_DUCKED)) + { + // Don't jump if path is blocked by monster or player. Otherwise, + // monster might attempt to jump OVER the monster/player, which + // ends up looking a bit goofy. Also don't jump if the monster's + // movement isn't deliberate (target=NULL) + if(trace.ent && (trace.ent->client || (trace.ent->svflags & SVF_MONSTER))) + canjump = false; + else if(target) + { + // Never jump unless it places monster closer to his goal + vec3_t dir; + VectorSubtract(target->s.origin, oldorg, dir); + d1 = VectorLength(dir); + VectorSubtract(target->s.origin, trace.endpos, dir); + d2 = VectorLength(dir); + if(d2 < d1) + canjump = true; + else + canjump = false; + } + else + canjump = false; + } + else + canjump = false; + + if (trace.allsolid) + { + if(canjump && (ent->monsterinfo.jumpup > 0)) + { + neworg[2] += ent->monsterinfo.jumpup - stepsize; + trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); + if (!trace.allsolid && !trace.startsolid && trace.fraction > 0 && (trace.plane.normal[2] > 0.9)) + { + if(!trace.ent || (!trace.ent->client && !(trace.ent->svflags & SVF_MONSTER) && !(trace.ent->svflags & SVF_DEADMONSTER))) + { + // Good plane to jump on. Make sure monster is more or less facing + // the obstacle to avoid cutting-corners jumps + trace_t tr; + vec3_t p2; + + VectorMA(ent->s.origin,1024,forward,p2); + tr = gi.trace(ent->s.origin,ent->mins,ent->maxs,p2,ent,MASK_MONSTERSOLID); + if(DotProduct(tr.plane.normal,forward) < -0.95) + { + jump = 1; + jumpheight = trace.endpos[2] - ent->s.origin[2]; + } + else + return false; + } + } + else + return false; + } + else + return false; + } + + if (trace.startsolid) + { + neworg[2] -= stepsize; + trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); + if (trace.allsolid || trace.startsolid) + return false; + } + + + // don't go in to water + // Lazarus: misc_actors don't go swimming, but wading is fine + if (ent->monsterinfo.aiflags & AI_ACTOR) + { + // First check for lava/slime under feet - but only if we're not already in + // a liquid + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + if (ent->waterlevel == 0) + { + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + if (contents & (CONTENTS_LAVA | CONTENTS_SLIME)) + return false; + } + test[2] = trace.endpos[2] + ent->viewheight - 1; + contents = gi.pointcontents(test); + if (contents & MASK_WATER) + return false; + } + else if (ent->waterlevel == 0) + { + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + + if (contents & MASK_WATER) + return false; + } + + // Lazarus: Don't intentionally walk into lasers. + dist = VectorLength(move); + if(dist > 0.) + { + edict_t *e; + trace_t laser_trace; + vec_t delta; + vec3_t laser_mins, laser_maxs; + vec3_t laser_start, laser_end; + vec3_t monster_mins, monster_maxs; + + for(i=game.maxclients+1; iinuse) + continue; + if(!e->classname) + continue; + if(e->class_id != ENTITY_TARGET_LASER) + continue; + if(e->svflags & SVF_NOCLIENT) + continue; + if( (e->style == 2) || (e->style == 3)) + continue; + if(!gi.inPVS(ent->s.origin,e->s.origin)) + continue; + // Check to see if monster is ALREADY in the path of this laser. + // If so, allow the move so he can get out. + VectorMA(e->s.origin,2048,e->movedir,laser_end); + laser_trace = gi.trace(e->s.origin,NULL,NULL,laser_end,NULL,CONTENTS_SOLID|CONTENTS_MONSTER); + if(laser_trace.ent == ent) + continue; + VectorCopy(laser_trace.endpos,laser_end); + laser_mins[0] = min(e->s.origin[0],laser_end[0]); + laser_mins[1] = min(e->s.origin[1],laser_end[1]); + laser_mins[2] = min(e->s.origin[2],laser_end[2]); + laser_maxs[0] = max(e->s.origin[0],laser_end[0]); + laser_maxs[1] = max(e->s.origin[1],laser_end[1]); + laser_maxs[2] = max(e->s.origin[2],laser_end[2]); + monster_mins[0] = min(oldorg[0],trace.endpos[0]) + ent->mins[0]; + monster_mins[1] = min(oldorg[1],trace.endpos[1]) + ent->mins[1]; + monster_mins[2] = min(oldorg[2],trace.endpos[2]) + ent->mins[2]; + monster_maxs[0] = max(oldorg[0],trace.endpos[0]) + ent->maxs[0]; + monster_maxs[1] = max(oldorg[1],trace.endpos[1]) + ent->maxs[1]; + monster_maxs[2] = max(oldorg[2],trace.endpos[2]) + ent->maxs[2]; + if( monster_maxs[0] < laser_mins[0] ) continue; + if( monster_maxs[1] < laser_mins[1] ) continue; + if( monster_maxs[2] < laser_mins[2] ) continue; + if( monster_mins[0] > laser_maxs[0] ) continue; + if( monster_mins[1] > laser_maxs[1] ) continue; + if( monster_mins[2] > laser_maxs[2] ) continue; + // If we arrive here, some part of the bounding box surrounding + // monster's total movement intersects laser bounding box. + // If laser is parallel to x, y, or z, we definitely + // know this move will put monster in path of laser + if ( (e->movedir[0] == 1.) || (e->movedir[1] == 1.) || (e->movedir[2] == 1.)) + return false; + // Shift psuedo laser towards monster's current position up to + // the total distance he's proposing moving. + delta = min(16,dist); + VectorCopy(move,dir); + VectorNormalize(dir); + while(delta < dist+15.875) + { + if(delta > dist) delta = dist; + VectorMA(e->s.origin, -delta,dir,laser_start); + VectorMA(e->s.old_origin,-delta,dir,laser_end); + laser_trace = gi.trace(laser_start,NULL,NULL,laser_end,world,CONTENTS_SOLID|CONTENTS_MONSTER); + if(laser_trace.ent == ent) + return false; + delta += 16; + } + } + } + if ((trace.fraction == 1) && !jump && canjump && (ent->monsterinfo.jumpdn > 0)) + { + end[2] = oldorg[2] + move[2] - ent->monsterinfo.jumpdn; + trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID | MASK_WATER); + if(trace.fraction < 1 && (trace.plane.normal[2] > 0.9) && (trace.contents & MASK_SOLID) && (neworg[2] - 16 > trace.endpos[2])) + { + if(!trace.ent || (!trace.ent->client && !(trace.ent->svflags & SVF_MONSTER) && !(trace.ent->svflags & SVF_DEADMONSTER))) + jump = -1; + } + } + + + if ((trace.fraction == 1) && !jump) + { + // if monster had the ground pulled out, go ahead and fall + if ( ent->flags & FL_PARTIALGROUND ) + { + VectorAdd (ent->s.origin, move, ent->s.origin); + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + ent->groundentity = NULL; + return true; + } + return false; // walked off an edge + } + + // check point traces down for dangling corners + VectorCopy (trace.endpos, ent->s.origin); + + if(!jump) + { + bool skip = false; + // if monster CAN jump down, and a position just a bit forward would be + // a good jump-down spot, allow (briefly) !M_CheckBottom + if (canjump && target && (target->s.origin[2] < ent->s.origin[2]) && (ent->monsterinfo.jumpdn > 0)) + { + vec3_t p1, p2; + trace_t tr; + + VectorMA(oldorg,48,forward,p1); + tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, p1, ent, MASK_MONSTERSOLID); + if(tr.fraction == 1) + { + p2[0] = p1[0]; + p2[1] = p1[1]; + p2[2] = p1[2] - ent->monsterinfo.jumpdn; + tr = gi.trace(p1,ent->mins,ent->maxs,p2,ent,MASK_MONSTERSOLID | MASK_WATER); + if(tr.fraction < 1 && (tr.plane.normal[2] > 0.9) && (tr.contents & MASK_SOLID) && (p1[2] - 16 > tr.endpos[2])) + { + if(!tr.ent || (!tr.ent->client && !(tr.ent->svflags & SVF_MONSTER) && !(tr.ent->svflags & SVF_DEADMONSTER))) + { + VectorSubtract(target->s.origin, tr.endpos, dir); + d2 = VectorLength(dir); + if(d2 < d1) + skip = true; + } + } + } + + } + if (!skip) + { + if (!M_CheckBottom (ent)) + { + if ( ent->flags & FL_PARTIALGROUND ) + { // entity had floor mostly pulled out from underneath it + // and is trying to correct + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + return true; + } + VectorCopy (oldorg, ent->s.origin); + return false; + } + } + } + + if ( ent->flags & FL_PARTIALGROUND ) + { + ent->flags &= ~FL_PARTIALGROUND; + } + ent->groundentity = trace.ent; + if(trace.ent) + ent->groundentity_linkcount = trace.ent->linkcount; + +// the move is ok + if(jump) + { + VectorScale(move, 10, ent->velocity); + if(jump > 0) + { + ent->monsterinfo.jump(ent); + ent->velocity[2] = 2.5*jumpheight + 80; + } + else + { + ent->velocity[2] = max(ent->velocity[2],100); + if(oldorg[2] - ent->s.origin[2] > 48) + ent->s.origin[2] = oldorg[2] + ent->velocity[2]*FRAMETIME; + } + if(relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + } + else if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + return true; +} + + +/* +=============== +M_walkmove +=============== +*/ +bool M_walkmove (edict_t *ent, float yaw, float dist) +{ + vec3_t move; + + if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) + return false; + + yaw = yaw*M_PI*2 / 360; + + move[0] = cos(yaw)*dist; + move[1] = sin(yaw)*dist; + move[2] = 0; + + return SV_movestep(ent, move, true); +} + // //================= // other_FallingDamage @@ -1120,15 +1648,6 @@ bool SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) if (check->groundentity != pusher) check->groundentity = NULL; - // Lazarus - don't block movewith trains with a rider - they may end up - // being stuck, but that beats a small pitch or roll causing - // blocked trains/gibbed monsters - if (check->movewith_ent == pusher) - { - gi.linkentity (check); - continue; - } - block = SV_TestEntityPosition (check); if (block && (pusher->flags & FL_TRACKTRAIN) && (check->client || (check->svflags & SVF_MONSTER)) && (check->groundentity == pusher) ) @@ -1873,7 +2392,8 @@ void SV_Physics_Step (edict_t *ent) if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) { vel = ent->velocity; speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); - if (speed) { + if (speed) + { friction = sv_friction; control = speed < sv_stopspeed ? sv_stopspeed : speed; @@ -2038,14 +2558,7 @@ int SV_VehicleMove (edict_t *ent, float time, int mask) for (i=0 ; i<3 ; i++) end[i] = origin[i] + time_left * ent->velocity[i]; -retry: trace = gi.trace (start, mins, maxs, end, ignore, mask); - if(trace.ent && (trace.ent->movewith_ent == ent) ) - { - ignore = trace.ent; - VectorCopy(trace.endpos,start); - goto retry; - } if (trace.allsolid) { @@ -2533,6 +3046,57 @@ void SV_Physics_Conveyor(edict_t *ent) } } +void M_CheckGround (edict_t *ent) +{ + vec3_t point; + trace_t trace; + + if (level.time < ent->gravity_debounce_time) + return; + + if (ent->flags & (FL_SWIM|FL_FLY)) + return; + + if (ent->velocity[2] > 100) + { + ent->groundentity = NULL; + return; + } + +// if the hull point one-quarter unit down is solid the entity is on ground + point[0] = ent->s.origin[0]; + point[1] = ent->s.origin[1]; + point[2] = ent->s.origin[2] - 0.25; + + trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, point, ent, MASK_MONSTERSOLID); + + // check steepness + if ( trace.plane.normal[2] < 0.7 && !trace.startsolid) + { + ent->groundentity = NULL; + return; + } + + // Lazarus: The following 2 lines were in the original code and commented out + // by id. However, the effect of this is that a player walking over + // a dead monster who is laying on a brush model will cause the + // dead monster to drop through the brush model. This change *may* + // have other consequences, though, so watch out for this. + + ent->groundentity = trace.ent; + ent->groundentity_linkcount = trace.ent->linkcount; +// if (!trace.startsolid && !trace.allsolid) +// VectorCopy (trace.endpos, ent->s.origin); + if (!trace.startsolid && !trace.allsolid) + { + VectorCopy (trace.endpos, ent->s.origin); + ent->groundentity = trace.ent; + ent->groundentity_linkcount = trace.ent->linkcount; +// ent->velocity[2] = 0; Lazarus: what if the groundentity is moving? + ent->velocity[2] = trace.ent->velocity[2]; + } +} + /* ================ G_RunEntity diff --git a/server/global/g_save.c b/server/g_save.c similarity index 85% rename from server/global/g_save.c rename to server/g_save.c index 57633ec8..dbe42e40 100644 --- a/server/global/g_save.c +++ b/server/g_save.c @@ -101,18 +101,14 @@ field_t fields[] = {"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP}, {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}, - // Lazarus additions - {"actor_current_weapon", FOFS(actor_current_weapon), F_INT}, {"aiflags", FOFS(monsterinfo.aiflags), F_INT}, {"alpha", FOFS(alpha), F_FLOAT}, {"axis", FOFS(axis), F_INT}, - {"base_radius", FOFS(base_radius), F_FLOAT}, {"bleft", FOFS(bleft), F_VECTOR}, {"blood_type", FOFS(blood_type), F_INT}, {"bob", FOFS(bob), F_FLOAT}, {"bobframe", FOFS(bobframe), F_INT}, {"busy", FOFS(busy), F_INT}, - {"child", FOFS(child), F_EDICT}, {"class_id", FOFS(class_id), F_INT}, {"color", FOFS(color), F_VECTOR}, {"crane_beam", FOFS(crane_beam), F_EDICT, FFL_NOSPAWN}, @@ -129,21 +125,12 @@ field_t fields[] = {"datafile", FOFS(datafile), F_LSTRING}, {"deadflag", FOFS(deadflag), F_INT}, {"density", FOFS(density), F_FLOAT}, - {"destroytarget", FOFS(destroytarget), F_LSTRING}, {"dmgteam", FOFS(dmgteam), F_LSTRING}, - {"do_not_rotate", FOFS(do_not_rotate), F_INT}, {"duration", FOFS(duration), F_FLOAT}, {"effects", FOFS(effects), F_INT}, {"fadein", FOFS(fadein), F_FLOAT}, {"fadeout", FOFS(fadeout), F_FLOAT}, {"flies", FOFS(monsterinfo.flies), F_FLOAT}, - {"fog_color", FOFS(fog_color), F_VECTOR}, - {"fog_density", FOFS(fog_density), F_FLOAT}, - {"fog_far", FOFS(fog_far), F_FLOAT}, - {"fog_model", FOFS(fog_model), F_INT}, - {"fog_near", FOFS(fog_near), F_FLOAT}, - {"fogclip", FOFS(fogclip), F_INT}, - {"followtarget", FOFS(followtarget), F_LSTRING}, {"frame", FOFS(s.frame), F_INT}, {"framenumbers", FOFS(framenumbers), F_INT}, {"gib_health", FOFS(gib_health), F_INT}, @@ -158,10 +145,6 @@ field_t fields[] = {"max_health", FOFS(max_health), F_INT}, {"max_range", FOFS(monsterinfo.max_range), F_FLOAT}, {"moreflags", FOFS(moreflags), F_INT}, - {"movewith", FOFS(movewith), F_LSTRING}, - {"movewith_ent", FOFS(movewith_ent), F_EDICT}, - {"movewith_next", FOFS(movewith_next), F_EDICT}, - {"movewith_offset", FOFS(movewith_offset), F_VECTOR}, {"move_to", FOFS(move_to), F_LSTRING}, {"muzzle", FOFS(muzzle), F_VECTOR}, {"muzzle2", FOFS(muzzle2), F_VECTOR}, @@ -173,7 +156,6 @@ field_t fields[] = {"org_mins", FOFS(org_mins), F_VECTOR}, {"org_size", FOFS(org_size), F_VECTOR}, {"owner_id", FOFS(owner_id), F_INT}, - {"parent_attach_angles", FOFS(parent_attach_angles), F_VECTOR}, {"pitch_speed", FOFS(pitch_speed), F_FLOAT}, {"powerarmor", FOFS(powerarmor), F_INT}, {"prev_grenade", FOFS(prev_grenade), F_EDICT, FFL_NOSPAWN}, @@ -192,30 +174,12 @@ field_t fields[] = {"target2", FOFS(target2), F_LSTRING}, {"tright", FOFS(tright), F_VECTOR}, {"turn_rider", FOFS(turn_rider), F_INT}, - {"turret", FOFS(turret), F_EDICT}, {"usermodel", FOFS(usermodel), F_LSTRING}, {"vehicle", FOFS(vehicle), F_EDICT, FFL_NOSPAWN}, {"viewer", FOFS(viewer), F_EDICT}, {"viewheight", FOFS(viewheight), F_INT}, - {"viewmessage", FOFS(viewmessage), F_LSTRING}, {"yaw_speed", FOFS(yaw_speed), F_FLOAT}, - // ROGUE - {"bad_area", FOFS(bad_area), F_EDICT}, - // while the hint_path stuff could be reassembled on the fly, no reason to be different - {"hint_chain", FOFS(hint_chain), F_EDICT}, - {"monster_hint_chain", FOFS(monster_hint_chain), F_EDICT}, - {"target_hint_chain", FOFS(target_hint_chain), F_EDICT}, - // - {"goal_hint", FOFS(monsterinfo.goal_hint), F_EDICT}, - {"badMedic1", FOFS(monsterinfo.badMedic1), F_EDICT}, - {"badMedic2", FOFS(monsterinfo.badMedic2), F_EDICT}, - {"last_player_enemy", FOFS(monsterinfo.last_player_enemy), F_EDICT}, - {"commander", FOFS(monsterinfo.commander), F_EDICT}, - {"blocked", FOFS(monsterinfo.blocked), F_MMOVE, FFL_NOSPAWN}, - {"duck", FOFS(monsterinfo.duck), F_MMOVE, FFL_NOSPAWN}, - {"unduck", FOFS(monsterinfo.unduck), F_MMOVE, FFL_NOSPAWN}, - {"sidestep", FOFS(monsterinfo.sidestep), F_MMOVE, FFL_NOSPAWN}, {0, 0, 0, 0} }; @@ -229,10 +193,6 @@ field_t levelfields[] = {"sound_entity", LLOFS(sound_entity), F_EDICT}, {"sound2_entity", LLOFS(sound2_entity), F_EDICT}, - // ROGUE - {"disguise_violator", LLOFS(disguise_violator), F_EDICT}, - // ROGUE - {NULL, 0, F_INT} }; @@ -241,8 +201,6 @@ field_t clientfields[] = {"pers.weapon", CLOFS(pers.weapon), F_ITEM}, {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM}, {"newweapon", CLOFS(newweapon), F_ITEM}, - {"chasecam", CLOFS(chasecam), F_EDICT}, - {"oldplayer", CLOFS(oldplayer), F_EDICT}, {NULL, 0, F_INT} }; @@ -256,7 +214,6 @@ only happens when a new game is started or a save game is loaded. ============ */ -void ReadTextureSurfaceAssignments(); void InitGame (void) { gi.dprintf ("====== Init %s ======\n\n", GameTitle ); @@ -316,31 +273,21 @@ void InitGame (void) // dm map list sv_maplist = gi.cvar ("sv_maplist", "", 0); - // Lazarus - actorchicken = gi.cvar("actorchicken", "1", CVAR_SERVERINFO|CVAR_LATCH); - actorjump = gi.cvar("actorjump", "1", CVAR_SERVERINFO|CVAR_LATCH); - actorscram = gi.cvar("actorscram", "1", CVAR_SERVERINFO|CVAR_LATCH); alert_sounds = gi.cvar("alert_sounds", "0", CVAR_SERVERINFO|CVAR_LATCH); - allow_fog = gi.cvar ("allow_fog", "1", CVAR_ARCHIVE); cd_loopcount = gi.cvar("cd_loopcount","4",0); cl_gun = gi.cvar("cl_gun", "1", 0); corpse_fade = gi.cvar("corpse_fade", "0", CVAR_SERVERINFO|CVAR_LATCH); corpse_fadetime = gi.cvar("corpse_fadetime", "20", 0); crosshair = gi.cvar("crosshair", "1", 0); - fmod_nomusic = gi.cvar("fmod_nomusic", "0", CVAR_ARCHIVE); - footstep_sounds = gi.cvar("footstep_sounds", "0", CVAR_SERVERINFO|CVAR_LATCH); fov = gi.cvar("fov", "90", 0); hand = gi.cvar("hand", "0", 0); jetpack_weenie = gi.cvar("jetpack_weenie", "0", CVAR_SERVERINFO); joy_pitchsensitivity = gi.cvar("joy_pitchsensitivity", "1", 0); joy_yawsensitivity = gi.cvar("joy_yawsensitivity", "-1", 0); jump_kick = gi.cvar("jump_kick", "0", CVAR_SERVERINFO|CVAR_LATCH); - lights = gi.cvar("lights", "1", 0); - lightsmin = gi.cvar("lightsmin", "a", CVAR_SERVERINFO); m_pitch = gi.cvar("m_pitch", "0.022", 0); m_yaw = gi.cvar("m_yaw", "0.022", 0); monsterjump = gi.cvar("monsterjump", "1", CVAR_SERVERINFO|CVAR_LATCH); - packet_fmod_playback = gi.cvar("packet_fmod_playback", "0", CVAR_SERVERINFO); player_vampire = gi.cvar("player_vampire", "0", CVAR_SERVERINFO|CVAR_LATCH); rocket_strafe = gi.cvar("rocket_strafe", "0", 0); s_primary = gi.cvar("s_primary", "0", 0); @@ -394,9 +341,6 @@ void InitGame (void) } } - tpp = gi.cvar ("tpp", "0", CVAR_ARCHIVE); - tpp_auto = gi.cvar ("tpp_auto", "1", 0); - crossh = gi.cvar ("crossh", "1", 0); allow_download = gi.cvar("allow_download", "0", 0); // If this is an SP game and "readout" is not set, force allow_download off @@ -425,9 +369,6 @@ void InitGame (void) game.maxclients = maxclients->value; game.clients = TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); globals.num_edicts = game.maxclients+1; - - if(footstep_sounds->value) - ReadTextureSurfaceAssignments(); } //========================================================= @@ -839,32 +780,8 @@ void WriteLevel (vfile_t *f) { ent = &g_edicts[i]; if (!ent->inuse) continue; - if (ent->class_id == ENTITY_TARGET_PLAYBACK) - { - edict_t e; - memcpy(&e, ent, sizeof(edict_t)); - if(FMOD_IsPlaying(ent)) - { - e.think = target_playback_delayed_restart; - e.nextthink = level.time + 1.0; - // A misuse of groundentity_linkcount, but - // maybe nobody is watching. - e.groundentity_linkcount = g_edicts[1].linkcount; - } - else - { - e.think = NULL; - e.nextthink = 0; - } - e.stream = NULL; - gi.VFs.Write (f, &i, sizeof(i)); - WriteEdict (f, &e); - } - else - { - gi.VFs.Write (f, &i, sizeof(i)); - WriteEdict (f, ent); - } + gi.VFs.Write (f, &i, sizeof(i)); + WriteEdict (f, ent); } i = -1; gi.VFs.Write (f, &i, sizeof(i)); @@ -887,7 +804,6 @@ calling ReadLevel. No clients are connected yet. ================= */ -void LoadTransitionEnts(); void ReadLevel (vfile_t *f) { int entnum; @@ -959,13 +875,6 @@ void ReadLevel (vfile_t *f) if (ent->class_id == ENTITY_TARGET_CROSSLEVEL_TARGET) ent->nextthink = level.time + ent->delay; } - - // DWH: Load transition entities - if(game.transition_ents) - { - LoadTransitionEnts(); - actor_files(); - } } void WriteLump (dsavehdr_t *hdr, file_t *f, int lumpnum, bool autosave) diff --git a/server/g_spawn.c b/server/g_spawn.c new file mode 100644 index 00000000..756d41f3 --- /dev/null +++ b/server/g_spawn.c @@ -0,0 +1,753 @@ +#include "g_local.h" + +void SP_info_player_start (edict_t *ent); +void SP_info_player_deathmatch (edict_t *ent); +void SP_info_player_coop (edict_t *ent); +void SP_info_player_intermission (edict_t *ent); +void SP_worldspawn (edict_t *ent); +void SP_misc_explobox (edict_t *self); + +spawn_t spawns[] = +{ + {"info_player_start", SP_info_player_start}, + {"info_player_deathmatch", SP_info_player_deathmatch}, + {"info_player_coop", SP_info_player_coop}, + {"info_player_intermission", SP_info_player_intermission}, + + + {"misc_explobox", SP_misc_explobox}, + {"worldspawn", SP_worldspawn}, + {NULL, NULL} +}; + +/* +=============== +ED_CallSpawn + +Finds the spawn function for the entity and calls it +=============== +*/ +void ED_CallSpawn (edict_t *ent) +{ + spawn_t *s; + gitem_t *item; + int i; + + // Lazarus: if this fails, edict is freed. + + if (!ent->classname) + { + gi.dprintf ("ED_CallSpawn: NULL classname\n"); + G_FreeEdict(ent); + return; + } + + // check item spawn functions + for (i=0,item=itemlist ; iclassname) + continue; + if (!strcmp(item->classname, ent->classname)) + { // found it + SpawnItem (ent, item); + return; + } + } + + // check normal spawn functions + for (s=spawns ; s->name ; s++) + { + if (!strcmp(s->name, ent->classname)) + { // found it + s->spawn (ent); + return; + } + } + gi.dprintf ("%s doesn't have a spawn function\n", ent->classname); + G_FreeEdict(ent); +} + +/* +============= +ED_NewString +============= +*/ +char *ED_NewString (char *string) +{ + char *newb, *new_p; + int i,l; + + l = strlen(string) + 1; + + newb = TagMalloc (l, TAG_LEVEL); + + new_p = newb; + + for (i=0 ; i< l ; i++) + { + if (string[i] == '\\' && i < l-1) + { + i++; + if (string[i] == 'n') + *new_p++ = '\n'; + else + *new_p++ = '\\'; + } + else + *new_p++ = string[i]; + } + + return newb; +} + + + + +/* +=============== +ED_ParseField + +Takes a key/value pair and sets the binary values +in an edict +=============== +*/ +void ED_ParseField (char *key, char *value, edict_t *ent) +{ + field_t *f; + byte *b; + float v; + vec3_t vec; + + for (f=fields ; f->name ; f++) + { + if (!(f->flags & FFL_NOSPAWN) && !strcasecmp(f->name, key)) + { // found it + if (f->flags & FFL_SPAWNTEMP) + b = (byte *)&st; + else + b = (byte *)ent; + + switch (f->type) + { + case F_LSTRING: + *(char **)(b+f->ofs) = ED_NewString (value); + break; + case F_VECTOR: + sscanf (value, "%f %f %f", &vec[0], &vec[1], &vec[2]); + ((float *)(b+f->ofs))[0] = vec[0]; + ((float *)(b+f->ofs))[1] = vec[1]; + ((float *)(b+f->ofs))[2] = vec[2]; + break; + case F_INT: + *(int *)(b+f->ofs) = atoi(value); + break; + case F_FLOAT: + *(float *)(b+f->ofs) = atof(value); + break; + case F_ANGLEHACK: + v = atof(value); + ((float *)(b+f->ofs))[0] = 0; + ((float *)(b+f->ofs))[1] = v; + ((float *)(b+f->ofs))[2] = 0; + break; + case F_IGNORE: + break; + } + return; + } + } + gi.dprintf ("%s is not a field\n", key); +} + +/* +==================== +ED_ParseEdict + +Parses an edict out of the given string, returning the new position +ed should be a properly initialized empty edict. +==================== +*/ +char *ED_ParseEdict (char *data, edict_t *ent) +{ + bool init; + char keyname[256]; + char *com_token; + + init = false; + memset (&st, 0, sizeof(st)); + + // go through all the dictionary pairs + while (1) + { + // parse key + com_token = COM_Parse (&data); + if (com_token[0] == '}') break; + if (!data) gi.error ("ED_ParseEntity: EOF without closing brace"); + + strncpy (keyname, com_token, sizeof(keyname)-1); + + // parse value + com_token = COM_Parse (&data); + if (!data) gi.error ("ED_ParseEntity: EOF without closing brace"); + + if (com_token[0] == '}') + gi.error ("ED_ParseEntity: closing brace without data"); + + init = true; + + // keynames with a leading underscore are used for utility comments, + // and are immediately discarded by quake + if (keyname[0] == '_') continue; + + ED_ParseField (keyname, com_token, ent); + } + + if (!init) memset (ent, 0, sizeof(*ent)); + + return data; +} + + +/* +================ +G_FindTeams + +Chain together all entities with a matching team field. + +All but the first will have the FL_TEAMSLAVE flag set. +All but the last will have the teamchain field set to the next one +================ +*/ +void G_FindTeams (void) +{ + edict_t *e, *e2, *chain; + int i, j; + int c, c2; + + c = 0; + c2 = 0; + for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++) + { + if (!e->inuse) + continue; + if (!e->team) + continue; + if (e->flags & FL_TEAMSLAVE) + continue; + // Lazarus: some entities may have psuedo-teams that shouldn't be handled here + if (e->class_id == ENTITY_TARGET_CHANGE) + continue; + if (e->class_id == ENTITY_TARGET_CLONE) + continue; + chain = e; + e->teammaster = e; + c++; + c2++; + for (j=i+1, e2=e+1 ; j < globals.num_edicts ; j++,e2++) + { + if (!e2->inuse) + continue; + if (!e2->team) + continue; + if (e2->flags & FL_TEAMSLAVE) + continue; + if (!strcmp(e->team, e2->team)) + { + c2++; + chain->teamchain = e2; + e2->teammaster = e; + chain = e2; + e2->flags |= FL_TEAMSLAVE; + } + } + } + + if(level.time < 2) + gi.dprintf ("%i teams with %i entities\n", c, c2); +} +/* +============== +SpawnEntities + +Creates a server's entity / program execution context by +parsing textual entity definitions out of an ent file. +============== +*/ +void SpawnEntities (char *mapname, char *entities, char *spawnpoint) +{ + edict_t *ent; + int inhibit; + char *com_token; + int i; + float skill_level; + extern int max_modelindex; + extern int max_soundindex; + + if(developer->value) + gi.dprintf("====== SpawnEntities ========\n"); + skill_level = floor (skill->value); + if (skill_level < 0) + skill_level = 0; + if (skill_level > 3) + skill_level = 3; + if (skill->value != skill_level) + gi.cvar_forceset("skill", va("%f", skill_level)); + + SaveClientData (); + + FreeTags (TAG_LEVEL); + + memset (&level, 0, sizeof(level)); + memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); + // Lazarus: these are used to track model and sound indices + // in g_main.c: + max_modelindex = 0; + max_soundindex = 0; + + strncpy (level.mapname, mapname, sizeof(level.mapname)-1); + strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1); + + // set client fields on player ents + for (i=0 ; iclassname, "trigger_once") && !strcasecmp(ent->model, "*27")) + ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; + + // remove things (except the world) from different skill levels or deathmatch + if (ent != g_edicts) + { + if (deathmatch->value) + { + if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) + { + G_FreeEdict (ent); + inhibit++; + continue; + } + } + else + { + if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || + ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || + (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) + ) + { + G_FreeEdict (ent); + inhibit++; + continue; + } + } + + ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_DEATHMATCH); + } + + ED_CallSpawn (ent); + ent->s.renderfx |= RF_IR_VISIBLE; //PGM + } + + gi.dprintf ("%i entities inhibited\n", inhibit); + + G_FindTeams (); + + // Get origin offsets (mainly for brush models w/o origin brushes) + for (i=1, ent=g_edicts+i ; i < globals.num_edicts ; i++,ent++) + { + VectorAdd(ent->absmin,ent->absmax,ent->origin_offset); + VectorScale(ent->origin_offset,0.5,ent->origin_offset); + VectorSubtract(ent->origin_offset,ent->s.origin,ent->origin_offset); + } +} + + +//=================================================================== + +#if 0 + // cursor positioning + xl + xr + yb + yt + xv + yv + + // drawing + statpic + pic + num + string + + // control + if + ifeq + ifbit + endif + +#endif + +char *single_statusbar = +"yb -24 " + +// health +"xv 0 " +"hnum " +"xv 50 " +"pic 0 " + +// ammo +"if 2 " +"{ xv 100 " +"anum " +"xv 150 " +"pic 2 " +"} " + +// armor +"if 4 " +"{ xv 200 " +"rnum " +"xv 250 " +"pic 4 " +"} " + +// selected item +"if 6 " +"{ xv 296 " +"pic 6 " +"} " + +"yb -50 " + +// picked up item +"if 7 " +"{ xv 0 " +"pic 7 " +"xv 26 " +"yb -42 " +"stat_string 8 " +"yb -50 " +"} " + +// timer (was xv 262) +"if 9 " +"{ xv 230 " +"num 4 10 " +"xv 296 " +"pic 9 " +"} " + +// help / weapon icon +"if 11 " +"{ xv 148 " +"pic 11 " +"} " + +// vehicle speed +"if 22 " +"{ yb -90 " +"xv 128 " +"pic 22 " +"} " + +// zoom +"if 23 " +"{ yv 0 " +"xv 0 " +"pic 23 " +"} " +; + + +char *dm_statusbar = +"yb -24 " + +// health +"xv 0 " +"hnum " +"xv 50 " +"pic 0 " + +// ammo +"if 2 " +"{ xv 100 " +"anum " +"xv 150 " +"pic 2 " +"} " + +// armor +"if 4 " +"{ xv 200 " +"rnum " +"xv 250 " +"pic 4 " +"} " + +// selected item +"if 6 " +"{ xv 296 " +"pic 6 " +"} " + +"yb -50 " + +// picked up item +"if 7 " +"{ xv 0 " +"pic 7 " +"xv 26 " +"yb -42 " +"stat_string 8 " +"yb -50 " +"} " + +// timer +"if 9 " +"{ xv 230 " +"num 4 10 " +"xv 296 " +"pic 9 " +"} " + +// help / weapon icon +"if 11 " +"{ xv 148 " +"pic 11 " +"} " + +// frags +"xr -50 " +"yt 2 " +"num 3 14 " + +// spectator +"if 17 " +"{ xv 0 " +"yb -58 " +"string2 \"SPECTATOR MODE\" " +"} " + +// chase camera +"if 16 " +"{ xv 0 " +"yb -68 " +"string \"Chasing\" " +"xv 64 " +"stat_string 16 " +"} " + +// vehicle speed +"if 22 " +"{ yb -90 " +"xv 128 " +"pic 22 " +"} " +; + +/*QUAKED worldspawn (0 0 0) ? + +Only used for the world. +"skyname" environment map name +"skyaxis" vector axis for rotating sky +"skyrotate" speed of rotation in degrees/second +"sounds" music cd track number +"gravity" 800 is default gravity +"message" text to print at user logon +*/ +//void SetChromakey(); +void SP_worldspawn (edict_t *ent) +{ + ent->class_id = ENTITY_WORLDSPAWN; + ent->movetype = MOVETYPE_PUSH; + ent->solid = SOLID_BSP; + ent->inuse = true; // since the world doesn't use G_Spawn() + ent->s.modelindex = 1; // world model is always index 1 + + //--------------- + + // reserve some spots for dead player bodies for coop / deathmatch + InitBodyQue (); + + // set configstrings for items + SetItemNames (); + + if (st.nextmap) + strcpy (level.nextmap, st.nextmap); + + // make some data visible to the server + + if (ent->message && ent->message[0]) + { + gi.configstring (CS_NAME, ent->message); + strncpy (level.level_name, ent->message, sizeof(level.level_name)); + } + else + strncpy (level.level_name, level.mapname, sizeof(level.level_name)); + + if (st.sky && st.sky[0]) + gi.configstring (CS_SKY, st.sky); + else + gi.configstring (CS_SKY, "sky"); + + gi.configstring (CS_SKYROTATE, va("%f", st.skyrotate) ); + + gi.configstring (CS_SKYAXIS, va("%f %f %f", + st.skyaxis[0], st.skyaxis[1], st.skyaxis[2]) ); + + gi.configstring (CS_CDTRACK, va("%i", ent->sounds) ); + + gi.configstring (CS_MAXCLIENTS, va("%i", (int)(maxclients->value) ) ); + + // status bar program + if (deathmatch->value) + gi.configstring (CS_STATUSBAR, dm_statusbar); + else + gi.configstring (CS_STATUSBAR, single_statusbar); + + //--------------- + + // help icon for statusbar + gi.imageindex ("i_help"); + level.pic_health = gi.imageindex ("i_health"); + gi.imageindex ("help"); + gi.imageindex ("field_3"); + + if (!st.gravity) + gi.cvar_set("sv_gravity", "800"); + else + gi.cvar_set("sv_gravity", st.gravity); + + snd_fry = gi.soundindex ("player/fry.wav"); // standing in lava / slime + + PrecacheItem (FindItem ("Blaster")); + + gi.soundindex ("player/lava1.wav"); + gi.soundindex ("player/lava2.wav"); + + gi.soundindex ("misc/pc_up.wav"); + gi.soundindex ("misc/talk1.wav"); + + gi.soundindex ("misc/udeath.wav"); + + // gibs + gi.soundindex ("items/respawn1.wav"); + + // sexed sounds + gi.soundindex ("*death1.wav"); + gi.soundindex ("*death2.wav"); + gi.soundindex ("*death3.wav"); + gi.soundindex ("*death4.wav"); + gi.soundindex ("*fall1.wav"); + gi.soundindex ("*fall2.wav"); + gi.soundindex ("*gurp1.wav"); // drowning damage + gi.soundindex ("*gurp2.wav"); + gi.soundindex ("*jump1.wav"); // player jump + gi.soundindex ("*pain25_1.wav"); + gi.soundindex ("*pain25_2.wav"); + gi.soundindex ("*pain50_1.wav"); + gi.soundindex ("*pain50_2.wav"); + gi.soundindex ("*pain75_1.wav"); + gi.soundindex ("*pain75_2.wav"); + gi.soundindex ("*pain100_1.wav"); + gi.soundindex ("*pain100_2.wav"); + + gi.modelindex ("#w_blaster.md2"); + + gi.soundindex ("player/gasp1.wav"); // gasping for air + gi.soundindex ("player/gasp2.wav"); // head breaking surface, not gasping + + gi.soundindex ("player/watr_in.wav"); // feet hitting water + gi.soundindex ("player/watr_out.wav"); // feet leaving water + + gi.soundindex ("player/watr_un.wav"); // head going underwater + + gi.soundindex ("player/u_breath1.wav"); + gi.soundindex ("player/u_breath2.wav"); + + gi.soundindex ("items/pkup.wav"); // bonus item pickup + gi.soundindex ("world/land.wav"); // landing thud + gi.soundindex ("misc/h2ohit1.wav"); // landing splash + + gi.soundindex ("items/damage.wav"); + gi.soundindex ("items/protect.wav"); + gi.soundindex ("items/protect4.wav"); + gi.soundindex ("weapons/noammo.wav"); + + gi.soundindex ("infantry/inflies1.wav"); + + sm_meat_index = gi.modelindex ("models/objects/gibs/sm_meat/tris.md2"); + gi.modelindex ("models/objects/gibs/arm/tris.md2"); + gi.modelindex ("models/objects/gibs/bone/tris.md2"); + gi.modelindex ("models/objects/gibs/bone2/tris.md2"); + gi.modelindex ("models/objects/gibs/chest/tris.md2"); + gi.modelindex ("models/objects/gibs/skull/tris.md2"); + gi.modelindex ("models/objects/gibs/head2/tris.md2"); + + gi.soundindex ("mud/mud_in2.wav"); + gi.soundindex ("mud/mud_out1.wav"); + gi.soundindex ("mud/mud_un1.wav"); + gi.soundindex ("mud/wade_mud1.wav"); + gi.soundindex ("mud/wade_mud2.wav"); + + // FMOD 3D sound attenuation: + if(ent->attenuation <= 0.) + ent->attenuation = 1.0; + + // FMOD 3D sound Doppler shift: + if(st.shift > 0) + ent->moveinfo.distance = st.shift; + else if(st.shift < 0) + ent->moveinfo.distance = 0.0; + else + ent->moveinfo.distance = 1.0; + + // cvar overrides for effects flags: + if(alert_sounds->value) + world->effects |= FX_WORLDSPAWN_ALERTSOUNDS; + if(corpse_fade->value) + world->effects |= FX_WORLDSPAWN_CORPSEFADE; + if(jump_kick->value) + world->effects |= FX_WORLDSPAWN_JUMPKICK; +} + +int nohud = 0; + +void Hud_On() +{ + if (deathmatch->value) gi.configstring (CS_STATUSBAR, dm_statusbar); + else gi.configstring (CS_STATUSBAR, single_statusbar); + nohud = 0; +} + +void Hud_Off() +{ + gi.configstring (CS_STATUSBAR, NULL); + nohud = 1; +} + +void Cmd_ToggleHud () +{ + if (deathmatch->value) return; + if (nohud) Hud_On(); + else Hud_Off(); +} diff --git a/server/global/g_svcmds.c b/server/g_svcmds.c similarity index 100% rename from server/global/g_svcmds.c rename to server/g_svcmds.c diff --git a/server/global/g_utils.c b/server/g_utils.c similarity index 61% rename from server/global/g_utils.c rename to server/g_utils.c index cd918a41..808ea897 100644 --- a/server/global/g_utils.c +++ b/server/g_utils.c @@ -109,7 +109,6 @@ findradius2 Returns entities that have origins within a spherical area -ROGUE - tweaks for performance for tesla specific code only returns entities that can be damaged only returns entities that are SVF_DAMAGEABLE @@ -134,8 +133,6 @@ edict_t *findradius2 (edict_t *from, vec3_t org, float rad) continue; if (!from->takedamage) continue; - if (!(from->svflags & SVF_DAMAGEABLE)) - continue; for (j=0 ; j<3 ; j++) eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j])*0.5); if (VectorLength(eorg) > rad) @@ -579,18 +576,6 @@ void G_FreeEdict (edict_t *ed) { // Lazarus - if part of a movewith chain, remove from // the chain and repair broken links - if(ed->movewith) { - edict_t *e; - edict_t *parent=NULL; - int i; - - for(i=1; imovewith_next == ed) parent=e; - } - if(parent) parent->movewith_next = ed->movewith_next; - } - gi.unlinkentity (ed); // unlink from world // Lazarus: In SP we no longer reserve slots for bodyque's @@ -616,10 +601,6 @@ void G_FreeEdict (edict_t *ed) ed->flash->inuse = false; } - // Lazarus: reflections - if (!(ed->flags & FL_REFLECT)) - DeleteReflection(ed,-1); - memset (ed, 0, sizeof(*ed)); ed->classname = "freed"; ed->freetime = level.time; @@ -657,8 +638,6 @@ void G_TouchTriggers (edict_t *ent) continue; if (!hit->touch) continue; - if (ent->client && ent->client->spycam && !(hit->svflags & SVF_TRIGGER_CAMOWNER)) - continue; hit->touch (hit, ent, NULL, NULL); } } @@ -799,13 +778,7 @@ edict_t *LookingAt(edict_t *ent, int filter, vec3_t endpos, float *range) return NULL; } VectorClear(end); - if(ent->client->chasetoggle) - { - AngleVectors(ent->client->v_angle, forward, NULL, NULL); - VectorCopy(ent->client->chasecam->s.origin,start); - ignore = ent->client->chasecam; - } - else if(ent->client->spycam) + if(ent->client->spycam) { AngleVectors(ent->client->ps.viewangles, forward, NULL, NULL); VectorCopy(ent->s.origin,start); @@ -1000,4 +973,428 @@ void G_UseTarget (edict_t *ent, edict_t *activator, edict_t *target) return; } } +} + +/* +============= +visible + +returns 1 if the entity is visible to self, even if not infront () +============= +*/ +bool visible (edict_t *self, edict_t *other) +{ + vec3_t spot1; + vec3_t spot2; + trace_t trace; + + VectorCopy (self->s.origin, spot1); + spot1[2] += self->viewheight; + VectorCopy (other->s.origin, spot2); + spot2[2] += other->viewheight; + trace = gi.trace (spot1, vec3_origin, vec3_origin, spot2, self, MASK_OPAQUE); + + // Lazarus: Take fog into account for monsters + + if ( (trace.fraction == 1.0) || (trace.ent == other)) + { + self->monsterinfo.visibility = 1.0; + return true; + } + return false; +} + + +/* +============= +infront + +returns 1 if the entity is in front (in sight) of self +============= +*/ +bool infront (edict_t *self, edict_t *other) +{ + vec3_t vec; + float dot; + vec3_t forward; + + AngleVectors (self->s.angles, forward, NULL, NULL); + VectorSubtract (other->s.origin, self->s.origin, vec); + VectorNormalize (vec); + dot = DotProduct (vec, forward); + + if (dot > 0.3) + return true; + return false; +} + +void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod) +{ + gclient_t *client; + int take; + int save; + int te_sparks; + edict_t *attacker; + edict_t *targ; + + targ = in_targ; + + if (!targ || !targ->inuse) + return; + + if (!targ->takedamage) + return; + + if (!in_attacker) + attacker = world; + else + attacker = in_attacker; + + + // If targ is a fake player for the real player viewing camera, get that player + // out of the camera and do the damage to him + if (targ->class_id == ENTITY_CAMPLAYER) { + if(targ->target_ent && targ->target_ent->client && targ->target_ent->client->spycam) + { + if(attacker->enemy == targ) + { + attacker->enemy = targ->target_ent; + attacker->goalentity = NULL; + attacker->movetarget = NULL; + } + targ = targ->target_ent; + if(attacker->svflags & SVF_MONSTER) + { + if(attacker->spawnflags & SF_MONSTER_GOODGUY) + { + if(attacker->enemy == targ) + { + attacker->enemy = NULL; + attacker->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; + attacker->monsterinfo.attack_finished = 0; + attacker->monsterinfo.pausetime = level.time + 100000000; + if(attacker->monsterinfo.stand) + attacker->monsterinfo.stand(attacker); + } + } + } + } + else + return; // don't damage target_monitor camplayer + } + // friendly fire avoidance + // if enabled you can't hurt teammates (but you can hurt yourself) + // knockback still occurs + if ((targ != attacker) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value)) + { + if (OnSameTeam (targ, attacker)) + { + if ((int)(dmflags->value) & DF_NO_FRIENDLY_FIRE) + damage = 0; + else + mod |= MOD_FRIENDLY_FIRE; + } + } + meansOfDeath = mod; + + // easy mode takes half damage + if (skill->value == 0 && deathmatch->value == 0 && targ->client) + { + damage *= 0.5; + if (!damage) + damage = 1; + } + + client = targ->client; + + if (dflags & DAMAGE_BULLET) + te_sparks = TE_BULLET_SPARKS; + else + te_sparks = TE_SPARKS; + + VectorNormalize(dir); + +// bonus damage for suprising a monster + if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) && (attacker->client) && (!targ->enemy) && (targ->health > 0)) + damage *= 2; + + if (targ->flags & FL_NO_KNOCKBACK) + knockback = 0; + +// Lazarus: If monster is currently chasing a "thing" and mod is a laser, +// ignore knockback to give poor guy a chance to vamoose. + if (targ->movetarget && (targ->movetarget->class_id == ENTITY_THING) && (mod == MOD_TARGET_LASER)) + knockback = 0; + +// figure momentum add + if (!(dflags & DAMAGE_NO_KNOCKBACK)) + { + // Lazarus: Added MOVETYPE_TOSS to no knockback (pickup items and dead bodies) + if ((knockback) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP) && (targ->movetype != MOVETYPE_TOSS)) + { + vec3_t kvel; + float mass; + + if (targ->mass < 50) + mass = 50; + else + mass = targ->mass; + + if (targ->client && attacker == targ) + { + VectorScale (dir, 1600.0 * (float)knockback / mass, kvel); // the rocket jump hack... + } + else + { + VectorScale (dir, 500.0 * (float)knockback / mass, kvel); + } + VectorAdd (targ->velocity, kvel, targ->velocity); + } + } + + take = damage; + save = 0; + + // check for invincibility + if ((client && client->invincible_framenum > level.framenum ) && !(dflags & DAMAGE_NO_PROTECTION)) + { + if (targ->pain_debounce_time < level.time) + { + gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0); + targ->pain_debounce_time = level.time + 2; + } + take = 0; + save = damage; + } + + // do the damage + if (take) + { + if(targ->client) + { + if(in_targ != targ) + { + // Then player has taken the place of whatever was originally + // damaged, as in switching from func_monitor usage. Limit + // damage so that player isn't killed, and make him temporarily + // invincible + targ->health = max(2,targ->health - take); + targ->client->invincible_framenum = level.framenum+2; + targ->pain_debounce_time = max(targ->pain_debounce_time,level.time+0.3); + } + else if(level.framenum - targ->client->startframe > 30) + targ->health = targ->health - take; + else if(targ->health > 10) + targ->health = max(10,targ->health - take); + } + else + { + // Lazarus: For func_explosive target, check spawnflags and, if needed, + // damage type + if(targ->class_id == ENTITY_FUNC_EXPLOSIVE) + { + bool good_damage = true; + + if(targ->spawnflags & 8) // explosion only + { + good_damage = false; + if(mod == MOD_GRENADE) good_damage = true; + if(mod == MOD_G_SPLASH) good_damage = true; + if(mod == MOD_ROCKET) good_damage = true; + if(mod == MOD_R_SPLASH) good_damage = true; + if(mod == MOD_BFG_BLAST) good_damage = true; + if(mod == MOD_HANDGRENADE) good_damage = true; + if(mod == MOD_HG_SPLASH) good_damage = true; + if(mod == MOD_EXPLOSIVE) good_damage = true; + if(mod == MOD_BARREL) good_damage = true; + if(mod == MOD_BOMB) good_damage = true; + } + if(!good_damage) return; + } + + targ->health = targ->health - take; + } + + if (targ->health <= 0) + { + if ((targ->svflags & SVF_MONSTER) || (client)) + targ->flags |= FL_NO_KNOCKBACK; + Killed (targ, inflictor, attacker, take, point); + return; + } + } + + if (client) + { + if (!(targ->flags & FL_GODMODE) && (take)) + targ->pain (targ, attacker, knockback, take); + } + else if (take) + { + if (targ->pain) + targ->pain (targ, attacker, knockback, take); + } + + // add to the damage inflicted on a player this frame + // the total will be turned into screen blends and view angle kicks + // at the end of the frame + if (client) + { + client->damage_parmor += 10; + client->damage_armor += 10; + client->damage_blood += take; + client->damage_knockback += knockback; + VectorCopy (point, client->damage_from); + } +} + + +/* +============ +T_RadiusDamage + +Lazarus adds dmg_slope to alter the radius damage equation. (Standard Q2 = -0.5) +============ +*/ +void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod, double dmg_slope) +{ + float points; + edict_t *ent = NULL; + vec3_t v; + vec3_t dir; + + while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) + { + if (ent == ignore) + continue; + if (!ent->takedamage) + continue; + + VectorAdd (ent->mins, ent->maxs, v); + VectorMA (ent->s.origin, 0.5, v, v); + VectorSubtract (inflictor->s.origin, v, v); + points = damage + dmg_slope * VectorLength (v); + if (ent == attacker) + points = points * 0.5; + if (points > 0) + { + if (CanDamage (ent, inflictor)) + { + VectorSubtract (ent->s.origin, inflictor->s.origin, dir); + T_Damage (ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); + } + } + } +} + +/* +============ +Killed +============ +*/ +void misc_deadsoldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); +void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + if (targ->health < -999) targ->health = -999; + + targ->enemy = attacker; + + if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD)) + { + if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY) ) + { + level.killed_monsters++; + if (coop->value && attacker->client) + attacker->client->resp.score++; + // medics won't heal monsters that they kill themselves + if (attacker->class_id == ENTITY_MONSTER_MEDIC) + targ->owner = attacker; + } + } + + if (targ->movetype == MOVETYPE_PUSH || targ->movetype == MOVETYPE_STOP || targ->movetype == MOVETYPE_NONE) + { // doors, triggers, etc + targ->die (targ, inflictor, attacker, damage, point); + return; + } + + if (inflictor->movetype == MOVETYPE_PUSH) + { + // Lazarus - Die function won't gib NO_GIB monsters... blow 'em up + if((targ->die != misc_deadsoldier_die) && (targ->spawnflags & SF_MONSTER_NOGIB)) + { + BecomeExplosion1(targ); + return; + } + } + targ->die (targ, inflictor, attacker, damage, point); +} + +/* +============ +CanDamage + +Returns true if the inflictor can directly damage the target. Used for +explosions and melee attacks. +============ +*/ +bool CanDamage (edict_t *targ, edict_t *inflictor) +{ + vec3_t dest; + trace_t trace; + +// bmodels need special checking because their origin is 0,0,0 + if (targ->movetype == MOVETYPE_PUSH) + { + VectorAdd (targ->absmin, targ->absmax, dest); + VectorScale (dest, 0.5, dest); + trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); + if (trace.fraction == 1.0) + return true; + if (trace.ent == targ) + return true; + return false; + } + + trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID); + if (trace.fraction == 1.0 || trace.ent == targ) + return true; + + // Lazarus: This is kinda cheesy, but avoids doing goofy things in a map to make this work. If a LOS + // from inflictor to targ is blocked by a func_tracktrain, AND the targ is riding/driving + // the tracktrain, go ahead and hurt him. + + if(trace.ent && (trace.ent->flags & FL_TRACKTRAIN) && ((trace.ent->owner == targ) || (targ->groundentity == trace.ent)) ) + return true; + + VectorCopy (targ->s.origin, dest); + dest[0] += 15.0; + dest[1] += 15.0; + trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); + if (trace.fraction == 1.0 || trace.ent == targ) + return true; + + VectorCopy (targ->s.origin, dest); + dest[0] += 15.0; + dest[1] -= 15.0; + trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); + if (trace.fraction == 1.0 || trace.ent == targ) + return true; + + VectorCopy (targ->s.origin, dest); + dest[0] -= 15.0; + dest[1] += 15.0; + trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); + if (trace.fraction == 1.0 || trace.ent == targ) + return true; + + VectorCopy (targ->s.origin, dest); + dest[0] -= 15.0; + dest[1] -= 15.0; + trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); + if (trace.fraction == 1.0 || trace.ent == targ) + return true; + + + return false; } \ No newline at end of file diff --git a/server/global/fmod.h b/server/global/fmod.h deleted file mode 100644 index 704ece52..00000000 --- a/server/global/fmod.h +++ /dev/null @@ -1,802 +0,0 @@ -//========================================================================================== -// FMOD Main header file. Copyright (c), FireLight Multimedia 1999-2001. -//========================================================================================== - -#ifndef _FMOD_H_ -#define _FMOD_H_ - -//=============================================================================================== -// DEFINITIONS -//=============================================================================================== - -#if defined(__GNUC__) && defined(WIN32) - #define _cdecl -#endif /* defined(__GNUC__) && defined(WIN32) */ - -#if defined(PLATFORM_LINUX) - #define _cdecl - #define _stdcall - #define __cdecl - #define __stdcall - #define __declspec(x) - #define __PS __attribute__((packed)) /* gcc packed */ -#else - #define __PS /*dummy*/ -#endif - -#define F_API _stdcall - -#ifdef DLL_EXPORTS - #define DLL_API __declspec(dllexport) -#else - #ifdef __LCC__ - #define DLL_API F_API - #else - #define DLL_API - #endif // __LCC__ -#endif //DLL_EXPORTS - -#define FMOD_VERSION 3.31f - -// fmod defined types -typedef struct FSOUND_MATERIAL FSOUND_MATERIAL; -typedef struct FSOUND_GEOMLIST FSOUND_GEOMLIST; -typedef struct FSOUND_SAMPLE FSOUND_SAMPLE; -typedef struct FSOUND_STREAM FSOUND_STREAM; -typedef struct FSOUND_DSPUNIT FSOUND_DSPUNIT; -typedef struct FMUSIC_MODULE FMUSIC_MODULE; - -// callback types -typedef signed char (_cdecl *FSOUND_STREAMCALLBACK) (FSOUND_STREAM *stream, void *buff, int len, int param); -typedef void * (_cdecl *FSOUND_DSPCALLBACK) (void *originalbuffer, void *newbuffer, int length, int param); -typedef void (_cdecl *FMUSIC_CALLBACK) (FMUSIC_MODULE *mod, unsigned char param); - -/* -[ENUM] -[ - [DESCRIPTION] - On failure of commands in FMOD, use FSOUND_GetError to attain what happened. - - [SEE_ALSO] - FSOUND_GetError -] -*/ -enum FMOD_ERRORS -{ - FMOD_ERR_NONE, // No errors - FMOD_ERR_BUSY, // Cannot call this command after FSOUND_Init. Call FSOUND_Close first. - FMOD_ERR_UNINITIALIZED, // This command failed because FSOUND_Init was not called - FMOD_ERR_INIT, // Error initializing output device. - FMOD_ERR_ALLOCATED, // Error initializing output device, but more specifically, the output device is already in use and cannot be reused. - FMOD_ERR_PLAY, // Playing the sound failed. - FMOD_ERR_OUTPUT_FORMAT, // Soundcard does not support the features needed for this soundsystem (16bit stereo output) - FMOD_ERR_COOPERATIVELEVEL, // Error setting cooperative level for hardware. - FMOD_ERR_CREATEBUFFER, // Error creating hardware sound buffer. - FMOD_ERR_FILE_NOTFOUND, // File not found - FMOD_ERR_FILE_FORMAT, // Unknown file format - FMOD_ERR_FILE_BAD, // Error loading file - FMOD_ERR_MEMORY, // Not enough memory - FMOD_ERR_VERSION, // The version number of this file format is not supported - FMOD_ERR_INVALID_PARAM, // An invalid parameter was passed to this function - FMOD_ERR_NO_EAX, // Tried to use an EAX command on a non EAX enabled channel or output. - FMOD_ERR_NO_EAX2, // Tried to use an advanced EAX2 command on a non EAX2 enabled channel or output. - FMOD_ERR_CHANNEL_ALLOC, // Failed to allocate a new channel - FMOD_ERR_RECORD, // Recording is not supported on this machine - FMOD_ERR_MEDIAPLAYER, // Windows Media Player not installed so cant play wma or use internet streaming. -}; - - -/* -[ENUM] -[ - [DESCRIPTION] - These output types are used with FSOUND_SetOutput, to choose which output driver to use. - - FSOUND_OUTPUT_A3D will cause FSOUND_Init to FAIL if you have not got a vortex - based A3D card. The suggestion for this is to immediately try and reinitialize FMOD with - FSOUND_OUTPUT_DSOUND, and if this fails, try initializing FMOD with FSOUND_OUTPUT_WAVEOUT. - - FSOUND_OUTPUT_DSOUND will not support hardware 3d acceleration if the sound card driver - does not support DirectX 6 Voice Manager Extensions. - - [SEE_ALSO] - FSOUND_SetOutput - FSOUND_GetOutput -] -*/ -enum FSOUND_OUTPUTTYPES -{ - FSOUND_OUTPUT_NOSOUND, // NoSound driver, all calls to this succeed but do nothing. - FSOUND_OUTPUT_WINMM, // Windows Multimedia driver. - FSOUND_OUTPUT_DSOUND, // DirectSound driver. You need this to get EAX or EAX2 support. - FSOUND_OUTPUT_A3D, // A3D driver. You need this to get geometry support. - FSOUND_OUTPUT_OSS, // Linux/Unix OSS (Open Sound System) driver, i.e. the kernel sound drivers. - FSOUND_OUTPUT_ESD, // Linux/Unix ESD (Enlightment Sound Daemon) driver. - FSOUND_OUTPUT_ALSA // Linux Alsa driver. -}; - - -/* -[ENUM] -[ - [DESCRIPTION] - These mixer types are used with FSOUND_SetMixer, to choose which mixer to use, or to act - upon for other reasons using FSOUND_GetMixer. - - [SEE_ALSO] - FSOUND_SetMixer - FSOUND_GetMixer -] -*/ -enum FSOUND_MIXERTYPES -{ - FSOUND_MIXER_AUTODETECT, // Enables autodetection of the fastest mixer based on your cpu. - FSOUND_MIXER_BLENDMODE, // Enables the standard non mmx, blendmode mixer. - FSOUND_MIXER_MMXP5, // Enables the mmx, pentium optimized blendmode mixer. - FSOUND_MIXER_MMXP6, // Enables the mmx, ppro/p2/p3 optimized mixer. - - FSOUND_MIXER_QUALITY_AUTODETECT,// Enables autodetection of the fastest quality mixer based on your cpu. - FSOUND_MIXER_QUALITY_FPU, // Enables the interpolating/volume ramping FPU mixer. - FSOUND_MIXER_QUALITY_MMXP5, // Enables the interpolating/volume ramping p5 MMX mixer. - FSOUND_MIXER_QUALITY_MMXP6, // Enables the interpolating/volume ramping ppro/p2/p3+ MMX mixer. -}; - -/* -[ENUM] -[ - [DESCRIPTION] - These definitions describe the type of song being played. - - [SEE_ALSO] - FMUSIC_GetType -] -*/ -enum FMUSIC_TYPES -{ - FMUSIC_TYPE_NONE, - FMUSIC_TYPE_MOD, // Protracker / Fasttracker - FMUSIC_TYPE_S3M, // ScreamTracker 3 - FMUSIC_TYPE_XM, // FastTracker 2 - FMUSIC_TYPE_IT, // Impulse Tracker. - FMUSIC_TYPE_MIDI, // MIDI file -}; - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_DSP_PRIORITIES - - [DESCRIPTION] - These default priorities are - - [SEE_ALSO] - FSOUND_DSP_Create - FSOUND_DSP_SetPriority -] -*/ -#define FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT 0 // DSP CLEAR unit - done first -#define FSOUND_DSP_DEFAULTPRIORITY_SFXUNIT 100 // DSP SFX unit - done second -#define FSOUND_DSP_DEFAULTPRIORITY_MUSICUNIT 200 // DSP MUSIC unit - done third -#define FSOUND_DSP_DEFAULTPRIORITY_USER 300 // User priority, use this as reference -#define FSOUND_DSP_DEFAULTPRIORITY_CLIPANDCOPYUNIT 1000 // DSP CLIP AND COPY unit - last -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_CAPS - - [DESCRIPTION] - Driver description bitfields. Use FSOUND_Driver_GetCaps to determine if a driver enumerated - has the settings you are after. The enumerated driver depends on the output mode, see - FSOUND_OUTPUTTYPES - - [SEE_ALSO] - FSOUND_GetDriverCaps - FSOUND_OUTPUTTYPES -] -*/ -#define FSOUND_CAPS_HARDWARE 0x1 // This driver supports hardware accelerated 3d sound. -#define FSOUND_CAPS_EAX 0x2 // This driver supports EAX reverb -#define FSOUND_CAPS_GEOMETRY_OCCLUSIONS 0x4 // This driver supports (A3D) geometry occlusions -#define FSOUND_CAPS_GEOMETRY_REFLECTIONS 0x8 // This driver supports (A3D) geometry reflections -#define FSOUND_CAPS_EAX2 0x10 // This driver supports EAX2/A3D3 reverb -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_MODES - - [DESCRIPTION] - Sample description bitfields, OR them together for loading and describing samples. -] -*/ -#define FSOUND_LOOP_OFF 0x00000001 // For non looping samples. -#define FSOUND_LOOP_NORMAL 0x00000002 // For forward looping samples. -#define FSOUND_LOOP_BIDI 0x00000004 // For bidirectional looping samples. (no effect if in hardware). -#define FSOUND_8BITS 0x00000008 // For 8 bit samples. -#define FSOUND_16BITS 0x00000010 // For 16 bit samples. -#define FSOUND_MONO 0x00000020 // For mono samples. -#define FSOUND_STEREO 0x00000040 // For stereo samples. -#define FSOUND_UNSIGNED 0x00000080 // For source data containing unsigned samples. -#define FSOUND_SIGNED 0x00000100 // For source data containing signed data. -#define FSOUND_DELTA 0x00000200 // For source data stored as delta values. -#define FSOUND_IT214 0x00000400 // For source data stored using IT214 compression. -#define FSOUND_IT215 0x00000800 // For source data stored using IT215 compression. -#define FSOUND_HW3D 0x00001000 // Attempts to make samples use 3d hardware acceleration. (if the card supports it) -#define FSOUND_2D 0x00002000 // Ignores any 3d processing. overrides FSOUND_HW3D. Located in software. -#define FSOUND_STREAMABLE 0x00004000 // For a streamable sound where you feed the data to it. If you dont supply this sound may come out corrupted. (only affects a3d output) -#define FSOUND_LOADMEMORY 0x00008000 // 'name' will be interpreted as a pointer to data for streaming and samples. -#define FSOUND_LOADRAW 0x00010000 // For will ignore file format and treat as raw pcm. -#define FSOUND_MPEGACCURATE 0x00020000 // For FSOUND_Stream_OpenFile - for accurate FSOUND_Stream_GetLengthMs/FSOUND_Stream_SetTime. WARNING, see FSOUNDStream_OpenFile for inital opening time performance issues. - -// Default sample type. Loop off, 8bit mono, signed, not hardware accelerated. -// Some API functions ignore 8bits and mono, as it may be an mpeg/wav/etc which has its format predetermined. -#define FSOUND_NORMAL (FSOUND_LOOP_OFF | FSOUND_8BITS | FSOUND_MONO) -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_CDPLAYMODES - - [DESCRIPTION] - Playback method for a CD Audio track, using FSOUND_CD_Play - - [SEE_ALSO] - FSOUND_CD_Play -] -*/ -#define FSOUND_CD_PLAYCONTINUOUS 0 // Starts from the current track and plays to end of CD. -#define FSOUND_CD_PLAYONCE 1 // Plays the specified track then stops. -#define FSOUND_CD_PLAYLOOPED 2 // Plays the specified track looped, forever until stopped manually. -#define FSOUND_CD_PLAYRANDOM 3 // Plays tracks in random order -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_CHANNELSAMPLEMODE - - [DESCRIPTION] - Miscellaneous values for FMOD functions. - - [SEE_ALSO] - FSOUND_PlaySound - FSOUND_PlaySound3DAttrib - - FSOUND_Sample_Alloc - FSOUND_Sample_Load - FSOUND_SetPan -] -*/ -#define FSOUND_FREE -1 // value to play on any free channel, or to allocate a sample in a free sample slot. -#define FSOUND_UNMANAGED -2 // value to allocate a sample that is NOT managed by FSOUND or placed in a sample slot. -#define FSOUND_ALL -3 // for a channel index , this flag will affect ALL channels available! Not supported by every function. -#define FSOUND_STEREOPAN -1 // value for FSOUND_SetPan so that stereo sounds are not played at half volume. See FSOUND_SetPan for more on this. -// [DEFINE_END] - - -/* -[ENUM] -[ - [DESCRIPTION] - These are environment types defined for use with the FSOUND_Reverb API. - - [SEE_ALSO] - FSOUND_Reverb_SetEnvironment - FSOUND_Reverb_SetEnvironmentAdvanced -] -*/ -enum FSOUND_REVERB_ENVIRONMENTS -{ - FSOUND_ENVIRONMENT_GENERIC, - FSOUND_ENVIRONMENT_PADDEDCELL, - FSOUND_ENVIRONMENT_ROOM, - FSOUND_ENVIRONMENT_BATHROOM, - FSOUND_ENVIRONMENT_LIVINGROOM, - FSOUND_ENVIRONMENT_STONEROOM, - FSOUND_ENVIRONMENT_AUDITORIUM, - FSOUND_ENVIRONMENT_CONCERTHALL, - FSOUND_ENVIRONMENT_CAVE, - FSOUND_ENVIRONMENT_ARENA, - FSOUND_ENVIRONMENT_HANGAR, - FSOUND_ENVIRONMENT_CARPETEDHALLWAY, - FSOUND_ENVIRONMENT_HALLWAY, - FSOUND_ENVIRONMENT_STONECORRIDOR, - FSOUND_ENVIRONMENT_ALLEY, - FSOUND_ENVIRONMENT_FOREST, - FSOUND_ENVIRONMENT_CITY, - FSOUND_ENVIRONMENT_MOUNTAINS, - FSOUND_ENVIRONMENT_QUARRY, - FSOUND_ENVIRONMENT_PLAIN, - FSOUND_ENVIRONMENT_PARKINGLOT, - FSOUND_ENVIRONMENT_SEWERPIPE, - FSOUND_ENVIRONMENT_UNDERWATER, - FSOUND_ENVIRONMENT_DRUGGED, - FSOUND_ENVIRONMENT_DIZZY, - FSOUND_ENVIRONMENT_PSYCHOTIC, - - FSOUND_ENVIRONMENT_COUNT -}; - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_REVERBMIX_USEDISTANCE - - [DESCRIPTION] - Used with FSOUND_Reverb_SetMix, this setting allows reverb to attenuate based on distance from the listener. - Instead of hard coding a value with FSOUND_Reverb_SetMix, this value can be used instead, for a more natural - reverb dropoff. - - [SEE_ALSO] - FSOUND_Reverb_SetMix -] -*/ -#define FSOUND_REVERBMIX_USEDISTANCE -1.0f // used with FSOUND_Reverb_SetMix to scale reverb by distance -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_REVERB_IGNOREPARAM - - [DESCRIPTION] - Used with FSOUND_Reverb_SetEnvironment and FSOUND_Reverb_SetEnvironmentAdvanced, this can - be placed in the place of a specific parameter for the reverb setting. It allows you to - not set any parameters except the ones you are interested in .. and example would be this. - FSOUND_Reverb_SetEnvironment(FSOUND_REVERB_IGNOREPARAM, - FSOUND_REVERB_IGNOREPARAM, - FSOUND_REVERB_IGNOREPARAM, - 0.0f); - This means env, vol and decay are left alone, but 'damp' is set to 0. - - [SEE_ALSO] - FSOUND_Reverb_SetEnvironment - FSOUND_Reverb_SetEnvironmentAdvanced -] -*/ -#define FSOUND_REVERB_IGNOREPARAM -9999999 // used with FSOUND_Reverb_SetEnvironmentAdvanced to ignore certain parameters by choice. -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_REVERB_PRESETS - - [DESCRIPTION] - A set of predefined environment PARAMETERS, created by Creative Labs - These can be placed directly into the FSOUND_Reverb_SetEnvironment call - - [SEE_ALSO] - FSOUND_Reverb_SetEnvironment -] -*/ -#define FSOUND_PRESET_OFF FSOUND_ENVIRONMENT_GENERIC,0.0f,0.0f,0.0f -#define FSOUND_PRESET_GENERIC FSOUND_ENVIRONMENT_GENERIC,0.5f,1.493f,0.5f -#define FSOUND_PRESET_PADDEDCELL FSOUND_ENVIRONMENT_PADDEDCELL,0.25f,0.1f,0.0f -#define FSOUND_PRESET_ROOM FSOUND_ENVIRONMENT_ROOM,0.417f,0.4f,0.666f -#define FSOUND_PRESET_BATHROOM FSOUND_ENVIRONMENT_BATHROOM,0.653f,1.499f,0.166f -#define FSOUND_PRESET_LIVINGROOM FSOUND_ENVIRONMENT_LIVINGROOM,0.208f,0.478f,0.0f -#define FSOUND_PRESET_STONEROOM FSOUND_ENVIRONMENT_STONEROOM,0.5f,2.309f,0.888f -#define FSOUND_PRESET_AUDITORIUM FSOUND_ENVIRONMENT_AUDITORIUM,0.403f,4.279f,0.5f -#define FSOUND_PRESET_CONCERTHALL FSOUND_ENVIRONMENT_CONCERTHALL,0.5f,3.961f,0.5f -#define FSOUND_PRESET_CAVE FSOUND_ENVIRONMENT_CAVE,0.5f,2.886f,1.304f -#define FSOUND_PRESET_ARENA FSOUND_ENVIRONMENT_ARENA,0.361f,7.284f,0.332f -#define FSOUND_PRESET_HANGAR FSOUND_ENVIRONMENT_HANGAR,0.5f,10.0f,0.3f -#define FSOUND_PRESET_CARPETEDHALLWAY FSOUND_ENVIRONMENT_CARPETEDHALLWAY,0.153f,0.259f,2.0f -#define FSOUND_PRESET_HALLWAY FSOUND_ENVIRONMENT_HALLWAY,0.361f,1.493f,0.0f -#define FSOUND_PRESET_STONECORRIDOR FSOUND_ENVIRONMENT_STONECORRIDOR,0.444f,2.697f,0.638f -#define FSOUND_PRESET_ALLEY FSOUND_ENVIRONMENT_ALLEY,0.25f,1.752f,0.776f -#define FSOUND_PRESET_FOREST FSOUND_ENVIRONMENT_FOREST,0.111f,3.145f,0.472f -#define FSOUND_PRESET_CITY FSOUND_ENVIRONMENT_CITY,0.111f,2.767f,0.224f -#define FSOUND_PRESET_MOUNTAINS FSOUND_ENVIRONMENT_MOUNTAINS,0.194f,7.841f,0.472f -#define FSOUND_PRESET_QUARRY FSOUND_ENVIRONMENT_QUARRY,1.0f,1.499f,0.5f -#define FSOUND_PRESET_PLAIN FSOUND_ENVIRONMENT_PLAIN,0.097f,2.767f,0.224f -#define FSOUND_PRESET_PARKINGLOT FSOUND_ENVIRONMENT_PARKINGLOT,0.208f,1.652f,1.5f -#define FSOUND_PRESET_SEWERPIPE FSOUND_ENVIRONMENT_SEWERPIPE,0.652f,2.886f,0.25f -#define FSOUND_PRESET_UNDERWATER FSOUND_ENVIRONMENT_UNDERWATER,1.0f,1.499f,0.0f -#define FSOUND_PRESET_DRUGGED FSOUND_ENVIRONMENT_DRUGGED,0.875f, 8.392f,1.388f -#define FSOUND_PRESET_DIZZY FSOUND_ENVIRONMENT_DIZZY,0.139f,17.234f,0.666f -#define FSOUND_PRESET_PSYCHOTIC FSOUND_ENVIRONMENT_PSYCHOTIC,0.486f,7.563f,0.806f -// [DEFINE_END] - - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_GEOMETRY_MODES - - [DESCRIPTION] - Geometry flags, used as the mode flag in FSOUND_Geometry_AddPolygon - - [SEE_ALSO] - FSOUND_Geometry_AddPolygon -] -*/ -#define FSOUND_GEOMETRY_NORMAL 0x0 // Default geometry type. Occluding polygon -#define FSOUND_GEOMETRY_REFLECTIVE 0x01 // This polygon is reflective -#define FSOUND_GEOMETRY_OPENING 0x02 // Overlays a transparency over the previous polygon. The 'openingfactor' value supplied is copied internally. -#define FSOUND_GEOMETRY_OPENING_REFERENCE 0x04 // Overlays a transparency over the previous polygon. The 'openingfactor' supplied is pointed to (for access when building a list) -// [DEFINE_END] - -/* -[DEFINE_START] -[ - [NAME] - FSOUND_INIT_FLAGS - - [DESCRIPTION] - Initialization flags. Use them with FSOUND_Init in the flags parameter to change various behaviour. - - [SEE_ALSO] - FSOUND_Init -] -*/ -#define FSOUND_INIT_USEDEFAULTMIDISYNTH 0x01 // Causes MIDI playback to force software decoding. -// [DEFINE_END] - - - - -//=============================================================================================== -// FUNCTION PROTOTYPES -//=============================================================================================== - -/* Lazarus: We use GetProcAddress to resolve FMOD references, so these aren't needed (and - cause conflicts if we try to use the same names. - -#ifdef __cplusplus -extern "C" { -#endif - -// ================================== -// Initialization / Global functions. -// ================================== - -// *Pre* FSOUND_Init functions. These can't be called after FSOUND_Init is -// called (they will fail). They set up FMOD system functionality. -DLL_API signed char F_API FSOUND_SetOutput(int outputtype); -DLL_API signed char F_API FSOUND_SetDriver(int driver); -DLL_API signed char F_API FSOUND_SetMixer(int mixer); -DLL_API signed char F_API FSOUND_SetBufferSize(int len_ms); -DLL_API signed char F_API FSOUND_SetHWND(void *hwnd); -DLL_API signed char F_API FSOUND_SetMinHardwareChannels(int min); -DLL_API signed char F_API FSOUND_SetMaxHardwareChannels(int max); - -// Main initialization / closedown functions. -// Note : Use FSOUND_INIT_USEDEFAULTMIDISYNTH with FSOUND_Init for software override with MIDI playback. -DLL_API signed char F_API FSOUND_Init(int mixrate, int maxsoftwarechannels, unsigned int flags); -DLL_API void F_API FSOUND_Close(); - -// Runtime -DLL_API void F_API FSOUND_SetSFXMasterVolume(int volume); -DLL_API void F_API FSOUND_SetPanSeperation(float pansep); - -// System information. -DLL_API int F_API FSOUND_GetError(); -DLL_API float F_API FSOUND_GetVersion(); -DLL_API int F_API FSOUND_GetOutput(); -DLL_API int F_API FSOUND_GetDriver(); -DLL_API int F_API FSOUND_GetMixer(); -DLL_API int F_API FSOUND_GetNumDrivers(); -DLL_API signed char * F_API FSOUND_GetDriverName(int id); -DLL_API signed char F_API FSOUND_GetDriverCaps(int id, unsigned int *caps); -DLL_API int F_API FSOUND_GetOutputRate(); -DLL_API int F_API FSOUND_GetMaxChannels(); -DLL_API int F_API FSOUND_GetMaxSamples(); -DLL_API int F_API FSOUND_GetSFXMasterVolume(); -DLL_API int F_API FSOUND_GetNumHardwareChannels(); -DLL_API int F_API FSOUND_GetChannelsPlaying(); -DLL_API float F_API FSOUND_GetCPUUsage(); - -// =================================== -// Sample management / load functions. -// =================================== - -// Note : Use FSOUND_LOADMEMORY flag with FSOUND_Sample_Load to load from memory. -// Use FSOUND_LOADRAW flag with FSOUND_Sample_Load to treat as as raw pcm data. - -// Sample creation and management functions -DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Load(int index, const char *name, unsigned int mode, int memlength); -DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Alloc(int index, int length, unsigned int mode, int deffreq, int defvol, int defpan, int defpri); -DLL_API void F_API FSOUND_Sample_Free(FSOUND_SAMPLE *sptr); -DLL_API signed char F_API FSOUND_Sample_Upload(FSOUND_SAMPLE *sptr, void *srcdata, unsigned int mode); -DLL_API signed char F_API FSOUND_Sample_Lock(FSOUND_SAMPLE *sptr, int offset, int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2); -DLL_API signed char F_API FSOUND_Sample_Unlock(FSOUND_SAMPLE *sptr, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2); - -// Sample control functions -DLL_API signed char F_API FSOUND_Sample_SetLoopMode(FSOUND_SAMPLE *sptr, unsigned int loopmode); -DLL_API signed char F_API FSOUND_Sample_SetLoopPoints(FSOUND_SAMPLE *sptr, int loopstart, int loopend); -DLL_API signed char F_API FSOUND_Sample_SetDefaults(FSOUND_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri); -DLL_API signed char F_API FSOUND_Sample_SetMinMaxDistance(FSOUND_SAMPLE *sptr, float min, float max); - -// Sample information -DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Get(int sampno); -DLL_API char * F_API FSOUND_Sample_GetName(FSOUND_SAMPLE *sptr); -DLL_API unsigned int F_API FSOUND_Sample_GetLength(FSOUND_SAMPLE *sptr); -DLL_API signed char F_API FSOUND_Sample_GetLoopPoints(FSOUND_SAMPLE *sptr, int *loopstart, int *loopend); -DLL_API signed char F_API FSOUND_Sample_GetDefaults(FSOUND_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri); -DLL_API unsigned int F_API FSOUND_Sample_GetMode(FSOUND_SAMPLE *sptr); - -// ============================ -// Channel control functions. -// ============================ - -// Playing and stopping sounds. -DLL_API int F_API FSOUND_PlaySound(int channel, FSOUND_SAMPLE *sptr); -DLL_API int F_API FSOUND_PlaySound3DAttrib(int channel, FSOUND_SAMPLE *sptr, int freq, int vol, int pan, float *pos, float *vel); -DLL_API signed char F_API FSOUND_StopSound(int channel); - -// Functions to control playback of a channel. -DLL_API signed char F_API FSOUND_SetFrequency(int channel, int freq); -DLL_API signed char F_API FSOUND_SetVolume(int channel, int vol); -DLL_API signed char F_API FSOUND_SetVolumeAbsolute(int channel, int vol); -DLL_API signed char F_API FSOUND_SetPan(int channel, int pan); -DLL_API signed char F_API FSOUND_SetSurround(int channel, signed char surround); -DLL_API signed char F_API FSOUND_SetMute(int channel, signed char mute); -DLL_API signed char F_API FSOUND_SetPriority(int channel, int priority); -DLL_API signed char F_API FSOUND_SetReserved(int channel, signed char reserved); -DLL_API signed char F_API FSOUND_SetPaused(int channel, signed char paused); -DLL_API signed char F_API FSOUND_SetLoopMode(int channel, unsigned int loopmode); - -// Channel information -DLL_API signed char F_API FSOUND_IsPlaying(int channel); -DLL_API int F_API FSOUND_GetFrequency(int channel); -DLL_API int F_API FSOUND_GetVolume(int channel); -DLL_API int F_API FSOUND_GetPan(int channel); -DLL_API signed char F_API FSOUND_GetSurround(int channel); -DLL_API signed char F_API FSOUND_GetMute(int channel); -DLL_API int F_API FSOUND_GetPriority(int channel); -DLL_API signed char F_API FSOUND_GetReserved(int channel); -DLL_API signed char F_API FSOUND_GetPaused(int channel); -DLL_API unsigned int F_API FSOUND_GetCurrentPosition(int channel); -DLL_API FSOUND_SAMPLE * F_API FSOUND_GetCurrentSample(int channel); -DLL_API float F_API FSOUND_GetCurrentVU(int channel); - -// =================== -// 3D sound functions. -// =================== -// see also FSOUND_PlaySound3DAttrib (above) -// see also FSOUND_Sample_SetMinMaxDistance (above) -DLL_API void F_API FSOUND_3D_Update(); -DLL_API signed char F_API FSOUND_3D_SetAttributes(int channel, float *pos, float *vel); -DLL_API signed char F_API FSOUND_3D_GetAttributes(int channel, float *pos, float *vel); -DLL_API void F_API FSOUND_3D_Listener_SetAttributes(float *pos, float *vel, float fx, float fy, float fz, float tx, float ty, float tz); -DLL_API void F_API FSOUND_3D_Listener_GetAttributes(float *pos, float *vel, float *fx, float *fy, float *fz, float *tx, float *ty, float *tz); -DLL_API void F_API FSOUND_3D_Listener_SetDopplerFactor(float scale); -DLL_API void F_API FSOUND_3D_Listener_SetDistanceFactor(float scale); -DLL_API void F_API FSOUND_3D_Listener_SetRolloffFactor(float scale); - -// ========================= -// File Streaming functions. -// ========================= - -// Note : Use FSOUND_LOADMEMORY flag with FSOUND_Stream_OpenFile to stream from memory. -// Use FSOUND_LOADRAW flag with FSOUND_Stream_OpenFile to treat stream as raw pcm data. -// Use FSOUND_MPEGACCURATE flag with FSOUND_Stream_OpenFile to open mpegs in 'accurate mode' for seeking etc. - -DLL_API FSOUND_STREAM * F_API FSOUND_Stream_OpenFile(const char *filename, unsigned int mode, int memlength); -DLL_API FSOUND_STREAM * F_API FSOUND_Stream_Create(FSOUND_STREAMCALLBACK callback, int length, unsigned int mode, int samplerate, int userdata); -DLL_API int F_API FSOUND_Stream_Play(int channel, FSOUND_STREAM *stream); -DLL_API int F_API FSOUND_Stream_Play3DAttrib(int channel, FSOUND_STREAM *stream, int freq, int vol, int pan, float *pos, float *vel); -DLL_API signed char F_API FSOUND_Stream_Stop(FSOUND_STREAM *stream); -DLL_API signed char F_API FSOUND_Stream_Close(FSOUND_STREAM *stream); -DLL_API signed char F_API FSOUND_Stream_SetEndCallback(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, int userdata); -DLL_API signed char F_API FSOUND_Stream_SetSynchCallback(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, int userdata); -DLL_API FSOUND_SAMPLE * F_API FSOUND_Stream_GetSample(FSOUND_STREAM *stream); -DLL_API FSOUND_DSPUNIT *F_API FSOUND_Stream_CreateDSP(FSOUND_STREAM *stream, FSOUND_DSPCALLBACK callback, int priority, int param); - -DLL_API signed char F_API FSOUND_Stream_SetPaused(FSOUND_STREAM *stream, signed char paused); -DLL_API signed char F_API FSOUND_Stream_GetPaused(FSOUND_STREAM *stream); -DLL_API signed char F_API FSOUND_Stream_SetPosition(FSOUND_STREAM *stream, int position); -DLL_API int F_API FSOUND_Stream_GetPosition(FSOUND_STREAM *stream); -DLL_API signed char F_API FSOUND_Stream_SetTime(FSOUND_STREAM *stream, int ms); -DLL_API int F_API FSOUND_Stream_GetTime(FSOUND_STREAM *stream); -DLL_API int F_API FSOUND_Stream_GetLength(FSOUND_STREAM *stream); -DLL_API int F_API FSOUND_Stream_GetLengthMs(FSOUND_STREAM *stream); - -// =================== -// CD audio functions. -// =================== - -DLL_API signed char F_API FSOUND_CD_Play(int track); -DLL_API void F_API FSOUND_CD_SetPlayMode(signed char mode); -DLL_API signed char F_API FSOUND_CD_Stop(); -DLL_API signed char F_API FSOUND_CD_SetPaused(signed char paused); -DLL_API signed char F_API FSOUND_CD_SetVolume(int volume); -DLL_API signed char F_API FSOUND_CD_Eject(); - -DLL_API signed char F_API FSOUND_CD_GetPaused(); -DLL_API int F_API FSOUND_CD_GetTrack(); -DLL_API int F_API FSOUND_CD_GetNumTracks(); -DLL_API int F_API FSOUND_CD_GetVolume(); -DLL_API int F_API FSOUND_CD_GetTrackLength(int track); -DLL_API int F_API FSOUND_CD_GetTrackTime(); - - -// ============== -// DSP functions. -// ============== - -// DSP Unit control and information functions. -DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_Create(FSOUND_DSPCALLBACK callback, int priority, int param); -DLL_API void F_API FSOUND_DSP_Free(FSOUND_DSPUNIT *unit); -DLL_API void F_API FSOUND_DSP_SetPriority(FSOUND_DSPUNIT *unit, int priority); -DLL_API int F_API FSOUND_DSP_GetPriority(FSOUND_DSPUNIT *unit); -DLL_API void F_API FSOUND_DSP_SetActive(FSOUND_DSPUNIT *unit, signed char active); -DLL_API signed char F_API FSOUND_DSP_GetActive(FSOUND_DSPUNIT *unit); - -// Functions to get hold of FSOUND 'system DSP unit' handles. -DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetClearUnit(); -DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetSFXUnit(); -DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetMusicUnit(); -DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetClipAndCopyUnit(); - -// misc DSP functions -DLL_API signed char F_API FSOUND_DSP_MixBuffers(void *destbuffer, void *srcbuffer, int len, int freq, int vol, int pan, unsigned int mode); -DLL_API void F_API FSOUND_DSP_ClearMixBuffer(); -DLL_API int F_API FSOUND_DSP_GetBufferLength(); - -// ============================================= -// Geometry functions. (NOT SUPPORTED IN LINUX) -// ============================================= - -// scene/polygon functions -DLL_API signed char F_API FSOUND_Geometry_AddPolygon(float *p1, float *p2, float *p3, float *p4, float *normal, unsigned int mode, float *openingfactor); -DLL_API int F_API FSOUND_Geometry_AddList(FSOUND_GEOMLIST *geomlist); - -// polygon list functions -DLL_API FSOUND_GEOMLIST * F_API FSOUND_Geometry_List_Create(signed char boundingvolume); -DLL_API signed char F_API FSOUND_Geometry_List_Free(FSOUND_GEOMLIST *geomlist); -DLL_API signed char F_API FSOUND_Geometry_List_Begin(FSOUND_GEOMLIST *geomlist); -DLL_API signed char F_API FSOUND_Geometry_List_End(FSOUND_GEOMLIST *geomlist); - -// material functions -DLL_API FSOUND_MATERIAL * F_API FSOUND_Geometry_Material_Create(); -DLL_API signed char F_API FSOUND_Geometry_Material_Free(FSOUND_MATERIAL *material); -DLL_API signed char F_API FSOUND_Geometry_Material_SetAttributes(FSOUND_MATERIAL *material, float reflectancegain, float reflectancefreq, float transmittancegain, float transmittancefreq); -DLL_API signed char F_API FSOUND_Geometry_Material_GetAttributes(FSOUND_MATERIAL *material, float *reflectancegain, float *reflectancefreq, float *transmittancegain, float *transmittancefreq); -DLL_API signed char F_API FSOUND_Geometry_Material_Set(FSOUND_MATERIAL *material); - -// ======================================================================== -// Reverb functions. (eax, eax2, a3d 3.0 reverb) (NOT SUPPORTED IN LINUX) -// ======================================================================== - -// eax1, eax2, a3d 3.0 (use FSOUND_REVERB_PRESETS if you like), (eax2 support through emulation/parameter conversion) -DLL_API signed char F_API FSOUND_Reverb_SetEnvironment(int env, float vol, float decay, float damp); -// eax2, a3d 3.0 only, does not work on eax1 -DLL_API signed char F_API FSOUND_Reverb_SetEnvironmentAdvanced( - int env, - int Room, // [-10000, 0] default: -10000 mB or use FSOUND_REVERB_IGNOREPARAM - int RoomHF, // [-10000, 0] default: 0 mB or use FSOUND_REVERB_IGNOREPARAM - float RoomRolloffFactor, // [0.0, 10.0] default: 0.0 or use FSOUND_REVERB_IGNOREPARAM - float DecayTime, // [0.1, 20.0] default: 1.0 s or use FSOUND_REVERB_IGNOREPARAM - float DecayHFRatio, // [0.1, 2.0] default: 0.5 or use FSOUND_REVERB_IGNOREPARAM - int Reflections, // [-10000, 1000] default: -10000 mB or use FSOUND_REVERB_IGNOREPARAM - float ReflectionsDelay, // [0.0, 0.3] default: 0.02 s or use FSOUND_REVERB_IGNOREPARAM - int Reverb, // [-10000, 2000] default: -10000 mB or use FSOUND_REVERB_IGNOREPARAM - float ReverbDelay, // [0.0, 0.1] default: 0.04 s or use FSOUND_REVERB_IGNOREPARAM - float EnvironmentSize, // [0.0, 100.0] default: 100.0 % or use FSOUND_REVERB_IGNOREPARAM - float EnvironmentDiffusion, // [0.0, 100.0] default: 100.0 % or use FSOUND_REVERB_IGNOREPARAM - float AirAbsorptionHF); // [20.0, 20000.0] default: 5000.0 Hz or use FSOUND_REVERB_IGNOREPARAM - -DLL_API signed char F_API FSOUND_Reverb_SetMix(int channel, float mix); - -// information functions -DLL_API signed char F_API FSOUND_Reverb_GetEnvironment(int *env, float *vol, float *decay, float *damp); -DLL_API signed char F_API FSOUND_Reverb_GetEnvironmentAdvanced( - int *env, - int *Room, - int *RoomHF, - float *RoomRolloffFactor, - float *DecayTime, - float *DecayHFRatio, - int *Reflections, - float *ReflectionsDelay, - int *Reverb, - float *ReverbDelay, - float *EnvironmentSize, - float *EnvironmentDiffusion, - float *AirAbsorptionHF); -DLL_API signed char F_API FSOUND_Reverb_GetMix(int channel, float *mix); - -// ============================================= -// Recording functions (NOT SUPPORTED IN LINUX) -// ============================================= - -// recording initialization functions -DLL_API signed char F_API FSOUND_Record_SetDriver(int outputtype); -DLL_API int F_API FSOUND_Record_GetNumDrivers(); -DLL_API signed char * F_API FSOUND_Record_GetDriverName(int id); -DLL_API int F_API FSOUND_Record_GetDriver(); - -// recording functionality. Only one recording session will work at a time -DLL_API signed char F_API FSOUND_Record_StartSample(FSOUND_SAMPLE *sptr, signed char loop);// record to sample -DLL_API signed char F_API FSOUND_Record_Stop(); // stop recording -DLL_API int F_API FSOUND_Record_GetPosition(); // offset in sample, or wav file - -// ========================= -// File system override -// ========================= - -DLL_API void F_API FSOUND_File_SetCallbacks(unsigned int (_cdecl *OpenCallback)(const char *name), - void (_cdecl *CloseCallback)(unsigned int handle), - int (_cdecl *ReadCallback)(void *buffer, int size, unsigned int handle), - int (_cdecl *SeekCallback)(unsigned int handle, int pos, signed char mode), - int (_cdecl *TellCallback)(unsigned int handle)); - -// ============================================================================================= -// FMUSIC API -// ============================================================================================= - -// Song management / playback functions. -DLL_API FMUSIC_MODULE * F_API FMUSIC_LoadSong(const char *name); -DLL_API FMUSIC_MODULE * F_API FMUSIC_LoadSongMemory(void *data, int length); -DLL_API signed char F_API FMUSIC_FreeSong(FMUSIC_MODULE *mod); -DLL_API signed char F_API FMUSIC_PlaySong(FMUSIC_MODULE *mod); -DLL_API signed char F_API FMUSIC_StopSong(FMUSIC_MODULE *mod); -DLL_API void F_API FMUSIC_StopAllSongs(); -DLL_API signed char F_API FMUSIC_SetZxxCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback); -DLL_API signed char F_API FMUSIC_SetRowCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int rowstep); -DLL_API signed char F_API FMUSIC_SetOrderCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int orderstep); -DLL_API signed char F_API FMUSIC_SetInstCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int instrument); -DLL_API signed char F_API FMUSIC_SetSample(FMUSIC_MODULE *mod, int sampno, FSOUND_SAMPLE *sptr); -DLL_API signed char F_API FMUSIC_OptimizeChannels(FMUSIC_MODULE *mod, int maxchannels, int minvolume); - -// Runtime song functions. -DLL_API signed char F_API FMUSIC_SetReverb(signed char reverb); // MIDI only. -DLL_API signed char F_API FMUSIC_SetOrder(FMUSIC_MODULE *mod, int order); -DLL_API signed char F_API FMUSIC_SetPaused(FMUSIC_MODULE *mod, signed char pause); -DLL_API signed char F_API FMUSIC_SetMasterVolume(FMUSIC_MODULE *mod, int volume); -DLL_API signed char F_API FMUSIC_SetPanSeperation(FMUSIC_MODULE *mod, float pansep); - -// Static song information functions. -DLL_API char * F_API FMUSIC_GetName(FMUSIC_MODULE *mod); -DLL_API signed char F_API FMUSIC_GetType(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetNumOrders(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetNumPatterns(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetNumInstruments(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetNumSamples(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetNumChannels(FMUSIC_MODULE *mod); -DLL_API FSOUND_SAMPLE * F_API FMUSIC_GetSample(FMUSIC_MODULE *mod, int sampno); -DLL_API int F_API FMUSIC_GetPatternLength(FMUSIC_MODULE *mod, int orderno); - -// Runtime song information. -DLL_API signed char F_API FMUSIC_IsFinished(FMUSIC_MODULE *mod); -DLL_API signed char F_API FMUSIC_IsPlaying(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetMasterVolume(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetGlobalVolume(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetOrder(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetPattern(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetSpeed(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetBPM(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetRow(FMUSIC_MODULE *mod); -DLL_API signed char F_API FMUSIC_GetPaused(FMUSIC_MODULE *mod); -DLL_API int F_API FMUSIC_GetTime(FMUSIC_MODULE *mod); - -#ifdef __cplusplus -} -#endif - -*/ - -#endif diff --git a/server/global/g_ai.c b/server/global/g_ai.c deleted file mode 100644 index c1234b46..00000000 --- a/server/global/g_ai.c +++ /dev/null @@ -1,1935 +0,0 @@ -// g_ai.c - -#include "g_local.h" - -bool FindTarget (edict_t *self); -extern cvar_t *maxclients; - -bool ai_checkattack (edict_t *self, float dist); -edict_t *medic_FindDeadMonster (edict_t *self); - -bool enemy_vis; -bool enemy_infront; -int enemy_range; -float enemy_yaw; - -// SeekEnemy is used to help a monster/actor navigate to its enemy. It's -// not by any means a complete solution - zigzag routes aren't handled at -// all. But in many situations this is a big improvement over standard AI - -bool SeekEnemy(edict_t *self) -{ - float angle, yaw, yaw_0; - int i; - trace_t tr1, tr2; - vec3_t target, vec; - - VectorSubtract(self->enemy->s.origin,self->s.origin,vec); - yaw_0 = vectoyaw(vec); - yaw_0 = anglemod( (int)(yaw_0/45)*45 ); - target[2] = self->enemy->s.origin[2]; - for(i=0; i<8; i++) - { - if(i % 2) - yaw = yaw_0 - (i+1)*22.5; - else - yaw = yaw_0 + i*22.5; - angle = yaw * (M_PI*2 / 360); - vec[0] = cos(angle); - vec[1] = sin(angle); - vec[2] = 0; - VectorMA(self->s.origin,256.,vec,target); - tr1 = gi.trace(self->s.origin,NULL,NULL,target,self,MASK_OPAQUE); - tr2 = gi.trace(self->enemy->s.origin,NULL,NULL,tr1.endpos,self->enemy,MASK_OPAQUE); - if(tr2.fraction == 1.0) - { - edict_t *thing; - - thing = SpawnThing(); - VectorCopy(tr1.endpos,thing->s.origin); - thing->touch_debounce_time = level.time + 5.0; - thing->target_ent = self; - ED_CallSpawn(thing); - // make it think a bit faster than normal 2 sec. so if monster - // sees enemy enroute he'll face enemy - thing->nextthink = level.time + 1.0; - self->movetarget = self->goalentity = thing; - self->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - self->monsterinfo.aiflags |= (AI_CHASE_THING | AI_SEEK_ENEMY); - VectorSubtract(thing->s.origin,self->s.origin,vec); - self->ideal_yaw = vectoyaw(vec); - // wait a while before first attack - if (!(self->monsterinfo.aiflags & AI_STAND_GROUND)) - AttackFinished (self, 1); - return true; - } - } - return false; -} - -/* -================= -AI_SetSightClient - -Called once each frame to set level.sight_client to the -player to be checked for in findtarget. - -If all clients are either dead or in notarget, sight_client -will be null. - -In coop games, sight_client will cycle between the clients. -================= -*/ -void AI_SetSightClient (void) -{ - edict_t *ent; - int start, check; - - if (level.sight_client == NULL) - start = 1; - else - start = level.sight_client - g_edicts; - - check = start; - while (1) - { - check++; - if (check > game.maxclients) - check = 1; - ent = &g_edicts[check]; - if (ent->inuse - && ent->health > 0 - && !(ent->flags & (FL_NOTARGET|FL_DISGUISED) ) ) - { - // If player is using func_monitor, make - // the sight_client = the fake player at the - // monitor currently taking the player's place. - // Do NOT do this for players using a - // target_monitor, though... in this case - // both player and fake player are ignored. - if(ent->client && ent->client->camplayer) - { - if(ent->client->spycam) - { - level.sight_client = ent->client->camplayer; - return; - } - } - else - { - level.sight_client = ent; - return; // got one - } - } - if (check == start) - { - level.sight_client = NULL; - return; // nobody to see - } - } -} - -//============================================================================ - -/* -============= -ai_move - -Move the specified distance at current facing. -This replaces the QC functions: ai_forward, ai_back, ai_pain, and ai_painforward -============== -*/ -void ai_move (edict_t *self, float dist) -{ - M_walkmove (self, self->s.angles[YAW], dist); -} - - -/* -============= -ai_stand - -Used for standing around and looking for players -Distance is for slight position adjustments needed by the animations -============== -*/ -void ai_stand (edict_t *self, float dist) -{ - vec3_t v; - - if (dist) - M_walkmove (self, self->s.angles[YAW], dist); - - if(self->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - if(!self->enemy || !self->enemy->inuse) - { - self->movetarget = self->goalentity = self->monsterinfo.leader; - self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - self->monsterinfo.pausetime = 0; - } - } - - if ( (self->monsterinfo.aiflags & AI_CHICKEN) ) - { - if ( (level.framenum - self->monsterinfo.chicken_framenum > 200) || - (self->enemy && (self->enemy->last_attacked_framenum > level.framenum - 2) ) ) - { - self->monsterinfo.aiflags &= ~(AI_CHICKEN | AI_STAND_GROUND); - self->monsterinfo.pausetime = 0; - if(self->enemy) - FoundTarget(self); - } - } - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - if (self->enemy && self->enemy->inuse) - { - float length; - - VectorSubtract (self->enemy->s.origin, self->s.origin, v); - length = VectorLength(v); - self->ideal_yaw = vectoyaw(v); - - if((level.time >= self->monsterinfo.rangetime) && (self->monsterinfo.aiflags & AI_RANGE_PAUSE)) - { - if((length < self->monsterinfo.ideal_range[0]) && (rand() & 3)) - self->monsterinfo.rangetime = level.time + 0.5; - if((length < self->monsterinfo.ideal_range[1]) && (length > self->monsterinfo.ideal_range[0]) && (rand() & 1)) - self->monsterinfo.rangetime = level.time + 0.2; - } - - if (self->s.angles[YAW] != self->ideal_yaw && self->monsterinfo.aiflags & AI_RANGE_PAUSE) - { - if(self->monsterinfo.rangetime < level.time) - { - // Lazarus: Don't run if we're still too close - if(self->monsterinfo.min_range > 0) - { - if(length > self->monsterinfo.min_range) - { - self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_RANGE_PAUSE); - self->monsterinfo.run (self); - } - } - else - { - self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_RANGE_PAUSE); - self->monsterinfo.run (self); - } - } - } - M_ChangeYaw (self); - ai_checkattack (self, 0); - if(!enemy_vis && (self->monsterinfo.aiflags & AI_RANGE_PAUSE)) - { - self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_RANGE_PAUSE); - self->monsterinfo.run (self); - } - } - else - FindTarget (self); - return; - } - - if (FindTarget (self)) - return; - - if (level.time > self->monsterinfo.pausetime) - { - // Lazarus: Solve problem of monsters pausing at path_corners, taking off in - // original direction - if(self->enemy && self->enemy->inuse) - { - VectorSubtract (self->enemy->s.origin, self->s.origin, v); - } - else if(self->goalentity) - { - VectorSubtract (self->goalentity->s.origin, self->s.origin, v); - } - else - { - self->monsterinfo.pausetime = level.time + random() * 15; - return; - } - self->ideal_yaw = vectoyaw (v); - - // Lazarus: Let misc_actors who are following their leader RUN even when not mad - if( (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) && (self->movetarget) && - (self->movetarget->inuse) ) - { - float R; - R = realrange(self,self->movetarget); - if(R > ACTOR_FOLLOW_RUN_RANGE) - self->monsterinfo.run (self); - else if(R > ACTOR_FOLLOW_STAND_RANGE || !self->movetarget->client) - self->monsterinfo.walk (self); - } - else - self->monsterinfo.walk (self); - return; - } - - if (!(self->spawnflags & SF_MONSTER_SIGHT) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time)) - { - if(self->monsterinfo.aiflags & AI_MEDIC) - abortHeal(self,false); - - if (self->monsterinfo.idle_time) - { - self->monsterinfo.idle (self); - self->monsterinfo.idle_time = level.time + 15 + random() * 15; - } - else - { - self->monsterinfo.idle_time = level.time + random() * 15; - } - } -} - - -void ai_walk (edict_t *self, float dist) -{ - // Lazarus: If we're following the leader and have no enemy, run to him - if ((!self->enemy) && (self->monsterinfo.aiflags & AI_FOLLOW_LEADER)) - self->movetarget = self->goalentity = self->monsterinfo.leader; - - M_MoveToGoal (self, dist); - - // check for noticing a player - if (FindTarget (self)) - return; - - if ((self->monsterinfo.search) && (level.time > self->monsterinfo.idle_time)) - { - if(self->monsterinfo.aiflags & AI_MEDIC) - abortHeal(self,false); - - if (self->monsterinfo.idle_time) - { - self->monsterinfo.search (self); - self->monsterinfo.idle_time = level.time + 15 + random() * 15; - } - else - { - self->monsterinfo.idle_time = level.time + random() * 15; - } - } -} - - -/* -============= -ai_charge - -Turns towards target and advances -Use this call with a distnace of 0 to replace ai_face -============== -*/ -void ai_charge (edict_t *self, float dist) -{ - vec3_t v; - - // Lazarus: Check for existence and validity of enemy. - // This is normally not necessary, but target_anger making - // monster mad at a static object (a pickup, for example) - // previously resulted in weirdness here - if(!self->enemy || !self->enemy->inuse) - return; - - VectorSubtract (self->enemy->s.origin, self->s.origin, v); - self->ideal_yaw = vectoyaw(v); - M_ChangeYaw (self); - if (dist) - M_walkmove (self, self->s.angles[YAW], dist); -} - - -/* -============= -ai_turn - -don't move, but turn towards ideal_yaw -Distance is for slight position adjustments needed by the animations -============= -*/ -void ai_turn (edict_t *self, float dist) -{ - if (dist) - M_walkmove (self, self->s.angles[YAW], dist); - - if (FindTarget (self)) - return; - - M_ChangeYaw (self); -} - - - -/* - -.enemy -Will be world if not currently angry at anyone. - -.movetarget -The next path spot to walk toward. If .enemy, ignore .movetarget. -When an enemy is killed, the monster will try to return to it's path. - -.hunt_time -Set to time + something when the player is in sight, but movement straight for -him is blocked. This causes the monster to use wall following code for -movement direction instead of sighting on the player. - -.ideal_yaw -A yaw angle of the intended direction, which will be turned towards at up -to 45 deg / state. If the enemy is in view and hunt_time is not active, -this will be the exact line towards the enemy. - -.pausetime -A monster will leave it's stand state and head towards it's .movetarget when -time > .pausetime. - -walkmove(angle, speed) primitive is all or nothing -*/ - -/* -============= -range - -returns the range catagorization of an entity reletive to self -0 melee range, will become hostile even if back is turned -1 visibility and infront, or visibility and show hostile -2 infront and show hostile -3 only triggered by damage -============= -*/ -int range (edict_t *self, edict_t *other) -{ - vec3_t v; - float len; - - VectorSubtract (self->s.origin, other->s.origin, v); - len = VectorLength (v); - if (len < MELEE_DISTANCE) - return RANGE_MELEE; - if (len < 500) - return RANGE_NEAR; - if (len < self->monsterinfo.max_range) - return RANGE_MID; - return RANGE_FAR; -} - -/* -============= -visible - -returns 1 if the entity is visible to self, even if not infront () -============= -*/ -bool visible (edict_t *self, edict_t *other) -{ - vec3_t spot1; - vec3_t spot2; - trace_t trace; - - VectorCopy (self->s.origin, spot1); - spot1[2] += self->viewheight; - VectorCopy (other->s.origin, spot2); - spot2[2] += other->viewheight; - trace = gi.trace (spot1, vec3_origin, vec3_origin, spot2, self, MASK_OPAQUE); - - // Lazarus: Take fog into account for monsters - - if ( (trace.fraction == 1.0) || (trace.ent == other)) - { - if( (level.active_fog) && (self->svflags & SVF_MONSTER) ) - { - fog_t *pfog; - float r; - float dw; - vec3_t v; - - pfog = &level.fog; - VectorSubtract(spot2,spot1,v); - r = VectorLength(v); - switch(pfog->Model) - { - case 1: - dw = pfog->Density/10000. * r; - self->monsterinfo.visibility = exp( -dw ); - break; - case 2: - dw = pfog->Density/10000. * r; - self->monsterinfo.visibility = exp( -dw*dw ); - break; - default: - if((r < pfog->Near) || (pfog->Near == pfog->Far)) - self->monsterinfo.visibility = 1.0; - else if(r > pfog->Far) - self->monsterinfo.visibility = 0.0; - else - self->monsterinfo.visibility = 1.0 - (r - pfog->Near)/(pfog->Far - pfog->Near); - break; - } -// if(developer->value) -// gi.dprintf("r=%g, vis=%g\n",r,self->monsterinfo.visibility); - if(self->monsterinfo.visibility < 0.05) - return false; - else - return true; - } - else - { - self->monsterinfo.visibility = 1.0; - return true; - } - } - return false; -} - - -/* -============= -infront - -returns 1 if the entity is in front (in sight) of self -============= -*/ -bool infront (edict_t *self, edict_t *other) -{ - vec3_t vec; - float dot; - vec3_t forward; - - AngleVectors (self->s.angles, forward, NULL, NULL); - VectorSubtract (other->s.origin, self->s.origin, vec); - VectorNormalize (vec); - dot = DotProduct (vec, forward); - - if (dot > 0.3) - return true; - return false; -} - -/* -============= -canReach - -similar to visible, but uses a different mask -============= -*/ -bool canReach (edict_t *self, edict_t *other) -{ - vec3_t spot1; - vec3_t spot2; - trace_t trace; - - VectorCopy (self->s.origin, spot1); - spot1[2] += self->viewheight; - VectorCopy (other->s.origin, spot2); - spot2[2] += other->viewheight; - trace = gi.trace (spot1, vec3_origin, vec3_origin, spot2, self, MASK_SHOT|MASK_WATER); - - if (trace.fraction == 1.0 || trace.ent == other) // PGM - return true; - return false; -} - -//============================================================================ - -void HuntTarget (edict_t *self) -{ - vec3_t vec; - - // Lazarus: avert impending disaster - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - - self->goalentity = self->enemy; - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.stand (self); - else - self->monsterinfo.run (self); - - // Lazarus - help dummies find their enemy, maybe. - if (!visible(self,self->enemy) && !(self->monsterinfo.aiflags & AI_SEEK_ENEMY)) - { - if(SeekEnemy(self)) - return; - } - VectorSubtract (self->enemy->s.origin, self->s.origin, vec); - self->ideal_yaw = vectoyaw(vec); - // wait a while before first attack - if (!(self->monsterinfo.aiflags & AI_STAND_GROUND)) - AttackFinished (self, 1); -} - -void FoundTarget (edict_t *self) -{ - edict_t *goodguy; - vec3_t v; -// trace_t tr; - - // Lazarus: avert impending disaster - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - - if (self->monsterinfo.aiflags & AI_CHICKEN) - return; - - // let other monsters see this monster for a while, but not if - // it's simply a reflection - if (self->enemy->client && !(self->enemy->flags & FL_REFLECT)) - { - self->enemy->flags &= ~FL_DISGUISED; - - level.sight_entity = self; - level.sight_entity_framenum = level.framenum; - level.sight_entity->light_level = 128; - - goodguy = NULL; - goodguy = G_Find(NULL,FOFS(dmgteam),"player"); - while(goodguy) - { - if(goodguy->health > 0) - { - if(!goodguy->enemy) - { - if(goodguy->monsterinfo.aiflags & AI_ACTOR) - { - // Can he see enemy? -// tr = gi.trace(goodguy->s.origin,vec3_origin,vec3_origin,self->enemy->s.origin,goodguy,MASK_OPAQUE); -// if(tr.fraction == 1.0) - if(gi.inPVS(goodguy->s.origin,self->enemy->s.origin)) - { - goodguy->monsterinfo.aiflags |= AI_FOLLOW_LEADER; - goodguy->monsterinfo.old_leader = NULL; - goodguy->monsterinfo.leader = self->enemy; - } - } - } - } - goodguy = G_Find(goodguy,FOFS(dmgteam),"player"); - } - } - self->show_hostile = level.time + 1; // wake up other monsters - VectorCopy(self->enemy->s.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; - } - // Lazarus: Huh? How come yaw for combattarget isn't set? - VectorSubtract(self->movetarget->s.origin,self->s.origin,v); - self->ideal_yaw = vectoyaw(v); - - // 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! - // Lazarus: Why, why, why???? This doesn't remove the point_combat, only makes it inaccessible - // to other monsters. - //self->movetarget->targetname = NULL; - self->monsterinfo.pausetime = 0; - - // run for it - self->monsterinfo.run (self); -} - - -/* -=========== -FindTarget - -Self is currently not attacking anything, so try to find a target - -Returns TRUE if an enemy was sighted - -When a player fires a missile, the point of impact becomes a fakeplayer so -that monsters that see the impact will respond as if they had seen the -player. - -To avoid spending too much time, only a single client (or fakeclient) is -checked each frame. This means multi player games will have slightly -slower noticing monsters. -============ -*/ -bool FindTarget (edict_t *self) -{ - edict_t *client=NULL; - bool heardit; - edict_t *reflection; - edict_t *self_reflection; - int r; - - if(self->monsterinfo.aiflags & (AI_CHASE_THING | AI_HINT_TEST)) - return false; - - if (self->monsterinfo.aiflags & AI_GOOD_GUY) - { - if (self->goalentity && self->goalentity->inuse && self->goalentity->classname) - { - if (self->goalentity->class_id == ENTITY_TARGET_ACTOR) - return false; - } - - // Lazarus: Look for monsters - if( !self->enemy ) - { - if( self->monsterinfo.aiflags & AI_FOLLOW_LEADER ) - { - int i; - edict_t *e; - edict_t *best=NULL; - vec_t dist, best_dist; - - best_dist = self->monsterinfo.max_range; - for(i=game.maxclients+1; iinuse) - continue; - if(!(e->svflags & SVF_MONSTER)) - continue; - if(e->svflags & SVF_NOCLIENT) - continue; - if(e->solid == SOLID_NOT) - continue; - if(e->monsterinfo.aiflags & AI_GOOD_GUY) - continue; - if(!visible(self,e)) - continue; - if ( self->monsterinfo.aiflags & AI_BRUTAL ) - { - if (e->health <= e->gib_health) - continue; - } - else if (e->health <= 0) - continue; - dist = realrange(self,e); - if(dist < best_dist) - { - best_dist = dist; - best = e; - } - } - if(best) - { - self->enemy = best; - FoundTarget(self); - return true; - } - } - return false; - } - else if (level.time < self->monsterinfo.pausetime ) - return false; - else { - if (!visible (self, self->enemy)) - return false; - else { - FoundTarget(self); - return true; - } - } - } - - // if we're going to a combat point, just proceed - if (self->monsterinfo.aiflags & AI_COMBAT_POINT) - return false; - -// if the first spawnflag bit is set, the monster will only wake up on -// really seeing the player, not another monster getting angry or hearing -// something - -// revised behavior so they will wake up if they "see" a player make a noise -// but not weapon impact/explosion noises - - heardit = false; - if ((level.sight_entity_framenum >= (level.framenum - 1)) && !(self->spawnflags & SF_MONSTER_SIGHT) ) - { - client = level.sight_entity; - if (client->enemy == self->enemy) - { - return false; - } - } - else if (level.disguise_violation_framenum > level.framenum) - { - client = level.disguise_violator; - } - else if (level.sound_entity_framenum >= (level.framenum - 1)) - { - client = level.sound_entity; - heardit = true; - } - else if (!(self->enemy) && (level.sound2_entity_framenum >= (level.framenum - 1)) && !(self->spawnflags & SF_MONSTER_SIGHT) ) - { - client = level.sound2_entity; - heardit = true; - } - else - { - client = level.sight_client; - if (!client) - return false; // no clients to get mad at - } - - // if the entity went away, forget it - if (!client || !client->inuse) - return false; - - // Lazarus - if(client->client && client->client->camplayer) - client = client->client->camplayer; - - if (client == self->enemy) - return true; // JDC false; - - // Lazarus: Force idle medics to look for dead monsters - if (!self->enemy && (self->class_id == ENTITY_MONSTER_MEDIC)) - { - if(medic_FindDeadMonster(self)) - return true; - } - - //PMM - hintpath coop fix - if ((self->monsterinfo.aiflags & AI_HINT_PATH) && (coop) && (coop->value)) - heardit = false; - // pmm - - if (client->client) - { - if (client->flags & FL_NOTARGET) - return false; - } - else if (client->svflags & SVF_MONSTER) - { - if (!client->enemy) - return false; - if (client->enemy->flags & FL_NOTARGET) - return false; - } - else if (heardit) - { - if (client->owner && (client->owner->flags & FL_NOTARGET)) - return false; - } - else - return false; - - reflection = NULL; - self_reflection = NULL; - if (level.num_reflectors) - { - int i; - edict_t *ref; - - for(i=0; i<6 && !reflection; i++) - { - ref = client->reflection[i]; - if(ref && visible(self,ref) && infront(self,ref)) - { - reflection = ref; - self_reflection = self->reflection[i]; - } - } - } - - if (!heardit) - { - r = range (self, client); - - if (r == RANGE_FAR) - return false; - -// this is where we would check invisibility - - // is client in a spot too dark to be seen? - if (client->light_level <= 5) - return false; - - if (!visible (self, client)) - { - vec3_t temp; - - if (!reflection) - return false; - - self->goalentity = self->movetarget = reflection; - VectorSubtract(reflection->s.origin,self->s.origin,temp); - self->ideal_yaw = vectoyaw(temp); - M_ChangeYaw (self); - // If MORON (=4) is set, then the reflection becomes the - // enemy. Otherwise if DUMMY (=8) is set, reflection - // becomes the enemy ONLY if the monster cannot see his - // own reflection in the same mirror. And if neither situation - // applies, then reflection is treated identically - // to a player noise. - // Don't do the MORON/DUMMY bit if SF_MONSTER_KNOWS_MIRRORS - // is set (set automatically for melee-only monsters, and - // turned on once other monsters have figured out the truth) - if(!(self->spawnflags & SF_MONSTER_KNOWS_MIRRORS)) - { - if(reflection->activator->spawnflags & 4) - { - self->monsterinfo.attack_state = 0; - self->enemy = reflection; - goto got_one; - } - if(reflection->activator->spawnflags & 8) - { - if(!self_reflection || !visible(self,self_reflection)) - { - self->monsterinfo.attack_state = 0; - self->enemy = reflection; - goto got_one; - } - } - } - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags &= ~AI_STAND_GROUND; - self->monsterinfo.run(self); - return false; - } - - if (reflection && !(self->spawnflags & SF_MONSTER_KNOWS_MIRRORS) && - !infront(self,client)) - { - // Client is visible but behind monster. - // If MORON or DUMMY for the parent func_reflect is set, - // attack the reflection (in the case of DUMMY, only - // if monster doesn't see himself in the same mirror) - if( (reflection->activator->spawnflags & 4) || - ( (reflection->activator->spawnflags & 8) && - (!self_reflection || !visible(self,self_reflection)) ) ) - { - vec3_t temp; - - self->goalentity = self->movetarget = reflection; - VectorSubtract(reflection->s.origin,self->s.origin,temp); - self->ideal_yaw = vectoyaw(temp); - M_ChangeYaw (self); - self->enemy = reflection; - goto got_one; - } - } - - if (!reflection) - { - if (r == RANGE_NEAR) - { - if (client->show_hostile < level.time && !infront (self, client)) - return false; - } - else if (r == RANGE_MID) - { - if (!infront (self, client)) - return false; - } - } - - self->enemy = client; - - if (self->enemy->class_id != ENTITY_PLAYER_NOISE) - { - self->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - - if (!self->enemy->client) - { - self->enemy = self->enemy->enemy; - if (!self->enemy->client) - { - self->enemy = NULL; - return false; - } - } - } - } - else // heardit - { - vec3_t temp; - - if (self->spawnflags & SF_MONSTER_SIGHT) - { - if (!visible (self, client)) - return false; - } - else if(!(client->flags & FL_REFLECT)) - { - if (!gi.inPHS(self->s.origin, client->s.origin)) - return false; - } - - VectorSubtract (client->s.origin, self->s.origin, temp); - - if (VectorLength(temp) > 1000) // too far to hear - { - return false; - } - - // check area portals - if they are different and not connected then we can't hear it - if (!(client->flags & FL_REFLECT)) - { - if (client->areanum != self->areanum) - if (!gi.AreasConnected(self->areanum, client->areanum)) - return false; - } - - self->ideal_yaw = vectoyaw(temp); - M_ChangeYaw (self); - - // hunt the sound for a bit; hopefully find the real player - self->monsterinfo.aiflags |= AI_SOUND_TARGET; - self->enemy = client; - } - -got_one: - -// -// got one -// - // PMM - if we got an enemy, we need to bail out of hint paths, so take over here - if (self->monsterinfo.aiflags & AI_HINT_PATH) - { - // this calls foundtarget for us - hintpath_stop (self); - } - else if(self->monsterinfo.aiflags & AI_MEDIC_PATROL) - { - medic_StopPatrolling (self); - } - else - { - FoundTarget (self); - } - // pmm - - if (!(self->monsterinfo.aiflags & AI_SOUND_TARGET) && (self->monsterinfo.sight)) - self->monsterinfo.sight (self, self->enemy); - - return true; -} - - -//============================================================================= - -/* -============ -FacingIdeal - -============ -*/ -bool FacingIdeal(edict_t *self) -{ - float delta; - - delta = anglemod(self->s.angles[YAW] - self->ideal_yaw); - if (delta > 45 && delta < 315) - return false; - return true; -} - - -//============================================================================= - -bool M_CheckAttack (edict_t *self) -{ - vec3_t spot1, spot2; - float chance; - trace_t tr; - - // Lazarus: Paranoia check - if (!self->enemy) - return false; - - if (self->enemy->health > 0) - { - // see if any entities are in the way of the shot - VectorCopy (self->s.origin, spot1); - spot1[2] += self->viewheight; - VectorCopy (self->enemy->s.origin, spot2); - spot2[2] += self->enemy->viewheight; - tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA|CONTENTS_WINDOW); - - // do we have a clear shot? - if (tr.ent != self->enemy) - { - if (!(self->enemy->flags & FL_REFLECT)) - return false; - if (tr.ent != world) - return false; - } - } - - // melee attack - if (enemy_range == RANGE_MELEE) - { - // don't always melee in easy mode - if (skill->value == 0 && (rand()&3) ) - return false; - if (self->monsterinfo.melee) - self->monsterinfo.attack_state = AS_MELEE; - else - self->monsterinfo.attack_state = AS_MISSILE; - return true; - } - -// missile attack - if (!self->monsterinfo.attack) - return false; - - if (level.time < self->monsterinfo.attack_finished) - return false; - - if (enemy_range == RANGE_FAR) - return false; - - if (self->enemy->flags == FL_REFLECT) - { - // no waiting for reflections - shoot 'em NOW - chance = 2.0; - } - else if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - chance = 0.4; - } - else if (enemy_range == RANGE_MELEE) - { - chance = 0.2; - } - else if (enemy_range == RANGE_NEAR) - { - chance = 0.1; - } - else if (enemy_range == RANGE_MID) - { - chance = 0.02; - } - else - return false; - - if (skill->value == 0) - chance *= 0.5; - else if (skill->value >= 2) - chance *= 2; - - if (random () < chance) - { - self->monsterinfo.attack_state = AS_MISSILE; - self->monsterinfo.attack_finished = level.time + 2*random(); - return true; - } - - if (self->flags & FL_FLY) - { - if (random() < 0.3) - self->monsterinfo.attack_state = AS_SLIDING; - else - self->monsterinfo.attack_state = AS_STRAIGHT; - } - - return false; -} - - -/* -============= -ai_run_melee - -Turn and close until within an angle to launch a melee attack -============= -*/ -void ai_run_melee(edict_t *self) -{ - self->ideal_yaw = enemy_yaw; - M_ChangeYaw (self); - - if (FacingIdeal(self)) - { - self->monsterinfo.melee (self); - self->monsterinfo.attack_state = AS_STRAIGHT; - } -} - - -/* -============= -ai_run_missile - -Turn in place until within an angle to launch a missile attack -============= -*/ -void ai_run_missile(edict_t *self) -{ - self->ideal_yaw = enemy_yaw; - M_ChangeYaw (self); - - if (FacingIdeal(self)) - { - self->monsterinfo.attack (self); - self->monsterinfo.attack_state = AS_STRAIGHT; - } -}; - - -/* -============= -ai_run_slide - -Strafe sideways, but stay at aproximately the same range -============= -*/ -void ai_run_slide(edict_t *self, float distance) -{ - float ofs; - - self->ideal_yaw = enemy_yaw; - M_ChangeYaw (self); - - if (self->monsterinfo.lefty) - ofs = 90; - else - ofs = -90; - - if (M_walkmove (self, self->ideal_yaw + ofs, distance)) - return; - - self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; - M_walkmove (self, self->ideal_yaw - ofs, distance); -} - - -/* -============= -ai_checkattack - -Decides if we're going to attack or do something else -used by ai_run and ai_stand -============= -*/ -bool ai_checkattack (edict_t *self, float dist) -{ - vec3_t temp; - bool hesDeadJim; - - // this causes monsters to run blindly to the combat point w/o firing - if (self->goalentity) - { - if (self->monsterinfo.aiflags & AI_COMBAT_POINT) - return false; - - if (self->monsterinfo.aiflags & AI_SOUND_TARGET) - { - if ((level.time - self->enemy->teleport_time) > 5.0) - { - if (self->goalentity == self->enemy) - if (self->movetarget) - self->goalentity = self->movetarget; - else - self->goalentity = NULL; - self->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - if (self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND) - self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - } - else - { - self->show_hostile = level.time + 1; - return false; - } - } - } - - enemy_vis = false; - -// see if the enemy is dead - hesDeadJim = false; - if ((!self->enemy) || (!self->enemy->inuse)) - { - hesDeadJim = true; - } - else if (self->monsterinfo.aiflags & AI_MEDIC) - { - if (self->enemy->health > 0) - { - hesDeadJim = true; - self->monsterinfo.aiflags &= ~AI_MEDIC; - } - } - else if (self->enemy->flags & FL_REFLECT) - { - hesDeadJim = false; - } - else - { - if (self->monsterinfo.aiflags & AI_BRUTAL) - { - // Lazarus: This value should be enemy class-dependent - //if (self->enemy->health <= -80) - if (self->enemy->health <= self->enemy->gib_health) - hesDeadJim = true; - } - else - { - if (self->enemy->health <= 0) - hesDeadJim = true; - } - } - - if (hesDeadJim) - { - self->enemy = NULL; - // FIXME: look all around for other targets - if (self->oldenemy && self->oldenemy->health > 0) - { - self->enemy = self->oldenemy; - self->oldenemy = NULL; - HuntTarget (self); - } - else - { - if (self->movetarget) - { - self->goalentity = self->movetarget; - - // Lazarus: Let misc_actors who are following their leader RUN even when not mad - if( (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) && - (self->movetarget) && - (self->movetarget->inuse) ) - { - float R; - - R = realrange(self,self->movetarget); - if(R > ACTOR_FOLLOW_RUN_RANGE) - self->monsterinfo.run (self); - else if(R > ACTOR_FOLLOW_STAND_RANGE || !self->movetarget->client) - self->monsterinfo.walk (self); - else { - self->monsterinfo.pausetime = level.time + 0.5; - self->monsterinfo.stand (self); - } - } - else - self->monsterinfo.walk (self); - } - else - { - // we need the pausetime otherwise the stand code - // will just revert to walking with no target and - // the monsters will wonder around aimlessly trying - // to hunt the world entity - self->monsterinfo.pausetime = level.time + 100000000; - self->monsterinfo.stand (self); - } - return true; - } - } - - self->show_hostile = level.time + 1; // wake up other monsters - -// check knowledge of enemy - - enemy_vis = visible(self, self->enemy); - - if (enemy_vis) - { - self->monsterinfo.search_time = level.time + 5; - VectorCopy (self->enemy->s.origin, self->monsterinfo.last_sighting); - } - -// look for other coop players here -// if (coop && self->monsterinfo.search_time < level.time) -// { -// if (FindTarget (self)) -// return true; -// } - - if (self->monsterinfo.aiflags & AI_CHICKEN) - { - if (enemy_vis) - { - if (ai_chicken(self,self->enemy)) - return false; - else - { - self->monsterinfo.aiflags &= ~(AI_CHICKEN | AI_STAND_GROUND); - self->monsterinfo.pausetime = 0; - FoundTarget(self); - } - } - else - return false; - } - - enemy_infront = infront(self, self->enemy); - enemy_range = range(self, self->enemy); - VectorSubtract (self->enemy->s.origin, self->s.origin, temp); - enemy_yaw = vectoyaw(temp); - - - // JDC self->ideal_yaw = enemy_yaw; - - if (self->monsterinfo.attack_state == AS_MISSILE) - { - ai_run_missile (self); - return true; - } - if (self->monsterinfo.attack_state == AS_MELEE) - { - ai_run_melee (self); - return true; - } - - // if enemy is not currently visible, we will never attack - if (!enemy_vis) - return false; - - if( self->monsterinfo.checkattack (self) ) - { - self->enemy->last_attacked_framenum = level.framenum; - return true; - } - else - return false; -} - - -#define HINT_PATH_START_TIME 3 -#define HINT_PATH_RESTART_TIME 5 - -/* -============= -ai_run - -The monster has an enemy it is trying to kill -============= -*/ -void ai_run (edict_t *self, float dist) -{ - vec3_t v; - edict_t *tempgoal; - edict_t *save; - bool new; - edict_t *marker; - float d1, d2; - trace_t tr; - vec3_t v_forward, v_right; - float left, center, right; - vec3_t left_target, right_target; - bool alreadyMoved = false; - bool gotcha=false; - edict_t *realEnemy; - - // if we're going to a combat point, just proceed - if ( self->monsterinfo.aiflags & (AI_COMBAT_POINT | AI_CHASE_THING | AI_HINT_TEST)) - { - M_MoveToGoal (self, dist); - return; - } - - if ( self->monsterinfo.aiflags & AI_MEDIC_PATROL ) - { - if (!FindTarget(self)) - { - M_MoveToGoal(self,dist); - return; - } - } - - // If currently mad at a reflection, AND we've already shot at it once, set - // flag indicating that this monster got suddenly smarter about mirrors, and - // turn him on the real enemy - if (self->enemy && (self->enemy->flags & FL_REFLECT)) - { - if( (self->enemy->last_attacked_framenum > 0) && - (self->enemy->last_attacked_framenum < level.framenum-5) ) - { - self->enemy->last_attacked_framenum = 0; - self->spawnflags |= SF_MONSTER_KNOWS_MIRRORS; - self->enemy = self->enemy->owner; - self->movetarget = self->goalentity = self->enemy; - VectorSubtract(self->enemy->s.origin,self->s.origin,v); - self->ideal_yaw = vectoyaw(v); - if(!alreadyMoved) - M_MoveToGoal(self,dist); - return; - } - } - - // Lazarus: If running at a reflection, go ahead, until source of reflection - // is visible - if (!self->enemy && self->movetarget && (self->movetarget->flags & FL_REFLECT)) - { - if( !visible(self,self->movetarget->owner)) - { - M_MoveToGoal(self,dist); - return; - } - } - - // Lazarus: If we're following the leader and have no enemy, go ahead - if ((!self->enemy) && (self->monsterinfo.aiflags & AI_FOLLOW_LEADER)) - { - self->movetarget = self->goalentity = self->monsterinfo.leader; - if(!self->movetarget) - { - self->monsterinfo.pausetime = level.time + 2; - self->monsterinfo.stand(self); - return; - } - self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - self->monsterinfo.pausetime = 0; - M_MoveToGoal (self, dist); - return; - } -//========== -//PGM - // if we're currently looking for a hint path - if (self->monsterinfo.aiflags & AI_HINT_PATH) - { - // determine direction to our destination hintpath. - // FIXME - is this needed EVERY time? I was having trouble with them - // sometimes not going after it, and this fixed it. -// VectorSubtract(self->movetarget->s.origin, self->s.origin, v); -// vectoangles(v, v_forward); -// self->ideal_yaw = v_forward[YAW]; -// gi.dprintf("seeking hintpath. origin: %s %0.1f\n", vtos(v), self->ideal_yaw); - M_MoveToGoal (self, dist); - if(!self->inuse) - return; // PGM - g_touchtrigger free problem -// return; - - // first off, make sure we're looking for the player, not a noise he made - if (self->enemy) - { - if (self->enemy->inuse) - { - if (self->enemy->class_id != ENTITY_PLAYER_NOISE) - realEnemy = self->enemy; - else if (self->enemy->owner) - realEnemy = self->enemy->owner; - else // uh oh, can't figure out enemy, bail - { - self->enemy = NULL; - hintpath_stop (self); - return; - } - } - else - { - self->enemy = NULL; - hintpath_stop (self); - return; - } - } - else - { - hintpath_stop (self); - return; - } - - if (coop && coop->value) - { - // if we're in coop, check my real enemy first .. if I SEE him, set gotcha to true - if (self->enemy && visible(self, realEnemy)) - gotcha = true; - else // otherwise, let FindTarget bump us out of hint paths, if appropriate - FindTarget(self); - } - else - { - // Lazarus: special case for medics with AI_MEDIC and AI_HINT_PATH set. If - // range is farther than MEDIC_MAX_HEAL_DISTANCE we essentially - // lie... pretend the enemy isn't seen. - if ( self->monsterinfo.aiflags & AI_MEDIC ) - { - if(realrange(self,realEnemy) > MEDIC_MAX_HEAL_DISTANCE) - { - // Since we're on a hint_path trying to get in position to - // heal monster, rather than actually healing him, - // allow more time - self->timestamp = level.time + MEDIC_TRY_TIME; - return; - } - } - - if(self->enemy && visible(self, realEnemy)) - gotcha = true; - } - - // if we see the player, stop following hintpaths. - if (gotcha) - { - // disconnect from hintpaths and start looking normally for players. - hintpath_stop (self); - } - return; - } -//PGM -//========== - - if (self->monsterinfo.aiflags & AI_SOUND_TARGET) - { - if (self->enemy) - VectorSubtract (self->s.origin, self->enemy->s.origin, v); - - if ((!self->enemy) || (VectorLength(v) < 64)) - { - self->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - self->monsterinfo.stand (self); - return; - } - - if (!(self->monsterinfo.aiflags & AI_SEEK_ENEMY)) - { - if(SeekEnemy(self)) - { - if(!alreadyMoved) - M_MoveToGoal(self,dist); - return; - } - } - - M_MoveToGoal (self, dist); - // PMM - prevent double moves for sound_targets - alreadyMoved = true; - // pmm - if(!self->inuse) - return; // PGM - g_touchtrigger free problem - - if (!FindTarget (self)) - return; - } - - if(ai_checkattack (self, dist)) - return; - - if (self->monsterinfo.attack_state == AS_SLIDING) - { - ai_run_slide (self, dist); - return; - } - - // Lazarus: If enemy is currently unseen, try our random vector - // business. - if (self->enemy && self->enemy->inuse && !enemy_vis && - !(self->monsterinfo.aiflags & (AI_SOUND_TARGET | AI_SEEK_ENEMY)) ) - { - if(SeekEnemy(self)) - { - if(!alreadyMoved) - M_MoveToGoal(self,dist); - return; - } - } - - if ((self->enemy) && (self->enemy->inuse) && (enemy_vis)) - { -// if (self.aiflags & AI_LOST_SIGHT) -// dprint("regained sight\n"); - if(!alreadyMoved) - M_MoveToGoal (self, dist); - if(!self->inuse) - return; - self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; - VectorCopy (self->enemy->s.origin, self->monsterinfo.last_sighting); - self->monsterinfo.trail_time = level.time; - return; - } - -//======= -//PGM - // if we've been looking (unsuccessfully) for the player for 3 seconds - if((self->monsterinfo.trail_time + HINT_PATH_START_TIME) <= level.time) - { - // and we haven't checked for valid hint paths in the last 5 seconds - if((self->monsterinfo.last_hint_time + HINT_PATH_RESTART_TIME) <= level.time) - { - // check for hint_paths. - self->monsterinfo.last_hint_time = level.time; - if(monsterlost_checkhint(self)) - return; - } - } -//PGM -//======= - - // coop will change to another enemy if visible - if (coop->value) - { // FIXME: insane guys get mad with this, which causes crashes! - if (FindTarget (self)) - return; - } - - // Lazarus: for medics, IF hint_paths are present then cut back a bit on max - // search time and let him go idle so he'll start tracking hint_paths - if (self->monsterinfo.search_time) - { - if ((self->class_id == ENTITY_MONSTER_MEDIC) && hint_paths_present) - { - if(developer->value) - gi.dprintf("medic search_time=%g\n",level.time - self->monsterinfo.search_time); - - if (level.time > (self->monsterinfo.search_time + 15)) - { - if(developer->value) - gi.dprintf("medic search timeout, going idle\n"); - - if(!alreadyMoved) - M_MoveToGoal (self, dist); - self->monsterinfo.search_time = 0; - if(self->goalentity == self->enemy) - self->goalentity = NULL; - if(self->movetarget == self->enemy) - self->movetarget = NULL; - self->enemy = self->oldenemy = NULL; - self->monsterinfo.pausetime = level.time + 2; - self->monsterinfo.stand(self); - return; - } - } - else if (level.time > (self->monsterinfo.search_time + 20)) - { - if(!alreadyMoved) - M_MoveToGoal (self, dist); - self->monsterinfo.search_time = 0; - return; - } - } - - save = self->goalentity; - tempgoal = G_Spawn(); - self->goalentity = tempgoal; - - new = false; - - if (!(self->monsterinfo.aiflags & AI_LOST_SIGHT)) - { - // just lost sight of the player, decide where to go first -// dprint("lost sight of player, last seen at "); dprint(vtos(self.last_sighting)); dprint("\n"); - self->monsterinfo.aiflags |= (AI_LOST_SIGHT | AI_PURSUIT_LAST_SEEN); - self->monsterinfo.aiflags &= ~(AI_PURSUE_NEXT | AI_PURSUE_TEMP); - new = true; - } - - if (self->monsterinfo.aiflags & AI_PURSUE_NEXT) - { - self->monsterinfo.aiflags &= ~AI_PURSUE_NEXT; -// dprint("reached current goal: "); dprint(vtos(self.origin)); dprint(" "); dprint(vtos(self.last_sighting)); dprint(" "); dprint(ftos(vlen(self.origin - self.last_sighting))); dprint("\n"); - - // give ourself more time since we got this far - self->monsterinfo.search_time = level.time + 5; - - if (self->monsterinfo.aiflags & AI_PURSUE_TEMP) - { -// dprint("was temp goal; retrying original\n"); - self->monsterinfo.aiflags &= ~AI_PURSUE_TEMP; - marker = NULL; - VectorCopy (self->monsterinfo.saved_goal, self->monsterinfo.last_sighting); - new = true; - } - else if (self->monsterinfo.aiflags & AI_PURSUIT_LAST_SEEN) - { - self->monsterinfo.aiflags &= ~AI_PURSUIT_LAST_SEEN; - marker = PlayerTrail_PickFirst (self); - } - else - { - marker = PlayerTrail_PickNext (self); - } - - if (marker) - { - VectorCopy (marker->s.origin, self->monsterinfo.last_sighting); - self->monsterinfo.trail_time = marker->timestamp; - self->s.angles[YAW] = self->ideal_yaw = marker->s.angles[YAW]; -// dprint("heading is "); dprint(ftos(self.ideal_yaw)); dprint("\n"); - -// debug_drawline(self.origin, self.last_sighting, 52); - new = true; - } - } - - VectorSubtract (self->s.origin, self->monsterinfo.last_sighting, v); - d1 = VectorLength(v); - if (d1 <= dist) - { - self->monsterinfo.aiflags |= AI_PURSUE_NEXT; - dist = d1; - } - - VectorCopy (self->monsterinfo.last_sighting, self->goalentity->s.origin); - - if (new) - { - tr = gi.trace(self->s.origin, self->mins, self->maxs, self->monsterinfo.last_sighting, self, MASK_PLAYERSOLID); - if (tr.fraction < 1) - { - VectorSubtract (self->goalentity->s.origin, self->s.origin, v); - d1 = VectorLength(v); - center = tr.fraction; - d2 = d1 * ((center+1)/2); - self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v); - AngleVectors(self->s.angles, v_forward, v_right, NULL); - - VectorSet(v, d2, -16, 0); - G_ProjectSource (self->s.origin, v, v_forward, v_right, left_target); - tr = gi.trace(self->s.origin, self->mins, self->maxs, left_target, self, MASK_PLAYERSOLID); - left = tr.fraction; - - VectorSet(v, d2, 16, 0); - G_ProjectSource (self->s.origin, v, v_forward, v_right, right_target); - tr = gi.trace(self->s.origin, self->mins, self->maxs, right_target, self, MASK_PLAYERSOLID); - right = tr.fraction; - - center = (d1*center)/d2; - if (left >= center && left > right) - { - if (left < 1) - { - VectorSet(v, d2 * left * 0.5, -16, 0); - G_ProjectSource (self->s.origin, v, v_forward, v_right, left_target); - } - VectorCopy (self->monsterinfo.last_sighting, self->monsterinfo.saved_goal); - self->monsterinfo.aiflags |= AI_PURSUE_TEMP; - VectorCopy (left_target, self->goalentity->s.origin); - VectorCopy (left_target, self->monsterinfo.last_sighting); - VectorSubtract (self->goalentity->s.origin, self->s.origin, v); - self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v); - } - else if (right >= center && right > left) - { - if (right < 1) - { - VectorSet(v, d2 * right * 0.5, 16, 0); - G_ProjectSource (self->s.origin, v, v_forward, v_right, right_target); - } - VectorCopy (self->monsterinfo.last_sighting, self->monsterinfo.saved_goal); - self->monsterinfo.aiflags |= AI_PURSUE_TEMP; - VectorCopy (right_target, self->goalentity->s.origin); - VectorCopy (right_target, self->monsterinfo.last_sighting); - VectorSubtract (self->goalentity->s.origin, self->s.origin, v); - self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v); - } - } - } - - M_MoveToGoal (self, dist); - if(!self->inuse) - return; - - G_FreeEdict(tempgoal); - - if (self) - self->goalentity = save; -} - -static int chase_angle[] = {270,450,225,495,540}; -bool ai_chicken (edict_t *self, edict_t *badguy) -{ - int i; - edict_t *thing; - vec3_t atk, dir, best_dir, end, forward; - vec_t travel, yaw; - vec3_t mins, maxs; - vec3_t testpos; - vec_t best_dist=0; - trace_t trace1, trace2; - - // No point in hiding from attacker if he's gone - if(!badguy || !badguy->inuse) - return false; - - if(!self || !self->inuse || (self->health <= 0)) - return false; - - if(!actorchicken->value) - return false; - - // If we've already been here, quit - if(self->monsterinfo.aiflags & AI_CHICKEN) - { - if(self->movetarget && (self->movetarget->class_id == ENTITY_THING)) - return true; - } - - VectorCopy(self->mins,mins); - mins[2] += 18; - if(mins[2] > 0) mins[2] = 0; - VectorCopy(self->maxs,maxs); - - // Find a vector that will hide the actor from his enemy - VectorCopy(badguy->s.origin,atk); - atk[2] += badguy->viewheight; - VectorClear(best_dir); - AngleVectors(self->s.angles,forward,NULL,NULL); - dir[2] = 0; - for(travel=512; travel>63 && best_dist == 0; travel /= 2) - { - for(i=0; i<5 && best_dist == 0; i++) - { - yaw = self->s.angles[YAW] + chase_angle[i]; - yaw = (int)(yaw/45)*45; - yaw = anglemod(yaw); - yaw *= M_PI/180; - dir[0] = cos(yaw); - dir[1] = sin(yaw); - VectorMA(self->s.origin,travel,dir,end); - trace1 = gi.trace(self->s.origin,mins,maxs,end,self,MASK_MONSTERSOLID); - // Test whether proposed position can be seen by badguy. Test - // isn't foolproof - tests against 1) new origin, 2) new origin + maxs, - // 3) new origin + mins, and 4) new origin + min x,y, max z. - trace2 = gi.trace(trace1.endpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - VectorAdd(trace1.endpos,self->maxs,testpos); - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - VectorAdd(trace1.endpos,self->mins,testpos); - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - testpos[2] = trace1.endpos[2] + self->maxs[2]; - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - best_dist = trace1.fraction * travel; - if(best_dist < 32) // not much point to this move - continue; - VectorCopy(dir,best_dir); - } - } - return false; - - if(best_dist < 32) - return false; - - // This snaps the angles, which may not be all that good but it sure - // is quicker than turning in place - vectoangles(best_dir,self->s.angles); - thing = SpawnThing(); - VectorMA(self->s.origin,best_dist,best_dir,thing->s.origin); - thing->touch_debounce_time = level.time + 3.0; - thing->target_ent = self; - ED_CallSpawn(thing); - self->movetarget = self->goalentity = thing; - self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags |= (AI_CHASE_THING | AI_CHICKEN); - gi.linkentity(self); - self->monsterinfo.run(self); - self->monsterinfo.chicken_framenum = level.framenum; - return true; -} diff --git a/server/global/g_chase.c b/server/global/g_chase.c deleted file mode 100644 index 2a559bb6..00000000 --- a/server/global/g_chase.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "g_local.h" - -void UpdateChaseCam(edict_t *ent) -{ - vec3_t o, ownerv, goal; - edict_t *targ; - vec3_t forward, right; - trace_t trace; - int i; - vec3_t oldgoal; - vec3_t angles; - - // is our chase target gone? - if (!ent->client->chase_target->inuse - || ent->client->chase_target->client->resp.spectator) { - edict_t *old = ent->client->chase_target; - ChaseNext(ent); - if (ent->client->chase_target == old) { - ent->client->chase_target = NULL; - ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - return; - } - } - - targ = ent->client->chase_target; - - VectorCopy(targ->s.origin, ownerv); - VectorCopy(ent->s.origin, oldgoal); - - ownerv[2] += targ->viewheight; - - VectorCopy(targ->client->v_angle, angles); - if (angles[PITCH] > 56) - angles[PITCH] = 56; - AngleVectors (angles, forward, right, NULL); - VectorNormalize(forward); - VectorMA(ownerv, -30, forward, o); - - if (o[2] < targ->s.origin[2] + 20) - o[2] = targ->s.origin[2] + 20; - - // jump animation lifts - if (!targ->groundentity) - o[2] += 16; - - trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID); - - VectorCopy(trace.endpos, goal); - - VectorMA(goal, 2, forward, goal); - - // pad for floors and ceilings - VectorCopy(goal, o); - o[2] += 6; - trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); - if (trace.fraction < 1) { - VectorCopy(trace.endpos, goal); - goal[2] -= 6; - } - - VectorCopy(goal, o); - o[2] -= 6; - trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); - if (trace.fraction < 1) { - VectorCopy(trace.endpos, goal); - goal[2] += 6; - } - - if (targ->deadflag) - ent->client->ps.pmove.pm_type = PM_DEAD; - else - ent->client->ps.pmove.pm_type = PM_FREEZE; - - VectorCopy(goal, ent->s.origin); - for (i=0 ; i<3 ; i++) - ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]); - - if (targ->deadflag) { - ent->client->ps.viewangles[ROLL] = 40; - ent->client->ps.viewangles[PITCH] = -15; - ent->client->ps.viewangles[YAW] = targ->client->killer_yaw; - } else { - VectorCopy(targ->client->v_angle, ent->client->ps.viewangles); - VectorCopy(targ->client->v_angle, ent->client->v_angle); - } - - ent->viewheight = 0; - ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - gi.linkentity(ent); -} - -void ChaseNext(edict_t *ent) -{ - int i; - edict_t *e; - - if (!ent->client->chase_target) - return; - - i = ent->client->chase_target - g_edicts; - do { - i++; - if (i > maxclients->value) - i = 1; - e = g_edicts + i; - if (!e->inuse) - continue; - if (!e->client->resp.spectator) - break; - } while (e != ent->client->chase_target); - - ent->client->chase_target = e; - ent->client->update_chase = true; -} - -void ChasePrev(edict_t *ent) -{ - int i; - edict_t *e; - - if (!ent->client->chase_target) - return; - - i = ent->client->chase_target - g_edicts; - do { - i--; - if (i < 1) - i = maxclients->value; - e = g_edicts + i; - if (!e->inuse) - continue; - if (!e->client->resp.spectator) - break; - } while (e != ent->client->chase_target); - - ent->client->chase_target = e; - ent->client->update_chase = true; -} - -void GetChaseTarget(edict_t *ent) -{ - int i; - edict_t *other; - - for (i = 1; i <= maxclients->value; i++) { - other = g_edicts + i; - if (other->inuse && !other->client->resp.spectator) { - ent->client->chase_target = other; - ent->client->update_chase = true; - UpdateChaseCam(ent); - return; - } - } - gi.centerprintf(ent, "No other players to chase."); -} - diff --git a/server/global/g_combat.c b/server/global/g_combat.c deleted file mode 100644 index 674874ff..00000000 --- a/server/global/g_combat.c +++ /dev/null @@ -1,1104 +0,0 @@ -// g_combat.c - -#include "g_local.h" - -void HuntTarget (edict_t *); -void M_SetEffects (edict_t *ent); -/* -ROGUE -clean up heal targets for medic -*/ -void cleanupHealTarget (edict_t *ent) -{ - ent->monsterinfo.healer = NULL; - ent->takedamage = DAMAGE_YES; - ent->monsterinfo.aiflags &= ~AI_RESURRECTING; - M_SetEffects (ent); -} - -/* -============ -CanDamage - -Returns true if the inflictor can directly damage the target. Used for -explosions and melee attacks. -============ -*/ -bool CanDamage (edict_t *targ, edict_t *inflictor) -{ - vec3_t dest; - trace_t trace; - -// bmodels need special checking because their origin is 0,0,0 - if (targ->movetype == MOVETYPE_PUSH) - { - VectorAdd (targ->absmin, targ->absmax, dest); - VectorScale (dest, 0.5, dest); - trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); - if (trace.fraction == 1.0) - return true; - if (trace.ent == targ) - return true; - return false; - } - - trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID); - if (trace.fraction == 1.0 || trace.ent == targ) - return true; - - // Lazarus: This is kinda cheesy, but avoids doing goofy things in a map to make this work. If a LOS - // from inflictor to targ is blocked by a func_tracktrain, AND the targ is riding/driving - // the tracktrain, go ahead and hurt him. - - if(trace.ent && (trace.ent->flags & FL_TRACKTRAIN) && ((trace.ent->owner == targ) || (targ->groundentity == trace.ent)) ) - return true; - - VectorCopy (targ->s.origin, dest); - dest[0] += 15.0; - dest[1] += 15.0; - trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); - if (trace.fraction == 1.0 || trace.ent == targ) - return true; - - VectorCopy (targ->s.origin, dest); - dest[0] += 15.0; - dest[1] -= 15.0; - trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); - if (trace.fraction == 1.0 || trace.ent == targ) - return true; - - VectorCopy (targ->s.origin, dest); - dest[0] -= 15.0; - dest[1] += 15.0; - trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); - if (trace.fraction == 1.0 || trace.ent == targ) - return true; - - VectorCopy (targ->s.origin, dest); - dest[0] -= 15.0; - dest[1] -= 15.0; - trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); - if (trace.fraction == 1.0 || trace.ent == targ) - return true; - - - return false; -} - - -/* -============ -Killed -============ -*/ -void misc_deadsoldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); -void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - if (targ->health < -999) - targ->health = -999; - - if (targ->monsterinfo.aiflags & AI_MEDIC) - { - if (targ->enemy) // god, I hope so - { - cleanupHealTarget (targ->enemy); - } - - // clean up self - targ->monsterinfo.aiflags &= ~AI_MEDIC; - targ->enemy = attacker; - } - else - { - targ->enemy = attacker; - } - - if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD)) - { - if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY) ) - { - level.killed_monsters++; - if (coop->value && attacker->client) - attacker->client->resp.score++; - // medics won't heal monsters that they kill themselves - if (attacker->class_id == ENTITY_MONSTER_MEDIC) - targ->owner = attacker; - } - } - - if (targ->movetype == MOVETYPE_PUSH || targ->movetype == MOVETYPE_STOP || targ->movetype == MOVETYPE_NONE) - { // doors, triggers, etc - targ->die (targ, inflictor, attacker, damage, point); - return; - } - - if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD)) - { - targ->touch = NULL; - monster_death_use (targ); - } - - if (inflictor->movetype == MOVETYPE_PUSH) - { - // Lazarus - Die function won't gib NO_GIB monsters... blow 'em up - if((targ->die != misc_deadsoldier_die) && (targ->spawnflags & SF_MONSTER_NOGIB)) - { - BecomeExplosion1(targ); - return; - } - } - - // Lazarus: disengage from tracktrain - if (targ->vehicle && (targ->vehicle->flags & FL_TRACKTRAIN)) - tracktrain_disengage(targ->vehicle); - - targ->die (targ, inflictor, attacker, damage, point); -} - - -/* -================ -SpawnDamage -modified for Lazarus: -damage removed since it isn't used -added color for monster blood -================ -*/ -void SpawnDamage (int type, vec3_t origin, vec3_t normal) -{ - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE (type); - WRITE_COORD (origin); - WRITE_DIR (normal); - MESSAGE_SEND (MSG_PVS, origin, NULL); - - if(level.num_reflectors) - ReflectSparks(type,origin,normal); -} - -int BloodType (int index) -{ - switch (index) { - case 1: - return TE_GREENBLOOD; - case 2: - return TE_SPARKS; - default: - return TE_BLOOD; - } -} - -/* -============ -T_Damage - -targ entity that is being damaged -inflictor entity that is causing the damage -attacker entity that caused the inflictor to damage targ - example: targ=monster, inflictor=rocket, attacker=player - -dir direction of the attack -point point at which the damage is being inflicted -normal normal vector from that point -damage amount of damage being inflicted -knockback force to be applied against targ as a result of the damage - -dflags these flags are used to control how T_Damage works - DAMAGE_RADIUS damage was indirect (from a nearby explosion) - DAMAGE_NO_ARMOR armor does not protect from this damage - DAMAGE_ENERGY damage is from an energy based weapon - DAMAGE_NO_KNOCKBACK do not affect velocity, just view angles - DAMAGE_BULLET damage is from a bullet (used for ricochets) - DAMAGE_NO_PROTECTION kills godmode, armor, everything -============ -*/ -static int CheckPowerArmor (edict_t *ent, vec3_t point, vec3_t normal, int damage, int dflags) -{ - gclient_t *client; - int save; - int power_armor_type; - int index; - int damagePerCell; - int pa_te_type; - int power=0; - int power_used; - - if (!damage) - return 0; - - client = ent->client; - - if (dflags & DAMAGE_NO_ARMOR) - return 0; - - if (client) - { - power_armor_type = PowerArmorType (ent); - if (power_armor_type != POWER_ARMOR_NONE) - { - index = cells_index; - power = client->pers.inventory[index]; - } - } - else if (ent->svflags & SVF_MONSTER) - { - power_armor_type = ent->monsterinfo.power_armor_type; - power = ent->monsterinfo.power_armor_power; - } - else - return 0; - - if (power_armor_type == POWER_ARMOR_NONE) - return 0; - if (!power) - return 0; - - if (power_armor_type == POWER_ARMOR_SCREEN) - { - vec3_t vec; - float dot; - vec3_t forward; - - // only works if damage point is in front - AngleVectors (ent->s.angles, forward, NULL, NULL); - VectorSubtract (point, ent->s.origin, vec); - VectorNormalize (vec); - dot = DotProduct (vec, forward); - if (dot <= 0.3) - return 0; - - damagePerCell = 1; - pa_te_type = TE_SCREEN_SPARKS; - damage = damage / 3; - } - else - { - damagePerCell = 2; - pa_te_type = TE_SHIELD_SPARKS; - damage = (2 * damage) / 3; - } - - save = power * damagePerCell; - if (!save) - return 0; - if (save > damage) - save = damage; - - SpawnDamage (pa_te_type, point, normal); - ent->powerarmor_time = level.time + 0.2; - - power_used = save / damagePerCell; - - if (client) - client->pers.inventory[index] -= power_used; - else - ent->monsterinfo.power_armor_power -= power_used; - return save; -} - -static int CheckArmor (edict_t *ent, vec3_t point, vec3_t normal, int damage, int te_sparks, int dflags) -{ - gclient_t *client; - int save; - int index; - gitem_t *armor; - - if (!damage) - return 0; - - client = ent->client; - - if (!client) - return 0; - - if (dflags & DAMAGE_NO_ARMOR) - return 0; - - index = ArmorIndex (ent); - if (!index) - return 0; - - armor = GetItemByIndex (index); - - if (dflags & DAMAGE_ENERGY) - save = ceil(((gitem_armor_t *)armor->info)->energy_protection*damage); - else - save = ceil(((gitem_armor_t *)armor->info)->normal_protection*damage); - if (save >= client->pers.inventory[index]) - save = client->pers.inventory[index]; - - if (!save) - return 0; - - client->pers.inventory[index] -= save; - SpawnDamage (te_sparks, point, normal); - - return save; -} - -void monster_start_go (edict_t *self); -void target_animate(edict_t *); -void DefendMyFriend (edict_t *self, edict_t *enemy) -{ - self->spawnflags &= ~(SF_MONSTER_AMBUSH | SF_MONSTER_SIGHT); - self->enemy = enemy; - self->monsterinfo.aiflags |= AI_TARGET_ANGER; - FoundTarget (self); -} - -void CallMyFriends (edict_t *targ, edict_t *attacker) -{ - edict_t *teammate; - - if(!targ || !attacker) - return; - - // Lazarus dmgteam stuff - if( (attacker->client && !(attacker->flags & FL_NOTARGET)) || (attacker->svflags & SVF_MONSTER)) - { // the attacker is a player or a monster - if( (targ->svflags & SVF_MONSTER) && (targ->dmgteam) && (targ->health > 0) ) - { // the target is a live monster on a dmgteam - if( !attacker->dmgteam || strcmp(targ->dmgteam,attacker->dmgteam) ) - { // attacker is not on same dmgteam as target - if( !strcasecmp(targ->dmgteam,"player") && attacker->client ) - { // Target is a GOOD_GUY, attacked by the player. Allow self-defense, - // but don't get other dmgteam teammates involved. - // Special case for misc_actors - if ACTOR_BAD_GUY isn't set, - // actor stays on the same team and only taunts player - if(!(targ->monsterinfo.aiflags & AI_ACTOR) || (targ->spawnflags & SF_ACTOR_BAD_GUY)) - { - targ->enemy = targ->movetarget = targ->goalentity = attacker; - targ->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; - if(visible(targ,targ->enemy)) - FoundTarget(targ); - else - HuntTarget(targ); - } - } - else if( !(targ->svflags & SVF_MONSTER) || !(attacker->svflags & SVF_MONSTER) || - (targ->monsterinfo.aiflags & AI_FREEFORALL) || - ((targ->monsterinfo.aiflags & AI_GOOD_GUY) != (attacker->monsterinfo.aiflags & AI_GOOD_GUY)) ) - { - // Either target is not a monster, or attacker is not a monster, or - // they're both monsters but one is AI_GOOD_GUY and the other is not, - // or we've turned the game into a free-for-all with a target_monsterbattle - teammate = G_Find(NULL,FOFS(dmgteam),targ->dmgteam); - while(teammate) - { - if(teammate != targ) - { - if(teammate->svflags & SVF_MONSTER) - { - if(teammate->health > 0 && (teammate->enemy != attacker) && !(teammate->monsterinfo.aiflags & AI_CHASE_THING)) - { - if(!teammate->enemy || !teammate->enemy->dmgteam || !attacker->dmgteam ) - { - // If either 1) this teammate doesn't currently have an enemy, - // or 2) the teammate's enemy is not a member of a dmgteam - // or 3) the attacker is not a member of a dmgteam - // then set the attacker as the enemy of this teammate - DefendMyFriend(teammate,attacker); - } - else if(strcmp(teammate->enemy->dmgteam,attacker->dmgteam)) - { - // attacker is a member of a team different than the - // current enemy - DefendMyFriend(teammate,attacker); - } - } - } - else if(!(teammate->svflags & SVF_DEADMONSTER)) - G_UseTargets(teammate,attacker); - } - teammate = G_Find(teammate,FOFS(dmgteam),targ->dmgteam); - } - } - } - } - } - if( targ->client && (attacker->svflags & SVF_MONSTER) ) - { - // target is player; attacker is monster... alert "good guys", if any -// trace_t tr; - edict_t *teammate = NULL; - teammate = G_Find(NULL,FOFS(dmgteam),"player"); - while(teammate) - { - if((teammate->health > 0) && !(teammate->monsterinfo.aiflags & AI_CHASE_THING) && (teammate != attacker)) - { - // Can teammate see player? -// tr = gi.trace(teammate->s.origin,vec3_origin,vec3_origin,targ->s.origin,teammate,MASK_OPAQUE); -// if(tr.fraction == 1.0) - if(gi.inPVS(teammate->s.origin,targ->s.origin)) - { - teammate->enemy = attacker; - FoundTarget(teammate); - if(teammate->monsterinfo.aiflags & AI_ACTOR) - { - teammate->monsterinfo.aiflags |= AI_FOLLOW_LEADER; - teammate->monsterinfo.old_leader = NULL; - teammate->monsterinfo.leader = targ; - } - } - } - teammate = G_Find(teammate,FOFS(dmgteam),"player"); - } - } - // If player attacks a GOODGUY, turn GOODGUY stuff off - if (attacker->client && (targ->svflags & SVF_MONSTER) && (targ->spawnflags & SF_MONSTER_GOODGUY)) - { - if(!(targ->monsterinfo.aiflags & AI_ACTOR) || (targ->spawnflags & SF_ACTOR_BAD_GUY)) - { - targ->spawnflags &= ~SF_MONSTER_GOODGUY; - targ->monsterinfo.aiflags &= ~(AI_GOOD_GUY + AI_FOLLOW_LEADER); - if(targ->dmgteam && !strcasecmp(targ->dmgteam,"player")) - targ->dmgteam = NULL; - } - } - // 1.6.1.3 change - one chance and one chance only to call friends -/* if(targ->dmgteam) - if(strcasecmp(targ->dmgteam,"player")) - targ->dmgteam = NULL; */ -} - -void M_ReactToDamage (edict_t *targ, edict_t *attacker) -{ - bool is_turret; - - if( targ->health <= 0 ) - return; - - // If targ is currently chasing a "thing" or we're running a hint_path test, he - // doesn't really care what else is happening - if (targ->monsterinfo.aiflags & (AI_CHASE_THING | AI_HINT_TEST)) - return; - - // If targ is a robot camera, ignore damage - if (targ->flags & FL_ROBOT) - return; - - is_turret = (attacker->class_id == ENTITY_TURRET_BREACH); - - targ->spawnflags &= ~(SF_MONSTER_AMBUSH | SF_MONSTER_SIGHT); // 1.6.1.3 - - // Lazarus - monsters will get mad at and attack turrets. - // For environmental effects (lava, lasers, etc.) - evade - if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER) && !is_turret && - !(targ->monsterinfo.aiflags & AI_DUCKED) ) - { - if(!targ->movetarget || (targ->movetarget->class_id != ENTITY_THING) ) - { - int i; - edict_t *thing; - vec3_t atk, dir, best_dir, end, forward; - vec3_t mins, maxs; - vec_t dist, run; - vec_t best_dist=0; - trace_t trace1, trace2; - - VectorCopy(targ->mins,mins); - mins[2] += 16; // max step height? not sure about this - if(mins[2] > 0) mins[2] = 0; - VectorCopy(targ->maxs,maxs); - if( (attacker==world) || - (attacker->class_id == ENTITY_FUNC_DOOR) || - (attacker->class_id == ENTITY_FUNC_WATER) || - (attacker->class_id == ENTITY_FUNC_PUSHABLE) ) - { - // Just send the monster straight ahead and hope for the best. - thing = SpawnThing(); - VectorCopy(targ->s.angles,thing->s.angles); - AngleVectors(targ->s.angles,dir,NULL,NULL); - for(i=0; i<5; i++) { - dir[2] = 0.1*i; - VectorNormalize(dir); - VectorMA(targ->s.origin,8192,dir,end); - trace1 = gi.trace(targ->s.origin,mins,maxs,end,targ,MASK_MONSTERSOLID); - dist = trace1.fraction * 8192; - if(dist > best_dist) { - best_dist = dist; - VectorCopy(dir,best_dir); - } - } - } - else if(attacker->class_id == ENTITY_TARGET_LASER) - { - // Send the monster in a direction perpendicular to laser - // path, whichever direction is closest to current angles - thing = SpawnThing(); - if(attacker->movedir[2] > 0.7) - { - // Just move straight ahead and hope for the best - AngleVectors(targ->s.angles,best_dir,NULL,NULL); - } - else - { - VectorCopy(attacker->movedir,best_dir); - best_dir[2] = best_dir[0]; - best_dir[0] = -best_dir[1]; - best_dir[1] = best_dir[2]; - best_dir[2] = 0; - AngleVectors(targ->s.angles,dir,NULL,NULL); - if(DotProduct(best_dir,dir) < 0) - VectorNegate(best_dir,best_dir); - } - } - else - { - // Attacked by a point entity or moving brush model - // not covered above. Find a vector that will hide the - // monster from the attacker. - if(!VectorLength(attacker->size)) { - // point entity - VectorCopy(attacker->s.origin,atk); - } else { - // brush model... can't rely on origin - VectorMA(attacker->mins,0.5,attacker->size,atk); - } - VectorClear(best_dir); - AngleVectors(targ->s.angles,forward,NULL,NULL); - for(i=0; i<32 && best_dist == 0; i++) { - // Weight escape route tests in favor of forward-facing direction - if(random() > 0.5) { - dir[0] = forward[0] + 0.5*crandom(); - dir[1] = forward[1] + 0.5*crandom(); - dir[2] = forward[2]; - } else { - dir[0] = crandom(); - dir[1] = crandom(); - dir[2] = 0; - } - VectorNormalize(dir); - VectorMA(targ->s.origin,8192,dir,end); - trace1 = gi.trace(targ->s.origin,mins,maxs,end,targ,MASK_MONSTERSOLID); - trace2 = gi.trace(trace1.endpos,NULL,NULL,atk,targ,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - dist = trace1.fraction * 8192; - if(dist > best_dist) { - best_dist = dist; - VectorCopy(dir,best_dir); - } - } - if(best_dist == 0.) - return; - thing = SpawnThing(); - vectoangles(best_dir,thing->s.angles); - } - if( (attacker->class_id == ENTITY_FUNC_DOOR) || - (attacker->class_id == ENTITY_FUNC_PUSHABLE) ) - run = 256; - else - run = 8192; - VectorMA(targ->s.origin,run,best_dir,end); - trace1 = gi.trace(targ->s.origin,mins,maxs,end,targ,MASK_MONSTERSOLID); - dist = trace1.fraction * run; - VectorMA(targ->s.origin, dist, best_dir, thing->s.origin); - // If monster already has an enemy, use a short lifespan for thing - if(targ->enemy) - thing->touch_debounce_time = level.time + 2.0; - else - thing->touch_debounce_time = level.time + max(5.0,dist/50.); - thing->target_ent = targ; - ED_CallSpawn(thing); - targ->movetarget = targ->goalentity = thing; - targ->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - targ->monsterinfo.aiflags |= AI_CHASE_THING; - targ->monsterinfo.run(targ); - } - return; - } - - // Lazarus: If in a no-win situation, actors run away - if (targ->monsterinfo.aiflags & AI_ACTOR) - { - if (targ->health < targ->max_health/3) - { - if (attacker->health > attacker->max_health/2) - { - if (attacker->health > targ->health) - { - if(ai_chicken(targ,attacker)) - return; - } - } - } - } - - if (attacker == targ || attacker == targ->enemy) - return; - - // if we are a good guy monster and our attacker is a player - // or another good guy, do not get mad at them - if (targ->monsterinfo.aiflags & AI_GOOD_GUY) - { - if (attacker->client || (attacker->monsterinfo.aiflags & AI_GOOD_GUY)) - return; - } - -//PGM - // if we're currently mad at something a target_anger made us mad at, ignore - // damage - if (targ->enemy && (targ->monsterinfo.aiflags & AI_TARGET_ANGER)) - { - float percentHealth; - - // make sure whatever we were pissed at is still around. - if(targ->enemy->inuse) - { - percentHealth = (float)(targ->health) / (float)(targ->max_health); - if( targ->enemy->inuse && (percentHealth > 0.33)) - return; - } - - // remove the target anger flag - targ->monsterinfo.aiflags &= ~AI_TARGET_ANGER; - } -//PGM - -// PMM -// if we're healing someone, do like above and try to stay with them - if ((targ->enemy) && (targ->monsterinfo.aiflags & AI_MEDIC)) - { - float percentHealth; - - percentHealth = (float)(targ->health) / (float)(targ->max_health); - // ignore it some of the time - if( targ->enemy->inuse && percentHealth > 0.25) - return; - - // remove the medic flag - targ->monsterinfo.aiflags &= ~AI_MEDIC; - cleanupHealTarget (targ->enemy); - } -// PMM - - // we now know that we are not both good guys - - // if attacker is a client, get mad at them because he's good and we're not - if (attacker->client || is_turret) - { - targ->monsterinfo.aiflags &= ~AI_SOUND_TARGET; - - // this can only happen in coop (both new and old enemies are clients) - // only switch if can't see the current enemy - if (targ->enemy && targ->enemy->client) - { - if (visible(targ, targ->enemy)) - { - targ->oldenemy = attacker; - return; - } - targ->oldenemy = targ->enemy; - } - targ->enemy = attacker; - if(visible(targ,targ->enemy)) - FoundTarget (targ); - else - HuntTarget (targ); - return; - } - - // it's the same base (walk/swim/fly) type and a different classname and it's not a tank - // (they spray too much), get mad at them - if (((targ->flags & (FL_FLY|FL_SWIM)) == (attacker->flags & (FL_FLY|FL_SWIM))) && - (strcmp (targ->classname, attacker->classname) != 0) && - (attacker->class_id != ENTITY_MONSTER_TANK) && - (attacker->class_id != ENTITY_MONSTER_SUPERTANK) && - (attacker->class_id != ENTITY_MONSTER_MAKRON) && - (attacker->class_id != ENTITY_MONSTER_JORG) ) - { - // Lazarus: Check IGNORE_SHOTS spawnflag for attacker. If set AND - // targ and attacker have same GOODGUY setting, don't respond - // to attacks. - if( ( (targ->spawnflags & SF_MONSTER_GOODGUY) != (attacker->spawnflags & SF_MONSTER_GOODGUY) ) || - !(attacker->spawnflags & SF_MONSTER_IGNORESHOTS) ) - { - if (targ->enemy && targ->enemy->client) - targ->oldenemy = targ->enemy; - targ->enemy = attacker; - if(visible(targ,targ->enemy)) - FoundTarget (targ); - else - HuntTarget (targ); - return; - } - } - // if they *meant* to shoot us, then shoot back - else if (attacker->enemy == targ) - { - if (targ->enemy && targ->enemy->client) - targ->oldenemy = targ->enemy; - targ->enemy = attacker; - if(visible(targ,targ->enemy)) - FoundTarget (targ); - else - HuntTarget (targ); - return; - } - // otherwise get mad at whoever they are mad at (help our buddy) unless it is us! - else if (attacker->enemy && attacker->enemy != targ) - { - if (targ->enemy && targ->enemy->client) - targ->oldenemy = targ->enemy; - targ->enemy = attacker->enemy; - if(visible(targ,targ->enemy)) - FoundTarget (targ); - else - HuntTarget (targ); - return; - } -} - -bool CheckTeamDamage (edict_t *targ, edict_t *attacker) -{ - //FIXME make the next line real and uncomment this block - // if ((ability to damage a teammate == OFF) && (targ's team == attacker's team)) - return false; -} - -void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod) -{ - gclient_t *client; - int take; - int save; - int asave; - int psave; - int te_sparks; - edict_t *attacker; - edict_t *targ; - - targ = in_targ; - - if (!targ || !targ->inuse) - return; - - if (!targ->takedamage) - return; - - // Lazarus: If monster/actor is currently being forced to use - // specific animations due to target_animation, release that - // control over it. - if((targ->think == target_animate) && (targ->svflags & SVF_MONSTER)) - { - targ->think = monster_think; - targ->nextthink = level.time + FRAMETIME; - } - - if (!in_attacker) - attacker = world; - else - attacker = in_attacker; - - - // If targ is a fake player for the real player viewing camera, get that player - // out of the camera and do the damage to him - if (targ->class_id == ENTITY_CAMPLAYER) { - if(targ->target_ent && targ->target_ent->client && targ->target_ent->client->spycam) - { - if(attacker->enemy == targ) - { - attacker->enemy = targ->target_ent; - attacker->goalentity = NULL; - attacker->movetarget = NULL; - } - targ = targ->target_ent; - camera_off(targ); - if(attacker->svflags & SVF_MONSTER) - { - if(attacker->spawnflags & SF_MONSTER_GOODGUY) - { - if(attacker->enemy == targ) - { - attacker->enemy = NULL; - attacker->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; - attacker->monsterinfo.attack_finished = 0; - attacker->monsterinfo.pausetime = level.time + 100000000; - if(attacker->monsterinfo.stand) - attacker->monsterinfo.stand(attacker); - } - } - else - { - if(attacker->enemy == targ) - FoundTarget(attacker); - } - } - } - else - return; // don't damage target_monitor camplayer - } - // If targ is a remote turret_driver and attacker is a player, replace turret_driver - // with normal infantry dude and turn TRACK off on corresponding turret_breach - if ( targ->classname && (targ->class_id == ENTITY_TURRET_DRIVER) && - (targ->spawnflags & 1) && (attacker->client) ) { - edict_t *monster; - monster = targ->child; - if(monster) { - monster->health = targ->health; - if(targ->target_ent) { - targ->target_ent->spawnflags &= ~4; - targ->target_ent->move_angles[0] = 0; - targ->target_ent->owner = NULL; - } - G_FreeEdict(targ); - monster->solid = SOLID_BBOX; - monster->movetype = MOVETYPE_STEP; - monster->svflags &= ~SVF_NOCLIENT; - monster_start_go (monster); - gi.linkentity (monster); - monster->enemy = attacker; - FoundTarget(monster); - targ = monster; - } - } - - // friendly fire avoidance - // if enabled you can't hurt teammates (but you can hurt yourself) - // knockback still occurs - if ((targ != attacker) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value)) - { - if (OnSameTeam (targ, attacker)) - { - if ((int)(dmflags->value) & DF_NO_FRIENDLY_FIRE) - damage = 0; - else - mod |= MOD_FRIENDLY_FIRE; - } - } - meansOfDeath = mod; - - // easy mode takes half damage - if (skill->value == 0 && deathmatch->value == 0 && targ->client) - { - damage *= 0.5; - if (!damage) - damage = 1; - } - - client = targ->client; - - if (dflags & DAMAGE_BULLET) - te_sparks = TE_BULLET_SPARKS; - else - te_sparks = TE_SPARKS; - - VectorNormalize(dir); - -// bonus damage for suprising a monster - if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) && (attacker->client) && (!targ->enemy) && (targ->health > 0)) - damage *= 2; - - if (targ->flags & FL_NO_KNOCKBACK) - knockback = 0; - -// Lazarus: If monster is currently chasing a "thing" and mod is a laser, -// ignore knockback to give poor guy a chance to vamoose. - if (targ->movetarget && (targ->movetarget->class_id == ENTITY_THING) && (mod == MOD_TARGET_LASER)) - knockback = 0; - -// figure momentum add - if (!(dflags & DAMAGE_NO_KNOCKBACK)) - { - // Lazarus: Added MOVETYPE_TOSS to no knockback (pickup items and dead bodies) - if ((knockback) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP) && (targ->movetype != MOVETYPE_TOSS)) - { - vec3_t kvel; - float mass; - - if (targ->mass < 50) - mass = 50; - else - mass = targ->mass; - - if (targ->client && attacker == targ) - { - VectorScale (dir, 1600.0 * (float)knockback / mass, kvel); // the rocket jump hack... - } - else - { - VectorScale (dir, 500.0 * (float)knockback / mass, kvel); - } - VectorAdd (targ->velocity, kvel, targ->velocity); - } - } - - take = damage; - save = 0; - - // check for godmode - if ( (targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION) ) - { - take = 0; - save = damage; - SpawnDamage (te_sparks, point, normal); - } - - // check for invincibility - if ((client && client->invincible_framenum > level.framenum ) && !(dflags & DAMAGE_NO_PROTECTION)) - { - if (targ->pain_debounce_time < level.time) - { - gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0); - targ->pain_debounce_time = level.time + 2; - } - take = 0; - save = damage; - } - - psave = CheckPowerArmor (targ, point, normal, take, dflags); - take -= psave; - - asave = CheckArmor (targ, point, normal, take, te_sparks, dflags); - take -= asave; - - //treat cheat/powerup savings the same as armor - asave += save; - - // team damage avoidance - if (!(dflags & DAMAGE_NO_PROTECTION) && CheckTeamDamage (targ, attacker)) - return; - -// do the damage - if (take) - { - // Lazarus: dmgteam stuff - CallMyFriends(targ,attacker); - - // Lazarus: Sparks rather than blood for NOGIB dead monsters - if ((targ->svflags & SVF_MONSTER) && (targ->spawnflags & SF_MONSTER_NOGIB) && (targ->health <= 0)) - SpawnDamage (TE_SPARKS, point, normal); - else { - if ((targ->svflags & SVF_MONSTER) || (client)) - SpawnDamage ( BloodType(targ->blood_type), point, normal ); - else - SpawnDamage (te_sparks, point, normal); - } - - - if(targ->client) - { - if(in_targ != targ) - { - // Then player has taken the place of whatever was originally - // damaged, as in switching from func_monitor usage. Limit - // damage so that player isn't killed, and make him temporarily - // invincible - targ->health = max(2,targ->health - take); - targ->client->invincible_framenum = level.framenum+2; - targ->pain_debounce_time = max(targ->pain_debounce_time,level.time+0.3); - } - else if(level.framenum - targ->client->startframe > 30) - targ->health = targ->health - take; - else if(targ->health > 10) - targ->health = max(10,targ->health - take); - } - else - { - // Lazarus: For func_explosive target, check spawnflags and, if needed, - // damage type - if(targ->class_id == ENTITY_FUNC_EXPLOSIVE) - { - bool good_damage = true; - - if(targ->spawnflags & 8) // explosion only - { - good_damage = false; - if(mod == MOD_GRENADE) good_damage = true; - if(mod == MOD_G_SPLASH) good_damage = true; - if(mod == MOD_ROCKET) good_damage = true; - if(mod == MOD_R_SPLASH) good_damage = true; - if(mod == MOD_BFG_BLAST) good_damage = true; - if(mod == MOD_HANDGRENADE) good_damage = true; - if(mod == MOD_HG_SPLASH) good_damage = true; - if(mod == MOD_EXPLOSIVE) good_damage = true; - if(mod == MOD_BARREL) good_damage = true; - if(mod == MOD_BOMB) good_damage = true; - } - if(!good_damage) return; - } - - targ->health = targ->health - take; - } - - if (targ->health <= 0) - { - if ((targ->svflags & SVF_MONSTER) || (client)) - targ->flags |= FL_NO_KNOCKBACK; - Killed (targ, inflictor, attacker, take, point); - return; - } - } - - if (targ->svflags & SVF_MONSTER) - { - M_ReactToDamage (targ, attacker); - if (!(targ->monsterinfo.aiflags & AI_DUCKED) && (take)) - { - targ->pain (targ, attacker, knockback, take); - // nightmare mode monsters don't go into pain frames often - if (skill->value == 3) - targ->pain_debounce_time = level.time + 5; - } - } - else if (client) - { - if (!(targ->flags & FL_GODMODE) && (take)) - targ->pain (targ, attacker, knockback, take); - } - else if (take) - { - if (targ->pain) - targ->pain (targ, attacker, knockback, take); - } - - // add to the damage inflicted on a player this frame - // the total will be turned into screen blends and view angle kicks - // at the end of the frame - if (client) - { - client->damage_parmor += psave; - client->damage_armor += asave; - client->damage_blood += take; - client->damage_knockback += knockback; - VectorCopy (point, client->damage_from); - } -} - - -/* -============ -T_RadiusDamage - -Lazarus adds dmg_slope to alter the radius damage equation. (Standard Q2 = -0.5) -============ -*/ -void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod, double dmg_slope) -{ - float points; - edict_t *ent = NULL; - vec3_t v; - vec3_t dir; - - while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) - { - if (ent == ignore) - continue; - if (!ent->takedamage) - continue; - - VectorAdd (ent->mins, ent->maxs, v); - VectorMA (ent->s.origin, 0.5, v, v); - VectorSubtract (inflictor->s.origin, v, v); - points = damage + dmg_slope * VectorLength (v); - if (ent == attacker) - points = points * 0.5; - if (points > 0) - { - if (CanDamage (ent, inflictor)) - { - VectorSubtract (ent->s.origin, inflictor->s.origin, dir); - T_Damage (ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); - } - } - } -} diff --git a/server/global/g_jetpack.c b/server/global/g_jetpack.c deleted file mode 100644 index e3b0dc14..00000000 --- a/server/global/g_jetpack.c +++ /dev/null @@ -1,229 +0,0 @@ -#include "g_local.h" - -#ifdef JETPACK_MOD -/*we get silly velocity-effects when we are on ground and try to - accelerate, so lift us a little bit if possible*/ -bool Jet_AvoidGround( edict_t *ent ) -{ - vec3_t new_origin; - trace_t trace; - bool success; - -/*Check if there is enough room above us before we change origin[2]*/ - - new_origin[0] = ent->s.origin[0]; - new_origin[1] = ent->s.origin[1]; - new_origin[2] = ent->s.origin[2] + 0.5; - trace = gi.trace( ent->s.origin, ent->mins, ent->maxs, new_origin, ent, MASK_PLAYERSOLID ); - if ( success=(trace.plane.normal[2]==0) ) - /*no ceiling?*/ - ent->s.origin[2] += 0.5; - /*then make sure off ground*/ - return success; -} - -/*If a player dies with activated jetpack this function will be called -and produces a little explosion*/ - -void Jet_BecomeExplosion( edict_t *ent, int damage ) -{ - MESSAGE_BEGIN( svc_temp_entity ); - WRITE_BYTE( TE_EXPLOSION1 ); // TE_EXPLOSION2 is possible too - WRITE_COORD( ent->s.origin ); - MESSAGE_SEND( MSG_PVS, ent->s.origin, NULL ); - - gi.sound( ent, CHAN_BODY, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0 ); - - if (level.num_reflectors) - ReflectExplosion (TE_EXPLOSION1, ent->s.origin); - -// Lazarus: NO! This is taken care of already in player_die - /*throw some gib*/ -/* for ( n=0; n<4; n++ ) - ThrowGib( ent, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC ); - ThrowClientHead( ent, damage ); */ - ent->takedamage = DAMAGE_NO; -} - -/*The lifting effect is done through changing the origin, it -gives the best results. Of course its a little dangerous because -if we dont take care, we can move into solid*/ - -void Jet_ApplyLifting( edict_t *ent ) -{ - float delta; - vec3_t new_origin; - trace_t trace; - int time = 24; - /*must be >0, time/10 = time in sec for a complete cycle (up/down)*/ - float amplitude = 2.0; - /*calculate the z-distance to lift in this step*/ - delta = sin( (float)((level.framenum%time)*(360/time))/180*M_PI ) * amplitude; - delta = (float)((int)(delta*8))/8; /*round to multiples of 0.125*/ - VectorCopy( ent->s.origin, new_origin ); - new_origin[2] += delta; - if( VectorLength(ent->velocity) == 0 ) - { - /*i dont know the reason yet, but there is some floating so we - have to compensate that here (only if there is no velocity left)*/ - new_origin[0] -= 0.125; - new_origin[1] -= 0.125; - new_origin[2] -= 0.125; - } - /*before we change origin, its important to check that we dont go - into solid*/ - trace = gi.trace( ent->s.origin, ent->mins, ent->maxs, new_origin, ent, MASK_MONSTERSOLID ); - if ( trace.plane.normal[2] == 0 ) - VectorCopy( new_origin, ent->s.origin ); -} - -/*This function applys some sparks to your jetpack*/ - -void Jet_ApplySparks ( edict_t *ent ) -{ - vec3_t forward, right; - vec3_t pack_pos, jet_vector; - AngleVectors(ent->client->v_angle, forward, right, NULL); - VectorScale (forward, -8, pack_pos); - VectorAdd (pack_pos, ent->s.origin, pack_pos); - pack_pos[2] += 6; - VectorScale (forward, -50, jet_vector); - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_SPARKS); - WRITE_COORD (pack_pos); - WRITE_DIR (jet_vector); - MESSAGE_SEND (MSG_PVS, pack_pos, NULL); - - if(level.num_reflectors) - ReflectSparks(TE_SPARKS,pack_pos,jet_vector); -} - -/*Now for the main movement code. The steering is a lot like in water, that -means your viewing direction is your moving direction. You have three -direction Boosters: the big Main Booster and the smaller up-down and -left-right Boosters. -There are only 2 adds to the code of the first tutorial: the jetpack_nextthink -and the rolling. -The other modifications results in the use of the built-in quake functions, -there is no change in moving behavior (reinventing the wheel is a lot of -"fun" and a BIG waste of time ;-))*/ - -void Jet_ApplyJet( edict_t *ent, usercmd_t *ucmd ) -{ - float direction; - float scale; - vec3_t acc; - vec3_t forward, right; - - /*clear gravity so we dont have to compensate it with the Boosters*/ - ent->client->ps.pmove.gravity = 0; - - /*calculate the direction vectors dependent on viewing direction - (length of the vectors forward/right is always 1, the coordinates of - the vectors are values of how much youre looking in a specific direction - [if youre looking up to the top, the x/y values are nearly 0 the - z value is nearly 1])*/ - AngleVectors( ent->client->v_angle, forward, right, NULL ); - /*Run jet only 10 times a second so movement doesn't depend on fps - because ClientThink is called as often as possible - (fps<10 still is a problem ?)*/ - if ( ent->client->jetpack_nextthink <= level.framenum ) - { - ent->client->jetpack_nextthink = level.framenum + 1; - /*clear acceleration-vector*/ - VectorClear( acc ); - /*if we are moving forward or backward add MainBooster acceleration - (60)*/ - if ( ucmd->forwardmove ) - { - /*are we accelerating backward or forward?*/ - direction = (ucmd->forwardmove<0) ? -1.0 : 1.0; - /*add the acceleration for each direction*/ - if(jetpack_weenie->value) - { - acc[0] += forward[0] * direction * 60; - acc[1] += forward[1] * direction * 60; - acc[2] += forward[2] * direction * 60; - } - else - { - acc[0] += forward[0] * direction * 120; - acc[1] += forward[1] * direction * 120; - } - } - /*if we sidestep add Left-Right-Booster acceleration (40)*/ - if ( ucmd->sidemove ) - { /*are we accelerating left or right*/ - direction = (ucmd->sidemove<0) ? -1.0 : 1.0; - /*add only to x and y acceleration*/ - if(jetpack_weenie->value) - scale = direction * 40; - else - scale = direction * 80; - acc[0] += right[0] * scale; - acc[1] += right[1] * scale; - } - - /*if we crouch or jump add Up-Down-Booster acceleration (30)*/ - if ( ucmd->upmove ) - { - if(jetpack_weenie->value) - scale = 30; - else - scale = 45; - acc[2] += ucmd->upmove > 0 ? scale : -scale; - } - /*now apply some friction dependent on velocity (higher velocity results - in higher friction), without acceleration this will reduce the velocity - to 0 in a few steps*/ - ent->velocity[0] *= 0.83; - ent->velocity[1] *= 0.83; - ent->velocity[2] *= 0.86; - /*then accelerate with the calculated values. If the new acceleration for - a direction is smaller than an earlier, the friction will reduce the speed - in that direction to the new value in a few steps, so if youre flying - curves or around corners youre floating a little bit in the old direction*/ - VectorAdd( ent->velocity, acc, ent->velocity ); - /*round velocitys (is this necessary?)*/ - ent->velocity[0] = (float)((int)(ent->velocity[0]*8))/8; - ent->velocity[1] = (float)((int)(ent->velocity[1]*8))/8; - ent->velocity[2] = (float)((int)(ent->velocity[2]*8))/8; - /*Bound X and Y velocity so that friction and acceleration dont need to be - synced on maxvelocitys*/ - if(jetpack_weenie->value) - { - if(ent->velocity[0] > 300) ent->velocity[0] = 300; - if(ent->velocity[0] < -300) ent->velocity[0] = -300; - if(ent->velocity[1] > 300) ent->velocity[1] = 300; - if(ent->velocity[1] < -300) ent->velocity[1] = -300; - } - else - { - if(ent->velocity[0] > 1000) ent->velocity[0] = 1000; - if(ent->velocity[0] < -1000) ent->velocity[0] = -1000; - if(ent->velocity[1] > 1000) ent->velocity[1] = 1000; - if(ent->velocity[1] < -1000) ent->velocity[1] = -1000; - } - /*add some gentle up and down when idle (not accelerating)*/ - if( (VectorLength(acc) == 0) && (!ent->groundentity)) - Jet_ApplyLifting( ent ); - } //if ( ent->client->jetpack_nextthink... - /*add rolling when we fly curves or boost left/right*/ - if((bob_roll->value > 0) && (jetpack_weenie->value || !ent->groundentity)) - { - ent->client->kick_angles[ROLL] = -DotProduct( ent->velocity, right ) * ent->client->jetpack_roll; - if(ucmd->sidemove) - ent->client->jetpack_roll = min(0.02,ent->client->jetpack_roll + 0.002); - else - ent->client->jetpack_roll = max(0.00,ent->client->jetpack_roll - 0.002); - } - else - ent->client->jetpack_roll = 0; - /*last but not least add some smoke*/ - Jet_ApplySparks( ent ); - -// gi.dprintf("%5g %5g %5g\n",ent->velocity[0],ent->velocity[1],ent->velocity[2]); -} -#endif - diff --git a/server/global/g_newai.c b/server/global/g_newai.c deleted file mode 100644 index d3653ae7..00000000 --- a/server/global/g_newai.c +++ /dev/null @@ -1,1395 +0,0 @@ - -#include "g_local.h" - -//=============================== -// BLOCKED Logic -//=============================== - -/* - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_DEBUGTRAIL); - WRITE_COORD (pt1); - WRITE_COORD (pt2); - MESSAGE_SEND (MSG_PVS, pt1, NULL); - - self->nextthink = level.time + 10; -*/ - -// plat states, copied from g_func.c - -#define STATE_TOP 0 -#define STATE_BOTTOM 1 -#define STATE_UP 2 -#define STATE_DOWN 3 - -bool face_wall (edict_t *self); -void HuntTarget (edict_t *self); - -// PMM -bool parasite_drain_attack_ok (vec3_t start, vec3_t end); - - -// blocked_checkshot -// shotchance: 0-1, chance they'll take the shot if it's clear. -bool blocked_checkshot (edict_t *self, float shotChance) -{ - bool playerVisible; - - if(!self->enemy) - return false; - - // blocked checkshot is only against players. this will - // filter out player sounds and other shit they should - // not be firing at. - if(!(self->enemy->client)) - return false; - - if (random() < shotChance) - return false; - - // PMM - special handling for the parasite - if (self->class_id == ENTITY_MONSTER_PARASITE) - { - vec3_t f, r, offset, start, end; - trace_t tr; - AngleVectors (self->s.angles, f, r, NULL); - VectorSet (offset, 24, 0, 6); - G_ProjectSource (self->s.origin, offset, f, r, start); - - VectorCopy (self->enemy->s.origin, end); - if (!parasite_drain_attack_ok(start, end)) - { - end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; - if (!parasite_drain_attack_ok(start, end)) - { - end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; - if (!parasite_drain_attack_ok(start, end)) - return false; - } - } - VectorCopy (self->enemy->s.origin, end); - - tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); - if (tr.ent != self->enemy) - { - self->monsterinfo.aiflags |= AI_BLOCKED; - - if(self->monsterinfo.attack) - self->monsterinfo.attack(self); - - self->monsterinfo.aiflags &= ~AI_BLOCKED; - return true; - } - } - - playerVisible = visible (self, self->enemy); - return false; -} - -// blocked_checkplat -// dist: how far they are trying to walk. -bool blocked_checkplat (edict_t *self, float dist) -{ - int playerPosition; - trace_t trace; - vec3_t pt1, pt2; - vec3_t forward; - edict_t *plat; - - if(!self->enemy) - return false; - - // check player's relative altitude - if(self->enemy->absmin[2] >= self->absmax[2]) - playerPosition = 1; - else if(self->enemy->absmax[2] <= self->absmin[2]) - playerPosition = -1; - else - playerPosition = 0; - - // if we're close to the same position, don't bother trying plats. - if(playerPosition == 0) - return false; - - plat = NULL; - - // see if we're already standing on a plat. - if(self->groundentity && self->groundentity != world) - { - if(!strncmp(self->groundentity->classname, "func_plat", 8)) - plat = self->groundentity; - } - - // if we're not, check to see if we'll step onto one with this move - if(!plat) - { - AngleVectors (self->s.angles, forward, NULL, NULL); - VectorMA(self->s.origin, dist, forward, pt1); - VectorCopy (pt1, pt2); - pt2[2] -= 384; - - trace = gi.trace(pt1, vec3_origin, vec3_origin, pt2, self, MASK_MONSTERSOLID); - if(trace.fraction < 1 && !trace.allsolid && !trace.startsolid) - { - if(!strncmp(trace.ent->classname, "func_plat", 8)) - { - plat = trace.ent; - } - } - } - - // if we've found a plat, trigger it. - if(plat && plat->use) - { - if (playerPosition == 1) - { - if((self->groundentity == plat && plat->moveinfo.state == STATE_BOTTOM) || - (self->groundentity != plat && plat->moveinfo.state == STATE_TOP)) - { -// if(g_showlogic && g_showlogic->value) -// gi.dprintf("player above, and plat will raise. using!\n"); - plat->use (plat, self, self); - return true; - } - } - else if(playerPosition == -1) - { - if((self->groundentity == plat && plat->moveinfo.state == STATE_TOP) || - (self->groundentity != plat && plat->moveinfo.state == STATE_BOTTOM)) - { -// if(g_showlogic && g_showlogic->value) -// gi.dprintf("player below, and plat will lower. using!\n"); - plat->use (plat, self, self); - return true; - } - } -// if(g_showlogic && g_showlogic->value) -// gi.dprintf("hit a plat, not using. ppos: %d plat: %d\n", playerPosition, plat->moveinfo.state); - } - - return false; -} - -// blocked_checkjump -// dist: how far they are trying to walk. -// maxDown/maxUp: how far they'll ok a jump for. set to 0 to disable that direction. -bool blocked_checkjump (edict_t *self, float dist, float maxDown, float maxUp) -{ - int playerPosition; - trace_t trace; - vec3_t pt1, pt2; - vec3_t forward, up; - vec_t d0, d1; - edict_t *target; - - // Lazarus: Rogue only did this for enemies. We do it for enemies or - // movetargets - - if(!self->monsterinfo.jump) - return false; - if(self->enemy) - target = self->enemy; - else if(self->movetarget) - target = self->movetarget; - else - return false; - - VectorSubtract(target->s.origin,self->s.origin,pt1); - d0 = VectorLength(pt1); - - AngleVectors (self->s.angles, forward, NULL, up); - VectorMA(self->s.origin, 48, forward, pt1); - - if(target->absmin[2] > (self->absmin[2] + 16)) - playerPosition = 1; - else if(target->absmin[2] < (self->absmin[2] - 16)) - playerPosition = -1; - else - playerPosition = 0; - - if(playerPosition == -1 && maxDown) - { - // check to make sure we can even get to the spot we're going to "fall" from - trace = gi.trace(self->s.origin, self->mins, self->maxs, pt1, self, MASK_MONSTERSOLID); - if(trace.fraction < 1) - return false; - - VectorCopy (pt1, pt2); - pt2[2] = self->mins[2] - maxDown - 1; - - trace = gi.trace(pt1, vec3_origin, vec3_origin, pt2, self, MASK_MONSTERSOLID | MASK_WATER); - if(trace.fraction < 1 && !trace.allsolid && !trace.startsolid) - { - if((self->absmin[2] - trace.endpos[2]) >= 24 && trace.contents & MASK_SOLID) - { - if( (target->absmin[2] - trace.endpos[2]) > 32) - return false; - if(trace.plane.normal[2] < 0.9) - return false; - VectorSubtract(target->s.origin,trace.endpos,pt1); - d1 = VectorLength(pt1); - if(d0 < d1) - return false; - self->velocity[0] = forward[0]*dist*10; - self->velocity[1] = forward[1]*dist*10; - self->velocity[2] = max(self->velocity[2],100); - gi.linkentity(self); - return true; - } - } - } - else if(playerPosition == 1 && maxUp) - { - VectorCopy(pt1, pt2); - pt1[2] = self->absmax[2] + maxUp; - - trace = gi.trace(pt1, vec3_origin, vec3_origin, pt2, self, MASK_MONSTERSOLID | MASK_WATER); - if(trace.fraction < 1 && !trace.allsolid && !trace.startsolid) - { - if((trace.endpos[2] - self->absmin[2]) <= maxUp && trace.contents & MASK_SOLID) - { - VectorSubtract(target->s.origin,trace.endpos,pt1); - d1 = VectorLength(pt1); - if(d0 < d1) - return false; - face_wall(self); - self->monsterinfo.jump(self); - self->velocity[0] = forward[0]*dist*10; - self->velocity[1] = forward[1]*dist*10; - self->velocity[2] = max(self->velocity[2],200); - gi.linkentity(self); - return true; - } - } - } - return false; -} - -// checks to see if another coop player is nearby, and will switch. -bool blocked_checknewenemy (edict_t *self) -{ -/* - int player; - edict_t *ent; - - if (!(coop->value)) - return false; - - for (player = 1; player <= game.maxclients; player++) - { - ent = &g_edicts[player]; - if (!ent->inuse) - continue; - if (!ent->client) - continue; - if (ent == self->enemy) - continue; - - if (visible (self, ent)) - { - if (g_showlogic && g_showlogic->value) - gi.dprintf ("B_CNE: %s acquired new enemy %s\n", self->classname, ent->client->pers.netname); - - self->enemy = ent; - FoundTarget (self); - return true; - } - } - - return false; -*/ - return false; -} - -// ************************* -// HINT PATHS -// ************************* - -#define HINT_ENDPOINT 0x0001 - -int hint_paths_present; -edict_t *hint_path_start[MAX_HINT_CHAINS]; -int num_hint_paths; - -// -// AI code -// - -// ============= -// hintpath_findstart - given any hintpath node, finds the start node -// ============= -edict_t *hintpath_findstart(edict_t *ent) -{ - edict_t *e; - edict_t *last; - int field; - - if(ent->target) // starting point - { - last = world; - field = FOFS(targetname); - e = G_Find(NULL, field, ent->target); - while(e) - { - last = e; - if(!e->target) - break; - e = G_Find(NULL, field, e->target); - } - } - else // end point - { - last = world; - field = FOFS(target); - e = G_Find(NULL, field, ent->targetname); - while(e) - { - last = e; - if(!e->targetname) - break; - e = G_Find(NULL, field, e->targetname); - } - } - - if(!(last->spawnflags & HINT_ENDPOINT)) - { -// gi.dprintf ("end of chain is not HINT_ENDPOINT\n"); - return NULL; - } - - if(last == world) - last = NULL; - return last; -} - -// ============= -// hintpath_other_end - given one endpoint of a hintpath, returns the other end. -// ============= -edict_t *hintpath_other_end(edict_t *ent) -{ - edict_t *e; - edict_t *last; - int field; - - if(ent->target) // starting point - { - last = world; - field = FOFS(targetname); - e = G_Find(NULL, field, ent->target); - while(e) - { - last = e; - if(!e->target) - break; - e = G_Find(NULL, field, e->target); - } - } - else // end point - { - last = world; - field = FOFS(target); - e = G_Find(NULL, field, ent->targetname); - while(e) - { - last = e; - if(!e->targetname) - break; - e = G_Find(NULL, field, e->targetname); - } - } - - if(!(last->spawnflags & HINT_ENDPOINT)) - { -// gi.dprintf ("end of chain is not HINT_ENDPOINT\n"); - return NULL; - } - - if(last == world) - last = NULL; - return last; -} - -// ============= -// hintpath_go - starts a monster (self) moving towards the hintpath (point) -// disables all contrary AI flags. -// ============= -void hintpath_go (edict_t *self, edict_t *point) -{ - vec3_t dir; - vec3_t angles; - - VectorSubtract(point->s.origin, self->s.origin, dir); - vectoangles2(dir, angles); - - self->ideal_yaw = angles[YAW]; - self->goalentity = self->movetarget = point; - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags |= AI_HINT_PATH; - self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP); - // run for it - self->monsterinfo.search_time = level.time; - self->monsterinfo.run (self); -} - -// ============= -// hintpath_stop - bails a monster out of following hint paths -// ============= -void hintpath_stop (edict_t *self) -{ - self->goalentity = NULL; - self->movetarget = NULL; -// self->monsterinfo.last_hint = NULL; - self->monsterinfo.last_hint_time = level.time; - self->monsterinfo.goal_hint = NULL; - self->monsterinfo.aiflags &= ~AI_HINT_PATH; - if (has_valid_enemy(self)) - { - // if we can see our target, go nuts - if (visible(self, self->enemy)) - { - FoundTarget (self); - return; - } - // otherwise, keep chasing - HuntTarget (self); - return; - } - // if our enemy is no longer valid, forget about our enemy and go into stand - self->enemy = NULL; - // we need the pausetime otherwise the stand code - // will just revert to walking with no target and - // the monsters will wonder around aimlessly trying - // to hunt the world entity - self->monsterinfo.pausetime = level.time + 100000000; - self->monsterinfo.stand (self); -} - -// ============= -// monsterlost_checkhint - the monster (self) will check around for valid hintpaths. -// a valid hintpath is one where the two endpoints can see both the monster -// and the monster's enemy. if only one person is visible from the endpoints, -// it will not go for it. -// ============= -bool monsterlost_checkhint2 (edict_t *self); - -bool monsterlost_checkhint (edict_t *self) -{ - edict_t *e, *monster_pathchain, *target_pathchain, *checkpoint; - edict_t *closest; - float closest_range = 1000000; - edict_t *start, *destination; - int field; - int count1=0, count2=0, count3=0, count4=0, count5=0; - float r; - int i; - bool hint_path_represented[MAX_HINT_CHAINS]; - - // if there are no hint paths on this map, exit immediately. - if(!hint_paths_present) - return false; - - if(!self->enemy) - return false; - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - return false; - -// if (!strcmp(self->classname, "monster_turret")) -// return false; - - monster_pathchain = NULL; - - field = FOFS(classname); - - // find all the hint_paths. - // FIXME - can we not do this every time? - for (i=0; i < num_hint_paths; i++) - { - e = hint_path_start[i]; - while(e) - { - count1++; - if (e->monster_hint_chain) - e->monster_hint_chain = NULL; - if (monster_pathchain) - { - checkpoint->monster_hint_chain = e; - checkpoint = e; - } - else - { - monster_pathchain = e; - checkpoint = e; - } - e = e->hint_chain; - } - } - - // filter them by distance and visibility to the monster - e = monster_pathchain; - checkpoint = NULL; - while (e) - { - r = realrange (self, e); - -// if (r > 512) -// count3++; - - if (r > 512) - { - count2++; - if (checkpoint) - { - checkpoint->monster_hint_chain = e->monster_hint_chain; - e->monster_hint_chain = NULL; - e = checkpoint->monster_hint_chain; - continue; - } - else - { - // use checkpoint as temp pointer - checkpoint = e; - e = e->monster_hint_chain; - checkpoint->monster_hint_chain = NULL; - // and clear it again - checkpoint = NULL; - // since we have yet to find a valid one (or else checkpoint would be set) move the - // start of monster_pathchain - monster_pathchain = e; - continue; - } - } - if (!visible(self, e)) - { - count4++; - if (checkpoint) - { - checkpoint->monster_hint_chain = e->monster_hint_chain; - e->monster_hint_chain = NULL; - e = checkpoint->monster_hint_chain; - continue; - } - else - { - // use checkpoint as temp pointer - checkpoint = e; - e = e->monster_hint_chain; - checkpoint->monster_hint_chain = NULL; - // and clear it again - checkpoint = NULL; - // since we have yet to find a valid one (or else checkpoint would be set) move the - // start of monster_pathchain - monster_pathchain = e; - continue; - } - } - count5++; - checkpoint = e; - e = e->monster_hint_chain; - } - - // at this point, we have a list of all of the eligible hint nodes for the monster - // we now take them, figure out what hint chains they're on, and traverse down those chains, - // seeing whether any can see the player - // - // first, we figure out which hint chains we have represented in monster_pathchain - if (count5 == 0) - return false; - - for (i=0; i < num_hint_paths; i++) - { - hint_path_represented[i] = false; - } - e = monster_pathchain; - checkpoint = NULL; - while (e) - { - if ((e->hint_chain_id < 0) || (e->hint_chain_id > num_hint_paths)) - return false; - hint_path_represented[e->hint_chain_id] = true; - e = e->monster_hint_chain; - } - - count1 = 0; - count2 = 0; - count3 = 0; - count4 = 0; - count5 = 0; - - // now, build the target_pathchain which contains all of the hint_path nodes we need to check for - // validity (within range, visibility) - target_pathchain = NULL; - checkpoint = NULL; - for (i=0; i < num_hint_paths; i++) - { - // if this hint chain is represented in the monster_hint_chain, add all of it's nodes to the target_pathchain - // for validity checking - if (hint_path_represented[i]) - { - e = hint_path_start[i]; - while (e) - { - if (target_pathchain) - { - checkpoint->target_hint_chain = e; - checkpoint = e; - } - else - { - target_pathchain = e; - checkpoint = e; - } - e = e->hint_chain; - } - } - } - - // target_pathchain is a list of all of the hint_path nodes we need to check for validity relative to the target - e = target_pathchain; - checkpoint = NULL; - while (e) - { - r = realrange (self->enemy, e); - - if (r > 512) - { - count2++; - if (checkpoint) - { - checkpoint->target_hint_chain = e->target_hint_chain; - e->target_hint_chain = NULL; - e = checkpoint->target_hint_chain; - continue; - } - else - { - // use checkpoint as temp pointer - checkpoint = e; - e = e->target_hint_chain; - checkpoint->target_hint_chain = NULL; - // and clear it again - checkpoint = NULL; - target_pathchain = e; - continue; - } - } - if (!visible(self->enemy, e)) - { - count4++; - if (checkpoint) - { - checkpoint->target_hint_chain = e->target_hint_chain; - e->target_hint_chain = NULL; - e = checkpoint->target_hint_chain; - continue; - } - else - { - // use checkpoint as temp pointer - checkpoint = e; - e = e->target_hint_chain; - checkpoint->target_hint_chain = NULL; - // and clear it again - checkpoint = NULL; - target_pathchain = e; - continue; - } - } - // if it passes all the tests, it's a keeper - count5++; - checkpoint = e; - e = e->target_hint_chain; - } - - // at this point we should have: - // monster_pathchain - a list of "monster valid" hint_path nodes linked together by monster_hint_chain - // target_pathcain - a list of "target valid" hint_path nodes linked together by target_hint_chain. these - // are filtered such that only nodes which are on the same chain as "monster valid" nodes - // - // Now, we figure out which "monster valid" node we want to use - // - // To do this, we first off make sure we have some target nodes. If we don't, there are no valid hint_path nodes - // for us to take - // - // If we have some, we filter all of our "monster valid" nodes by which ones have "target valid" nodes on them - // - // Once this filter is finished, we select the closest "monster valid" node, and go to it. - - if (count5 == 0) - return false; - - // reuse the hint_chain_represented array, this time to see which chains are represented by the target - for (i=0; i < num_hint_paths; i++) - { - hint_path_represented[i] = false; - } - - e = target_pathchain; - checkpoint = NULL; - while (e) - { - if ((e->hint_chain_id < 0) || (e->hint_chain_id > num_hint_paths)) - return false; - hint_path_represented[e->hint_chain_id] = true; - e = e->target_hint_chain; - } - - // traverse the monster_pathchain - if the hint_node isn't represented in the "target valid" chain list, - // remove it - // if it is on the list, check it for range from the monster. If the range is the closest, keep it - // - closest = NULL; - e = monster_pathchain; - while (e) - { - if (!(hint_path_represented[e->hint_chain_id])) - { - checkpoint = e->monster_hint_chain; - e->monster_hint_chain = NULL; - e = checkpoint; - continue; - } - r = realrange(self, e); - if (r < closest_range) { - closest = e; - closest_range = r; // Lazarus: This was left out, ya doofuses - } - e = e->monster_hint_chain; - } - - if (!closest) - return false; - - start = closest; - // now we know which one is the closest to the monster .. this is the one the monster will go to - // we need to finally determine what the DESTINATION node is for the monster .. walk down the hint_chain, - // and find the closest one to the player - - closest = NULL; - closest_range = 10000000; - e = target_pathchain; - while (e) - { - if (start->hint_chain_id == e->hint_chain_id) - { - r = realrange(self->enemy, e); // Lazarus: This WAS realrange(self, e)... that can't be right - if (r < closest_range) { - closest = e; - closest_range = r; // Lazarus: again, you idjits left this out - } - } - e = e->target_hint_chain; - } - - if (!closest) - return false; - - destination = closest; - - self->monsterinfo.goal_hint = destination; -// self->monsterinfo.last_hint = NULL; - hintpath_go(self, start); - - return true; -} -// -// Path code -// - -// ============= -// hint_path_touch - someone's touched the hint_path -// ============= -void hint_path_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - edict_t *e, *goal, *next; -// int chain; // direction - (-1) = upstream, (1) = downstream, (0) = done - bool goalFound = false; - - if(other->monsterinfo.aiflags & AI_MEDIC_PATROL) - { - if(other->movetarget == self) - medic_NextPatrolPoint(other,self); - return; - } - - if(other->monsterinfo.aiflags & AI_HINT_TEST) - { - if(other->movetarget == self) - HintTestNext(other,self); - return; - } - - // make sure we're the target of it's obsession - if(other->movetarget == self) - { - goal = other->monsterinfo.goal_hint; - - // if the monster is where he wants to be - if (goal == self) - { - hintpath_stop (other); - return; - } - else - { - // if we aren't, figure out which way we want to go - e = hint_path_start[self->hint_chain_id]; - while (e) - { - // if we get up to ourselves on the hint chain, we're going down it - if (e == self) - { - next = e->hint_chain; - break; - } - if (e == goal) - goalFound = true; - // if we get to where the next link on the chain is this hint_path and have found the goal on the way - // we're going upstream, so remember who the previous link is - if ((e->hint_chain == self) && goalFound) - { - next = e; - break; - } - e = e->hint_chain; - } - } - - // if we couldn't find it, have the monster go back to normal hunting. - if(!next) - { - hintpath_stop(other); - return; - } - - // set the last_hint entry to this hint_path, and - // send him on his way - hintpath_go(other, next); - - // have the monster freeze if the hint path we just touched has a wait time - // on it, for example, when riding a plat. - if(self->wait) - other->nextthink = level.time + self->wait; - } -} - -/*QUAKED hint_path (.5 .3 0) (-8 -8 -8) (8 8 8) END -Target: next hint path - -END - set this flag on the endpoints of each hintpath. - -"wait" - set this if you want the monster to freeze when they touch this hintpath -*/ -void SP_hint_path (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict(self); - return; - } - - if (!self->targetname && !self->target) - { - gi.dprintf ("unlinked hint_path at %s\n", vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - - self->class_id = ENTITY_HINT_PATH; - // Lazarus: Corrections for mappers that can't follow instructions :-) - if (!self->targetname) - self->spawnflags |= HINT_ENDPOINT; - if (!self->target) - self->spawnflags |= HINT_ENDPOINT; - - self->solid = SOLID_TRIGGER; - self->touch = hint_path_touch; - VectorSet (self->mins, -8, -8, -8); - VectorSet (self->maxs, 8, 8, 8); - self->svflags |= SVF_NOCLIENT; - gi.linkentity (self); -} - -//int hint_paths_present; -//edict_t *hint_path_start[100]; -//int num_hint_paths; - -// ============ -// InitHintPaths - Called by InitGame (g_save) to enable quick exits if valid -// ============ -void InitHintPaths (void) -{ - edict_t *e, *current; - int field, i, count2; - bool errors = false; - - hint_paths_present = 0; - - // check all the hint_paths. - field = FOFS(classname); - e = G_Find(NULL, field, "hint_path"); - if(e) - hint_paths_present = 1; - else - return; - - memset (hint_path_start, 0, MAX_HINT_CHAINS*sizeof (edict_t *)); - num_hint_paths = 0; - while(e) - { - if(e->spawnflags & HINT_ENDPOINT) - { - if (e->target) // start point - { - if (e->targetname) // this is a bad end, ignore it - { - gi.dprintf ("Hint path at %s marked as endpoint with both target (%s) and targetname (%s)\n", - vtos (e->s.origin), e->target, e->targetname); - errors = true; - } - else - { - if (num_hint_paths >= MAX_HINT_CHAINS) - { -// gi.dprintf ("Only %d hint chains allowed. Connect some together!\n", MAX_HINT_CHAINS); - break; - } - hint_path_start[num_hint_paths++] = e; - } - } - } - e = G_Find(e, field, "hint_path"); - } - - field = FOFS(targetname); - for (i=0; i< num_hint_paths; i++) - { - count2 = 1; - current = hint_path_start[i]; - current->hint_chain_id = i; - e = G_Find(NULL, field, current->target); - if (G_Find(e, field, current->target)) - { - gi.dprintf ("\nForked hint path at %s detected for chain %d, target %s\n", - vtos (current->s.origin), num_hint_paths, current->target); - hint_path_start[i]->hint_chain = NULL; - count2 = 0; - errors = true; - continue; - } - while (e) - { - if (e->hint_chain) - { - gi.dprintf ("\nCircular hint path at %s detected for chain %d, targetname %s\n", - vtos (e->s.origin), num_hint_paths, e->targetname); - hint_path_start[i]->hint_chain = NULL; - count2 = 0; - errors = true; - break; - } - count2++; - current->hint_chain = e; - current = e; - current->hint_chain_id = i; - if (!current->target) - break; - e = G_Find(NULL, field, current->target); - if (G_Find(e, field, current->target)) - { - gi.dprintf ("\nForked hint path at %s detected for chain %d, target %s\n", - vtos (current->s.origin), num_hint_paths, current->target); - hint_path_start[i]->hint_chain = NULL; - count2 = 0; - break; - } - } - } -} - -// ***************************** -// MISCELLANEOUS STUFF -// ***************************** - -// PMM - inback -// use to see if opponent is behind you (not to side) -// if it looks a lot like infront, well, there's a reason - -bool inback (edict_t *self, edict_t *other) -{ - vec3_t vec; - float dot; - vec3_t forward; - - AngleVectors (self->s.angles, forward, NULL, NULL); - VectorSubtract (other->s.origin, self->s.origin, vec); - VectorNormalize (vec); - dot = DotProduct (vec, forward); - - if (dot < -0.3) - return true; - return false; -} - -float realrange (edict_t *self, edict_t *other) -{ - vec3_t dir; - - VectorSubtract (self->s.origin, other->s.origin, dir); - return VectorLength(dir); -} - -bool face_wall (edict_t *self) -{ - vec3_t pt; - vec3_t forward; - vec3_t ang; - trace_t tr; - - AngleVectors (self->s.angles, forward, NULL, NULL); - VectorMA(self->s.origin, 64, forward, pt); - tr = gi.trace(self->s.origin, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID); - if(tr.fraction < 1 && !tr.allsolid && !tr.startsolid) - { - vectoangles2(tr.plane.normal, ang); - self->ideal_yaw = ang[YAW] + 180; - if(self->ideal_yaw > 360) - self->ideal_yaw -= 360; - - M_ChangeYaw(self); - return true; - } - - return false; -} - -// -// Monster "Bad" Areas -// - -void badarea_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ -// drawbbox(ent); -} - -edict_t *SpawnBadArea(vec3_t mins, vec3_t maxs, float lifespan, edict_t *owner) -{ - edict_t *badarea; - vec3_t origin; - - VectorAdd(mins, maxs, origin); - VectorScale(origin, 0.5, origin); - - VectorSubtract(maxs, origin, maxs); - VectorSubtract(mins, origin, mins); - - badarea = G_Spawn(); - VectorCopy(origin, badarea->s.origin); - VectorCopy(maxs, badarea->maxs); - VectorCopy(mins, badarea->mins); - badarea->touch = badarea_touch; - badarea->movetype = MOVETYPE_NONE; - badarea->solid = SOLID_TRIGGER; - badarea->classname = "bad_area"; - gi.linkentity (badarea); - - if(lifespan) - { - badarea->think = G_FreeEdict; - badarea->nextthink = level.time + lifespan; - } - if(owner) - { - badarea->owner = owner; - } - -// drawbbox(badarea); - return badarea; -} - -// CheckForBadArea -// This is a customized version of G_TouchTriggers that will check -// for bad area triggers and return them if they're touched. -edict_t *CheckForBadArea(edict_t *ent) -{ - int i, num; - edict_t *touch[MAX_EDICTS], *hit; - vec3_t mins, maxs; - - VectorAdd(ent->s.origin, ent->mins, mins); - VectorAdd(ent->s.origin, ent->maxs, maxs); - - num = gi.BoxEdicts (mins, maxs, touch, MAX_EDICTS, AREA_TRIGGERS); - -// drawbbox(ent); - - // be careful, it is possible to have an entity in this - // list removed before we get to it (killtriggered) - for (i=0 ; iinuse) - continue; - if (hit->touch == badarea_touch) - { - return hit; - } - } - - return NULL; -} - -// predictive calculator -// target is who you want to shoot -// start is where the shot comes from -// bolt_speed is how fast the shot is -// eye_height is a boolean to say whether or not to adjust to targets eye_height -// offset is how much time to miss by -// aimdir is the resulting aim direction (pass in NULL if you don't want it) -// aimpoint is the resulting aimpoint (pass in NULL if don't want it) -void PredictAim (edict_t *target, vec3_t start, float bolt_speed, bool eye_height, float offset, vec3_t aimdir, vec3_t aimpoint) -{ - vec3_t dir, vec; - float dist, time; - - if (!target || !target->inuse) - { - VectorCopy (vec3_origin, aimdir); - return; - } - - VectorSubtract(target->s.origin, start, dir); - if (eye_height) - dir[2] += target->viewheight; - dist = VectorLength(dir); - time = dist / bolt_speed; - - - VectorMA(target->s.origin, time - offset, target->velocity, vec); - - if (eye_height) - vec[2] += target->viewheight; - - if (aimdir) - { - VectorSubtract (vec, start, aimdir); - VectorNormalize (aimdir); - } - - if (aimpoint) - { - VectorCopy (vec, aimpoint); - } -} - - -bool below (edict_t *self, edict_t *other) -{ - vec3_t vec; - float dot; - vec3_t down; - - VectorSubtract (other->s.origin, self->s.origin, vec); - VectorNormalize (vec); - VectorSet (down, 0, 0, -1); - dot = DotProduct (vec, down); - - if (dot > 0.95) // 18 degree arc below - return true; - return false; -} - -void drawbbox (edict_t *self) -{ - int lines[4][3] = { - {1, 2, 4}, - {1, 2, 7}, - {1, 4, 5}, - {2, 4, 7} - }; - - int starts[4] = {0, 3, 5, 6}; - - vec3_t pt[8]; - int i, j, k; - vec3_t coords[2]; - vec3_t newbox; - vec3_t f,r,u, dir; - - VectorCopy (self->absmin, coords[0]); - VectorCopy (self->absmax, coords[1]); - - for (i=0; i<=1; i++) - { - for (j=0; j<=1; j++) - { - for (k=0; k<=1; k++) - { - pt[4*i+2*j+k][0] = coords[i][0]; - pt[4*i+2*j+k][1] = coords[j][1]; - pt[4*i+2*j+k][2] = coords[k][2]; - } - } - } - - for (i=0; i<= 3; i++) - { - for (j=0; j<= 2; j++) - { - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_DEBUGTRAIL); - WRITE_COORD (pt[starts[i]]); - WRITE_COORD (pt[lines[i][j]]); - MESSAGE_SEND (MSG_ALL, pt[starts[i]], NULL); - } - } - - vectoangles2 (self->s.angles, dir); - AngleVectors (dir, f, r, u); - - VectorMA (self->s.origin, 50, f, newbox); - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_DEBUGTRAIL); - WRITE_COORD (self->s.origin); - WRITE_COORD (newbox); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - VectorClear (newbox); - - VectorMA (self->s.origin, 50, r, newbox); - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_DEBUGTRAIL); - WRITE_COORD (self->s.origin); - WRITE_COORD (newbox); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - VectorClear (newbox); - - VectorMA (self->s.origin, 50, u, newbox); - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_DEBUGTRAIL); - WRITE_COORD (self->s.origin); - WRITE_COORD (newbox); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - VectorClear (newbox); -} - -//========================= -//========================= -bool has_valid_enemy (edict_t *self) -{ - if (!self->enemy) - return false; - - if (!self->enemy->inuse) - return false; - - // Lazarus: this doesn't take into account medics pursuing dead monsters -// if (self->enemy->health < 1) -// return false; - if (self->monsterinfo.aiflags & AI_MEDIC) - { - if(self->enemy->health > 0) - return false; - } - else if(self->enemy->health < 1) - return false; - - return true; -} - -// this returns a randomly selected coop player who is visible to self -// returns NULL if bad - -edict_t * PickCoopTarget (edict_t *self) -{ - // no more than 4 players in coop, so.. - edict_t *targets[4]; - int num_targets = 0, targetID; - edict_t *ent; - int player; - - // if we're not in coop, this is a noop - if (!coop || !coop->value) - return NULL; - - memset (targets, 0, 4*sizeof(edict_t *)); - - for (player = 1; player <= game.maxclients; player++) - { - ent = &g_edicts[player]; - if (!ent->inuse) - continue; - if (!ent->client) - continue; - if (visible(self, ent)) - targets[num_targets++] = ent; - } - - if (!num_targets) - return NULL; - - // get a number from 0 to (num_targets-1) - targetID = (random() * (float)num_targets); - - // just in case we got a 1.0 from random - if (targetID == num_targets) - targetID--; - - return targets[targetID]; -} - -// only meant to be used in coop -int CountPlayers (void) -{ - edict_t *ent; - int count = 0; - int player; - - // if we're not in coop, this is a noop - if (!coop || !coop->value) - return 1; - - for (player = 1; player <= game.maxclients; player++) - { - ent = &g_edicts[player]; - if (!ent->inuse) - continue; - if (!ent->client) - continue; - count++; - } -/* - ent = g_edicts+1; // skip the worldspawn - while (ent) - { - if ((ent->client) && (ent->inuse)) - { - ent++; - count++; - } - else - ent = NULL; - } -*/ - return count; -} - -//******************* -// JUMPING AIDS -//******************* - -void monster_jump_start (edict_t *self) -{ - self->timestamp = level.time; -} - -bool monster_jump_finished (edict_t *self) -{ - if ((level.time - self->timestamp) > 3) - return true; -// Lazarus: Ummm? I suppose this should return false here, though this -// line was not included in Rogue's code - return false; -} - - - diff --git a/server/global/g_sound.c b/server/global/g_sound.c deleted file mode 100644 index 161ab044..00000000 --- a/server/global/g_sound.c +++ /dev/null @@ -1,1388 +0,0 @@ -#include "g_local.h" -#include "fmod.h" -#include - -#define SF_PLAYBACK_LOOP 1 -#define SF_PLAYBACK_TOGGLE 2 -#define SF_PLAYBACK_MUSIC 4 // Is set, mapper says this is "music" and won't be played if fmod_nomusic is set -#define SF_PLAYBACK_STARTON 8 -#define SF_PLAYBACK_3D 16 // Position info is used -#define SF_PLAYBACK_MUSICFILE 64 // Internal use, used to distinguish .mod, .s3m, .xm files -#define SF_PLAYBACK_SAMPLE 128 // Used to distinguish samples from streams -#define SF_PLAYBACK_TURNED_OFF 256 // Internal use, set when a target_playback is TURNED OFF rather - // than simply reaching the end - -HMODULE hFMOD=(HMODULE)NULL; // Handle of fmod.dll -bool qFMOD_Footsteps; // Set to false in SP_worldspawn for DM/coop - -struct texsurf_s -{ - int step_id; - char tex[16]; -}; -typedef struct texsurf_s texsurf_t; -#define MAX_TEX_SURF 256 -texsurf_t tex_surf[MAX_TEX_SURF]; -int num_texsurfs; - - -/* Here's what Lazarus does at the end of SP_worldspawn: - - if(footstep_sounds->value) - world->effects |= FX_WORLDSPAWN_STEPSOUNDS; - - if(deathmatch->value || coop->value) - qFMOD_Footsteps = false; - else if(world->effects & FX_WORLDSPAWN_STEPSOUNDS) - { - qFMOD_Footsteps = true; - FMOD_Init(); - } - else - qFMOD_Footsteps = false; - - You'll notice that we don't use FMOD to play any footstep sounds UNLESS a map effects flag is - set - the only good reason for this requirement is kinda complicated: 1) FMOD doesn't like - "s_primary 1" at all, and using that setting will foul up ALL sounds on some sound cards - whether any FMOD functions are used or not. 2) We want to precache footstep sounds for - performance reasons. However, we can't know at runtime whether any surfaces in the map - use new surface flags for footsteps. So.. we want to call FMOD_Init to load FMOD and - precache footsteps, but we DON'T want to do that unless we really need to so that players - who normally use "s_primary 1" can continue to do so. - - The footstep_sounds cvar forces STEPSOUNDS on, AND tells the code to check for the - existence of and read texsurfs.txt in the game folder. Surface flag values override settings - in texsurfs.txt. - - One nice optimization - once a match is found for a texture in texsurfs.txt, the - applicable surface_t structure has the appropriate surface flag set by the code. This means - that subsequent checks of the surface will involve only an integer comparison rather than - searching through the table with many string comparisons. Also, if a texture is NOT found - in texsurfs.txt, SURF_STANDARD gets set so that we don't need to check this surface again. -*/ - -/* All of the following isn't strictly necessary. Rather than using LoadLibrary and - GetProcAddress for all the FMOD functions, you COULD just link to their import - library. However, that means that your DLL will fail to load if FMOD.DLL isn't - found. Doing it this way removes that problem. Note that you'll also need to - comment out all of the API definitions in FMOD.H if you use this method. */ - -typedef signed char (__stdcall *FMUSIC_FREESONG) (FMUSIC_MODULE *mod); -typedef int (__stdcall *FMUSIC_GETMASTERVOLUME) (FMUSIC_MODULE *mod); -typedef signed char (__stdcall *FMUSIC_ISPLAYING) (FMUSIC_MODULE *mod); -typedef FMUSIC_MODULE *(__stdcall *FMUSIC_LOADSONG) (const char *name); -typedef signed char (__stdcall *FMUSIC_SETMASTERVOLUME) (FMUSIC_MODULE *mod,int volume); -typedef signed char (__stdcall *FMUSIC_PLAYSONG) (FMUSIC_MODULE *mod); -typedef void (__stdcall *FMUSIC_STOPALLSONGS) (); -typedef signed char (__stdcall *FMUSIC_STOPSONG) (FMUSIC_MODULE *mod); - -typedef void (__stdcall *FSOUND_3D_LISTENER_SETATTRIBUTES) (float *pos,float *vel,float fx,float fy,float fz,float tx,float ty,float tz); -typedef void (__stdcall *FSOUND_3D_LISTENER_SETDISTANCEFACTOR) (float scale); -typedef void (__stdcall *FSOUND_3D_LISTENER_SETDOPPLERFACTOR) (float scale); -typedef void (__stdcall *FSOUND_3D_LISTENER_SETROLLOFFFACTOR) (float scale); -typedef signed char (__stdcall *FSOUND_3D_SETATTRIBUTES) (int channel,float *pos,float *vel); -typedef void (__stdcall *FSOUND_3D_UPDATE) (); -typedef void (__stdcall *FSOUND_CLOSE) (); -typedef int (__stdcall *FSOUND_GETERROR) (); -typedef int (__stdcall *FSOUND_GETVOLUME) (int channel); -typedef signed char (__stdcall *FSOUND_INIT) (int mixrate, - int maxsoftwarechannels, - unsigned int flags ); -typedef signed char (__stdcall *FSOUND_ISPLAYING) (int channel); -typedef int (__stdcall *FSOUND_PLAYSOUND3DATTRIB) (int channel, - FSOUND_SAMPLE *sptr, - int freq, - int vol, - int pan, - float *pos, - float *vel); -typedef signed char (__stdcall *FSOUND_REVERB_SETMIX) (int channel, float mix); -typedef void (__stdcall *FSOUND_SAMPLE_FREE) (FSOUND_SAMPLE *sptr); -typedef FSOUND_SAMPLE *(__stdcall *FSOUND_SAMPLE_LOAD) (int index,const char *name,unsigned int mode,int memlength); -typedef signed char (__stdcall *FSOUND_SAMPLE_SETMINMAXDISTANCE) (FSOUND_SAMPLE *sptr,float min,float max); - -typedef signed char (__stdcall *FSOUND_SETBUFFERSIZE) (int len_ms); -typedef signed char (__stdcall *FSOUND_SETMIXER) (int mixer); -typedef signed char (__stdcall *FSOUND_SETOUTPUT) (int outputtype); -typedef signed char (__stdcall *FSOUND_SETVOLUME) (int channel, int volume); -typedef signed char (__stdcall *FSOUND_STOPSOUND) (int channel); -typedef signed char (__stdcall *FSOUND_STREAM_CLOSE) (FSOUND_STREAM *stream); -typedef int (__stdcall *FSOUND_STREAM_GETLENGTHMS) (FSOUND_STREAM *stream); -typedef FSOUND_STREAM *(__stdcall *FSOUND_STREAM_OPENFILE) (const char *filename, - unsigned int mode, - int memlength); -typedef int (__stdcall *FSOUND_STREAM_PLAY) (int channel, FSOUND_STREAM *stream); -typedef int (__stdcall *FSOUND_STREAM_PLAY3DATTRIB) (int channel, - FSOUND_STREAM *stream, - int freq, - int vol, - int pan, - float *pos, - float *vel ); -typedef signed char (__stdcall *FSOUND_STREAM_SETENDCALLBACK) (FSOUND_STREAM *stream, - FSOUND_STREAMCALLBACK callback, - int userdata); - - -FMUSIC_FREESONG FMUSIC_FreeSong; -FMUSIC_GETMASTERVOLUME FMUSIC_GetMasterVolume; -FMUSIC_ISPLAYING FMUSIC_IsPlaying; -FMUSIC_LOADSONG FMUSIC_LoadSong; -FMUSIC_PLAYSONG FMUSIC_PlaySong; -FMUSIC_SETMASTERVOLUME FMUSIC_SetMasterVolume; -FMUSIC_STOPALLSONGS FMUSIC_StopAllSongs; -FMUSIC_STOPSONG FMUSIC_StopSong; - -FSOUND_3D_LISTENER_SETATTRIBUTES FSOUND_3D_Listener_SetAttributes; -FSOUND_3D_LISTENER_SETDISTANCEFACTOR FSOUND_3D_Listener_SetDistanceFactor; -FSOUND_3D_LISTENER_SETDOPPLERFACTOR FSOUND_3D_Listener_SetDopplerFactor; -FSOUND_3D_LISTENER_SETROLLOFFFACTOR FSOUND_3D_Listener_SetRolloffFactor; -FSOUND_3D_SETATTRIBUTES FSOUND_3D_SetAttributes; -FSOUND_3D_UPDATE FSOUND_3D_Update; -FSOUND_CLOSE FSOUND_Close; -FSOUND_GETERROR FSOUND_GetError; -FSOUND_GETVOLUME FSOUND_GetVolume; -FSOUND_INIT FSOUND_Init; -FSOUND_ISPLAYING FSOUND_IsPlaying; -FSOUND_PLAYSOUND3DATTRIB FSOUND_PlaySound3DAttrib; -FSOUND_REVERB_SETMIX FSOUND_Reverb_SetMix; -FSOUND_SAMPLE_FREE FSOUND_Sample_Free; -FSOUND_SAMPLE_LOAD FSOUND_Sample_Load; -FSOUND_SAMPLE_SETMINMAXDISTANCE FSOUND_Sample_SetMinMaxDistance; -FSOUND_SETOUTPUT FSOUND_SetOutput; -FSOUND_SETVOLUME FSOUND_SetVolume; -FSOUND_STOPSOUND FSOUND_StopSound; -FSOUND_STREAM_CLOSE FSOUND_Stream_Close; -FSOUND_STREAM_GETLENGTHMS FSOUND_Stream_GetLengthMs; -FSOUND_STREAM_OPENFILE FSOUND_Stream_OpenFile; -FSOUND_STREAM_PLAY FSOUND_Stream_Play; -FSOUND_STREAM_PLAY3DATTRIB FSOUND_Stream_Play3DAttrib; -FSOUND_STREAM_SETENDCALLBACK FSOUND_Stream_SetEndCallback; - -/* Lazarus currently has 44 footstep sounds. These sounds are precached to avoid - a barely noticeable hiccup when the sounds are first played. The #defines for the - Footstep[] indices are in const.h */ - -FSOUND_SAMPLE *Footstep[44]; - -void PlayFootstep(edict_t *ent, footstep_t index) -{ - if(index < 0) - ent->s.event = EV_FOOTSTEP; - else - { - if(hFMOD && Footstep[index]) - FSOUND_PlaySound3DAttrib(FSOUND_FREE, Footstep[index], -1, 128, -1, NULL, NULL ); - else - ent->s.event = EV_FOOTSTEP; - } - /* Mapper has the option of setting a worldspawn flag to generate a "player_noise" - entity when the player makes a footstep sound. Normally, monsters ignore footsteps. */ - if(world->effects & FX_WORLDSPAWN_ALERTSOUNDS) - PlayerNoise(ent,ent->s.origin,PNOISE_SELF); -} - -char *FootFile(char *in) -{ - static char filename[256]; - static char prefix[256]; - static int init=0; - - if(!init) - { - cvar_t *basedir, *gamedir; - basedir = gi.cvar("basedir", "", 0); - gamedir = gi.cvar("gamedir", "", 0); - if(strlen(gamedir->string)) - sprintf(prefix,"%s/%s/sound/player/",basedir->string,gamedir->string); - else - sprintf(prefix,"%s/sound/player/",basedir->string); - init = 1; - } - sprintf(filename,"%s%s",prefix,in); - return filename; -} -void PrecacheFootsteps() -{ - int mode=FSOUND_LOOP_OFF | FSOUND_2D; - - if(!hFMOD) - return; - - Footstep[FOOTSTEP_SLOSH1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_slosh1.wav"), mode, 0); - Footstep[FOOTSTEP_SLOSH2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_slosh2.wav"), mode, 0); - Footstep[FOOTSTEP_SLOSH3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_slosh3.wav"), mode, 0); - Footstep[FOOTSTEP_SLOSH4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_slosh4.wav"), mode, 0); - Footstep[FOOTSTEP_LADDER1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_ladder1.wav"), mode, 0); - Footstep[FOOTSTEP_LADDER2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_ladder2.wav"), mode, 0); - Footstep[FOOTSTEP_LADDER3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_ladder3.wav"), mode, 0); - Footstep[FOOTSTEP_LADDER4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_ladder4.wav"), mode, 0); - Footstep[FOOTSTEP_METAL1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_metal1.wav"), mode, 0); - Footstep[FOOTSTEP_METAL2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_metal2.wav"), mode, 0); - Footstep[FOOTSTEP_METAL3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_metal3.wav"), mode, 0); - Footstep[FOOTSTEP_METAL4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_metal4.wav"), mode, 0); - Footstep[FOOTSTEP_DIRT1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_dirt1.wav"), mode, 0); - Footstep[FOOTSTEP_DIRT2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_dirt2.wav"), mode, 0); - Footstep[FOOTSTEP_DIRT3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_dirt3.wav"), mode, 0); - Footstep[FOOTSTEP_DIRT4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_dirt4.wav"), mode, 0); - Footstep[FOOTSTEP_VENT1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_duct1.wav"), mode, 0); - Footstep[FOOTSTEP_VENT2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_duct2.wav"), mode, 0); - Footstep[FOOTSTEP_VENT3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_duct3.wav"), mode, 0); - Footstep[FOOTSTEP_VENT4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_duct4.wav"), mode, 0); - Footstep[FOOTSTEP_GRATE1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grate1.wav"), mode, 0); - Footstep[FOOTSTEP_GRATE2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grate2.wav"), mode, 0); - Footstep[FOOTSTEP_GRATE3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grate3.wav"), mode, 0); - Footstep[FOOTSTEP_GRATE4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grate4.wav"), mode, 0); - Footstep[FOOTSTEP_TILE1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_tile1.wav"), mode, 0); - Footstep[FOOTSTEP_TILE2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_tile2.wav"), mode, 0); - Footstep[FOOTSTEP_TILE3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_tile3.wav"), mode, 0); - Footstep[FOOTSTEP_TILE4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_tile4.wav"), mode, 0); - Footstep[FOOTSTEP_GRASS1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grass1.wav"), mode, 0); - Footstep[FOOTSTEP_GRASS2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grass2.wav"), mode, 0); - Footstep[FOOTSTEP_GRASS3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grass3.wav"), mode, 0); - Footstep[FOOTSTEP_GRASS4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_grass4.wav"), mode, 0); - Footstep[FOOTSTEP_SNOW1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_snow1.wav"), mode, 0); - Footstep[FOOTSTEP_SNOW2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_snow2.wav"), mode, 0); - Footstep[FOOTSTEP_SNOW3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_snow3.wav"), mode, 0); - Footstep[FOOTSTEP_SNOW4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_snow4.wav"), mode, 0); - Footstep[FOOTSTEP_CARPET1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_carpet1.wav"), mode, 0); - Footstep[FOOTSTEP_CARPET2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_carpet2.wav"), mode, 0); - Footstep[FOOTSTEP_CARPET3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_carpet3.wav"), mode, 0); - Footstep[FOOTSTEP_CARPET4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_carpet4.wav"), mode, 0); - Footstep[FOOTSTEP_FORCE1] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_force1.wav"), mode, 0); - Footstep[FOOTSTEP_FORCE2] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_force2.wav"), mode, 0); - Footstep[FOOTSTEP_FORCE3] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_force3.wav"), mode, 0); - Footstep[FOOTSTEP_FORCE4] = FSOUND_Sample_Load(FSOUND_FREE,FootFile("pl_force4.wav"), mode, 0); -} - -/* -================= -FootStep - -Plays appropriate footstep sound depending on surface flags of the ground. -Since this is a replacement for plain Jane EV_FOOTSTEP, we already know -the player is definitely on the ground when this is called. -================= -*/ -void FootStep(edict_t *ent) -{ - static int iSkipStep = 0; - - trace_t tr; - vec3_t end; - int r; - int surface; - - r = (rand() & 1) + ent->client->leftfoot*2; - ent->client->leftfoot = 1 - ent->client->leftfoot; - - if(qFMOD_Footsteps) - { - if((ent->waterlevel == 1) && (ent->watertype & CONTENTS_WATER)) - { - // Slosh sounds - PlayFootstep(ent,FOOTSTEP_SLOSH1 + r); - return; - } - if((ent->waterlevel == 2) && (ent->watertype & CONTENTS_WATER)) - { - // Wade sounds - if(iSkipStep == 0) - { - iSkipStep++; - return; - } - if(iSkipStep++ == 3) - iSkipStep = 0; - - switch(r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade2.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade1.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade3.wav"),1.0,ATTN_NORM,0); break; - } - if(world->effects & FX_WORLDSPAWN_ALERTSOUNDS) - PlayerNoise(ent,ent->s.origin,PNOISE_SELF); - return; - } - VectorCopy(ent->s.origin,end); - end[2] -= 64; - tr = gi.trace(ent->s.origin,NULL,NULL,end,ent,MASK_SOLID | MASK_WATER); - if(!tr.surface) - { - PlayFootstep(ent,-1); - return; - } - - surface = tr.surface->flags & SURF_STEPMASK; - switch (surface) { - case SURF_METAL: - PlayFootstep(ent,FOOTSTEP_METAL1 + r); - break; - case SURF_DIRT: - PlayFootstep(ent,FOOTSTEP_DIRT1 + r); - break; - case SURF_VENT: - PlayFootstep(ent,FOOTSTEP_VENT1 + r); - break; - case SURF_GRATE: - PlayFootstep(ent,FOOTSTEP_GRATE1 + r); - break; - case SURF_TILE: - PlayFootstep(ent,FOOTSTEP_TILE1 + r); - break; - case SURF_GRASS: - PlayFootstep(ent,FOOTSTEP_GRASS1 + r); - break; - case SURF_SNOW: - PlayFootstep(ent,FOOTSTEP_SNOW1 + r); - break; - case SURF_CARPET: - PlayFootstep(ent,FOOTSTEP_CARPET1 + r); - break; - case SURF_FORCE: - PlayFootstep(ent,FOOTSTEP_FORCE1 + r); - break; - case SURF_STANDARD: - PlayFootstep(ent,-1); - break; - default: - if(footstep_sounds->value && num_texsurfs) - { - int i; - int step=-1; - for(i=0; iname,tex_surf[i].tex)) - { - if(!tex_surf[i].step_id) - { - step = -1; - tr.surface->flags |= SURF_STANDARD; - } - else - { - step = 4*(tex_surf[i].step_id-1) + r; - tr.surface->flags |= (SURF_METAL << (tex_surf[i].step_id - 1)); - } - break; - } - } - PlayFootstep(ent,step); - } - else - PlayFootstep(ent,-1); - } - } - else - { // Use normal Q2 sound. Note that no provisions are made for potential - // Index Overflow problems. Coders need to make sure that mappers are - // aware of this for multiplayer (non-FMOD) maps. - if((ent->waterlevel == 1) && (ent->watertype & CONTENTS_WATER)) - { - // Slosh sounds - switch(r) - { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_slosh1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_slosh3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_slosh2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_slosh4.wav"),1.0,ATTN_NORM,0); break; - } - if(world->effects & FX_WORLDSPAWN_ALERTSOUNDS) - PlayerNoise(ent,ent->s.origin,PNOISE_SELF); - return; - } - if((ent->waterlevel == 2) && (ent->watertype & CONTENTS_WATER)) - { - // Wade sounds - if(iSkipStep == 0) - { - iSkipStep++; - return; - } - if(iSkipStep++ == 3) - iSkipStep = 0; - - switch(r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade2.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade1.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/wade3.wav"),1.0,ATTN_NORM,0); break; - } - if(world->effects & FX_WORLDSPAWN_ALERTSOUNDS) - PlayerNoise(ent,ent->s.origin,PNOISE_SELF); - return; - } - VectorCopy(ent->s.origin,end); - end[2] -= 32; - tr = gi.trace(ent->s.origin,NULL,NULL,end,ent,MASK_SOLID | MASK_WATER); - if(!tr.surface) - { - PlayFootstep(ent,-1); - return; - } - - surface = tr.surface->flags & SURF_STEPMASK; - switch (surface) { - case SURF_METAL: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_DIRT: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_VENT: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_GRATE: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_TILE: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_GRASS: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_SNOW: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_CARPET: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet4.wav"),1.0,ATTN_NORM,0); break; - } - break; - case SURF_FORCE: - switch (r) { - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force4.wav"),1.0,ATTN_NORM,0); break; - } - break; - default: - if(footstep_sounds->value && num_texsurfs) - { - int i; - int step=-1; - for(i=0; iname,tex_surf[i].tex)) - { - if(!tex_surf[i].step_id) - { - step = -1; - tr.surface->flags |= SURF_STANDARD; - } - else - { - step = 4*(tex_surf[i].step_id-1) + r; - tr.surface->flags |= (SURF_METAL << (tex_surf[i].step_id - 1)); - } - break; - } - } - switch(step) - { - case FOOTSTEP_METAL1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_METAL2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_METAL3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_METAL4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_metal4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_DIRT1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_DIRT2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_DIRT3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_DIRT4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_dirt4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_VENT1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_VENT2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_VENT3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_VENT4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_duct4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRATE1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRATE2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRATE3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRATE4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grate4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_TILE1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_TILE2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_TILE3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_TILE4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_tile4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRASS1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRASS2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRASS3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_GRASS4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_grass4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_SNOW1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_SNOW2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_SNOW3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_SNOW4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_snow4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_CARPET1:gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_CARPET2:gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_CARPET3:gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_CARPET4:gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_carpet4.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_FORCE1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force1.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_FORCE2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force3.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_FORCE3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force2.wav"),1.0,ATTN_NORM,0); break; - case FOOTSTEP_FORCE4: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_force4.wav"),1.0,ATTN_NORM,0); break; - default: ent->s.event = EV_FOOTSTEP; - } - } - else - ent->s.event = EV_FOOTSTEP; - } - if(world->effects & FX_WORLDSPAWN_ALERTSOUNDS) - PlayerNoise(ent,ent->s.origin,PNOISE_SELF); - } -} - -void ReadTextureSurfaceAssignments() -{ - file_t *f; - char line[1024]; - - num_texsurfs = 0; - - f = gi.Fs.Open("scripts/texsurfs.txt","rt"); - if(!f) return; - - //UNDONE: get params with parsing fcts - while(gi.Fs.Gets(f, line, sizeof(line)) && num_texsurfs < MAX_TEX_SURF) - { -// gi.dprintf("%d %s\n",tex_surf[num_texsurfs].step_id,tex_surf[num_texsurfs].tex); - num_texsurfs++; - } - - gi.Fs.Close(f); -} - -/* All other footstep-related code is in p_view.c. Short version: replace all - "ent->s.event = EV_FOOTSTEP" with a call to Footstep and check out G_SetClientEvent, - where water and ladder sounds are played. */ - -bool FMOD_Init() -{ - char dllname[_MAX_PATH]; - - if(!deathmatch) - deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH); - - /* This is a Lazarus-specific cvar that overrides the decision to not use FMOD in - DM. Only reason to do this is if you want to use FMOD while playing against bots. - Don't ask me about the crazy name - this is what MD suggested :-) */ - if(!packet_fmod_playback) - packet_fmod_playback = gi.cvar("packet_fmod_playback", "0", CVAR_SERVERINFO); - - /* FMOD really really REALLY does not like "s_primary 1", particularly on better - sound cards. We tried all sorts of workarounds to no avail before settling on - bitching at the player and making it HIS fault. */ - if(!s_primary) - s_primary = gi.cvar("s_primary", "0", 0); - if(s_primary->value) - { - gi.dprintf("target_playback requires s_primary be set to 0.\n" - "At the console type:\n" - "s_primary 0;sound_restart\n"); - } - - if(deathmatch->value && !packet_fmod_playback->value) - { - hFMOD = (HMODULE)(NULL); - return false; - } - GameDirRelativePath("fmod.dll",dllname); - hFMOD = LoadLibrary(dllname); - if(hFMOD) - { - FMUSIC_FreeSong = (FMUSIC_FREESONG)GetProcAddress(hFMOD,"_FMUSIC_FreeSong@4"); - FMUSIC_GetMasterVolume = (FMUSIC_GETMASTERVOLUME)GetProcAddress(hFMOD,"_FMUSIC_GetMasterVolume@4"); - FMUSIC_IsPlaying = (FMUSIC_ISPLAYING)GetProcAddress(hFMOD,"_FMUSIC_IsPlaying@4"); - FMUSIC_LoadSong = (FMUSIC_LOADSONG)GetProcAddress(hFMOD,"_FMUSIC_LoadSong@4"); - FMUSIC_PlaySong = (FMUSIC_PLAYSONG)GetProcAddress(hFMOD,"_FMUSIC_PlaySong@4"); - FMUSIC_SetMasterVolume = (FMUSIC_SETMASTERVOLUME)GetProcAddress(hFMOD,"_FMUSIC_SetMasterVolume@8"); - FMUSIC_StopAllSongs = (FMUSIC_STOPALLSONGS)GetProcAddress(hFMOD,"_FMUSIC_StopAllSongs@0"); - FMUSIC_StopSong = (FMUSIC_STOPSONG)GetProcAddress(hFMOD,"_FMUSIC_StopSong@4"); - - FSOUND_3D_Listener_SetAttributes = (FSOUND_3D_LISTENER_SETATTRIBUTES)GetProcAddress(hFMOD,"_FSOUND_3D_Listener_SetAttributes@32"); - FSOUND_3D_Listener_SetDistanceFactor = (FSOUND_3D_LISTENER_SETDISTANCEFACTOR)GetProcAddress(hFMOD,"_FSOUND_3D_Listener_SetDistanceFactor@4"); - FSOUND_3D_Listener_SetDopplerFactor = (FSOUND_3D_LISTENER_SETDOPPLERFACTOR)GetProcAddress(hFMOD,"_FSOUND_3D_Listener_SetDopplerFactor@4"); - FSOUND_3D_Listener_SetRolloffFactor = (FSOUND_3D_LISTENER_SETROLLOFFFACTOR)GetProcAddress(hFMOD,"_FSOUND_3D_Listener_SetRolloffFactor@4"); - FSOUND_3D_SetAttributes = (FSOUND_3D_SETATTRIBUTES)GetProcAddress(hFMOD,"_FSOUND_3D_SetAttributes@12"); - FSOUND_3D_Update = (FSOUND_3D_UPDATE)GetProcAddress(hFMOD,"_FSOUND_3D_Update@0"); - FSOUND_Close = (FSOUND_CLOSE)GetProcAddress(hFMOD,"_FSOUND_Close@0"); - FSOUND_GetError = (FSOUND_GETERROR)GetProcAddress(hFMOD,"_FSOUND_GetError@0"); - FSOUND_GetVolume = (FSOUND_GETVOLUME)GetProcAddress(hFMOD,"_FSOUND_GetVolume@4"); - FSOUND_Init = (FSOUND_INIT)GetProcAddress(hFMOD,"_FSOUND_Init@12"); - FSOUND_IsPlaying = (FSOUND_ISPLAYING)GetProcAddress(hFMOD,"_FSOUND_IsPlaying@4"); - FSOUND_PlaySound3DAttrib = (FSOUND_PLAYSOUND3DATTRIB)GetProcAddress(hFMOD,"_FSOUND_PlaySound3DAttrib@28"); - FSOUND_Reverb_SetMix = (FSOUND_REVERB_SETMIX)GetProcAddress(hFMOD,"_FSOUND_Reverb_SetMix@8"); - FSOUND_Sample_Free = (FSOUND_SAMPLE_FREE)GetProcAddress(hFMOD,"_FSOUND_Sample_Free@4"); - FSOUND_Sample_Load = (FSOUND_SAMPLE_LOAD)GetProcAddress(hFMOD,"_FSOUND_Sample_Load@16"); - FSOUND_Sample_SetMinMaxDistance = (FSOUND_SAMPLE_SETMINMAXDISTANCE)GetProcAddress(hFMOD,"_FSOUND_Sample_SetMinMaxDistance@12"); - - FSOUND_SetOutput = (FSOUND_SETOUTPUT)GetProcAddress(hFMOD,"_FSOUND_SetOutput@4"); - FSOUND_SetVolume = (FSOUND_SETVOLUME)GetProcAddress(hFMOD,"_FSOUND_SetVolume@8"); - FSOUND_StopSound = (FSOUND_STOPSOUND)GetProcAddress(hFMOD,"_FSOUND_StopSound@4"); - FSOUND_Stream_Close = (FSOUND_STREAM_CLOSE)GetProcAddress(hFMOD,"_FSOUND_Stream_Close@4"); - FSOUND_Stream_GetLengthMs = (FSOUND_STREAM_GETLENGTHMS)GetProcAddress(hFMOD,"_FSOUND_Stream_GetLengthMs@4"); - FSOUND_Stream_OpenFile = (FSOUND_STREAM_OPENFILE)GetProcAddress(hFMOD,"_FSOUND_Stream_OpenFile@12"); - FSOUND_Stream_Play = (FSOUND_STREAM_PLAY)GetProcAddress(hFMOD,"_FSOUND_Stream_Play@8"); - FSOUND_Stream_Play3DAttrib= (FSOUND_STREAM_PLAY3DATTRIB)GetProcAddress(hFMOD,"_FSOUND_Stream_Play3DAttrib@28"); - FSOUND_Stream_SetEndCallback = (FSOUND_STREAM_SETENDCALLBACK)GetProcAddress(hFMOD,"_FSOUND_Stream_SetEndCallback@12"); - - if(!FSOUND_Init(44100, 32, 0)) - { - gi.dprintf("FSOUND_Init failed, error code=%d\n",FSOUND_GetError()); - FSOUND_Close(); - FreeLibrary(hFMOD); - hFMOD = (HMODULE)(-1); - return false; - } - FSOUND_3D_Listener_SetRolloffFactor(world->attenuation); - FSOUND_3D_Listener_SetDopplerFactor(world->moveinfo.distance); - if(qFMOD_Footsteps) - PrecacheFootsteps(); - return true; - } - return false; -} - -/* FMOD_Shutdown is called by ShutdownGame and also by our goofy - "sound_restart" console command (which I don't recommend duplicating). */ - -void FMOD_Shutdown() -{ - if(hFMOD) - { - FMOD_Stop(); // stops all target_playback sounds - FSOUND_Close(); - FreeLibrary(hFMOD); - hFMOD = (HMODULE)NULL; - } -} - -/*====================================================================================== - - Everything below this point is related to target_playback. Don't want target_playback? - Then you're done :-) - - Add these to the edict_s structure in g_local.h - - // FMOD - int *stream; // Actually a FSOUND_STREAM * or FMUSIC_MODULE * - int channel; - - Only other real change is in WriteLevel. The purpose of the mess below is - to restart a target_playback that was playing when the player left a level - if he returns to the same level. The linkcount business is used in - target_playback_delayed_restart to postpone playback until the player is - conscious - initial version didn't do this and it was disconcerting to - players to have music crank up while the level was loading. - - // write out all the entities - for (i=0 ; iinuse) - continue; - if (ent->class_id == ENTITY_TARGET_PLAYBACK) - { - edict_t e; - memcpy(&e,ent,sizeof(edict_t)); - if(FMOD_IsPlaying(ent)) - { - e.think = target_playback_delayed_restart; - e.nextthink = level.time + 1.0; - // A misuse of groundentity_linkcount, but - // maybe nobody is watching. - e.groundentity_linkcount = g_edicts[1].linkcount; - } - else - { - e.think = NULL; - e.nextthink = 0; - } - e.stream = NULL; - fwrite (&i, sizeof(i), 1, f); - WriteEdict (f, &e); - } - else - { - fwrite (&i, sizeof(i), 1, f); - WriteEdict (f, ent); - } - } - -=======================================================================================*/ - -/* FMOD_UpdateListenerPos is called every frame from G_RunFrame, but ONLY if the - map contains 3D sounds. Add this to the end of G_RunFrame: - - if ( (level.num_3D_sounds > 0) && (game.maxclients == 1)) - FMOD_UpdateListenerPos(); - - level.num_3D_sounds is incremented in SP_target_playback for 3D sounds and - decremented if a 3D target_playback "dies". - -*/ -void FMOD_UpdateListenerPos() -{ - vec3_t pos, vel, forward, up; - edict_t *player = &g_edicts[1]; - - if(!player || !player->inuse) - return; - - if(!hFMOD) return; - - AngleVectors(player->s.angles,forward,NULL,up); - VectorSet(pos,player->s.origin[1],player->s.origin[2],player->s.origin[0]); - VectorSet(vel,player->velocity[1],player->velocity[2],player->velocity[0]); - VectorScale(pos,0.025,pos); - VectorScale(vel,0.025,vel); - FSOUND_3D_Listener_SetAttributes(pos,vel,-forward[1],forward[2],-forward[0],-up[1],up[2],-up[0]); - FSOUND_3D_Update(); -} - -/* FMOD_UpdateSpeakerPos is called whenever a 3D target_playback moves. Only way to - move a target_playback in Lazarus currently is to set it to "movewith" a train. - Lazarus uses 40 Q2 units/meter scale factor (that's where the 0.025 below comes - in). FMOD *does* allow you to set a scale factor that supposedly allows you to - use whatever units you want rather than multiplying position and velocity every - time, but I found that it screws up the attenuation with distance features. */ - -void FMOD_UpdateSpeakerPos(edict_t *speaker) -{ - vec3_t pos, vel; - - if(!hFMOD) return; - - if(!speaker->stream) - return; - - VectorSet(pos,speaker->s.origin[1],speaker->s.origin[2],speaker->s.origin[0]); - VectorSet(vel,speaker->velocity[1],speaker->velocity[2],speaker->velocity[0]); - VectorScale(pos,0.025,pos); - VectorScale(vel,0.025,vel); - FSOUND_3D_SetAttributes(speaker->channel,pos,vel); -} - -/* FMOD_Stop stops all playback, but doesn't kill FMOD. It is called by - FMOD_Shutdown and use_target_changelevel. */ - -void FMOD_Stop() -{ - if(hFMOD) - { - edict_t *e; - int i; - - for(i=game.maxclients+1; iinuse) - continue; - if(!e->stream) - continue; - if(e->spawnflags & SF_PLAYBACK_MUSICFILE) - { - if(FMUSIC_IsPlaying((FMUSIC_MODULE *)e->stream)) - FMUSIC_StopSong ((FMUSIC_MODULE *)e->stream); - FMUSIC_FreeSong ((FMUSIC_MODULE *)e->stream); - } - else if(e->spawnflags & SF_PLAYBACK_SAMPLE) - { - FSOUND_StopSound(e->channel); - FSOUND_Sample_Free((FSOUND_SAMPLE *)e->stream); - } - else - FSOUND_Stream_Close((FSOUND_STREAM *)e->stream); - e->stream = NULL; - } - } - -} - -/* Music files don't have a "duration", or at least not one that you can have - reported by FMOD. So if you want to ramp them down, loop them, or do other - effects at the end of a song you'll have to have the music-playing - target_playback "think" with CheckEndMusic. */ - -void CheckEndMusic( edict_t *ent ) -{ - if(!ent->inuse) - return; - if(!ent->stream) - return; - if(!(ent->spawnflags & SF_PLAYBACK_MUSICFILE)) - return; - - if(FMUSIC_IsPlaying((FMUSIC_MODULE *)ent->stream)) - ent->nextthink = level.time + 1.0; - else - { - if(!(ent->spawnflags & SF_PLAYBACK_TURNED_OFF)) - { - if(ent->spawnflags & SF_PLAYBACK_LOOP) - { - // We didn't turn it off, so crank it back up - FMOD_PlaySound(ent); - return; - } - if(ent->target) - { - char *save_message; - save_message = ent->message; - ent->message = NULL; - G_UseTargets(ent, ent->activator); - ent->message = save_message; - } - } - FMUSIC_FreeSong ((FMUSIC_MODULE *)ent->stream); - ent->stream = NULL; - if(!ent->count) - G_FreeEdict(ent); - } -} - -void CheckEndSample(edict_t *ent) -{ - if(!ent->inuse) - return; - if(!ent->stream) - return; - if(FSOUND_IsPlaying(ent->channel)) - ent->nextthink = level.time + 1.0; - else - { - if(!(ent->spawnflags & SF_PLAYBACK_TURNED_OFF)) - { - if(ent->target) - { - char *save_message; - save_message = ent->message; - ent->message = NULL; - G_UseTargets(ent, ent->activator); - ent->message = save_message; - } - } - FSOUND_StopSound(ent->channel); - FSOUND_Sample_Free((FSOUND_SAMPLE *)ent->stream); - ent->stream = NULL; - if(!ent->count) - G_FreeEdict(ent); - } -} - -signed char EndStream(FSOUND_STREAM *stream,void *buff,int len,int param) -{ - edict_t *e; - - e = (edict_t *)param; - if(!e) - return TRUE; - if(!e->inuse) - return TRUE; - - if(!(e->spawnflags & SF_PLAYBACK_TURNED_OFF)) - { - if(e->target) - { - char *save_message; - save_message = e->message; - e->message = NULL; - G_UseTargets(e, e->activator); - e->message = save_message; - } - } - FSOUND_Stream_Close(stream); - e->stream = NULL; - if(!e->count) - G_FreeEdict(e); - - return TRUE; -} - -int FMOD_PlaySound(edict_t *ent) -{ - int mode; - - if(!hFMOD) - FMOD_Init(); - - if(!hFMOD) - { - gi.dprintf("FMOD.DLL not loaded\n"); - return 0; - } - - if(ent->spawnflags & SF_PLAYBACK_MUSICFILE) - { - ent->stream = (int *)FMUSIC_LoadSong(ent->message); - if(ent->stream) - { - FMUSIC_SetMasterVolume((FMUSIC_MODULE *)ent->stream,(int)(ent->volume)); - if( FMUSIC_PlaySong((FMUSIC_MODULE *)ent->stream) ) - { - ent->think = CheckEndMusic; - ent->nextthink = level.time + 1.0; - return 1; - } - else - { - gi.dprintf("FMUSIC_PlaySong failed on %s\n",ent->message); - return 0; - } - } - else - { - gi.dprintf("FMUSIC_LoadSong failed on %s\n",ent->message); - return 0; - } - } - else if(ent->spawnflags & SF_PLAYBACK_SAMPLE) - { - if(!ent->stream) - { - if(ent->spawnflags & SF_PLAYBACK_LOOP) - mode = FSOUND_LOOP_NORMAL; - else - mode = FSOUND_LOOP_OFF; - - if(!(ent->spawnflags & SF_PLAYBACK_3D)) - mode |= FSOUND_2D; - - ent->stream = (int *)FSOUND_Sample_Load(FSOUND_FREE,ent->message, mode, 0); - } - if(ent->stream) - { - int volume; - - if(ent->fadein > 0) - volume = 0; - else - volume = (int)(ent->volume); - - if(ent->spawnflags & SF_PLAYBACK_3D) - { - vec3_t pos; - - VectorSet(pos,ent->s.origin[1],ent->s.origin[2],ent->s.origin[0]); - VectorScale(pos,0.025,pos); - ent->channel = FSOUND_PlaySound3DAttrib(FSOUND_FREE, (FSOUND_SAMPLE *)ent->stream, -1, volume, -1, pos, NULL ); - FSOUND_Sample_SetMinMaxDistance( (FSOUND_SAMPLE *)ent->stream, ent->moveinfo.distance, 1000000000.0f); - FSOUND_Reverb_SetMix(ent->channel,1.0f); - } - else - { - ent->channel = FSOUND_PlaySound3DAttrib(FSOUND_FREE, (FSOUND_SAMPLE *)ent->stream, -1, volume, -1, NULL, NULL ); - FSOUND_Reverb_SetMix(ent->channel,1.0f); - } - - if(ent->channel >= 0) - { - ent->spawnflags &= ~SF_PLAYBACK_TURNED_OFF; - return 1; - } - else - { - gi.dprintf("FSOUND_PlaySound3DAttrib failed on %s\n",ent->message); - return 0; - } - } - else - { - gi.dprintf("FSOUND_Sample_Load failed on %s\n",ent->message); - ent->channel = -1; - return 0; - } - } - else - { - if(ent->spawnflags & SF_PLAYBACK_LOOP) - mode = FSOUND_LOOP_NORMAL; - else - mode = FSOUND_LOOP_OFF; - - // ??? Don't use FSOUND_HW3D because A3D cards screw up??? - - if(!(ent->spawnflags & SF_PLAYBACK_3D)) - mode |= FSOUND_2D; - - ent->stream = (int *)FSOUND_Stream_OpenFile(ent->message, mode, 0); - if(ent->stream) - { - int volume; - - if(ent->fadein > 0) - volume = 0; - else - volume = (int)(ent->volume); - - if(ent->spawnflags & SF_PLAYBACK_3D) - { - vec3_t pos; - - VectorSet(pos,ent->s.origin[1],ent->s.origin[2],ent->s.origin[0]); - VectorScale(pos,0.025,pos); - ent->channel = FSOUND_Stream_Play3DAttrib(FSOUND_FREE, (FSOUND_STREAM *)ent->stream, -1, volume, -1, pos, NULL ); - FSOUND_Reverb_SetMix(ent->channel,1.0f); - } - else - { - ent->channel = FSOUND_Stream_Play3DAttrib(FSOUND_FREE, (FSOUND_STREAM *)ent->stream, -1, volume, -1, NULL, NULL ); - FSOUND_Reverb_SetMix(ent->channel,1.0f); - } - - if(ent->channel >= 0) - { - ent->spawnflags &= ~SF_PLAYBACK_TURNED_OFF; - FSOUND_Stream_SetEndCallback((FSOUND_STREAM *)ent->stream,EndStream,(int)ent); - return 1; - } - else - { - gi.dprintf("FSOUND_Stream_Play3DAttrib failed on %s\n",ent->message); - return 0; - } - } - else - { - gi.dprintf("FSOUND_Stream_OpenFile failed on %s\n",ent->message); - ent->channel = -1; - return 0; - } - } -} - - -void FMOD_StopSound (edict_t *ent, bool free) -{ - if(!hFMOD) - return; - - ent->spawnflags |= SF_PLAYBACK_TURNED_OFF; - - if(ent->spawnflags & SF_PLAYBACK_MUSICFILE) - { - if(FMUSIC_IsPlaying((FMUSIC_MODULE *)ent->stream)) - FMUSIC_StopSong ((FMUSIC_MODULE *)ent->stream); - if(free) - { - FMUSIC_FreeSong ((FMUSIC_MODULE *)ent->stream); - ent->stream = NULL; - } - } - else if(ent->spawnflags & SF_PLAYBACK_SAMPLE) - { - if(FSOUND_IsPlaying(ent->channel)) - FSOUND_StopSound(ent->channel); - ent->channel = -1; - if(free) - { - FSOUND_Sample_Free((FSOUND_SAMPLE *)ent->stream); - ent->stream = NULL; - } - } - else - { - if(FSOUND_IsPlaying(ent->channel)) - FSOUND_StopSound(ent->channel); - ent->channel = -1; - if(free) - { - FSOUND_Stream_Close((FSOUND_STREAM *)ent->stream); - ent->stream = NULL; - } - } - - if(!ent->count) - G_FreeEdict(ent); -} - -void target_playback_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - if(!hFMOD) - return; - - // if it's 3D, decrement level 3D count for efficiency - if(self->spawnflags & SF_PLAYBACK_3D) - level.num_3D_sounds--; - - self->count = 0; - FMOD_StopSound(self,true); -} - -void target_playback_fadeout (edict_t *ent) -{ - int volume; - - if(!ent->stream) - return; - - if(ent->fadeout <= 0) // should never have come here? - return; - - if(level.time - ent->timestamp < ent->fadeout) - { - volume = (int)(ent->density * (1.0 - (level.time-ent->timestamp)/ent->fadeout)); - if(ent->spawnflags & SF_PLAYBACK_MUSICFILE) - FMUSIC_SetMasterVolume((FMUSIC_MODULE *)ent->stream,volume); - else - FSOUND_SetVolume(ent->channel,volume); - ent->nextthink = level.time + FRAMETIME; - } -} - -void target_playback_fadein (edict_t *ent) -{ - int volume; - - if(!ent->stream) - return; - - if(ent->fadein <= 0) // should never have come here? - return; - - if(level.time > ent->timestamp + ent->fadein) - return; - - volume = (int)(ent->volume*(level.time - ent->timestamp)/ent->fadein); - if(ent->spawnflags & SF_PLAYBACK_MUSICFILE) - FMUSIC_SetMasterVolume((FMUSIC_MODULE *)ent->stream,volume); - else - { - if(!FSOUND_SetVolume(ent->channel,volume)) - gi.dprintf("FSOUND_SetVolume failed, error code=%d, channel=%d\n",FSOUND_GetError(),ent->channel); - } - ent->nextthink = level.time + FRAMETIME; -} - -bool FMOD_IsPlaying(edict_t *ent) -{ - if(ent->spawnflags & SF_PLAYBACK_MUSICFILE) - { - if(ent->stream) - return FMUSIC_IsPlaying((FMUSIC_MODULE *)ent->stream); - else - return false; - } - else if(ent->channel >= 0) - { - return FSOUND_IsPlaying(ent->channel); - } - return false; -} - -void Use_Target_Playback (edict_t *ent, edict_t *other, edict_t *activator) -{ - vec3_t pos = {0, 0, 0}; - vec3_t vel = {0, 0, 0}; - int volume = 255; - - if(fmod_nomusic->value && (ent->spawnflags & SF_PLAYBACK_MUSIC)) - return; - - if(s_primary->value) - { - gi.dprintf("target_playback requires s_primary be set to 0.\n" - "At the console type:\n" - "s_primary 0;sound_restart\n"); - return; - } - - if(!ent->count) - { - if(ent->stream) - FMOD_StopSound(ent,true); - else - G_FreeEdict(ent); - return; - } - - if(FMOD_IsPlaying(ent)) - { - if(ent->spawnflags & (SF_PLAYBACK_LOOP | SF_PLAYBACK_TOGGLE)) - { - if(ent->fadeout > 0) - { - if(ent->spawnflags & SF_PLAYBACK_MUSICFILE) - ent->density = FMUSIC_GetMasterVolume((FMUSIC_MODULE *)ent->stream); - else - ent->density = FSOUND_GetVolume(ent->channel); - ent->timestamp = level.time; - ent->think = target_playback_fadeout; - ent->think(ent); - } - else - { - FMOD_StopSound (ent, ((ent->spawnflags & SF_PLAYBACK_SAMPLE) ? false : true )); - ent->think = NULL; - ent->nextthink = 0; - } - return; - } - else - { - // Not toggled - just turn it off then restart it below - FMOD_StopSound (ent, ((ent->spawnflags & SF_PLAYBACK_SAMPLE) ? false : true )); - ent->think = NULL; - ent->nextthink = 0; - } - } - - if( !FMOD_PlaySound(ent) ) - return; - - ent->count--; - ent->timestamp = level.time; - ent->activator = activator; - if(ent->fadein > 0) - { - ent->think = target_playback_fadein; - ent->nextthink = level.time + FRAMETIME; - } -} - -void target_playback_delayed_start (edict_t *ent) -{ - if(!g_edicts[1].linkcount || (ent->groundentity_linkcount == g_edicts[1].linkcount)) - ent->nextthink = level.time + FRAMETIME; - else - ent->use(ent,world,world); -} - -void target_playback_delayed_restart (edict_t *ent) -{ - if(!g_edicts[1].linkcount || (ent->groundentity_linkcount == g_edicts[1].linkcount)) - ent->nextthink = level.time + FRAMETIME; - else - { - ent->think = target_playback_delayed_start; - ent->nextthink = level.time + 2.0; - } -} - -void SP_target_playback (edict_t *ent) -{ - char filename[_MAX_PATH]; - - if(!hFMOD) - FMOD_Init(); - - if(!hFMOD) - { - gi.dprintf("fmod.dll not loaded, cannot use target_playback.\n"); - G_FreeEdict(ent); - return; - } - if(!st.noise) - { - gi.dprintf("target_playback with no noise set at %s\n", vtos(ent->s.origin)); - G_FreeEdict(ent); - return; - } - ent->class_id = ENTITY_TARGET_PLAYBACK; - GameDirRelativePath(st.noise,filename); - ent->message = TagMalloc(strlen(filename)+1,TAG_LEVEL); - strcpy(ent->message,filename); - - if (ent->fadein < 0) - ent->fadein = 0; - if (ent->fadeout < 0) - ent->fadeout = 0; - - strlwr(ent->message); - if( strstr(ent->message,".mod") || - strstr(ent->message,".s3m") || - strstr(ent->message,".xm") || - strstr(ent->message,".mid") ) - ent->spawnflags |= SF_PLAYBACK_MUSICFILE; - - if (!ent->volume) - ent->volume = 1.0; - ent->volume *= 255; - if (!ent->count) - ent->count = -1; - - if (ent->spawnflags & SF_PLAYBACK_3D) - { - if(!strstr(ent->message,".mp3")) - ent->spawnflags |= SF_PLAYBACK_SAMPLE; - level.num_3D_sounds++; - - if(st.distance) - ent->moveinfo.distance = st.distance * 0.025f; - else - ent->moveinfo.distance = 5.0f; - } - else - ent->spawnflags &= ~SF_PLAYBACK_SAMPLE; - - ent->use = Use_Target_Playback; - ent->die = target_playback_die; - - if (ent->spawnflags & SF_PLAYBACK_STARTON) - { - ent->think = target_playback_delayed_start; - ent->nextthink = level.time + 1.0; - } - - if(ent->movewith) - ent->movetype = MOVETYPE_PUSH; - else - ent->movetype = MOVETYPE_NONE; - gi.linkentity (ent); - - ent->stream = NULL; - ent->channel = -1; - if(ent->spawnflags & SF_PLAYBACK_SAMPLE) - { - // precache sound to prevent stutter when it finally IS played - int mode; - if(ent->spawnflags & SF_PLAYBACK_LOOP) - mode = FSOUND_LOOP_NORMAL; - else - mode = FSOUND_LOOP_OFF; - - if(!(ent->spawnflags & SF_PLAYBACK_3D)) - mode |= FSOUND_2D; - - ent->stream = (int *)FSOUND_Sample_Load(FSOUND_FREE,ent->message, mode, 0); - } -} - diff --git a/server/global/g_spawn.c b/server/global/g_spawn.c deleted file mode 100644 index d658263d..00000000 --- a/server/global/g_spawn.c +++ /dev/null @@ -1,1343 +0,0 @@ -#include "g_local.h" - -#ifdef WESQ2 -int NumSpawnedItems; -SPAWNED_ITEM SpawnedItem[MAX_SPAWNED_ITEMS]; -#endif - -void SP_item_health (edict_t *self); -void SP_item_health_small (edict_t *self); -void SP_item_health_large (edict_t *self); -void SP_item_health_mega (edict_t *self); - -void SP_info_player_start (edict_t *ent); -void SP_info_player_deathmatch (edict_t *ent); -void SP_info_player_coop (edict_t *ent); -void SP_info_player_intermission (edict_t *ent); - -void SP_func_plat (edict_t *ent); -void SP_func_rotating (edict_t *ent); -void SP_func_button (edict_t *ent); -void SP_func_door (edict_t *ent); -void SP_func_door_secret (edict_t *ent); -void SP_func_door_rotating (edict_t *ent); -void SP_func_water (edict_t *ent); -void SP_func_train (edict_t *ent); -void SP_func_conveyor (edict_t *self); -void SP_func_wall (edict_t *self); -void SP_func_object (edict_t *self); -void SP_func_explosive (edict_t *self); -void SP_func_timer (edict_t *self); -void SP_func_areaportal (edict_t *ent); -void SP_func_clock (edict_t *ent); -void SP_func_killbox (edict_t *ent); - -void SP_trigger_always (edict_t *ent); -void SP_trigger_once (edict_t *ent); -void SP_trigger_multiple (edict_t *ent); -void SP_trigger_relay (edict_t *ent); -void SP_trigger_push (edict_t *ent); -void SP_trigger_hurt (edict_t *ent); -void SP_trigger_key (edict_t *ent); -void SP_trigger_counter (edict_t *ent); -void SP_trigger_elevator (edict_t *ent); -void SP_trigger_gravity (edict_t *ent); -void SP_trigger_monsterjump (edict_t *ent); - -void SP_target_temp_entity (edict_t *ent); -void SP_target_speaker (edict_t *ent); -void SP_target_explosion (edict_t *ent); -void SP_target_changelevel (edict_t *ent); -void SP_target_secret (edict_t *ent); -void SP_target_goal (edict_t *ent); -void SP_target_splash (edict_t *ent); -void SP_target_spawner (edict_t *ent); -void SP_target_blaster (edict_t *ent); -void SP_target_crosslevel_trigger (edict_t *ent); -void SP_target_crosslevel_target (edict_t *ent); -void SP_target_laser (edict_t *self); -void SP_target_help (edict_t *ent); -void SP_target_actor (edict_t *ent); -void SP_target_lightramp (edict_t *self); -void SP_target_earthquake (edict_t *ent); -void SP_target_character (edict_t *ent); -void SP_target_string (edict_t *ent); - -void SP_worldspawn (edict_t *ent); -void SP_viewthing (edict_t *ent); - -void SP_light (edict_t *self); -void SP_light_mine1 (edict_t *ent); -void SP_light_mine2 (edict_t *ent); -void SP_info_null (edict_t *self); -void SP_info_notnull (edict_t *self); -void SP_path_corner (edict_t *self); -void SP_point_combat (edict_t *self); - -void SP_misc_explobox (edict_t *self); -void SP_misc_banner (edict_t *self); -void SP_misc_satellite_dish (edict_t *self); -void SP_misc_actor (edict_t *self); -void SP_misc_gib_arm (edict_t *self); -void SP_misc_gib_leg (edict_t *self); -void SP_misc_gib_head (edict_t *self); -void SP_misc_insane (edict_t *self); -void SP_misc_deadsoldier (edict_t *self); -void SP_misc_viper (edict_t *self); -void SP_misc_viper_bomb (edict_t *self); -void SP_misc_bigviper (edict_t *self); -void SP_misc_strogg_ship (edict_t *self); -void SP_misc_teleporter (edict_t *self); -void SP_misc_teleporter_dest (edict_t *self); -void SP_misc_blackhole (edict_t *self); -void SP_misc_eastertank (edict_t *self); -void SP_misc_easterchick (edict_t *self); -void SP_misc_easterchick2 (edict_t *self); - -void SP_monster_berserk (edict_t *self); -void SP_monster_gladiator (edict_t *self); -void SP_monster_gunner (edict_t *self); -void SP_monster_infantry (edict_t *self); -void SP_monster_soldier_light (edict_t *self); -void SP_monster_soldier (edict_t *self); -void SP_monster_soldier_ss (edict_t *self); -void SP_monster_tank (edict_t *self); -void SP_monster_medic (edict_t *self); -void SP_monster_flipper (edict_t *self); -void SP_monster_chick (edict_t *self); -void SP_monster_parasite (edict_t *self); -void SP_monster_flyer (edict_t *self); -void SP_monster_brain (edict_t *self); -void SP_monster_floater (edict_t *self); -void SP_monster_hover (edict_t *self); -void SP_monster_mutant (edict_t *self); -void SP_monster_supertank (edict_t *self); -void SP_monster_boss2 (edict_t *self); -void SP_monster_jorg (edict_t *self); -void SP_monster_boss3_stand (edict_t *self); - -void SP_monster_commander_body (edict_t *self); - -void SP_turret_breach (edict_t *self); -void SP_turret_base (edict_t *self); -void SP_turret_driver (edict_t *self); - -// Lazarus -void SP_crane_beam (edict_t *self); -void SP_crane_hoist (edict_t *self); -void SP_crane_hook (edict_t *self); -void SP_crane_control (edict_t *self); -void SP_crane_reset (edict_t *self); -void SP_hint_path (edict_t *self); -void SP_func_bobbingwater (edict_t *self); -void SP_func_door_rot_dh (edict_t *self); -void SP_func_door_swinging (edict_t *self); -void SP_func_force_wall(edict_t *ent); -void SP_func_monitor (edict_t *self); -void SP_func_pendulum (edict_t *self); -void SP_func_pivot (edict_t *self); -void SP_func_pushable (edict_t *self); -void SP_func_reflect (edict_t *self); -void SP_func_rotating_dh (edict_t *self); -void SP_func_trackchange (edict_t *self); -void SP_func_tracktrain (edict_t *self); -void SP_func_trainbutton (edict_t *self); -void SP_func_vehicle (edict_t *self); -void SP_info_train_start (edict_t *self); -void SP_misc_light (edict_t *self); -void SP_model_spawn (edict_t *self); -void SP_model_train (edict_t *self); -void SP_model_turret (edict_t *self); -void SP_monster_makron (edict_t *self); -void SP_path_track (edict_t *self); -void SP_target_anger (edict_t *self); -void SP_target_animation (edict_t *self); -void SP_target_attractor (edict_t *self); -void SP_target_CD (edict_t *self); -void SP_target_change (edict_t *self); -void SP_target_clone (edict_t *self); -void SP_target_effect (edict_t *self); -void SP_target_fade (edict_t *self); -void SP_target_failure (edict_t *self); -void SP_target_fog (edict_t *self); -void SP_target_fountain (edict_t *self); -void SP_target_lightswitch (edict_t *self); -void SP_target_locator (edict_t *self); -void SP_target_lock (edict_t *self); -void SP_target_lock_clue (edict_t *self); -void SP_target_lock_code (edict_t *self); -void SP_target_lock_digit (edict_t *self); -void SP_target_monitor (edict_t *ent); -void SP_target_monsterbattle (edict_t *self); -void SP_target_movewith (edict_t *self); -void SP_target_precipitation (edict_t *self); -void SP_target_rocks (edict_t *self); -void SP_target_rotation (edict_t *self); -void SP_target_set_effect (edict_t *self); -void SP_target_skill (edict_t *self); -void SP_target_sky (edict_t *self); -void SP_target_playback (edict_t *self); -void SP_target_text (edict_t *self); -void SP_thing (edict_t *self); -void SP_tremor_trigger_multiple (edict_t *self); -void SP_trigger_bbox (edict_t *self); -void SP_trigger_disguise (edict_t *self); -void SP_trigger_fog (edict_t *self); -void SP_trigger_inside (edict_t *self); -void SP_trigger_look (edict_t *self); -void SP_trigger_mass (edict_t *self); -void SP_trigger_scales (edict_t *self); -void SP_trigger_speaker (edict_t *self); -void SP_trigger_switch (edict_t *self); -void SP_trigger_teleporter (edict_t *self); -void SP_trigger_transition (edict_t *self); -// transition entities -void SP_bolt (edict_t *self); -void SP_debris (edict_t *self); -void SP_gib (edict_t *self); -void SP_gibhead (edict_t *self); -void SP_grenade (edict_t *self); -void SP_handgrenade (edict_t *self); -void SP_rocket (edict_t *self); -// -// end Lazarus - -#ifdef WESQ2 -void SP_misc_bomb (edict_t *self); -void SP_misc_ladder (edict_t *self); -void SP_misc_tank1 (edict_t *self); -void SP_misc_tank2 (edict_t *self); -#endif - -spawn_t spawns[] = { - {"item_health", SP_item_health}, - {"item_health_small", SP_item_health_small}, - {"item_health_large", SP_item_health_large}, - {"item_health_mega", SP_item_health_mega}, - - {"info_player_start", SP_info_player_start}, - {"info_player_deathmatch", SP_info_player_deathmatch}, - {"info_player_coop", SP_info_player_coop}, - {"info_player_intermission", SP_info_player_intermission}, - - {"func_plat", SP_func_plat}, - {"func_button", SP_func_button}, - {"func_door", SP_func_door}, - {"func_door_secret", SP_func_door_secret}, - {"func_door_rotating", SP_func_door_rotating}, - {"func_rotating", SP_func_rotating}, - {"func_train", SP_func_train}, - {"func_water", SP_func_water}, - {"func_conveyor", SP_func_conveyor}, - {"func_areaportal", SP_func_areaportal}, - {"func_clock", SP_func_clock}, - {"func_reflect", SP_func_reflect}, - {"func_wall", SP_func_wall}, - {"func_object", SP_func_object}, - {"func_timer", SP_func_timer}, - {"func_explosive", SP_func_explosive}, - {"func_killbox", SP_func_killbox}, - - {"target_actor", SP_target_actor}, - {"target_animation", SP_target_animation}, - {"target_blaster", SP_target_blaster}, - {"target_changelevel", SP_target_changelevel}, - {"target_character", SP_target_character}, - {"target_crosslevel_target", SP_target_crosslevel_target}, - {"target_crosslevel_trigger", SP_target_crosslevel_trigger}, - {"target_earthquake", SP_target_earthquake}, - {"target_explosion", SP_target_explosion}, - {"target_goal", SP_target_goal}, - {"target_help", SP_target_help}, - {"target_laser", SP_target_laser}, - {"target_lightramp", SP_target_lightramp}, - {"target_secret", SP_target_secret}, - {"target_spawner", SP_target_spawner}, - {"target_speaker", SP_target_speaker}, - {"target_splash", SP_target_splash}, - {"target_string", SP_target_string}, - {"target_temp_entity", SP_target_temp_entity}, - - {"trigger_always", SP_trigger_always}, - {"trigger_counter", SP_trigger_counter}, - {"trigger_elevator", SP_trigger_elevator}, - {"trigger_gravity", SP_trigger_gravity}, - {"trigger_hurt", SP_trigger_hurt}, - {"trigger_key", SP_trigger_key}, - {"trigger_once", SP_trigger_once}, - {"trigger_monsterjump", SP_trigger_monsterjump}, - {"trigger_multiple", SP_trigger_multiple}, - {"trigger_push", SP_trigger_push}, - {"trigger_relay", SP_trigger_relay}, - - {"viewthing", SP_viewthing}, - {"worldspawn", SP_worldspawn}, - - {"light", SP_light}, - {"light_mine1", SP_light_mine1}, - {"light_mine2", SP_light_mine2}, - {"info_null", SP_info_null}, - {"func_group", SP_info_null}, - {"info_notnull", SP_info_notnull}, - {"path_corner", SP_path_corner}, - {"point_combat", SP_point_combat}, - - {"misc_explobox", SP_misc_explobox}, - {"misc_banner", SP_misc_banner}, - {"misc_satellite_dish", SP_misc_satellite_dish}, - {"misc_actor", SP_misc_actor}, - {"misc_gib_arm", SP_misc_gib_arm}, - {"misc_gib_leg", SP_misc_gib_leg}, - {"misc_gib_head", SP_misc_gib_head}, - {"misc_insane", SP_misc_insane}, - {"misc_deadsoldier", SP_misc_deadsoldier}, - {"misc_viper", SP_misc_viper}, - {"misc_viper_bomb", SP_misc_viper_bomb}, - {"misc_bigviper", SP_misc_bigviper}, - {"misc_strogg_ship", SP_misc_strogg_ship}, - {"misc_teleporter", SP_misc_teleporter}, - {"misc_teleporter_dest", SP_misc_teleporter_dest}, - {"misc_blackhole", SP_misc_blackhole}, - {"misc_eastertank", SP_misc_eastertank}, - {"misc_easterchick", SP_misc_easterchick}, - {"misc_easterchick2", SP_misc_easterchick2}, - - {"monster_berserk", SP_monster_berserk}, - {"monster_gladiator", SP_monster_gladiator}, - {"monster_gunner", SP_monster_gunner}, - {"monster_infantry", SP_monster_infantry}, - {"monster_soldier_light", SP_monster_soldier_light}, - {"monster_soldier", SP_monster_soldier}, - {"monster_soldier_ss", SP_monster_soldier_ss}, - {"monster_tank", SP_monster_tank}, - {"monster_tank_commander", SP_monster_tank}, - {"monster_medic", SP_monster_medic}, - {"monster_flipper", SP_monster_flipper}, - {"monster_chick", SP_monster_chick}, - {"monster_parasite", SP_monster_parasite}, - {"monster_flyer", SP_monster_flyer}, - {"monster_brain", SP_monster_brain}, - {"monster_floater", SP_monster_floater}, - {"monster_hover", SP_monster_hover}, - {"monster_mutant", SP_monster_mutant}, - {"monster_supertank", SP_monster_supertank}, - {"monster_boss2", SP_monster_boss2}, - {"monster_boss3_stand", SP_monster_boss3_stand}, - {"monster_jorg", SP_monster_jorg}, - - {"monster_commander_body", SP_monster_commander_body}, - - {"turret_breach", SP_turret_breach}, - {"turret_base", SP_turret_base}, - {"turret_driver", SP_turret_driver}, - -// Lazarus - {"crane_beam", SP_crane_beam}, - {"crane_hoist", SP_crane_hoist}, - {"crane_hook", SP_crane_hook}, - {"crane_control",SP_crane_control}, - {"crane_reset",SP_crane_reset}, - {"func_bobbingwater", SP_func_bobbingwater}, - {"func_door_rot_dh", SP_func_door_rot_dh}, - {"func_door_swinging", SP_func_door_swinging}, - {"func_force_wall", SP_func_force_wall}, - {"func_monitor", SP_func_monitor}, - {"func_pendulum", SP_func_pendulum}, - {"func_pivot", SP_func_pivot}, - {"func_pushable", SP_func_pushable}, - {"func_rotating_dh", SP_func_rotating_dh}, - {"func_trackchange", SP_func_trackchange}, - {"func_tracktrain", SP_func_tracktrain}, - {"func_trainbutton", SP_func_trainbutton}, - {"func_vehicle", SP_func_vehicle}, - {"hint_path", SP_hint_path}, - {"info_train_start", SP_info_train_start}, - {"misc_light", SP_misc_light}, - {"model_spawn", SP_model_spawn}, - {"model_train", SP_model_train}, - {"model_turret", SP_model_turret}, - {"monster_makron", SP_monster_makron}, - {"path_track", SP_path_track}, - {"target_anger", SP_target_anger}, - {"target_attractor", SP_target_attractor}, - {"target_bmodel_spawner", SP_target_clone}, - {"target_cd", SP_target_CD}, - {"target_change", SP_target_change}, - {"target_clone", SP_target_clone}, - {"target_effect", SP_target_effect}, - {"target_fade", SP_target_fade}, - {"target_failure", SP_target_failure}, - {"target_fog", SP_target_fog}, - {"target_fountain", SP_target_fountain}, - {"target_lightswitch", SP_target_lightswitch}, - {"target_locator", SP_target_locator}, - {"target_lock", SP_target_lock}, - {"target_lock_clue", SP_target_lock_clue}, - {"target_lock_code", SP_target_lock_code}, - {"target_lock_digit", SP_target_lock_digit}, - {"target_monitor", SP_target_monitor}, - {"target_monsterbattle", SP_target_monsterbattle}, - {"target_movewith", SP_target_movewith}, - {"target_precipitation", SP_target_precipitation}, - {"target_rocks", SP_target_rocks}, - {"target_rotation", SP_target_rotation}, - {"target_set_effect", SP_target_set_effect}, - {"target_skill", SP_target_skill}, - {"target_sky", SP_target_sky}, - {"target_playback", SP_target_playback}, - {"target_text", SP_target_text}, - {"thing", SP_thing}, - {"tremor_trigger_multiple", SP_tremor_trigger_multiple}, - {"trigger_bbox", SP_trigger_bbox}, - {"trigger_disguise", SP_trigger_disguise}, - {"trigger_fog", SP_trigger_fog}, - {"trigger_inside", SP_trigger_inside}, - {"trigger_look", SP_trigger_look}, - {"trigger_mass", SP_trigger_mass}, - {"trigger_scales", SP_trigger_scales}, - {"trigger_speaker", SP_trigger_speaker}, - {"trigger_switch", SP_trigger_switch}, - {"trigger_teleporter", SP_trigger_teleporter}, - {"trigger_transition", SP_trigger_transition}, -// transition entities - {"bolt", SP_bolt}, - {"debris", SP_debris}, - {"gib", SP_gib}, - {"gibhead", SP_gibhead}, - {"grenade", SP_grenade}, - {"hgrenade", SP_handgrenade}, - {"rocket", SP_rocket}, - {"homing rocket", SP_rocket}, -// end Lazarus - -#ifdef WESQ2 - {"misc_bomb", SP_misc_bomb}, - {"misc_ladder", SP_misc_ladder}, - {"misc_tank1", SP_misc_tank1}, - {"misc_tank2", SP_misc_tank2}, -#endif - - {NULL, NULL} -}; - -/* -=============== -ED_CallSpawn - -Finds the spawn function for the entity and calls it -=============== -*/ -void ED_CallSpawn (edict_t *ent) -{ - spawn_t *s; - gitem_t *item; - int i; - - // Lazarus: if this fails, edict is freed. - - if (!ent->classname) - { - gi.dprintf ("ED_CallSpawn: NULL classname\n"); - G_FreeEdict(ent); - return; - } - - // Lazarus: Preserve original angles for movewith stuff - // before G_SetMoveDir wipes 'em out - VectorCopy(ent->s.angles, ent->org_angles); - - // check item spawn functions - for (i=0,item=itemlist ; iclassname) - continue; - if (!strcmp(item->classname, ent->classname)) - { // found it - SpawnItem (ent, item); - return; - } - } - - // check normal spawn functions - for (s=spawns ; s->name ; s++) - { - if (!strcmp(s->name, ent->classname)) - { // found it - s->spawn (ent); - return; - } - } - gi.dprintf ("%s doesn't have a spawn function\n", ent->classname); - G_FreeEdict(ent); -} - -/* -============= -ED_NewString -============= -*/ -char *ED_NewString (char *string) -{ - char *newb, *new_p; - int i,l; - - l = strlen(string) + 1; - - newb = TagMalloc (l, TAG_LEVEL); - - new_p = newb; - - for (i=0 ; i< l ; i++) - { - if (string[i] == '\\' && i < l-1) - { - i++; - if (string[i] == 'n') - *new_p++ = '\n'; - else - *new_p++ = '\\'; - } - else - *new_p++ = string[i]; - } - - return newb; -} - - - - -/* -=============== -ED_ParseField - -Takes a key/value pair and sets the binary values -in an edict -=============== -*/ -void ED_ParseField (char *key, char *value, edict_t *ent) -{ - field_t *f; - byte *b; - float v; - vec3_t vec; - - for (f=fields ; f->name ; f++) - { - if (!(f->flags & FFL_NOSPAWN) && !strcasecmp(f->name, key)) - { // found it - if (f->flags & FFL_SPAWNTEMP) - b = (byte *)&st; - else - b = (byte *)ent; - - switch (f->type) - { - case F_LSTRING: - *(char **)(b+f->ofs) = ED_NewString (value); - break; - case F_VECTOR: - sscanf (value, "%f %f %f", &vec[0], &vec[1], &vec[2]); - ((float *)(b+f->ofs))[0] = vec[0]; - ((float *)(b+f->ofs))[1] = vec[1]; - ((float *)(b+f->ofs))[2] = vec[2]; - break; - case F_INT: - *(int *)(b+f->ofs) = atoi(value); - break; - case F_FLOAT: - *(float *)(b+f->ofs) = atof(value); - break; - case F_ANGLEHACK: - v = atof(value); - ((float *)(b+f->ofs))[0] = 0; - ((float *)(b+f->ofs))[1] = v; - ((float *)(b+f->ofs))[2] = 0; - break; - case F_IGNORE: - break; - } - return; - } - } - gi.dprintf ("%s is not a field\n", key); -} - -/* -==================== -ED_ParseEdict - -Parses an edict out of the given string, returning the new position -ed should be a properly initialized empty edict. -==================== -*/ -char *ED_ParseEdict (char *data, edict_t *ent) -{ - bool init; - char keyname[256]; - char *com_token; - - init = false; - memset (&st, 0, sizeof(st)); - - // go through all the dictionary pairs - while (1) - { - // parse key - com_token = COM_Parse (&data); - if (com_token[0] == '}') break; - if (!data) gi.error ("ED_ParseEntity: EOF without closing brace"); - - strncpy (keyname, com_token, sizeof(keyname)-1); - - // parse value - com_token = COM_Parse (&data); - if (!data) gi.error ("ED_ParseEntity: EOF without closing brace"); - - if (com_token[0] == '}') - gi.error ("ED_ParseEntity: closing brace without data"); - - init = true; - - // keynames with a leading underscore are used for utility comments, - // and are immediately discarded by quake - if (keyname[0] == '_') continue; - - ED_ParseField (keyname, com_token, ent); - } - - if (!init) memset (ent, 0, sizeof(*ent)); - - return data; -} - - -/* -================ -G_FindTeams - -Chain together all entities with a matching team field. - -All but the first will have the FL_TEAMSLAVE flag set. -All but the last will have the teamchain field set to the next one -================ -*/ -void G_FindTeams (void) -{ - edict_t *e, *e2, *chain; - int i, j; - int c, c2; - - c = 0; - c2 = 0; - for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++) - { - if (!e->inuse) - continue; - if (!e->team) - continue; - if (e->flags & FL_TEAMSLAVE) - continue; - // Lazarus: some entities may have psuedo-teams that shouldn't be handled here - if (e->class_id == ENTITY_TARGET_CHANGE) - continue; - if (e->class_id == ENTITY_TARGET_CLONE) - continue; - chain = e; - e->teammaster = e; - c++; - c2++; - for (j=i+1, e2=e+1 ; j < globals.num_edicts ; j++,e2++) - { - if (!e2->inuse) - continue; - if (!e2->team) - continue; - if (e2->flags & FL_TEAMSLAVE) - continue; - if (!strcmp(e->team, e2->team)) - { - c2++; - chain->teamchain = e2; - e2->teammaster = e; - chain = e2; - e2->flags |= FL_TEAMSLAVE; - } - } - } - - if(level.time < 2) - gi.dprintf ("%i teams with %i entities\n", c, c2); -} - -void trans_ent_filename (char *); -void ReadEdict (file_t *f, edict_t *ent); -void LoadTransitionEnts() -{ - if(developer->value) gi.dprintf("==== LoadTransitionEnts ====\n"); - if(game.transition_ents) - { - char t_file[_MAX_PATH]; - int i, j; - file_t *f; - vec3_t v_spawn; - edict_t *ent; - edict_t *spawn; - - VectorClear(v_spawn); - if(strlen(game.spawnpoint)) - { - spawn = G_Find(NULL,FOFS(targetname),game.spawnpoint); - while(spawn) - { - if(spawn->class_id == ENTITY_INFO_PLAYER_START) - { - VectorCopy(spawn->s.origin,v_spawn); - break; - } - spawn = G_Find(spawn,FOFS(targetname),game.spawnpoint); - } - } - trans_ent_filename (t_file); - f = gi.Fs.Open(t_file,"rb"); - if(!f) gi.error("LoadTransitionEnts: Cannot open %s\n",t_file); - else - { - for(i=0; isvflags & SVF_MONSTER) - { - if(!ent->health) - { - ent->health = -1; - ent->deadflag = DEAD_DEAD; - } - else if(ent->deadflag == DEAD_DEAD) - { - ent->health = min(ent->health,-1); - } - } - VectorAdd(ent->s.origin,v_spawn,ent->s.origin); - VectorCopy(ent->s.origin,ent->s.old_origin); - ED_CallSpawn (ent); - if(ent->owner_id) - { - if(ent->owner_id < 0) - { - ent->owner = &g_edicts[-ent->owner_id]; - } - else - { - // We KNOW owners precede owned ents in the - // list because of the way it was constructed - ent->owner = NULL; - for(j=game.maxclients+1; jowner; j++) - { - if(ent->owner_id == g_edicts[j].id) - ent->owner = &g_edicts[j]; - } - } - ent->owner_id = 0; - } - ent->s.renderfx |= RF_IR_VISIBLE; - } - gi.Fs.Close(f); - } - } -} - -/* -============== -SpawnEntities - -Creates a server's entity / program execution context by -parsing textual entity definitions out of an ent file. -============== -*/ -void SpawnEntities (char *mapname, char *entities, char *spawnpoint) -{ - edict_t *ent; - int inhibit; - char *com_token; - int i; - float skill_level; - extern int max_modelindex; - extern int max_soundindex; - extern int lastgibframe; - - if(developer->value) - gi.dprintf("====== SpawnEntities ========\n"); - skill_level = floor (skill->value); - if (skill_level < 0) - skill_level = 0; - if (skill_level > 3) - skill_level = 3; - if (skill->value != skill_level) - gi.cvar_forceset("skill", va("%f", skill_level)); - - SaveClientData (); - - FreeTags (TAG_LEVEL); - - memset (&level, 0, sizeof(level)); - memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); - // Lazarus: these are used to track model and sound indices - // in g_main.c: - max_modelindex = 0; - max_soundindex = 0; - - // Lazarus: last frame a gib was spawned in - lastgibframe = 0; - - strncpy (level.mapname, mapname, sizeof(level.mapname)-1); - strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1); - - // set client fields on player ents - for (i=0 ; iclassname, "trigger_once") && !strcasecmp(ent->model, "*27")) - ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; - - // remove things (except the world) from different skill levels or deathmatch - if (ent != g_edicts) - { - if (deathmatch->value) - { - if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) - { - G_FreeEdict (ent); - inhibit++; - continue; - } - } - else - { - if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || - ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || - (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) - ) - { - G_FreeEdict (ent); - inhibit++; - continue; - } - } - - ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_DEATHMATCH); - } - - ED_CallSpawn (ent); - ent->s.renderfx |= RF_IR_VISIBLE; //PGM - } - -#ifdef WESQ2 - SpawnEntfileItems(); - ReadPeakPressures(); -#endif - - gi.dprintf ("%i entities inhibited\n", inhibit); - - G_FindTeams (); - - // DWH - G_FindCraneParts(); - - // Get origin offsets (mainly for brush models w/o origin brushes) - for (i=1, ent=g_edicts+i ; i < globals.num_edicts ; i++,ent++) - { - VectorAdd(ent->absmin,ent->absmax,ent->origin_offset); - VectorScale(ent->origin_offset,0.5,ent->origin_offset); - VectorSubtract(ent->origin_offset,ent->s.origin,ent->origin_offset); - } - - // end DWH - - PlayerTrail_Init (); - - if(!deathmatch->value) - InitHintPaths(); - - for(i=1, ent=g_edicts+i; i < globals.num_edicts; i++, ent++) - { - if(!ent->movewith) - continue; - if(ent->movewith_ent) - continue; - ent->movewith_ent = G_Find(NULL,FOFS(targetname),ent->movewith); - // Make sure that we can really "movewith" this guy. This check - // allows us to have movewith parent with same targetname as - // other entities - while(ent->movewith_ent && - ( (ent->movewith_ent->class_id != ENTITY_FUNC_TRAIN) && - (ent->movewith_ent->class_id != ENTITY_MODEL_TRAIN) && - (ent->movewith_ent->class_id != ENTITY_FUNC_DOOR) && - (ent->movewith_ent->class_id != ENTITY_FUNC_VEHICLE) && - (ent->movewith_ent->class_id != ENTITY_FUNC_TRACKTRAIN) ) ) - ent->movewith_ent = G_Find(ent->movewith_ent,FOFS(targetname),ent->movewith); - if(ent->movewith_ent) - movewith_init(ent->movewith_ent); - } - -/* for(i=1, ent=g_edicts+i; i < globals.num_edicts; i++, ent++) - { - gi.dprintf("%s:%s - movewith=%s, movewith_ent=%s:%s, movewith_next=%s:%s\n====================\n", - ent->classname, (ent->targetname ? ent->targetname : "noname"), - (ent->movewith ? ent->movewith : "N/A"), - (ent->movewith_ent ? ent->movewith_ent->classname : "N/A"), - (ent->movewith_ent ? (ent->movewith_ent->targetname ? ent->movewith_ent->targetname : "noname") : "N/A"), - (ent->movewith_next ? ent->movewith_next->classname : "N/A"), - (ent->movewith_next ? (ent->movewith_next->targetname ? ent->movewith_next->targetname : "noname") : "N/A")); - - } */ - - if(game.transition_ents) - LoadTransitionEnts(); - - actor_files(); - -} - - -//=================================================================== - -#if 0 - // cursor positioning - xl - xr - yb - yt - xv - yv - - // drawing - statpic - pic - num - string - - // control - if - ifeq - ifbit - endif - -#endif - -char *single_statusbar = -"yb -24 " - -// health -"xv 0 " -"hnum " -"xv 50 " -"pic 0 " - -// ammo -"if 2 " -"{ xv 100 " -"anum " -"xv 150 " -"pic 2 " -"} " - -// armor -"if 4 " -"{ xv 200 " -"rnum " -"xv 250 " -"pic 4 " -"} " - -// selected item -"if 6 " -"{ xv 296 " -"pic 6 " -"} " - -"yb -50 " - -// picked up item -"if 7 " -"{ xv 0 " -"pic 7 " -"xv 26 " -"yb -42 " -"stat_string 8 " -"yb -50 " -"} " - -// timer (was xv 262) -"if 9 " -"{ xv 230 " -"num 4 10 " -"xv 296 " -"pic 9 " -"} " - -// help / weapon icon -"if 11 " -"{ xv 148 " -"pic 11 " -"} " - -// vehicle speed -"if 22 " -"{ yb -90 " -"xv 128 " -"pic 22 " -"} " - -// zoom -"if 23 " -"{ yv 0 " -"xv 0 " -"pic 23 " -"} " -; - - -char *dm_statusbar = -"yb -24 " - -// health -"xv 0 " -"hnum " -"xv 50 " -"pic 0 " - -// ammo -"if 2 " -"{ xv 100 " -"anum " -"xv 150 " -"pic 2 " -"} " - -// armor -"if 4 " -"{ xv 200 " -"rnum " -"xv 250 " -"pic 4 " -"} " - -// selected item -"if 6 " -"{ xv 296 " -"pic 6 " -"} " - -"yb -50 " - -// picked up item -"if 7 " -"{ xv 0 " -"pic 7 " -"xv 26 " -"yb -42 " -"stat_string 8 " -"yb -50 " -"} " - -// timer -"if 9 " -"{ xv 230 " -"num 4 10 " -"xv 296 " -"pic 9 " -"} " - -// help / weapon icon -"if 11 " -"{ xv 148 " -"pic 11 " -"} " - -// frags -"xr -50 " -"yt 2 " -"num 3 14 " - -// spectator -"if 17 " -"{ xv 0 " -"yb -58 " -"string2 \"SPECTATOR MODE\" " -"} " - -// chase camera -"if 16 " -"{ xv 0 " -"yb -68 " -"string \"Chasing\" " -"xv 64 " -"stat_string 16 " -"} " - -// vehicle speed -"if 22 " -"{ yb -90 " -"xv 128 " -"pic 22 " -"} " -; - -/*QUAKED worldspawn (0 0 0) ? - -Only used for the world. -"skyname" environment map name -"skyaxis" vector axis for rotating sky -"skyrotate" speed of rotation in degrees/second -"sounds" music cd track number -"gravity" 800 is default gravity -"message" text to print at user logon -*/ -//void SetChromakey(); -void SP_worldspawn (edict_t *ent) -{ - ent->class_id = ENTITY_WORLDSPAWN; - ent->movetype = MOVETYPE_PUSH; - ent->solid = SOLID_BSP; - ent->inuse = true; // since the world doesn't use G_Spawn() - ent->s.modelindex = 1; // world model is always index 1 - - //--------------- - - // reserve some spots for dead player bodies for coop / deathmatch - InitBodyQue (); - - // set configstrings for items - SetItemNames (); - - if (st.nextmap) - strcpy (level.nextmap, st.nextmap); - - // make some data visible to the server - - if (ent->message && ent->message[0]) - { - gi.configstring (CS_NAME, ent->message); - strncpy (level.level_name, ent->message, sizeof(level.level_name)); - } - else - strncpy (level.level_name, level.mapname, sizeof(level.level_name)); - - if (st.sky && st.sky[0]) - gi.configstring (CS_SKY, st.sky); - else - gi.configstring (CS_SKY, "sky"); - - gi.configstring (CS_SKYROTATE, va("%f", st.skyrotate) ); - - gi.configstring (CS_SKYAXIS, va("%f %f %f", - st.skyaxis[0], st.skyaxis[1], st.skyaxis[2]) ); - - gi.configstring (CS_CDTRACK, va("%i", ent->sounds) ); - - gi.configstring (CS_MAXCLIENTS, va("%i", (int)(maxclients->value) ) ); - - // status bar program - if (deathmatch->value) - gi.configstring (CS_STATUSBAR, dm_statusbar); - else - gi.configstring (CS_STATUSBAR, single_statusbar); - - //--------------- - - // help icon for statusbar - gi.imageindex ("i_help"); - level.pic_health = gi.imageindex ("i_health"); - gi.imageindex ("help"); - gi.imageindex ("field_3"); - - if (!st.gravity) - gi.cvar_set("sv_gravity", "800"); - else - gi.cvar_set("sv_gravity", st.gravity); - - snd_fry = gi.soundindex ("player/fry.wav"); // standing in lava / slime - - PrecacheItem (FindItem ("Blaster")); - - gi.soundindex ("player/lava1.wav"); - gi.soundindex ("player/lava2.wav"); - - gi.soundindex ("misc/pc_up.wav"); - gi.soundindex ("misc/talk1.wav"); - - gi.soundindex ("misc/udeath.wav"); - - // gibs - gi.soundindex ("items/respawn1.wav"); - - // sexed sounds - gi.soundindex ("*death1.wav"); - gi.soundindex ("*death2.wav"); - gi.soundindex ("*death3.wav"); - gi.soundindex ("*death4.wav"); - gi.soundindex ("*fall1.wav"); - gi.soundindex ("*fall2.wav"); - gi.soundindex ("*gurp1.wav"); // drowning damage - gi.soundindex ("*gurp2.wav"); - gi.soundindex ("*jump1.wav"); // player jump - gi.soundindex ("*pain25_1.wav"); - gi.soundindex ("*pain25_2.wav"); - gi.soundindex ("*pain50_1.wav"); - gi.soundindex ("*pain50_2.wav"); - gi.soundindex ("*pain75_1.wav"); - gi.soundindex ("*pain75_2.wav"); - gi.soundindex ("*pain100_1.wav"); - gi.soundindex ("*pain100_2.wav"); - - // sexed models - // THIS ORDER MUST MATCH THE DEFINES IN g_local.h - // you can add more, max 15 - gi.modelindex ("#w_blaster.md2"); - gi.modelindex ("#w_shotgun.md2"); - gi.modelindex ("#w_sshotgun.md2"); - gi.modelindex ("#w_machinegun.md2"); - gi.modelindex ("#w_chaingun.md2"); - gi.modelindex ("#a_grenades.md2"); - gi.modelindex ("#w_glauncher.md2"); - gi.modelindex ("#w_rlauncher.md2"); - gi.modelindex ("#w_hyperblaster.md2"); - gi.modelindex ("#w_railgun.md2"); - gi.modelindex ("#w_bfg.md2"); - - //------------------- - - gi.soundindex ("player/gasp1.wav"); // gasping for air - gi.soundindex ("player/gasp2.wav"); // head breaking surface, not gasping - - gi.soundindex ("player/watr_in.wav"); // feet hitting water - gi.soundindex ("player/watr_out.wav"); // feet leaving water - - gi.soundindex ("player/watr_un.wav"); // head going underwater - - gi.soundindex ("player/u_breath1.wav"); - gi.soundindex ("player/u_breath2.wav"); - - gi.soundindex ("items/pkup.wav"); // bonus item pickup - gi.soundindex ("world/land.wav"); // landing thud - gi.soundindex ("misc/h2ohit1.wav"); // landing splash - - gi.soundindex ("items/damage.wav"); - gi.soundindex ("items/protect.wav"); - gi.soundindex ("items/protect4.wav"); - gi.soundindex ("weapons/noammo.wav"); - - gi.soundindex ("infantry/inflies1.wav"); - - sm_meat_index = gi.modelindex ("models/objects/gibs/sm_meat/tris.md2"); - gi.modelindex ("models/objects/gibs/arm/tris.md2"); - gi.modelindex ("models/objects/gibs/bone/tris.md2"); - gi.modelindex ("models/objects/gibs/bone2/tris.md2"); - gi.modelindex ("models/objects/gibs/chest/tris.md2"); - gi.modelindex ("models/objects/gibs/skull/tris.md2"); - gi.modelindex ("models/objects/gibs/head2/tris.md2"); - - gi.soundindex ("mud/mud_in2.wav"); - gi.soundindex ("mud/mud_out1.wav"); - gi.soundindex ("mud/mud_un1.wav"); - gi.soundindex ("mud/wade_mud1.wav"); - gi.soundindex ("mud/wade_mud2.wav"); - - Lights(); - - // Fog clipping - if "fogclip" is non-zero, force gl_clear to a good - // value for obscuring HOM with fog... "good" is driver-dependent - if(ent->fogclip) - { - if(gl_driver && !strcasecmp(gl_driver->string,"3dfxgl")) - gi.cvar_forceset("gl_clear", "0"); - else - gi.cvar_forceset("gl_clear", "1"); - } - - // FMOD 3D sound attenuation: - if(ent->attenuation <= 0.) - ent->attenuation = 1.0; - - // FMOD 3D sound Doppler shift: - if(st.shift > 0) - ent->moveinfo.distance = st.shift; - else if(st.shift < 0) - ent->moveinfo.distance = 0.0; - else - ent->moveinfo.distance = 1.0; - - // cvar overrides for effects flags: - if(alert_sounds->value) - world->effects |= FX_WORLDSPAWN_ALERTSOUNDS; - if(corpse_fade->value) - world->effects |= FX_WORLDSPAWN_CORPSEFADE; - if(jump_kick->value) - world->effects |= FX_WORLDSPAWN_JUMPKICK; - if(footstep_sounds->value) - world->effects |= FX_WORLDSPAWN_STEPSOUNDS; - - if(deathmatch->value || coop->value) - qFMOD_Footsteps = false; - else if(world->effects & FX_WORLDSPAWN_STEPSOUNDS) - { - qFMOD_Footsteps = true; - FMOD_Init(); - } - else - qFMOD_Footsteps = false; -} - -// Hud toggle ripped from TPP source - -int nohud = 0; - -void Hud_On() -{ - if (deathmatch->value) - gi.configstring (CS_STATUSBAR, dm_statusbar); - else - gi.configstring (CS_STATUSBAR, single_statusbar); - nohud = 0; -} - -void Hud_Off() -{ - gi.configstring (CS_STATUSBAR, NULL); - nohud = 1; -} - -void Cmd_ToggleHud () -{ - if (deathmatch->value) - return; - if (nohud) - Hud_On(); - else - Hud_Off(); -} diff --git a/server/m_flash.c b/server/m_flash.c deleted file mode 100644 index 0c7e620d..00000000 --- a/server/m_flash.c +++ /dev/null @@ -1,469 +0,0 @@ -// m_flash.c - -#include "g_local.h" - -// this file is included in both the game dll and quake2, -// the game needs it to source shot locations, the client -// needs it to position muzzle flashes -vec3_t monster_flash_offset [] = -{ -// flash 0 is not used - 0.0, 0.0, 0.0, - -// MZ2_TANK_BLASTER_1 1 - 20.7, -18.5, 28.7, -// MZ2_TANK_BLASTER_2 2 - 16.6, -21.5, 30.1, -// MZ2_TANK_BLASTER_3 3 - 11.8, -23.9, 32.1, -// MZ2_TANK_MACHINEGUN_1 4 - 22.9, -0.7, 25.3, -// MZ2_TANK_MACHINEGUN_2 5 - 22.2, 6.2, 22.3, -// MZ2_TANK_MACHINEGUN_3 6 - 19.4, 13.1, 18.6, -// MZ2_TANK_MACHINEGUN_4 7 - 19.4, 18.8, 18.6, -// MZ2_TANK_MACHINEGUN_5 8 - 17.9, 25.0, 18.6, -// MZ2_TANK_MACHINEGUN_6 9 - 14.1, 30.5, 20.6, -// MZ2_TANK_MACHINEGUN_7 10 - 9.3, 35.3, 22.1, -// MZ2_TANK_MACHINEGUN_8 11 - 4.7, 38.4, 22.1, -// MZ2_TANK_MACHINEGUN_9 12 - -1.1, 40.4, 24.1, -// MZ2_TANK_MACHINEGUN_10 13 - -6.5, 41.2, 24.1, -// MZ2_TANK_MACHINEGUN_11 14 - 3.2, 40.1, 24.7, -// MZ2_TANK_MACHINEGUN_12 15 - 11.7, 36.7, 26.0, -// MZ2_TANK_MACHINEGUN_13 16 - 18.9, 31.3, 26.0, -// MZ2_TANK_MACHINEGUN_14 17 - 24.4, 24.4, 26.4, -// MZ2_TANK_MACHINEGUN_15 18 - 27.1, 17.1, 27.2, -// MZ2_TANK_MACHINEGUN_16 19 - 28.5, 9.1, 28.0, -// MZ2_TANK_MACHINEGUN_17 20 - 27.1, 2.2, 28.0, -// MZ2_TANK_MACHINEGUN_18 21 - 24.9, -2.8, 28.0, -// MZ2_TANK_MACHINEGUN_19 22 - 21.6, -7.0, 26.4, -// MZ2_TANK_ROCKET_1 23 - 6.2, 29.1, 49.1, -// MZ2_TANK_ROCKET_2 24 - 6.9, 23.8, 49.1, -// MZ2_TANK_ROCKET_3 25 - 8.3, 17.8, 49.5, - -// MZ2_INFANTRY_MACHINEGUN_1 26 - 26.6, 7.1, 13.1, -// MZ2_INFANTRY_MACHINEGUN_2 27 - 18.2, 7.5, 15.4, -// MZ2_INFANTRY_MACHINEGUN_3 28 - 17.2, 10.3, 17.9, -// MZ2_INFANTRY_MACHINEGUN_4 29 - 17.0, 12.8, 20.1, -// MZ2_INFANTRY_MACHINEGUN_5 30 - 15.1, 14.1, 21.8, -// MZ2_INFANTRY_MACHINEGUN_6 31 - 11.8, 17.2, 23.1, -// MZ2_INFANTRY_MACHINEGUN_7 32 - 11.4, 20.2, 21.0, -// MZ2_INFANTRY_MACHINEGUN_8 33 - 9.0, 23.0, 18.9, -// MZ2_INFANTRY_MACHINEGUN_9 34 - 13.9, 18.6, 17.7, -// MZ2_INFANTRY_MACHINEGUN_10 35 - 15.4, 15.6, 15.8, -// MZ2_INFANTRY_MACHINEGUN_11 36 - 10.2, 15.2, 25.1, -// MZ2_INFANTRY_MACHINEGUN_12 37 - -1.9, 15.1, 28.2, -// MZ2_INFANTRY_MACHINEGUN_13 38 - -12.4, 13.0, 20.2, - -// MZ2_SOLDIER_BLASTER_1 39 - 10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2, -// MZ2_SOLDIER_BLASTER_2 40 - 21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2, -// MZ2_SOLDIER_SHOTGUN_1 41 - 10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2, -// MZ2_SOLDIER_SHOTGUN_2 42 - 21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_1 43 - 10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_2 44 - 21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2, - -// MZ2_GUNNER_MACHINEGUN_1 45 - 30.1 * 1.15, 3.9 * 1.15, 19.6 * 1.15, -// MZ2_GUNNER_MACHINEGUN_2 46 - 29.1 * 1.15, 2.5 * 1.15, 20.7 * 1.15, -// MZ2_GUNNER_MACHINEGUN_3 47 - 28.2 * 1.15, 2.5 * 1.15, 22.2 * 1.15, -// MZ2_GUNNER_MACHINEGUN_4 48 - 28.2 * 1.15, 3.6 * 1.15, 22.0 * 1.15, -// MZ2_GUNNER_MACHINEGUN_5 49 - 26.9 * 1.15, 2.0 * 1.15, 23.4 * 1.15, -// MZ2_GUNNER_MACHINEGUN_6 50 - 26.5 * 1.15, 0.6 * 1.15, 20.8 * 1.15, -// MZ2_GUNNER_MACHINEGUN_7 51 - 26.9 * 1.15, 0.5 * 1.15, 21.5 * 1.15, -// MZ2_GUNNER_MACHINEGUN_8 52 - 29.0 * 1.15, 2.4 * 1.15, 19.5 * 1.15, -// MZ2_GUNNER_GRENADE_1 53 - 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, -// MZ2_GUNNER_GRENADE_2 54 - 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, -// MZ2_GUNNER_GRENADE_3 55 - 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, -// MZ2_GUNNER_GRENADE_4 56 - 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, - -// MZ2_CHICK_ROCKET_1 57 -// -24.8, -9.0, 39.0, - 24.8, -9.0, 39.0, // PGM - this was incorrect in Q2 - -// MZ2_FLYER_BLASTER_1 58 - 12.1, 13.4, -14.5, -// MZ2_FLYER_BLASTER_2 59 - 12.1, -7.4, -14.5, - -// MZ2_MEDIC_BLASTER_1 60 - 12.1, 5.4, 16.5, - -// MZ2_GLADIATOR_RAILGUN_1 61 - 30.0, 18.0, 28.0, - -// MZ2_HOVER_BLASTER_1 62 - 32.5, -0.8, 10.0, - -// MZ2_ACTOR_MACHINEGUN_1 63 - 18.4, 7.4, 9.6, - -// MZ2_SUPERTANK_MACHINEGUN_1 64 - 30.0, 30.0, 88.5, -// MZ2_SUPERTANK_MACHINEGUN_2 65 - 30.0, 30.0, 88.5, -// MZ2_SUPERTANK_MACHINEGUN_3 66 - 30.0, 30.0, 88.5, -// MZ2_SUPERTANK_MACHINEGUN_4 67 - 30.0, 30.0, 88.5, -// MZ2_SUPERTANK_MACHINEGUN_5 68 - 30.0, 30.0, 88.5, -// MZ2_SUPERTANK_MACHINEGUN_6 69 - 30.0, 30.0, 88.5, -// MZ2_SUPERTANK_ROCKET_1 70 - 16.0, -22.5, 91.2, -// MZ2_SUPERTANK_ROCKET_2 71 - 16.0, -33.4, 86.7, -// MZ2_SUPERTANK_ROCKET_3 72 - 16.0, -42.8, 83.3, - -// --- Start Xian Stuff --- -// MZ2_BOSS2_MACHINEGUN_L1 73 - 32, -40, 70, -// MZ2_BOSS2_MACHINEGUN_L2 74 - 32, -40, 70, -// MZ2_BOSS2_MACHINEGUN_L3 75 - 32, -40, 70, -// MZ2_BOSS2_MACHINEGUN_L4 76 - 32, -40, 70, -// MZ2_BOSS2_MACHINEGUN_L5 77 - 32, -40, 70, -// --- End Xian Stuff - -// MZ2_BOSS2_ROCKET_1 78 - 22.0, 16.0, 10.0, -// MZ2_BOSS2_ROCKET_2 79 - 22.0, 8.0, 10.0, -// MZ2_BOSS2_ROCKET_3 80 - 22.0, -8.0, 10.0, -// MZ2_BOSS2_ROCKET_4 81 - 22.0, -16.0, 10.0, - -// MZ2_FLOAT_BLASTER_1 82 - 32.5, -0.8, 10, - -// MZ2_SOLDIER_BLASTER_3 83 - 20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2, -// MZ2_SOLDIER_SHOTGUN_3 84 - 20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_3 85 - 20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2, -// MZ2_SOLDIER_BLASTER_4 86 - 7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2, -// MZ2_SOLDIER_SHOTGUN_4 87 - 7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_4 88 - 7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2, -// MZ2_SOLDIER_BLASTER_5 89 - 30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2, -// MZ2_SOLDIER_SHOTGUN_5 90 - 30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_5 91 - 30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2, -// MZ2_SOLDIER_BLASTER_6 92 - 27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2, -// MZ2_SOLDIER_SHOTGUN_6 93 - 27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_6 94 - 27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2, -// MZ2_SOLDIER_BLASTER_7 95 - 28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2, -// MZ2_SOLDIER_SHOTGUN_7 96 - 28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_7 97 - 28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2, -// MZ2_SOLDIER_BLASTER_8 98 -// 34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2, - 31.5 * 1.2, 9.6 * 1.2, 10.1 * 1.2, -// MZ2_SOLDIER_SHOTGUN_8 99 - 34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2, -// MZ2_SOLDIER_MACHINEGUN_8 100 - 34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2, - -// --- Xian shit below --- -// MZ2_MAKRON_BFG 101 - 17, -19.5, 62.9, -// MZ2_MAKRON_BLASTER_1 102 - -3.6, -24.1, 59.5, -// MZ2_MAKRON_BLASTER_2 103 - -1.6, -19.3, 59.5, -// MZ2_MAKRON_BLASTER_3 104 - -0.1, -14.4, 59.5, -// MZ2_MAKRON_BLASTER_4 105 - 2.0, -7.6, 59.5, -// MZ2_MAKRON_BLASTER_5 106 - 3.4, 1.3, 59.5, -// MZ2_MAKRON_BLASTER_6 107 - 3.7, 11.1, 59.5, -// MZ2_MAKRON_BLASTER_7 108 - -0.3, 22.3, 59.5, -// MZ2_MAKRON_BLASTER_8 109 - -6, 33, 59.5, -// MZ2_MAKRON_BLASTER_9 110 - -9.3, 36.4, 59.5, -// MZ2_MAKRON_BLASTER_10 111 - -7, 35, 59.5, -// MZ2_MAKRON_BLASTER_11 112 - -2.1, 29, 59.5, -// MZ2_MAKRON_BLASTER_12 113 - 3.9, 17.3, 59.5, -// MZ2_MAKRON_BLASTER_13 114 - 6.1, 5.8, 59.5, -// MZ2_MAKRON_BLASTER_14 115 - 5.9, -4.4, 59.5, -// MZ2_MAKRON_BLASTER_15 116 - 4.2, -14.1, 59.5, -// MZ2_MAKRON_BLASTER_16 117 - 2.4, -18.8, 59.5, -// MZ2_MAKRON_BLASTER_17 118 - -1.8, -25.5, 59.5, -// MZ2_MAKRON_RAILGUN_1 119 - -17.3, 7.8, 72.4, - -// MZ2_JORG_MACHINEGUN_L1 120 - 78.5, -47.1, 96, -// MZ2_JORG_MACHINEGUN_L2 121 - 78.5, -47.1, 96, -// MZ2_JORG_MACHINEGUN_L3 122 - 78.5, -47.1, 96, -// MZ2_JORG_MACHINEGUN_L4 123 - 78.5, -47.1, 96, -// MZ2_JORG_MACHINEGUN_L5 124 - 78.5, -47.1, 96, -// MZ2_JORG_MACHINEGUN_L6 125 - 78.5, -47.1, 96, -// MZ2_JORG_MACHINEGUN_R1 126 - 78.5, 46.7, 96, -// MZ2_JORG_MACHINEGUN_R2 127 - 78.5, 46.7, 96, -// MZ2_JORG_MACHINEGUN_R3 128 - 78.5, 46.7, 96, -// MZ2_JORG_MACHINEGUN_R4 129 - 78.5, 46.7, 96, -// MZ2_JORG_MACHINEGUN_R5 130 - 78.5, 46.7, 96, -// MZ2_JORG_MACHINEGUN_R6 131 - 78.5, 46.7, 96, -// MZ2_JORG_BFG_1 132 - 6.3, -9, 111.2, - -// MZ2_BOSS2_MACHINEGUN_R1 73 - 32, 40, 70, -// MZ2_BOSS2_MACHINEGUN_R2 74 - 32, 40, 70, -// MZ2_BOSS2_MACHINEGUN_R3 75 - 32, 40, 70, -// MZ2_BOSS2_MACHINEGUN_R4 76 - 32, 40, 70, -// MZ2_BOSS2_MACHINEGUN_R5 77 - 32, 40, 70, - -// --- End Xian Shit --- - -// ROGUE -// note that the above really ends at 137 -// carrier machineguns -// MZ2_CARRIER_MACHINEGUN_L1 - 56, -32, 32, -// MZ2_CARRIER_MACHINEGUN_R1 - 56, 32, 32, -// MZ2_CARRIER_GRENADE - 42, 24, 50, -// MZ2_TURRET_MACHINEGUN 141 - 16, 0, 0, -// MZ2_TURRET_ROCKET 142 - 16, 0, 0, -// MZ2_TURRET_BLASTER 143 - 16, 0, 0, -// MZ2_STALKER_BLASTER 144 - 24, 0, 6, -// MZ2_DAEDALUS_BLASTER 145 - 32.5, -0.8, 10.0, -// MZ2_MEDIC_BLASTER_2 146 - 12.1, 5.4, 16.5, -// MZ2_CARRIER_RAILGUN 147 - 32, 0, 6, -// MZ2_WIDOW_DISRUPTOR 148 - 57.72, 14.50, 88.81, -// MZ2_WIDOW_BLASTER 149 - 56, 32, 32, -// MZ2_WIDOW_RAIL 150 - 62, -20, 84, -// MZ2_WIDOW_PLASMABEAM 151 // PMM - not used! - 32, 0, 6, -// MZ2_CARRIER_MACHINEGUN_L2 152 - 61, -32, 12, -// MZ2_CARRIER_MACHINEGUN_R2 153 - 61, 32, 12, -// MZ2_WIDOW_RAIL_LEFT 154 - 17, -62, 91, -// MZ2_WIDOW_RAIL_RIGHT 155 - 68, 12, 86, -// MZ2_WIDOW_BLASTER_SWEEP1 156 pmm - the sweeps need to be in sequential order - 47.5, 56, 89, -// MZ2_WIDOW_BLASTER_SWEEP2 157 - 54, 52, 91, -// MZ2_WIDOW_BLASTER_SWEEP3 158 - 58, 40, 91, -// MZ2_WIDOW_BLASTER_SWEEP4 159 - 68, 30, 88, -// MZ2_WIDOW_BLASTER_SWEEP5 160 - 74, 20, 88, -// MZ2_WIDOW_BLASTER_SWEEP6 161 - 73, 11, 87, -// MZ2_WIDOW_BLASTER_SWEEP7 162 - 73, 3, 87, -// MZ2_WIDOW_BLASTER_SWEEP8 163 - 70, -12, 87, -// MZ2_WIDOW_BLASTER_SWEEP9 164 - 67, -20, 90, -// MZ2_WIDOW_BLASTER_100 165 - -20, 76, 90, -// MZ2_WIDOW_BLASTER_90 166 - -8, 74, 90, -// MZ2_WIDOW_BLASTER_80 167 - 0, 72, 90, -// MZ2_WIDOW_BLASTER_70 168 d06 - 10, 71, 89, -// MZ2_WIDOW_BLASTER_60 169 d07 - 23, 70, 87, -// MZ2_WIDOW_BLASTER_50 170 d08 - 32, 64, 85, -// MZ2_WIDOW_BLASTER_40 171 - 40, 58, 84, -// MZ2_WIDOW_BLASTER_30 172 d10 - 48, 50, 83, -// MZ2_WIDOW_BLASTER_20 173 - 54, 42, 82, -// MZ2_WIDOW_BLASTER_10 174 d12 - 56, 34, 82, -// MZ2_WIDOW_BLASTER_0 175 - 58, 26, 82, -// MZ2_WIDOW_BLASTER_10L 176 d14 - 60, 16, 82, -// MZ2_WIDOW_BLASTER_20L 177 - 59, 6, 81, -// MZ2_WIDOW_BLASTER_30L 178 d16 - 58, -2, 80, -// MZ2_WIDOW_BLASTER_40L 179 - 57, -10, 79, -// MZ2_WIDOW_BLASTER_50L 180 d18 - 54, -18, 78, -// MZ2_WIDOW_BLASTER_60L 181 - 42, -32, 80, -// MZ2_WIDOW_BLASTER_70L 182 d20 - 36, -40, 78, -// MZ2_WIDOW_RUN_1 183 - 68.4, 10.88, 82.08, -// MZ2_WIDOW_RUN_2 184 - 68.51, 8.64, 85.14, -// MZ2_WIDOW_RUN_3 185 - 68.66, 6.38, 88.78, -// MZ2_WIDOW_RUN_4 186 - 68.73, 5.1, 84.47, -// MZ2_WIDOW_RUN_5 187 - 68.82, 4.79, 80.52, -// MZ2_WIDOW_RUN_6 188 - 68.77, 6.11, 85.37, -// MZ2_WIDOW_RUN_7 189 - 68.67, 7.99, 90.24, -// MZ2_WIDOW_RUN_8 190 - 68.55, 9.54, 87.36, -// MZ2_CARRIER_ROCKET_1 191 - 0, 0, -5, -// MZ2_CARRIER_ROCKET_2 192 - 0, 0, -5, -// MZ2_CARRIER_ROCKET_3 193 - 0, 0, -5, -// MZ2_CARRIER_ROCKET_4 194 - 0, 0, -5, -// MZ2_WIDOW2_BEAMER_1 195 -// 72.13, -17.63, 93.77, - 69.00, -17.63, 93.77, -// MZ2_WIDOW2_BEAMER_2 196 -// 71.46, -17.08, 89.82, - 69.00, -17.08, 89.82, -// MZ2_WIDOW2_BEAMER_3 197 -// 71.47, -18.40, 90.70, - 69.00, -18.40, 90.70, -// MZ2_WIDOW2_BEAMER_4 198 -// 71.96, -18.34, 94.32, - 69.00, -18.34, 94.32, -// MZ2_WIDOW2_BEAMER_5 199 -// 72.25, -18.30, 97.98, - 69.00, -18.30, 97.98, -// MZ2_WIDOW2_BEAM_SWEEP_1 200 - 45.04, -59.02, 92.24, -// MZ2_WIDOW2_BEAM_SWEEP_2 201 - 50.68, -54.70, 91.96, -// MZ2_WIDOW2_BEAM_SWEEP_3 202 - 56.57, -47.72, 91.65, -// MZ2_WIDOW2_BEAM_SWEEP_4 203 - 61.75, -38.75, 91.38, -// MZ2_WIDOW2_BEAM_SWEEP_5 204 - 65.55, -28.76, 91.24, -// MZ2_WIDOW2_BEAM_SWEEP_6 205 - 67.79, -18.90, 91.22, -// MZ2_WIDOW2_BEAM_SWEEP_7 206 - 68.60, -9.52, 91.23, -// MZ2_WIDOW2_BEAM_SWEEP_8 207 - 68.08, 0.18, 91.32, -// MZ2_WIDOW2_BEAM_SWEEP_9 208 - 66.14, 9.79, 91.44, -// MZ2_WIDOW2_BEAM_SWEEP_10 209 - 62.77, 18.91, 91.65, -// MZ2_WIDOW2_BEAM_SWEEP_11 210 - 58.29, 27.11, 92.00, - -// end of table - 0.0, 0.0, 0.0 -}; diff --git a/server/monsters/m_player.h b/server/m_player.h similarity index 100% rename from server/monsters/m_player.h rename to server/m_player.h diff --git a/server/monsters/g_monster.c b/server/monsters/g_monster.c deleted file mode 100644 index da7a1459..00000000 --- a/server/monsters/g_monster.c +++ /dev/null @@ -1,1340 +0,0 @@ -#include "g_local.h" - -void InitiallyDead (edict_t *self); - -// Lazarus: If worldspawn CORPSE_SINK effects flag is set, -// monsters/actors fade out and sink into the floor -// 30 seconds after death - -#define SINKAMT 1 -void FadeSink (edict_t *ent) -{ - ent->count++; - ent->s.origin[2]-=SINKAMT; - ent->think=FadeSink; - if (ent->count==5) - { - ent->s.renderfx &= ~RF_TRANSLUCENT; - ent->s.effects |= EF_SPHERETRANS; - } - if (ent->count==10) - ent->think=G_FreeEdict; - ent->nextthink=level.time+FRAMETIME; -} -void FadeDieSink (edict_t *ent) -{ - ent->takedamage = DAMAGE_NO; // can't gib 'em once they start sinking - ent->s.effects &= ~EF_FLIES; - ent->s.sound = 0; - ent->s.origin[2]-=SINKAMT; - ent->s.renderfx=RF_TRANSLUCENT; - ent->think=FadeSink; - ent->nextthink=level.time+FRAMETIME; - ent->count=0; -} - - -// Lazarus: M_SetDeath is used to restore the death movement, -// bounding box, and a few other parameters for dead -// monsters that change levels with a trigger_transition - -bool M_SetDeath(edict_t *self, mmove_t **deathmoves) -{ - mmove_t *move=NULL; - mmove_t *dmove; - - if(self->health > 0) - return false; - - while(*deathmoves && !move) - { - dmove = *deathmoves; - if( (self->s.frame >= dmove->firstframe) && - (self->s.frame <= dmove->lastframe) ) - move = dmove; - else - deathmoves++; - } - if(move) - { - self->monsterinfo.currentmove = move; - if(self->monsterinfo.currentmove->endfunc) - self->monsterinfo.currentmove->endfunc(self); - self->s.frame = move->lastframe; - self->s.skin |= 1; - return true; - } - return false; -} - -// -// monster weapons -// - -//FIXME monsters should call these with a totally accurate direction -// and we can mess it up based on skill. Spread should be for normal -// and we can tighten or loosen based on skill. We could muck with -// the damages too, but I'm not sure that's such a good idea. -void monster_fire_bullet (edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype) -{ - fire_bullet (self, start, dir, damage, kick, hspread, vspread, MOD_UNKNOWN); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - -void monster_fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int flashtype) -{ - fire_shotgun (self, start, aimdir, damage, kick, hspread, vspread, count, MOD_UNKNOWN); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - -void monster_fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect) -{ - fire_blaster (self, start, dir, damage, speed, effect, false); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - -void monster_fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int flashtype) -{ - fire_grenade (self, start, aimdir, damage, speed, 2.5, damage+40); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - -void monster_fire_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, edict_t *homing_target) -{ - fire_rocket (self, start, dir, damage, speed, damage+20, damage, homing_target); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - -void monster_fire_railgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int flashtype) -{ - fire_rail (self, start, aimdir, damage, kick); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - -void monster_fire_bfg (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int kick, float damage_radius, int flashtype) -{ - fire_bfg (self, start, aimdir, damage, speed, damage_radius); - - MESSAGE_BEGIN (svc_muzzleflash2); - WRITE_SHORT (self - g_edicts); - WRITE_BYTE (flashtype); - MESSAGE_SEND (MSG_PVS, start, NULL); -} - - - -// -// Monster utility functions -// - -void M_FliesOff (edict_t *self) -{ - self->s.effects &= ~EF_FLIES; - self->s.sound = 0; -} - -void M_FliesOn (edict_t *self) -{ - if (self->waterlevel) - return; - self->s.effects |= EF_FLIES; - self->s.sound = gi.soundindex ("infantry/inflies1.wav"); - self->think = M_FliesOff; - self->nextthink = level.time + 60; -} - -void M_FlyCheck (edict_t *self) -{ - if (self->monsterinfo.flies > 1.0) - { - // should ALREADY have flies - self->think = M_FliesOff; - self->nextthink = level.time + 60; - return; - } - - if (self->waterlevel) - return; - - if (random() > self->monsterinfo.flies) - return; - - self->think = M_FliesOn; - self->nextthink = level.time + 5 + 10 * random(); -} - -void AttackFinished (edict_t *self, float time) -{ - self->monsterinfo.attack_finished = level.time + time; -} - - -void M_CheckGround (edict_t *ent) -{ - vec3_t point; - trace_t trace; - - if (level.time < ent->gravity_debounce_time) - return; - - if (ent->flags & (FL_SWIM|FL_FLY)) - return; - - if (ent->velocity[2] > 100) - { - ent->groundentity = NULL; - return; - } - -// if the hull point one-quarter unit down is solid the entity is on ground - point[0] = ent->s.origin[0]; - point[1] = ent->s.origin[1]; - point[2] = ent->s.origin[2] - 0.25; - - trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, point, ent, MASK_MONSTERSOLID); - - // check steepness - if ( trace.plane.normal[2] < 0.7 && !trace.startsolid) - { - ent->groundentity = NULL; - return; - } - - // Lazarus: The following 2 lines were in the original code and commented out - // by id. However, the effect of this is that a player walking over - // a dead monster who is laying on a brush model will cause the - // dead monster to drop through the brush model. This change *may* - // have other consequences, though, so watch out for this. - - ent->groundentity = trace.ent; - ent->groundentity_linkcount = trace.ent->linkcount; -// if (!trace.startsolid && !trace.allsolid) -// VectorCopy (trace.endpos, ent->s.origin); - if (!trace.startsolid && !trace.allsolid) - { - VectorCopy (trace.endpos, ent->s.origin); - ent->groundentity = trace.ent; - ent->groundentity_linkcount = trace.ent->linkcount; -// ent->velocity[2] = 0; Lazarus: what if the groundentity is moving? - ent->velocity[2] = trace.ent->velocity[2]; - } -} - - -void M_CatagorizePosition (edict_t *ent) -{ - vec3_t point; - int cont; - -// -// get waterlevel -// -// Lazarus... more broken code because of origin being screwed up -// point[0] = ent->s.origin[0]; -// point[1] = ent->s.origin[1]; -// point[2] = ent->s.origin[2] + ent->mins[2] + 1; - point[0] = (ent->absmax[0] + ent->absmin[0])/2; - point[1] = (ent->absmax[1] + ent->absmin[1])/2; - point[2] = ent->absmin[2] + 2; - - cont = gi.pointcontents (point); - - if (!(cont & MASK_WATER)) - { - ent->waterlevel = 0; - ent->watertype = 0; - return; - } - - ent->watertype = cont; - ent->waterlevel = 1; - point[2] += 26; - cont = gi.pointcontents (point); - if (!(cont & MASK_WATER)) - return; - - ent->waterlevel = 2; - point[2] += 22; - cont = gi.pointcontents (point); - if (cont & MASK_WATER) - ent->waterlevel = 3; -} - - -void M_WorldEffects (edict_t *ent) -{ - int dmg; - - if (ent->health > 0) - { - if (!(ent->flags & FL_SWIM)) - { - if (ent->waterlevel < 3) - { - ent->air_finished = level.time + 12; - } - else if (ent->air_finished < level.time) - { // drown! - if (ent->pain_debounce_time < level.time) - { - dmg = 2 + 2 * floor(level.time - ent->air_finished); - if (dmg > 15) - dmg = 15; - T_Damage (ent, world, world, vec3_origin, ent->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); - ent->pain_debounce_time = level.time + 1; - } - } - } - else - { - if (ent->waterlevel > 0) - { - ent->air_finished = level.time + 9; - } - else if (ent->air_finished < level.time) - { // suffocate! - if (ent->pain_debounce_time < level.time) - { - dmg = 2 + 2 * floor(level.time - ent->air_finished); - if (dmg > 15) - dmg = 15; - T_Damage (ent, world, world, vec3_origin, ent->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); - ent->pain_debounce_time = level.time + 1; - } - } - } - } - - if (ent->waterlevel == 0) - { - if (ent->flags & FL_INWATER) - { - if (ent->watertype & CONTENTS_MUD) - gi.sound (ent, CHAN_BODY, gi.soundindex("mud/mud_out1.wav"), 1, ATTN_NORM, 0); - else - gi.sound (ent, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0); - ent->flags &= ~FL_INWATER; - } - return; - } - - if ((ent->watertype & CONTENTS_LAVA) && !(ent->flags & FL_IMMUNE_LAVA)) - { - if (ent->damage_debounce_time < level.time) - { - ent->damage_debounce_time = level.time + 0.2; - T_Damage (ent, world, world, vec3_origin, ent->s.origin, vec3_origin, 10*ent->waterlevel, 0, 0, MOD_LAVA); - } - } - if ((ent->watertype & CONTENTS_SLIME) && !(ent->flags & FL_IMMUNE_SLIME)) - { - if (ent->damage_debounce_time < level.time) - { - ent->damage_debounce_time = level.time + 1; - T_Damage (ent, world, world, vec3_origin, ent->s.origin, vec3_origin, 4*ent->waterlevel, 0, 0, MOD_SLIME); - } - } - - if ( !(ent->flags & FL_INWATER) ) - { - if (!(ent->svflags & SVF_DEADMONSTER)) - { - if (ent->watertype & CONTENTS_LAVA) - if (random() <= 0.5) - gi.sound (ent, CHAN_BODY, gi.soundindex("player/lava1.wav"), 1, ATTN_NORM, 0); - else - gi.sound (ent, CHAN_BODY, gi.soundindex("player/lava2.wav"), 1, ATTN_NORM, 0); - else if (ent->watertype & CONTENTS_SLIME) - gi.sound (ent, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); - else if (ent->watertype & CONTENTS_MUD) - gi.sound (ent, CHAN_BODY, gi.soundindex("mud/mud_in2.wav"), 1, ATTN_NORM, 0); - else if (ent->watertype & CONTENTS_WATER) - gi.sound (ent, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); - } - - ent->flags |= FL_INWATER; - ent->old_watertype = ent->watertype; - ent->damage_debounce_time = 0; - } -} - - -void M_droptofloor (edict_t *ent) -{ - vec3_t end; - trace_t trace; - - ent->s.origin[2] += 1; - VectorCopy (ent->s.origin, end); - end[2] -= 256; - - trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); - - if (trace.fraction == 1 || trace.allsolid) - return; - - VectorCopy (trace.endpos, ent->s.origin); - - gi.linkentity (ent); - M_CheckGround (ent); - M_CatagorizePosition (ent); -} - - -void M_SetEffects (edict_t *ent) -{ - ent->s.effects &= ~(EF_COLOR_SHELL|EF_POWERSCREEN); - ent->s.renderfx &= ~(RF_SHELL_RED|RF_SHELL_GREEN|RF_SHELL_BLUE); - - if (ent->monsterinfo.aiflags & AI_RESURRECTING) - { - ent->s.effects |= EF_COLOR_SHELL; - ent->s.renderfx |= RF_SHELL_RED; - } - - if (ent->health <= 0) - return; - - if (ent->powerarmor_time > level.time) - { - if (ent->monsterinfo.power_armor_type == POWER_ARMOR_SCREEN) - { - ent->s.effects |= EF_POWERSCREEN; - } - else if (ent->monsterinfo.power_armor_type == POWER_ARMOR_SHIELD) - { - ent->s.effects |= EF_COLOR_SHELL; - ent->s.renderfx |= RF_SHELL_GREEN; - } - } -} - - -void M_MoveFrame (edict_t *self) -{ - mmove_t *move; - int index; - - // Lazarus: For live monsters weaker than gladiator who aren't already running from - // something, evade live grenades on the ground. - if((self->health > 0) && (self->max_health < 400) && !(self->monsterinfo.aiflags & AI_CHASE_THING) && self->monsterinfo.run) - Grenade_Evade (self); - - move = self->monsterinfo.currentmove; - self->nextthink = level.time + FRAMETIME; - - if ((self->monsterinfo.nextframe) && (self->monsterinfo.nextframe >= move->firstframe) && (self->monsterinfo.nextframe <= move->lastframe)) - { - self->s.frame = self->monsterinfo.nextframe; - self->monsterinfo.nextframe = 0; - } - else - { - if (self->s.frame == move->lastframe) - { - if (move->endfunc) - { - move->endfunc (self); - - // regrab move, endfunc is very likely to change it - move = self->monsterinfo.currentmove; - - // check for death - if (self->svflags & SVF_DEADMONSTER) - return; - } - } - - if (self->s.frame < move->firstframe || self->s.frame > move->lastframe) - { - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - self->s.frame = move->firstframe; - } - else - { - if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) - { - self->s.frame++; - if (self->s.frame > move->lastframe) - self->s.frame = move->firstframe; - } - } - } - - index = self->s.frame - move->firstframe; - if (move->frame[index].aifunc) - if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) - move->frame[index].aifunc (self, move->frame[index].dist * self->monsterinfo.scale); - else - move->frame[index].aifunc (self, 0); - - if (move->frame[index].thinkfunc) - move->frame[index].thinkfunc (self); -} - - -void monster_think (edict_t *self) -{ - M_MoveFrame (self); - if (self->linkcount != self->monsterinfo.linkcount) - { - self->monsterinfo.linkcount = self->linkcount; - M_CheckGround (self); - } - M_CatagorizePosition (self); - M_WorldEffects (self); - M_SetEffects (self); -} - - -/* -================ -monster_use - -Using a monster makes it angry at the current activator -================ -*/ -void monster_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if (self->enemy) - return; - if (self->health <= 0) - return; - if (activator->flags & FL_NOTARGET) - return; - if (!(activator->client) && !(activator->monsterinfo.aiflags & AI_GOOD_GUY)) - return; - if (activator->flags & FL_DISGUISED) - return; - - // if monster is "used" by player, turn off good guy stuff - if (activator->client) - { - self->spawnflags &= ~SF_MONSTER_GOODGUY; - self->monsterinfo.aiflags &= ~(AI_GOOD_GUY + AI_FOLLOW_LEADER); - if(self->dmgteam && !strcasecmp(self->dmgteam,"player")) - self->dmgteam = NULL; - } - -// delay reaction so if the monster is teleported, its sound is still heard - self->enemy = activator; - FoundTarget (self); -} - - -void monster_start_go (edict_t *self); - - -void monster_triggered_spawn (edict_t *self) -{ - self->s.origin[2] += 1; - KillBox (self); - - self->solid = SOLID_BBOX; - self->movetype = MOVETYPE_STEP; - self->svflags &= ~SVF_NOCLIENT; - self->air_finished = level.time + 12; - gi.linkentity (self); - - monster_start_go (self); - - if (self->enemy && !(self->spawnflags & SF_MONSTER_SIGHT) && !(self->enemy->flags & FL_NOTARGET)) - { - if(!(self->enemy->flags & FL_DISGUISED)) - FoundTarget (self); - else - self->enemy = NULL; - } - else - self->enemy = NULL; -} - -void monster_triggered_spawn_use (edict_t *self, edict_t *other, edict_t *activator) -{ - // we have a one frame delay here so we don't telefrag the guy who activated us - self->think = monster_triggered_spawn; - self->nextthink = level.time + FRAMETIME; - if (activator->client) - self->enemy = activator; - // Lazarus: Add 'em up - if(!(self->monsterinfo.aiflags & AI_GOOD_GUY)) - level.total_monsters++; - self->use = monster_use; -} - -void monster_triggered_start (edict_t *self) -{ - self->solid = SOLID_NOT; - self->movetype = MOVETYPE_NONE; - self->svflags |= SVF_NOCLIENT; - self->nextthink = 0; - self->use = monster_triggered_spawn_use; - // Lazarus - self->spawnflags &= ~SF_MONSTER_TRIGGER_SPAWN; -} - - -/* -================ -monster_death_use - -When a monster dies, it fires all of its targets with the current -enemy as activator. -================ -*/ -void monster_death_use (edict_t *self) -{ - edict_t *player; - int i; - - self->flags &= ~(FL_FLY|FL_SWIM); - self->monsterinfo.aiflags &= AI_GOOD_GUY; - - // Lazarus: If actor/monster is being used as a camera by a player, - // turn camera off for that player - for(i=0,player=g_edicts+1; ivalue; i++, player++) { - if(player->client && player->client->spycam == self) - camera_off(player); - } - - - if (self->item) - { - Drop_Item (self, self->item); - self->item = NULL; - } - - if (self->deathtarget) - self->target = self->deathtarget; - - if (!self->target) - return; - - G_UseTargets (self, self->enemy); -} - - -//============================================================================ - -bool monster_start (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return false; - } - - // Lazarus: Already gibbed monsters passed across levels via trigger_transition: - if ( (self->max_health > 0) && (self->health <= self->gib_health) && !(self->spawnflags & SF_MONSTER_NOGIB) ) - { - void SP_gibhead(edict_t *); - - SP_gibhead(self); - return true; - } - - // Lazarus: Good guys - if (self->spawnflags & SF_MONSTER_GOODGUY) { - self->monsterinfo.aiflags |= AI_GOOD_GUY; - if(!self->dmgteam) { - self->dmgteam = TagMalloc(8*sizeof(char), TAG_LEVEL); - strcpy(self->dmgteam,"player"); - } - } - - // Lazarus: Max range for sight/attack - if(st.distance) - self->monsterinfo.max_range = max(500,st.distance); - else - self->monsterinfo.max_range = 1280; // Q2 default is 1000. We're mean. - - // Lazarus: We keep SIGHT to mean what old AMBUSH does, and AMBUSH additionally - // now means don't play idle sounds -/* if ((self->spawnflags & MONSTER_SIGHT) && !(self->monsterinfo.aiflags & AI_GOOD_GUY)) - { - self->spawnflags &= ~MONSTER_SIGHT; - self->spawnflags |= MONSTER_AMBUSH; - } */ - if ((self->spawnflags & SF_MONSTER_AMBUSH) && !(self->monsterinfo.aiflags & AI_GOOD_GUY)) - self->spawnflags |= SF_MONSTER_SIGHT; - - // Lazarus: Don't add trigger spawned monsters until they are actually spawned - if (!(self->monsterinfo.aiflags & AI_GOOD_GUY) && !(self->spawnflags & SF_MONSTER_TRIGGER_SPAWN)) - level.total_monsters++; - - self->nextthink = level.time + FRAMETIME; - self->svflags |= SVF_MONSTER; - self->s.renderfx |= RF_FRAMELERP; - - // Lazarus - map-settable renderfx and effects - self->s.renderfx |= self->renderfx; - self->s.effects |= self->effects; - - self->air_finished = level.time + 12; - self->use = monster_use; - // Lazarus - don't reset max_health unnecessarily - if(!self->max_health) - self->max_health = self->health; - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - else - self->s.skin &= ~1; - self->clipmask = MASK_MONSTERSOLID; - - if(self->monsterinfo.flies > 1.0) - { - self->s.effects |= EF_FLIES; - self->s.sound = gi.soundindex ("infantry/inflies1.wav"); - } - - // Lazarus - if(self->health <=0) - { - self->svflags |= SVF_DEADMONSTER; - self->movetype = MOVETYPE_TOSS; - self->takedamage = DAMAGE_YES; - self->monsterinfo.pausetime = 100000000; - self->monsterinfo.aiflags &= ~AI_RESPAWN_FINDPLAYER; - if(self->max_health > 0) - { - // This must be a dead monster who changed levels - // via trigger_transition - self->nextthink = 0; - self->deadflag = DEAD_DEAD; - } - if(self->s.effects & EF_FLIES && self->monsterinfo.flies <= 1.0) - { - self->think = M_FliesOff; - self->nextthink = level.time + 1 + random()*60; - } - return true; - } - else - { - // make sure red shell is turned off in case medic got confused: - self->monsterinfo.aiflags &= ~AI_RESURRECTING; - self->svflags &= ~SVF_DEADMONSTER; - self->takedamage = DAMAGE_AIM; - } - - if (!self->monsterinfo.checkattack) - self->monsterinfo.checkattack = M_CheckAttack; - VectorCopy (self->s.origin, self->s.old_origin); - - if (st.item) - { - self->item = FindItemByClassname (st.item); - if (!self->item) - gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item); - } - - // randomize what frame they start on - // Lazarus: preserve frame if set for monsters changing levels - if (!self->s.frame) - { - if (self->monsterinfo.currentmove) - self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1)); - } - - return true; -} - -void monster_start_go (edict_t *self) -{ - vec3_t v; - - if (self->health <= 0) - { - if (self->max_health <= 0) - InitiallyDead(self); - return; - } - - // Lazarus: move_origin for func_monitor - if(!VectorLength(self->move_origin)) - VectorSet(self->move_origin,0,0,self->viewheight); - - // check for target to point_combat and change to combattarget - if (self->target) - { - bool notcombat; - bool fixup; - edict_t *target; - - target = NULL; - notcombat = false; - fixup = false; - while ((target = G_Find (target, FOFS(targetname), self->target)) != NULL) - { - if (target->class_id == ENTITY_POINT_COMBAT) - { - self->combattarget = self->target; - fixup = true; - } - else - { - notcombat = true; - } - } - if (notcombat && self->combattarget) - gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin)); - if (fixup) - self->target = NULL; - } - - // validate combattarget - if (self->combattarget) - { - edict_t *target; - - target = NULL; - while ((target = G_Find (target, FOFS(targetname), self->combattarget)) != NULL) - { - if (target->class_id != ENTITY_POINT_COMBAT) - { - gi.dprintf("%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)\n", - self->classname, (int)self->s.origin[0], (int)self->s.origin[1], (int)self->s.origin[2], - self->combattarget, target->classname, (int)target->s.origin[0], (int)target->s.origin[1], - (int)target->s.origin[2]); - } - } - } - - if (self->target) - { - self->goalentity = self->movetarget = G_PickTarget(self->target); - if (!self->movetarget) - { - gi.dprintf ("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin)); - self->target = NULL; - self->monsterinfo.pausetime = 100000000; - self->monsterinfo.stand (self); - } - else if (self->movetarget->class_id == ENTITY_PATH_CORNER) - { - // Lazarus: Don't wipe out target for trigger spawned monsters - // that aren't triggered yet - if( ! (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) ) { - VectorSubtract (self->goalentity->s.origin, self->s.origin, v); - self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v); - self->monsterinfo.walk (self); - self->target = NULL; - } - } - else - { - self->goalentity = self->movetarget = NULL; - self->monsterinfo.pausetime = 100000000; - self->monsterinfo.stand (self); - } - } - else - { - self->monsterinfo.pausetime = 100000000; - self->monsterinfo.stand (self); - } - - self->think = monster_think; - self->nextthink = level.time + FRAMETIME; -} - - -void walkmonster_start_go (edict_t *self) -{ - if (!(self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) && level.time < 1) - { - M_droptofloor (self); - - if (self->groundentity) - if (!M_walkmove (self, 0, 0)) - gi.dprintf ("%s in solid at %s\n", self->classname, vtos(self->s.origin)); - } - - if (!self->yaw_speed) - self->yaw_speed = 20; - self->viewheight = 25; - - // Lazarus: monster_chick model is different from all others, in that origin of model - // is at the feet. So viewheight=25 puts her eyeballs at her waist, which is crippling - if(self->class_id == ENTITY_MONSTER_CHICK) - self->viewheight = 49; - - monster_start_go (self); - - if (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) - monster_triggered_start (self); - -} - -void walkmonster_start (edict_t *self) -{ - self->think = walkmonster_start_go; - monster_start (self); -} - - -void flymonster_start_go (edict_t *self) -{ - if (!M_walkmove (self, 0, 0)) - gi.dprintf ("%s in solid at %s\n", self->classname, vtos(self->s.origin)); - - if (!self->yaw_speed) - self->yaw_speed = 10; - self->viewheight = 25; - - self->monsterinfo.flies = 0.0; - - monster_start_go (self); - - if (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) - monster_triggered_start (self); -} - - -void flymonster_start (edict_t *self) -{ - self->flags |= FL_FLY; - self->think = flymonster_start_go; - monster_start (self); -} - - -void swimmonster_start_go (edict_t *self) -{ - if (!self->yaw_speed) - self->yaw_speed = 10; - self->viewheight = 10; - - monster_start_go (self); - - if (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) - monster_triggered_start (self); -} - -void swimmonster_start (edict_t *self) -{ - self->flags |= FL_SWIM; - self->think = swimmonster_start_go; - monster_start (self); -} - -//ROGUE - -void stationarymonster_start_go (edict_t *self); - -void stationarymonster_triggered_spawn (edict_t *self) -{ - KillBox (self); - - self->solid = SOLID_BBOX; - self->movetype = MOVETYPE_NONE; - self->svflags &= ~SVF_NOCLIENT; - self->air_finished = level.time + 12; - gi.linkentity (self); - - // FIXME - why doesn't this happen with real monsters? - self->spawnflags &= ~SF_MONSTER_TRIGGER_SPAWN; - - stationarymonster_start_go (self); - - if (self->enemy && !(self->spawnflags & SF_MONSTER_SIGHT) && !(self->enemy->flags & FL_NOTARGET)) - { - if(!(self->enemy->flags & FL_DISGUISED)) // PGM - FoundTarget (self); - else // PMM - just in case, make sure to clear the enemy so FindTarget doesn't get confused - self->enemy = NULL; - } - else - { - self->enemy = NULL; - } -} - -void stationarymonster_triggered_spawn_use (edict_t *self, edict_t *other, edict_t *activator) -{ - // we have a one frame delay here so we don't telefrag the guy who activated us - self->think = stationarymonster_triggered_spawn; - self->nextthink = level.time + FRAMETIME; - if (activator->client) - self->enemy = activator; - // Lazarus: Add 'em - if(!(self->monsterinfo.aiflags & AI_GOOD_GUY)) - level.total_monsters++; - self->use = monster_use; -} - -void stationarymonster_triggered_start (edict_t *self) -{ - self->solid = SOLID_NOT; - self->movetype = MOVETYPE_NONE; - self->svflags |= SVF_NOCLIENT; - self->nextthink = 0; - self->use = stationarymonster_triggered_spawn_use; -} - -void stationarymonster_start_go (edict_t *self) -{ -// PGM - only turrets use this, so remove the error message. They're supposed to be in solid. - -// if (!M_walkmove (self, 0, 0)) -// gi.dprintf ("%s in solid at %s\n", self->classname, vtos(self->s.origin)); - - if (!self->yaw_speed) - self->yaw_speed = 20; -// self->viewheight = 25; - - monster_start_go (self); - - if (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) - stationarymonster_triggered_start (self); -} - -void stationarymonster_start (edict_t *self) -{ - self->think = stationarymonster_start_go; - monster_start (self); -} - -// Following functions unique to Lazarus - -void InitiallyDead (edict_t *self) -{ - int damage; - - if(self->max_health > 0) - return; - -// gi.dprintf("InitiallyDead on %s at %s\n",self->classname,vtos(self->s.origin)); - - // initially dead bad guys shouldn't count against totals - if((self->max_health <= 0) && !(self->monsterinfo.aiflags & AI_GOOD_GUY)) - { - level.total_monsters--; - if(self->deadflag != DEAD_DEAD) - level.killed_monsters--; - } - if(self->deadflag != DEAD_DEAD) - { - damage = 1 - self->health; - self->health = 1; - T_Damage (self, world, world, vec3_origin, self->s.origin, vec3_origin, damage, 0, DAMAGE_NO_ARMOR, 0); - if(self->svflags & SVF_MONSTER) - { - self->svflags |= SVF_DEADMONSTER; - self->think = monster_think; - self->nextthink = level.time + FRAMETIME; - } - } - gi.linkentity(self); -} - -#define MAX_SKINS 16 -#define MAX_SKINNAME 64 - -#include -#include "pak.h" - -int PatchMonsterModel (char *modelname) -{ - cvar_t *gamedir; - int j; - int numskins; // number of skin entries - char skins[MAX_SKINS][MAX_SKINNAME]; // skin entries - char outfilename[MAX_OSPATH]; - char *p; - file_t *infile; - file_t *outfile; - dmdl_t model; // model header - byte *data; // model data - int datasize; // model data size (bytes) - int newoffset; // model data offset (after skins) - bool is_tank=false; - bool is_soldier=false; - - // get game (moddir) name - gamedir = gi.cvar("game", "", 0); - if (!*gamedir->string) return 0; // we're in baseq2 - - if (outfile = gi.Fs.Open (modelname, "rb")) - { - // output file already exists, move along - gi.Fs.Close (outfile); - return 0; - } - - numskins = 8; - // special cases - if(!strcmp(modelname,"models/monsters/tank/tris.md2")) - { - is_tank = true; - numskins = 16; - } - else if(!strcmp(modelname,"models/monsters/soldier/tris.md2")) - { - is_soldier = true; - numskins = 24; - } - - for (j = 0; j < numskins; j++) - { - memset (skins[j], 0, MAX_SKINNAME); - strcpy( skins[j], modelname ); - p = strstr( skins[j], "tris.md2" ); - if(!p) - { - gi.Fs.Close (outfile); - gi.dprintf( "Error patching %s\n",modelname); - return 0; - } - *p = 0; - if(is_soldier) - { - switch (j) - { - case 0: strcat (skins[j], "skin_lt.pcx"); break; - case 1: strcat (skins[j], "skin_ltp.pcx"); break; - case 2: strcat (skins[j], "skin.pcx"); break; - case 3: strcat (skins[j], "pain.pcx"); break; - case 4: strcat (skins[j], "skin_ss.pcx"); break; - case 5: strcat (skins[j], "skin_ssp.pcx"); break; - case 6: strcat (skins[j], "custom1_lt.pcx"); break; - case 7: strcat (skins[j], "custompain1_lt.pcx"); break; - case 8: strcat (skins[j], "custom1.pcx"); break; - case 9: strcat (skins[j], "custompain1.pcx"); break; - case 10: strcat (skins[j], "custom1_ss.pcx"); break; - case 11: strcat (skins[j], "custompain1_ss.pcx"); break; - case 12: strcat (skins[j], "custom2_lt.pcx"); break; - case 13: strcat (skins[j], "custompain2_lt.pcx"); break; - case 14: strcat (skins[j], "custom2.pcx"); break; - case 15: strcat (skins[j], "custompain2.pcx"); break; - case 16: strcat (skins[j], "custom2_ss.pcx"); break; - case 17: strcat (skins[j], "custompain2_ss.pcx"); break; - case 18: strcat (skins[j], "custom3_lt.pcx"); break; - case 19: strcat (skins[j], "custompain3_lt.pcx"); break; - case 20: strcat (skins[j], "custom3.pcx"); break; - case 21: strcat (skins[j], "custompain3.pcx"); break; - case 22: strcat (skins[j], "custom3_ss.pcx"); break; - case 23: strcat (skins[j], "custompain3_ss.pcx"); break; - } - } - else if(is_tank) - { - switch (j) - { - case 0: strcat (skins[j], "skin.pcx"); break; - case 1: strcat (skins[j], "pain.pcx"); break; - case 2: strcat (skins[j], "../ctank/skin.pcx"); break; - case 3: strcat (skins[j], "../ctank/pain.pcx"); break; - case 4: strcat (skins[j], "custom1.pcx"); break; - case 5: strcat (skins[j], "custompain1.pcx"); break; - case 6: strcat (skins[j], "../ctank/custom1.pcx"); break; - case 7: strcat (skins[j], "../ctank/custompain1.pcx"); break; - case 8: strcat (skins[j], "custom2.pcx"); break; - case 9: strcat (skins[j], "custompain2.pcx"); break; - case 10: strcat (skins[j], "../ctank/custom2.pcx"); break; - case 11: strcat (skins[j], "../ctank/custompain2.pcx"); break; - case 12: strcat (skins[j], "custom3.pcx"); break; - case 13: strcat (skins[j], "custompain3.pcx"); break; - case 14: strcat (skins[j], "../ctank/custom3.pcx"); break; - case 15: strcat (skins[j], "../ctank/custompain3.pcx"); break; - } - } - else - { - switch (j) - { - case 0: strcat (skins[j], "skin.pcx"); break; - case 1: strcat (skins[j], "pain.pcx"); break; - case 2: strcat (skins[j], "custom1.pcx"); break; - case 3: strcat (skins[j], "custompain1.pcx"); break; - case 4: strcat (skins[j], "custom2.pcx"); break; - case 5: strcat (skins[j], "custompain2.pcx"); break; - case 6: strcat (skins[j], "custom3.pcx"); break; - case 7: strcat (skins[j], "custompain3.pcx"); break; - } - } - } - - infile = gi.Fs.Open (modelname, "rb"); - if(!infile) - { - gi.dprintf ("PatchMonsterModel: %s not found\n", modelname ); - return 0; - } - gi.Fs.Read (infile, &model, sizeof (dmdl_t)); - - datasize = model.ofs_end - model.ofs_skins; - if ( !(data = malloc (datasize)) ) // make sure freed locally - { - gi.dprintf ("PatchMonsterModel: Could not allocate memory for model\n"); - return 0; - } - gi.Fs.Read (infile, data, datasize * sizeof (byte)); - gi.Fs.Close (infile); - - // update model info - model.num_skins = numskins; - - newoffset = numskins * MAX_SKINNAME; - model.ofs_st += newoffset; - model.ofs_tris += newoffset; - model.ofs_frames += newoffset; - model.ofs_glcmds += newoffset; - model.ofs_end += newoffset; - - // save new model - if (!(outfile = gi.Fs.Open (modelname, "wb")) ) - { - // file couldn't be created for some other reason - gi.dprintf ("PatchMonsterModel: Could not save %s\n", outfilename); - free (data); - return 0; - } - - gi.Fs.Write (outfile, &model, sizeof (dmdl_t)); - gi.Fs.Write (outfile, skins, sizeof (char) * newoffset); - gi.Fs.Write (outfile, data, sizeof (byte) * datasize); - - gi.Fs.Close (outfile); - gi.dprintf ("PatchMonsterModel: Saved %s\n", outfilename); - free (data); - return 1; -} - -void HintTestNext (edict_t *self, edict_t *hint) -{ - edict_t *next=NULL; - edict_t *e; - vec3_t dir; - - self->monsterinfo.aiflags &= ~AI_HINT_TEST; - if(self->goalentity == hint) - self->goalentity = NULL; - if(self->movetarget == hint) - self->movetarget = NULL; - if(self->monsterinfo.pathdir == 1) - { - if(hint->hint_chain) - next = hint->hint_chain; - else - self->monsterinfo.pathdir = -1; - } - if(self->monsterinfo.pathdir == -1) - { - e = hint_path_start[hint->hint_chain_id]; - while(e) - { - if(e->hint_chain == hint) - { - next = e; - break; - } - e = e->hint_chain; - } - } - if(!next) - { - self->monsterinfo.pathdir = 1; - next = hint->hint_chain; - } - if(next) - { - self->hint_chain_id = next->hint_chain_id; - VectorSubtract(next->s.origin, self->s.origin, dir); - self->ideal_yaw = vectoyaw(dir); - self->goalentity = self->movetarget = next; - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags = AI_HINT_TEST; - // run for it - self->monsterinfo.run (self); - gi.dprintf("%s (%s): Reached hint_path %s,\nsearching for hint_path %s at %s. %s\n", - self->classname, (self->targetname ? self->targetname : ""), - (hint->targetname ? hint->targetname : ""), - (next->targetname ? next->targetname : ""), - vtos(next->s.origin), - (visible(self,next) ? "I see it." : "I don't see it.")); - } - else - { - self->monsterinfo.pausetime = level.time + 100000000; - self->monsterinfo.stand (self); - gi.dprintf("%s (%s): Error finding next/previous hint_path from %s at %s.\n", - self->classname, (self->targetname ? self->targetname : ""), - (hint->targetname ? hint->targetname : ""), - vtos(hint->s.origin)); - } -} - -int HintTestStart (edict_t *self) -{ - edict_t *e; - edict_t *hint=NULL; - float dist; - vec3_t dir; - int i; - float bestdistance=99999; - - if(!hint_paths_present) - return 0; - - for(i=game.maxclients+1; iinuse) - continue; - if(e->class_id != ENTITY_HINT_PATH) - continue; - if(!visible(self,e)) - continue; - if(!canReach(self,e)) - continue; - VectorSubtract(e->s.origin,self->s.origin,dir); - dist = VectorLength(dir); - if(dist < bestdistance) - { - hint = e; - bestdistance = dist; - } - } - if(hint) - { - self->hint_chain_id = hint->hint_chain_id; - if(!self->monsterinfo.pathdir) - self->monsterinfo.pathdir = 1; - VectorSubtract(hint->s.origin, self->s.origin, dir); - self->ideal_yaw = vectoyaw(dir); - self->enemy = self->oldenemy = NULL; - self->goalentity = self->movetarget = hint; - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags = AI_HINT_TEST; - // run for it - self->monsterinfo.run (self); - return 1; - } - else - return -1; -} diff --git a/server/monsters/m_actor.c b/server/monsters/m_actor.c deleted file mode 100644 index 87dcf770..00000000 --- a/server/monsters/m_actor.c +++ /dev/null @@ -1,1972 +0,0 @@ -// m_actor.c -// -// Lazarus 1.4: Adopted Mappack misc_actor code -// -#include "g_local.h" -#include "m_actor.h" -#include "pak.h" - -static char wavname[NUM_ACTOR_SOUNDS][32] = -{ "jump1.wav", - "pain25_1.wav", - "pain25_2.wav", - "pain50_1.wav", - "pain50_2.wav", - "pain75_1.wav", - "pain75_2.wav", - "pain100_1.wav", - "pain100_2.wav", - "death1.wav", - "death2.wav", - "death3.wav", - "death4.wav" }; - -#define ACTOR_SOUND_JUMP 0 // Do NOT change this one -#define ACTOR_SOUND_PAIN_25_1 1 -#define ACTOR_SOUND_PAIN_25_2 2 -#define ACTOR_SOUND_PAIN_50_1 3 -#define ACTOR_SOUND_PAIN_50_2 4 -#define ACTOR_SOUND_PAIN_75_1 5 -#define ACTOR_SOUND_PAIN_75_2 6 -#define ACTOR_SOUND_PAIN_100_1 7 -#define ACTOR_SOUND_PAIN_100_2 8 -#define ACTOR_SOUND_DEATH1 9 -#define ACTOR_SOUND_DEATH2 10 -#define ACTOR_SOUND_DEATH3 11 -#define ACTOR_SOUND_DEATH4 12 - -mframe_t actor_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t actor_move_stand = {FRAME_stand01, FRAME_stand40, actor_frames_stand, NULL}; - -void actor_stand (edict_t *self) -{ - self->s.sound = 0; - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouch; - else - self->monsterinfo.currentmove = &actor_move_stand; - - // randomize on startup - if (level.time < 1.0) - self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1)); -} - -mframe_t actor_frames_walk [] = -{ -/* ai_walk, 4, NULL, - ai_walk, 15, NULL, - ai_walk, 15, NULL, - ai_walk, 8, NULL, - ai_walk, 20, NULL, - ai_walk, 15, NULL, - ai_walk, 8, NULL, - ai_walk, 17, NULL, - ai_walk, 12, NULL, - ai_walk, -2, NULL, - ai_walk, -2, NULL, - ai_walk, -1, NULL */ - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL -}; -mmove_t actor_move_walk = {FRAME_run1, FRAME_run6, actor_frames_walk, NULL}; - -mmove_t actor_move_run; -void actor_walk (edict_t *self) -{ - // prevent foolishness: - if (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - if(!self->movetarget || !self->movetarget->inuse || (self->movetarget == world)) - self->movetarget = self->monsterinfo.leader; - } - - if( (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) && - (self->movetarget) && - (self->movetarget->inuse) && - (self->movetarget->health > 0) ) - { - float R; - - R = realrange(self,self->movetarget); - if(R > ACTOR_FOLLOW_RUN_RANGE || self->enemy) - { - self->monsterinfo.currentmove = &actor_move_run; - if(self->monsterinfo.aiflags & AI_CROUCH) - { - self->monsterinfo.aiflags &= ~AI_CROUCH; - self->maxs[2] += 28; - self->viewheight += 28; - self->move_origin[2] += 28; - } - } - else if(R <= ACTOR_FOLLOW_STAND_RANGE && self->movetarget->client) - { - self->monsterinfo.pausetime = level.time + 0.5; - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouch; - else - self->monsterinfo.currentmove = &actor_move_stand; - } - else - { - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouchwalk; - else - self->monsterinfo.currentmove = &actor_move_walk; - } - } - else - { - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouchwalk; - else - self->monsterinfo.currentmove = &actor_move_walk; - } -} - -mframe_t actor_frames_walk_back [] = -{ - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL -}; -mmove_t actor_move_walk_back = {FRAME_run1, FRAME_run6, actor_frames_walk_back, NULL}; - -mframe_t actor_frames_crouchwalk_back [] = -{ - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL, - ai_walk, -10, NULL -}; -mmove_t actor_move_crouchwalk_back = {FRAME_crwalk1, FRAME_crwalk6, actor_frames_crouchwalk_back, NULL}; - -void actor_walk_back (edict_t *self) -{ - // prevent foolishness: - if (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - if(!self->movetarget || !self->movetarget->inuse || (self->movetarget == world)) - self->movetarget = self->monsterinfo.leader; - } - - if( (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) && - (self->movetarget) && - (self->movetarget->inuse) && - (self->movetarget->health > 0) ) - { - float R; - - R = realrange(self,self->movetarget); - if(R <= ACTOR_FOLLOW_STAND_RANGE && self->movetarget->client) - { - self->monsterinfo.pausetime = level.time + 0.5; - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouch; - else - self->monsterinfo.currentmove = &actor_move_stand; - } - else - { - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouchwalk_back; - else - self->monsterinfo.currentmove = &actor_move_walk_back; - } - } - else - { - if(self->monsterinfo.aiflags & AI_CROUCH) - self->monsterinfo.currentmove = &actor_move_crouchwalk_back; - else - self->monsterinfo.currentmove = &actor_move_walk_back; - } -} -mframe_t actor_frames_crouch [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t actor_move_crouch = {FRAME_crstnd01, FRAME_crstnd19, actor_frames_crouch, NULL}; - -mframe_t actor_frames_crouchwalk [] = -{ - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL, - ai_walk, 10, NULL -}; -mmove_t actor_move_crouchwalk = {FRAME_crwalk1, FRAME_crwalk6, actor_frames_crouchwalk, NULL}; - -// DWH: Changed running speed to a constant (equal to player running speed) for normal -// misc_actor and 2/3 that for "bad guys". Also eliminated excess frames. -mframe_t actor_frames_run [] = -{ - ai_run, 40, NULL, - ai_run, 40, NULL, - ai_run, 40, NULL, - ai_run, 40, NULL, - ai_run, 40, NULL, - ai_run, 40, NULL -}; -mmove_t actor_move_run = {FRAME_run1, FRAME_run6, actor_frames_run, NULL}; - -mframe_t actor_frames_run_bad [] = -{ - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 30, NULL -}; - -mmove_t actor_move_run_bad = {FRAME_run1, FRAME_run6, actor_frames_run_bad, NULL}; - -void actor_run (edict_t *self) -{ - // prevent foolishness: - if (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - if(!self->movetarget || !self->movetarget->inuse || (self->movetarget == world)) - self->movetarget = self->monsterinfo.leader; - } - if ((level.time < self->pain_debounce_time) && (!self->enemy)) - { - if (self->movetarget) - actor_walk(self); - else - actor_stand(self); - return; - } - - if ( self->monsterinfo.aiflags & AI_STAND_GROUND ) - { - actor_stand(self); - return; - } - - if( self->monsterinfo.aiflags & AI_CROUCH) - { - self->monsterinfo.aiflags &= ~AI_CROUCH; - self->maxs[2] += 28; - self->viewheight += 28; - self->move_origin[2] += 28; - } - - if( self->monsterinfo.aiflags & AI_GOOD_GUY ) { - self->monsterinfo.currentmove = &actor_move_run; - } - else - { - self->monsterinfo.currentmove = &actor_move_run_bad; - } -} - -mframe_t actor_frames_run_back [] = -{ - ai_run, -40, NULL, - ai_run, -40, NULL, - ai_run, -40, NULL, - ai_run, -40, NULL, - ai_run, -40, NULL, - ai_run, -40, NULL -}; -mmove_t actor_move_run_back = {FRAME_run1, FRAME_run6, actor_frames_run_back, NULL}; - -void actor_run_back (edict_t *self) -{ - // prevent foolishness: - if (self->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - if(!self->movetarget || !self->movetarget->inuse || (self->movetarget == world)) - self->movetarget = self->monsterinfo.leader; - } - if ((level.time < self->pain_debounce_time) && (!self->enemy)) - { - if (self->movetarget) - actor_walk_back(self); - else - actor_stand(self); - return; - } - - if ( self->monsterinfo.aiflags & AI_STAND_GROUND ) - { - actor_stand(self); - return; - } - - if( self->monsterinfo.aiflags & AI_CROUCH) - { - self->monsterinfo.aiflags &= ~AI_CROUCH; - self->maxs[2] += 28; - self->viewheight += 28; - self->move_origin[2] += 28; - } - - self->monsterinfo.currentmove = &actor_move_run_back; -} -mframe_t actor_frames_pain1 [] = -{ - ai_move, -5, NULL, - ai_move, 4, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL -}; -mmove_t actor_move_pain1 = {FRAME_pain101, FRAME_pain104, actor_frames_pain1, actor_run}; - -mframe_t actor_frames_pain2 [] = -{ - ai_move, -4, NULL, - ai_move, 4, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t actor_move_pain2 = {FRAME_pain201, FRAME_pain204, actor_frames_pain2, actor_run}; - -mframe_t actor_frames_pain3 [] = -{ - ai_move, -1, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL -}; -mmove_t actor_move_pain3 = {FRAME_pain301, FRAME_pain304, actor_frames_pain3, actor_run}; - -mframe_t actor_frames_flipoff [] = -{ - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL -}; -mmove_t actor_move_flipoff = {FRAME_flip01, FRAME_flip12, actor_frames_flipoff, actor_run}; - -mframe_t actor_frames_taunt [] = -{ - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL -}; -mmove_t actor_move_taunt = {FRAME_taunt01, FRAME_taunt17, actor_frames_taunt, actor_run}; - -void actor_ideal_range(edict_t *self) -{ - int weapon; - - weapon = self->actor_weapon[self->actor_current_weapon]; - - switch(weapon) - { - case 2: - self->monsterinfo.ideal_range[0] = 0; - self->monsterinfo.ideal_range[1] = 270; - break; - case 3: - self->monsterinfo.ideal_range[0] = 0; - self->monsterinfo.ideal_range[1] = 90; - break; - case 4: - case 5: - self->monsterinfo.ideal_range[0] = 0; - self->monsterinfo.ideal_range[1] = 450; - break; - case 6: - self->monsterinfo.ideal_range[0] = 200; - self->monsterinfo.ideal_range[1] = 450; - break; - case 7: - self->monsterinfo.ideal_range[0] = 300; - self->monsterinfo.ideal_range[1] = 1000; - break; - case 8: - self->monsterinfo.ideal_range[0] = 200; - self->monsterinfo.ideal_range[1] = 500; - break; - case 9: - case 10: - self->monsterinfo.ideal_range[0] = 300; - self->monsterinfo.ideal_range[1] = 1000; - break; - default: - self->monsterinfo.ideal_range[0] = 0; - self->monsterinfo.ideal_range[1] = 0; - } -} - -void actor_attack(edict_t *self); -void actor_switch (edict_t *self) -{ - self->actor_current_weapon = 1 - self->actor_current_weapon; - self->s.weaponmodel = self->actor_model_index[self->actor_current_weapon]; - actor_ideal_range(self); - gi.linkentity(self); -} -mframe_t actor_frames_switch [] = -{ - ai_run, 0, actor_switch, - ai_run, 0, NULL, - ai_run, 0, NULL -}; -mmove_t actor_move_switch = {FRAME_jump4, FRAME_jump6, actor_frames_switch, actor_attack}; - -void actor_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - int n; - int r, l; - - // DWH: Players don't have pain skins! -// if (self->health < (self->max_health / 2)) -// self->s.skin = 1; - - // Stop weapon sound, if any - self->s.sound = 0; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 1; - - // DWH: Use same scheme used for player pain sounds - if (!(self->flags & FL_GODMODE)) - { - r = (rand()&1); - if (self->health < 25) - l = 0; - else if (self->health < 50) - l = 2; - else if (self->health < 75) - l = 4; - else - l = 6; - gi.sound (self, CHAN_VOICE, self->actor_sound_index[ACTOR_SOUND_PAIN_25_1 + l + r], - 1, ATTN_NORM, 0); - } - - // Lazarus: Removed printed message, but keep taunt (not for monster actors, though) - if ((other->client) && (random() < 0.4) && (self->monsterinfo.aiflags & AI_GOOD_GUY)) - { - vec3_t v; - VectorSubtract (other->s.origin, self->s.origin, v); - self->ideal_yaw = vectoyaw (v); - if (random() < 0.5) { - self->monsterinfo.currentmove = &actor_move_flipoff; - } - else - { - self->monsterinfo.currentmove = &actor_move_taunt; - } - return; - } - - - n = rand() % 3; - if (n == 0) - self->monsterinfo.currentmove = &actor_move_pain1; - else if (n == 1) - self->monsterinfo.currentmove = &actor_move_pain2; - else - self->monsterinfo.currentmove = &actor_move_pain3; - -} - -// -// Attack code moved to m_actor_weap.c -// - -void actor_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t actor_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -13, NULL, - ai_move, 14, NULL, - ai_move, 3, NULL, - ai_move, -2, NULL -}; -mmove_t actor_move_death1 = {FRAME_death101, FRAME_death106, actor_frames_death1, actor_dead}; - -mframe_t actor_frames_death2 [] = -{ - ai_move, 0, NULL, - ai_move, 7, NULL, - ai_move, -6, NULL, - ai_move, -5, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL -}; -mmove_t actor_move_death2 = {FRAME_death201, FRAME_death206, actor_frames_death2, actor_dead}; - -void actor_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - //Remove the weapon model and turn off weapon sound, if any - self->s.weaponmodel = 0; - self->s.sound = 0; - -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, - self->actor_sound_index[ACTOR_SOUND_DEATH1 + (rand()%4)], 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - if(self->monsterinfo.aiflags & AI_CHASE_THING) - { - if(self->movetarget && (self->movetarget->class_id == ENTITY_THING)) - { - G_FreeEdict(self->movetarget); - self->movetarget = NULL; - } - } - self->monsterinfo.aiflags &= ~(AI_FOLLOW_LEADER | AI_CHASE_THING | AI_CHICKEN | AI_EVADE_GRENADE); - if (random() > 0.5) - self->monsterinfo.currentmove = &actor_move_death1; - else - self->monsterinfo.currentmove = &actor_move_death2; -} - -void actor_fire (edict_t *self) -{ - int weapon; - - weapon = self->actor_weapon[self->actor_current_weapon]; - - switch(weapon) { - case 1: - actorBlaster (self); - break; - case 2: - actorShotgun (self); - break; - case 3: - actorSuperShotgun (self); - break; - case 4: - actorMachineGun (self); - if (level.time >= self->monsterinfo.pausetime) -// self->monsterinfo.aiflags &= ~(AI_HOLD_FRAME|AI_STAND_GROUND); - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else -// self->monsterinfo.aiflags |= (AI_HOLD_FRAME|AI_STAND_GROUND); - self->monsterinfo.aiflags |= AI_HOLD_FRAME; - break; - case 5: - actorChaingun (self); - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; - break; - case 6: - actorGrenadeLauncher (self); - break; - case 7: - actorRocket(self); - break; - case 8: - actorHyperblaster(self); - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; - break; - case 9: - actorRailGun(self); - break; - case 10: - actorBFG(self); - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; - break; - } -} - -void actor_no_weapon_sound(edict_t *self) -{ - self->s.sound = 0; - gi.linkentity(self); -} - -static int chase_angle[] = {360,315,405,270,450,225,495,540}; -void actor_seekcover (edict_t *self) -{ - int i; - edict_t *thing; - vec3_t atk, dir, best_dir, end, forward; - vec_t travel, yaw; - vec3_t mins, maxs; - vec3_t testpos; - vec_t best_dist=0; - trace_t trace1, trace2; - - // No point in hiding from enemy if.. we don't have an enemy - if(!self->enemy || !self->enemy->inuse) - { - actor_run(self); - return; - } - if(!actorscram->value) - { - actor_run(self); - return; - } - // Don't hide from non-humanoid stuff - if(!self->enemy->client && !(self->enemy->svflags & SVF_MONSTER)) - { - actor_run(self); - return; - } - // This shouldn't happen, we're just being cautious. Quit now if - // already chasing a "thing" - if(self->movetarget && (self->movetarget->class_id == ENTITY_THING)) - { - actor_run(self); - return; - } - // Don't bother finding cover if we're within melee range of enemy - VectorSubtract(self->enemy->s.origin,self->s.origin,atk); - if(VectorLength(atk) < 80) - { - actor_run(self); - return; - } - VectorCopy(self->mins,mins); - mins[2] += 18; - if(mins[2] > 0) mins[2] = 0; - VectorCopy(self->maxs,maxs); - - // Find a vector that will hide the actor from his enemy - VectorCopy(self->enemy->s.origin,atk); - atk[2] += self->enemy->viewheight; - VectorClear(best_dir); - AngleVectors(self->s.angles,forward,NULL,NULL); - dir[2] = 0; - for(travel=64; travel<257 && best_dist == 0; travel *= 2) - { - for(i=0; i<8 && best_dist == 0; i++) - { - yaw = self->s.angles[YAW] + chase_angle[i]; - yaw = (int)(yaw/45)*45; - yaw = anglemod(yaw); - yaw *= M_PI/180; - dir[0] = cos(yaw); - dir[1] = sin(yaw); - VectorMA(self->s.origin,travel,dir,end); - trace1 = gi.trace(self->s.origin,mins,maxs,end,self,MASK_MONSTERSOLID); - // Test whether proposed position can be seen by enemy. Test - // isn't foolproof - tests against 1) new origin, 2-5) each corner of top - // of bounding box. - trace2 = gi.trace(trace1.endpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - VectorAdd(trace1.endpos,self->maxs,testpos); - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - testpos[0] = trace1.endpos[0] + self->mins[0]; - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - testpos[1] = trace1.endpos[1] + self->mins[1]; - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - testpos[0] = trace1.endpos[0] + self->maxs[0]; - trace2 = gi.trace(testpos,NULL,NULL,atk,self,MASK_SOLID); - if(trace2.fraction == 1.0) continue; - - best_dist = trace1.fraction * travel; - if(best_dist < 32) // not much point to this move - continue; - VectorCopy(dir,best_dir); - } - } - if(best_dist < 32) - { - actor_run(self); - return; - } - // This snaps the angles, which may not be all that good but it sure - // is quicker than turning in place - vectoangles(best_dir,self->s.angles); - thing = SpawnThing(); - VectorMA(self->s.origin,best_dist,best_dir,thing->s.origin); - thing->touch_debounce_time = level.time + 3.0; - thing->target_ent = self; - ED_CallSpawn(thing); - self->movetarget = self->goalentity = thing; - self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_STAND_GROUND | AI_TEMP_STAND_GROUND); - self->monsterinfo.aiflags |= (AI_SEEK_COVER | AI_CHASE_THING); - gi.linkentity(self); - actor_run(self); -} - -mframe_t actor_frames_attack [] = -{ - ai_charge, 0, actor_fire, - ai_charge, 0, actor_no_weapon_sound, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t actor_move_attack = {FRAME_attack1, FRAME_attack8, actor_frames_attack, actor_seekcover}; - -mframe_t actor_frames_crattack [] = -{ - ai_charge, 0, actor_fire, - ai_charge, 0, actor_no_weapon_sound, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t actor_move_crattack = {FRAME_crattak1, FRAME_crattak9, actor_frames_crattack, actor_run}; - -void actor_attack(edict_t *self) -{ - int n; - int weapon, w_select; - mmove_t *attackmove; - vec3_t v; - - w_select = self->actor_current_weapon; - weapon = self->actor_weapon[w_select]; - - if( self->enemy ) - { - if( w_select == 0 && self->actor_weapon[1] > 0 ) { - VectorSubtract(self->s.origin,self->enemy->s.origin,v); - if(VectorLength(v) < 200) { - self->monsterinfo.currentmove = &actor_move_switch; - return; - } - } - else if( w_select == 1 && self->actor_weapon[0] > 0 ) { - VectorSubtract(self->s.origin,self->enemy->s.origin,v); - if(VectorLength(v) > 300) { - self->monsterinfo.currentmove = &actor_move_switch; - return; - } - } - } - - self->actor_gunframe = 0; - - // temporary deal to toggle crouch -/* if(self->actor_crouch_time < level.time) - self->actor_crouch_time = level.time + 5; - else - self->actor_crouch_time = 0; */ - // end temp - - if(self->actor_crouch_time < level.time) - attackmove = &actor_move_attack; - else - attackmove = &actor_move_crattack; - - switch(weapon) { - case 1: - self->monsterinfo.currentmove = attackmove; - self->monsterinfo.pausetime = level.time + 2 * FRAMETIME; - break; - case 2: - self->monsterinfo.currentmove = attackmove; - self->monsterinfo.pausetime = level.time + 6 * FRAMETIME; - break; - case 3: - self->monsterinfo.currentmove = attackmove; - self->monsterinfo.pausetime = level.time + 10 * FRAMETIME; - break; - case 4: - self->monsterinfo.currentmove = attackmove; - n = (rand() & 15) + 3 + 7; - self->monsterinfo.pausetime = level.time + n * FRAMETIME; - break; - case 5: - self->monsterinfo.currentmove = attackmove; - n = (rand() & 20) + 20; - self->monsterinfo.pausetime = level.time + n * FRAMETIME; - break; - case 6: - case 7: - self->monsterinfo.currentmove = attackmove; - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { // if hes just standing there refire rate is normal - self->monsterinfo.pausetime = level.time + 7; - } - else - { // otherwise, allow the target to fire back - self->monsterinfo.pausetime = level.time + 2; - } - break; - case 8: - self->monsterinfo.currentmove = attackmove; - n = (rand() & 15) + 3 + 7; - self->monsterinfo.pausetime = level.time + n * FRAMETIME; - break; - case 9: - self->monsterinfo.currentmove = attackmove; - self->monsterinfo.pausetime = level.time + 3; - break; - case 10: - if(level.time > self->endtime) - { - self->monsterinfo.currentmove = attackmove; - self->monsterinfo.pausetime = level.time + 1.5; - } - else - self->monsterinfo.currentmove = &actor_move_stand; - break; - } -} - -void actor_use (edict_t *self, edict_t *other, edict_t *activator) -{ - vec3_t v; - - self->goalentity = self->movetarget = G_PickTarget(self->target); - if ((!self->movetarget) || (self->movetarget->class_id != ENTITY_TARGET_ACTOR)) - { - gi.dprintf ("%s has bad target %s at %s\n", self->classname, self->target, vtos(self->s.origin)); - self->target = NULL; - self->monsterinfo.pausetime = 100000000; - self->monsterinfo.stand (self); - return; - } - VectorSubtract (self->goalentity->s.origin, self->s.origin, v); - self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v); - self->monsterinfo.walk (self); - self->target = NULL; - if (self->pathtarget) - { - char *savetarget; - - savetarget = self->target; - self->target = self->pathtarget; - G_UseTargets (self, other); - self->target = savetarget; - } -} - -// Lazarus: checkattack - higher probabilities than normal monsters, -// also weapon-based - -static float chancefar[11] = { 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.2, 0.4, 0.2, 0.5, 0.8 }; -static float chancenear[11] = { 0.0, 0.4, 0.0, 0.0, 0.0, 0.0, 0.4, 0.4, 0.4, 0.4, 0.4 }; -bool actor_checkattack (edict_t *self) -{ - vec3_t v; - vec3_t forward, right, start, end; - float chance; - float range; - float goodchance, poorchance, lorange, hirange; - trace_t tr; - int weapon; - - // Paranoia check - if (!self->enemy) - return false; - - // If running to "thing", never attack - if(self->monsterinfo.aiflags & AI_CHASE_THING) - return false; - - weapon = self->actor_weapon[self->actor_current_weapon]; - // If actor has no weapon, well then of course he should not attack - if(weapon < 1 || weapon > 10) - return false; - - if (self->enemy->health > 0) - { - // see if any entities are in the way of the shot - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, self->muzzle, forward, right, start); - VectorCopy (self->enemy->s.origin, end); - - tr = gi.trace (start, NULL, NULL, end, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA|CONTENTS_WINDOW); - - // do we have a clear shot? - if (tr.ent != self->enemy) { - return false; - } - } - - VectorSubtract (self->s.origin, self->enemy->s.origin, v); - range = VectorLength (v); - - // melee attack - if (range <= MELEE_DISTANCE) - { - // don't always melee in easy mode - if (skill->value == 0 && (rand()&3) ) - return false; - self->monsterinfo.attack_state = AS_MISSILE; - return true; - } - -// missile attack - if (!self->monsterinfo.attack) - return false; - - if (level.time < self->monsterinfo.attack_finished) - return false; - - if (range > self->monsterinfo.max_range) - return false; - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - chance = 0.4; - } - else - { - if(weapon >= 2 && weapon <= 5) - { - // Scatter guns - probability of firing based on percentage of rounds - // that will hit target at a given range. - if(skill->value == 1) - goodchance = 0.6; - else if(skill->value > 1) - goodchance = 0.9; - else - goodchance = 0.3; - poorchance = 0.01; - switch(weapon) - { - case 2: lorange=270; hirange=500; break; - case 3: lorange= 90; hirange=200; break; - case 4: lorange=450; hirange=628; break; - case 5: lorange=450; hirange=628; break; - } - if(range <= lorange) - chance = goodchance; - else if(range > hirange) - chance = poorchance; - else - chance = goodchance + (range-lorange)/(hirange-lorange)*(poorchance-goodchance); - } - else - { - if (range <= 500) - chance = chancenear[weapon]; - else - chance = chancefar[weapon]; - if(self->monsterinfo.aiflags & AI_GOOD_GUY) - { - if(skill->value == 0) - chance *= 2; - else if(skill->value == 2) - chance *= 0.5; - else if(skill->value == 3) - chance *= 0.25; - } - else - { - if(skill->value == 0) - chance *= 0.5; - else if(skill->value == 2) - chance *= 2; - else if(skill->value == 3) - chance *= 4; - } - } - } - - if (random () < chance) - { - self->monsterinfo.attack_state = AS_MISSILE; - self->monsterinfo.attack_finished = level.time + 2*random(); - return true; - } - - return false; -} - -mmove_t actor_move_jump; -void actor_end_jump (edict_t *self) -{ - if(self->flags & FL_ROBOT) - { - if(self->monsterinfo.savemove) - { - actor_run(self); -// self->monsterinfo.currentmove = self->monsterinfo.savemove; -/* gi.dprintf("savemove=%d\n",self->monsterinfo.currentmove); - gi.dprintf("actor_move_jump=%d\n",&actor_move_jump); - gi.dprintf("actor_move_run=%d\n",&actor_move_run); - gi.dprintf("actor_move_walk=%d\n",&actor_move_walk); - gi.dprintf("actor_move_stand=%d\n",&actor_move_stand); */ - } - else if(self->enemy) - actor_run(self); - else if(self->movetarget) - actor_walk(self); - else - actor_stand(self); - } - else - actor_run(self); -} - -mframe_t actor_frames_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, actor_end_jump -}; - -mmove_t actor_move_jump = {FRAME_jump1, FRAME_jump6, actor_frames_jump, actor_jump}; - -void actor_jump (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, self->actor_sound_index[ACTOR_SOUND_JUMP], 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &actor_move_jump; -} -bool actor_blocked (edict_t *self, float dist) -{ - if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) )) - return true; - - if(blocked_checkjump (self, dist, self->monsterinfo.jumpdn, self->monsterinfo.jumpup)) - return true; - - if(blocked_checkplat (self, dist)) - return true; - - return false; -} - -mframe_t actor_frames_salute [] = -{ - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL, - ai_turn, 0, NULL -}; -mmove_t actor_move_salute = {FRAME_salute01, FRAME_salute11, actor_frames_salute, actor_run}; - -void actor_salute (edict_t *self) -{ - self->monsterinfo.currentmove = &actor_move_salute; -} -/*QUAKED misc_actor (1 .5 0) (-16 -16 -24) (16 16 32) -*/ - -#define ACTOR_ALIEN 1 -#define ACTOR_HUNTER 2 -#define ACTOR_PARANOID 3 -#define ACTOR_RATAMAHATTA 4 -#define ACTOR_RHINO 5 -#define ACTOR_SAS 6 -#define ACTOR_SLITH 7 -#define ACTOR_TERRAN 8 -#define ACTOR_WALKER 9 -#define ACTOR_WASTE 10 -#define ACTOR_XENOID 11 -#define ACTOR_ZUMLIN 12 - -#define NUM_ACTORPAK_ACTORS 12 -char ActorNames[NUM_ACTORPAK_ACTORS][32] = -{ "alien", "hunter", "paranoid","ratamahatta", - "rhino", "sas", "slith", "terran", - "walker", "waste", "xenoid", "zumlin" }; - -void SP_misc_actor (edict_t *self) -{ - char modelpath[256]; - char *p; - int i; - int ActorID = 0; - - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - - self->class_id = ENTITY_MISC_ACTOR; - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - if(self->usermodel) { - p = strstr(self->usermodel,"/tris.md2"); - if(p) *p = 0; - } - else { - self->usermodel = malloc(5); - strcpy(self->usermodel,"male"); - } - if( (!strcasecmp(self->usermodel,"male")) || - (!strcasecmp(self->usermodel,"female")) || - (!strcasecmp(self->usermodel,"cyborg")) ) - { - self->actor_id_model = true; - } - else - self->actor_id_model = false; - - sprintf(modelpath,"players/%s/tris.md2",self->usermodel); - self->s.modelindex = gi.modelindex(modelpath); - - for(i=0; iusermodel,ActorNames[i])) - ActorID = i+1; - } - - if(!VectorLength(self->bleft) && !VectorLength(self->tright)) - { - switch(ActorID) - { - case ACTOR_ALIEN: - VectorSet (self->mins, -28, -28, -24); - VectorSet (self->maxs, 28, 28, 32); - break; - case ACTOR_HUNTER: - VectorSet (self->mins, -24, -24, -24); - VectorSet (self->maxs, 24, 24, 32); - break; - case ACTOR_RATAMAHATTA: - case ACTOR_TERRAN: - VectorSet (self->mins, -20, -20, -24); - VectorSet (self->maxs, 20, 20, 32); - break; - case ACTOR_RHINO: - VectorSet (self->mins, -30, -30, -24); - VectorSet (self->maxs, 30, 30, 32); - break; - case ACTOR_SAS: - case ACTOR_XENOID: - case ACTOR_ZUMLIN: - VectorSet (self->mins, -18, -18, -24); - VectorSet (self->maxs, 18, 18, 32); - break; - case ACTOR_WALKER: - VectorSet (self->mins, -24, -24, -24); - VectorSet (self->maxs, 24, 24, 30); - break; - default: - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - } - } - else - { - VectorCopy (self->bleft, self->mins); - VectorCopy (self->tright, self->maxs); - } - - if (!self->health) - self->health = 100; - if (!self->gib_health) - self->gib_health = -40; - if (!self->mass) - self->mass = 200; - - if(self->sounds < 0) - { - self->actor_weapon[0] = 0; - self->actor_weapon[1] = -self->sounds; - } - else if(self->sounds < 10) - { - self->actor_weapon[0] = self->sounds; - self->actor_weapon[1] = 0; - } - else - { - self->actor_weapon[0] = self->sounds/100; - self->actor_weapon[1] = self->sounds % 100; - } - - if(!VectorLength(self->muzzle)) - { - switch(ActorID) - { - case ACTOR_ALIEN: - VectorSet(self->muzzle,42,5,15); - break; - case ACTOR_HUNTER: - switch(self->actor_weapon[0]) - { - case 1: VectorSet(self->muzzle,32,5,15);break; - case 2: VectorSet(self->muzzle,36,5,15);break; - case 3: VectorSet(self->muzzle,36,5,15);break; - case 4: VectorSet(self->muzzle,38,4,19);break; - case 5: VectorSet(self->muzzle,45,4.5,15);break; - case 6: VectorSet(self->muzzle,32,5,15);break; - case 7: VectorSet(self->muzzle,40,5,15);break; - case 8: VectorSet(self->muzzle,41,4,19);break; - case 9: VectorSet(self->muzzle,40,4,19);break; - case 10: VectorSet(self->muzzle,42,5,20);break; - } - break; - case ACTOR_PARANOID: - switch(self->actor_weapon[0]) - { - case 1: VectorSet(self->muzzle,18,7,10);break; - case 2: VectorSet(self->muzzle,22,7,10);break; - case 3: VectorSet(self->muzzle,22,7,10);break; - case 4: VectorSet(self->muzzle,18,7,12);break; - case 5: VectorSet(self->muzzle,26,7,16);break; - case 6: VectorSet(self->muzzle,24,7,10);break; - case 7: VectorSet(self->muzzle,26,7,10);break; - case 8: VectorSet(self->muzzle,18,7,14);break; - case 9: VectorSet(self->muzzle,28,7,10);break; - case 10: VectorSet(self->muzzle,28,7,10);break; - } - break; - case ACTOR_RATAMAHATTA: - VectorSet(self->muzzle,24,13,10); - break; - case ACTOR_RHINO: - VectorSet(self->muzzle,29,7,10); - break; - case ACTOR_SAS: - VectorSet(self->muzzle,17,6.5,17); - break; - case ACTOR_SLITH: - switch(self->actor_weapon[0]) - { - case 1: VectorSet(self->muzzle,32,7,10);break; - case 2: VectorSet(self->muzzle,32,7,10);break; - case 3: VectorSet(self->muzzle,32,7,10);break; - case 4: VectorSet(self->muzzle,25,5,-1);break; - case 5: VectorSet(self->muzzle,25,5,-1);break; - case 6: VectorSet(self->muzzle,32,7,10);break; - case 7: VectorSet(self->muzzle,32,7,10);break; - case 8: VectorSet(self->muzzle,12,6,-1);break; - case 9: VectorSet(self->muzzle,32,7,10);break; - case 10: VectorSet(self->muzzle,20,5,-1);break; - } - break; - case ACTOR_TERRAN: - VectorSet(self->muzzle,42,7,11.5); - break; - case ACTOR_WALKER: - VectorSet(self->muzzle,9,16,7); - break; - case ACTOR_WASTE: - switch(self->actor_weapon[0]) - { - case 1: VectorSet(self->muzzle,12, 9,9);break; - case 2: VectorSet(self->muzzle,22, 9,9);break; - case 3: VectorSet(self->muzzle,20, 9,9);break; - case 4: VectorSet(self->muzzle,11,11,7);break; - case 5: VectorSet(self->muzzle,26, 8,8);break; - case 6: VectorSet(self->muzzle,18, 9,7);break; - case 7: VectorSet(self->muzzle,26, 9,7);break; - case 8: VectorSet(self->muzzle,26, 7.5,8);break; - case 9: VectorSet(self->muzzle,26, 9,7);break; - case 10: VectorSet(self->muzzle,22,11,7);break; - } - break; - case ACTOR_XENOID: - VectorSet(self->muzzle,20,12,7); - break; - case ACTOR_ZUMLIN: - switch(self->actor_weapon[0]) - { - case 1: VectorSet(self->muzzle,22, 3,8);break; - case 2: VectorSet(self->muzzle,20, 2,9);break; - case 3: VectorSet(self->muzzle,20, 2,9);break; - case 4: VectorSet(self->muzzle, 8, 5,4);break; - case 5: VectorSet(self->muzzle,22, 2,4);break; - case 6: VectorSet(self->muzzle,20, 2,7);break; - case 7: VectorSet(self->muzzle,30, 2,9);break; - case 8: VectorSet(self->muzzle,20, 3,2);break; - case 9: VectorSet(self->muzzle,26, 2,9);break; - case 10: VectorSet(self->muzzle,16, 5,-2);break; - } - break; - default: - switch(self->actor_weapon[0]) - { - case 4: VectorSet(self->muzzle, 6 ,9 ,6 );break; - case 5: VectorSet(self->muzzle,20 ,9 ,8 );break; - case 8: VectorSet(self->muzzle,18 ,8 ,6 );break; - default:VectorSet(self->muzzle,18.4,7.4,9.6);break; - } - } - } - - if(!VectorLength(self->muzzle2)) - { - switch(ActorID) - { - case ACTOR_RHINO: - VectorSet(self->muzzle2,27,-15,13); - break; - case ACTOR_WALKER: - VectorSet(self->muzzle2,9,-11,7); - break; - } - } - if(VectorLength(self->muzzle2)) - self->monsterinfo.aiflags |= AI_TWO_GUNS; - - self->pain = actor_pain; - self->die = actor_die; - - self->monsterinfo.stand = actor_stand; - self->monsterinfo.walk = actor_walk; - self->monsterinfo.run = actor_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = actor_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = NULL; - self->monsterinfo.idle = NULL; - self->monsterinfo.checkattack = actor_checkattack; - if(actorjump->value) - { - self->monsterinfo.jump = actor_jump; - self->monsterinfo.jumpup = 48; - self->monsterinfo.jumpdn = 160; - } -// self->monsterinfo.blocked = actor_blocked; - - // There are several actions (mainly following a player leader) that - // are only applicable to misc_actor (not other monsters) - self->monsterinfo.aiflags |= AI_ACTOR; - if(!(self->spawnflags & SF_ACTOR_BAD_GUY) || (self->spawnflags & SF_MONSTER_GOODGUY)) - self->monsterinfo.aiflags |= AI_GOOD_GUY; - - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - - // Minimum distance - if(self->actor_weapon[1]) - self->monsterinfo.min_range = 0; - else - { - int weapon; - weapon = self->actor_weapon[0]; - if(weapon == 6 || weapon == 7 || weapon == 10) - self->monsterinfo.min_range = 200; - else - self->monsterinfo.min_range = 0; - } - // Ideal range - actor_ideal_range(self); - - gi.linkentity (self); - - self->monsterinfo.currentmove = &actor_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&actor_move_death1, - &actor_move_death2, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = 0.8; - walkmonster_start (self); - - // We've built the misc_actor model to include the standard - // Q2 male skins, specified with the style key. Default=grunt - self->s.skin = self->style; - - // actors always start in a dormant state, they *must* be used to get going - self->use = actor_use; - - // If health > 100000, actor is invulnerable - if(self->health >= 100000) - self->takedamage = DAMAGE_NO; - - self->common_name = "Actor"; - - // Muzzle flash - self->flash = G_Spawn(); - self->flash->classname = "muzzleflash"; - self->flash->model = "models/objects/flash/tris.md2"; - gi.setmodel(self->flash,self->flash->model); - self->flash->solid = SOLID_NOT; - self->flash->s.skin = 0; - self->flash->s.effects = EF_PLASMA; - self->flash->s.renderfx = RF_FULLBRIGHT; - self->flash->svflags |= SVF_NOCLIENT; - VectorCopy(self->s.origin,self->flash->s.origin); - gi.linkentity(self->flash); -} - - -/*QUAKED target_actor (.5 .3 0) (-8 -8 -8) (8 8 8) JUMP SHOOT ATTACK x HOLD BRUTAL -JUMP jump in set direction upon reaching this target -SHOOT take a single shot at the pathtarget -ATTACK attack pathtarget until it or actor is dead - -"target" next target_actor -"pathtarget" target of any action to be taken at this point -"wait" amount of time actor should pause at this point - -for JUMP only: -"speed" speed thrown forward (default 200) -"height" speed thrown upwards (default 200) -*/ - -void target_actor_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - vec3_t v; - - if (other->movetarget != self) - return; - - if (other->enemy) - return; - - other->goalentity = other->movetarget = NULL; - - if (self->spawnflags & 1) //jump - { - other->velocity[0] = self->movedir[0] * self->speed; - other->velocity[1] = self->movedir[1] * self->speed; - - if (other->groundentity) - { - other->groundentity = NULL; - other->velocity[2] = self->movedir[2]; - if(other->monsterinfo.aiflags & AI_ACTOR) - gi.sound (self, CHAN_VOICE, other->actor_sound_index[ACTOR_SOUND_JUMP], 1, ATTN_NORM, 0); - } - // NOTE: The jump animation won't work UNLESS this target_actor has a target. If this - // is the last target_actor in a sequence, the actor's run takes over and prevents - // the jump. -// if (!strcasecmp(other->classname,"misc_actor")) -// other->monsterinfo.currentmove = &actor_move_jump; - } - - if (self->spawnflags & 2) //shoot - { - if(self->pathtarget) { - if( G_Find(NULL,FOFS(targetname),self->pathtarget) != NULL ) { - other->enemy = G_PickTarget(self->pathtarget); - if (self->spawnflags & 8) - { - other->monsterinfo.aiflags |= AI_STAND_GROUND; - actor_stand (other); - } else - actor_attack(other); - } - else - other->enemy = NULL; - } else { - other->enemy = NULL; - } - } - else if (self->spawnflags & 4) //attack - { - if(self->pathtarget) { - if( G_Find(NULL,FOFS(targetname),self->pathtarget) != NULL ) - other->enemy = G_PickTarget(self->pathtarget); - else - other->enemy = NULL; - } else { - other->enemy = NULL; - } - if (other->enemy) - { - other->goalentity = other->enemy; - if (self->spawnflags & 32) - other->monsterinfo.aiflags |= AI_BRUTAL; - if (self->spawnflags & 16) - { - other->monsterinfo.aiflags |= AI_STAND_GROUND; - actor_stand (other); - } - else - { - actor_run (other); - } - } - } - - if (!(self->spawnflags & 6) && (self->pathtarget)) - { - char *savetarget; - - savetarget = self->target; - self->target = self->pathtarget; - G_UseTargets (self, other); - self->target = savetarget; - } - - // DWH: Allow blank target field - if(self->target) - other->movetarget = G_PickTarget(self->target); - else - other->movetarget = NULL; - - if(!other->goalentity) - other->goalentity = other->movetarget; - - if (self->wait) - { - other->monsterinfo.pausetime = level.time + self->wait; - other->monsterinfo.stand (other); - } - else - { - - if (!other->movetarget && !other->enemy) - { - other->monsterinfo.pausetime = level.time + 100000000; - other->monsterinfo.stand (other); - } - else if (other->movetarget == other->goalentity) - { - // DWH: Bug fix here... possible to get here with NULL movetarget and goalentity - if (other->movetarget) { - VectorSubtract (other->movetarget->s.origin, other->s.origin, v); - other->ideal_yaw = vectoyaw (v); - } - } - } - - self->count--; - if(!self->count) { - self->think = G_FreeEdict; - self->nextthink = level.time + 1; - } - -} - -void SP_target_actor (edict_t *self) -{ - if (deathmatch->value) { - G_FreeEdict(self); - return; - } - self->class_id = ENTITY_TARGET_ACTOR; - if (!self->targetname) - gi.dprintf ("%s with no targetname at %s\n", self->classname, vtos(self->s.origin)); - - self->solid = SOLID_TRIGGER; - self->touch = target_actor_touch; - VectorSet (self->mins, -8, -8, -8); - VectorSet (self->maxs, 8, 8, 8); - self->svflags = SVF_NOCLIENT; - - if (self->spawnflags & 1) - { - if (!self->speed) - self->speed = 200; - if (!st.height) - st.height = 200; - if (self->s.angles[YAW] == 0) - self->s.angles[YAW] = 360; - G_SetMovedir (self->s.angles, self->movedir); - self->movedir[2] = st.height; - } - gi.linkentity (self); -} - -typedef struct -{ - int index; -} actorlist; - -void actor_files () -{ - char path[256]; - char filename[256]; - int s_match, w_match[2]; - int i, j, k; - int num_actors = 0; - actorlist actors[MAX_EDICTS]; - cvar_t *basedir, *cddir, *gamedir; - edict_t *e, *e0; - - if(deathmatch->value) - return; - - basedir = gi.cvar("basedir", "", 0); - cddir = gi.cvar("cddir", "", 0); - gamedir = gi.cvar("gamedir", "", 0); - - memset(&actors,0,MAX_EDICTS*sizeof(actorlist)); - - for(i=game.maxclients+1; iinuse) continue; - if(!e->classname) continue; - if(!(e->monsterinfo.aiflags & AI_ACTOR)) continue; - - for(j=0; jactor_sound_index[j] = 0; - - s_match = 0; - w_match[0] = 0; - w_match[1] = 0; - if(num_actors > 0) { - for(j=0; jusermodel,e0->usermodel)) { - s_match = j+1; - if(e->actor_weapon[0] == e0->actor_weapon[0]) - w_match[0] = j*2+1; - else if(e->actor_weapon[0] == e0->actor_weapon[1]) - w_match[0] = j*2+2; - if(e->actor_weapon[1] == e0->actor_weapon[0]) - w_match[1] = j*2+1; - else if(e->actor_weapon[1] == e0->actor_weapon[1]) - w_match[1] = j*2+2; - } - } - if(s_match) { - // copy sound indices from previous actor - e0 = &g_edicts[actors[s_match-1].index]; - for(j=0; jactor_sound_index[j] = e0->actor_sound_index[j]; - } - if(w_match[0]) { - k = (w_match[0]-1) % 2; - e0 = &g_edicts[actors[ (w_match[0]-k-1)/2 ].index]; - e->s.weaponmodel = e->actor_model_index[0] = e0->actor_model_index[k]; - } - if(w_match[1]) { - k = (w_match[1]-1) % 2; - e0 = &g_edicts[actors[ (w_match[1]-k-1)/2 ].index]; - e->actor_model_index[1] = e0->actor_model_index[k]; - } - } - if(!s_match) { - // search for sounds on hard disk and in paks - actors[num_actors].index = i; - num_actors++; - - if(!strcasecmp(e->usermodel,"male") || !strcasecmp(e->usermodel,"female")) { - sprintf(path, "player/%s/",e->usermodel); - } else { - sprintf(path, "../players/%s/",e->usermodel); - } - - for(j=0; jactor_sound_index[j]) - continue; - - // If it's NOT a custom model, start by looking in game folder - if(strlen(gamedir->string)) - { - sprintf(filename,"sound/%s%s",path, wavname[j]); - if(gi.Fs.FileExists(filename)) - { - strcpy(filename, path); - strcat(filename, wavname[j]); - e->actor_sound_index[j] = gi.soundindex(filename); - continue; - } - } - - // If sound is STILL not found, use normal male sounds - sprintf(filename,"player/male/%s",wavname[j]); - e->actor_sound_index[j] = gi.soundindex(filename); - } - } - - // repeat this WHOLE DAMN THING for weapons - - for(k=0; k<2; k++) { - if(w_match[k]) continue; - if(!e->actor_weapon[k]) continue; - if((k==1) && (e->actor_weapon[0] == e->actor_weapon[1])) { - e->actor_model_index[1] = e->actor_model_index[0]; - continue; - } - if(s_match) - { - // Wasn't added to table on account of sounds - if(k==0 || w_match[0] > 0) { - // Either this is weapon 0, or weapon 0 was a match. Either - // way, this guy has something unique and hasn't been added - // to the table - actors[num_actors].index = i; - num_actors++; - } - } - - sprintf(filename,"players/%s/",e->usermodel); - switch(e->actor_weapon[k]) { - case 2: strcat(filename,"w_shotgun.md2"); break; - case 3: strcat(filename,"w_sshotgun.md2"); break; - case 4: strcat(filename,"w_machinegun.md2"); break; - case 5: strcat(filename,"w_chaingun.md2"); break; - case 6: strcat(filename,"w_glauncher.md2"); break; - case 7: strcat(filename,"w_rlauncher.md2"); break; - case 8: strcat(filename,"w_hyperblaster.md2"); break; - case 9: strcat(filename,"w_railgun.md2"); break; - case 10:strcat(filename,"w_bfg.md2"); break; - default:strcat(filename,"w_blaster.md2"); break; - } - - if(strlen(gamedir->string)) - { - // Start in game folder - if(gi.Fs.FileExists(filename)) - { - e->actor_model_index[k] = gi.modelindex(filename); - continue; - } - } - // If sound is STILL not found, start the fuck over and look for weapon.md2 - sprintf(filename,"players/%s/weapon.md2",e->usermodel); - - if(strlen(gamedir->string)) - { - // Start in game folder - if(gi.Fs.FileExists(filename)) - { - e->actor_model_index[k] = gi.modelindex(filename); - continue; - } - } - - // And if it's STILL not found, use - sprintf(filename,"players/male/weapon.md2"); - e->actor_model_index[k] = gi.modelindex(filename); - } - if(e->health > 0) e->s.weaponmodel = e->actor_model_index[e->actor_current_weapon]; - else e->s.weaponmodel = 0; - gi.linkentity(e); - } -} - -void actor_moveit (edict_t *player, edict_t *actor) -{ - edict_t *thing; - trace_t tr; - vec3_t dir, end; - vec_t d[3]; - vec_t temp; - vec_t travel; - int best=0; - - if(!(actor->monsterinfo.aiflags & AI_FOLLOW_LEADER)) - return; - if(actor->enemy) - return; - if(actor->health <= 0) - return; - travel = 256 + 128*crandom(); - thing = actor->vehicle; - if(!thing || !thing->inuse || (thing->class_id != ENTITY_THING)) - thing = actor->vehicle = SpawnThing(); - VectorSubtract(actor->s.origin,player->s.origin,dir); - dir[2] = 0; - VectorNormalize(dir); - if(!VectorLength(dir)) - VectorSet(dir,1.0,0.,0.); - VectorMA(actor->s.origin,travel,dir,end); - tr = gi.trace(actor->s.origin,NULL,NULL,end,actor,MASK_MONSTERSOLID); - d[best] = tr.fraction * travel; - if(d[best] < 64) - { - temp = dir[0]; - dir[0] = -dir[1]; - dir[1] = temp; - VectorMA(actor->s.origin,travel,dir,end); - tr = gi.trace(actor->s.origin,NULL,NULL,end,actor,MASK_MONSTERSOLID); - best = 1; - d[best] = tr.fraction * travel; - if(d[best] < 64) - { - dir[0] = -dir[0]; - dir[1] = -dir[1]; - VectorMA(actor->s.origin,travel,dir,end); - tr = gi.trace(actor->s.origin,NULL,NULL,end,actor,MASK_MONSTERSOLID); - best = 2; - d[best] = tr.fraction * travel; - if(d[best] < 64) - { - if(d[0] > d[1] && d[0] > d[2]) - best = 0; - else if(d[1] > d[0] && d[1] > d[2]) - best = 1; - if(best==1) - { - dir[0] = -dir[0]; - dir[1] = -dir[1]; - } - else if(best==0) - { - temp = -dir[1]; - dir[1] = dir[0]; - dir[0] = temp; - } - } - } - } - VectorCopy(tr.endpos, thing->s.origin); - thing->touch_debounce_time = level.time + max(5.0,d[best]/50.); - thing->target_ent = actor; - ED_CallSpawn(thing); - actor->monsterinfo.aiflags |= AI_CHASE_THING; - actor->movetarget = actor->goalentity = thing; - actor->monsterinfo.old_leader = player; - actor->monsterinfo.leader = thing; - VectorSubtract (thing->s.origin, actor->s.origin, dir); - actor->ideal_yaw = vectoyaw(dir); - actor->monsterinfo.run(actor); -} diff --git a/server/monsters/m_actor.h b/server/monsters/m_actor.h deleted file mode 100644 index 5862c3cc..00000000 --- a/server/monsters/m_actor.h +++ /dev/null @@ -1,234 +0,0 @@ -//ed - weapon protos -void actorBlaster (edict_t *self); -void actorShotgun (edict_t *self); -void actorSuperShotgun (edict_t *self); -void actorMachineGun (edict_t *self); -void actorChaingun (edict_t *self); -void actorGrenadeLauncher (edict_t *self); -void actorRocket (edict_t *self); -void actorHyperblaster (edict_t *self); -void actorRailGun (edict_t *self); -void actorBFG (edict_t *self); - -// Generated by ModelEd - -#define FRAME_stand01 0 -#define FRAME_stand02 1 -#define FRAME_stand03 2 -#define FRAME_stand04 3 -#define FRAME_stand05 4 -#define FRAME_stand06 5 -#define FRAME_stand07 6 -#define FRAME_stand08 7 -#define FRAME_stand09 8 -#define FRAME_stand10 9 -#define FRAME_stand11 10 -#define FRAME_stand12 11 -#define FRAME_stand13 12 -#define FRAME_stand14 13 -#define FRAME_stand15 14 -#define FRAME_stand16 15 -#define FRAME_stand17 16 -#define FRAME_stand18 17 -#define FRAME_stand19 18 -#define FRAME_stand20 19 -#define FRAME_stand21 20 -#define FRAME_stand22 21 -#define FRAME_stand23 22 -#define FRAME_stand24 23 -#define FRAME_stand25 24 -#define FRAME_stand26 25 -#define FRAME_stand27 26 -#define FRAME_stand28 27 -#define FRAME_stand29 28 -#define FRAME_stand30 29 -#define FRAME_stand31 30 -#define FRAME_stand32 31 -#define FRAME_stand33 32 -#define FRAME_stand34 33 -#define FRAME_stand35 34 -#define FRAME_stand36 35 -#define FRAME_stand37 36 -#define FRAME_stand38 37 -#define FRAME_stand39 38 -#define FRAME_stand40 39 - -#define FRAME_run1 40 -#define FRAME_run2 41 -#define FRAME_run3 42 -#define FRAME_run4 43 -#define FRAME_run5 44 -#define FRAME_run6 45 - -#define FRAME_attack1 46 -#define FRAME_attack2 47 -#define FRAME_attack3 48 -#define FRAME_attack4 49 -#define FRAME_attack5 50 -#define FRAME_attack6 51 -#define FRAME_attack7 52 -#define FRAME_attack8 53 - -#define FRAME_pain101 54 -#define FRAME_pain102 55 -#define FRAME_pain103 56 -#define FRAME_pain104 57 - -#define FRAME_pain201 58 -#define FRAME_pain202 59 -#define FRAME_pain203 60 -#define FRAME_pain204 61 - -#define FRAME_pain301 62 -#define FRAME_pain302 63 -#define FRAME_pain303 64 -#define FRAME_pain304 65 - -#define FRAME_jump1 66 -#define FRAME_jump2 67 -#define FRAME_jump3 68 -#define FRAME_jump4 69 -#define FRAME_jump5 70 -#define FRAME_jump6 71 - -#define FRAME_flip01 72 -#define FRAME_flip02 73 -#define FRAME_flip03 74 -#define FRAME_flip04 75 -#define FRAME_flip05 76 -#define FRAME_flip06 77 -#define FRAME_flip07 78 -#define FRAME_flip08 79 -#define FRAME_flip09 80 -#define FRAME_flip10 81 -#define FRAME_flip11 82 -#define FRAME_flip12 83 - -#define FRAME_salute01 84 -#define FRAME_salute02 85 -#define FRAME_salute03 86 -#define FRAME_salute04 87 -#define FRAME_salute05 88 -#define FRAME_salute06 89 -#define FRAME_salute07 90 -#define FRAME_salute08 91 -#define FRAME_salute09 92 -#define FRAME_salute10 93 -#define FRAME_salute11 94 - -#define FRAME_taunt01 95 -#define FRAME_taunt02 96 -#define FRAME_taunt03 97 -#define FRAME_taunt04 98 -#define FRAME_taunt05 99 -#define FRAME_taunt06 100 -#define FRAME_taunt07 101 -#define FRAME_taunt08 102 -#define FRAME_taunt09 103 -#define FRAME_taunt10 104 -#define FRAME_taunt11 105 -#define FRAME_taunt12 106 -#define FRAME_taunt13 107 -#define FRAME_taunt14 108 -#define FRAME_taunt15 109 -#define FRAME_taunt16 110 -#define FRAME_taunt17 111 - -#define FRAME_wave01 112 -#define FRAME_wave02 113 -#define FRAME_wave03 114 -#define FRAME_wave04 115 -#define FRAME_wave05 116 -#define FRAME_wave06 117 -#define FRAME_wave07 118 -#define FRAME_wave08 119 -#define FRAME_wave09 120 -#define FRAME_wave10 121 -#define FRAME_wave11 122 - -#define FRAME_point01 123 -#define FRAME_point02 124 -#define FRAME_point03 125 -#define FRAME_point04 126 -#define FRAME_point05 127 -#define FRAME_point06 128 -#define FRAME_point07 129 -#define FRAME_point08 130 -#define FRAME_point09 131 -#define FRAME_point10 132 -#define FRAME_point11 133 -#define FRAME_point12 134 - -#define FRAME_crstnd01 135 -#define FRAME_crstnd02 136 -#define FRAME_crstnd03 137 -#define FRAME_crstnd04 138 -#define FRAME_crstnd05 139 -#define FRAME_crstnd06 140 -#define FRAME_crstnd07 141 -#define FRAME_crstnd08 142 -#define FRAME_crstnd09 143 -#define FRAME_crstnd10 144 -#define FRAME_crstnd11 145 -#define FRAME_crstnd12 146 -#define FRAME_crstnd13 147 -#define FRAME_crstnd14 148 -#define FRAME_crstnd15 149 -#define FRAME_crstnd16 150 -#define FRAME_crstnd17 151 -#define FRAME_crstnd18 152 -#define FRAME_crstnd19 153 - -#define FRAME_crwalk1 154 -#define FRAME_crwalk2 155 -#define FRAME_crwalk3 156 -#define FRAME_crwalk4 157 -#define FRAME_crwalk5 158 -#define FRAME_crwalk6 159 - -#define FRAME_crattak1 160 -#define FRAME_crattak2 161 -#define FRAME_crattak3 162 -#define FRAME_crattak4 163 -#define FRAME_crattak5 164 -#define FRAME_crattak6 165 -#define FRAME_crattak7 166 -#define FRAME_crattak8 167 -#define FRAME_crattak9 168 - -#define FRAME_crpain1 169 -#define FRAME_crpain2 170 -#define FRAME_crpain3 171 -#define FRAME_crpain4 172 - -#define FRAME_crdeath1 173 -#define FRAME_crdeath2 174 -#define FRAME_crdeath3 175 -#define FRAME_crdeath4 176 -#define FRAME_crdeath5 177 - -#define FRAME_death101 178 -#define FRAME_death102 179 -#define FRAME_death103 180 -#define FRAME_death104 181 -#define FRAME_death105 182 -#define FRAME_death106 183 - -#define FRAME_death201 184 -#define FRAME_death202 185 -#define FRAME_death203 186 -#define FRAME_death204 187 -#define FRAME_death205 188 -#define FRAME_death206 189 - -#define FRAME_death301 190 -#define FRAME_death302 191 -#define FRAME_death303 192 -#define FRAME_death304 193 -#define FRAME_death305 194 -#define FRAME_death306 195 -#define FRAME_death307 196 -#define FRAME_death308 197 - -#define MODEL_SCALE 1.000000 - diff --git a/server/monsters/m_actor_weap.c b/server/monsters/m_actor_weap.c deleted file mode 100644 index 758d2c04..00000000 --- a/server/monsters/m_actor_weap.c +++ /dev/null @@ -1,734 +0,0 @@ -#include "g_local.h" -#include "m_actor.h" - -void muzzleflash_think(edict_t *flash) -{ - if(level.time >= flash->wait) - { - flash->svflags |= SVF_NOCLIENT; - flash->s.effects &= ~EF_HYPERBLASTER; - } - else - { - flash->svflags &= ~SVF_NOCLIENT; - if(flash->s.frame ^= 1) - flash->s.effects |= EF_HYPERBLASTER; - else - flash->s.effects &= ~EF_HYPERBLASTER; - flash->nextthink = level.time + FRAMETIME; - } - gi.linkentity(flash); -} - -void TraceAimPoint(vec3_t start,vec3_t target) -{ - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_DEBUGTRAIL); - WRITE_COORD (start); - WRITE_COORD (target); - MESSAGE_SEND (MSG_ALL, start, NULL); -} -void ActorTarget(edict_t *self, vec3_t target) -{ - float accuracy; - float dist; - float tf; - vec3_t v; - - if(!self->enemy) { - VectorClear(target); - return; - } - if(self->monsterinfo.aiflags & AI_GOOD_GUY) - accuracy = 5.0 - skill->value; - else - accuracy = skill->value + 2.0; - - if (self->enemy->health > 0) - { - int weapon; - trace_t tr; - vec3_t start; - bool can_see=false; - - VectorCopy(self->s.origin,start); - start[2] += self->viewheight; - VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); - weapon = self->actor_weapon[self->actor_current_weapon]; - - if(weapon == 7 && (rand() & 1)) - { - // Fire rockets at feet half the time - target[2] += self->enemy->mins[2] + 1; - tr = gi.trace(start,NULL,NULL,target,self,MASK_SHOT); - if(tr.ent == self->enemy) - can_see=true; - else - target[2] -= self->enemy->mins[2] + 1; - } - if(!can_see) - { - // Fire at origin if origin can be seen - tr = gi.trace(start,NULL,NULL,target,self,MASK_SHOT); - if(tr.ent == self->enemy) - can_see = true; - } - // Otherwise fire at eyeballs - if(!can_see) - target[2] += self->enemy->viewheight; - } - else - { - // For dead targets, fire at center of bounding box (point entities) - // or origin (brush models) - if(self->enemy->solid == SOLID_BBOX) - VectorMA(self->enemy->absmin,0.5,self->enemy->size,target); - else - VectorAdd(self->enemy->s.origin,self->enemy->origin_offset,target); - } - - if(accuracy == 5.0) - return; - - VectorSubtract(target,self->s.origin,v); - dist = VectorLength(v); - - tf = (dist < 256) ? dist/2 : 256; - tf *= (float) (5.0 - accuracy) / 25.0; - VectorAdd(target, tv(crandom() * tf, crandom() * tf, crandom() * tf * 0.2), target); -} - -//Blaster -void actorBlaster (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - int damage; - - if(!self->enemy || !self->enemy->inuse) - return; - - AngleVectors (self->s.angles, forward, right, up); - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - damage = 5; - else - damage = 10; - - monster_fire_blaster (self, start, forward, damage, 600, MZ2_SOLDIER_BLASTER_2, EF_BLASTER); - - if(developer->value) - TraceAimPoint(start,target); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - G_ProjectSource2(self->s.origin,self->muzzle2,forward,right,up,start); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - monster_fire_blaster (self, start, forward, damage, 600, MZ2_SOLDIER_BLASTER_2, EF_BLASTER); - } - -} - -//Shotgun -void actorShotgun (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - - if(!self->enemy || !self->enemy->inuse) - return; - - AngleVectors (self->s.angles, forward, right, up); - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - if(self->framenumbers % 2) - G_ProjectSource2(self->s.origin, self->muzzle2, forward, right, up, start); - else - G_ProjectSource2(self->s.origin, self->muzzle, forward, right, up, start); - self->framenumbers++; - } - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - fire_shotgun (self, start, forward, 4, 8, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); - - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_CHAINFIST_SMOKE); - WRITE_COORD(start); - MESSAGE_SEND(MSG_PVS, start, NULL); - - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/shotgf1b.wav"),1,ATTN_NORM,0); - - if(self->flash) - { - VectorCopy(start,self->flash->s.origin); - self->flash->s.frame = 0; - self->flash->think = muzzleflash_think; - self->flash->wait = level.time + FRAMETIME; - self->flash->think(self->flash); - } - - if(developer->value) - { - if (!(self->monsterinfo.aiflags & AI_TWO_GUNS) || (self->framenumbers % 2)) - TraceAimPoint(start,target); - } -} - -//Super Shotgun -void actorSuperShotgun (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - vec3_t angles; - - if(!self->enemy || !self->enemy->inuse) - return; - - AngleVectors (self->s.angles, forward, right, up); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - if(self->framenumbers % 2) - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - self->framenumbers++; - } - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - vectoangles(forward,angles); - angles[YAW] -= 5; - AngleVectors(angles,forward,NULL,NULL); - fire_shotgun (self, start, forward, 6, 12, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); - angles[YAW] += 10; - AngleVectors(angles,forward,NULL,NULL); - fire_shotgun (self, start, forward, 6, 12, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); - - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_CHAINFIST_SMOKE); - WRITE_COORD(start); - MESSAGE_SEND(MSG_PVS, start, NULL); - - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/sshotf1b.wav"),1,ATTN_NORM,0); - - if(self->flash) - { - VectorCopy(start,self->flash->s.origin); - self->flash->s.frame = 0; - self->flash->think = muzzleflash_think; - self->flash->wait = level.time + FRAMETIME; - self->flash->think(self->flash); - } - - if(developer->value) - { - if (!(self->monsterinfo.aiflags & AI_TWO_GUNS) || (self->framenumbers % 2)) - TraceAimPoint(start,target); - } -} - -// Machinegun -void actorMachineGun (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - int damage; - - if(!self->enemy || !self->enemy->inuse) { - self->monsterinfo.pausetime = 0; - return; - } - - AngleVectors (self->s.angles, forward, right, up); - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - damage = 2; - else - damage = 4; - - fire_bullet (self, start, forward, damage, 2, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); - - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_CHAINFIST_SMOKE); - WRITE_COORD(start); - MESSAGE_SEND(MSG_PVS, start, NULL); - - gi.positioned_sound(start,self,CHAN_WEAPON, gi.soundindex(va("weapons/machgf%db.wav",self->actor_gunframe % 5 + 1)),1,ATTN_NORM,0); - - if(self->flash) - { - VectorCopy(start,self->flash->s.origin); - self->flash->think = muzzleflash_think; - self->flash->wait = level.time + FRAMETIME; - self->flash->think(self->flash); - } - - if(developer->value) - TraceAimPoint(start,target); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - fire_bullet (self, start, forward, damage, 2, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); - - MESSAGE_BEGIN(svc_temp_entity); - WRITE_BYTE(TE_CHAINFIST_SMOKE); - WRITE_COORD(start); - MESSAGE_SEND(MSG_PVS, start, NULL); - } -} - -// Chaingun -void actorChaingun (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - int i; - int shots; - int damage; - - if(!self->enemy || !self->enemy->inuse) - self->monsterinfo.pausetime = 0; - - if(level.time >= self->monsterinfo.pausetime) { - self->s.sound = 0; - gi.sound(self,CHAN_AUTO,gi.soundindex("weapons/chngnd1a.wav"),1,ATTN_IDLE,0); - return; - } - - if(self->actor_gunframe == 0) - gi.sound(self, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); - - if(self->actor_gunframe == 21 && level.time < self->monsterinfo.pausetime) - self->actor_gunframe = 15; - else - self->actor_gunframe++; - - self->s.sound = gi.soundindex("weapons/chngnl1a.wav"); - - if(self->actor_gunframe <= 9) - shots = 1; - else if(self->actor_gunframe <= 14) - shots = 2; - else - shots = 3; - - AngleVectors (self->s.angles, forward, right, up); - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - damage = 2; - else - damage = 4; - - for(i=0; iactor_gunframe % 5 + 1)),1,ATTN_NORM,0); - - if(self->flash) - { - VectorCopy(start,self->flash->s.origin); - self->flash->think = muzzleflash_think; - self->flash->wait = level.time + FRAMETIME; - self->flash->think(self->flash); - } - - if(developer->value) - TraceAimPoint(start,target); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - for(i=0; ienemy || !self->enemy->inuse) - return; - - AngleVectors (self->s.angles, forward, right, up); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - if(self->framenumbers % 2) - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - self->framenumbers++; - } - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - - ActorTarget(self,target); - if(self->enemy->absmin[2] <= self->absmax[2]) - target[2] += self->enemy->mins[2] - self->enemy->viewheight; - VectorSubtract(target, start, aim); - - // lead target... 20, 35, 50, 65 chance of leading - if( random() < (0.2 + skill->value * 0.15) ) - { - float dist; - float time; - - dist = VectorLength (aim); - time = dist/GRENADE_VELOCITY; // Not correct, but better than nothin' - VectorMA(target, time, self->enemy->velocity, target); - VectorSubtract(target, start, aim); - } - - VectorCopy(aim,forward); - VectorNormalize (aim); - if(aim[2] < 1.0) { - float cosa, t, x, vx, y; - float drop; - float last_error, last_up, v_error; - int i; - VectorCopy(forward,target); // save target point - // horizontal distance to target - x = sqrt( forward[0]*forward[0] + forward[1]*forward[1]); - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - // constant horizontal velocity (since grenades don't have drag) - vx = GRENADE_VELOCITY * cosa; - // time to reach target x - t = x/vx; - // in that time, grenade will drop this much: - drop = 0.5*sv_gravity->value*t*(t+FRAMETIME); - forward[2] = target[2] + drop; - // this is a good first cut, but incorrect since angle now changes, so - // horizontal speed changes - VectorCopy(forward,aim); - VectorNormalize(aim); - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = GRENADE_VELOCITY * cosa; - t = x/vx; - y = GRENADE_VELOCITY*aim[2]*t - 0.5*sv_gravity->value*t*(t+FRAMETIME); - v_error = target[2]-y; - last_error = 2*v_error; - for(i=0; i<10 && fabs(v_error) > 4 && fabs(v_error) < fabs(last_error); i++) { - drop = 0.5*sv_gravity->value*t*(t+FRAMETIME); - forward[2] = target[2] + drop; - VectorCopy(forward,aim); - VectorNormalize(aim); - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = GRENADE_VELOCITY * cosa; - t = x/vx; - y = GRENADE_VELOCITY*aim[2]*t - 0.5*sv_gravity->value*t*(t+FRAMETIME); - v_error = target[2]-y; - // If error is increasing... we can't get there from here and - // probably shouldn't be here in the first place. Too late now... - // use last aim vector and shoot. - if(fabs(v_error) < fabs(last_error)) - last_up = forward[2]; - } - if(fabs(v_error) > fabs(last_error)) { - forward[2] = last_up; - VectorCopy(forward,aim); - VectorNormalize(aim); - } - // Sanity check... if gunner is at the same elevation or a bit above the - // target entity, check to make sure he won't bounce grenades off the - // top of a doorway. If he WOULD do that, then figure out the max elevation - // angle that will get the grenade through the door, and hope we get a - // good bounce. - if( (self->s.origin[2] - self->enemy->s.origin[2] < 160) && - (self->s.origin[2] - self->enemy->s.origin[2] > -16) ) { - trace_t tr; - - VectorAdd(start,forward,target); - tr = gi.trace(start,vec3_origin,vec3_origin,target,self,MASK_SOLID); - if(tr.fraction < 1.0) { - // OK... the aim vector hit a solid, but would the grenade actually hit? - int contents; - - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = GRENADE_VELOCITY * cosa; - VectorSubtract(tr.endpos,start,dist); - dist[2] = 0; - x = VectorLength(dist); - t = x/vx; - drop = 0.5*sv_gravity->value*t*(t+FRAMETIME); - tr.endpos[2] -= drop; - // move just a bit in the aim direction - tr.endpos[0] += aim[0]; - tr.endpos[1] += aim[1]; - contents = gi.pointcontents(tr.endpos); - while((contents & MASK_SOLID) && (target[2] > self->enemy->s.origin[2])) { - target[2] -= 8.0; - VectorSubtract(target,start,forward); - VectorCopy(forward,aim); - VectorNormalize(aim); - tr = gi.trace(start,vec3_origin,vec3_origin,target,self,MASK_SOLID); - if(tr.fraction < 1.0) { - cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]); - vx = GRENADE_VELOCITY * cosa; - VectorSubtract(tr.endpos,start,dist); - dist[2] = 0; - x = VectorLength(dist); - t = x/vx; - drop = 0.5*sv_gravity->value*t*(t+FRAMETIME); - tr.endpos[2] -= drop; - tr.endpos[0] += aim[0]; - tr.endpos[1] += aim[1]; - contents = gi.pointcontents(tr.endpos); - } - // drop aim point another bit for insurance - target[2] -= 8; - VectorSubtract(target,start,forward); - VectorCopy(forward,aim); - VectorNormalize(aim); - } - } - } - } - // DWH - take into account (sort of) Lazarus feature of adding shooter's velocity to - // grenade velocity - monster_speed = VectorLength(self->velocity); - if(monster_speed > 0) { - vec3_t v1; - vec_t delta; - - VectorCopy(self->velocity,v1); - VectorNormalize(v1); - delta = -monster_speed/GRENADE_VELOCITY; - VectorMA(aim,delta,v1,aim); - VectorNormalize(aim); - } - fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, 2.5, 90); - - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/grenlf1a.wav"),1,ATTN_NORM,0); - - if(developer->value) - { - if (!(self->monsterinfo.aiflags & AI_TWO_GUNS) || (self->framenumbers % 2)) - TraceAimPoint(start,target); - } -} - - -// Rocket Launcher -void actorRocket (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - int damage = 80; - - if(!self->enemy || !self->enemy->inuse) - return; - - AngleVectors (self->s.angles, forward, right, up); - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - if(self->framenumbers % 2) - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - self->framenumbers++; - } - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - fire_rocket (self, start, forward, damage, 550, damage+20, damage, - ( (self->spawnflags & SF_MONSTER_SPECIAL) ? self->enemy : NULL) ); - - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/rocklf1a.wav"),1,ATTN_NORM,0); - - if(developer->value) - { - if (!(self->monsterinfo.aiflags & AI_TWO_GUNS) || (self->framenumbers % 2)) - TraceAimPoint(start,target); - } -} - -void actorHyperblaster (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - int damage; - int effect; - - if(!self->enemy || !self->enemy->inuse) { - self->monsterinfo.pausetime = 0; - self->s.sound = 0; - return; - } - - self->s.sound = gi.soundindex("weapons/hyprbl1a.wav"); - - if (level.time >= self->monsterinfo.pausetime) - { - self->actor_gunframe++; - } - else - { - AngleVectors (self->s.angles, forward, right, up); - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - if ((random() * 3) < 1) - effect = EF_HYPERBLASTER; - else - effect = 0; - - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/hyprbf1a.wav"),1,ATTN_NORM,0); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - damage = 8; - else - damage = 15; - - fire_blaster (self, start, forward, damage, 1000, effect, true); - - if(developer->value) - TraceAimPoint(start,target); - - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - if ((random() * 3) < 1) - effect = EF_HYPERBLASTER; - else - effect = 0; - fire_blaster (self, start, forward, damage, 1000, effect, true); - } - - self->actor_gunframe++; - if (self->actor_gunframe == 12) - self->actor_gunframe = 6; - } - - if (self->actor_gunframe == 12) - { - gi.sound(self, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); - self->s.sound = 0; - } - -} - -// Railgun -void actorRailGun (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - - if(!self->enemy || !self->enemy->inuse) - return; - - AngleVectors (self->s.angles, forward, right, up); - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - if(self->framenumbers % 2) - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - self->framenumbers++; - } - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - fire_rail (self, start, forward, 80, 100); // Do slightly less damage - - gi.positioned_sound(start,self,CHAN_WEAPON,gi.soundindex("weapons/railgf1a.wav"),1,ATTN_NORM,0); - - if(developer->value) - { - if (!(self->monsterinfo.aiflags & AI_TWO_GUNS) || (self->framenumbers % 2)) - TraceAimPoint(start,target); - } -} - -void actorBFG (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right, up; - - if(!self->enemy || !self->enemy->inuse) { - self->monsterinfo.pausetime = 0; - return; - } - - if(self->actor_gunframe == 0) - gi.positioned_sound(self->s.origin,self,CHAN_WEAPON,gi.soundindex("weapons/bfg__f1y.wav"),1,ATTN_NORM,0); - - if(self->actor_gunframe == 10) - { - AngleVectors (self->s.angles, forward, right, up); - if(self->monsterinfo.aiflags & AI_TWO_GUNS) - { - if(self->framenumbers % 2) - G_ProjectSource2 (self->s.origin, self->muzzle2, forward, right, up, start); - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - self->framenumbers++; - } - else - G_ProjectSource2 (self->s.origin, self->muzzle, forward, right, up, start); - - ActorTarget(self,target); - VectorSubtract (target, start, forward); - VectorNormalize (forward); - fire_bfg (self, start, forward, 500, 300, 1000); - self->endtime = level.time + 1; - if(developer->value) - { - if (!(self->monsterinfo.aiflags & AI_TWO_GUNS) || (self->framenumbers % 2)) - TraceAimPoint(start,target); - } - } - self->actor_gunframe++; -} diff --git a/server/monsters/m_berserk.c b/server/monsters/m_berserk.c deleted file mode 100644 index 821c3c14..00000000 --- a/server/monsters/m_berserk.c +++ /dev/null @@ -1,502 +0,0 @@ -/* -============================================================================== - -BERSERK - -============================================================================== -*/ - -#include "g_local.h" -#include "m_berserk.h" - - -static int sound_pain; -static int sound_die; -static int sound_idle; -static int sound_punch; -static int sound_sight; -static int sound_search; - -void berserk_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void berserk_search (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); -} - - -void berserk_fidget (edict_t *self); -mframe_t berserk_frames_stand [] = -{ - ai_stand, 0, berserk_fidget, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t berserk_move_stand = {FRAME_stand1, FRAME_stand5, berserk_frames_stand, NULL}; - -void berserk_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &berserk_move_stand; -} - -mframe_t berserk_frames_stand_fidget [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t berserk_move_stand_fidget = {FRAME_standb1, FRAME_standb20, berserk_frames_stand_fidget, berserk_stand}; - -void berserk_fidget (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - return; - if (random() > 0.15) - return; - - self->monsterinfo.currentmove = &berserk_move_stand_fidget; - - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_WEAPON, sound_idle, 1, ATTN_IDLE, 0); -} - - -mframe_t berserk_frames_walk [] = -{ - ai_walk, 9.1, NULL, - ai_walk, 6.3, NULL, - ai_walk, 4.9, NULL, - ai_walk, 6.7, NULL, - ai_walk, 6.0, NULL, - ai_walk, 8.2, NULL, - ai_walk, 7.2, NULL, - ai_walk, 6.1, NULL, - ai_walk, 4.9, NULL, - ai_walk, 4.7, NULL, - ai_walk, 4.7, NULL, - ai_walk, 4.8, NULL -}; -mmove_t berserk_move_walk = {FRAME_walkc1, FRAME_walkc11, berserk_frames_walk, NULL}; - -void berserk_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &berserk_move_walk; -} - -/* - - ***************************** - SKIPPED THIS FOR NOW! - ***************************** - - Running -> Arm raised in air - -void() berserk_runb1 =[ $r_att1 , berserk_runb2 ] {ai_run(21);}; -void() berserk_runb2 =[ $r_att2 , berserk_runb3 ] {ai_run(11);}; -void() berserk_runb3 =[ $r_att3 , berserk_runb4 ] {ai_run(21);}; -void() berserk_runb4 =[ $r_att4 , berserk_runb5 ] {ai_run(25);}; -void() berserk_runb5 =[ $r_att5 , berserk_runb6 ] {ai_run(18);}; -void() berserk_runb6 =[ $r_att6 , berserk_runb7 ] {ai_run(19);}; -// running with arm in air : start loop -void() berserk_runb7 =[ $r_att7 , berserk_runb8 ] {ai_run(21);}; -void() berserk_runb8 =[ $r_att8 , berserk_runb9 ] {ai_run(11);}; -void() berserk_runb9 =[ $r_att9 , berserk_runb10 ] {ai_run(21);}; -void() berserk_runb10 =[ $r_att10 , berserk_runb11 ] {ai_run(25);}; -void() berserk_runb11 =[ $r_att11 , berserk_runb12 ] {ai_run(18);}; -void() berserk_runb12 =[ $r_att12 , berserk_runb7 ] {ai_run(19);}; -// running with arm in air : end loop -*/ - - -mframe_t berserk_frames_run1 [] = -{ - ai_run, 21, NULL, - ai_run, 11, NULL, - ai_run, 21, NULL, - ai_run, 25, NULL, - ai_run, 18, NULL, - ai_run, 19, NULL -}; -mmove_t berserk_move_run1 = {FRAME_run1, FRAME_run6, berserk_frames_run1, NULL}; - -void berserk_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &berserk_move_stand; - else - self->monsterinfo.currentmove = &berserk_move_run1; -} - - -void berserk_attack_spike (edict_t *self) -{ - static vec3_t aim = {MELEE_DISTANCE, 0, -24}; - fire_hit (self, aim, (15 + (rand() % 6)), 400); // Faster attack -- upwards and backwards -} - - -void berserk_swing (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_punch, 1, ATTN_NORM, 0); -} - -mframe_t berserk_frames_attack_spike [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, berserk_swing, - ai_charge, 0, berserk_attack_spike, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t berserk_move_attack_spike = {FRAME_att_c1, FRAME_att_c8, berserk_frames_attack_spike, berserk_run}; - - -void berserk_attack_club (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->mins[0], -4); - fire_hit (self, aim, (5 + (rand() % 6)), 400); // Slower attack -} - -mframe_t berserk_frames_attack_club [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, berserk_swing, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, berserk_attack_club, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t berserk_move_attack_club = {FRAME_att_c9, FRAME_att_c20, berserk_frames_attack_club, berserk_run}; - - -void berserk_strike (edict_t *self) -{ - //FIXME play impact sound -} - - -mframe_t berserk_frames_attack_strike [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, berserk_swing, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, berserk_strike, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 9.7, NULL, - ai_move, 13.6, NULL -}; - -mmove_t berserk_move_attack_strike = {FRAME_att_c21, FRAME_att_c34, berserk_frames_attack_strike, berserk_run}; - - -void berserk_melee (edict_t *self) -{ - if ((rand() % 2) == 0) - self->monsterinfo.currentmove = &berserk_move_attack_spike; - else - self->monsterinfo.currentmove = &berserk_move_attack_club; -} - - -/* -void() berserk_atke1 =[ $r_attb1, berserk_atke2 ] {ai_run(9);}; -void() berserk_atke2 =[ $r_attb2, berserk_atke3 ] {ai_run(6);}; -void() berserk_atke3 =[ $r_attb3, berserk_atke4 ] {ai_run(18.4);}; -void() berserk_atke4 =[ $r_attb4, berserk_atke5 ] {ai_run(25);}; -void() berserk_atke5 =[ $r_attb5, berserk_atke6 ] {ai_run(14);}; -void() berserk_atke6 =[ $r_attb6, berserk_atke7 ] {ai_run(20);}; -void() berserk_atke7 =[ $r_attb7, berserk_atke8 ] {ai_run(8.5);}; -void() berserk_atke8 =[ $r_attb8, berserk_atke9 ] {ai_run(3);}; -void() berserk_atke9 =[ $r_attb9, berserk_atke10 ] {ai_run(17.5);}; -void() berserk_atke10 =[ $r_attb10, berserk_atke11 ] {ai_run(17);}; -void() berserk_atke11 =[ $r_attb11, berserk_atke12 ] {ai_run(9);}; -void() berserk_atke12 =[ $r_attb12, berserk_atke13 ] {ai_run(25);}; -void() berserk_atke13 =[ $r_attb13, berserk_atke14 ] {ai_run(3.7);}; -void() berserk_atke14 =[ $r_attb14, berserk_atke15 ] {ai_run(2.6);}; -void() berserk_atke15 =[ $r_attb15, berserk_atke16 ] {ai_run(19);}; -void() berserk_atke16 =[ $r_attb16, berserk_atke17 ] {ai_run(25);}; -void() berserk_atke17 =[ $r_attb17, berserk_atke18 ] {ai_run(19.6);}; -void() berserk_atke18 =[ $r_attb18, berserk_run1 ] {ai_run(7.8);}; -*/ - - -mframe_t berserk_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t berserk_move_pain1 = {FRAME_painc1, FRAME_painc4, berserk_frames_pain1, berserk_run}; - - -mframe_t berserk_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t berserk_move_pain2 = {FRAME_painb1, FRAME_painb20, berserk_frames_pain2, berserk_run}; - -void berserk_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); - - if (skill->value == 3) - return; // no pain anims in nightmare - - if ((damage < 20) || (random() < 0.5)) - self->monsterinfo.currentmove = &berserk_move_pain1; - else - self->monsterinfo.currentmove = &berserk_move_pain2; -} - - -void berserk_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - - -mframe_t berserk_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL - -}; -mmove_t berserk_move_death1 = {FRAME_death1, FRAME_death13, berserk_frames_death1, berserk_dead}; - - -mframe_t berserk_frames_death2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t berserk_move_death2 = {FRAME_deathc1, FRAME_deathc8, berserk_frames_death2, berserk_dead}; - - -void berserk_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - - gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - if (damage >= 50) - self->monsterinfo.currentmove = &berserk_move_death1; - else - self->monsterinfo.currentmove = &berserk_move_death2; -} - -//=========== -//Jump -mframe_t berserk_frames_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t berserk_move_jump = { FRAME_run1, FRAME_run6, berserk_frames_jump, berserk_run }; - -void berserk_jump (edict_t *self) -{ - self->monsterinfo.currentmove = &berserk_move_jump; -} - - -/*QUAKED monster_berserk (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_berserk (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - - self->class_id = ENTITY_MONSTER_BERSERK; - self->spawnflags |= SF_MONSTER_KNOWS_MIRRORS; - // pre-caches - sound_pain = gi.soundindex ("berserk/berpain2.wav"); - sound_die = gi.soundindex ("berserk/berdeth2.wav"); - sound_idle = gi.soundindex ("berserk/beridle1.wav"); - sound_punch = gi.soundindex ("berserk/attack.wav"); - sound_search = gi.soundindex ("berserk/bersrch1.wav"); - sound_sight = gi.soundindex ("berserk/sight.wav"); - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/berserk/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex("models/monsters/berserk/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 240; - if(!self->gib_health) - self->gib_health = -60; - if(!self->mass) - self->mass = 250; - - self->pain = berserk_pain; - self->die = berserk_die; - - self->monsterinfo.stand = berserk_stand; - self->monsterinfo.walk = berserk_walk; - self->monsterinfo.run = berserk_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = NULL; - self->monsterinfo.melee = berserk_melee; - self->monsterinfo.sight = berserk_sight; - self->monsterinfo.search = berserk_search; - if(monsterjump->value) - { - self->monsterinfo.jump = berserk_jump; - self->monsterinfo.jumpup = 48; - self->monsterinfo.jumpdn = 160; - } - - self->monsterinfo.currentmove = &berserk_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&berserk_move_death1, - &berserk_move_death2, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.20; - self->common_name = "Berserker"; - - gi.linkentity (self); - - walkmonster_start (self); -} diff --git a/server/monsters/m_berserk.h b/server/monsters/m_berserk.h deleted file mode 100644 index 8ee75e19..00000000 --- a/server/monsters/m_berserk.h +++ /dev/null @@ -1,250 +0,0 @@ -// G:\quake2\baseq2\models/monsters/berserk - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand1 0 -#define FRAME_stand2 1 -#define FRAME_stand3 2 -#define FRAME_stand4 3 -#define FRAME_stand5 4 -#define FRAME_standb1 5 -#define FRAME_standb2 6 -#define FRAME_standb3 7 -#define FRAME_standb4 8 -#define FRAME_standb5 9 -#define FRAME_standb6 10 -#define FRAME_standb7 11 -#define FRAME_standb8 12 -#define FRAME_standb9 13 -#define FRAME_standb10 14 -#define FRAME_standb11 15 -#define FRAME_standb12 16 -#define FRAME_standb13 17 -#define FRAME_standb14 18 -#define FRAME_standb15 19 -#define FRAME_standb16 20 -#define FRAME_standb17 21 -#define FRAME_standb18 22 -#define FRAME_standb19 23 -#define FRAME_standb20 24 -#define FRAME_walkc1 25 -#define FRAME_walkc2 26 -#define FRAME_walkc3 27 -#define FRAME_walkc4 28 -#define FRAME_walkc5 29 -#define FRAME_walkc6 30 -#define FRAME_walkc7 31 -#define FRAME_walkc8 32 -#define FRAME_walkc9 33 -#define FRAME_walkc10 34 -#define FRAME_walkc11 35 -#define FRAME_run1 36 -#define FRAME_run2 37 -#define FRAME_run3 38 -#define FRAME_run4 39 -#define FRAME_run5 40 -#define FRAME_run6 41 -#define FRAME_att_a1 42 -#define FRAME_att_a2 43 -#define FRAME_att_a3 44 -#define FRAME_att_a4 45 -#define FRAME_att_a5 46 -#define FRAME_att_a6 47 -#define FRAME_att_a7 48 -#define FRAME_att_a8 49 -#define FRAME_att_a9 50 -#define FRAME_att_a10 51 -#define FRAME_att_a11 52 -#define FRAME_att_a12 53 -#define FRAME_att_a13 54 -#define FRAME_att_b1 55 -#define FRAME_att_b2 56 -#define FRAME_att_b3 57 -#define FRAME_att_b4 58 -#define FRAME_att_b5 59 -#define FRAME_att_b6 60 -#define FRAME_att_b7 61 -#define FRAME_att_b8 62 -#define FRAME_att_b9 63 -#define FRAME_att_b10 64 -#define FRAME_att_b11 65 -#define FRAME_att_b12 66 -#define FRAME_att_b13 67 -#define FRAME_att_b14 68 -#define FRAME_att_b15 69 -#define FRAME_att_b16 70 -#define FRAME_att_b17 71 -#define FRAME_att_b18 72 -#define FRAME_att_b19 73 -#define FRAME_att_b20 74 -#define FRAME_att_b21 75 -#define FRAME_att_c1 76 -#define FRAME_att_c2 77 -#define FRAME_att_c3 78 -#define FRAME_att_c4 79 -#define FRAME_att_c5 80 -#define FRAME_att_c6 81 -#define FRAME_att_c7 82 -#define FRAME_att_c8 83 -#define FRAME_att_c9 84 -#define FRAME_att_c10 85 -#define FRAME_att_c11 86 -#define FRAME_att_c12 87 -#define FRAME_att_c13 88 -#define FRAME_att_c14 89 -#define FRAME_att_c15 90 -#define FRAME_att_c16 91 -#define FRAME_att_c17 92 -#define FRAME_att_c18 93 -#define FRAME_att_c19 94 -#define FRAME_att_c20 95 -#define FRAME_att_c21 96 -#define FRAME_att_c22 97 -#define FRAME_att_c23 98 -#define FRAME_att_c24 99 -#define FRAME_att_c25 100 -#define FRAME_att_c26 101 -#define FRAME_att_c27 102 -#define FRAME_att_c28 103 -#define FRAME_att_c29 104 -#define FRAME_att_c30 105 -#define FRAME_att_c31 106 -#define FRAME_att_c32 107 -#define FRAME_att_c33 108 -#define FRAME_att_c34 109 -#define FRAME_r_att1 110 -#define FRAME_r_att2 111 -#define FRAME_r_att3 112 -#define FRAME_r_att4 113 -#define FRAME_r_att5 114 -#define FRAME_r_att6 115 -#define FRAME_r_att7 116 -#define FRAME_r_att8 117 -#define FRAME_r_att9 118 -#define FRAME_r_att10 119 -#define FRAME_r_att11 120 -#define FRAME_r_att12 121 -#define FRAME_r_att13 122 -#define FRAME_r_att14 123 -#define FRAME_r_att15 124 -#define FRAME_r_att16 125 -#define FRAME_r_att17 126 -#define FRAME_r_att18 127 -#define FRAME_r_attb1 128 -#define FRAME_r_attb2 129 -#define FRAME_r_attb3 130 -#define FRAME_r_attb4 131 -#define FRAME_r_attb5 132 -#define FRAME_r_attb6 133 -#define FRAME_r_attb7 134 -#define FRAME_r_attb8 135 -#define FRAME_r_attb9 136 -#define FRAME_r_attb10 137 -#define FRAME_r_attb11 138 -#define FRAME_r_attb12 139 -#define FRAME_r_attb13 140 -#define FRAME_r_attb14 141 -#define FRAME_r_attb15 142 -#define FRAME_r_attb16 143 -#define FRAME_r_attb17 144 -#define FRAME_r_attb18 145 -#define FRAME_slam1 146 -#define FRAME_slam2 147 -#define FRAME_slam3 148 -#define FRAME_slam4 149 -#define FRAME_slam5 150 -#define FRAME_slam6 151 -#define FRAME_slam7 152 -#define FRAME_slam8 153 -#define FRAME_slam9 154 -#define FRAME_slam10 155 -#define FRAME_slam11 156 -#define FRAME_slam12 157 -#define FRAME_slam13 158 -#define FRAME_slam14 159 -#define FRAME_slam15 160 -#define FRAME_slam16 161 -#define FRAME_slam17 162 -#define FRAME_slam18 163 -#define FRAME_slam19 164 -#define FRAME_slam20 165 -#define FRAME_slam21 166 -#define FRAME_slam22 167 -#define FRAME_slam23 168 -#define FRAME_duck1 169 -#define FRAME_duck2 170 -#define FRAME_duck3 171 -#define FRAME_duck4 172 -#define FRAME_duck5 173 -#define FRAME_duck6 174 -#define FRAME_duck7 175 -#define FRAME_duck8 176 -#define FRAME_duck9 177 -#define FRAME_duck10 178 -#define FRAME_fall1 179 -#define FRAME_fall2 180 -#define FRAME_fall3 181 -#define FRAME_fall4 182 -#define FRAME_fall5 183 -#define FRAME_fall6 184 -#define FRAME_fall7 185 -#define FRAME_fall8 186 -#define FRAME_fall9 187 -#define FRAME_fall10 188 -#define FRAME_fall11 189 -#define FRAME_fall12 190 -#define FRAME_fall13 191 -#define FRAME_fall14 192 -#define FRAME_fall15 193 -#define FRAME_fall16 194 -#define FRAME_fall17 195 -#define FRAME_fall18 196 -#define FRAME_fall19 197 -#define FRAME_fall20 198 -#define FRAME_painc1 199 -#define FRAME_painc2 200 -#define FRAME_painc3 201 -#define FRAME_painc4 202 -#define FRAME_painb1 203 -#define FRAME_painb2 204 -#define FRAME_painb3 205 -#define FRAME_painb4 206 -#define FRAME_painb5 207 -#define FRAME_painb6 208 -#define FRAME_painb7 209 -#define FRAME_painb8 210 -#define FRAME_painb9 211 -#define FRAME_painb10 212 -#define FRAME_painb11 213 -#define FRAME_painb12 214 -#define FRAME_painb13 215 -#define FRAME_painb14 216 -#define FRAME_painb15 217 -#define FRAME_painb16 218 -#define FRAME_painb17 219 -#define FRAME_painb18 220 -#define FRAME_painb19 221 -#define FRAME_painb20 222 -#define FRAME_death1 223 -#define FRAME_death2 224 -#define FRAME_death3 225 -#define FRAME_death4 226 -#define FRAME_death5 227 -#define FRAME_death6 228 -#define FRAME_death7 229 -#define FRAME_death8 230 -#define FRAME_death9 231 -#define FRAME_death10 232 -#define FRAME_death11 233 -#define FRAME_death12 234 -#define FRAME_death13 235 -#define FRAME_deathc1 236 -#define FRAME_deathc2 237 -#define FRAME_deathc3 238 -#define FRAME_deathc4 239 -#define FRAME_deathc5 240 -#define FRAME_deathc6 241 -#define FRAME_deathc7 242 -#define FRAME_deathc8 243 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_boss2.c b/server/monsters/m_boss2.c deleted file mode 100644 index 61a1e42c..00000000 --- a/server/monsters/m_boss2.c +++ /dev/null @@ -1,704 +0,0 @@ -/* -============================================================================== - -boss2 - -============================================================================== -*/ - -#include "g_local.h" -#include "m_boss2.h" - -void BossExplode (edict_t *self); - -bool infront (edict_t *self, edict_t *other); - -static int sound_pain1; -static int sound_pain2; -static int sound_pain3; -static int sound_death; -static int sound_search1; - -void boss2_search (edict_t *self) -{ - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0); -} - -void boss2_run (edict_t *self); -void boss2_stand (edict_t *self); -void boss2_dead (edict_t *self); -void boss2_attack (edict_t *self); -void boss2_attack_mg (edict_t *self); -void boss2_reattack_mg (edict_t *self); -void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); - -void Boss2Rocket (edict_t *self) -{ - vec3_t forward, right; - vec3_t start; - vec3_t dir; - vec3_t vec; - int rocketSpeed; - - if((self->spawnflags & SF_MONSTER_SPECIAL)) - rocketSpeed = 400; // Lazarus: Homing rockets are tougher if slow - else - rocketSpeed = 500 + (100 * skill->value); // PGM rock & roll.... :) - - AngleVectors (self->s.angles, forward, right, NULL); - - VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - -//1 - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start); - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_BOSS2_ROCKET_1, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); - -//2 - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start); - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_BOSS2_ROCKET_2, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); - -//3 - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start); - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_BOSS2_ROCKET_3, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); - -//4 - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_BOSS2_ROCKET_4, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); -} - -void boss2_firebullet_right (edict_t *self) -{ - vec3_t forward, right, target; - vec3_t start; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start); - VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); - target[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (target, start, forward); - VectorNormalize (forward); - monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1); -} - -void boss2_firebullet_left (edict_t *self) -{ - vec3_t forward, right, target; - vec3_t start; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start); - VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); - target[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (target, start, forward); - VectorNormalize (forward); - - monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1); -} - -void Boss2MachineGun (edict_t *self) -{ - boss2_firebullet_left(self); - boss2_firebullet_right(self); -} - - -mframe_t boss2_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t boss2_move_stand = {FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL}; - -mframe_t boss2_frames_fidget [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t boss2_move_fidget = {FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL}; - -mframe_t boss2_frames_walk [] = -{ - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL -}; -mmove_t boss2_move_walk = {FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL}; - - -mframe_t boss2_frames_run [] = -{ - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL -}; -mmove_t boss2_move_run = {FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL}; - -mframe_t boss2_frames_attack_pre_mg [] = -{ - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, boss2_attack_mg -}; -mmove_t boss2_move_attack_pre_mg = {FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL}; - - -// Loop this -mframe_t boss2_frames_attack_mg [] = -{ - ai_charge, 1, Boss2MachineGun, - ai_charge, 1, Boss2MachineGun, - ai_charge, 1, Boss2MachineGun, - ai_charge, 1, Boss2MachineGun, - ai_charge, 1, Boss2MachineGun, - ai_charge, 1, boss2_reattack_mg -}; -mmove_t boss2_move_attack_mg = {FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL}; - -mframe_t boss2_frames_attack_post_mg [] = -{ - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL -}; -mmove_t boss2_move_attack_post_mg = {FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run}; - -mframe_t boss2_frames_attack_rocket [] = -{ - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_move, -20, Boss2Rocket, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL -}; -mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run}; - -mframe_t boss2_frames_pain_heavy [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t boss2_move_pain_heavy = {FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run}; - -mframe_t boss2_frames_pain_light [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t boss2_move_pain_light = {FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run}; - -mframe_t boss2_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, BossExplode -}; -mmove_t boss2_move_death = {FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead}; - -void boss2_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &boss2_move_stand; -} - -void boss2_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &boss2_move_stand; - else - self->monsterinfo.currentmove = &boss2_move_run; -} - -void boss2_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &boss2_move_walk; -} - -void boss2_attack (edict_t *self) -{ - vec3_t vec; - float range; - - VectorSubtract (self->enemy->s.origin, self->s.origin, vec); - range = VectorLength (vec); - - if (range <= 125) - { - self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; - } - else - { - if (random() <= 0.6) - self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; - else - self->monsterinfo.currentmove = &boss2_move_attack_rocket; - } -} - -void boss2_attack_mg (edict_t *self) -{ - self->monsterinfo.currentmove = &boss2_move_attack_mg; -} - -void boss2_reattack_mg (edict_t *self) -{ - if ( infront(self, self->enemy) ) - if (random() <= 0.7) - self->monsterinfo.currentmove = &boss2_move_attack_mg; - else - self->monsterinfo.currentmove = &boss2_move_attack_post_mg; - else - self->monsterinfo.currentmove = &boss2_move_attack_post_mg; -} - - -void boss2_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; -// American wanted these at no attenuation - if (damage < 10) - { - gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); - self->monsterinfo.currentmove = &boss2_move_pain_light; - } - else if (damage < 30) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); - self->monsterinfo.currentmove = &boss2_move_pain_light; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); - self->monsterinfo.currentmove = &boss2_move_pain_heavy; - } -} - -void boss2_dead (edict_t *self) -{ - VectorSet (self->mins, -56, -56, 0); - VectorSet (self->maxs, 56, 56, 80); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); -} - -void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_NO; - self->count = 0; - self->monsterinfo.currentmove = &boss2_move_death; -#if 0 - int n; - - self->s.sound = 0; - // check for gib - if (self->health <= self->gib_health && !(self->spawnflags & MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->monsterinfo.currentmove = &boss2_move_death; -#endif -} - -bool Boss2_CheckAttack (edict_t *self) -{ - vec3_t spot1, spot2; - vec3_t temp; - float chance; - trace_t tr; - bool enemy_infront; - int enemy_range; - float enemy_yaw; - - if (self->enemy->health > 0) - { - // see if any entities are in the way of the shot - VectorCopy (self->s.origin, spot1); - spot1[2] += self->viewheight; - VectorCopy (self->enemy->s.origin, spot2); - spot2[2] += self->enemy->viewheight; - - tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); - - // do we have a clear shot? - if (tr.ent != self->enemy) - return false; - } - - enemy_infront = infront(self, self->enemy); - enemy_range = range(self, self->enemy); - VectorSubtract (self->enemy->s.origin, self->s.origin, temp); - enemy_yaw = vectoyaw(temp); - - self->ideal_yaw = enemy_yaw; - - - // melee attack - if (enemy_range == RANGE_MELEE) - { - if (self->monsterinfo.melee) - self->monsterinfo.attack_state = AS_MELEE; - else - self->monsterinfo.attack_state = AS_MISSILE; - return true; - } - -// missile attack - if (!self->monsterinfo.attack) - return false; - - if (level.time < self->monsterinfo.attack_finished) - return false; - - if (enemy_range == RANGE_FAR) - return false; - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - chance = 0.4; - } - else if (enemy_range == RANGE_MELEE) - { - chance = 0.8; - } - else if (enemy_range == RANGE_NEAR) - { - chance = 0.8; - } - else if (enemy_range == RANGE_MID) - { - chance = 0.8; - } - else - { - return false; - } - - if (random () < chance) - { - self->monsterinfo.attack_state = AS_MISSILE; - self->monsterinfo.attack_finished = level.time + 2*random(); - return true; - } - - if (self->flags & FL_FLY) - { - if (random() < 0.3) - self->monsterinfo.attack_state = AS_SLIDING; - else - self->monsterinfo.attack_state = AS_STRAIGHT; - } - - return false; -} - - - -/*QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight -*/ -void SP_monster_boss2 (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - - self->class_id = ENTITY_MONSTER_BOSS2; - // Lazarus: special purpose skins - if ( (self->spawnflags & SF_MONSTER_SPECIAL) && self->style ) - { - PatchMonsterModel("models/monsters/boss2/tris.md2"); - self->s.skin = self->style * 2; - } - - sound_pain1 = gi.soundindex ("bosshovr/bhvpain1.wav"); - sound_pain2 = gi.soundindex ("bosshovr/bhvpain2.wav"); - sound_pain3 = gi.soundindex ("bosshovr/bhvpain3.wav"); - sound_death = gi.soundindex ("bosshovr/bhvdeth1.wav"); - sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav"); - - self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/boss2/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/boss2/tris.md2"); - VectorSet (self->mins, -56, -56, 0); - VectorSet (self->maxs, 56, 56, 80); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 2000; - if(!self->gib_health) - self->gib_health = -200; - if(!self->mass) - self->mass = 1000; - - self->flags |= FL_IMMUNE_LASER; - - self->pain = boss2_pain; - self->die = boss2_die; - - self->monsterinfo.stand = boss2_stand; - self->monsterinfo.walk = boss2_walk; - self->monsterinfo.run = boss2_run; - self->monsterinfo.attack = boss2_attack; - self->monsterinfo.search = boss2_search; - self->monsterinfo.checkattack = Boss2_CheckAttack; - gi.linkentity (self); - - self->monsterinfo.currentmove = &boss2_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&boss2_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - - // Lazarus power armor - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - self->common_name = "Flying Boss"; - - flymonster_start (self); -} diff --git a/server/monsters/m_boss2.h b/server/monsters/m_boss2.h deleted file mode 100644 index 3bcbc05d..00000000 --- a/server/monsters/m_boss2.h +++ /dev/null @@ -1,187 +0,0 @@ -// G:\quake2\baseq2\models/monsters/boss2 - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand30 0 -#define FRAME_stand31 1 -#define FRAME_stand32 2 -#define FRAME_stand33 3 -#define FRAME_stand34 4 -#define FRAME_stand35 5 -#define FRAME_stand36 6 -#define FRAME_stand37 7 -#define FRAME_stand38 8 -#define FRAME_stand39 9 -#define FRAME_stand40 10 -#define FRAME_stand41 11 -#define FRAME_stand42 12 -#define FRAME_stand43 13 -#define FRAME_stand44 14 -#define FRAME_stand45 15 -#define FRAME_stand46 16 -#define FRAME_stand47 17 -#define FRAME_stand48 18 -#define FRAME_stand49 19 -#define FRAME_stand50 20 -#define FRAME_stand1 21 -#define FRAME_stand2 22 -#define FRAME_stand3 23 -#define FRAME_stand4 24 -#define FRAME_stand5 25 -#define FRAME_stand6 26 -#define FRAME_stand7 27 -#define FRAME_stand8 28 -#define FRAME_stand9 29 -#define FRAME_stand10 30 -#define FRAME_stand11 31 -#define FRAME_stand12 32 -#define FRAME_stand13 33 -#define FRAME_stand14 34 -#define FRAME_stand15 35 -#define FRAME_stand16 36 -#define FRAME_stand17 37 -#define FRAME_stand18 38 -#define FRAME_stand19 39 -#define FRAME_stand20 40 -#define FRAME_stand21 41 -#define FRAME_stand22 42 -#define FRAME_stand23 43 -#define FRAME_stand24 44 -#define FRAME_stand25 45 -#define FRAME_stand26 46 -#define FRAME_stand27 47 -#define FRAME_stand28 48 -#define FRAME_stand29 49 -#define FRAME_walk1 50 -#define FRAME_walk2 51 -#define FRAME_walk3 52 -#define FRAME_walk4 53 -#define FRAME_walk5 54 -#define FRAME_walk6 55 -#define FRAME_walk7 56 -#define FRAME_walk8 57 -#define FRAME_walk9 58 -#define FRAME_walk10 59 -#define FRAME_walk11 60 -#define FRAME_walk12 61 -#define FRAME_walk13 62 -#define FRAME_walk14 63 -#define FRAME_walk15 64 -#define FRAME_walk16 65 -#define FRAME_walk17 66 -#define FRAME_walk18 67 -#define FRAME_walk19 68 -#define FRAME_walk20 69 -#define FRAME_attack1 70 -#define FRAME_attack2 71 -#define FRAME_attack3 72 -#define FRAME_attack4 73 -#define FRAME_attack5 74 -#define FRAME_attack6 75 -#define FRAME_attack7 76 -#define FRAME_attack8 77 -#define FRAME_attack9 78 -#define FRAME_attack10 79 -#define FRAME_attack11 80 -#define FRAME_attack12 81 -#define FRAME_attack13 82 -#define FRAME_attack14 83 -#define FRAME_attack15 84 -#define FRAME_attack16 85 -#define FRAME_attack17 86 -#define FRAME_attack18 87 -#define FRAME_attack19 88 -#define FRAME_attack20 89 -#define FRAME_attack21 90 -#define FRAME_attack22 91 -#define FRAME_attack23 92 -#define FRAME_attack24 93 -#define FRAME_attack25 94 -#define FRAME_attack26 95 -#define FRAME_attack27 96 -#define FRAME_attack28 97 -#define FRAME_attack29 98 -#define FRAME_attack30 99 -#define FRAME_attack31 100 -#define FRAME_attack32 101 -#define FRAME_attack33 102 -#define FRAME_attack34 103 -#define FRAME_attack35 104 -#define FRAME_attack36 105 -#define FRAME_attack37 106 -#define FRAME_attack38 107 -#define FRAME_attack39 108 -#define FRAME_attack40 109 -#define FRAME_pain2 110 -#define FRAME_pain3 111 -#define FRAME_pain4 112 -#define FRAME_pain5 113 -#define FRAME_pain6 114 -#define FRAME_pain7 115 -#define FRAME_pain8 116 -#define FRAME_pain9 117 -#define FRAME_pain10 118 -#define FRAME_pain11 119 -#define FRAME_pain12 120 -#define FRAME_pain13 121 -#define FRAME_pain14 122 -#define FRAME_pain15 123 -#define FRAME_pain16 124 -#define FRAME_pain17 125 -#define FRAME_pain18 126 -#define FRAME_pain19 127 -#define FRAME_pain20 128 -#define FRAME_pain21 129 -#define FRAME_pain22 130 -#define FRAME_pain23 131 -#define FRAME_death2 132 -#define FRAME_death3 133 -#define FRAME_death4 134 -#define FRAME_death5 135 -#define FRAME_death6 136 -#define FRAME_death7 137 -#define FRAME_death8 138 -#define FRAME_death9 139 -#define FRAME_death10 140 -#define FRAME_death11 141 -#define FRAME_death12 142 -#define FRAME_death13 143 -#define FRAME_death14 144 -#define FRAME_death15 145 -#define FRAME_death16 146 -#define FRAME_death17 147 -#define FRAME_death18 148 -#define FRAME_death19 149 -#define FRAME_death20 150 -#define FRAME_death21 151 -#define FRAME_death22 152 -#define FRAME_death23 153 -#define FRAME_death24 154 -#define FRAME_death25 155 -#define FRAME_death26 156 -#define FRAME_death27 157 -#define FRAME_death28 158 -#define FRAME_death29 159 -#define FRAME_death30 160 -#define FRAME_death31 161 -#define FRAME_death32 162 -#define FRAME_death33 163 -#define FRAME_death34 164 -#define FRAME_death35 165 -#define FRAME_death36 166 -#define FRAME_death37 167 -#define FRAME_death38 168 -#define FRAME_death39 169 -#define FRAME_death40 170 -#define FRAME_death41 171 -#define FRAME_death42 172 -#define FRAME_death43 173 -#define FRAME_death44 174 -#define FRAME_death45 175 -#define FRAME_death46 176 -#define FRAME_death47 177 -#define FRAME_death48 178 -#define FRAME_death49 179 -#define FRAME_death50 180 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_boss3.c b/server/monsters/m_boss3.c deleted file mode 100644 index 2e9de97a..00000000 --- a/server/monsters/m_boss3.c +++ /dev/null @@ -1,58 +0,0 @@ -/* -============================================================================== - -boss3 - -============================================================================== -*/ - -#include "g_local.h" -#include "m_boss32.h" - -void Use_Boss3 (edict_t *ent, edict_t *other, edict_t *activator) -{ - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_BOSSTPORT); - WRITE_COORD (ent->s.origin); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - G_FreeEdict (ent); -} - -void Think_Boss3Stand (edict_t *ent) -{ - if (ent->s.frame == FRAME_stand260) - ent->s.frame = FRAME_stand201; - else - ent->s.frame++; - ent->nextthink = level.time + FRAMETIME; -} - -/*QUAKED monster_boss3_stand (1 .5 0) (-32 -32 0) (32 32 90) - -Just stands and cycles in one place until targeted, then teleports away. -*/ -void SP_monster_boss3_stand (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_BOSS3_STAND; - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - self->model = "models/monsters/boss3/rider/tris.md2"; - self->s.modelindex = gi.modelindex (self->model); - self->s.frame = FRAME_stand201; - - gi.soundindex ("misc/bigtele.wav"); - - VectorSet (self->mins, -32, -32, 0); - VectorSet (self->maxs, 32, 32, 90); - - self->use = Use_Boss3; - self->think = Think_Boss3Stand; - self->nextthink = level.time + FRAMETIME; - gi.linkentity (self); -} diff --git a/server/monsters/m_boss31.c b/server/monsters/m_boss31.c deleted file mode 100644 index 386fa699..00000000 --- a/server/monsters/m_boss31.c +++ /dev/null @@ -1,775 +0,0 @@ -/* -============================================================================== - -jorg - -============================================================================== -*/ - -#include "g_local.h" -#include "m_boss31.h" - -extern SP_monster_makron (edict_t *self); -bool visible (edict_t *self, edict_t *other); - -static int sound_pain1; -static int sound_pain2; -static int sound_pain3; -static int sound_idle; -static int sound_death; -static int sound_search1; -static int sound_search2; -static int sound_search3; -static int sound_attack1; -static int sound_attack2; -static int sound_firegun; -static int sound_step_left; -static int sound_step_right; -static int sound_death_hit; - -void BossExplode (edict_t *self); -void MakronToss (edict_t *self); - - -void jorg_search (edict_t *self) -{ - float r; - - r = random(); - - if (r <= 0.3) - gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); - else if (r <= 0.6) - gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_search3, 1, ATTN_NORM, 0); -} - - -void jorg_dead (edict_t *self); -void jorgBFG (edict_t *self); -void jorgMachineGun (edict_t *self); -void jorg_firebullet (edict_t *self); -void jorg_reattack1(edict_t *self); -void jorg_attack1(edict_t *self); -void jorg_idle(edict_t *self); -void jorg_step_left(edict_t *self); -void jorg_step_right(edict_t *self); -void jorg_death_hit(edict_t *self); - -// -// stand -// - -mframe_t jorg_frames_stand []= -{ - ai_stand, 0, jorg_idle, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 10 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 20 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 30 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 19, NULL, - ai_stand, 11, jorg_step_left, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 6, NULL, - ai_stand, 9, jorg_step_right, - ai_stand, 0, NULL, // 40 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, -2, NULL, - ai_stand, -17, jorg_step_left, - ai_stand, 0, NULL, - ai_stand, -12, NULL, // 50 - ai_stand, -14, jorg_step_right // 51 -}; -mmove_t jorg_move_stand = {FRAME_stand01, FRAME_stand51, jorg_frames_stand, NULL}; - -void jorg_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_NORM,0); -} - -void jorg_death_hit (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_death_hit, 1, ATTN_NORM,0); -} - - -void jorg_step_left (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0); -} - -void jorg_step_right (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0); -} - - -void jorg_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &jorg_move_stand; -} - -mframe_t jorg_frames_run [] = -{ - ai_run, 17, jorg_step_left, - ai_run, 0, NULL, - ai_run, 0, NULL, - ai_run, 0, NULL, - ai_run, 12, NULL, - ai_run, 8, NULL, - ai_run, 10, NULL, - ai_run, 33, jorg_step_right, - ai_run, 0, NULL, - ai_run, 0, NULL, - ai_run, 0, NULL, - ai_run, 9, NULL, - ai_run, 9, NULL, - ai_run, 9, NULL -}; -mmove_t jorg_move_run = {FRAME_walk06, FRAME_walk19, jorg_frames_run, NULL}; - -// -// walk -// - -mframe_t jorg_frames_start_walk [] = -{ - ai_walk, 5, NULL, - ai_walk, 6, NULL, - ai_walk, 7, NULL, - ai_walk, 9, NULL, - ai_walk, 15, NULL -}; -mmove_t jorg_move_start_walk = {FRAME_walk01, FRAME_walk05, jorg_frames_start_walk, NULL}; - -mframe_t jorg_frames_walk [] = -{ - ai_walk, 17, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 12, NULL, - ai_walk, 8, NULL, - ai_walk, 10, NULL, - ai_walk, 33, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 9, NULL, - ai_walk, 9, NULL, - ai_walk, 9, NULL -}; -mmove_t jorg_move_walk = {FRAME_walk06, FRAME_walk19, jorg_frames_walk, NULL}; - -mframe_t jorg_frames_end_walk [] = -{ - ai_walk, 11, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 8, NULL, - ai_walk, -8, NULL -}; -mmove_t jorg_move_end_walk = {FRAME_walk20, FRAME_walk25, jorg_frames_end_walk, NULL}; - -void jorg_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &jorg_move_walk; -} - -void jorg_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &jorg_move_stand; - else - self->monsterinfo.currentmove = &jorg_move_run; -} - -mframe_t jorg_frames_pain3 [] = -{ - ai_move, -28, NULL, - ai_move, -6, NULL, - ai_move, -3, jorg_step_left, - ai_move, -9, NULL, - ai_move, 0, jorg_step_right, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -7, NULL, - ai_move, 1, NULL, - ai_move, -11, NULL, - ai_move, -4, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 10, NULL, - ai_move, 11, NULL, - ai_move, 0, NULL, - ai_move, 10, NULL, - ai_move, 3, NULL, - ai_move, 10, NULL, - ai_move, 7, jorg_step_left, - ai_move, 17, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, jorg_step_right -}; -mmove_t jorg_move_pain3 = {FRAME_pain301, FRAME_pain325, jorg_frames_pain3, jorg_run}; - -mframe_t jorg_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t jorg_move_pain2 = {FRAME_pain201, FRAME_pain203, jorg_frames_pain2, jorg_run}; - -mframe_t jorg_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t jorg_move_pain1 = {FRAME_pain101, FRAME_pain103, jorg_frames_pain1, jorg_run}; - -mframe_t jorg_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 10 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 20 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 30 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 40 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, MakronToss, - ai_move, 0, BossExplode // 50 -}; -mmove_t jorg_move_death = {FRAME_death01, FRAME_death50, jorg_frames_death1, jorg_dead}; - -mframe_t jorg_frames_attack2 []= -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, jorgBFG, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t jorg_move_attack2 = {FRAME_attak201, FRAME_attak213, jorg_frames_attack2, jorg_run}; - -mframe_t jorg_frames_start_attack1 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t jorg_move_start_attack1 = {FRAME_attak101, FRAME_attak108, jorg_frames_start_attack1, jorg_attack1}; - -mframe_t jorg_frames_attack1[]= -{ - ai_charge, 0, jorg_firebullet, - ai_charge, 0, jorg_firebullet, - ai_charge, 0, jorg_firebullet, - ai_charge, 0, jorg_firebullet, - ai_charge, 0, jorg_firebullet, - ai_charge, 0, jorg_firebullet -}; -mmove_t jorg_move_attack1 = {FRAME_attak109, FRAME_attak114, jorg_frames_attack1, jorg_reattack1}; - -mframe_t jorg_frames_end_attack1[]= -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t jorg_move_end_attack1 = {FRAME_attak115, FRAME_attak118, jorg_frames_end_attack1, jorg_run}; - -void jorg_reattack1(edict_t *self) -{ - if (visible(self, self->enemy)) - if (random() < 0.9) - self->monsterinfo.currentmove = &jorg_move_attack1; - else - { - self->s.sound = 0; - self->monsterinfo.currentmove = &jorg_move_end_attack1; - } - else - { - self->s.sound = 0; - self->monsterinfo.currentmove = &jorg_move_end_attack1; - } -} - -void jorg_attack1(edict_t *self) -{ - self->monsterinfo.currentmove = &jorg_move_attack1; -} - -void jorg_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - self->s.sound = 0; - - if (level.time < self->pain_debounce_time) - return; - - // Lessen the chance of him going into his pain frames if he takes little damage - if (damage <= 40) - if (random()<=0.6) - return; - - /* - If he's entering his attack1 or using attack1, lessen the chance of him - going into pain - */ - - if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak108) ) - if (random() <= 0.005) - return; - - if ( (self->s.frame >= FRAME_attak109) && (self->s.frame <= FRAME_attak114) ) - if (random() <= 0.00005) - return; - - - if ( (self->s.frame >= FRAME_attak201) && (self->s.frame <= FRAME_attak208) ) - if (random() <= 0.005) - return; - - - self->pain_debounce_time = level.time + 3; - if (skill->value == 3) - return; // no pain anims in nightmare - - if (damage <= 50) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &jorg_move_pain1; - } - else if (damage <= 100) - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &jorg_move_pain2; - } - else - { - if (random() <= 0.3) - { - gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &jorg_move_pain3; - } - } -}; - -void jorgBFG (edict_t *self) -{ - vec3_t forward, right; - vec3_t start; - vec3_t dir; - vec3_t vec; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_BFG_1], forward, right, start); - - VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0); - /*void monster_fire_bfg (edict_t *self, - vec3_t start, - vec3_t aimdir, - int damage, - int speed, - int kick, - float damage_radius, - int flashtype)*/ - monster_fire_bfg (self, start, dir, 50, 300, 100, 200, MZ2_JORG_BFG_1); -} - -void jorg_firebullet_right (edict_t *self) -{ - vec3_t forward, right, target; - vec3_t start; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_R1], forward, right, start); - VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); - target[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (target, start, forward); - VectorNormalize (forward); - - monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_R1); -} - -void jorg_firebullet_left (edict_t *self) -{ - vec3_t forward, right, target; - vec3_t start; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_L1], forward, right, start); - VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); - target[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (target, start, forward); - VectorNormalize (forward); - monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_L1); -} - -void jorg_firebullet (edict_t *self) -{ - jorg_firebullet_left(self); - jorg_firebullet_right(self); -}; - -void jorg_attack(edict_t *self) -{ - vec3_t vec; - float range; - - VectorSubtract (self->enemy->s.origin, self->s.origin, vec); - range = VectorLength (vec); - - if (random() <= 0.75) - { - gi.sound (self, CHAN_VOICE, sound_attack1, 1, ATTN_NORM,0); - self->s.sound = gi.soundindex ("boss3/w_loop.wav"); - self->monsterinfo.currentmove = &jorg_move_start_attack1; - } - else - { - gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &jorg_move_attack2; - } -} - -void jorg_dead (edict_t *self) -{ -#if 0 - edict_t *tempent; - /* - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - */ - - // Jorg is on weaponmodel. Do not clear him. - VectorSet (self->mins, -60, -60, 0); - VectorSet (self->maxs, 60, 60, 72); - self->movetype = MOVETYPE_TOSS; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - tempent = G_Spawn(); - VectorCopy (self->s.origin, tempent->s.origin); - VectorCopy (self->s.angles, tempent->s.angles); - tempent->killtarget = self->killtarget; - tempent->target = self->target; - tempent->activator = self->enemy; - self->killtarget = 0; - self->target = 0; - SP_monster_makron (tempent); -#endif -} - - -void jorg_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_NO; - self->s.sound = 0; - self->count = 0; - self->monsterinfo.currentmove = &jorg_move_death; -} - -bool Jorg_CheckAttack (edict_t *self) -{ - vec3_t spot1, spot2; - vec3_t temp; - float chance; - trace_t tr; - bool enemy_infront; - int enemy_range; - float enemy_yaw; - - if (self->enemy->health > 0) - { - // see if any entities are in the way of the shot - VectorCopy (self->s.origin, spot1); - spot1[2] += self->viewheight; - VectorCopy (self->enemy->s.origin, spot2); - spot2[2] += self->enemy->viewheight; - - tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); - - // do we have a clear shot? - if (tr.ent != self->enemy) - return false; - } - - enemy_infront = infront(self, self->enemy); - enemy_range = range(self, self->enemy); - VectorSubtract (self->enemy->s.origin, self->s.origin, temp); - enemy_yaw = vectoyaw(temp); - - self->ideal_yaw = enemy_yaw; - - - // melee attack - if (enemy_range == RANGE_MELEE) - { - if (self->monsterinfo.melee) - self->monsterinfo.attack_state = AS_MELEE; - else - self->monsterinfo.attack_state = AS_MISSILE; - return true; - } - -// missile attack - if (!self->monsterinfo.attack) - return false; - - if (level.time < self->monsterinfo.attack_finished) - return false; - - if (enemy_range == RANGE_FAR) - return false; - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - chance = 0.4; - } - else if (enemy_range == RANGE_MELEE) - { - chance = 0.8; - } - else if (enemy_range == RANGE_NEAR) - { - chance = 0.4; - } - else if (enemy_range == RANGE_MID) - { - chance = 0.2; - } - else - { - return false; - } - - if (random () < chance) - { - self->monsterinfo.attack_state = AS_MISSILE; - self->monsterinfo.attack_finished = level.time + 2*random(); - return true; - } - - if (self->flags & FL_FLY) - { - if (random() < 0.3) - self->monsterinfo.attack_state = AS_SLIDING; - else - self->monsterinfo.attack_state = AS_STRAIGHT; - } - - return false; -} - - -void MakronPrecache (void); - -/*QUAKED monster_jorg (1 .5 0) (-80 -80 0) (90 90 140) Ambush Trigger_Spawn Sight -*/ -void SP_monster_jorg (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_JORG; - - sound_pain1 = gi.soundindex ("boss3/bs3pain1.wav"); - sound_pain2 = gi.soundindex ("boss3/bs3pain2.wav"); - sound_pain3 = gi.soundindex ("boss3/bs3pain3.wav"); - sound_death = gi.soundindex ("boss3/bs3deth1.wav"); - sound_attack1 = gi.soundindex ("boss3/bs3atck1.wav"); - sound_attack2 = gi.soundindex ("boss3/bs3atck2.wav"); - sound_search1 = gi.soundindex ("boss3/bs3srch1.wav"); - sound_search2 = gi.soundindex ("boss3/bs3srch2.wav"); - sound_search3 = gi.soundindex ("boss3/bs3srch3.wav"); - sound_idle = gi.soundindex ("boss3/bs3idle1.wav"); - sound_step_left = gi.soundindex ("boss3/step1.wav"); - sound_step_right = gi.soundindex ("boss3/step2.wav"); - sound_firegun = gi.soundindex ("boss3/xfire.wav"); - sound_death_hit = gi.soundindex ("boss3/d_hit.wav"); - - MakronPrecache (); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); - self->s.weaponmodel = gi.modelindex ("models/monsters/boss3/jorg/tris.md2"); - VectorSet (self->mins, -80, -80, 0); - VectorSet (self->maxs, 80, 80, 140); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 3000; - if(!self->gib_health) - self->gib_health = -2000; - if(!self->mass) - self->mass = 1000; - - self->pain = jorg_pain; - self->die = jorg_die; - self->monsterinfo.stand = jorg_stand; - self->monsterinfo.walk = jorg_walk; - self->monsterinfo.run = jorg_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = jorg_attack; - self->monsterinfo.search = jorg_search; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = NULL; - self->monsterinfo.checkattack = Jorg_CheckAttack; - gi.linkentity (self); - - self->monsterinfo.currentmove = &jorg_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&jorg_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - self->common_name = "Jorg"; - - walkmonster_start(self); -} diff --git a/server/monsters/m_boss31.h b/server/monsters/m_boss31.h deleted file mode 100644 index e4141592..00000000 --- a/server/monsters/m_boss31.h +++ /dev/null @@ -1,194 +0,0 @@ -// G:\quake2\baseq2\models/monsters/boss3/jorg - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_attak101 0 -#define FRAME_attak102 1 -#define FRAME_attak103 2 -#define FRAME_attak104 3 -#define FRAME_attak105 4 -#define FRAME_attak106 5 -#define FRAME_attak107 6 -#define FRAME_attak108 7 -#define FRAME_attak109 8 -#define FRAME_attak110 9 -#define FRAME_attak111 10 -#define FRAME_attak112 11 -#define FRAME_attak113 12 -#define FRAME_attak114 13 -#define FRAME_attak115 14 -#define FRAME_attak116 15 -#define FRAME_attak117 16 -#define FRAME_attak118 17 -#define FRAME_attak201 18 -#define FRAME_attak202 19 -#define FRAME_attak203 20 -#define FRAME_attak204 21 -#define FRAME_attak205 22 -#define FRAME_attak206 23 -#define FRAME_attak207 24 -#define FRAME_attak208 25 -#define FRAME_attak209 26 -#define FRAME_attak210 27 -#define FRAME_attak211 28 -#define FRAME_attak212 29 -#define FRAME_attak213 30 -#define FRAME_death01 31 -#define FRAME_death02 32 -#define FRAME_death03 33 -#define FRAME_death04 34 -#define FRAME_death05 35 -#define FRAME_death06 36 -#define FRAME_death07 37 -#define FRAME_death08 38 -#define FRAME_death09 39 -#define FRAME_death10 40 -#define FRAME_death11 41 -#define FRAME_death12 42 -#define FRAME_death13 43 -#define FRAME_death14 44 -#define FRAME_death15 45 -#define FRAME_death16 46 -#define FRAME_death17 47 -#define FRAME_death18 48 -#define FRAME_death19 49 -#define FRAME_death20 50 -#define FRAME_death21 51 -#define FRAME_death22 52 -#define FRAME_death23 53 -#define FRAME_death24 54 -#define FRAME_death25 55 -#define FRAME_death26 56 -#define FRAME_death27 57 -#define FRAME_death28 58 -#define FRAME_death29 59 -#define FRAME_death30 60 -#define FRAME_death31 61 -#define FRAME_death32 62 -#define FRAME_death33 63 -#define FRAME_death34 64 -#define FRAME_death35 65 -#define FRAME_death36 66 -#define FRAME_death37 67 -#define FRAME_death38 68 -#define FRAME_death39 69 -#define FRAME_death40 70 -#define FRAME_death41 71 -#define FRAME_death42 72 -#define FRAME_death43 73 -#define FRAME_death44 74 -#define FRAME_death45 75 -#define FRAME_death46 76 -#define FRAME_death47 77 -#define FRAME_death48 78 -#define FRAME_death49 79 -#define FRAME_death50 80 -#define FRAME_pain101 81 -#define FRAME_pain102 82 -#define FRAME_pain103 83 -#define FRAME_pain201 84 -#define FRAME_pain202 85 -#define FRAME_pain203 86 -#define FRAME_pain301 87 -#define FRAME_pain302 88 -#define FRAME_pain303 89 -#define FRAME_pain304 90 -#define FRAME_pain305 91 -#define FRAME_pain306 92 -#define FRAME_pain307 93 -#define FRAME_pain308 94 -#define FRAME_pain309 95 -#define FRAME_pain310 96 -#define FRAME_pain311 97 -#define FRAME_pain312 98 -#define FRAME_pain313 99 -#define FRAME_pain314 100 -#define FRAME_pain315 101 -#define FRAME_pain316 102 -#define FRAME_pain317 103 -#define FRAME_pain318 104 -#define FRAME_pain319 105 -#define FRAME_pain320 106 -#define FRAME_pain321 107 -#define FRAME_pain322 108 -#define FRAME_pain323 109 -#define FRAME_pain324 110 -#define FRAME_pain325 111 -#define FRAME_stand01 112 -#define FRAME_stand02 113 -#define FRAME_stand03 114 -#define FRAME_stand04 115 -#define FRAME_stand05 116 -#define FRAME_stand06 117 -#define FRAME_stand07 118 -#define FRAME_stand08 119 -#define FRAME_stand09 120 -#define FRAME_stand10 121 -#define FRAME_stand11 122 -#define FRAME_stand12 123 -#define FRAME_stand13 124 -#define FRAME_stand14 125 -#define FRAME_stand15 126 -#define FRAME_stand16 127 -#define FRAME_stand17 128 -#define FRAME_stand18 129 -#define FRAME_stand19 130 -#define FRAME_stand20 131 -#define FRAME_stand21 132 -#define FRAME_stand22 133 -#define FRAME_stand23 134 -#define FRAME_stand24 135 -#define FRAME_stand25 136 -#define FRAME_stand26 137 -#define FRAME_stand27 138 -#define FRAME_stand28 139 -#define FRAME_stand29 140 -#define FRAME_stand30 141 -#define FRAME_stand31 142 -#define FRAME_stand32 143 -#define FRAME_stand33 144 -#define FRAME_stand34 145 -#define FRAME_stand35 146 -#define FRAME_stand36 147 -#define FRAME_stand37 148 -#define FRAME_stand38 149 -#define FRAME_stand39 150 -#define FRAME_stand40 151 -#define FRAME_stand41 152 -#define FRAME_stand42 153 -#define FRAME_stand43 154 -#define FRAME_stand44 155 -#define FRAME_stand45 156 -#define FRAME_stand46 157 -#define FRAME_stand47 158 -#define FRAME_stand48 159 -#define FRAME_stand49 160 -#define FRAME_stand50 161 -#define FRAME_stand51 162 -#define FRAME_walk01 163 -#define FRAME_walk02 164 -#define FRAME_walk03 165 -#define FRAME_walk04 166 -#define FRAME_walk05 167 -#define FRAME_walk06 168 -#define FRAME_walk07 169 -#define FRAME_walk08 170 -#define FRAME_walk09 171 -#define FRAME_walk10 172 -#define FRAME_walk11 173 -#define FRAME_walk12 174 -#define FRAME_walk13 175 -#define FRAME_walk14 176 -#define FRAME_walk15 177 -#define FRAME_walk16 178 -#define FRAME_walk17 179 -#define FRAME_walk18 180 -#define FRAME_walk19 181 -#define FRAME_walk20 182 -#define FRAME_walk21 183 -#define FRAME_walk22 184 -#define FRAME_walk23 185 -#define FRAME_walk24 186 -#define FRAME_walk25 187 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_boss32.c b/server/monsters/m_boss32.c deleted file mode 100644 index a0d686eb..00000000 --- a/server/monsters/m_boss32.c +++ /dev/null @@ -1,953 +0,0 @@ -/* -============================================================================== - -Makron -- Final Boss - -============================================================================== -*/ - -#include "g_local.h" -#include "m_boss32.h" - -bool visible (edict_t *self, edict_t *other); - -void MakronRailgun (edict_t *self); -void MakronSaveloc (edict_t *self); -void MakronHyperblaster (edict_t *self); -void makron_step_left (edict_t *self); -void makron_step_right (edict_t *self); -void makronBFG (edict_t *self); -void makron_dead (edict_t *self); - -static int sound_pain4; -static int sound_pain5; -static int sound_pain6; -static int sound_death; -static int sound_step_left; -static int sound_step_right; -static int sound_attack_bfg; -static int sound_brainsplorch; -static int sound_prerailgun; -static int sound_popup; -static int sound_taunt1; -static int sound_taunt2; -static int sound_taunt3; -static int sound_hit; - -void makron_taunt (edict_t *self) -{ - float r; - - r=random(); - if (r <= 0.3) - gi.sound (self, CHAN_AUTO, sound_taunt1, 1, ATTN_NONE, 0); - else if (r <= 0.6) - gi.sound (self, CHAN_AUTO, sound_taunt2, 1, ATTN_NONE, 0); - else - gi.sound (self, CHAN_AUTO, sound_taunt3, 1, ATTN_NONE, 0); -} - -// -// stand -// - -mframe_t makron_frames_stand []= -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 10 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 20 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 30 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 40 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 50 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL // 60 -}; -mmove_t makron_move_stand = {FRAME_stand201, FRAME_stand260, makron_frames_stand, NULL}; - -void makron_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &makron_move_stand; -} - -mframe_t makron_frames_run [] = -{ - ai_run, 3, makron_step_left, - ai_run, 12, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, makron_step_right, - ai_run, 6, NULL, - ai_run, 12, NULL, - ai_run, 9, NULL, - ai_run, 6, NULL, - ai_run, 12, NULL -}; -mmove_t makron_move_run = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL}; - -void makron_hit (edict_t *self) -{ - gi.sound (self, CHAN_AUTO, sound_hit, 1, ATTN_NONE,0); -} - -void makron_popup (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_popup, 1, ATTN_NONE,0); -} - -void makron_step_left (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0); -} - -void makron_step_right (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0); -} - -void makron_brainsplorch (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_brainsplorch, 1, ATTN_NORM,0); -} - -void makron_prerailgun (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM,0); -} - - -mframe_t makron_frames_walk [] = -{ - ai_walk, 3, makron_step_left, - ai_walk, 12, NULL, - ai_walk, 8, NULL, - ai_walk, 8, NULL, - ai_walk, 8, makron_step_right, - ai_walk, 6, NULL, - ai_walk, 12, NULL, - ai_walk, 9, NULL, - ai_walk, 6, NULL, - ai_walk, 12, NULL -}; -mmove_t makron_move_walk = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL}; - -void makron_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &makron_move_walk; -} - -void makron_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &makron_move_stand; - else - self->monsterinfo.currentmove = &makron_move_run; -} - -mframe_t makron_frames_pain6 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 10 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, makron_popup, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 20 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, makron_taunt, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_pain6 = {FRAME_pain601, FRAME_pain627, makron_frames_pain6, makron_run}; - -mframe_t makron_frames_pain5 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_pain5 = {FRAME_pain501, FRAME_pain504, makron_frames_pain5, makron_run}; - -mframe_t makron_frames_pain4 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_pain4 = {FRAME_pain401, FRAME_pain404, makron_frames_pain4, makron_run}; - -mframe_t makron_frames_death2 [] = -{ - ai_move, -15, NULL, - ai_move, 3, NULL, - ai_move, -12, NULL, - ai_move, 0, makron_step_left, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 10 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 11, NULL, - ai_move, 12, NULL, - ai_move, 11, makron_step_right, - ai_move, 0, NULL, - ai_move, 0, NULL, // 20 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 30 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 5, NULL, - ai_move, 7, NULL, - ai_move, 6, makron_step_left, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, 2, NULL, // 40 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 50 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -6, NULL, - ai_move, -4, NULL, - ai_move, -6, makron_step_right, - ai_move, -4, NULL, - ai_move, -4, makron_step_left, - ai_move, 0, NULL, - ai_move, 0, NULL, // 60 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, -5, NULL, - ai_move, -3, makron_step_right, - ai_move, -8, NULL, - ai_move, -3, makron_step_left, - ai_move, -7, NULL, - ai_move, -4, NULL, - ai_move, -4, makron_step_right, // 70 - ai_move, -6, NULL, - ai_move, -7, NULL, - ai_move, 0, makron_step_left, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 80 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, // 90 - ai_move, 27, makron_hit, - ai_move, 26, NULL, - ai_move, 0, makron_brainsplorch, - ai_move, 0, NULL, - ai_move, 0, NULL // 95 -}; -mmove_t makron_move_death2 = {FRAME_death201, FRAME_death295, makron_frames_death2, makron_dead}; - -mframe_t makron_frames_death3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_death3 = {FRAME_death301, FRAME_death320, makron_frames_death3, NULL}; - -mframe_t makron_frames_sight [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_sight= {FRAME_active01, FRAME_active13, makron_frames_sight, makron_run}; - -void makronBFG (edict_t *self) -{ - vec3_t forward, right; - vec3_t start; - vec3_t dir; - vec3_t vec; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_BFG], forward, right, start); - - VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - gi.sound (self, CHAN_VOICE, sound_attack_bfg, 1, ATTN_NORM, 0); - monster_fire_bfg (self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG); -} - - -mframe_t makron_frames_attack3 []= -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, makronBFG, // FIXME: BFG Attack here - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_attack3 = {FRAME_attak301, FRAME_attak308, makron_frames_attack3, makron_run}; - -mframe_t makron_frames_attack4[]= -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, MakronHyperblaster, // fire - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_attack4 = {FRAME_attak401, FRAME_attak426, makron_frames_attack4, makron_run}; - -mframe_t makron_frames_attack5[]= -{ - ai_charge, 0, makron_prerailgun, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, MakronSaveloc, - ai_move, 0, MakronRailgun, // Fire railgun - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t makron_move_attack5 = {FRAME_attak501, FRAME_attak516, makron_frames_attack5, makron_run}; - -void MakronSaveloc (edict_t *self) -{ - VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot - self->pos1[2] += self->enemy->viewheight; -}; - -// FIXME: He's not firing from the proper Z -void MakronRailgun (edict_t *self) -{ - vec3_t start; - vec3_t dir; - vec3_t forward, right; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_RAILGUN_1], forward, right, start); - - // calc direction to where we targted - VectorSubtract (self->pos1, start, dir); - VectorNormalize (dir); - - monster_fire_railgun (self, start, dir, 50, 100, MZ2_MAKRON_RAILGUN_1); -} - -// FIXME: This is all wrong. He's not firing at the proper angles. -void MakronHyperblaster (edict_t *self) -{ - vec3_t dir; - vec3_t vec; - vec3_t start; - vec3_t forward, right; - int flash_number; - - flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405); - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - if (self->enemy) - { - VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - VectorSubtract (vec, start, vec); - vectoangles (vec, vec); - dir[0] = vec[0]; - } - else - { - dir[0] = 0; - } - if (self->s.frame <= FRAME_attak413) - dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413); - else - dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421); - dir[2] = 0; - - AngleVectors (dir, forward, NULL, NULL); - - monster_fire_blaster (self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER); -} - - -void makron_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - // Lessen the chance of him going into his pain frames - if (damage <=25) - if (random()<0.2) - return; - - self->pain_debounce_time = level.time + 3; - if (skill->value == 3) - return; // no pain anims in nightmare - - - if (damage <= 40) - { - gi.sound (self, CHAN_VOICE, sound_pain4, 1, ATTN_NONE,0); - self->monsterinfo.currentmove = &makron_move_pain4; - } - else if (damage <= 110) - { - gi.sound (self, CHAN_VOICE, sound_pain5, 1, ATTN_NONE,0); - self->monsterinfo.currentmove = &makron_move_pain5; - } - else - { - if (damage <= 150) - if (random() <= 0.45) - { - gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0); - self->monsterinfo.currentmove = &makron_move_pain6; - } - else - if (random() <= 0.35) - { - gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0); - self->monsterinfo.currentmove = &makron_move_pain6; - } - } -}; - -void makron_sight(edict_t *self, edict_t *other) -{ - self->monsterinfo.currentmove = &makron_move_sight; -}; - -void makron_attack(edict_t *self) -{ - vec3_t vec; - float range; - float r; - - r = random(); - - VectorSubtract (self->enemy->s.origin, self->s.origin, vec); - range = VectorLength (vec); - - - if (r <= 0.3) - self->monsterinfo.currentmove = &makron_move_attack3; - else if (r <= 0.6) - self->monsterinfo.currentmove = &makron_move_attack4; - else - self->monsterinfo.currentmove = &makron_move_attack5; -} - -/* ---- -Makron Torso. This needs to be spawned in ---- -*/ - -void makron_torso_think (edict_t *self) -{ - if (++self->s.frame < 365) - self->nextthink = level.time + FRAMETIME; - else - { - self->s.frame = 346; - self->nextthink = level.time + FRAMETIME; - } -} - -void makron_torso_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - // check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - for (n= 0; n < 1 /*4*/; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); - G_FreeEdict(self); - return; - } -} - -void makron_torso (edict_t *ent) -{ -// ent->movetype = MOVETYPE_NONE; -// ent->solid = SOLID_NOT; -// VectorSet (ent->mins, -8, -8, 0); -// VectorSet (ent->maxs, 8, 8, 8); - - // Lazarus changes to make makron torso gibbable - ent->movetype = MOVETYPE_NONE; - ent->solid = SOLID_BBOX; - ent->svflags = SVF_DEADMONSTER; - VectorSet (ent->mins, -32, -32, 0); - VectorSet (ent->maxs, 32, 32, 32); - ent->health = -1; - ent->gib_health = -900; - ent->die = makron_torso_die; - ent->takedamage = DAMAGE_YES; - ent->deadflag = DEAD_DEAD; - - ent->s.frame = 346; - ent->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); - ent->think = makron_torso_think; - ent->nextthink = level.time + 2 * FRAMETIME; - ent->s.sound = gi.soundindex ("makron/spine.wav"); - gi.linkentity (ent); -} - - -// -// death -// - -void makron_dead (edict_t *self) -{ - // Lazarus - this is way too big -// VectorSet (self->mins, -60, -60, 0); -// VectorSet (self->maxs, 60, 60, 72); - VectorSet (self->mins, -48, -48, 0); - VectorSet (self->maxs, 48, 48, 32); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); -} - - -void makron_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - edict_t *tempent; - - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - self->s.sound = 0; - // check for gib - if (self->health <= self->gib_health&& !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 1 /*4*/; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); - ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - tempent = G_Spawn(); - VectorCopy (self->s.origin, tempent->s.origin); - VectorCopy (self->s.angles, tempent->s.angles); - tempent->s.origin[1] -= 84; - makron_torso (tempent); - - self->monsterinfo.currentmove = &makron_move_death2; - -} - -bool Makron_CheckAttack (edict_t *self) -{ - vec3_t spot1, spot2; - vec3_t temp; - float chance; - trace_t tr; - bool enemy_infront; - int enemy_range; - float enemy_yaw; - - if (self->enemy->health > 0) - { - // see if any entities are in the way of the shot - VectorCopy (self->s.origin, spot1); - spot1[2] += self->viewheight; - VectorCopy (self->enemy->s.origin, spot2); - spot2[2] += self->enemy->viewheight; - - tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); - - // do we have a clear shot? - if (tr.ent != self->enemy) - return false; - } - - enemy_infront = infront(self, self->enemy); - enemy_range = range(self, self->enemy); - VectorSubtract (self->enemy->s.origin, self->s.origin, temp); - enemy_yaw = vectoyaw(temp); - - self->ideal_yaw = enemy_yaw; - - - // melee attack - if (enemy_range == RANGE_MELEE) - { - if (self->monsterinfo.melee) - self->monsterinfo.attack_state = AS_MELEE; - else - self->monsterinfo.attack_state = AS_MISSILE; - return true; - } - -// missile attack - if (!self->monsterinfo.attack) - return false; - - if (level.time < self->monsterinfo.attack_finished) - return false; - - if (enemy_range == RANGE_FAR) - return false; - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - chance = 0.4; - } - else if (enemy_range == RANGE_MELEE) - { - chance = 0.8; - } - else if (enemy_range == RANGE_NEAR) - { - chance = 0.4; - } - else if (enemy_range == RANGE_MID) - { - chance = 0.2; - } - else - { - return false; - } - - if (random () < chance) - { - self->monsterinfo.attack_state = AS_MISSILE; - self->monsterinfo.attack_finished = level.time + 2*random(); - return true; - } - - if (self->flags & FL_FLY) - { - if (random() < 0.3) - self->monsterinfo.attack_state = AS_SLIDING; - else - self->monsterinfo.attack_state = AS_STRAIGHT; - } - - return false; -} - - -// -// monster_makron -// - -void MakronPrecache (void) -{ - sound_pain4 = gi.soundindex ("makron/pain3.wav"); - sound_pain5 = gi.soundindex ("makron/pain2.wav"); - sound_pain6 = gi.soundindex ("makron/pain1.wav"); - sound_death = gi.soundindex ("makron/death.wav"); - sound_step_left = gi.soundindex ("makron/step1.wav"); - sound_step_right = gi.soundindex ("makron/step2.wav"); - sound_attack_bfg = gi.soundindex ("makron/bfg_fire.wav"); - sound_brainsplorch = gi.soundindex ("makron/brain1.wav"); - sound_prerailgun = gi.soundindex ("makron/rail_up.wav"); - sound_popup = gi.soundindex ("makron/popup.wav"); - sound_taunt1 = gi.soundindex ("makron/voice4.wav"); - sound_taunt2 = gi.soundindex ("makron/voice3.wav"); - sound_taunt3 = gi.soundindex ("makron/voice.wav"); - sound_hit = gi.soundindex ("makron/bhit.wav"); - - gi.modelindex ("models/monsters/boss3/rider/tris.md2"); -} - -/*QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight -*/ -void SP_monster_makron (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_MAKRON; - - MakronPrecache (); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); - VectorSet (self->mins, -30, -30, 0); - VectorSet (self->maxs, 30, 30, 90); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 3000; - - // Lazarus: get around Killed's prevention of health dropping below -999 -// if(!self->gib_health) -// self->gib_health = -2000; - self->gib_health = -900; - if(!self->mass) - self->mass = 500; - - self->pain = makron_pain; - self->die = makron_die; - self->monsterinfo.stand = makron_stand; - self->monsterinfo.walk = makron_walk; - self->monsterinfo.run = makron_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = makron_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = makron_sight; - self->monsterinfo.checkattack = Makron_CheckAttack; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - - gi.linkentity (self); - - self->monsterinfo.currentmove = &makron_move_sight; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&makron_move_death2, - &makron_move_death3, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - walkmonster_start(self); -} - - -/* -================= -MakronSpawn - -================= -*/ -void MakronSpawn (edict_t *self) -{ - vec3_t vec; - edict_t *player; - - SP_monster_makron (self); - - // jump at player - player = level.sight_client; - if (!player) - return; - - VectorSubtract (player->s.origin, self->s.origin, vec); - self->s.angles[YAW] = vectoyaw(vec); - VectorNormalize (vec); - VectorMA (vec3_origin, 400, vec, self->velocity); - self->velocity[2] = 200; - self->groundentity = NULL; -} - -/* -================= -MakronToss - -Jorg is just about dead, so set up to launch Makron out -================= -*/ -void MakronToss (edict_t *self) -{ - edict_t *ent; - - ent = G_Spawn (); - ent->nextthink = level.time + 0.8; - ent->think = MakronSpawn; - ent->target = self->target; - - ent->health = self->health2; - ent->mass = self->mass2; - ent->common_name = "Makron"; - - VectorCopy (self->s.origin, ent->s.origin); - -} diff --git a/server/monsters/m_boss32.h b/server/monsters/m_boss32.h deleted file mode 100644 index 7648fdc2..00000000 --- a/server/monsters/m_boss32.h +++ /dev/null @@ -1,497 +0,0 @@ -// G:\quake2\baseq2\models/monsters/boss3/rider - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_attak101 0 -#define FRAME_attak102 1 -#define FRAME_attak103 2 -#define FRAME_attak104 3 -#define FRAME_attak105 4 -#define FRAME_attak106 5 -#define FRAME_attak107 6 -#define FRAME_attak108 7 -#define FRAME_attak109 8 -#define FRAME_attak110 9 -#define FRAME_attak111 10 -#define FRAME_attak112 11 -#define FRAME_attak113 12 -#define FRAME_attak114 13 -#define FRAME_attak115 14 -#define FRAME_attak116 15 -#define FRAME_attak117 16 -#define FRAME_attak118 17 -#define FRAME_attak201 18 -#define FRAME_attak202 19 -#define FRAME_attak203 20 -#define FRAME_attak204 21 -#define FRAME_attak205 22 -#define FRAME_attak206 23 -#define FRAME_attak207 24 -#define FRAME_attak208 25 -#define FRAME_attak209 26 -#define FRAME_attak210 27 -#define FRAME_attak211 28 -#define FRAME_attak212 29 -#define FRAME_attak213 30 -#define FRAME_death01 31 -#define FRAME_death02 32 -#define FRAME_death03 33 -#define FRAME_death04 34 -#define FRAME_death05 35 -#define FRAME_death06 36 -#define FRAME_death07 37 -#define FRAME_death08 38 -#define FRAME_death09 39 -#define FRAME_death10 40 -#define FRAME_death11 41 -#define FRAME_death12 42 -#define FRAME_death13 43 -#define FRAME_death14 44 -#define FRAME_death15 45 -#define FRAME_death16 46 -#define FRAME_death17 47 -#define FRAME_death18 48 -#define FRAME_death19 49 -#define FRAME_death20 50 -#define FRAME_death21 51 -#define FRAME_death22 52 -#define FRAME_death23 53 -#define FRAME_death24 54 -#define FRAME_death25 55 -#define FRAME_death26 56 -#define FRAME_death27 57 -#define FRAME_death28 58 -#define FRAME_death29 59 -#define FRAME_death30 60 -#define FRAME_death31 61 -#define FRAME_death32 62 -#define FRAME_death33 63 -#define FRAME_death34 64 -#define FRAME_death35 65 -#define FRAME_death36 66 -#define FRAME_death37 67 -#define FRAME_death38 68 -#define FRAME_death39 69 -#define FRAME_death40 70 -#define FRAME_death41 71 -#define FRAME_death42 72 -#define FRAME_death43 73 -#define FRAME_death44 74 -#define FRAME_death45 75 -#define FRAME_death46 76 -#define FRAME_death47 77 -#define FRAME_death48 78 -#define FRAME_death49 79 -#define FRAME_death50 80 -#define FRAME_pain101 81 -#define FRAME_pain102 82 -#define FRAME_pain103 83 -#define FRAME_pain201 84 -#define FRAME_pain202 85 -#define FRAME_pain203 86 -#define FRAME_pain301 87 -#define FRAME_pain302 88 -#define FRAME_pain303 89 -#define FRAME_pain304 90 -#define FRAME_pain305 91 -#define FRAME_pain306 92 -#define FRAME_pain307 93 -#define FRAME_pain308 94 -#define FRAME_pain309 95 -#define FRAME_pain310 96 -#define FRAME_pain311 97 -#define FRAME_pain312 98 -#define FRAME_pain313 99 -#define FRAME_pain314 100 -#define FRAME_pain315 101 -#define FRAME_pain316 102 -#define FRAME_pain317 103 -#define FRAME_pain318 104 -#define FRAME_pain319 105 -#define FRAME_pain320 106 -#define FRAME_pain321 107 -#define FRAME_pain322 108 -#define FRAME_pain323 109 -#define FRAME_pain324 110 -#define FRAME_pain325 111 -#define FRAME_stand01 112 -#define FRAME_stand02 113 -#define FRAME_stand03 114 -#define FRAME_stand04 115 -#define FRAME_stand05 116 -#define FRAME_stand06 117 -#define FRAME_stand07 118 -#define FRAME_stand08 119 -#define FRAME_stand09 120 -#define FRAME_stand10 121 -#define FRAME_stand11 122 -#define FRAME_stand12 123 -#define FRAME_stand13 124 -#define FRAME_stand14 125 -#define FRAME_stand15 126 -#define FRAME_stand16 127 -#define FRAME_stand17 128 -#define FRAME_stand18 129 -#define FRAME_stand19 130 -#define FRAME_stand20 131 -#define FRAME_stand21 132 -#define FRAME_stand22 133 -#define FRAME_stand23 134 -#define FRAME_stand24 135 -#define FRAME_stand25 136 -#define FRAME_stand26 137 -#define FRAME_stand27 138 -#define FRAME_stand28 139 -#define FRAME_stand29 140 -#define FRAME_stand30 141 -#define FRAME_stand31 142 -#define FRAME_stand32 143 -#define FRAME_stand33 144 -#define FRAME_stand34 145 -#define FRAME_stand35 146 -#define FRAME_stand36 147 -#define FRAME_stand37 148 -#define FRAME_stand38 149 -#define FRAME_stand39 150 -#define FRAME_stand40 151 -#define FRAME_stand41 152 -#define FRAME_stand42 153 -#define FRAME_stand43 154 -#define FRAME_stand44 155 -#define FRAME_stand45 156 -#define FRAME_stand46 157 -#define FRAME_stand47 158 -#define FRAME_stand48 159 -#define FRAME_stand49 160 -#define FRAME_stand50 161 -#define FRAME_stand51 162 -#define FRAME_walk01 163 -#define FRAME_walk02 164 -#define FRAME_walk03 165 -#define FRAME_walk04 166 -#define FRAME_walk05 167 -#define FRAME_walk06 168 -#define FRAME_walk07 169 -#define FRAME_walk08 170 -#define FRAME_walk09 171 -#define FRAME_walk10 172 -#define FRAME_walk11 173 -#define FRAME_walk12 174 -#define FRAME_walk13 175 -#define FRAME_walk14 176 -#define FRAME_walk15 177 -#define FRAME_walk16 178 -#define FRAME_walk17 179 -#define FRAME_walk18 180 -#define FRAME_walk19 181 -#define FRAME_walk20 182 -#define FRAME_walk21 183 -#define FRAME_walk22 184 -#define FRAME_walk23 185 -#define FRAME_walk24 186 -#define FRAME_walk25 187 -#define FRAME_active01 188 -#define FRAME_active02 189 -#define FRAME_active03 190 -#define FRAME_active04 191 -#define FRAME_active05 192 -#define FRAME_active06 193 -#define FRAME_active07 194 -#define FRAME_active08 195 -#define FRAME_active09 196 -#define FRAME_active10 197 -#define FRAME_active11 198 -#define FRAME_active12 199 -#define FRAME_active13 200 -#define FRAME_attak301 201 -#define FRAME_attak302 202 -#define FRAME_attak303 203 -#define FRAME_attak304 204 -#define FRAME_attak305 205 -#define FRAME_attak306 206 -#define FRAME_attak307 207 -#define FRAME_attak308 208 -#define FRAME_attak401 209 -#define FRAME_attak402 210 -#define FRAME_attak403 211 -#define FRAME_attak404 212 -#define FRAME_attak405 213 -#define FRAME_attak406 214 -#define FRAME_attak407 215 -#define FRAME_attak408 216 -#define FRAME_attak409 217 -#define FRAME_attak410 218 -#define FRAME_attak411 219 -#define FRAME_attak412 220 -#define FRAME_attak413 221 -#define FRAME_attak414 222 -#define FRAME_attak415 223 -#define FRAME_attak416 224 -#define FRAME_attak417 225 -#define FRAME_attak418 226 -#define FRAME_attak419 227 -#define FRAME_attak420 228 -#define FRAME_attak421 229 -#define FRAME_attak422 230 -#define FRAME_attak423 231 -#define FRAME_attak424 232 -#define FRAME_attak425 233 -#define FRAME_attak426 234 -#define FRAME_attak501 235 -#define FRAME_attak502 236 -#define FRAME_attak503 237 -#define FRAME_attak504 238 -#define FRAME_attak505 239 -#define FRAME_attak506 240 -#define FRAME_attak507 241 -#define FRAME_attak508 242 -#define FRAME_attak509 243 -#define FRAME_attak510 244 -#define FRAME_attak511 245 -#define FRAME_attak512 246 -#define FRAME_attak513 247 -#define FRAME_attak514 248 -#define FRAME_attak515 249 -#define FRAME_attak516 250 -#define FRAME_death201 251 -#define FRAME_death202 252 -#define FRAME_death203 253 -#define FRAME_death204 254 -#define FRAME_death205 255 -#define FRAME_death206 256 -#define FRAME_death207 257 -#define FRAME_death208 258 -#define FRAME_death209 259 -#define FRAME_death210 260 -#define FRAME_death211 261 -#define FRAME_death212 262 -#define FRAME_death213 263 -#define FRAME_death214 264 -#define FRAME_death215 265 -#define FRAME_death216 266 -#define FRAME_death217 267 -#define FRAME_death218 268 -#define FRAME_death219 269 -#define FRAME_death220 270 -#define FRAME_death221 271 -#define FRAME_death222 272 -#define FRAME_death223 273 -#define FRAME_death224 274 -#define FRAME_death225 275 -#define FRAME_death226 276 -#define FRAME_death227 277 -#define FRAME_death228 278 -#define FRAME_death229 279 -#define FRAME_death230 280 -#define FRAME_death231 281 -#define FRAME_death232 282 -#define FRAME_death233 283 -#define FRAME_death234 284 -#define FRAME_death235 285 -#define FRAME_death236 286 -#define FRAME_death237 287 -#define FRAME_death238 288 -#define FRAME_death239 289 -#define FRAME_death240 290 -#define FRAME_death241 291 -#define FRAME_death242 292 -#define FRAME_death243 293 -#define FRAME_death244 294 -#define FRAME_death245 295 -#define FRAME_death246 296 -#define FRAME_death247 297 -#define FRAME_death248 298 -#define FRAME_death249 299 -#define FRAME_death250 300 -#define FRAME_death251 301 -#define FRAME_death252 302 -#define FRAME_death253 303 -#define FRAME_death254 304 -#define FRAME_death255 305 -#define FRAME_death256 306 -#define FRAME_death257 307 -#define FRAME_death258 308 -#define FRAME_death259 309 -#define FRAME_death260 310 -#define FRAME_death261 311 -#define FRAME_death262 312 -#define FRAME_death263 313 -#define FRAME_death264 314 -#define FRAME_death265 315 -#define FRAME_death266 316 -#define FRAME_death267 317 -#define FRAME_death268 318 -#define FRAME_death269 319 -#define FRAME_death270 320 -#define FRAME_death271 321 -#define FRAME_death272 322 -#define FRAME_death273 323 -#define FRAME_death274 324 -#define FRAME_death275 325 -#define FRAME_death276 326 -#define FRAME_death277 327 -#define FRAME_death278 328 -#define FRAME_death279 329 -#define FRAME_death280 330 -#define FRAME_death281 331 -#define FRAME_death282 332 -#define FRAME_death283 333 -#define FRAME_death284 334 -#define FRAME_death285 335 -#define FRAME_death286 336 -#define FRAME_death287 337 -#define FRAME_death288 338 -#define FRAME_death289 339 -#define FRAME_death290 340 -#define FRAME_death291 341 -#define FRAME_death292 342 -#define FRAME_death293 343 -#define FRAME_death294 344 -#define FRAME_death295 345 -#define FRAME_death301 346 -#define FRAME_death302 347 -#define FRAME_death303 348 -#define FRAME_death304 349 -#define FRAME_death305 350 -#define FRAME_death306 351 -#define FRAME_death307 352 -#define FRAME_death308 353 -#define FRAME_death309 354 -#define FRAME_death310 355 -#define FRAME_death311 356 -#define FRAME_death312 357 -#define FRAME_death313 358 -#define FRAME_death314 359 -#define FRAME_death315 360 -#define FRAME_death316 361 -#define FRAME_death317 362 -#define FRAME_death318 363 -#define FRAME_death319 364 -#define FRAME_death320 365 -#define FRAME_jump01 366 -#define FRAME_jump02 367 -#define FRAME_jump03 368 -#define FRAME_jump04 369 -#define FRAME_jump05 370 -#define FRAME_jump06 371 -#define FRAME_jump07 372 -#define FRAME_jump08 373 -#define FRAME_jump09 374 -#define FRAME_jump10 375 -#define FRAME_jump11 376 -#define FRAME_jump12 377 -#define FRAME_jump13 378 -#define FRAME_pain401 379 -#define FRAME_pain402 380 -#define FRAME_pain403 381 -#define FRAME_pain404 382 -#define FRAME_pain501 383 -#define FRAME_pain502 384 -#define FRAME_pain503 385 -#define FRAME_pain504 386 -#define FRAME_pain601 387 -#define FRAME_pain602 388 -#define FRAME_pain603 389 -#define FRAME_pain604 390 -#define FRAME_pain605 391 -#define FRAME_pain606 392 -#define FRAME_pain607 393 -#define FRAME_pain608 394 -#define FRAME_pain609 395 -#define FRAME_pain610 396 -#define FRAME_pain611 397 -#define FRAME_pain612 398 -#define FRAME_pain613 399 -#define FRAME_pain614 400 -#define FRAME_pain615 401 -#define FRAME_pain616 402 -#define FRAME_pain617 403 -#define FRAME_pain618 404 -#define FRAME_pain619 405 -#define FRAME_pain620 406 -#define FRAME_pain621 407 -#define FRAME_pain622 408 -#define FRAME_pain623 409 -#define FRAME_pain624 410 -#define FRAME_pain625 411 -#define FRAME_pain626 412 -#define FRAME_pain627 413 -#define FRAME_stand201 414 -#define FRAME_stand202 415 -#define FRAME_stand203 416 -#define FRAME_stand204 417 -#define FRAME_stand205 418 -#define FRAME_stand206 419 -#define FRAME_stand207 420 -#define FRAME_stand208 421 -#define FRAME_stand209 422 -#define FRAME_stand210 423 -#define FRAME_stand211 424 -#define FRAME_stand212 425 -#define FRAME_stand213 426 -#define FRAME_stand214 427 -#define FRAME_stand215 428 -#define FRAME_stand216 429 -#define FRAME_stand217 430 -#define FRAME_stand218 431 -#define FRAME_stand219 432 -#define FRAME_stand220 433 -#define FRAME_stand221 434 -#define FRAME_stand222 435 -#define FRAME_stand223 436 -#define FRAME_stand224 437 -#define FRAME_stand225 438 -#define FRAME_stand226 439 -#define FRAME_stand227 440 -#define FRAME_stand228 441 -#define FRAME_stand229 442 -#define FRAME_stand230 443 -#define FRAME_stand231 444 -#define FRAME_stand232 445 -#define FRAME_stand233 446 -#define FRAME_stand234 447 -#define FRAME_stand235 448 -#define FRAME_stand236 449 -#define FRAME_stand237 450 -#define FRAME_stand238 451 -#define FRAME_stand239 452 -#define FRAME_stand240 453 -#define FRAME_stand241 454 -#define FRAME_stand242 455 -#define FRAME_stand243 456 -#define FRAME_stand244 457 -#define FRAME_stand245 458 -#define FRAME_stand246 459 -#define FRAME_stand247 460 -#define FRAME_stand248 461 -#define FRAME_stand249 462 -#define FRAME_stand250 463 -#define FRAME_stand251 464 -#define FRAME_stand252 465 -#define FRAME_stand253 466 -#define FRAME_stand254 467 -#define FRAME_stand255 468 -#define FRAME_stand256 469 -#define FRAME_stand257 470 -#define FRAME_stand258 471 -#define FRAME_stand259 472 -#define FRAME_stand260 473 -#define FRAME_walk201 474 -#define FRAME_walk202 475 -#define FRAME_walk203 476 -#define FRAME_walk204 477 -#define FRAME_walk205 478 -#define FRAME_walk206 479 -#define FRAME_walk207 480 -#define FRAME_walk208 481 -#define FRAME_walk209 482 -#define FRAME_walk210 483 -#define FRAME_walk211 484 -#define FRAME_walk212 485 -#define FRAME_walk213 486 -#define FRAME_walk214 487 -#define FRAME_walk215 488 -#define FRAME_walk216 489 -#define FRAME_walk217 490 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_brain.c b/server/monsters/m_brain.c deleted file mode 100644 index 4b77e349..00000000 --- a/server/monsters/m_brain.c +++ /dev/null @@ -1,689 +0,0 @@ -/* -============================================================================== - -brain - -============================================================================== -*/ - -#include "g_local.h" -#include "m_brain.h" - - -static int sound_chest_open; -static int sound_tentacles_extend; -static int sound_tentacles_retract; -static int sound_death; -static int sound_idle1; -static int sound_idle2; -static int sound_idle3; -static int sound_pain1; -static int sound_pain2; -static int sound_sight; -static int sound_search; -static int sound_melee1; -static int sound_melee2; -static int sound_melee3; - - -void brain_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void brain_search (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); -} - - -void brain_run (edict_t *self); -void brain_dead (edict_t *self); - - -// -// STAND -// - -mframe_t brain_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t brain_move_stand = {FRAME_stand01, FRAME_stand30, brain_frames_stand, NULL}; - -void brain_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &brain_move_stand; -} - - -// -// IDLE -// - -mframe_t brain_frames_idle [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t brain_move_idle = {FRAME_stand31, FRAME_stand60, brain_frames_idle, brain_stand}; - -void brain_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_AUTO, sound_idle3, 1, ATTN_IDLE, 0); - self->monsterinfo.currentmove = &brain_move_idle; -} - - -// -// WALK -// -mframe_t brain_frames_walk1 [] = -{ - ai_walk, 7, NULL, - ai_walk, 2, NULL, - ai_walk, 3, NULL, - ai_walk, 3, NULL, - ai_walk, 1, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 9, NULL, - ai_walk, -4, NULL, - ai_walk, -1, NULL, - ai_walk, 2, NULL -}; -mmove_t brain_move_walk1 = {FRAME_walk101, FRAME_walk111, brain_frames_walk1, NULL}; - -// walk2 is FUBAR, do not use -#if 0 -void brain_walk2_cycle (edict_t *self) -{ - if (random() > 0.1) - self->monsterinfo.nextframe = FRAME_walk220; -} - -mframe_t brain_frames_walk2 [] = -{ - ai_walk, 3, NULL, - ai_walk, -2, NULL, - ai_walk, -4, NULL, - ai_walk, -3, NULL, - ai_walk, 0, NULL, - ai_walk, 1, NULL, - ai_walk, 12, NULL, - ai_walk, 0, NULL, - ai_walk, -3, NULL, - ai_walk, 0, NULL, - - ai_walk, -2, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 1, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 10, NULL, // Cycle Start - - ai_walk, -1, NULL, - ai_walk, 7, NULL, - ai_walk, 0, NULL, - ai_walk, 3, NULL, - ai_walk, -3, NULL, - ai_walk, 2, NULL, - ai_walk, 4, NULL, - ai_walk, -3, NULL, - ai_walk, 2, NULL, - ai_walk, 0, NULL, - - ai_walk, 4, brain_walk2_cycle, - ai_walk, -1, NULL, - ai_walk, -1, NULL, - ai_walk, -8, NULL, - ai_walk, 0, NULL, - ai_walk, 1, NULL, - ai_walk, 5, NULL, - ai_walk, 2, NULL, - ai_walk, -1, NULL, - ai_walk, -5, NULL -}; -mmove_t brain_move_walk2 = {FRAME_walk201, FRAME_walk240, brain_frames_walk2, NULL}; -#endif - -void brain_walk (edict_t *self) -{ -// if (random() <= 0.5) - self->monsterinfo.currentmove = &brain_move_walk1; -// else -// self->monsterinfo.currentmove = &brain_move_walk2; -} - - - -mframe_t brain_frames_defense [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t brain_move_defense = {FRAME_defens01, FRAME_defens08, brain_frames_defense, NULL}; - -mframe_t brain_frames_pain3 [] = -{ - ai_move, -2, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 3, NULL, - ai_move, 0, NULL, - ai_move, -4, NULL -}; -mmove_t brain_move_pain3 = {FRAME_pain301, FRAME_pain306, brain_frames_pain3, brain_run}; - -mframe_t brain_frames_pain2 [] = -{ - ai_move, -2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 3, NULL, - ai_move, 1, NULL, - ai_move, -2, NULL -}; -mmove_t brain_move_pain2 = {FRAME_pain201, FRAME_pain208, brain_frames_pain2, brain_run}; - -mframe_t brain_frames_pain1 [] = -{ - ai_move, -6, NULL, - ai_move, -2, NULL, - ai_move, -6, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 7, NULL, - ai_move, 0, NULL, - ai_move, 3, NULL, - ai_move, -1, NULL -}; -mmove_t brain_move_pain1 = {FRAME_pain101, FRAME_pain121, brain_frames_pain1, brain_run}; - - -// -// DUCK -// - -void brain_duck_down (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - self->monsterinfo.aiflags |= AI_DUCKED; - self->maxs[2] -= 32; - self->takedamage = DAMAGE_YES; - gi.linkentity (self); -} - -void brain_duck_hold (edict_t *self) -{ - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -void brain_duck_up (edict_t *self) -{ - self->monsterinfo.aiflags &= ~AI_DUCKED; - self->maxs[2] += 32; - self->takedamage = DAMAGE_AIM; - gi.linkentity (self); -} - -mframe_t brain_frames_duck [] = -{ - ai_move, 0, NULL, - ai_move, -2, brain_duck_down, - ai_move, 17, brain_duck_hold, - ai_move, -3, NULL, - ai_move, -1, brain_duck_up, - ai_move, -5, NULL, - ai_move, -6, NULL, - ai_move, -6, NULL -}; -mmove_t brain_move_duck = {FRAME_duck01, FRAME_duck08, brain_frames_duck, brain_run}; - -void brain_dodge (edict_t *self, edict_t *attacker, float eta) -{ - if (random() > 0.25) - return; - - if (!self->enemy) - self->enemy = attacker; - - self->monsterinfo.pausetime = level.time + eta + 0.5; - self->monsterinfo.currentmove = &brain_move_duck; -} - -mframe_t brain_frames_death2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 9, NULL, - ai_move, 0, NULL -}; -mmove_t brain_move_death2 = {FRAME_death201, FRAME_death205, brain_frames_death2, brain_dead}; - -mframe_t brain_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, 9, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t brain_move_death1 = {FRAME_death101, FRAME_death118, brain_frames_death1, brain_dead}; - - -// -// MELEE -// - -void brain_swing_right (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_melee1, 1, ATTN_NORM, 0); -} - -void brain_hit_right (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8); - if (fire_hit (self, aim, (15 + (rand() %5)), 40)) - gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0); -} - -void brain_swing_left (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_melee2, 1, ATTN_NORM, 0); -} - -void brain_hit_left (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8); - if (fire_hit (self, aim, (15 + (rand() %5)), 40)) - gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0); -} - -mframe_t brain_frames_attack1 [] = -{ - ai_charge, 8, NULL, - ai_charge, 3, NULL, - ai_charge, 5, NULL, - ai_charge, 0, NULL, - ai_charge, -3, brain_swing_right, - ai_charge, 0, NULL, - ai_charge, -5, NULL, - ai_charge, -7, brain_hit_right, - ai_charge, 0, NULL, - ai_charge, 6, brain_swing_left, - ai_charge, 1, NULL, - ai_charge, 2, brain_hit_left, - ai_charge, -3, NULL, - ai_charge, 6, NULL, - ai_charge, -1, NULL, - ai_charge, -3, NULL, - ai_charge, 2, NULL, - ai_charge, -11,NULL -}; -mmove_t brain_move_attack1 = {FRAME_attak101, FRAME_attak118, brain_frames_attack1, brain_run}; - -void brain_chest_open (edict_t *self) -{ - self->spawnflags &= ~65536; - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - gi.sound (self, CHAN_BODY, sound_chest_open, 1, ATTN_NORM, 0); -} - -void brain_tentacle_attack (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, 0, 8); - if (fire_hit (self, aim, (10 + (rand() %5)), -600) && skill->value > 0) - self->spawnflags |= 65536; - gi.sound (self, CHAN_WEAPON, sound_tentacles_retract, 1, ATTN_NORM, 0); -} - -void brain_chest_closed (edict_t *self) -{ - self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; - if (self->spawnflags & 65536) - { - self->spawnflags &= ~65536; - self->monsterinfo.currentmove = &brain_move_attack1; - } -} - -mframe_t brain_frames_attack2 [] = -{ - ai_charge, 5, NULL, - ai_charge, -4, NULL, - ai_charge, -4, NULL, - ai_charge, -3, NULL, - ai_charge, 0, brain_chest_open, - ai_charge, 0, NULL, - ai_charge, 13, brain_tentacle_attack, - ai_charge, 0, NULL, - ai_charge, 2, NULL, - ai_charge, 0, NULL, - ai_charge, -9, brain_chest_closed, - ai_charge, 0, NULL, - ai_charge, 4, NULL, - ai_charge, 3, NULL, - ai_charge, 2, NULL, - ai_charge, -3, NULL, - ai_charge, -6, NULL -}; -mmove_t brain_move_attack2 = {FRAME_attak201, FRAME_attak217, brain_frames_attack2, brain_run}; - -void brain_melee(edict_t *self) -{ - if (random() <= 0.5) - self->monsterinfo.currentmove = &brain_move_attack1; - else - self->monsterinfo.currentmove = &brain_move_attack2; -} - - -// -// RUN -// - -mframe_t brain_frames_run [] = -{ - ai_run, 9, NULL, - ai_run, 2, NULL, - ai_run, 3, NULL, - ai_run, 3, NULL, - ai_run, 1, NULL, - ai_run, 0, NULL, - ai_run, 0, NULL, - ai_run, 10, NULL, - ai_run, -4, NULL, - ai_run, -1, NULL, - ai_run, 2, NULL -}; -mmove_t brain_move_run = {FRAME_walk101, FRAME_walk111, brain_frames_run, NULL}; - -void brain_run (edict_t *self) -{ - self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &brain_move_stand; - else - self->monsterinfo.currentmove = &brain_move_run; -} - - -void brain_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - float r; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - if (skill->value == 3) - return; // no pain anims in nightmare - - r = random(); - if (r < 0.33) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &brain_move_pain1; - } - else if (r < 0.66) - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &brain_move_pain2; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &brain_move_pain3; - } -} - -void brain_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - - - -void brain_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->s.effects = 0; - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - if (random() <= 0.5) - self->monsterinfo.currentmove = &brain_move_death1; - else - self->monsterinfo.currentmove = &brain_move_death2; -} - -/*QUAKED monster_brain (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_brain (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_BRAIN; - - sound_chest_open = gi.soundindex ("brain/brnatck1.wav"); - sound_tentacles_extend = gi.soundindex ("brain/brnatck2.wav"); - sound_tentacles_retract = gi.soundindex ("brain/brnatck3.wav"); - sound_death = gi.soundindex ("brain/brndeth1.wav"); - sound_idle1 = gi.soundindex ("brain/brnidle1.wav"); - sound_idle2 = gi.soundindex ("brain/brnidle2.wav"); - sound_idle3 = gi.soundindex ("brain/brnlens1.wav"); - sound_pain1 = gi.soundindex ("brain/brnpain1.wav"); - sound_pain2 = gi.soundindex ("brain/brnpain2.wav"); - sound_sight = gi.soundindex ("brain/brnsght1.wav"); - sound_search = gi.soundindex ("brain/brnsrch1.wav"); - sound_melee1 = gi.soundindex ("brain/melee1.wav"); - sound_melee2 = gi.soundindex ("brain/melee2.wav"); - sound_melee3 = gi.soundindex ("brain/melee3.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/brain/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/brain/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 300; - if(!self->gib_health) - self->gib_health = -150; - if(!self->mass) - self->mass = 400; - - self->pain = brain_pain; - self->die = brain_die; - - self->monsterinfo.stand = brain_stand; - self->monsterinfo.walk = brain_walk; - self->monsterinfo.run = brain_run; - self->monsterinfo.dodge = brain_dodge; -// self->monsterinfo.attack = brain_attack; - self->monsterinfo.melee = brain_melee; - self->monsterinfo.sight = brain_sight; - self->monsterinfo.search = brain_search; - self->monsterinfo.idle = brain_idle; - - self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; - self->monsterinfo.power_armor_power = 100; - - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.10; - self->common_name = "Brains"; - - gi.linkentity (self); - - self->monsterinfo.currentmove = &brain_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&brain_move_death1, - &brain_move_death2, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - - walkmonster_start (self); -} diff --git a/server/monsters/m_brain.h b/server/monsters/m_brain.h deleted file mode 100644 index a23e8abc..00000000 --- a/server/monsters/m_brain.h +++ /dev/null @@ -1,228 +0,0 @@ -// G:\quake2\baseq2\models/monsters/brain - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_walk101 0 -#define FRAME_walk102 1 -#define FRAME_walk103 2 -#define FRAME_walk104 3 -#define FRAME_walk105 4 -#define FRAME_walk106 5 -#define FRAME_walk107 6 -#define FRAME_walk108 7 -#define FRAME_walk109 8 -#define FRAME_walk110 9 -#define FRAME_walk111 10 -#define FRAME_walk112 11 -#define FRAME_walk113 12 -#define FRAME_walk201 13 -#define FRAME_walk202 14 -#define FRAME_walk203 15 -#define FRAME_walk204 16 -#define FRAME_walk205 17 -#define FRAME_walk206 18 -#define FRAME_walk207 19 -#define FRAME_walk208 20 -#define FRAME_walk209 21 -#define FRAME_walk210 22 -#define FRAME_walk211 23 -#define FRAME_walk212 24 -#define FRAME_walk213 25 -#define FRAME_walk214 26 -#define FRAME_walk215 27 -#define FRAME_walk216 28 -#define FRAME_walk217 29 -#define FRAME_walk218 30 -#define FRAME_walk219 31 -#define FRAME_walk220 32 -#define FRAME_walk221 33 -#define FRAME_walk222 34 -#define FRAME_walk223 35 -#define FRAME_walk224 36 -#define FRAME_walk225 37 -#define FRAME_walk226 38 -#define FRAME_walk227 39 -#define FRAME_walk228 40 -#define FRAME_walk229 41 -#define FRAME_walk230 42 -#define FRAME_walk231 43 -#define FRAME_walk232 44 -#define FRAME_walk233 45 -#define FRAME_walk234 46 -#define FRAME_walk235 47 -#define FRAME_walk236 48 -#define FRAME_walk237 49 -#define FRAME_walk238 50 -#define FRAME_walk239 51 -#define FRAME_walk240 52 -#define FRAME_attak101 53 -#define FRAME_attak102 54 -#define FRAME_attak103 55 -#define FRAME_attak104 56 -#define FRAME_attak105 57 -#define FRAME_attak106 58 -#define FRAME_attak107 59 -#define FRAME_attak108 60 -#define FRAME_attak109 61 -#define FRAME_attak110 62 -#define FRAME_attak111 63 -#define FRAME_attak112 64 -#define FRAME_attak113 65 -#define FRAME_attak114 66 -#define FRAME_attak115 67 -#define FRAME_attak116 68 -#define FRAME_attak117 69 -#define FRAME_attak118 70 -#define FRAME_attak201 71 -#define FRAME_attak202 72 -#define FRAME_attak203 73 -#define FRAME_attak204 74 -#define FRAME_attak205 75 -#define FRAME_attak206 76 -#define FRAME_attak207 77 -#define FRAME_attak208 78 -#define FRAME_attak209 79 -#define FRAME_attak210 80 -#define FRAME_attak211 81 -#define FRAME_attak212 82 -#define FRAME_attak213 83 -#define FRAME_attak214 84 -#define FRAME_attak215 85 -#define FRAME_attak216 86 -#define FRAME_attak217 87 -#define FRAME_pain101 88 -#define FRAME_pain102 89 -#define FRAME_pain103 90 -#define FRAME_pain104 91 -#define FRAME_pain105 92 -#define FRAME_pain106 93 -#define FRAME_pain107 94 -#define FRAME_pain108 95 -#define FRAME_pain109 96 -#define FRAME_pain110 97 -#define FRAME_pain111 98 -#define FRAME_pain112 99 -#define FRAME_pain113 100 -#define FRAME_pain114 101 -#define FRAME_pain115 102 -#define FRAME_pain116 103 -#define FRAME_pain117 104 -#define FRAME_pain118 105 -#define FRAME_pain119 106 -#define FRAME_pain120 107 -#define FRAME_pain121 108 -#define FRAME_pain201 109 -#define FRAME_pain202 110 -#define FRAME_pain203 111 -#define FRAME_pain204 112 -#define FRAME_pain205 113 -#define FRAME_pain206 114 -#define FRAME_pain207 115 -#define FRAME_pain208 116 -#define FRAME_pain301 117 -#define FRAME_pain302 118 -#define FRAME_pain303 119 -#define FRAME_pain304 120 -#define FRAME_pain305 121 -#define FRAME_pain306 122 -#define FRAME_death101 123 -#define FRAME_death102 124 -#define FRAME_death103 125 -#define FRAME_death104 126 -#define FRAME_death105 127 -#define FRAME_death106 128 -#define FRAME_death107 129 -#define FRAME_death108 130 -#define FRAME_death109 131 -#define FRAME_death110 132 -#define FRAME_death111 133 -#define FRAME_death112 134 -#define FRAME_death113 135 -#define FRAME_death114 136 -#define FRAME_death115 137 -#define FRAME_death116 138 -#define FRAME_death117 139 -#define FRAME_death118 140 -#define FRAME_death201 141 -#define FRAME_death202 142 -#define FRAME_death203 143 -#define FRAME_death204 144 -#define FRAME_death205 145 -#define FRAME_duck01 146 -#define FRAME_duck02 147 -#define FRAME_duck03 148 -#define FRAME_duck04 149 -#define FRAME_duck05 150 -#define FRAME_duck06 151 -#define FRAME_duck07 152 -#define FRAME_duck08 153 -#define FRAME_defens01 154 -#define FRAME_defens02 155 -#define FRAME_defens03 156 -#define FRAME_defens04 157 -#define FRAME_defens05 158 -#define FRAME_defens06 159 -#define FRAME_defens07 160 -#define FRAME_defens08 161 -#define FRAME_stand01 162 -#define FRAME_stand02 163 -#define FRAME_stand03 164 -#define FRAME_stand04 165 -#define FRAME_stand05 166 -#define FRAME_stand06 167 -#define FRAME_stand07 168 -#define FRAME_stand08 169 -#define FRAME_stand09 170 -#define FRAME_stand10 171 -#define FRAME_stand11 172 -#define FRAME_stand12 173 -#define FRAME_stand13 174 -#define FRAME_stand14 175 -#define FRAME_stand15 176 -#define FRAME_stand16 177 -#define FRAME_stand17 178 -#define FRAME_stand18 179 -#define FRAME_stand19 180 -#define FRAME_stand20 181 -#define FRAME_stand21 182 -#define FRAME_stand22 183 -#define FRAME_stand23 184 -#define FRAME_stand24 185 -#define FRAME_stand25 186 -#define FRAME_stand26 187 -#define FRAME_stand27 188 -#define FRAME_stand28 189 -#define FRAME_stand29 190 -#define FRAME_stand30 191 -#define FRAME_stand31 192 -#define FRAME_stand32 193 -#define FRAME_stand33 194 -#define FRAME_stand34 195 -#define FRAME_stand35 196 -#define FRAME_stand36 197 -#define FRAME_stand37 198 -#define FRAME_stand38 199 -#define FRAME_stand39 200 -#define FRAME_stand40 201 -#define FRAME_stand41 202 -#define FRAME_stand42 203 -#define FRAME_stand43 204 -#define FRAME_stand44 205 -#define FRAME_stand45 206 -#define FRAME_stand46 207 -#define FRAME_stand47 208 -#define FRAME_stand48 209 -#define FRAME_stand49 210 -#define FRAME_stand50 211 -#define FRAME_stand51 212 -#define FRAME_stand52 213 -#define FRAME_stand53 214 -#define FRAME_stand54 215 -#define FRAME_stand55 216 -#define FRAME_stand56 217 -#define FRAME_stand57 218 -#define FRAME_stand58 219 -#define FRAME_stand59 220 -#define FRAME_stand60 221 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_chick.c b/server/monsters/m_chick.c deleted file mode 100644 index c5a5cb5d..00000000 --- a/server/monsters/m_chick.c +++ /dev/null @@ -1,782 +0,0 @@ -/* -============================================================================== - -chick - -============================================================================== -*/ - -#include "g_local.h" -#include "m_chick.h" - -bool visible (edict_t *self, edict_t *other); - -void chick_stand (edict_t *self); -void chick_run (edict_t *self); -void chick_reslash(edict_t *self); -void chick_rerocket(edict_t *self); -void chick_attack1(edict_t *self); - -static int sound_missile_prelaunch; -static int sound_missile_launch; -static int sound_melee_swing; -static int sound_melee_hit; -static int sound_missile_reload; -static int sound_death1; -static int sound_death2; -static int sound_fall_down; -static int sound_idle1; -static int sound_idle2; -static int sound_pain1; -static int sound_pain2; -static int sound_pain3; -static int sound_sight; -static int sound_search; - - -void ChickMoan (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - { - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); - else - gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0); - } -} - -mframe_t chick_frames_fidget [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, ChickMoan, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t chick_move_fidget = {FRAME_stand201, FRAME_stand230, chick_frames_fidget, chick_stand}; - -void chick_fidget (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - return; - if (random() <= 0.3) - self->monsterinfo.currentmove = &chick_move_fidget; -} - -mframe_t chick_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, chick_fidget, - -}; -mmove_t chick_move_stand = {FRAME_stand101, FRAME_stand130, chick_frames_stand, NULL}; - -void chick_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &chick_move_stand; -} - -mframe_t chick_frames_start_run [] = -{ - ai_run, 1, NULL, - ai_run, 0, NULL, - ai_run, 0, NULL, - ai_run, -1, NULL, - ai_run, -1, NULL, - ai_run, 0, NULL, - ai_run, 1, NULL, - ai_run, 3, NULL, - ai_run, 6, NULL, - ai_run, 3, NULL -}; -mmove_t chick_move_start_run = {FRAME_walk01, FRAME_walk10, chick_frames_start_run, chick_run}; - -mframe_t chick_frames_run [] = -{ - ai_run, 6, NULL, - ai_run, 8, NULL, - ai_run, 13, NULL, - ai_run, 5, NULL, - ai_run, 7, NULL, - ai_run, 4, NULL, - ai_run, 11, NULL, - ai_run, 5, NULL, - ai_run, 9, NULL, - ai_run, 7, NULL - -}; - -mmove_t chick_move_run = {FRAME_walk11, FRAME_walk20, chick_frames_run, NULL}; - -mframe_t chick_frames_walk [] = -{ - ai_walk, 6, NULL, - ai_walk, 8, NULL, - ai_walk, 13, NULL, - ai_walk, 5, NULL, - ai_walk, 7, NULL, - ai_walk, 4, NULL, - ai_walk, 11, NULL, - ai_walk, 5, NULL, - ai_walk, 9, NULL, - ai_walk, 7, NULL -}; - -mmove_t chick_move_walk = {FRAME_walk11, FRAME_walk20, chick_frames_walk, NULL}; - -void chick_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &chick_move_walk; -} - -void chick_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - self->monsterinfo.currentmove = &chick_move_stand; - return; - } - - if (self->monsterinfo.currentmove == &chick_move_walk || - self->monsterinfo.currentmove == &chick_move_start_run) - { - self->monsterinfo.currentmove = &chick_move_run; - } - else - { - self->monsterinfo.currentmove = &chick_move_start_run; - } -} - -mframe_t chick_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t chick_move_pain1 = {FRAME_pain101, FRAME_pain105, chick_frames_pain1, chick_run}; - -mframe_t chick_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t chick_move_pain2 = {FRAME_pain201, FRAME_pain205, chick_frames_pain2, chick_run}; - -mframe_t chick_frames_pain3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -6, NULL, - ai_move, 3, NULL, - ai_move, 11, NULL, - ai_move, 3, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 4, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, -3, NULL, - ai_move, -4, NULL, - ai_move, 5, NULL, - ai_move, 7, NULL, - ai_move, -2, NULL, - ai_move, 3, NULL, - ai_move, -5, NULL, - ai_move, -2, NULL, - ai_move, -8, NULL, - ai_move, 2, NULL -}; -mmove_t chick_move_pain3 = {FRAME_pain301, FRAME_pain321, chick_frames_pain3, chick_run}; - -void chick_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - float r; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - r = random(); - if (r < 0.33) - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - else if (r < 0.66) - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (damage <= 10) - self->monsterinfo.currentmove = &chick_move_pain1; - else if (damage <= 25) - self->monsterinfo.currentmove = &chick_move_pain2; - else - self->monsterinfo.currentmove = &chick_move_pain3; -} - -void chick_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, 0); - VectorSet (self->maxs, 16, 16, 16); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t chick_frames_death2 [] = -{ - ai_move, -6, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -5, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -2, NULL, - ai_move, 1, NULL, - ai_move, 10, NULL, - ai_move, 2, NULL, - ai_move, 3, NULL, - ai_move, 1, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 3, NULL, - ai_move, 3, NULL, - ai_move, 1, NULL, - ai_move, -3, NULL, - ai_move, -5, NULL, - ai_move, 4, NULL, - ai_move, 15, NULL, - ai_move, 14, NULL, - ai_move, 1, NULL -}; -mmove_t chick_move_death2 = {FRAME_death201, FRAME_death223, chick_frames_death2, chick_dead}; - -mframe_t chick_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -7, NULL, - ai_move, 4, NULL, - ai_move, 11, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL - -}; -mmove_t chick_move_death1 = {FRAME_death101, FRAME_death112, chick_frames_death1, chick_dead}; - -void chick_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - n = rand() % 2; - if (n == 0) - { - self->monsterinfo.currentmove = &chick_move_death1; - gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); - } - else - { - self->monsterinfo.currentmove = &chick_move_death2; - gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); - } -} - - -void chick_duck_down (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - self->monsterinfo.aiflags |= AI_DUCKED; - self->maxs[2] -= 32; - self->takedamage = DAMAGE_YES; - self->monsterinfo.pausetime = level.time + 1; - gi.linkentity (self); -} - -void chick_duck_hold (edict_t *self) -{ - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -void chick_duck_up (edict_t *self) -{ - self->monsterinfo.aiflags &= ~AI_DUCKED; - self->maxs[2] += 32; - self->takedamage = DAMAGE_AIM; - gi.linkentity (self); -} - -mframe_t chick_frames_duck [] = -{ - ai_move, 0, chick_duck_down, - ai_move, 1, NULL, - ai_move, 4, chick_duck_hold, - ai_move, -4, NULL, - ai_move, -5, chick_duck_up, - ai_move, 3, NULL, - ai_move, 1, NULL -}; -mmove_t chick_move_duck = {FRAME_duck01, FRAME_duck07, chick_frames_duck, chick_run}; - -void chick_dodge (edict_t *self, edict_t *attacker, float eta) -{ - if (random() > 0.25) - return; - - if (!self->enemy) - self->enemy = attacker; - - self->monsterinfo.currentmove = &chick_move_duck; -} - -void ChickSlash (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->mins[0], 10); - gi.sound (self, CHAN_WEAPON, sound_melee_swing, 1, ATTN_NORM, 0); - fire_hit (self, aim, (10 + (rand() %6)), 100); -} - - -void ChickRocket (edict_t *self) -{ - // DWH: Added skill level-dependent rocket speed, leading target, suicide prevention, - // target elevation dependent target location, and homing rockets - - trace_t trace; - vec3_t forward, right; - vec3_t start; - vec3_t dir; - vec3_t vec; - int rocketSpeed; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_CHICK_ROCKET_1], forward, right, start); - - if((self->spawnflags & SF_MONSTER_SPECIAL)) - rocketSpeed = 400; // DWH: Homing rockets are tougher if slow - else - rocketSpeed = 500 + (100 * skill->value); // PGM rock & roll.... :) - - if(visible(self,self->enemy)) - { - VectorCopy (self->enemy->s.origin, vec); - if(!(self->enemy->flags & FL_REFLECT)) - { - if(random() < 0.66 || (start[2] < self->enemy->absmin[2])) - vec[2] += self->enemy->viewheight; - else - vec[2] = self->enemy->absmin[2]; - } - VectorSubtract (vec, start, dir); - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - // lead target, but not if using homers - // 20, 35, 50, 65 chance of leading - // DWH: Switched this around from Rogue code... it led target more often - // for Easy, which seemed backwards - if( (random() < (0.2 + skill->value * 0.15) ) && !(self->spawnflags & SF_MONSTER_SPECIAL)) - { - float dist; - float time; - - dist = VectorLength (dir); - time = dist/rocketSpeed; - VectorMA(vec, time, self->enemy->velocity, vec); - VectorSubtract(vec, start, dir); - } - } - else - { - // Fire at feet of last known position - VectorCopy(self->monsterinfo.last_sighting,vec); - vec[2] += self->enemy->mins[2]; - VectorSubtract(vec,start,dir); - } - - VectorNormalize(dir); - - if(self->enemy->flags & FL_REFLECT) - { - // If forcing chick to shoot at reflection, go ahead - monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); - } - else - { - // paranoia, make sure we're not shooting a target right next to us - trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); - if(trace.ent == self->enemy || trace.ent == world) - { - VectorSubtract(trace.endpos,start,vec); - if(VectorLength(vec) > MELEE_DISTANCE) - { - if(trace.fraction > 0.5 || (trace.ent && trace.ent->client)) - monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); - } - } - } -} - -void Chick_PreAttack1 (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_missile_prelaunch, 1, ATTN_NORM, 0); -} - -void ChickReload (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0); -} - -void chick_skip_frames (edict_t *self) -{ - if(skill->value >= 1) - { - if(self->s.frame == FRAME_attak102) - self->s.frame = FRAME_attak103; - if(self->s.frame == FRAME_attak105) - self->s.frame = FRAME_attak106; - } - if(skill->value > 1) - if(self->s.frame == FRAME_attak109) - self->s.frame = FRAME_attak112; -} - -mframe_t chick_frames_start_attack1 [] = -{ - ai_charge, 0, Chick_PreAttack1, - ai_charge, 0, chick_skip_frames, - ai_charge, 0, chick_skip_frames, - ai_charge, 4, chick_skip_frames, - ai_charge, 0, chick_skip_frames, - ai_charge, -3, chick_skip_frames, - ai_charge, 3, chick_skip_frames, - ai_charge, 5, chick_skip_frames, - ai_charge, 7, chick_skip_frames, - ai_charge, 0, chick_skip_frames, - ai_charge, 0, chick_skip_frames, - ai_charge, 0, chick_skip_frames, - ai_charge, 0, chick_attack1 -}; -mmove_t chick_move_start_attack1 = {FRAME_attak101, FRAME_attak113, chick_frames_start_attack1, NULL}; - - -mframe_t chick_frames_attack1 [] = -{ - ai_charge, 19, ChickRocket, - ai_charge, -6, NULL, - ai_charge, -5, NULL, - ai_charge, -2, NULL, - ai_charge, -7, NULL, - ai_charge, 0, NULL, - ai_charge, 1, NULL, - ai_charge, 10, ChickReload, - ai_charge, 4, NULL, - ai_charge, 5, NULL, - ai_charge, 6, NULL, - ai_charge, 6, NULL, - ai_charge, 4, NULL, - ai_charge, 3, chick_rerocket - -}; -mmove_t chick_move_attack1 = {FRAME_attak114, FRAME_attak127, chick_frames_attack1, NULL}; - -mframe_t chick_frames_end_attack1 [] = -{ - ai_charge, -3, NULL, - ai_charge, 0, NULL, - ai_charge, -6, NULL, - ai_charge, -4, NULL, - ai_charge, -2, NULL -}; -mmove_t chick_move_end_attack1 = {FRAME_attak128, FRAME_attak132, chick_frames_end_attack1, chick_run}; - -void chick_rerocket(edict_t *self) -{ - if (self->enemy->health > 0) - { - if (range (self, self->enemy) > RANGE_MELEE) - if ( visible (self, self->enemy) ) - if (random() <= 0.6) - { - self->monsterinfo.currentmove = &chick_move_attack1; - return; - } - } - self->monsterinfo.currentmove = &chick_move_end_attack1; -} - -void chick_attack1(edict_t *self) -{ - self->monsterinfo.currentmove = &chick_move_attack1; -} - -mframe_t chick_frames_slash [] = -{ - ai_charge, 1, NULL, - ai_charge, 7, ChickSlash, - ai_charge, -7, NULL, - ai_charge, 1, NULL, - ai_charge, -1, NULL, - ai_charge, 1, NULL, - ai_charge, 0, NULL, - ai_charge, 1, NULL, - ai_charge, -2, chick_reslash -}; -mmove_t chick_move_slash = {FRAME_attak204, FRAME_attak212, chick_frames_slash, NULL}; - -mframe_t chick_frames_end_slash [] = -{ - ai_charge, -6, NULL, - ai_charge, -1, NULL, - ai_charge, -6, NULL, - ai_charge, 0, NULL -}; -mmove_t chick_move_end_slash = {FRAME_attak213, FRAME_attak216, chick_frames_end_slash, chick_run}; - - -void chick_reslash(edict_t *self) -{ - if (self->enemy->health > 0) - { - if (range (self, self->enemy) == RANGE_MELEE) - if (random() <= 0.9) - { - self->monsterinfo.currentmove = &chick_move_slash; - return; - } - else - { - self->monsterinfo.currentmove = &chick_move_end_slash; - return; - } - } - self->monsterinfo.currentmove = &chick_move_end_slash; -} - -void chick_slash(edict_t *self) -{ - self->monsterinfo.currentmove = &chick_move_slash; -} - - -mframe_t chick_frames_start_slash [] = -{ - ai_charge, 1, NULL, - ai_charge, 8, NULL, - ai_charge, 3, NULL -}; -mmove_t chick_move_start_slash = {FRAME_attak201, FRAME_attak203, chick_frames_start_slash, chick_slash}; - - - -void chick_melee(edict_t *self) -{ - self->monsterinfo.currentmove = &chick_move_start_slash; -} - - -void chick_attack(edict_t *self) -{ - self->monsterinfo.currentmove = &chick_move_start_attack1; -} - -void chick_sight(edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -/*QUAKED monster_chick (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_chick (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_CHICK; - - sound_missile_prelaunch = gi.soundindex ("chick/chkatck1.wav"); - sound_missile_launch = gi.soundindex ("chick/chkatck2.wav"); - sound_melee_swing = gi.soundindex ("chick/chkatck3.wav"); - sound_melee_hit = gi.soundindex ("chick/chkatck4.wav"); - sound_missile_reload = gi.soundindex ("chick/chkatck5.wav"); - sound_death1 = gi.soundindex ("chick/chkdeth1.wav"); - sound_death2 = gi.soundindex ("chick/chkdeth2.wav"); - sound_fall_down = gi.soundindex ("chick/chkfall1.wav"); - sound_idle1 = gi.soundindex ("chick/chkidle1.wav"); - sound_idle2 = gi.soundindex ("chick/chkidle2.wav"); - sound_pain1 = gi.soundindex ("chick/chkpain1.wav"); - sound_pain2 = gi.soundindex ("chick/chkpain2.wav"); - sound_pain3 = gi.soundindex ("chick/chkpain3.wav"); - sound_sight = gi.soundindex ("chick/chksght1.wav"); - sound_search = gi.soundindex ("chick/chksrch1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/bitch/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/bitch/tris.md2"); - VectorSet (self->mins, -16, -16, 0); - VectorSet (self->maxs, 16, 16, 56); - - // DWH: mapper-configurable health - if(!self->health) - self->health = 175; - if(!self->gib_health) - self->gib_health = -70; - if(!self->mass) - self->mass = 200; - - self->pain = chick_pain; - self->die = chick_die; - - self->monsterinfo.stand = chick_stand; - self->monsterinfo.walk = chick_walk; - self->monsterinfo.run = chick_run; - self->monsterinfo.dodge = chick_dodge; - self->monsterinfo.attack = chick_attack; - self->monsterinfo.melee = chick_melee; - self->monsterinfo.sight = chick_sight; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.40; - self->common_name = "Iron Maiden"; - - gi.linkentity (self); - - self->monsterinfo.currentmove = &chick_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&chick_move_death1, - &chick_move_death2, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - - walkmonster_start (self); -} diff --git a/server/monsters/m_chick.h b/server/monsters/m_chick.h deleted file mode 100644 index a61f8ca2..00000000 --- a/server/monsters/m_chick.h +++ /dev/null @@ -1,294 +0,0 @@ -// G:\quake2\baseq2\models/monsters/bitch - -// This file generated by qdata - Do NOT Modify - -#define FRAME_attak101 0 -#define FRAME_attak102 1 -#define FRAME_attak103 2 -#define FRAME_attak104 3 -#define FRAME_attak105 4 -#define FRAME_attak106 5 -#define FRAME_attak107 6 -#define FRAME_attak108 7 -#define FRAME_attak109 8 -#define FRAME_attak110 9 -#define FRAME_attak111 10 -#define FRAME_attak112 11 -#define FRAME_attak113 12 -#define FRAME_attak114 13 -#define FRAME_attak115 14 -#define FRAME_attak116 15 -#define FRAME_attak117 16 -#define FRAME_attak118 17 -#define FRAME_attak119 18 -#define FRAME_attak120 19 -#define FRAME_attak121 20 -#define FRAME_attak122 21 -#define FRAME_attak123 22 -#define FRAME_attak124 23 -#define FRAME_attak125 24 -#define FRAME_attak126 25 -#define FRAME_attak127 26 -#define FRAME_attak128 27 -#define FRAME_attak129 28 -#define FRAME_attak130 29 -#define FRAME_attak131 30 -#define FRAME_attak132 31 -#define FRAME_attak201 32 -#define FRAME_attak202 33 -#define FRAME_attak203 34 -#define FRAME_attak204 35 -#define FRAME_attak205 36 -#define FRAME_attak206 37 -#define FRAME_attak207 38 -#define FRAME_attak208 39 -#define FRAME_attak209 40 -#define FRAME_attak210 41 -#define FRAME_attak211 42 -#define FRAME_attak212 43 -#define FRAME_attak213 44 -#define FRAME_attak214 45 -#define FRAME_attak215 46 -#define FRAME_attak216 47 -#define FRAME_death101 48 -#define FRAME_death102 49 -#define FRAME_death103 50 -#define FRAME_death104 51 -#define FRAME_death105 52 -#define FRAME_death106 53 -#define FRAME_death107 54 -#define FRAME_death108 55 -#define FRAME_death109 56 -#define FRAME_death110 57 -#define FRAME_death111 58 -#define FRAME_death112 59 -#define FRAME_death201 60 -#define FRAME_death202 61 -#define FRAME_death203 62 -#define FRAME_death204 63 -#define FRAME_death205 64 -#define FRAME_death206 65 -#define FRAME_death207 66 -#define FRAME_death208 67 -#define FRAME_death209 68 -#define FRAME_death210 69 -#define FRAME_death211 70 -#define FRAME_death212 71 -#define FRAME_death213 72 -#define FRAME_death214 73 -#define FRAME_death215 74 -#define FRAME_death216 75 -#define FRAME_death217 76 -#define FRAME_death218 77 -#define FRAME_death219 78 -#define FRAME_death220 79 -#define FRAME_death221 80 -#define FRAME_death222 81 -#define FRAME_death223 82 -#define FRAME_duck01 83 -#define FRAME_duck02 84 -#define FRAME_duck03 85 -#define FRAME_duck04 86 -#define FRAME_duck05 87 -#define FRAME_duck06 88 -#define FRAME_duck07 89 -#define FRAME_pain101 90 -#define FRAME_pain102 91 -#define FRAME_pain103 92 -#define FRAME_pain104 93 -#define FRAME_pain105 94 -#define FRAME_pain201 95 -#define FRAME_pain202 96 -#define FRAME_pain203 97 -#define FRAME_pain204 98 -#define FRAME_pain205 99 -#define FRAME_pain301 100 -#define FRAME_pain302 101 -#define FRAME_pain303 102 -#define FRAME_pain304 103 -#define FRAME_pain305 104 -#define FRAME_pain306 105 -#define FRAME_pain307 106 -#define FRAME_pain308 107 -#define FRAME_pain309 108 -#define FRAME_pain310 109 -#define FRAME_pain311 110 -#define FRAME_pain312 111 -#define FRAME_pain313 112 -#define FRAME_pain314 113 -#define FRAME_pain315 114 -#define FRAME_pain316 115 -#define FRAME_pain317 116 -#define FRAME_pain318 117 -#define FRAME_pain319 118 -#define FRAME_pain320 119 -#define FRAME_pain321 120 -#define FRAME_stand101 121 -#define FRAME_stand102 122 -#define FRAME_stand103 123 -#define FRAME_stand104 124 -#define FRAME_stand105 125 -#define FRAME_stand106 126 -#define FRAME_stand107 127 -#define FRAME_stand108 128 -#define FRAME_stand109 129 -#define FRAME_stand110 130 -#define FRAME_stand111 131 -#define FRAME_stand112 132 -#define FRAME_stand113 133 -#define FRAME_stand114 134 -#define FRAME_stand115 135 -#define FRAME_stand116 136 -#define FRAME_stand117 137 -#define FRAME_stand118 138 -#define FRAME_stand119 139 -#define FRAME_stand120 140 -#define FRAME_stand121 141 -#define FRAME_stand122 142 -#define FRAME_stand123 143 -#define FRAME_stand124 144 -#define FRAME_stand125 145 -#define FRAME_stand126 146 -#define FRAME_stand127 147 -#define FRAME_stand128 148 -#define FRAME_stand129 149 -#define FRAME_stand130 150 -#define FRAME_stand201 151 -#define FRAME_stand202 152 -#define FRAME_stand203 153 -#define FRAME_stand204 154 -#define FRAME_stand205 155 -#define FRAME_stand206 156 -#define FRAME_stand207 157 -#define FRAME_stand208 158 -#define FRAME_stand209 159 -#define FRAME_stand210 160 -#define FRAME_stand211 161 -#define FRAME_stand212 162 -#define FRAME_stand213 163 -#define FRAME_stand214 164 -#define FRAME_stand215 165 -#define FRAME_stand216 166 -#define FRAME_stand217 167 -#define FRAME_stand218 168 -#define FRAME_stand219 169 -#define FRAME_stand220 170 -#define FRAME_stand221 171 -#define FRAME_stand222 172 -#define FRAME_stand223 173 -#define FRAME_stand224 174 -#define FRAME_stand225 175 -#define FRAME_stand226 176 -#define FRAME_stand227 177 -#define FRAME_stand228 178 -#define FRAME_stand229 179 -#define FRAME_stand230 180 -#define FRAME_walk01 181 -#define FRAME_walk02 182 -#define FRAME_walk03 183 -#define FRAME_walk04 184 -#define FRAME_walk05 185 -#define FRAME_walk06 186 -#define FRAME_walk07 187 -#define FRAME_walk08 188 -#define FRAME_walk09 189 -#define FRAME_walk10 190 -#define FRAME_walk11 191 -#define FRAME_walk12 192 -#define FRAME_walk13 193 -#define FRAME_walk14 194 -#define FRAME_walk15 195 -#define FRAME_walk16 196 -#define FRAME_walk17 197 -#define FRAME_walk18 198 -#define FRAME_walk19 199 -#define FRAME_walk20 200 -#define FRAME_walk21 201 -#define FRAME_walk22 202 -#define FRAME_walk23 203 -#define FRAME_walk24 204 -#define FRAME_walk25 205 -#define FRAME_walk26 206 -#define FRAME_walk27 207 -#define FRAME_recln201 208 -#define FRAME_recln202 209 -#define FRAME_recln203 210 -#define FRAME_recln204 211 -#define FRAME_recln205 212 -#define FRAME_recln206 213 -#define FRAME_recln207 214 -#define FRAME_recln208 215 -#define FRAME_recln209 216 -#define FRAME_recln210 217 -#define FRAME_recln211 218 -#define FRAME_recln212 219 -#define FRAME_recln213 220 -#define FRAME_recln214 221 -#define FRAME_recln215 222 -#define FRAME_recln216 223 -#define FRAME_recln217 224 -#define FRAME_recln218 225 -#define FRAME_recln219 226 -#define FRAME_recln220 227 -#define FRAME_recln221 228 -#define FRAME_recln222 229 -#define FRAME_recln223 230 -#define FRAME_recln224 231 -#define FRAME_recln225 232 -#define FRAME_recln226 233 -#define FRAME_recln227 234 -#define FRAME_recln228 235 -#define FRAME_recln229 236 -#define FRAME_recln230 237 -#define FRAME_recln231 238 -#define FRAME_recln232 239 -#define FRAME_recln233 240 -#define FRAME_recln234 241 -#define FRAME_recln235 242 -#define FRAME_recln236 243 -#define FRAME_recln237 244 -#define FRAME_recln238 245 -#define FRAME_recln239 246 -#define FRAME_recln240 247 -#define FRAME_recln101 248 -#define FRAME_recln102 249 -#define FRAME_recln103 250 -#define FRAME_recln104 251 -#define FRAME_recln105 252 -#define FRAME_recln106 253 -#define FRAME_recln107 254 -#define FRAME_recln108 255 -#define FRAME_recln109 256 -#define FRAME_recln110 257 -#define FRAME_recln111 258 -#define FRAME_recln112 259 -#define FRAME_recln113 260 -#define FRAME_recln114 261 -#define FRAME_recln115 262 -#define FRAME_recln116 263 -#define FRAME_recln117 264 -#define FRAME_recln118 265 -#define FRAME_recln119 266 -#define FRAME_recln120 267 -#define FRAME_recln121 268 -#define FRAME_recln122 269 -#define FRAME_recln123 270 -#define FRAME_recln124 271 -#define FRAME_recln125 272 -#define FRAME_recln126 273 -#define FRAME_recln127 274 -#define FRAME_recln128 275 -#define FRAME_recln129 276 -#define FRAME_recln130 277 -#define FRAME_recln131 278 -#define FRAME_recln132 279 -#define FRAME_recln133 280 -#define FRAME_recln134 281 -#define FRAME_recln135 282 -#define FRAME_recln136 283 -#define FRAME_recln137 284 -#define FRAME_recln138 285 -#define FRAME_recln139 286 -#define FRAME_recln140 287 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_flipper.c b/server/monsters/m_flipper.c deleted file mode 100644 index 953884d8..00000000 --- a/server/monsters/m_flipper.c +++ /dev/null @@ -1,416 +0,0 @@ -/* -============================================================================== - -FLIPPER - -============================================================================== -*/ - -#include "g_local.h" -#include "m_flipper.h" - - -static int sound_chomp; -static int sound_attack; -static int sound_pain1; -static int sound_pain2; -static int sound_death; -static int sound_idle; -static int sound_search; -static int sound_sight; - - -void flipper_stand (edict_t *self); - -mframe_t flipper_frames_stand [] = -{ - ai_stand, 0, NULL -}; - -mmove_t flipper_move_stand = {FRAME_flphor01, FRAME_flphor01, flipper_frames_stand, NULL}; - -void flipper_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &flipper_move_stand; -} - -#define FLIPPER_RUN_SPEED 24 - -mframe_t flipper_frames_run [] = -{ - ai_run, FLIPPER_RUN_SPEED, NULL, // 6 - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, // 10 - - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, // 20 - - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL, - ai_run, FLIPPER_RUN_SPEED, NULL // 29 -}; -mmove_t flipper_move_run_loop = {FRAME_flpver06, FRAME_flpver29, flipper_frames_run, NULL}; - -void flipper_run_loop (edict_t *self) -{ - self->monsterinfo.currentmove = &flipper_move_run_loop; -} - -mframe_t flipper_frames_run_start [] = -{ - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL -}; -mmove_t flipper_move_run_start = {FRAME_flpver01, FRAME_flpver06, flipper_frames_run_start, flipper_run_loop}; - -void flipper_run (edict_t *self) -{ - self->monsterinfo.currentmove = &flipper_move_run_start; -} - -/* Standard Swimming */ -mframe_t flipper_frames_walk [] = -{ - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL -}; -mmove_t flipper_move_walk = {FRAME_flphor01, FRAME_flphor24, flipper_frames_walk, NULL}; - -void flipper_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &flipper_move_walk; -} - -mframe_t flipper_frames_start_run [] = -{ - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, NULL, - ai_run, 8, flipper_run -}; -mmove_t flipper_move_start_run = {FRAME_flphor01, FRAME_flphor05, flipper_frames_start_run, NULL}; - -void flipper_start_run (edict_t *self) -{ - self->monsterinfo.currentmove = &flipper_move_start_run; -} - -mframe_t flipper_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flipper_move_pain2 = {FRAME_flppn101, FRAME_flppn105, flipper_frames_pain2, flipper_run}; - -mframe_t flipper_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flipper_move_pain1 = {FRAME_flppn201, FRAME_flppn205, flipper_frames_pain1, flipper_run}; - -void flipper_bite (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, 0, 0); - fire_hit (self, aim, 5, 0); -} - -void flipper_preattack (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0); -} - -mframe_t flipper_frames_attack [] = -{ - ai_charge, 0, flipper_preattack, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, flipper_bite, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, flipper_bite, - ai_charge, 0, NULL -}; -mmove_t flipper_move_attack = {FRAME_flpbit01, FRAME_flpbit20, flipper_frames_attack, flipper_run}; - -void flipper_melee(edict_t *self) -{ - self->monsterinfo.currentmove = &flipper_move_attack; -} - -void flipper_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - int n; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - n = (rand() + 1) % 2; - if (n == 0) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &flipper_move_pain1; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &flipper_move_pain2; - } -} - -void flipper_dead (edict_t *self) -{ -// VectorSet (self->mins, -16, -16, -24); -// VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t flipper_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flipper_move_death = {FRAME_flpdth01, FRAME_flpdth56, flipper_frames_death, flipper_dead}; - -void flipper_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void flipper_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->monsterinfo.currentmove = &flipper_move_death; -} - -/*QUAKED monster_flipper (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_flipper (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_FLIPPER; - self->spawnflags |= SF_MONSTER_KNOWS_MIRRORS; - - sound_pain1 = gi.soundindex ("flipper/flppain1.wav"); - sound_pain2 = gi.soundindex ("flipper/flppain2.wav"); - sound_death = gi.soundindex ("flipper/flpdeth1.wav"); - sound_chomp = gi.soundindex ("flipper/flpatck1.wav"); - sound_attack = gi.soundindex ("flipper/flpatck2.wav"); - sound_idle = gi.soundindex ("flipper/flpidle1.wav"); - sound_search = gi.soundindex ("flipper/flpsrch1.wav"); - sound_sight = gi.soundindex ("flipper/flpsght1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/flipper/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/flipper/tris.md2"); - VectorSet (self->mins, -16, -16, 0); - VectorSet (self->maxs, 16, 16, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 50; - if(!self->gib_health) - self->gib_health = -30; - if(!self->mass) - self->mass = 100; - - self->pain = flipper_pain; - self->die = flipper_die; - - self->monsterinfo.stand = flipper_stand; - self->monsterinfo.walk = flipper_walk; - self->monsterinfo.run = flipper_start_run; - self->monsterinfo.melee = flipper_melee; - self->monsterinfo.sight = flipper_sight; - - gi.linkentity (self); - - self->monsterinfo.currentmove = &flipper_move_stand; - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.90; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&flipper_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Barracuda Shark"; - - self->monsterinfo.scale = MODEL_SCALE; - - swimmonster_start (self); -} diff --git a/server/monsters/m_flipper.h b/server/monsters/m_flipper.h deleted file mode 100644 index 78de1edb..00000000 --- a/server/monsters/m_flipper.h +++ /dev/null @@ -1,166 +0,0 @@ -// G:\quake2\baseq2\models/monsters/flipper - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_flpbit01 0 -#define FRAME_flpbit02 1 -#define FRAME_flpbit03 2 -#define FRAME_flpbit04 3 -#define FRAME_flpbit05 4 -#define FRAME_flpbit06 5 -#define FRAME_flpbit07 6 -#define FRAME_flpbit08 7 -#define FRAME_flpbit09 8 -#define FRAME_flpbit10 9 -#define FRAME_flpbit11 10 -#define FRAME_flpbit12 11 -#define FRAME_flpbit13 12 -#define FRAME_flpbit14 13 -#define FRAME_flpbit15 14 -#define FRAME_flpbit16 15 -#define FRAME_flpbit17 16 -#define FRAME_flpbit18 17 -#define FRAME_flpbit19 18 -#define FRAME_flpbit20 19 -#define FRAME_flptal01 20 -#define FRAME_flptal02 21 -#define FRAME_flptal03 22 -#define FRAME_flptal04 23 -#define FRAME_flptal05 24 -#define FRAME_flptal06 25 -#define FRAME_flptal07 26 -#define FRAME_flptal08 27 -#define FRAME_flptal09 28 -#define FRAME_flptal10 29 -#define FRAME_flptal11 30 -#define FRAME_flptal12 31 -#define FRAME_flptal13 32 -#define FRAME_flptal14 33 -#define FRAME_flptal15 34 -#define FRAME_flptal16 35 -#define FRAME_flptal17 36 -#define FRAME_flptal18 37 -#define FRAME_flptal19 38 -#define FRAME_flptal20 39 -#define FRAME_flptal21 40 -#define FRAME_flphor01 41 -#define FRAME_flphor02 42 -#define FRAME_flphor03 43 -#define FRAME_flphor04 44 -#define FRAME_flphor05 45 -#define FRAME_flphor06 46 -#define FRAME_flphor07 47 -#define FRAME_flphor08 48 -#define FRAME_flphor09 49 -#define FRAME_flphor10 50 -#define FRAME_flphor11 51 -#define FRAME_flphor12 52 -#define FRAME_flphor13 53 -#define FRAME_flphor14 54 -#define FRAME_flphor15 55 -#define FRAME_flphor16 56 -#define FRAME_flphor17 57 -#define FRAME_flphor18 58 -#define FRAME_flphor19 59 -#define FRAME_flphor20 60 -#define FRAME_flphor21 61 -#define FRAME_flphor22 62 -#define FRAME_flphor23 63 -#define FRAME_flphor24 64 -#define FRAME_flpver01 65 -#define FRAME_flpver02 66 -#define FRAME_flpver03 67 -#define FRAME_flpver04 68 -#define FRAME_flpver05 69 -#define FRAME_flpver06 70 -#define FRAME_flpver07 71 -#define FRAME_flpver08 72 -#define FRAME_flpver09 73 -#define FRAME_flpver10 74 -#define FRAME_flpver11 75 -#define FRAME_flpver12 76 -#define FRAME_flpver13 77 -#define FRAME_flpver14 78 -#define FRAME_flpver15 79 -#define FRAME_flpver16 80 -#define FRAME_flpver17 81 -#define FRAME_flpver18 82 -#define FRAME_flpver19 83 -#define FRAME_flpver20 84 -#define FRAME_flpver21 85 -#define FRAME_flpver22 86 -#define FRAME_flpver23 87 -#define FRAME_flpver24 88 -#define FRAME_flpver25 89 -#define FRAME_flpver26 90 -#define FRAME_flpver27 91 -#define FRAME_flpver28 92 -#define FRAME_flpver29 93 -#define FRAME_flppn101 94 -#define FRAME_flppn102 95 -#define FRAME_flppn103 96 -#define FRAME_flppn104 97 -#define FRAME_flppn105 98 -#define FRAME_flppn201 99 -#define FRAME_flppn202 100 -#define FRAME_flppn203 101 -#define FRAME_flppn204 102 -#define FRAME_flppn205 103 -#define FRAME_flpdth01 104 -#define FRAME_flpdth02 105 -#define FRAME_flpdth03 106 -#define FRAME_flpdth04 107 -#define FRAME_flpdth05 108 -#define FRAME_flpdth06 109 -#define FRAME_flpdth07 110 -#define FRAME_flpdth08 111 -#define FRAME_flpdth09 112 -#define FRAME_flpdth10 113 -#define FRAME_flpdth11 114 -#define FRAME_flpdth12 115 -#define FRAME_flpdth13 116 -#define FRAME_flpdth14 117 -#define FRAME_flpdth15 118 -#define FRAME_flpdth16 119 -#define FRAME_flpdth17 120 -#define FRAME_flpdth18 121 -#define FRAME_flpdth19 122 -#define FRAME_flpdth20 123 -#define FRAME_flpdth21 124 -#define FRAME_flpdth22 125 -#define FRAME_flpdth23 126 -#define FRAME_flpdth24 127 -#define FRAME_flpdth25 128 -#define FRAME_flpdth26 129 -#define FRAME_flpdth27 130 -#define FRAME_flpdth28 131 -#define FRAME_flpdth29 132 -#define FRAME_flpdth30 133 -#define FRAME_flpdth31 134 -#define FRAME_flpdth32 135 -#define FRAME_flpdth33 136 -#define FRAME_flpdth34 137 -#define FRAME_flpdth35 138 -#define FRAME_flpdth36 139 -#define FRAME_flpdth37 140 -#define FRAME_flpdth38 141 -#define FRAME_flpdth39 142 -#define FRAME_flpdth40 143 -#define FRAME_flpdth41 144 -#define FRAME_flpdth42 145 -#define FRAME_flpdth43 146 -#define FRAME_flpdth44 147 -#define FRAME_flpdth45 148 -#define FRAME_flpdth46 149 -#define FRAME_flpdth47 150 -#define FRAME_flpdth48 151 -#define FRAME_flpdth49 152 -#define FRAME_flpdth50 153 -#define FRAME_flpdth51 154 -#define FRAME_flpdth52 155 -#define FRAME_flpdth53 156 -#define FRAME_flpdth54 157 -#define FRAME_flpdth55 158 -#define FRAME_flpdth56 159 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_float.c b/server/monsters/m_float.c deleted file mode 100644 index 0f4d3237..00000000 --- a/server/monsters/m_float.c +++ /dev/null @@ -1,683 +0,0 @@ -/* -============================================================================== - -floater - -============================================================================== -*/ - -#include "g_local.h" -#include "m_float.h" - - -static int sound_attack2; -static int sound_attack3; -static int sound_death1; -static int sound_idle; -static int sound_pain1; -static int sound_pain2; -static int sound_sight; - - -void floater_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void floater_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - - -//void floater_stand1 (edict_t *self); -void floater_dead (edict_t *self); -void floater_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); -void floater_run (edict_t *self); -void floater_wham (edict_t *self); -void floater_zap (edict_t *self); - - -void floater_fire_blaster (edict_t *self) -{ - vec3_t start; - vec3_t forward, right; - vec3_t end; - vec3_t dir; - int effect; - - if ((self->s.frame == FRAME_attak104) || (self->s.frame == FRAME_attak107)) - effect = EF_HYPERBLASTER; - else - effect = 0; - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_FLOAT_BLASTER_1], forward, right, start); - - VectorCopy (self->enemy->s.origin, end); - end[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (end, start, dir); - monster_fire_blaster (self, start, dir, 1, 1000, MZ2_FLOAT_BLASTER_1, effect); -} - - -mframe_t floater_frames_stand1 [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t floater_move_stand1 = {FRAME_stand101, FRAME_stand152, floater_frames_stand1, NULL}; - -mframe_t floater_frames_stand2 [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t floater_move_stand2 = {FRAME_stand201, FRAME_stand252, floater_frames_stand2, NULL}; - -void floater_stand (edict_t *self) -{ - if (random() <= 0.5) - self->monsterinfo.currentmove = &floater_move_stand1; - else - self->monsterinfo.currentmove = &floater_move_stand2; -} - -mframe_t floater_frames_activate [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t floater_move_activate = {FRAME_actvat01, FRAME_actvat31, floater_frames_activate, NULL}; - -mframe_t floater_frames_attack1 [] = -{ - ai_charge, 0, NULL, // Blaster attack - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, floater_fire_blaster, // BOOM (0, -25.8, 32.5) -- LOOP Starts - ai_charge, 0, floater_fire_blaster, - ai_charge, 0, floater_fire_blaster, - ai_charge, 0, floater_fire_blaster, - ai_charge, 0, floater_fire_blaster, - ai_charge, 0, floater_fire_blaster, - ai_charge, 0, floater_fire_blaster, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL // -- LOOP Ends -}; -mmove_t floater_move_attack1 = {FRAME_attak101, FRAME_attak114, floater_frames_attack1, floater_run}; - -mframe_t floater_frames_attack2 [] = -{ - ai_charge, 0, NULL, // Claws - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, floater_wham, // WHAM (0, -45, 29.6) -- LOOP Starts - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // -- LOOP Ends - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t floater_move_attack2 = {FRAME_attak201, FRAME_attak225, floater_frames_attack2, floater_run}; - -mframe_t floater_frames_attack3 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, floater_zap, // -- LOOP Starts - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // -- LOOP Ends - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t floater_move_attack3 = {FRAME_attak301, FRAME_attak334, floater_frames_attack3, floater_run}; - -mframe_t floater_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t floater_move_death = {FRAME_death01, FRAME_death13, floater_frames_death, floater_dead}; - -mframe_t floater_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t floater_move_pain1 = {FRAME_pain101, FRAME_pain107, floater_frames_pain1, floater_run}; - -mframe_t floater_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t floater_move_pain2 = {FRAME_pain201, FRAME_pain208, floater_frames_pain2, floater_run}; - -mframe_t floater_frames_pain3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t floater_move_pain3 = {FRAME_pain301, FRAME_pain312, floater_frames_pain3, floater_run}; - -mframe_t floater_frames_walk [] = -{ - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL -}; -mmove_t floater_move_walk = {FRAME_stand101, FRAME_stand152, floater_frames_walk, NULL}; - -mframe_t floater_frames_run [] = -{ - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL, - ai_run, 13, NULL -}; -mmove_t floater_move_run = {FRAME_stand101, FRAME_stand152, floater_frames_run, NULL}; - -void floater_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &floater_move_stand1; - else - self->monsterinfo.currentmove = &floater_move_run; -} - -void floater_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &floater_move_walk; -} - -void floater_wham (edict_t *self) -{ - static vec3_t aim = {MELEE_DISTANCE, 0, 0}; - gi.sound (self, CHAN_WEAPON, sound_attack3, 1, ATTN_NORM, 0); - fire_hit (self, aim, 5 + rand() % 6, -50); -} - -void floater_zap (edict_t *self) -{ - vec3_t forward, right; - vec3_t origin; - vec3_t dir; - vec3_t offset; - - VectorSubtract (self->enemy->s.origin, self->s.origin, dir); - - AngleVectors (self->s.angles, forward, right, NULL); - //FIXME use a flash and replace these two lines with the commented one - VectorSet (offset, 18.5, -0.9, 10); - G_ProjectSource (self->s.origin, offset, forward, right, origin); -// G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, origin); - - gi.sound (self, CHAN_WEAPON, sound_attack2, 1, ATTN_NORM, 0); - - //FIXME use the flash, Luke - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_SPLASH); - WRITE_BYTE (32); - WRITE_COORD (origin); - WRITE_DIR (dir); - WRITE_BYTE (1); //sparks - MESSAGE_SEND (MSG_PVS, origin, NULL); - - T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, 5 + rand() % 6, -10, DAMAGE_ENERGY, MOD_UNKNOWN); -} - -void floater_attack(edict_t *self) -{ - self->monsterinfo.currentmove = &floater_move_attack1; -} - - -void floater_melee(edict_t *self) -{ - if (random() < 0.5) - self->monsterinfo.currentmove = &floater_move_attack3; - else - self->monsterinfo.currentmove = &floater_move_attack2; -} - - -void floater_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - int n; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - if (skill->value == 3) - return; // no pain anims in nightmare - - n = (rand() + 1) % 3; - if (n == 0) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &floater_move_pain1; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &floater_move_pain2; - } -} - -void floater_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); -} - -void floater_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); - BecomeExplosion1(self); -} - -/*QUAKED monster_floater (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_floater (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_FLOATER; - - sound_attack2 = gi.soundindex ("floater/fltatck2.wav"); - sound_attack3 = gi.soundindex ("floater/fltatck3.wav"); - sound_death1 = gi.soundindex ("floater/fltdeth1.wav"); - sound_idle = gi.soundindex ("floater/fltidle1.wav"); - sound_pain1 = gi.soundindex ("floater/fltpain1.wav"); - sound_pain2 = gi.soundindex ("floater/fltpain2.wav"); - sound_sight = gi.soundindex ("floater/fltsght1.wav"); - - gi.soundindex ("floater/fltatck1.wav"); - - self->s.sound = gi.soundindex ("floater/fltsrch1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/float/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/float/tris.md2"); - VectorSet (self->mins, -24, -24, -24); - VectorSet (self->maxs, 24, 24, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 200; - if(!self->gib_health) - self->gib_health = -80; - if(!self->mass) - self->mass = 300; - - self->pain = floater_pain; - self->die = floater_die; - - self->monsterinfo.stand = floater_stand; - self->monsterinfo.walk = floater_walk; - self->monsterinfo.run = floater_run; -// self->monsterinfo.dodge = floater_dodge; - self->monsterinfo.attack = floater_attack; - self->monsterinfo.melee = floater_melee; - self->monsterinfo.sight = floater_sight; - self->monsterinfo.idle = floater_idle; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - self->common_name = "Technician"; - - gi.linkentity (self); - - if(self->health < 0) - { - mmove_t *deathmoves[] = {&floater_move_death, - NULL}; - if(!M_SetDeath(self,(mmove_t **)&deathmoves)) - self->monsterinfo.currentmove = &floater_move_stand1; - } - else - { - if (random() <= 0.5) - self->monsterinfo.currentmove = &floater_move_stand1; - else - self->monsterinfo.currentmove = &floater_move_stand2; - } - - self->monsterinfo.scale = MODEL_SCALE; - - flymonster_start (self); -} diff --git a/server/monsters/m_float.h b/server/monsters/m_float.h deleted file mode 100644 index e403804b..00000000 --- a/server/monsters/m_float.h +++ /dev/null @@ -1,254 +0,0 @@ -// G:\quake2\baseq2\models/monsters/float - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_actvat01 0 -#define FRAME_actvat02 1 -#define FRAME_actvat03 2 -#define FRAME_actvat04 3 -#define FRAME_actvat05 4 -#define FRAME_actvat06 5 -#define FRAME_actvat07 6 -#define FRAME_actvat08 7 -#define FRAME_actvat09 8 -#define FRAME_actvat10 9 -#define FRAME_actvat11 10 -#define FRAME_actvat12 11 -#define FRAME_actvat13 12 -#define FRAME_actvat14 13 -#define FRAME_actvat15 14 -#define FRAME_actvat16 15 -#define FRAME_actvat17 16 -#define FRAME_actvat18 17 -#define FRAME_actvat19 18 -#define FRAME_actvat20 19 -#define FRAME_actvat21 20 -#define FRAME_actvat22 21 -#define FRAME_actvat23 22 -#define FRAME_actvat24 23 -#define FRAME_actvat25 24 -#define FRAME_actvat26 25 -#define FRAME_actvat27 26 -#define FRAME_actvat28 27 -#define FRAME_actvat29 28 -#define FRAME_actvat30 29 -#define FRAME_actvat31 30 -#define FRAME_attak101 31 -#define FRAME_attak102 32 -#define FRAME_attak103 33 -#define FRAME_attak104 34 -#define FRAME_attak105 35 -#define FRAME_attak106 36 -#define FRAME_attak107 37 -#define FRAME_attak108 38 -#define FRAME_attak109 39 -#define FRAME_attak110 40 -#define FRAME_attak111 41 -#define FRAME_attak112 42 -#define FRAME_attak113 43 -#define FRAME_attak114 44 -#define FRAME_attak201 45 -#define FRAME_attak202 46 -#define FRAME_attak203 47 -#define FRAME_attak204 48 -#define FRAME_attak205 49 -#define FRAME_attak206 50 -#define FRAME_attak207 51 -#define FRAME_attak208 52 -#define FRAME_attak209 53 -#define FRAME_attak210 54 -#define FRAME_attak211 55 -#define FRAME_attak212 56 -#define FRAME_attak213 57 -#define FRAME_attak214 58 -#define FRAME_attak215 59 -#define FRAME_attak216 60 -#define FRAME_attak217 61 -#define FRAME_attak218 62 -#define FRAME_attak219 63 -#define FRAME_attak220 64 -#define FRAME_attak221 65 -#define FRAME_attak222 66 -#define FRAME_attak223 67 -#define FRAME_attak224 68 -#define FRAME_attak225 69 -#define FRAME_attak301 70 -#define FRAME_attak302 71 -#define FRAME_attak303 72 -#define FRAME_attak304 73 -#define FRAME_attak305 74 -#define FRAME_attak306 75 -#define FRAME_attak307 76 -#define FRAME_attak308 77 -#define FRAME_attak309 78 -#define FRAME_attak310 79 -#define FRAME_attak311 80 -#define FRAME_attak312 81 -#define FRAME_attak313 82 -#define FRAME_attak314 83 -#define FRAME_attak315 84 -#define FRAME_attak316 85 -#define FRAME_attak317 86 -#define FRAME_attak318 87 -#define FRAME_attak319 88 -#define FRAME_attak320 89 -#define FRAME_attak321 90 -#define FRAME_attak322 91 -#define FRAME_attak323 92 -#define FRAME_attak324 93 -#define FRAME_attak325 94 -#define FRAME_attak326 95 -#define FRAME_attak327 96 -#define FRAME_attak328 97 -#define FRAME_attak329 98 -#define FRAME_attak330 99 -#define FRAME_attak331 100 -#define FRAME_attak332 101 -#define FRAME_attak333 102 -#define FRAME_attak334 103 -#define FRAME_death01 104 -#define FRAME_death02 105 -#define FRAME_death03 106 -#define FRAME_death04 107 -#define FRAME_death05 108 -#define FRAME_death06 109 -#define FRAME_death07 110 -#define FRAME_death08 111 -#define FRAME_death09 112 -#define FRAME_death10 113 -#define FRAME_death11 114 -#define FRAME_death12 115 -#define FRAME_death13 116 -#define FRAME_pain101 117 -#define FRAME_pain102 118 -#define FRAME_pain103 119 -#define FRAME_pain104 120 -#define FRAME_pain105 121 -#define FRAME_pain106 122 -#define FRAME_pain107 123 -#define FRAME_pain201 124 -#define FRAME_pain202 125 -#define FRAME_pain203 126 -#define FRAME_pain204 127 -#define FRAME_pain205 128 -#define FRAME_pain206 129 -#define FRAME_pain207 130 -#define FRAME_pain208 131 -#define FRAME_pain301 132 -#define FRAME_pain302 133 -#define FRAME_pain303 134 -#define FRAME_pain304 135 -#define FRAME_pain305 136 -#define FRAME_pain306 137 -#define FRAME_pain307 138 -#define FRAME_pain308 139 -#define FRAME_pain309 140 -#define FRAME_pain310 141 -#define FRAME_pain311 142 -#define FRAME_pain312 143 -#define FRAME_stand101 144 -#define FRAME_stand102 145 -#define FRAME_stand103 146 -#define FRAME_stand104 147 -#define FRAME_stand105 148 -#define FRAME_stand106 149 -#define FRAME_stand107 150 -#define FRAME_stand108 151 -#define FRAME_stand109 152 -#define FRAME_stand110 153 -#define FRAME_stand111 154 -#define FRAME_stand112 155 -#define FRAME_stand113 156 -#define FRAME_stand114 157 -#define FRAME_stand115 158 -#define FRAME_stand116 159 -#define FRAME_stand117 160 -#define FRAME_stand118 161 -#define FRAME_stand119 162 -#define FRAME_stand120 163 -#define FRAME_stand121 164 -#define FRAME_stand122 165 -#define FRAME_stand123 166 -#define FRAME_stand124 167 -#define FRAME_stand125 168 -#define FRAME_stand126 169 -#define FRAME_stand127 170 -#define FRAME_stand128 171 -#define FRAME_stand129 172 -#define FRAME_stand130 173 -#define FRAME_stand131 174 -#define FRAME_stand132 175 -#define FRAME_stand133 176 -#define FRAME_stand134 177 -#define FRAME_stand135 178 -#define FRAME_stand136 179 -#define FRAME_stand137 180 -#define FRAME_stand138 181 -#define FRAME_stand139 182 -#define FRAME_stand140 183 -#define FRAME_stand141 184 -#define FRAME_stand142 185 -#define FRAME_stand143 186 -#define FRAME_stand144 187 -#define FRAME_stand145 188 -#define FRAME_stand146 189 -#define FRAME_stand147 190 -#define FRAME_stand148 191 -#define FRAME_stand149 192 -#define FRAME_stand150 193 -#define FRAME_stand151 194 -#define FRAME_stand152 195 -#define FRAME_stand201 196 -#define FRAME_stand202 197 -#define FRAME_stand203 198 -#define FRAME_stand204 199 -#define FRAME_stand205 200 -#define FRAME_stand206 201 -#define FRAME_stand207 202 -#define FRAME_stand208 203 -#define FRAME_stand209 204 -#define FRAME_stand210 205 -#define FRAME_stand211 206 -#define FRAME_stand212 207 -#define FRAME_stand213 208 -#define FRAME_stand214 209 -#define FRAME_stand215 210 -#define FRAME_stand216 211 -#define FRAME_stand217 212 -#define FRAME_stand218 213 -#define FRAME_stand219 214 -#define FRAME_stand220 215 -#define FRAME_stand221 216 -#define FRAME_stand222 217 -#define FRAME_stand223 218 -#define FRAME_stand224 219 -#define FRAME_stand225 220 -#define FRAME_stand226 221 -#define FRAME_stand227 222 -#define FRAME_stand228 223 -#define FRAME_stand229 224 -#define FRAME_stand230 225 -#define FRAME_stand231 226 -#define FRAME_stand232 227 -#define FRAME_stand233 228 -#define FRAME_stand234 229 -#define FRAME_stand235 230 -#define FRAME_stand236 231 -#define FRAME_stand237 232 -#define FRAME_stand238 233 -#define FRAME_stand239 234 -#define FRAME_stand240 235 -#define FRAME_stand241 236 -#define FRAME_stand242 237 -#define FRAME_stand243 238 -#define FRAME_stand244 239 -#define FRAME_stand245 240 -#define FRAME_stand246 241 -#define FRAME_stand247 242 -#define FRAME_stand248 243 -#define FRAME_stand249 244 -#define FRAME_stand250 245 -#define FRAME_stand251 246 -#define FRAME_stand252 247 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_flyer.c b/server/monsters/m_flyer.c deleted file mode 100644 index 48c39431..00000000 --- a/server/monsters/m_flyer.c +++ /dev/null @@ -1,633 +0,0 @@ -/* -============================================================================== - -flyer - -============================================================================== -*/ - -#include "g_local.h" -#include "m_flyer.h" - -bool visible (edict_t *self, edict_t *other); - -static int nextmove; // Used for start/stop frames - -static int sound_sight; -static int sound_idle; -static int sound_pain1; -static int sound_pain2; -static int sound_slash; -static int sound_sproing; -static int sound_die; - - -void flyer_check_melee(edict_t *self); -void flyer_loop_melee (edict_t *self); -void flyer_melee (edict_t *self); -void flyer_setstart (edict_t *self); -void flyer_stand (edict_t *self); -void flyer_nextmove (edict_t *self); - - -void flyer_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void flyer_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - -void flyer_pop_blades (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_sproing, 1, ATTN_NORM, 0); -} - - -mframe_t flyer_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t flyer_move_stand = {FRAME_stand01, FRAME_stand45, flyer_frames_stand, NULL}; - - -mframe_t flyer_frames_walk [] = -{ - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL -}; -mmove_t flyer_move_walk = {FRAME_stand01, FRAME_stand45, flyer_frames_walk, NULL}; - -mframe_t flyer_frames_run [] = -{ - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL -}; -mmove_t flyer_move_run = {FRAME_stand01, FRAME_stand45, flyer_frames_run, NULL}; - -void flyer_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &flyer_move_stand; - else - self->monsterinfo.currentmove = &flyer_move_run; -} - -void flyer_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &flyer_move_walk; -} - -void flyer_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &flyer_move_stand; -} - -mframe_t flyer_frames_start [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, flyer_nextmove -}; -mmove_t flyer_move_start = {FRAME_start01, FRAME_start06, flyer_frames_start, NULL}; - -mframe_t flyer_frames_stop [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, flyer_nextmove -}; -mmove_t flyer_move_stop = {FRAME_stop01, FRAME_stop07, flyer_frames_stop, NULL}; - -void flyer_stop (edict_t *self) -{ - self->monsterinfo.currentmove = &flyer_move_stop; -} - -void flyer_start (edict_t *self) -{ - self->monsterinfo.currentmove = &flyer_move_start; -} - - -mframe_t flyer_frames_rollright [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_rollright = {FRAME_rollr01, FRAME_rollr09, flyer_frames_rollright, NULL}; - -mframe_t flyer_frames_rollleft [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_rollleft = {FRAME_rollf01, FRAME_rollf09, flyer_frames_rollleft, NULL}; - -mframe_t flyer_frames_pain3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_pain3 = {FRAME_pain301, FRAME_pain304, flyer_frames_pain3, flyer_run}; - -mframe_t flyer_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_pain2 = {FRAME_pain201, FRAME_pain204, flyer_frames_pain2, flyer_run}; - -mframe_t flyer_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_pain1 = {FRAME_pain101, FRAME_pain109, flyer_frames_pain1, flyer_run}; - -mframe_t flyer_frames_defense [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // Hold this frame - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_defense = {FRAME_defens01, FRAME_defens06, flyer_frames_defense, NULL}; - -mframe_t flyer_frames_bankright [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_bankright = {FRAME_bankr01, FRAME_bankr07, flyer_frames_bankright, NULL}; - -mframe_t flyer_frames_bankleft [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t flyer_move_bankleft = {FRAME_bankl01, FRAME_bankl07, flyer_frames_bankleft, NULL}; - - -void flyer_fire (edict_t *self, int flash_number) -{ - vec3_t start; - vec3_t forward, right; - vec3_t end; - vec3_t dir; - int effect; - - if ((self->s.frame == FRAME_attak204) || (self->s.frame == FRAME_attak207) || (self->s.frame == FRAME_attak210)) - effect = EF_HYPERBLASTER; - else - effect = 0; - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - VectorCopy (self->enemy->s.origin, end); - end[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (end, start, dir); - monster_fire_blaster (self, start, dir, 1, 1000, flash_number, effect); -} - -void flyer_fireleft (edict_t *self) -{ - flyer_fire (self, MZ2_FLYER_BLASTER_1); -} - -void flyer_fireright (edict_t *self) -{ - flyer_fire (self, MZ2_FLYER_BLASTER_2); -} - - -mframe_t flyer_frames_attack2 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, -10, flyer_fireleft, // left gun - ai_charge, -10, flyer_fireright, // right gun - ai_charge, -10, flyer_fireleft, // left gun - ai_charge, -10, flyer_fireright, // right gun - ai_charge, -10, flyer_fireleft, // left gun - ai_charge, -10, flyer_fireright, // right gun - ai_charge, -10, flyer_fireleft, // left gun - ai_charge, -10, flyer_fireright, // right gun - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t flyer_move_attack2 = {FRAME_attak201, FRAME_attak217, flyer_frames_attack2, flyer_run}; - - -void flyer_slash_left (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->mins[0], 0); - fire_hit (self, aim, 5, 0); - gi.sound (self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0); -} - -void flyer_slash_right (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 0); - fire_hit (self, aim, 5, 0); - gi.sound (self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0); -} - -mframe_t flyer_frames_start_melee [] = -{ - ai_charge, 0, flyer_pop_blades, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t flyer_move_start_melee = {FRAME_attak101, FRAME_attak106, flyer_frames_start_melee, flyer_loop_melee}; - -mframe_t flyer_frames_end_melee [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t flyer_move_end_melee = {FRAME_attak119, FRAME_attak121, flyer_frames_end_melee, flyer_run}; - - -mframe_t flyer_frames_loop_melee [] = -{ - ai_charge, 0, NULL, // Loop Start - ai_charge, 0, NULL, - ai_charge, 0, flyer_slash_left, // Left Wing Strike - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, flyer_slash_right, // Right Wing Strike - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL // Loop Ends - -}; -mmove_t flyer_move_loop_melee = {FRAME_attak107, FRAME_attak118, flyer_frames_loop_melee, flyer_check_melee}; - -void flyer_loop_melee (edict_t *self) -{ -/* if (random() <= 0.5) - self->monsterinfo.currentmove = &flyer_move_attack1; - else */ - self->monsterinfo.currentmove = &flyer_move_loop_melee; -} - - - -void flyer_attack (edict_t *self) -{ -/* if (random() <= 0.5) - self->monsterinfo.currentmove = &flyer_move_attack1; - else */ - self->monsterinfo.currentmove = &flyer_move_attack2; -} - -void flyer_setstart (edict_t *self) -{ - nextmove = ACTION_run; - self->monsterinfo.currentmove = &flyer_move_start; -} - -void flyer_nextmove (edict_t *self) -{ - if (nextmove == ACTION_attack1) - self->monsterinfo.currentmove = &flyer_move_start_melee; - else if (nextmove == ACTION_attack2) - self->monsterinfo.currentmove = &flyer_move_attack2; - else if (nextmove == ACTION_run) - self->monsterinfo.currentmove = &flyer_move_run; -} - -void flyer_melee (edict_t *self) -{ -// flyer.nextmove = ACTION_attack1; -// self->monsterinfo.currentmove = &flyer_move_stop; - self->monsterinfo.currentmove = &flyer_move_start_melee; -} - -void flyer_check_melee(edict_t *self) -{ - if (range (self, self->enemy) == RANGE_MELEE) - if (random() <= 0.8) - self->monsterinfo.currentmove = &flyer_move_loop_melee; - else - self->monsterinfo.currentmove = &flyer_move_end_melee; - else - self->monsterinfo.currentmove = &flyer_move_end_melee; -} - -void flyer_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - int n; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - if (skill->value == 3) - return; // no pain anims in nightmare - - n = rand() % 3; - if (n == 0) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &flyer_move_pain1; - } - else if (n == 1) - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &flyer_move_pain2; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &flyer_move_pain3; - } -} - - -void flyer_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); - BecomeExplosion1(self); -} - - -/*QUAKED monster_flyer (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_flyer (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_FLYER; - - // fix a map bug in jail5.bsp - if (!strcasecmp(level.mapname, "jail5") && (self->s.origin[2] == -104)) - { - self->targetname = self->target; - self->target = NULL; - } - - sound_sight = gi.soundindex ("flyer/flysght1.wav"); - sound_idle = gi.soundindex ("flyer/flysrch1.wav"); - sound_pain1 = gi.soundindex ("flyer/flypain1.wav"); - sound_pain2 = gi.soundindex ("flyer/flypain2.wav"); - sound_slash = gi.soundindex ("flyer/flyatck2.wav"); - sound_sproing = gi.soundindex ("flyer/flyatck1.wav"); - sound_die = gi.soundindex ("flyer/flydeth1.wav"); - - gi.soundindex ("flyer/flyatck3.wav"); - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/flyer/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/flyer/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - self->s.sound = gi.soundindex ("flyer/flyidle1.wav"); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 50; - if(!self->mass) - self->mass = 50; - - self->pain = flyer_pain; - self->die = flyer_die; - - self->monsterinfo.stand = flyer_stand; - self->monsterinfo.walk = flyer_walk; - self->monsterinfo.run = flyer_run; - self->monsterinfo.attack = flyer_attack; - self->monsterinfo.melee = flyer_melee; - self->monsterinfo.sight = flyer_sight; - self->monsterinfo.idle = flyer_idle; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - self->common_name = "Flyer"; - - gi.linkentity (self); - - self->monsterinfo.currentmove = &flyer_move_stand; - self->monsterinfo.scale = MODEL_SCALE; - - flymonster_start (self); -} diff --git a/server/monsters/m_flyer.h b/server/monsters/m_flyer.h deleted file mode 100644 index d1506e35..00000000 --- a/server/monsters/m_flyer.h +++ /dev/null @@ -1,163 +0,0 @@ -// G:\quake2\baseq2\models/monsters/flyer - -// This file generated by ModelGen - Do NOT Modify - -#define ACTION_nothing 0 -#define ACTION_attack1 1 -#define ACTION_attack2 2 -#define ACTION_run 3 -#define ACTION_walk 4 - -#define FRAME_start01 0 -#define FRAME_start02 1 -#define FRAME_start03 2 -#define FRAME_start04 3 -#define FRAME_start05 4 -#define FRAME_start06 5 -#define FRAME_stop01 6 -#define FRAME_stop02 7 -#define FRAME_stop03 8 -#define FRAME_stop04 9 -#define FRAME_stop05 10 -#define FRAME_stop06 11 -#define FRAME_stop07 12 -#define FRAME_stand01 13 -#define FRAME_stand02 14 -#define FRAME_stand03 15 -#define FRAME_stand04 16 -#define FRAME_stand05 17 -#define FRAME_stand06 18 -#define FRAME_stand07 19 -#define FRAME_stand08 20 -#define FRAME_stand09 21 -#define FRAME_stand10 22 -#define FRAME_stand11 23 -#define FRAME_stand12 24 -#define FRAME_stand13 25 -#define FRAME_stand14 26 -#define FRAME_stand15 27 -#define FRAME_stand16 28 -#define FRAME_stand17 29 -#define FRAME_stand18 30 -#define FRAME_stand19 31 -#define FRAME_stand20 32 -#define FRAME_stand21 33 -#define FRAME_stand22 34 -#define FRAME_stand23 35 -#define FRAME_stand24 36 -#define FRAME_stand25 37 -#define FRAME_stand26 38 -#define FRAME_stand27 39 -#define FRAME_stand28 40 -#define FRAME_stand29 41 -#define FRAME_stand30 42 -#define FRAME_stand31 43 -#define FRAME_stand32 44 -#define FRAME_stand33 45 -#define FRAME_stand34 46 -#define FRAME_stand35 47 -#define FRAME_stand36 48 -#define FRAME_stand37 49 -#define FRAME_stand38 50 -#define FRAME_stand39 51 -#define FRAME_stand40 52 -#define FRAME_stand41 53 -#define FRAME_stand42 54 -#define FRAME_stand43 55 -#define FRAME_stand44 56 -#define FRAME_stand45 57 -#define FRAME_attak101 58 -#define FRAME_attak102 59 -#define FRAME_attak103 60 -#define FRAME_attak104 61 -#define FRAME_attak105 62 -#define FRAME_attak106 63 -#define FRAME_attak107 64 -#define FRAME_attak108 65 -#define FRAME_attak109 66 -#define FRAME_attak110 67 -#define FRAME_attak111 68 -#define FRAME_attak112 69 -#define FRAME_attak113 70 -#define FRAME_attak114 71 -#define FRAME_attak115 72 -#define FRAME_attak116 73 -#define FRAME_attak117 74 -#define FRAME_attak118 75 -#define FRAME_attak119 76 -#define FRAME_attak120 77 -#define FRAME_attak121 78 -#define FRAME_attak201 79 -#define FRAME_attak202 80 -#define FRAME_attak203 81 -#define FRAME_attak204 82 -#define FRAME_attak205 83 -#define FRAME_attak206 84 -#define FRAME_attak207 85 -#define FRAME_attak208 86 -#define FRAME_attak209 87 -#define FRAME_attak210 88 -#define FRAME_attak211 89 -#define FRAME_attak212 90 -#define FRAME_attak213 91 -#define FRAME_attak214 92 -#define FRAME_attak215 93 -#define FRAME_attak216 94 -#define FRAME_attak217 95 -#define FRAME_bankl01 96 -#define FRAME_bankl02 97 -#define FRAME_bankl03 98 -#define FRAME_bankl04 99 -#define FRAME_bankl05 100 -#define FRAME_bankl06 101 -#define FRAME_bankl07 102 -#define FRAME_bankr01 103 -#define FRAME_bankr02 104 -#define FRAME_bankr03 105 -#define FRAME_bankr04 106 -#define FRAME_bankr05 107 -#define FRAME_bankr06 108 -#define FRAME_bankr07 109 -#define FRAME_rollf01 110 -#define FRAME_rollf02 111 -#define FRAME_rollf03 112 -#define FRAME_rollf04 113 -#define FRAME_rollf05 114 -#define FRAME_rollf06 115 -#define FRAME_rollf07 116 -#define FRAME_rollf08 117 -#define FRAME_rollf09 118 -#define FRAME_rollr01 119 -#define FRAME_rollr02 120 -#define FRAME_rollr03 121 -#define FRAME_rollr04 122 -#define FRAME_rollr05 123 -#define FRAME_rollr06 124 -#define FRAME_rollr07 125 -#define FRAME_rollr08 126 -#define FRAME_rollr09 127 -#define FRAME_defens01 128 -#define FRAME_defens02 129 -#define FRAME_defens03 130 -#define FRAME_defens04 131 -#define FRAME_defens05 132 -#define FRAME_defens06 133 -#define FRAME_pain101 134 -#define FRAME_pain102 135 -#define FRAME_pain103 136 -#define FRAME_pain104 137 -#define FRAME_pain105 138 -#define FRAME_pain106 139 -#define FRAME_pain107 140 -#define FRAME_pain108 141 -#define FRAME_pain109 142 -#define FRAME_pain201 143 -#define FRAME_pain202 144 -#define FRAME_pain203 145 -#define FRAME_pain204 146 -#define FRAME_pain301 147 -#define FRAME_pain302 148 -#define FRAME_pain303 149 -#define FRAME_pain304 150 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_gladiator.c b/server/monsters/m_gladiator.c deleted file mode 100644 index 6df2696b..00000000 --- a/server/monsters/m_gladiator.c +++ /dev/null @@ -1,434 +0,0 @@ -/* -============================================================================== - -GLADIATOR - -============================================================================== -*/ - -#include "g_local.h" -#include "m_gladiator.h" - - -static int sound_pain1; -static int sound_pain2; -static int sound_die; -static int sound_gun; -static int sound_cleaver_swing; -static int sound_cleaver_hit; -static int sound_cleaver_miss; -static int sound_idle; -static int sound_search; -static int sound_sight; - - -void gladiator_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - -void gladiator_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void gladiator_search (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); -} - -void gladiator_cleaver_swing (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0); -} - -mframe_t gladiator_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t gladiator_move_stand = {FRAME_stand1, FRAME_stand7, gladiator_frames_stand, NULL}; - -void gladiator_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &gladiator_move_stand; -} - - -mframe_t gladiator_frames_walk [] = -{ - ai_walk, 15, NULL, - ai_walk, 7, NULL, - ai_walk, 6, NULL, - ai_walk, 5, NULL, - ai_walk, 2, NULL, - ai_walk, 0, NULL, - ai_walk, 2, NULL, - ai_walk, 8, NULL, - ai_walk, 12, NULL, - ai_walk, 8, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 2, NULL, - ai_walk, 2, NULL, - ai_walk, 1, NULL, - ai_walk, 8, NULL -}; -mmove_t gladiator_move_walk = {FRAME_walk1, FRAME_walk16, gladiator_frames_walk, NULL}; - -void gladiator_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &gladiator_move_walk; -} - - -mframe_t gladiator_frames_run [] = -{ - ai_run, 23, NULL, - ai_run, 14, NULL, - ai_run, 14, NULL, - ai_run, 21, NULL, - ai_run, 12, NULL, - ai_run, 13, NULL -}; -mmove_t gladiator_move_run = {FRAME_run1, FRAME_run6, gladiator_frames_run, NULL}; - -void gladiator_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &gladiator_move_stand; - else - self->monsterinfo.currentmove = &gladiator_move_run; -} - - -void GaldiatorMelee (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->mins[0], -4); - if (fire_hit (self, aim, (20 + (rand() %5)), 300)) - gi.sound (self, CHAN_AUTO, sound_cleaver_hit, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_AUTO, sound_cleaver_miss, 1, ATTN_NORM, 0); -} - -mframe_t gladiator_frames_attack_melee [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, gladiator_cleaver_swing, - ai_charge, 0, NULL, - ai_charge, 0, GaldiatorMelee, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, gladiator_cleaver_swing, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, GaldiatorMelee, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t gladiator_move_attack_melee = {FRAME_melee1, FRAME_melee17, gladiator_frames_attack_melee, gladiator_run}; - -void gladiator_melee(edict_t *self) -{ - self->monsterinfo.currentmove = &gladiator_move_attack_melee; -} - - -void GladiatorGun (edict_t *self) -{ - vec3_t start; - vec3_t dir; - vec3_t forward, right; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GLADIATOR_RAILGUN_1], forward, right, start); - - // calc direction to where we targeted - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - self->pos1[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - self->pos1[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - self->pos1[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (self->pos1, start, dir); - VectorNormalize (dir); - - monster_fire_railgun (self, start, dir, 50, 100, MZ2_GLADIATOR_RAILGUN_1); -} - -mframe_t gladiator_frames_attack_gun [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, GladiatorGun, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t gladiator_move_attack_gun = {FRAME_attack1, FRAME_attack9, gladiator_frames_attack_gun, gladiator_run}; - -void gladiator_attack(edict_t *self) -{ -/* Lazarus: What the hell is this? Why give the play a safe zone at all??? - - float range; - vec3_t v; - - // a small safe zone - VectorSubtract (self->s.origin, self->enemy->s.origin, v); - range = VectorLength(v); - if (range <= (MELEE_DISTANCE + 32)) - return; -*/ - // charge up the railgun - gi.sound (self, CHAN_WEAPON, sound_gun, 1, ATTN_NORM, 0); - VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot - self->pos1[2] += self->enemy->viewheight; - self->monsterinfo.currentmove = &gladiator_move_attack_gun; -} - - -mframe_t gladiator_frames_pain [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t gladiator_move_pain = {FRAME_pain1, FRAME_pain6, gladiator_frames_pain, gladiator_run}; - -mframe_t gladiator_frames_pain_air [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t gladiator_move_pain_air = {FRAME_painup1, FRAME_painup7, gladiator_frames_pain_air, gladiator_run}; - -void gladiator_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - { - if ((self->velocity[2] > 100) && (self->monsterinfo.currentmove == &gladiator_move_pain)) - self->monsterinfo.currentmove = &gladiator_move_pain_air; - return; - } - - self->pain_debounce_time = level.time + 3; - - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (self->velocity[2] > 100) - self->monsterinfo.currentmove = &gladiator_move_pain_air; - else - self->monsterinfo.currentmove = &gladiator_move_pain; - -} - - -void gladiator_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t gladiator_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t gladiator_move_death = {FRAME_death1, FRAME_death22, gladiator_frames_death, gladiator_dead}; - -void gladiator_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - self->monsterinfo.currentmove = &gladiator_move_death; -} - -//=========== -//PGM -bool gladiator_blocked (edict_t *self, float dist) -{ - if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) )) - return true; - - if(blocked_checkplat (self, dist)) - return true; - - return false; -} -//PGM -//=========== - -/*QUAKED monster_gladiator (1 .5 0) (-32 -32 -24) (32 32 64) Ambush Trigger_Spawn Sight -*/ -void SP_monster_gladiator (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_GLADIATOR; - - sound_pain1 = gi.soundindex ("gladiator/pain.wav"); - sound_pain2 = gi.soundindex ("gladiator/gldpain2.wav"); - sound_die = gi.soundindex ("gladiator/glddeth2.wav"); - sound_gun = gi.soundindex ("gladiator/railgun.wav"); - sound_cleaver_swing = gi.soundindex ("gladiator/melee1.wav"); - sound_cleaver_hit = gi.soundindex ("gladiator/melee2.wav"); - sound_cleaver_miss = gi.soundindex ("gladiator/melee3.wav"); - sound_idle = gi.soundindex ("gladiator/gldidle1.wav"); - sound_search = gi.soundindex ("gladiator/gldsrch1.wav"); - sound_sight = gi.soundindex ("gladiator/sight.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/gladiatr/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/gladiatr/tris.md2"); - VectorSet (self->mins, -32, -32, -24); - // Lazarus: Why so tall? -// VectorSet (self->maxs, 32, 32, 64); - VectorSet (self->maxs, 32, 32, 48); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 400; - if(!self->gib_health) - self->gib_health = -175; - if(!self->mass) - self->mass = 400; - - self->pain = gladiator_pain; - self->die = gladiator_die; - - self->monsterinfo.stand = gladiator_stand; - self->monsterinfo.walk = gladiator_walk; - self->monsterinfo.run = gladiator_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = gladiator_attack; - self->monsterinfo.melee = gladiator_melee; - self->monsterinfo.sight = gladiator_sight; - self->monsterinfo.idle = gladiator_idle; - self->monsterinfo.search = gladiator_search; - self->monsterinfo.blocked = gladiator_blocked; // PGM - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.05; - - gi.linkentity (self); - self->monsterinfo.currentmove = &gladiator_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&gladiator_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Gladiator"; - - self->monsterinfo.scale = MODEL_SCALE; - - walkmonster_start (self); -} diff --git a/server/monsters/m_gladiator.h b/server/monsters/m_gladiator.h deleted file mode 100644 index 6bdbc779..00000000 --- a/server/monsters/m_gladiator.h +++ /dev/null @@ -1,96 +0,0 @@ -// G:\quake2\baseq2\models/monsters/gladiatr - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand1 0 -#define FRAME_stand2 1 -#define FRAME_stand3 2 -#define FRAME_stand4 3 -#define FRAME_stand5 4 -#define FRAME_stand6 5 -#define FRAME_stand7 6 -#define FRAME_walk1 7 -#define FRAME_walk2 8 -#define FRAME_walk3 9 -#define FRAME_walk4 10 -#define FRAME_walk5 11 -#define FRAME_walk6 12 -#define FRAME_walk7 13 -#define FRAME_walk8 14 -#define FRAME_walk9 15 -#define FRAME_walk10 16 -#define FRAME_walk11 17 -#define FRAME_walk12 18 -#define FRAME_walk13 19 -#define FRAME_walk14 20 -#define FRAME_walk15 21 -#define FRAME_walk16 22 -#define FRAME_run1 23 -#define FRAME_run2 24 -#define FRAME_run3 25 -#define FRAME_run4 26 -#define FRAME_run5 27 -#define FRAME_run6 28 -#define FRAME_melee1 29 -#define FRAME_melee2 30 -#define FRAME_melee3 31 -#define FRAME_melee4 32 -#define FRAME_melee5 33 -#define FRAME_melee6 34 -#define FRAME_melee7 35 -#define FRAME_melee8 36 -#define FRAME_melee9 37 -#define FRAME_melee10 38 -#define FRAME_melee11 39 -#define FRAME_melee12 40 -#define FRAME_melee13 41 -#define FRAME_melee14 42 -#define FRAME_melee15 43 -#define FRAME_melee16 44 -#define FRAME_melee17 45 -#define FRAME_attack1 46 -#define FRAME_attack2 47 -#define FRAME_attack3 48 -#define FRAME_attack4 49 -#define FRAME_attack5 50 -#define FRAME_attack6 51 -#define FRAME_attack7 52 -#define FRAME_attack8 53 -#define FRAME_attack9 54 -#define FRAME_pain1 55 -#define FRAME_pain2 56 -#define FRAME_pain3 57 -#define FRAME_pain4 58 -#define FRAME_pain5 59 -#define FRAME_pain6 60 -#define FRAME_death1 61 -#define FRAME_death2 62 -#define FRAME_death3 63 -#define FRAME_death4 64 -#define FRAME_death5 65 -#define FRAME_death6 66 -#define FRAME_death7 67 -#define FRAME_death8 68 -#define FRAME_death9 69 -#define FRAME_death10 70 -#define FRAME_death11 71 -#define FRAME_death12 72 -#define FRAME_death13 73 -#define FRAME_death14 74 -#define FRAME_death15 75 -#define FRAME_death16 76 -#define FRAME_death17 77 -#define FRAME_death18 78 -#define FRAME_death19 79 -#define FRAME_death20 80 -#define FRAME_death21 81 -#define FRAME_death22 82 -#define FRAME_painup1 83 -#define FRAME_painup2 84 -#define FRAME_painup3 85 -#define FRAME_painup4 86 -#define FRAME_painup5 87 -#define FRAME_painup6 88 -#define FRAME_painup7 89 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_gunner.c b/server/monsters/m_gunner.c deleted file mode 100644 index b80b1820..00000000 --- a/server/monsters/m_gunner.c +++ /dev/null @@ -1,813 +0,0 @@ -/* -============================================================================== - -GUNNER - -============================================================================== -*/ - -#include "g_local.h" -#include "m_gunner.h" - - -static int sound_pain; -static int sound_pain2; -static int sound_death; -static int sound_idle; -static int sound_open; -static int sound_search; -static int sound_sight; - -// NOTE: Original gunner grenade velocity was 600 units/sec, but then -// fire_grenade added 200 units/sec in a direction perpendicular -// to the aim direction. We've removed that from fire_grenade -// (for the gunner, not for players) since the gunner now shoots -// smarter, and adjusted things so that the initial velocity out -// of the barrel is the same. -#define GRENADE_VELOCITY 632.4555320337 -#define GRENADE_VELOCITY_SQUARED 400000 - -void gunner_idlesound (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - -void gunner_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void gunner_search (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); -} - - -bool visible (edict_t *self, edict_t *other); -void GunnerGrenade (edict_t *self); -void GunnerFire (edict_t *self); -void gunner_fire_chain(edict_t *self); -void gunner_refire_chain(edict_t *self); - - -void gunner_stand (edict_t *self); - -mframe_t gunner_frames_fidget [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, gunner_idlesound, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t gunner_move_fidget = {FRAME_stand31, FRAME_stand70, gunner_frames_fidget, gunner_stand}; - -void gunner_fidget (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - return; - if (random() <= 0.05) - self->monsterinfo.currentmove = &gunner_move_fidget; -} - -mframe_t gunner_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, gunner_fidget, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, gunner_fidget, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, gunner_fidget -}; -mmove_t gunner_move_stand = {FRAME_stand01, FRAME_stand30, gunner_frames_stand, NULL}; - -void gunner_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &gunner_move_stand; -} - - -mframe_t gunner_frames_walk [] = -{ - ai_walk, 0, NULL, - ai_walk, 3, NULL, - ai_walk, 4, NULL, - ai_walk, 5, NULL, - ai_walk, 7, NULL, - ai_walk, 2, NULL, - ai_walk, 6, NULL, - ai_walk, 4, NULL, - ai_walk, 2, NULL, - ai_walk, 7, NULL, - ai_walk, 5, NULL, - ai_walk, 7, NULL, - ai_walk, 4, NULL -}; -mmove_t gunner_move_walk = {FRAME_walk07, FRAME_walk19, gunner_frames_walk, NULL}; - -void gunner_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &gunner_move_walk; -} - -mframe_t gunner_frames_run [] = -{ - ai_run, 26, NULL, - ai_run, 9, NULL, - ai_run, 9, NULL, - ai_run, 9, NULL, - ai_run, 15, NULL, - ai_run, 10, NULL, - ai_run, 13, NULL, - ai_run, 6, NULL -}; - -mmove_t gunner_move_run = {FRAME_run01, FRAME_run08, gunner_frames_run, NULL}; - -void gunner_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &gunner_move_stand; - else - self->monsterinfo.currentmove = &gunner_move_run; -} - -mframe_t gunner_frames_runandshoot [] = -{ - ai_run, 32, NULL, - ai_run, 15, NULL, - ai_run, 10, NULL, - ai_run, 18, NULL, - ai_run, 8, NULL, - ai_run, 20, NULL -}; - -mmove_t gunner_move_runandshoot = {FRAME_runs01, FRAME_runs06, gunner_frames_runandshoot, NULL}; - -void gunner_runandshoot (edict_t *self) -{ - self->monsterinfo.currentmove = &gunner_move_runandshoot; -} - -mframe_t gunner_frames_pain3 [] = -{ - ai_move, -3, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL -}; -mmove_t gunner_move_pain3 = {FRAME_pain301, FRAME_pain305, gunner_frames_pain3, gunner_run}; - -mframe_t gunner_frames_pain2 [] = -{ - ai_move, -2, NULL, - ai_move, 11, NULL, - ai_move, 6, NULL, - ai_move, 2, NULL, - ai_move, -1, NULL, - ai_move, -7, NULL, - ai_move, -2, NULL, - ai_move, -7, NULL -}; -mmove_t gunner_move_pain2 = {FRAME_pain201, FRAME_pain208, gunner_frames_pain2, gunner_run}; - -mframe_t gunner_frames_pain1 [] = -{ - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, -5, NULL, - ai_move, 3, NULL, - ai_move, -1, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, -2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t gunner_move_pain1 = {FRAME_pain101, FRAME_pain118, gunner_frames_pain1, gunner_run}; - -void gunner_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (rand()&1) - gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (damage <= 10) - self->monsterinfo.currentmove = &gunner_move_pain3; - else if (damage <= 25) - self->monsterinfo.currentmove = &gunner_move_pain2; - else - self->monsterinfo.currentmove = &gunner_move_pain1; -} - -void gunner_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t gunner_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -7, NULL, - ai_move, -3, NULL, - ai_move, -5, NULL, - ai_move, 8, NULL, - ai_move, 6, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t gunner_move_death = {FRAME_death01, FRAME_death11, gunner_frames_death, gunner_dead}; - -void gunner_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->monsterinfo.currentmove = &gunner_move_death; -} - -bool gunner_grenade_check(edict_t *self) -{ - vec3_t start; - vec3_t forward, right; - vec3_t target; - trace_t tr; - vec3_t dir; - vec3_t vhorz; - float horz,vertmax; - - if(!self->enemy) - return false; - - // if the player is above my head, use machinegun. - -// if(self->absmax[2] <= self->enemy->absmin[2]) -// return false; - - // Lazarus: We can do better than that... see below - - - // check to see that we can trace to the player before we start - // tossing grenades around. - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GUNNER_GRENADE_1], forward, right, start); - - // see if we're too close - VectorSubtract (self->enemy->s.origin, self->s.origin, dir); - if (VectorLength(dir) < 100) - return false; - - // Lazarus: Max vertical distance - this is approximate and conservative - VectorCopy(dir,vhorz); - vhorz[2] = 0; - horz = VectorLength(vhorz); - vertmax = (GRENADE_VELOCITY_SQUARED)/(2*sv_gravity->value) - - 0.5*sv_gravity->value*horz*horz/GRENADE_VELOCITY_SQUARED; - if(dir[2] > vertmax) - return false; - - // Lazarus: Make sure there's a more-or-less clear flight path to target - // Rogue checked target origin, but if target is above gunner then the trace - // would almost always hit the platform the target was standing on - VectorCopy(self->enemy->s.origin,target); - target[2] = self->enemy->absmax[2]; - tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT); - if(tr.ent == self->enemy || tr.fraction == 1) - return true; - // Repeat for feet... in case we're looking down at a target standing under, - // for example, a short doorway - target[2] = self->enemy->absmin[2]; - tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT); - if(tr.ent == self->enemy || tr.fraction == 1) - return true; - - return false; -} - -void gunner_duck_down (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - self->monsterinfo.aiflags |= AI_DUCKED; - if (skill->value >= 2) - { - // Lazarus: Added check for goodness of grenade firing - if (random() > 0.5 && gunner_grenade_check(self)) - GunnerGrenade (self); - } - - self->maxs[2] -= 32; - self->takedamage = DAMAGE_YES; - self->monsterinfo.pausetime = level.time + 1; - gi.linkentity (self); -} - -void gunner_duck_hold (edict_t *self) -{ - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -void gunner_duck_up (edict_t *self) -{ - self->monsterinfo.aiflags &= ~AI_DUCKED; - self->maxs[2] += 32; - self->takedamage = DAMAGE_AIM; - gi.linkentity (self); -} - -mframe_t gunner_frames_duck [] = -{ - ai_move, 1, gunner_duck_down, - ai_move, 1, NULL, - ai_move, 1, gunner_duck_hold, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, 0, gunner_duck_up, - ai_move, -1, NULL -}; -mmove_t gunner_move_duck = {FRAME_duck01, FRAME_duck08, gunner_frames_duck, gunner_run}; - -void gunner_dodge (edict_t *self, edict_t *attacker, float eta) -{ - if (random() > 0.25) - return; - - if (!self->enemy) - self->enemy = attacker; - - self->monsterinfo.currentmove = &gunner_move_duck; -} - -void gunner_opengun (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_open, 1, ATTN_IDLE, 0); -} - -void GunnerFire (edict_t *self) -{ - vec3_t start; - vec3_t forward, right; - vec3_t target; - vec3_t aim; - int flash_number; - - flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216); - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - // project enemy back a bit and target there - VectorCopy (self->enemy->s.origin, target); - VectorMA (target, -0.2, self->enemy->velocity, target); - target[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (target, start, aim); - VectorNormalize (aim); - monster_fire_bullet (self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); -} - -void GunnerGrenade (edict_t *self) -{ - vec3_t start,target; - vec3_t forward, right, up; - vec3_t aim; - vec_t monster_speed; - int flash_number; - - if(!self->enemy || !self->enemy->inuse) - return; - - if (self->s.frame == FRAME_attak105) - flash_number = MZ2_GUNNER_GRENADE_1; - else if (self->s.frame == FRAME_attak108) - { - if(skill->value == 0) - return; - flash_number = MZ2_GUNNER_GRENADE_2; - } - else if (self->s.frame == FRAME_attak111) - flash_number = MZ2_GUNNER_GRENADE_3; - else // (self->s.frame == FRAME_attak114) - { - if(skill->value < 2) - return; - flash_number = MZ2_GUNNER_GRENADE_4; - } - - AngleVectors (self->s.angles, forward, right, up); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - // Lazarus - Improved gunner's grenade-aiming ability quite a bit - -// VectorCopy (forward, aim); - - // aim at enemy's feet if he's at same elevation or lower. otherwise aim at origin - VectorCopy(self->enemy->s.origin,target); - if(self->enemy->absmin[2] <= self->absmax[2]) target[2] = self->enemy->absmin[2]; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - // Lazarus - skill level-dependent accuracy -/* if(skill->value < 2) - { - float dist; - - VectorSubtract(target, start, aim); - dist = VectorLength (aim); - dist = min(dist,512); - - target[0] += crandom() * dist/8 * (2 - skill->value); - target[1] += crandom() * dist/8 * (2 - skill->value); - } */ - - // lead target... 20, 35, 50, 65 chance of leading - if( random() < (0.2 + skill->value * 0.15) ) - { - float dist; - float time; - - VectorSubtract(target, start, aim); - dist = VectorLength (aim); - time = dist/GRENADE_VELOCITY; // Not correct, but better than nothin' - VectorMA(target, time, self->enemy->velocity, target); - } - - AimGrenade (self, start, target, GRENADE_VELOCITY, aim); - // Lazarus - take into account (sort of) feature of adding shooter's velocity to - // grenade velocity - monster_speed = VectorLength(self->velocity); - if(monster_speed > 0) { - vec3_t v1; - vec_t delta; - - VectorCopy(self->velocity,v1); - VectorNormalize(v1); - delta = -monster_speed/GRENADE_VELOCITY; - VectorMA(aim,delta,v1,aim); - VectorNormalize(aim); - } - - monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number); -} - -mframe_t gunner_frames_attack_chain [] = -{ - /* - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - */ - ai_charge, 0, gunner_opengun, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t gunner_move_attack_chain = {FRAME_attak209, FRAME_attak215, gunner_frames_attack_chain, gunner_fire_chain}; - -mframe_t gunner_frames_fire_chain [] = -{ - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire, - ai_charge, 0, GunnerFire -}; -mmove_t gunner_move_fire_chain = {FRAME_attak216, FRAME_attak223, gunner_frames_fire_chain, gunner_refire_chain}; - -mframe_t gunner_frames_endfire_chain [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t gunner_move_endfire_chain = {FRAME_attak224, FRAME_attak230, gunner_frames_endfire_chain, gunner_run}; - -mframe_t gunner_frames_attack_grenade [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, GunnerGrenade, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, GunnerGrenade, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, GunnerGrenade, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, GunnerGrenade, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t gunner_move_attack_grenade = {FRAME_attak101, FRAME_attak121, gunner_frames_attack_grenade, gunner_run}; - -void gunner_attack(edict_t *self) -{ - if (range (self, self->enemy) == RANGE_MELEE) - { - self->monsterinfo.currentmove = &gunner_move_attack_chain; - } - else - { - // Lazarus: Added bit of logic to check whether grenades are good to fire, - // and made it more likely to fire grenades on harder skill levels - if (random() <= (0.5 + 0.05*skill->value) && gunner_grenade_check(self) ) - self->monsterinfo.currentmove = &gunner_move_attack_grenade; - else - self->monsterinfo.currentmove = &gunner_move_attack_chain; - } -} - -void gunner_fire_chain(edict_t *self) -{ - self->monsterinfo.currentmove = &gunner_move_fire_chain; -} - -void gunner_refire_chain(edict_t *self) -{ - if (self->enemy->health > 0) - if ( visible (self, self->enemy) ) - if (random() <= 0.5) - { - self->monsterinfo.currentmove = &gunner_move_fire_chain; - return; - } - self->monsterinfo.currentmove = &gunner_move_endfire_chain; -} - -mframe_t gunner_frames_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t gunner_move_jump = { FRAME_run01, FRAME_run08, gunner_frames_jump, gunner_run }; - -void gunner_jump (edict_t *self) -{ - self->monsterinfo.currentmove = &gunner_move_jump; -} - -/*QUAKED monster_gunner (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_gunner (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_GUNNER; - - sound_death = gi.soundindex ("gunner/death1.wav"); - sound_pain = gi.soundindex ("gunner/gunpain2.wav"); - sound_pain2 = gi.soundindex ("gunner/gunpain1.wav"); - sound_idle = gi.soundindex ("gunner/gunidle1.wav"); - sound_open = gi.soundindex ("gunner/gunatck1.wav"); - sound_search = gi.soundindex ("gunner/gunsrch1.wav"); - sound_sight = gi.soundindex ("gunner/sight1.wav"); - if(monsterjump->value) - { - self->monsterinfo.jump = gunner_jump; - self->monsterinfo.jumpup = 48; - self->monsterinfo.jumpdn = 64; - } - - gi.soundindex ("gunner/gunatck2.wav"); - gi.soundindex ("gunner/gunatck3.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/gunner/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/gunner/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 175; - if(!self->gib_health) - self->gib_health = -70; - if(!self->mass) - self->mass = 200; - - self->pain = gunner_pain; - self->die = gunner_die; - - self->monsterinfo.stand = gunner_stand; - self->monsterinfo.walk = gunner_walk; - self->monsterinfo.run = gunner_run; - self->monsterinfo.dodge = gunner_dodge; - self->monsterinfo.attack = gunner_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = gunner_sight; - self->monsterinfo.search = gunner_search; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.30; - - // Lazarus - use move_origin for grenade aiming - VectorCopy(monster_flash_offset[MZ2_GUNNER_GRENADE_1],self->move_origin); - - gi.linkentity (self); - self->monsterinfo.currentmove = &gunner_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&gunner_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Gunner"; - - self->monsterinfo.scale = MODEL_SCALE; - - walkmonster_start (self); -} diff --git a/server/monsters/m_gunner.h b/server/monsters/m_gunner.h deleted file mode 100644 index fc3f5324..00000000 --- a/server/monsters/m_gunner.h +++ /dev/null @@ -1,215 +0,0 @@ -// G:\quake2\baseq2\models/gunner - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand01 0 -#define FRAME_stand02 1 -#define FRAME_stand03 2 -#define FRAME_stand04 3 -#define FRAME_stand05 4 -#define FRAME_stand06 5 -#define FRAME_stand07 6 -#define FRAME_stand08 7 -#define FRAME_stand09 8 -#define FRAME_stand10 9 -#define FRAME_stand11 10 -#define FRAME_stand12 11 -#define FRAME_stand13 12 -#define FRAME_stand14 13 -#define FRAME_stand15 14 -#define FRAME_stand16 15 -#define FRAME_stand17 16 -#define FRAME_stand18 17 -#define FRAME_stand19 18 -#define FRAME_stand20 19 -#define FRAME_stand21 20 -#define FRAME_stand22 21 -#define FRAME_stand23 22 -#define FRAME_stand24 23 -#define FRAME_stand25 24 -#define FRAME_stand26 25 -#define FRAME_stand27 26 -#define FRAME_stand28 27 -#define FRAME_stand29 28 -#define FRAME_stand30 29 -#define FRAME_stand31 30 -#define FRAME_stand32 31 -#define FRAME_stand33 32 -#define FRAME_stand34 33 -#define FRAME_stand35 34 -#define FRAME_stand36 35 -#define FRAME_stand37 36 -#define FRAME_stand38 37 -#define FRAME_stand39 38 -#define FRAME_stand40 39 -#define FRAME_stand41 40 -#define FRAME_stand42 41 -#define FRAME_stand43 42 -#define FRAME_stand44 43 -#define FRAME_stand45 44 -#define FRAME_stand46 45 -#define FRAME_stand47 46 -#define FRAME_stand48 47 -#define FRAME_stand49 48 -#define FRAME_stand50 49 -#define FRAME_stand51 50 -#define FRAME_stand52 51 -#define FRAME_stand53 52 -#define FRAME_stand54 53 -#define FRAME_stand55 54 -#define FRAME_stand56 55 -#define FRAME_stand57 56 -#define FRAME_stand58 57 -#define FRAME_stand59 58 -#define FRAME_stand60 59 -#define FRAME_stand61 60 -#define FRAME_stand62 61 -#define FRAME_stand63 62 -#define FRAME_stand64 63 -#define FRAME_stand65 64 -#define FRAME_stand66 65 -#define FRAME_stand67 66 -#define FRAME_stand68 67 -#define FRAME_stand69 68 -#define FRAME_stand70 69 -#define FRAME_walk01 70 -#define FRAME_walk02 71 -#define FRAME_walk03 72 -#define FRAME_walk04 73 -#define FRAME_walk05 74 -#define FRAME_walk06 75 -#define FRAME_walk07 76 -#define FRAME_walk08 77 -#define FRAME_walk09 78 -#define FRAME_walk10 79 -#define FRAME_walk11 80 -#define FRAME_walk12 81 -#define FRAME_walk13 82 -#define FRAME_walk14 83 -#define FRAME_walk15 84 -#define FRAME_walk16 85 -#define FRAME_walk17 86 -#define FRAME_walk18 87 -#define FRAME_walk19 88 -#define FRAME_walk20 89 -#define FRAME_walk21 90 -#define FRAME_walk22 91 -#define FRAME_walk23 92 -#define FRAME_walk24 93 -#define FRAME_run01 94 -#define FRAME_run02 95 -#define FRAME_run03 96 -#define FRAME_run04 97 -#define FRAME_run05 98 -#define FRAME_run06 99 -#define FRAME_run07 100 -#define FRAME_run08 101 -#define FRAME_runs01 102 -#define FRAME_runs02 103 -#define FRAME_runs03 104 -#define FRAME_runs04 105 -#define FRAME_runs05 106 -#define FRAME_runs06 107 -#define FRAME_attak101 108 -#define FRAME_attak102 109 -#define FRAME_attak103 110 -#define FRAME_attak104 111 -#define FRAME_attak105 112 -#define FRAME_attak106 113 -#define FRAME_attak107 114 -#define FRAME_attak108 115 -#define FRAME_attak109 116 -#define FRAME_attak110 117 -#define FRAME_attak111 118 -#define FRAME_attak112 119 -#define FRAME_attak113 120 -#define FRAME_attak114 121 -#define FRAME_attak115 122 -#define FRAME_attak116 123 -#define FRAME_attak117 124 -#define FRAME_attak118 125 -#define FRAME_attak119 126 -#define FRAME_attak120 127 -#define FRAME_attak121 128 -#define FRAME_attak201 129 -#define FRAME_attak202 130 -#define FRAME_attak203 131 -#define FRAME_attak204 132 -#define FRAME_attak205 133 -#define FRAME_attak206 134 -#define FRAME_attak207 135 -#define FRAME_attak208 136 -#define FRAME_attak209 137 -#define FRAME_attak210 138 -#define FRAME_attak211 139 -#define FRAME_attak212 140 -#define FRAME_attak213 141 -#define FRAME_attak214 142 -#define FRAME_attak215 143 -#define FRAME_attak216 144 -#define FRAME_attak217 145 -#define FRAME_attak218 146 -#define FRAME_attak219 147 -#define FRAME_attak220 148 -#define FRAME_attak221 149 -#define FRAME_attak222 150 -#define FRAME_attak223 151 -#define FRAME_attak224 152 -#define FRAME_attak225 153 -#define FRAME_attak226 154 -#define FRAME_attak227 155 -#define FRAME_attak228 156 -#define FRAME_attak229 157 -#define FRAME_attak230 158 -#define FRAME_pain101 159 -#define FRAME_pain102 160 -#define FRAME_pain103 161 -#define FRAME_pain104 162 -#define FRAME_pain105 163 -#define FRAME_pain106 164 -#define FRAME_pain107 165 -#define FRAME_pain108 166 -#define FRAME_pain109 167 -#define FRAME_pain110 168 -#define FRAME_pain111 169 -#define FRAME_pain112 170 -#define FRAME_pain113 171 -#define FRAME_pain114 172 -#define FRAME_pain115 173 -#define FRAME_pain116 174 -#define FRAME_pain117 175 -#define FRAME_pain118 176 -#define FRAME_pain201 177 -#define FRAME_pain202 178 -#define FRAME_pain203 179 -#define FRAME_pain204 180 -#define FRAME_pain205 181 -#define FRAME_pain206 182 -#define FRAME_pain207 183 -#define FRAME_pain208 184 -#define FRAME_pain301 185 -#define FRAME_pain302 186 -#define FRAME_pain303 187 -#define FRAME_pain304 188 -#define FRAME_pain305 189 -#define FRAME_death01 190 -#define FRAME_death02 191 -#define FRAME_death03 192 -#define FRAME_death04 193 -#define FRAME_death05 194 -#define FRAME_death06 195 -#define FRAME_death07 196 -#define FRAME_death08 197 -#define FRAME_death09 198 -#define FRAME_death10 199 -#define FRAME_death11 200 -#define FRAME_duck01 201 -#define FRAME_duck02 202 -#define FRAME_duck03 203 -#define FRAME_duck04 204 -#define FRAME_duck05 205 -#define FRAME_duck06 206 -#define FRAME_duck07 207 -#define FRAME_duck08 208 - -#define MODEL_SCALE 1.150000 diff --git a/server/monsters/m_hover.c b/server/monsters/m_hover.c deleted file mode 100644 index a663f312..00000000 --- a/server/monsters/m_hover.c +++ /dev/null @@ -1,634 +0,0 @@ -/* -============================================================================== - -hover - -============================================================================== -*/ - -#include "g_local.h" -#include "m_hover.h" - -bool visible (edict_t *self, edict_t *other); - - -static int sound_pain1; -static int sound_pain2; -static int sound_death1; -static int sound_death2; -static int sound_sight; -static int sound_search1; -static int sound_search2; - - -void hover_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void hover_search (edict_t *self) -{ - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); -} - - -void hover_run (edict_t *self); -void hover_stand (edict_t *self); -void hover_dead (edict_t *self); -void hover_attack (edict_t *self); -void hover_reattack (edict_t *self); -void hover_fire_blaster (edict_t *self); -void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); - -mframe_t hover_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t hover_move_stand = {FRAME_stand01, FRAME_stand30, hover_frames_stand, NULL}; - -mframe_t hover_frames_stop1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_stop1 = {FRAME_stop101, FRAME_stop109, hover_frames_stop1, NULL}; - -mframe_t hover_frames_stop2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_stop2 = {FRAME_stop201, FRAME_stop208, hover_frames_stop2, NULL}; - -mframe_t hover_frames_takeoff [] = -{ - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, 5, NULL, - ai_move, -1, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, -6, NULL, - ai_move, -9, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_takeoff = {FRAME_takeof01, FRAME_takeof30, hover_frames_takeoff, NULL}; - -mframe_t hover_frames_pain3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_pain3 = {FRAME_pain301, FRAME_pain309, hover_frames_pain3, hover_run}; - -mframe_t hover_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_pain2 = {FRAME_pain201, FRAME_pain212, hover_frames_pain2, hover_run}; - -mframe_t hover_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, -8, NULL, - ai_move, -4, NULL, - ai_move, -6, NULL, - ai_move, -4, NULL, - ai_move, -3, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 3, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, 7, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 5, NULL, - ai_move, 3, NULL, - ai_move, 4, NULL -}; -mmove_t hover_move_pain1 = {FRAME_pain101, FRAME_pain128, hover_frames_pain1, hover_run}; - -mframe_t hover_frames_land [] = -{ - ai_move, 0, NULL -}; -mmove_t hover_move_land = {FRAME_land01, FRAME_land01, hover_frames_land, NULL}; - -mframe_t hover_frames_forward [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_forward = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_forward, NULL}; - -mframe_t hover_frames_walk [] = -{ - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL -}; -mmove_t hover_move_walk = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_walk, NULL}; - -mframe_t hover_frames_run [] = -{ - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL, - ai_run, 10, NULL -}; -mmove_t hover_move_run = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_run, NULL}; - -mframe_t hover_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -10,NULL, - ai_move, 3, NULL, - ai_move, 5, NULL, - ai_move, 4, NULL, - ai_move, 7, NULL -}; -mmove_t hover_move_death1 = {FRAME_death101, FRAME_death111, hover_frames_death1, hover_dead}; - -mframe_t hover_frames_backward [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t hover_move_backward = {FRAME_backwd01, FRAME_backwd24, hover_frames_backward, NULL}; - -mframe_t hover_frames_start_attack [] = -{ - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL -}; -mmove_t hover_move_start_attack = {FRAME_attak101, FRAME_attak103, hover_frames_start_attack, hover_attack}; - -mframe_t hover_frames_attack1 [] = -{ - ai_charge, -10, hover_fire_blaster, - ai_charge, -10, hover_fire_blaster, - ai_charge, 0, hover_reattack, -}; -mmove_t hover_move_attack1 = {FRAME_attak104, FRAME_attak106, hover_frames_attack1, NULL}; - - -mframe_t hover_frames_end_attack [] = -{ - ai_charge, 1, NULL, - ai_charge, 1, NULL -}; -mmove_t hover_move_end_attack = {FRAME_attak107, FRAME_attak108, hover_frames_end_attack, hover_run}; - -void hover_reattack (edict_t *self) -{ - if (self->enemy->health > 0 ) - if (visible (self, self->enemy) ) - if (random() <= 0.6) - { - self->monsterinfo.currentmove = &hover_move_attack1; - return; - } - self->monsterinfo.currentmove = &hover_move_end_attack; -} - - -void hover_fire_blaster (edict_t *self) -{ - vec3_t start; - vec3_t forward, right; - vec3_t end; - vec3_t dir; - int effect; - - if (self->s.frame == FRAME_attak104) - effect = EF_HYPERBLASTER; - else - effect = 0; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start); - - VectorCopy (self->enemy->s.origin, end); - end[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (end, start, dir); - monster_fire_blaster (self, start, dir, 1, 1000, MZ2_HOVER_BLASTER_1, effect); -} - - -void hover_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &hover_move_stand; -} - -void hover_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &hover_move_stand; - else - self->monsterinfo.currentmove = &hover_move_run; -} - -void hover_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &hover_move_walk; -} - -void hover_start_attack (edict_t *self) -{ - self->monsterinfo.currentmove = &hover_move_start_attack; -} - -void hover_attack(edict_t *self) -{ - self->monsterinfo.currentmove = &hover_move_attack1; -} - - -void hover_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (damage <= 25) - { - if (random() < 0.5) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &hover_move_pain3; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &hover_move_pain2; - } - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &hover_move_pain1; - } -} - -void hover_deadthink (edict_t *self) -{ - if (!self->groundentity && level.time < self->timestamp) - { - self->nextthink = level.time + FRAMETIME; - return; - } - BecomeExplosion1(self); -} - -void hover_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->think = hover_deadthink; - self->nextthink = level.time + FRAMETIME; - self->timestamp = level.time + 15; - gi.linkentity (self); -} - -void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->monsterinfo.currentmove = &hover_move_death1; -} - -/*QUAKED monster_hover (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_hover (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_HOVER; - - sound_pain1 = gi.soundindex ("hover/hovpain1.wav"); - sound_pain2 = gi.soundindex ("hover/hovpain2.wav"); - sound_death1 = gi.soundindex ("hover/hovdeth1.wav"); - sound_death2 = gi.soundindex ("hover/hovdeth2.wav"); - sound_sight = gi.soundindex ("hover/hovsght1.wav"); - sound_search1 = gi.soundindex ("hover/hovsrch1.wav"); - sound_search2 = gi.soundindex ("hover/hovsrch2.wav"); - - gi.soundindex ("hover/hovatck1.wav"); - - self->s.sound = gi.soundindex ("hover/hovidle1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/hover/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex("models/monsters/hover/tris.md2"); - VectorSet (self->mins, -24, -24, -24); - VectorSet (self->maxs, 24, 24, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 240; - if(!self->gib_health) - self->gib_health = -100; - if(!self->mass) - self->mass = 150; - - self->pain = hover_pain; - self->die = hover_die; - - self->monsterinfo.stand = hover_stand; - self->monsterinfo.walk = hover_walk; - self->monsterinfo.run = hover_run; -// self->monsterinfo.dodge = hover_dodge; - self->monsterinfo.attack = hover_start_attack; - self->monsterinfo.sight = hover_sight; - self->monsterinfo.search = hover_search; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - - gi.linkentity (self); - self->monsterinfo.currentmove = &hover_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&hover_move_death1, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Icarus"; - self->monsterinfo.scale = MODEL_SCALE; - - flymonster_start (self); -} diff --git a/server/monsters/m_hover.h b/server/monsters/m_hover.h deleted file mode 100644 index 74c8684b..00000000 --- a/server/monsters/m_hover.h +++ /dev/null @@ -1,211 +0,0 @@ -// G:\quake2\baseq2\models/monsters/hover - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand01 0 -#define FRAME_stand02 1 -#define FRAME_stand03 2 -#define FRAME_stand04 3 -#define FRAME_stand05 4 -#define FRAME_stand06 5 -#define FRAME_stand07 6 -#define FRAME_stand08 7 -#define FRAME_stand09 8 -#define FRAME_stand10 9 -#define FRAME_stand11 10 -#define FRAME_stand12 11 -#define FRAME_stand13 12 -#define FRAME_stand14 13 -#define FRAME_stand15 14 -#define FRAME_stand16 15 -#define FRAME_stand17 16 -#define FRAME_stand18 17 -#define FRAME_stand19 18 -#define FRAME_stand20 19 -#define FRAME_stand21 20 -#define FRAME_stand22 21 -#define FRAME_stand23 22 -#define FRAME_stand24 23 -#define FRAME_stand25 24 -#define FRAME_stand26 25 -#define FRAME_stand27 26 -#define FRAME_stand28 27 -#define FRAME_stand29 28 -#define FRAME_stand30 29 -#define FRAME_forwrd01 30 -#define FRAME_forwrd02 31 -#define FRAME_forwrd03 32 -#define FRAME_forwrd04 33 -#define FRAME_forwrd05 34 -#define FRAME_forwrd06 35 -#define FRAME_forwrd07 36 -#define FRAME_forwrd08 37 -#define FRAME_forwrd09 38 -#define FRAME_forwrd10 39 -#define FRAME_forwrd11 40 -#define FRAME_forwrd12 41 -#define FRAME_forwrd13 42 -#define FRAME_forwrd14 43 -#define FRAME_forwrd15 44 -#define FRAME_forwrd16 45 -#define FRAME_forwrd17 46 -#define FRAME_forwrd18 47 -#define FRAME_forwrd19 48 -#define FRAME_forwrd20 49 -#define FRAME_forwrd21 50 -#define FRAME_forwrd22 51 -#define FRAME_forwrd23 52 -#define FRAME_forwrd24 53 -#define FRAME_forwrd25 54 -#define FRAME_forwrd26 55 -#define FRAME_forwrd27 56 -#define FRAME_forwrd28 57 -#define FRAME_forwrd29 58 -#define FRAME_forwrd30 59 -#define FRAME_forwrd31 60 -#define FRAME_forwrd32 61 -#define FRAME_forwrd33 62 -#define FRAME_forwrd34 63 -#define FRAME_forwrd35 64 -#define FRAME_stop101 65 -#define FRAME_stop102 66 -#define FRAME_stop103 67 -#define FRAME_stop104 68 -#define FRAME_stop105 69 -#define FRAME_stop106 70 -#define FRAME_stop107 71 -#define FRAME_stop108 72 -#define FRAME_stop109 73 -#define FRAME_stop201 74 -#define FRAME_stop202 75 -#define FRAME_stop203 76 -#define FRAME_stop204 77 -#define FRAME_stop205 78 -#define FRAME_stop206 79 -#define FRAME_stop207 80 -#define FRAME_stop208 81 -#define FRAME_takeof01 82 -#define FRAME_takeof02 83 -#define FRAME_takeof03 84 -#define FRAME_takeof04 85 -#define FRAME_takeof05 86 -#define FRAME_takeof06 87 -#define FRAME_takeof07 88 -#define FRAME_takeof08 89 -#define FRAME_takeof09 90 -#define FRAME_takeof10 91 -#define FRAME_takeof11 92 -#define FRAME_takeof12 93 -#define FRAME_takeof13 94 -#define FRAME_takeof14 95 -#define FRAME_takeof15 96 -#define FRAME_takeof16 97 -#define FRAME_takeof17 98 -#define FRAME_takeof18 99 -#define FRAME_takeof19 100 -#define FRAME_takeof20 101 -#define FRAME_takeof21 102 -#define FRAME_takeof22 103 -#define FRAME_takeof23 104 -#define FRAME_takeof24 105 -#define FRAME_takeof25 106 -#define FRAME_takeof26 107 -#define FRAME_takeof27 108 -#define FRAME_takeof28 109 -#define FRAME_takeof29 110 -#define FRAME_takeof30 111 -#define FRAME_land01 112 -#define FRAME_pain101 113 -#define FRAME_pain102 114 -#define FRAME_pain103 115 -#define FRAME_pain104 116 -#define FRAME_pain105 117 -#define FRAME_pain106 118 -#define FRAME_pain107 119 -#define FRAME_pain108 120 -#define FRAME_pain109 121 -#define FRAME_pain110 122 -#define FRAME_pain111 123 -#define FRAME_pain112 124 -#define FRAME_pain113 125 -#define FRAME_pain114 126 -#define FRAME_pain115 127 -#define FRAME_pain116 128 -#define FRAME_pain117 129 -#define FRAME_pain118 130 -#define FRAME_pain119 131 -#define FRAME_pain120 132 -#define FRAME_pain121 133 -#define FRAME_pain122 134 -#define FRAME_pain123 135 -#define FRAME_pain124 136 -#define FRAME_pain125 137 -#define FRAME_pain126 138 -#define FRAME_pain127 139 -#define FRAME_pain128 140 -#define FRAME_pain201 141 -#define FRAME_pain202 142 -#define FRAME_pain203 143 -#define FRAME_pain204 144 -#define FRAME_pain205 145 -#define FRAME_pain206 146 -#define FRAME_pain207 147 -#define FRAME_pain208 148 -#define FRAME_pain209 149 -#define FRAME_pain210 150 -#define FRAME_pain211 151 -#define FRAME_pain212 152 -#define FRAME_pain301 153 -#define FRAME_pain302 154 -#define FRAME_pain303 155 -#define FRAME_pain304 156 -#define FRAME_pain305 157 -#define FRAME_pain306 158 -#define FRAME_pain307 159 -#define FRAME_pain308 160 -#define FRAME_pain309 161 -#define FRAME_death101 162 -#define FRAME_death102 163 -#define FRAME_death103 164 -#define FRAME_death104 165 -#define FRAME_death105 166 -#define FRAME_death106 167 -#define FRAME_death107 168 -#define FRAME_death108 169 -#define FRAME_death109 170 -#define FRAME_death110 171 -#define FRAME_death111 172 -#define FRAME_backwd01 173 -#define FRAME_backwd02 174 -#define FRAME_backwd03 175 -#define FRAME_backwd04 176 -#define FRAME_backwd05 177 -#define FRAME_backwd06 178 -#define FRAME_backwd07 179 -#define FRAME_backwd08 180 -#define FRAME_backwd09 181 -#define FRAME_backwd10 182 -#define FRAME_backwd11 183 -#define FRAME_backwd12 184 -#define FRAME_backwd13 185 -#define FRAME_backwd14 186 -#define FRAME_backwd15 187 -#define FRAME_backwd16 188 -#define FRAME_backwd17 189 -#define FRAME_backwd18 190 -#define FRAME_backwd19 191 -#define FRAME_backwd20 192 -#define FRAME_backwd21 193 -#define FRAME_backwd22 194 -#define FRAME_backwd23 195 -#define FRAME_backwd24 196 -#define FRAME_attak101 197 -#define FRAME_attak102 198 -#define FRAME_attak103 199 -#define FRAME_attak104 200 -#define FRAME_attak105 201 -#define FRAME_attak106 202 -#define FRAME_attak107 203 -#define FRAME_attak108 204 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_infantry.c b/server/monsters/m_infantry.c deleted file mode 100644 index 063cc397..00000000 --- a/server/monsters/m_infantry.c +++ /dev/null @@ -1,666 +0,0 @@ -/* -============================================================================== - -INFANTRY - -============================================================================== -*/ - -#include "g_local.h" -#include "m_infantry.h" - -void InfantryMachineGun (edict_t *self); - - -static int sound_pain1; -static int sound_pain2; -static int sound_die1; -static int sound_die2; - -static int sound_gunshot; -static int sound_weapon_cock; -static int sound_punch_swing; -static int sound_punch_hit; -static int sound_sight; -static int sound_search; -static int sound_idle; - - -mframe_t infantry_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t infantry_move_stand = {FRAME_stand50, FRAME_stand71, infantry_frames_stand, NULL}; - -void infantry_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &infantry_move_stand; -} - - -mframe_t infantry_frames_fidget [] = -{ - ai_stand, 1, NULL, - ai_stand, 0, NULL, - ai_stand, 1, NULL, - ai_stand, 3, NULL, - ai_stand, 6, NULL, - ai_stand, 3, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 1, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 1, NULL, - ai_stand, 0, NULL, - ai_stand, -1, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 1, NULL, - ai_stand, 0, NULL, - ai_stand, -2, NULL, - ai_stand, 1, NULL, - ai_stand, 1, NULL, - ai_stand, 1, NULL, - ai_stand, -1, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, -1, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, -1, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 1, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, -1, NULL, - ai_stand, -1, NULL, - ai_stand, 0, NULL, - ai_stand, -3, NULL, - ai_stand, -2, NULL, - ai_stand, -3, NULL, - ai_stand, -3, NULL, - ai_stand, -2, NULL -}; -mmove_t infantry_move_fidget = {FRAME_stand01, FRAME_stand49, infantry_frames_fidget, infantry_stand}; - -void infantry_fidget (edict_t *self) -{ - self->monsterinfo.currentmove = &infantry_move_fidget; - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - -mframe_t infantry_frames_walk [] = -{ - ai_walk, 5, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 5, NULL, - ai_walk, 4, NULL, - ai_walk, 5, NULL, - ai_walk, 6, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 5, NULL -}; -mmove_t infantry_move_walk = {FRAME_walk03, FRAME_walk14, infantry_frames_walk, NULL}; - -void infantry_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &infantry_move_walk; -} - -mframe_t infantry_frames_run [] = -{ - ai_run, 10, NULL, - ai_run, 20, NULL, - ai_run, 5, NULL, - ai_run, 7, NULL, - ai_run, 30, NULL, - ai_run, 35, NULL, - ai_run, 2, NULL, - ai_run, 6, NULL -}; -mmove_t infantry_move_run = {FRAME_run01, FRAME_run08, infantry_frames_run, NULL}; - -void infantry_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &infantry_move_stand; - else - self->monsterinfo.currentmove = &infantry_move_run; -} - - -mframe_t infantry_frames_pain1 [] = -{ - ai_move, -3, NULL, - ai_move, -2, NULL, - ai_move, -1, NULL, - ai_move, -2, NULL, - ai_move, -1, NULL, - ai_move, 1, NULL, - ai_move, -1, NULL, - ai_move, 1, NULL, - ai_move, 6, NULL, - ai_move, 2, NULL -}; -mmove_t infantry_move_pain1 = {FRAME_pain101, FRAME_pain110, infantry_frames_pain1, infantry_run}; - -mframe_t infantry_frames_pain2 [] = -{ - ai_move, -3, NULL, - ai_move, -3, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 5, NULL, - ai_move, 2, NULL -}; -mmove_t infantry_move_pain2 = {FRAME_pain201, FRAME_pain210, infantry_frames_pain2, infantry_run}; - -void infantry_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - int n; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - n = rand() % 2; - if (n == 0) - { - self->monsterinfo.currentmove = &infantry_move_pain1; - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - } - else - { - self->monsterinfo.currentmove = &infantry_move_pain2; - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - } -} - - -vec3_t aimangles[] = -{ - 0.0, 5.0, 0.0, - 10.0, 15.0, 0.0, - 20.0, 25.0, 0.0, - 25.0, 35.0, 0.0, - 30.0, 40.0, 0.0, - 30.0, 45.0, 0.0, - 25.0, 50.0, 0.0, - 20.0, 40.0, 0.0, - 15.0, 35.0, 0.0, - 40.0, 35.0, 0.0, - 70.0, 35.0, 0.0, - 90.0, 35.0, 0.0 -}; - -void InfantryMachineGun (edict_t *self) -{ - vec3_t start, target; - vec3_t forward, right; - vec3_t vec; - int flash_number; - - if (self->s.frame == FRAME_attak111) - { - flash_number = MZ2_INFANTRY_MACHINEGUN_1; - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - if (self->enemy && self->enemy->inuse) - { - VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); - target[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (target, start, forward); - VectorNormalize (forward); - } - else - { - AngleVectors (self->s.angles, forward, right, NULL); - } - } - else - { - flash_number = MZ2_INFANTRY_MACHINEGUN_2 + (self->s.frame - FRAME_death211); - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - VectorSubtract (self->s.angles, aimangles[flash_number-MZ2_INFANTRY_MACHINEGUN_2], vec); - AngleVectors (vec, forward, NULL, NULL); - } - - monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); -} - -void infantry_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_BODY, sound_sight, 1, ATTN_NORM, 0); -} - -void infantry_dead (edict_t *self) -{ - // Lazarus: Stupid... if flies aren't set by M_FlyCheck, monster_think - // will cause us to come back here over and over and over - // until flies ARE set or monster is gibbed. - // This line fixes that: - self->nextthink = 0; - - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } - -} - -mframe_t infantry_frames_death1 [] = -{ - ai_move, -4, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -4, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, 3, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, -2, NULL, - ai_move, 2, NULL, - ai_move, 2, NULL, - ai_move, 9, NULL, - ai_move, 9, NULL, - ai_move, 5, NULL, - ai_move, -3, NULL, - ai_move, -3, NULL -}; -mmove_t infantry_move_death1 = {FRAME_death101, FRAME_death120, infantry_frames_death1, infantry_dead}; - -// Off with his head -mframe_t infantry_frames_death2 [] = -{ - ai_move, 0, NULL, - ai_move, 1, NULL, - ai_move, 5, NULL, - ai_move, -1, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 4, NULL, - ai_move, 3, NULL, - ai_move, 0, NULL, - ai_move, -2, InfantryMachineGun, - ai_move, -2, InfantryMachineGun, - ai_move, -3, InfantryMachineGun, - ai_move, -1, InfantryMachineGun, - ai_move, -2, InfantryMachineGun, - ai_move, 0, InfantryMachineGun, - ai_move, 2, InfantryMachineGun, - ai_move, 2, InfantryMachineGun, - ai_move, 3, InfantryMachineGun, - ai_move, -10, InfantryMachineGun, - ai_move, -7, InfantryMachineGun, - ai_move, -8, InfantryMachineGun, - ai_move, -6, NULL, - ai_move, 4, NULL, - ai_move, 0, NULL -}; -mmove_t infantry_move_death2 = {FRAME_death201, FRAME_death225, infantry_frames_death2, infantry_dead}; - -mframe_t infantry_frames_death3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -6, NULL, - ai_move, -11, NULL, - ai_move, -3, NULL, - ai_move, -11, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t infantry_move_death3 = {FRAME_death301, FRAME_death309, infantry_frames_death3, infantry_dead}; - - -void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - n = rand() % 3; - if (n == 0) - { - self->monsterinfo.currentmove = &infantry_move_death1; - gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); - } - else if (n == 1) - { - self->monsterinfo.currentmove = &infantry_move_death2; - gi.sound (self, CHAN_VOICE, sound_die1, 1, ATTN_NORM, 0); - } - else - { - self->monsterinfo.currentmove = &infantry_move_death3; - gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); - } -} - - -void infantry_duck_down (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - self->monsterinfo.aiflags |= AI_DUCKED; - self->maxs[2] -= 32; - self->takedamage = DAMAGE_YES; - self->monsterinfo.pausetime = level.time + 1; - gi.linkentity (self); -} - -void infantry_duck_hold (edict_t *self) -{ - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -void infantry_duck_up (edict_t *self) -{ - self->monsterinfo.aiflags &= ~AI_DUCKED; - self->maxs[2] += 32; - self->takedamage = DAMAGE_AIM; - gi.linkentity (self); -} - -mframe_t infantry_frames_duck [] = -{ - ai_move, -2, infantry_duck_down, - ai_move, -5, infantry_duck_hold, - ai_move, 3, NULL, - ai_move, 4, infantry_duck_up, - ai_move, 0, NULL -}; -mmove_t infantry_move_duck = {FRAME_duck01, FRAME_duck05, infantry_frames_duck, infantry_run}; - -void infantry_dodge (edict_t *self, edict_t *attacker, float eta) -{ - if (random() > 0.25) - return; - - if (!self->enemy) - self->enemy = attacker; - - self->monsterinfo.currentmove = &infantry_move_duck; -} - - -void infantry_cock_gun (edict_t *self) -{ - int n; - - gi.sound (self, CHAN_WEAPON, sound_weapon_cock, 1, ATTN_NORM, 0); - n = (rand() & 15) + 3 + 7; - self->monsterinfo.pausetime = level.time + n * FRAMETIME; -} - -void infantry_fire (edict_t *self) -{ - InfantryMachineGun (self); - - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -mframe_t infantry_frames_attack1 [] = -{ - ai_charge, 4, NULL, - ai_charge, -1, NULL, - ai_charge, -1, NULL, - ai_charge, 0, infantry_cock_gun, - ai_charge, -1, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 2, NULL, - ai_charge, -2, NULL, - ai_charge, -3, NULL, - ai_charge, 1, infantry_fire, - ai_charge, 5, NULL, - ai_charge, -1, NULL, - ai_charge, -2, NULL, - ai_charge, -3, NULL -}; - -mmove_t infantry_move_attack1 = {FRAME_attak101, FRAME_attak115, infantry_frames_attack1, infantry_run}; - - -void infantry_swing (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_punch_swing, 1, ATTN_NORM, 0); -} - -void infantry_smack (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, 0, 0); - if (fire_hit (self, aim, (5 + (rand() % 5)), 50)) - gi.sound (self, CHAN_WEAPON, sound_punch_hit, 1, ATTN_NORM, 0); -} - -mframe_t infantry_frames_attack2 [] = -{ - ai_charge, 3, NULL, - ai_charge, 6, NULL, - ai_charge, 0, infantry_swing, - ai_charge, 8, NULL, - ai_charge, 5, NULL, - ai_charge, 8, infantry_smack, - ai_charge, 6, NULL, - ai_charge, 3, NULL, -}; -mmove_t infantry_move_attack2 = {FRAME_attak201, FRAME_attak208, infantry_frames_attack2, infantry_run}; - -void infantry_attack(edict_t *self) -{ - if (range (self, self->enemy) == RANGE_MELEE) - self->monsterinfo.currentmove = &infantry_move_attack2; - else - self->monsterinfo.currentmove = &infantry_move_attack1; -} - -//Jump -mframe_t infantry_frames_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t infantry_move_jump = { FRAME_run01, FRAME_run08, infantry_frames_jump, infantry_run }; - -void infantry_jump (edict_t *self) -{ - self->monsterinfo.currentmove = &infantry_move_jump; -} - -/*QUAKED monster_infantry (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_infantry (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_INFANTRY; - - sound_pain1 = gi.soundindex ("infantry/infpain1.wav"); - sound_pain2 = gi.soundindex ("infantry/infpain2.wav"); - sound_die1 = gi.soundindex ("infantry/infdeth1.wav"); - sound_die2 = gi.soundindex ("infantry/infdeth2.wav"); - - sound_gunshot = gi.soundindex ("infantry/infatck1.wav"); - sound_weapon_cock = gi.soundindex ("infantry/infatck3.wav"); - sound_punch_swing = gi.soundindex ("infantry/infatck2.wav"); - sound_punch_hit = gi.soundindex ("infantry/melee2.wav"); - - sound_sight = gi.soundindex ("infantry/infsght1.wav"); - sound_search = gi.soundindex ("infantry/infsrch1.wav"); - sound_idle = gi.soundindex ("infantry/infidle1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/infantry/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 100; - if(!self->gib_health) - self->gib_health = -40; - if(!self->mass) - self->mass = 200; - - self->pain = infantry_pain; - self->die = infantry_die; - - self->monsterinfo.stand = infantry_stand; - self->monsterinfo.walk = infantry_walk; - self->monsterinfo.run = infantry_run; - self->monsterinfo.dodge = infantry_dodge; - self->monsterinfo.attack = infantry_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = infantry_sight; - self->monsterinfo.idle = infantry_fidget; - if(monsterjump->value) - { - self->monsterinfo.jump = infantry_jump; - self->monsterinfo.jumpup = 48; - self->monsterinfo.jumpdn = 160; - } - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.40; - - gi.linkentity (self); - self->monsterinfo.currentmove = &infantry_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&infantry_move_death1, - &infantry_move_death2, - &infantry_move_death3, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Enforcer"; - - self->monsterinfo.scale = MODEL_SCALE; - - walkmonster_start (self); -} - diff --git a/server/monsters/m_infantry.h b/server/monsters/m_infantry.h deleted file mode 100644 index d0314541..00000000 --- a/server/monsters/m_infantry.h +++ /dev/null @@ -1,213 +0,0 @@ -// G:\quake2\baseq2\models/monsters/infantry - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_gun02 0 -#define FRAME_stand01 1 -#define FRAME_stand02 2 -#define FRAME_stand03 3 -#define FRAME_stand04 4 -#define FRAME_stand05 5 -#define FRAME_stand06 6 -#define FRAME_stand07 7 -#define FRAME_stand08 8 -#define FRAME_stand09 9 -#define FRAME_stand10 10 -#define FRAME_stand11 11 -#define FRAME_stand12 12 -#define FRAME_stand13 13 -#define FRAME_stand14 14 -#define FRAME_stand15 15 -#define FRAME_stand16 16 -#define FRAME_stand17 17 -#define FRAME_stand18 18 -#define FRAME_stand19 19 -#define FRAME_stand20 20 -#define FRAME_stand21 21 -#define FRAME_stand22 22 -#define FRAME_stand23 23 -#define FRAME_stand24 24 -#define FRAME_stand25 25 -#define FRAME_stand26 26 -#define FRAME_stand27 27 -#define FRAME_stand28 28 -#define FRAME_stand29 29 -#define FRAME_stand30 30 -#define FRAME_stand31 31 -#define FRAME_stand32 32 -#define FRAME_stand33 33 -#define FRAME_stand34 34 -#define FRAME_stand35 35 -#define FRAME_stand36 36 -#define FRAME_stand37 37 -#define FRAME_stand38 38 -#define FRAME_stand39 39 -#define FRAME_stand40 40 -#define FRAME_stand41 41 -#define FRAME_stand42 42 -#define FRAME_stand43 43 -#define FRAME_stand44 44 -#define FRAME_stand45 45 -#define FRAME_stand46 46 -#define FRAME_stand47 47 -#define FRAME_stand48 48 -#define FRAME_stand49 49 -#define FRAME_stand50 50 -#define FRAME_stand51 51 -#define FRAME_stand52 52 -#define FRAME_stand53 53 -#define FRAME_stand54 54 -#define FRAME_stand55 55 -#define FRAME_stand56 56 -#define FRAME_stand57 57 -#define FRAME_stand58 58 -#define FRAME_stand59 59 -#define FRAME_stand60 60 -#define FRAME_stand61 61 -#define FRAME_stand62 62 -#define FRAME_stand63 63 -#define FRAME_stand64 64 -#define FRAME_stand65 65 -#define FRAME_stand66 66 -#define FRAME_stand67 67 -#define FRAME_stand68 68 -#define FRAME_stand69 69 -#define FRAME_stand70 70 -#define FRAME_stand71 71 -#define FRAME_walk01 72 -#define FRAME_walk02 73 -#define FRAME_walk03 74 -#define FRAME_walk04 75 -#define FRAME_walk05 76 -#define FRAME_walk06 77 -#define FRAME_walk07 78 -#define FRAME_walk08 79 -#define FRAME_walk09 80 -#define FRAME_walk10 81 -#define FRAME_walk11 82 -#define FRAME_walk12 83 -#define FRAME_walk13 84 -#define FRAME_walk14 85 -#define FRAME_walk15 86 -#define FRAME_walk16 87 -#define FRAME_walk17 88 -#define FRAME_walk18 89 -#define FRAME_walk19 90 -#define FRAME_walk20 91 -#define FRAME_run01 92 -#define FRAME_run02 93 -#define FRAME_run03 94 -#define FRAME_run04 95 -#define FRAME_run05 96 -#define FRAME_run06 97 -#define FRAME_run07 98 -#define FRAME_run08 99 -#define FRAME_pain101 100 -#define FRAME_pain102 101 -#define FRAME_pain103 102 -#define FRAME_pain104 103 -#define FRAME_pain105 104 -#define FRAME_pain106 105 -#define FRAME_pain107 106 -#define FRAME_pain108 107 -#define FRAME_pain109 108 -#define FRAME_pain110 109 -#define FRAME_pain201 110 -#define FRAME_pain202 111 -#define FRAME_pain203 112 -#define FRAME_pain204 113 -#define FRAME_pain205 114 -#define FRAME_pain206 115 -#define FRAME_pain207 116 -#define FRAME_pain208 117 -#define FRAME_pain209 118 -#define FRAME_pain210 119 -#define FRAME_duck01 120 -#define FRAME_duck02 121 -#define FRAME_duck03 122 -#define FRAME_duck04 123 -#define FRAME_duck05 124 -#define FRAME_death101 125 -#define FRAME_death102 126 -#define FRAME_death103 127 -#define FRAME_death104 128 -#define FRAME_death105 129 -#define FRAME_death106 130 -#define FRAME_death107 131 -#define FRAME_death108 132 -#define FRAME_death109 133 -#define FRAME_death110 134 -#define FRAME_death111 135 -#define FRAME_death112 136 -#define FRAME_death113 137 -#define FRAME_death114 138 -#define FRAME_death115 139 -#define FRAME_death116 140 -#define FRAME_death117 141 -#define FRAME_death118 142 -#define FRAME_death119 143 -#define FRAME_death120 144 -#define FRAME_death201 145 -#define FRAME_death202 146 -#define FRAME_death203 147 -#define FRAME_death204 148 -#define FRAME_death205 149 -#define FRAME_death206 150 -#define FRAME_death207 151 -#define FRAME_death208 152 -#define FRAME_death209 153 -#define FRAME_death210 154 -#define FRAME_death211 155 -#define FRAME_death212 156 -#define FRAME_death213 157 -#define FRAME_death214 158 -#define FRAME_death215 159 -#define FRAME_death216 160 -#define FRAME_death217 161 -#define FRAME_death218 162 -#define FRAME_death219 163 -#define FRAME_death220 164 -#define FRAME_death221 165 -#define FRAME_death222 166 -#define FRAME_death223 167 -#define FRAME_death224 168 -#define FRAME_death225 169 -#define FRAME_death301 170 -#define FRAME_death302 171 -#define FRAME_death303 172 -#define FRAME_death304 173 -#define FRAME_death305 174 -#define FRAME_death306 175 -#define FRAME_death307 176 -#define FRAME_death308 177 -#define FRAME_death309 178 -#define FRAME_block01 179 -#define FRAME_block02 180 -#define FRAME_block03 181 -#define FRAME_block04 182 -#define FRAME_block05 183 -#define FRAME_attak101 184 -#define FRAME_attak102 185 -#define FRAME_attak103 186 -#define FRAME_attak104 187 -#define FRAME_attak105 188 -#define FRAME_attak106 189 -#define FRAME_attak107 190 -#define FRAME_attak108 191 -#define FRAME_attak109 192 -#define FRAME_attak110 193 -#define FRAME_attak111 194 -#define FRAME_attak112 195 -#define FRAME_attak113 196 -#define FRAME_attak114 197 -#define FRAME_attak115 198 -#define FRAME_attak201 199 -#define FRAME_attak202 200 -#define FRAME_attak203 201 -#define FRAME_attak204 202 -#define FRAME_attak205 203 -#define FRAME_attak206 204 -#define FRAME_attak207 205 -#define FRAME_attak208 206 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_insane.c b/server/monsters/m_insane.c deleted file mode 100644 index 75208a06..00000000 --- a/server/monsters/m_insane.c +++ /dev/null @@ -1,690 +0,0 @@ -/* -============================================================================== - -insane - -============================================================================== -*/ - -#include "g_local.h" -#include "m_insane.h" - - -static int sound_fist; -static int sound_shake; -static int sound_moan; -static int sound_scream[8]; - -void insane_fist (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_fist, 1, ATTN_IDLE, 0); -} - -void insane_shake (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_shake, 1, ATTN_IDLE, 0); -} - -void insane_moan (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_moan, 1, ATTN_IDLE, 0); -} - -void insane_scream (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_scream[rand()%8], 1, ATTN_IDLE, 0); -} - - -void insane_stand (edict_t *self); -void insane_dead (edict_t *self); -void insane_cross (edict_t *self); -void insane_walk (edict_t *self); -void insane_run (edict_t *self); -void insane_checkdown (edict_t *self); -void insane_checkup (edict_t *self); -void insane_onground (edict_t *self); - - -mframe_t insane_frames_stand_normal [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, insane_checkdown -}; -mmove_t insane_move_stand_normal = {FRAME_stand60, FRAME_stand65, insane_frames_stand_normal, insane_stand}; - -mframe_t insane_frames_stand_insane [] = -{ - ai_stand, 0, insane_shake, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, insane_checkdown -}; -mmove_t insane_move_stand_insane = {FRAME_stand65, FRAME_stand94, insane_frames_stand_insane, insane_stand}; - -mframe_t insane_frames_uptodown [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, insane_moan, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 2.7, NULL, - ai_move, 4.1, NULL, - ai_move, 6, NULL, - ai_move, 7.6, NULL, - ai_move, 3.6, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, insane_fist, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, insane_fist, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_uptodown = {FRAME_stand1, FRAME_stand40, insane_frames_uptodown, insane_onground}; - - -mframe_t insane_frames_downtoup [] = -{ - ai_move, -0.7, NULL, // 41 - ai_move, -1.2, NULL, // 42 - ai_move, -1.5, NULL, // 43 - ai_move, -4.5, NULL, // 44 - ai_move, -3.5, NULL, // 45 - ai_move, -0.2, NULL, // 46 - ai_move, 0, NULL, // 47 - ai_move, -1.3, NULL, // 48 - ai_move, -3, NULL, // 49 - ai_move, -2, NULL, // 50 - ai_move, 0, NULL, // 51 - ai_move, 0, NULL, // 52 - ai_move, 0, NULL, // 53 - ai_move, -3.3, NULL, // 54 - ai_move, -1.6, NULL, // 55 - ai_move, -0.3, NULL, // 56 - ai_move, 0, NULL, // 57 - ai_move, 0, NULL, // 58 - ai_move, 0, NULL // 59 -}; -mmove_t insane_move_downtoup = {FRAME_stand41, FRAME_stand59, insane_frames_downtoup, insane_stand}; - -mframe_t insane_frames_jumpdown [] = -{ - ai_move, 0.2, NULL, - ai_move, 11.5, NULL, - ai_move, 5.1, NULL, - ai_move, 7.1, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_jumpdown = {FRAME_stand96, FRAME_stand100, insane_frames_jumpdown, insane_onground}; - - -mframe_t insane_frames_down [] = -{ - ai_move, 0, NULL, // 100 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 110 - ai_move, -1.7, NULL, - ai_move, -1.6, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, insane_fist, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 120 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 130 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, insane_moan, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 140 - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, // 150 - ai_move, 0.5, NULL, - ai_move, 0, NULL, - ai_move, -0.2, insane_scream, - ai_move, 0, NULL, - ai_move, 0.2, NULL, - ai_move, 0.4, NULL, - ai_move, 0.6, NULL, - ai_move, 0.8, NULL, - ai_move, 0.7, NULL, - ai_move, 0, insane_checkup // 160 -}; -mmove_t insane_move_down = {FRAME_stand100, FRAME_stand160, insane_frames_down, insane_onground}; - -mframe_t insane_frames_walk_normal [] = -{ - ai_walk, 0, insane_scream, - ai_walk, 2.5, NULL, - ai_walk, 3.5, NULL, - ai_walk, 1.7, NULL, - ai_walk, 2.3, NULL, - ai_walk, 2.4, NULL, - ai_walk, 2.2, NULL, - ai_walk, 4.2, NULL, - ai_walk, 5.6, NULL, - ai_walk, 3.3, NULL, - ai_walk, 2.4, NULL, - ai_walk, 0.9, NULL, - ai_walk, 0, NULL -}; -mmove_t insane_move_walk_normal = {FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_walk}; -mmove_t insane_move_run_normal = {FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_run}; - -mframe_t insane_frames_walk_insane [] = -{ - ai_walk, 0, insane_scream, // walk 1 - ai_walk, 3.4, NULL, // walk 2 - ai_walk, 3.6, NULL, // 3 - ai_walk, 2.9, NULL, // 4 - ai_walk, 2.2, NULL, // 5 - ai_walk, 2.6, NULL, // 6 - ai_walk, 0, NULL, // 7 - ai_walk, 0.7, NULL, // 8 - ai_walk, 4.8, NULL, // 9 - ai_walk, 5.3, NULL, // 10 - ai_walk, 1.1, NULL, // 11 - ai_walk, 2, NULL, // 12 - ai_walk, 0.5, NULL, // 13 - ai_walk, 0, NULL, // 14 - ai_walk, 0, NULL, // 15 - ai_walk, 4.9, NULL, // 16 - ai_walk, 6.7, NULL, // 17 - ai_walk, 3.8, NULL, // 18 - ai_walk, 2, NULL, // 19 - ai_walk, 0.2, NULL, // 20 - ai_walk, 0, NULL, // 21 - ai_walk, 3.4, NULL, // 22 - ai_walk, 6.4, NULL, // 23 - ai_walk, 5, NULL, // 24 - ai_walk, 1.8, NULL, // 25 - ai_walk, 0, NULL // 26 -}; -mmove_t insane_move_walk_insane = {FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_walk}; -mmove_t insane_move_run_insane = {FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_run}; - -mframe_t insane_frames_stand_pain [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_stand_pain = {FRAME_st_pain2, FRAME_st_pain12, insane_frames_stand_pain, insane_run}; - -mframe_t insane_frames_stand_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_stand_death = {FRAME_st_death2, FRAME_st_death18, insane_frames_stand_death, insane_dead}; - -mframe_t insane_frames_crawl [] = -{ - ai_walk, 0, insane_scream, - ai_walk, 1.5, NULL, - ai_walk, 2.1, NULL, - ai_walk, 3.6, NULL, - ai_walk, 2, NULL, - ai_walk, 0.9, NULL, - ai_walk, 3, NULL, - ai_walk, 3.4, NULL, - ai_walk, 2.4, NULL -}; -mmove_t insane_move_crawl = {FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL}; -mmove_t insane_move_runcrawl = {FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL}; - -mframe_t insane_frames_crawl_pain [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_crawl_pain = {FRAME_cr_pain2, FRAME_cr_pain10, insane_frames_crawl_pain, insane_run}; - -mframe_t insane_frames_crawl_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_crawl_death = {FRAME_cr_death10, FRAME_cr_death16, insane_frames_crawl_death, insane_dead}; - -mframe_t insane_frames_cross [] = -{ - ai_move, 0, insane_moan, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_cross = {FRAME_cross1, FRAME_cross15, insane_frames_cross, insane_cross}; - -mframe_t insane_frames_struggle_cross [] = -{ - ai_move, 0, insane_scream, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t insane_move_struggle_cross = {FRAME_cross16, FRAME_cross30, insane_frames_struggle_cross, insane_cross}; - -void insane_cross (edict_t *self) -{ - if (random() < 0.8) - self->monsterinfo.currentmove = &insane_move_cross; - else - self->monsterinfo.currentmove = &insane_move_struggle_cross; -} - -void insane_walk (edict_t *self) -{ - if ( self->spawnflags & 16 ) // Hold Ground? - if (self->s.frame == FRAME_cr_pain10) - { - self->monsterinfo.currentmove = &insane_move_down; - return; - } - if (self->spawnflags & 4) - self->monsterinfo.currentmove = &insane_move_crawl; - else - if (random() <= 0.5) - self->monsterinfo.currentmove = &insane_move_walk_normal; - else - self->monsterinfo.currentmove = &insane_move_walk_insane; -} - -void insane_run (edict_t *self) -{ - if ( self->spawnflags & 16 ) // Hold Ground? - if (self->s.frame == FRAME_cr_pain10) - { - self->monsterinfo.currentmove = &insane_move_down; - return; - } - if (self->spawnflags & 4) // Crawling? - self->monsterinfo.currentmove = &insane_move_runcrawl; - else - if (random() <= 0.5) // Else, mix it up - self->monsterinfo.currentmove = &insane_move_run_normal; - else - self->monsterinfo.currentmove = &insane_move_run_insane; -} - - -void insane_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - int l,r; - -// if (self->health < (self->max_health / 2)) -// self->s.skin = 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - r = 1 + (rand()&1); - if (self->health < 25) - l = 25; - else if (self->health < 50) - l = 50; - else if (self->health < 75) - l = 75; - else - l = 100; - gi.sound (self, CHAN_VOICE, gi.soundindex (va("player/male/pain%i_%i.wav", l, r)), 1, ATTN_IDLE, 0); - - if (skill->value == 3) - return; // no pain anims in nightmare - - // Don't go into pain frames if crucified. - if (self->spawnflags & 8) - { - self->monsterinfo.currentmove = &insane_move_struggle_cross; - return; - } - - if ( ((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)) ) - { - self->monsterinfo.currentmove = &insane_move_crawl_pain; - } - else - self->monsterinfo.currentmove = &insane_move_stand_pain; - -} - -void insane_onground (edict_t *self) -{ - self->monsterinfo.currentmove = &insane_move_down; -} - -void insane_checkdown (edict_t *self) -{ -// if ( (self->s.frame == FRAME_stand94) || (self->s.frame == FRAME_stand65) ) - if (self->spawnflags & 32) // Always stand - return; - if (random() < 0.3) - if (random() < 0.5) - self->monsterinfo.currentmove = &insane_move_uptodown; - else - self->monsterinfo.currentmove = &insane_move_jumpdown; -} - -void insane_checkup (edict_t *self) -{ - // If Hold_Ground and Crawl are set - if ( (self->spawnflags & 4) && (self->spawnflags & 16) ) - return; - if (random() < 0.5) - self->monsterinfo.currentmove = &insane_move_downtoup; - -} - -void insane_stand (edict_t *self) -{ - if (self->spawnflags & 8) // If crucified - { - self->monsterinfo.currentmove = &insane_move_cross; - self->monsterinfo.aiflags |= AI_STAND_GROUND; - } - // If Hold_Ground and Crawl are set - else if ( (self->spawnflags & 4) && (self->spawnflags & 16) ) - self->monsterinfo.currentmove = &insane_move_down; - else - if (random() < 0.5) - self->monsterinfo.currentmove = &insane_move_stand_normal; - else - self->monsterinfo.currentmove = &insane_move_stand_insane; -} - -void insane_dead (edict_t *self) -{ - if (self->spawnflags & 8) - { - self->flags |= FL_FLY; - } - else - { - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - } - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck(self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - - -void insane_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_IDLE, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - - gi.sound (self, CHAN_VOICE, gi.soundindex(va("player/male/death%i.wav", (rand()%4)+1)), 1, ATTN_IDLE, 0); - - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - if (self->spawnflags & 8) - { - insane_dead (self); - } - else - { - if ( ((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)) ) - self->monsterinfo.currentmove = &insane_move_crawl_death; - else - self->monsterinfo.currentmove = &insane_move_stand_death; - } -} - - -/*QUAKED misc_insane (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn CRAWL CRUCIFIED STAND_GROUND ALWAYS_STAND -*/ -void SP_misc_insane (edict_t *self) -{ -// static int skin = 0; //@@ - - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MISC_INSANE; - - sound_fist = gi.soundindex ("insane/insane11.wav"); - sound_shake = gi.soundindex ("insane/insane5.wav"); - sound_moan = gi.soundindex ("insane/insane7.wav"); - sound_scream[0] = gi.soundindex ("insane/insane1.wav"); - sound_scream[1] = gi.soundindex ("insane/insane2.wav"); - sound_scream[2] = gi.soundindex ("insane/insane3.wav"); - sound_scream[3] = gi.soundindex ("insane/insane4.wav"); - sound_scream[4] = gi.soundindex ("insane/insane6.wav"); - sound_scream[5] = gi.soundindex ("insane/insane8.wav"); - sound_scream[6] = gi.soundindex ("insane/insane9.wav"); - sound_scream[7] = gi.soundindex ("insane/insane10.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - self->s.modelindex = gi.modelindex("models/monsters/insane/tris.md2"); - - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - - if(!self->health) - self->health = 100; - if(!self->gib_health) - self->gib_health = -50; - if(!self->mass) - self->mass = 300; - - self->pain = insane_pain; - self->die = insane_die; - - self->monsterinfo.stand = insane_stand; - self->monsterinfo.walk = insane_walk; - self->monsterinfo.run = insane_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = NULL; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = NULL; - self->monsterinfo.aiflags |= AI_GOOD_GUY; - - self->common_name = "Insane Marine"; -//@@ -// self->s.skin = skin; -// skin++; -// if (skin > 12) -// skin = 0; - - gi.linkentity (self); - - if (self->spawnflags & 16) // Stand Ground - self->monsterinfo.aiflags |= AI_STAND_GROUND; - - self->monsterinfo.currentmove = &insane_move_stand_normal; - - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.30; - - self->monsterinfo.scale = MODEL_SCALE; - - if (self->spawnflags & 8) // Crucified ? - { - VectorSet (self->mins, -16, 0, 0); - VectorSet (self->maxs, 16, 8, 32); - self->flags |= FL_NO_KNOCKBACK; - flymonster_start (self); - } - else - { - walkmonster_start (self); - self->s.skin = rand()%3; - } -} diff --git a/server/monsters/m_insane.h b/server/monsters/m_insane.h deleted file mode 100644 index f839230b..00000000 --- a/server/monsters/m_insane.h +++ /dev/null @@ -1,288 +0,0 @@ -// G:\quake2\baseq2\models/monsters/insane - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand1 0 -#define FRAME_stand2 1 -#define FRAME_stand3 2 -#define FRAME_stand4 3 -#define FRAME_stand5 4 -#define FRAME_stand6 5 -#define FRAME_stand7 6 -#define FRAME_stand8 7 -#define FRAME_stand9 8 -#define FRAME_stand10 9 -#define FRAME_stand11 10 -#define FRAME_stand12 11 -#define FRAME_stand13 12 -#define FRAME_stand14 13 -#define FRAME_stand15 14 -#define FRAME_stand16 15 -#define FRAME_stand17 16 -#define FRAME_stand18 17 -#define FRAME_stand19 18 -#define FRAME_stand20 19 -#define FRAME_stand21 20 -#define FRAME_stand22 21 -#define FRAME_stand23 22 -#define FRAME_stand24 23 -#define FRAME_stand25 24 -#define FRAME_stand26 25 -#define FRAME_stand27 26 -#define FRAME_stand28 27 -#define FRAME_stand29 28 -#define FRAME_stand30 29 -#define FRAME_stand31 30 -#define FRAME_stand32 31 -#define FRAME_stand33 32 -#define FRAME_stand34 33 -#define FRAME_stand35 34 -#define FRAME_stand36 35 -#define FRAME_stand37 36 -#define FRAME_stand38 37 -#define FRAME_stand39 38 -#define FRAME_stand40 39 -#define FRAME_stand41 40 -#define FRAME_stand42 41 -#define FRAME_stand43 42 -#define FRAME_stand44 43 -#define FRAME_stand45 44 -#define FRAME_stand46 45 -#define FRAME_stand47 46 -#define FRAME_stand48 47 -#define FRAME_stand49 48 -#define FRAME_stand50 49 -#define FRAME_stand51 50 -#define FRAME_stand52 51 -#define FRAME_stand53 52 -#define FRAME_stand54 53 -#define FRAME_stand55 54 -#define FRAME_stand56 55 -#define FRAME_stand57 56 -#define FRAME_stand58 57 -#define FRAME_stand59 58 -#define FRAME_stand60 59 -#define FRAME_stand61 60 -#define FRAME_stand62 61 -#define FRAME_stand63 62 -#define FRAME_stand64 63 -#define FRAME_stand65 64 -#define FRAME_stand66 65 -#define FRAME_stand67 66 -#define FRAME_stand68 67 -#define FRAME_stand69 68 -#define FRAME_stand70 69 -#define FRAME_stand71 70 -#define FRAME_stand72 71 -#define FRAME_stand73 72 -#define FRAME_stand74 73 -#define FRAME_stand75 74 -#define FRAME_stand76 75 -#define FRAME_stand77 76 -#define FRAME_stand78 77 -#define FRAME_stand79 78 -#define FRAME_stand80 79 -#define FRAME_stand81 80 -#define FRAME_stand82 81 -#define FRAME_stand83 82 -#define FRAME_stand84 83 -#define FRAME_stand85 84 -#define FRAME_stand86 85 -#define FRAME_stand87 86 -#define FRAME_stand88 87 -#define FRAME_stand89 88 -#define FRAME_stand90 89 -#define FRAME_stand91 90 -#define FRAME_stand92 91 -#define FRAME_stand93 92 -#define FRAME_stand94 93 -#define FRAME_stand95 94 -#define FRAME_stand96 95 -#define FRAME_stand97 96 -#define FRAME_stand98 97 -#define FRAME_stand99 98 -#define FRAME_stand100 99 -#define FRAME_stand101 100 -#define FRAME_stand102 101 -#define FRAME_stand103 102 -#define FRAME_stand104 103 -#define FRAME_stand105 104 -#define FRAME_stand106 105 -#define FRAME_stand107 106 -#define FRAME_stand108 107 -#define FRAME_stand109 108 -#define FRAME_stand110 109 -#define FRAME_stand111 110 -#define FRAME_stand112 111 -#define FRAME_stand113 112 -#define FRAME_stand114 113 -#define FRAME_stand115 114 -#define FRAME_stand116 115 -#define FRAME_stand117 116 -#define FRAME_stand118 117 -#define FRAME_stand119 118 -#define FRAME_stand120 119 -#define FRAME_stand121 120 -#define FRAME_stand122 121 -#define FRAME_stand123 122 -#define FRAME_stand124 123 -#define FRAME_stand125 124 -#define FRAME_stand126 125 -#define FRAME_stand127 126 -#define FRAME_stand128 127 -#define FRAME_stand129 128 -#define FRAME_stand130 129 -#define FRAME_stand131 130 -#define FRAME_stand132 131 -#define FRAME_stand133 132 -#define FRAME_stand134 133 -#define FRAME_stand135 134 -#define FRAME_stand136 135 -#define FRAME_stand137 136 -#define FRAME_stand138 137 -#define FRAME_stand139 138 -#define FRAME_stand140 139 -#define FRAME_stand141 140 -#define FRAME_stand142 141 -#define FRAME_stand143 142 -#define FRAME_stand144 143 -#define FRAME_stand145 144 -#define FRAME_stand146 145 -#define FRAME_stand147 146 -#define FRAME_stand148 147 -#define FRAME_stand149 148 -#define FRAME_stand150 149 -#define FRAME_stand151 150 -#define FRAME_stand152 151 -#define FRAME_stand153 152 -#define FRAME_stand154 153 -#define FRAME_stand155 154 -#define FRAME_stand156 155 -#define FRAME_stand157 156 -#define FRAME_stand158 157 -#define FRAME_stand159 158 -#define FRAME_stand160 159 -#define FRAME_walk27 160 -#define FRAME_walk28 161 -#define FRAME_walk29 162 -#define FRAME_walk30 163 -#define FRAME_walk31 164 -#define FRAME_walk32 165 -#define FRAME_walk33 166 -#define FRAME_walk34 167 -#define FRAME_walk35 168 -#define FRAME_walk36 169 -#define FRAME_walk37 170 -#define FRAME_walk38 171 -#define FRAME_walk39 172 -#define FRAME_walk1 173 -#define FRAME_walk2 174 -#define FRAME_walk3 175 -#define FRAME_walk4 176 -#define FRAME_walk5 177 -#define FRAME_walk6 178 -#define FRAME_walk7 179 -#define FRAME_walk8 180 -#define FRAME_walk9 181 -#define FRAME_walk10 182 -#define FRAME_walk11 183 -#define FRAME_walk12 184 -#define FRAME_walk13 185 -#define FRAME_walk14 186 -#define FRAME_walk15 187 -#define FRAME_walk16 188 -#define FRAME_walk17 189 -#define FRAME_walk18 190 -#define FRAME_walk19 191 -#define FRAME_walk20 192 -#define FRAME_walk21 193 -#define FRAME_walk22 194 -#define FRAME_walk23 195 -#define FRAME_walk24 196 -#define FRAME_walk25 197 -#define FRAME_walk26 198 -#define FRAME_st_pain2 199 -#define FRAME_st_pain3 200 -#define FRAME_st_pain4 201 -#define FRAME_st_pain5 202 -#define FRAME_st_pain6 203 -#define FRAME_st_pain7 204 -#define FRAME_st_pain8 205 -#define FRAME_st_pain9 206 -#define FRAME_st_pain10 207 -#define FRAME_st_pain11 208 -#define FRAME_st_pain12 209 -#define FRAME_st_death2 210 -#define FRAME_st_death3 211 -#define FRAME_st_death4 212 -#define FRAME_st_death5 213 -#define FRAME_st_death6 214 -#define FRAME_st_death7 215 -#define FRAME_st_death8 216 -#define FRAME_st_death9 217 -#define FRAME_st_death10 218 -#define FRAME_st_death11 219 -#define FRAME_st_death12 220 -#define FRAME_st_death13 221 -#define FRAME_st_death14 222 -#define FRAME_st_death15 223 -#define FRAME_st_death16 224 -#define FRAME_st_death17 225 -#define FRAME_st_death18 226 -#define FRAME_crawl1 227 -#define FRAME_crawl2 228 -#define FRAME_crawl3 229 -#define FRAME_crawl4 230 -#define FRAME_crawl5 231 -#define FRAME_crawl6 232 -#define FRAME_crawl7 233 -#define FRAME_crawl8 234 -#define FRAME_crawl9 235 -#define FRAME_cr_pain2 236 -#define FRAME_cr_pain3 237 -#define FRAME_cr_pain4 238 -#define FRAME_cr_pain5 239 -#define FRAME_cr_pain6 240 -#define FRAME_cr_pain7 241 -#define FRAME_cr_pain8 242 -#define FRAME_cr_pain9 243 -#define FRAME_cr_pain10 244 -#define FRAME_cr_death10 245 -#define FRAME_cr_death11 246 -#define FRAME_cr_death12 247 -#define FRAME_cr_death13 248 -#define FRAME_cr_death14 249 -#define FRAME_cr_death15 250 -#define FRAME_cr_death16 251 -#define FRAME_cross1 252 -#define FRAME_cross2 253 -#define FRAME_cross3 254 -#define FRAME_cross4 255 -#define FRAME_cross5 256 -#define FRAME_cross6 257 -#define FRAME_cross7 258 -#define FRAME_cross8 259 -#define FRAME_cross9 260 -#define FRAME_cross10 261 -#define FRAME_cross11 262 -#define FRAME_cross12 263 -#define FRAME_cross13 264 -#define FRAME_cross14 265 -#define FRAME_cross15 266 -#define FRAME_cross16 267 -#define FRAME_cross17 268 -#define FRAME_cross18 269 -#define FRAME_cross19 270 -#define FRAME_cross20 271 -#define FRAME_cross21 272 -#define FRAME_cross22 273 -#define FRAME_cross23 274 -#define FRAME_cross24 275 -#define FRAME_cross25 276 -#define FRAME_cross26 277 -#define FRAME_cross27 278 -#define FRAME_cross28 279 -#define FRAME_cross29 280 -#define FRAME_cross30 281 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_medic.c b/server/monsters/m_medic.c deleted file mode 100644 index 3b133b03..00000000 --- a/server/monsters/m_medic.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* -============================================================================== - -MEDIC - -============================================================================== -*/ - -#include "g_local.h" -#include "m_medic.h" - -bool visible (edict_t *self, edict_t *other); - -int medic_test=0; -static int sound_idle1; -static int sound_pain1; -static int sound_pain2; -static int sound_die; -static int sound_sight; -static int sound_search; -static int sound_hook_launch; -static int sound_hook_hit; -static int sound_hook_heal; -static int sound_hook_retract; - -void M_SetEffects (edict_t *ent); - -void deadmonster_think (edict_t *self) -{ - // Lazarus. This turns off the "owner" value of a dead monster - // that medic previously aborted on after 2 seconds. If the delay - // was NOT used, medic might just rotate around on top of monster - // continuously trying to revive him unsuccessfully. And if owner - // isn't turned off, medic would never try to revive the monster - // once an abortHeal was called. - if(self->target_ent && self->target_ent->inuse) { - edict_t *deadmonster = self->target_ent; - if(deadmonster->monsterinfo.healer) { - edict_t *medic = deadmonster->monsterinfo.healer; - if(medic->inuse) { - vec3_t dir; - VectorSubtract(medic->s.origin,deadmonster->s.origin,dir); - if(VectorLength(dir) < 64) { - self->nextthink = level.time + 1.0; - return; - } - } else - deadmonster->monsterinfo.healer = NULL; - } - deadmonster->owner = NULL; - } - G_FreeEdict(self); -} - -void cleanupHeal (edict_t *self, bool change_frame) -{ - // clean up target, if we have one and it's legit - if (self->enemy && self->enemy->inuse) - { - edict_t *temp; // Lazarus - - //self->enemy->monsterinfo.healer = NULL; - self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING; - self->enemy->takedamage = DAMAGE_AIM; - // Lazarus - temp = G_Spawn(); - temp->svflags = SVF_NOCLIENT; - temp->target_ent = self->enemy; - temp->think = deadmonster_think; - temp->nextthink = level.time + 2.0; - gi.linkentity(temp); - M_SetEffects (self->enemy); - } - - if (change_frame) - self->monsterinfo.nextframe = FRAME_attack52; -} - -void DeleteBadMedic(edict_t *self) -{ - edict_t *monster; - - monster = self->activator; - if(monster) - { - if(self->monsterinfo.badMedic1) - monster->monsterinfo.badMedic1 = NULL; - if(self->monsterinfo.badMedic2) - monster->monsterinfo.badMedic2 = NULL; - } - G_FreeEdict(self); -} -void abortHeal (edict_t *self, bool mark) -{ - edict_t *temp; - - // clean up target - cleanupHeal (self, true); - - if ((mark) && (self->enemy) && (self->enemy->inuse)) - { - if ((self->enemy->monsterinfo.badMedic1) && (self->enemy->monsterinfo.badMedic1->inuse) - && (!strncmp(self->enemy->monsterinfo.badMedic1->classname, "monster_medic", 13)) ) - self->enemy->monsterinfo.badMedic2 = self; - else - self->enemy->monsterinfo.badMedic1 = self; - - temp = G_Spawn(); - temp->activator = self->enemy; - if(self == self->enemy->monsterinfo.badMedic1) - temp->monsterinfo.badMedic1 = self; - else - temp->monsterinfo.badMedic2 = self; - temp->think = DeleteBadMedic; - temp->nextthink = level.time + 60; - } - - // clean up self - self->monsterinfo.aiflags &= ~AI_MEDIC; - if ((self->oldenemy) && (self->oldenemy->inuse)) - self->enemy = self->oldenemy; - else - self->enemy = NULL; - - self->monsterinfo.medicTries = 0; -} - -// Lazarus: embedded returns true if argument entity's bounding box intersects -// a solid. -bool embedded (edict_t *ent) -{ - trace_t tr; - - tr = gi.trace(ent->s.origin,ent->mins,ent->maxs,ent->s.origin,ent,MASK_MONSTERSOLID); - if(tr.startsolid) - return true; - else - return false; -} - -edict_t *medic_FindDeadMonster (edict_t *self) -{ - edict_t *ent = NULL; - edict_t *best = NULL; - - while ((ent = findradius(ent, self->s.origin, 1024)) != NULL) - { - if (ent == self) - continue; - if (!(ent->svflags & SVF_MONSTER)) - continue; - if (ent->monsterinfo.aiflags & AI_GOOD_GUY) - continue; - if (ent->owner) - continue; - if (ent->health > 0) - continue; - if (ent->nextthink && (ent->think != M_FliesOff) && (ent->think != M_FliesOn)) - continue; - // check to make sure we haven't bailed on this guy already - if ((ent->monsterinfo.badMedic1 == self) || (ent->monsterinfo.badMedic2 == self)) - continue; - if (!visible(self, ent)) - continue; - if (embedded(ent)) - continue; - if (!canReach(self,ent)) - continue; - if (!best) - { - best = ent; - continue; - } - if (ent->max_health <= best->max_health) - continue; - best = ent; - } - - if(best) - { - self->oldenemy = self->enemy; - self->enemy = best; - self->enemy->owner = best; - self->monsterinfo.aiflags |= AI_MEDIC; - self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL; - self->monsterinfo.medicTries = 0; - self->movetarget = self->goalentity = NULL; - self->enemy->monsterinfo.healer = self; - self->timestamp = level.time + MEDIC_TRY_TIME; - FoundTarget (self); - - if(developer->value) - gi.dprintf("medic found dead monster: %s at %s\n", - best->classname,vtos(best->s.origin)); - - } - return best; -} - -void medic_StopPatrolling (edict_t *self) -{ - self->goalentity = NULL; - self->movetarget = NULL; - self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL; - if (!(self->monsterinfo.aiflags & AI_MEDIC)) - { - if(medic_FindDeadMonster(self)) - return; - } - if (has_valid_enemy(self)) - { - if (visible(self, self->enemy)) - { - FoundTarget (self); - return; - } - HuntTarget (self); - return; - } - if(self->monsterinfo.aiflags & AI_MEDIC) - abortHeal(self,false); -} - -void medic_NextPatrolPoint (edict_t *self, edict_t *hint) -{ - edict_t *next=NULL; - edict_t *e; - vec3_t dir; - bool switch_paths=false; - - self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL; - -// if(self->monsterinfo.aiflags & AI_MEDIC) -// return; - - if(self->goalentity == hint) - self->goalentity = NULL; - if(self->movetarget == hint) - self->movetarget = NULL; - if (!(self->monsterinfo.aiflags & AI_MEDIC)) - { - if(medic_FindDeadMonster(self)) - return; - } - if(self->monsterinfo.pathdir == 1) - { - if(hint->hint_chain) - next = hint->hint_chain; - else - { - self->monsterinfo.pathdir = -1; - switch_paths = true; - } - } - if(self->monsterinfo.pathdir == -1) - { - e = hint_path_start[hint->hint_chain_id]; - while(e) - { - if(e->hint_chain == hint) - { - next = e; - break; - } - e = e->hint_chain; - } - } - if(!next) - { - self->monsterinfo.pathdir = 1; - next = hint->hint_chain; - switch_paths = true; - } - // If switch_paths is true, we reached the end of a hint_chain. Just for grins, - // search for *another* visible hint_path chain and use it if it's reasonably close - if(switch_paths && num_hint_paths > 1) - { - edict_t *e; - edict_t *alternate=NULL; - float dist; - vec3_t dir; - int i; - float bestdistance=512; - - for(i=game.maxclients+1; iinuse) - continue; - if(e->class_id != ENTITY_HINT_PATH) - continue; - if(next && (e->hint_chain_id == next->hint_chain_id)) - continue; - if(!visible(self,e)) - continue; - if(!canReach(self,e)) - continue; - VectorSubtract(e->s.origin,self->s.origin,dir); - dist = VectorLength(dir); - if(dist < bestdistance) - { - alternate = e; - bestdistance = dist; - } - } - if(alternate) - next = alternate; - } - if(next) - { - self->hint_chain_id = next->hint_chain_id; - VectorSubtract(next->s.origin, self->s.origin, dir); - self->ideal_yaw = vectoyaw(dir); - self->goalentity = self->movetarget = next; - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags |= AI_MEDIC_PATROL; - self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP); - // run for it - self->monsterinfo.run (self); - } - else - { - self->monsterinfo.pausetime = level.time + 100000000; - self->monsterinfo.stand (self); - } -} - -void medic_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); - - if(self->monsterinfo.aiflags & AI_MEDIC) - { - // Then we must have reached this point after losing sight - // of our patient. - abortHeal(self,false); - } - - if(medic_FindDeadMonster(self)) - return; - - // If the map has hint_paths, AND the medic isn't at a HOLD point_combat, - // AND the medic has previously called FoundTarget (trail_time set to - // level.time), then look for hint_path chain and follow it, hopefully - // to find monsters to resurrect - if(self->monsterinfo.aiflags & AI_HINT_TEST) - return; - - if(hint_paths_present && !(self->monsterinfo.aiflags & AI_STAND_GROUND) - && ((self->monsterinfo.trail_time > 0) || medic_test) ) - { - edict_t *e; - edict_t *hint=NULL; - float dist; - vec3_t dir; - int i; - float bestdistance=99999; - - for(i=game.maxclients+1; iinuse) - continue; - if(e->class_id != ENTITY_HINT_PATH) - continue; - if(!visible(self,e)) - continue; - if(!canReach(self,e)) - continue; - VectorSubtract(e->s.origin,self->s.origin,dir); - dist = VectorLength(dir); - if(dist < bestdistance) - { - hint = e; - bestdistance = dist; - } - } - if(hint) - { - self->hint_chain_id = hint->hint_chain_id; - if(!self->monsterinfo.pathdir) - self->monsterinfo.pathdir = 1; - VectorSubtract(hint->s.origin, self->s.origin, dir); - self->ideal_yaw = vectoyaw(dir); - self->goalentity = self->movetarget = hint; - self->monsterinfo.pausetime = 0; - self->monsterinfo.aiflags |= AI_MEDIC_PATROL; - self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP); - // run for it - self->monsterinfo.run (self); - } - } -} - -void medic_search (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_IDLE, 0); - - if (!self->oldenemy) - medic_FindDeadMonster(self); -} - -void medic_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - - -mframe_t medic_frames_stand [] = -{ - ai_stand, 0, medic_idle, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - -}; -mmove_t medic_move_stand = {FRAME_wait1, FRAME_wait90, medic_frames_stand, NULL}; - -void medic_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &medic_move_stand; -} - - -mframe_t medic_frames_walk [] = -{ - ai_walk, 6.2, NULL, - ai_walk, 18.1, NULL, - ai_walk, 1, NULL, - ai_walk, 9, NULL, - ai_walk, 10, NULL, - ai_walk, 9, NULL, - ai_walk, 11, NULL, - ai_walk, 11.6, NULL, - ai_walk, 2, NULL, - ai_walk, 9.9, NULL, - ai_walk, 14, NULL, - ai_walk, 9.3, NULL -}; -mmove_t medic_move_walk = {FRAME_walk1, FRAME_walk12, medic_frames_walk, NULL}; - -void medic_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &medic_move_walk; -} - - -mframe_t medic_frames_run [] = -{ - ai_run, 18, NULL, - ai_run, 22.5, NULL, - ai_run, 25.4, NULL, - ai_run, 23.4, NULL, - ai_run, 24, NULL, - ai_run, 35.6, NULL - -}; -mmove_t medic_move_run = {FRAME_run1, FRAME_run6, medic_frames_run, NULL}; - -void medic_run (edict_t *self) -{ - if (!(self->monsterinfo.aiflags & AI_MEDIC)) - { - if (medic_FindDeadMonster(self)) - return; - } - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &medic_move_stand; - else - self->monsterinfo.currentmove = &medic_move_run; -} - - -mframe_t medic_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t medic_move_pain1 = {FRAME_paina1, FRAME_paina8, medic_frames_pain1, medic_run}; - -mframe_t medic_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t medic_move_pain2 = {FRAME_painb1, FRAME_painb15, medic_frames_pain2, medic_run}; - -void medic_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (random() < 0.5) - { - self->monsterinfo.currentmove = &medic_move_pain1; - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - } - else - { - self->monsterinfo.currentmove = &medic_move_pain2; - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - } -} - -void medic_fire_blaster (edict_t *self) -{ - vec3_t start; - vec3_t forward, right; - vec3_t end; - vec3_t dir; - int effect; - - if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12)) - effect = EF_BLASTER; - else if ((self->s.frame == FRAME_attack19) || (self->s.frame == FRAME_attack22) || (self->s.frame == FRAME_attack25) || (self->s.frame == FRAME_attack28)) - effect = EF_HYPERBLASTER; - else - effect = 0; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1], forward, right, start); - - VectorCopy (self->enemy->s.origin, end); - end[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (end, start, dir); - monster_fire_blaster (self, start, dir, 2, 1000, MZ2_MEDIC_BLASTER_1, effect); -} - - -void medic_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t medic_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t medic_move_death = {FRAME_death1, FRAME_death30, medic_frames_death, medic_dead}; - -void medic_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - // if we had a pending patient, free him up for another medic - if ((self->enemy) && (self->enemy->owner == self)) - self->enemy->owner = NULL; - -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - self->monsterinfo.currentmove = &medic_move_death; -} - - -void medic_duck_down (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - self->monsterinfo.aiflags |= AI_DUCKED; - self->maxs[2] -= 32; - self->takedamage = DAMAGE_YES; - self->monsterinfo.pausetime = level.time + 1; - gi.linkentity (self); -} - -void medic_duck_hold (edict_t *self) -{ - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -void medic_duck_up (edict_t *self) -{ - self->monsterinfo.aiflags &= ~AI_DUCKED; - self->maxs[2] += 32; - self->takedamage = DAMAGE_AIM; - gi.linkentity (self); -} - -mframe_t medic_frames_duck [] = -{ - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, medic_duck_down, - ai_move, -1, medic_duck_hold, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, medic_duck_up, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL -}; -mmove_t medic_move_duck = {FRAME_duck1, FRAME_duck16, medic_frames_duck, medic_run}; - -void medic_dodge (edict_t *self, edict_t *attacker, float eta) -{ - if (random() > 0.25) - return; - - if (!self->enemy) - self->enemy = attacker; - - self->monsterinfo.currentmove = &medic_move_duck; -} - -mframe_t medic_frames_attackHyperBlaster [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, medic_fire_blaster -}; -mmove_t medic_move_attackHyperBlaster = {FRAME_attack15, FRAME_attack30, medic_frames_attackHyperBlaster, medic_run}; - - -void medic_continue (edict_t *self) -{ - if (visible (self, self->enemy) ) - if (random() <= 0.95) - self->monsterinfo.currentmove = &medic_move_attackHyperBlaster; -} - - -mframe_t medic_frames_attackBlaster [] = -{ - ai_charge, 0, NULL, - ai_charge, 5, NULL, - ai_charge, 5, NULL, - ai_charge, 3, NULL, - ai_charge, 2, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, medic_fire_blaster, - ai_charge, 0, NULL, - ai_charge, 0, medic_continue // Change to medic_continue... Else, go to frame 32 -}; -mmove_t medic_move_attackBlaster = {FRAME_attack1, FRAME_attack14, medic_frames_attackBlaster, medic_run}; - - -void medic_hook_launch (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_hook_launch, 1, ATTN_NORM, 0); -} - -void ED_CallSpawn (edict_t *ent); - -static vec3_t medic_cable_offsets[] = -{ - 45.0, -9.2, 15.5, - 48.4, -9.7, 15.2, - 47.8, -9.8, 15.8, - 47.3, -9.3, 14.3, - 45.4, -10.1, 13.1, - 41.9, -12.7, 12.0, - 37.8, -15.8, 11.2, - 34.3, -18.4, 10.7, - 32.7, -19.7, 10.4, - 32.7, -19.7, 10.4 -}; - -void medic_cable_attack (edict_t *self) -{ - vec3_t offset, start, end, f, r; - trace_t tr; - vec3_t dir; - - if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->health <= self->enemy->gib_health)) - { - abortHeal (self,false); - return; - } - // Lazarus: check embeddment - if (embedded(self->enemy)) - { - abortHeal (self,false); - return; - } - - // see if our enemy has changed to a client, or our target has more than 0 health, - // abort it .. we got switched to someone else due to damage - if ((self->enemy->client) || (self->enemy->health > 0)) { - abortHeal (self,false); - return; - } - - AngleVectors (self->s.angles, f, r, NULL); - VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset); - G_ProjectSource (self->s.origin, offset, f, r, start); - - // check for max distance - // Lazarus: Not needed, done in checkattack - // check for min distance - VectorSubtract (self->enemy->s.origin, start, dir); -/* distance = VectorLength(dir); - if (distance < MEDIC_MIN_DISTANCE) { - gi.dprintf("MEDIC_MIN_DISTANCE\n"); - abortHeal (self,false); - return; - } */ - - // Lazarus: Check for enemy behind muzzle... don't do these guys, 'cause usually this - // results in monster entanglement - VectorNormalize(dir); - if(DotProduct(dir,f) < 0.) { - abortHeal (self,false); - return; - } - - // check for min/max pitch - // Rogue takes this out... makes medic more likely to heal and - // comments say "doesn't look bad when it fails"... we'll see -/* vectoangles (dir, angles); - if (angles[0] < -180) - angles[0] += 360; - if (fabs(angles[0]) > 45) - return; */ - - tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT); - if (tr.fraction != 1.0 && tr.ent != self->enemy) - { - if (tr.ent == world) - { - // give up on second try - if (self->monsterinfo.medicTries > 1) - { - abortHeal (self,true); - return; - } - self->monsterinfo.medicTries++; - cleanupHeal (self, 1); - return; - } - abortHeal (self,false); - return; - } - - if (self->s.frame == FRAME_attack43) - { - gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0); - self->enemy->monsterinfo.aiflags |= AI_RESURRECTING; - M_SetEffects(self->enemy); - } - else if (self->s.frame == FRAME_attack50) - { - self->enemy->spawnflags &= SF_MONSTER_NOGIB; - self->enemy->monsterinfo.aiflags = 0; - self->enemy->target = NULL; - self->enemy->targetname = NULL; - self->enemy->combattarget = NULL; - self->enemy->deathtarget = NULL; - self->enemy->owner = self; - // Lazarus: reset initially dead monsters to use the INVERSE of their - // initial health, and force gib_health to default value - if(self->enemy->max_health < 0) - { - self->enemy->max_health = -self->enemy->max_health; - self->enemy->gib_health = 0; - } - self->enemy->health = self->enemy->max_health; - self->enemy->takedamage = DAMAGE_AIM; - self->enemy->flags &= ~FL_NO_KNOCKBACK; - self->enemy->pain_debounce_time = 0; - self->enemy->damage_debounce_time = 0; - self->enemy->deadflag = DEAD_NO; - if(self->enemy->s.effects & EF_FLIES) - M_FliesOff(self->enemy); - ED_CallSpawn (self->enemy); - self->enemy->monsterinfo.healer = NULL; - self->enemy->owner = NULL; - if (self->enemy->think) - { - self->enemy->nextthink = level.time; - self->enemy->think (self->enemy); - } - self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING; - M_SetEffects(self->enemy); - if (self->oldenemy && self->oldenemy->client) - { - self->enemy->enemy = self->oldenemy; - FoundTarget (self->enemy); - } - else - { - // Lazarus: this should make oblivious monsters - // find player again - self->enemy->enemy = NULL; - } - - } - else - { - if (self->s.frame == FRAME_attack44) - gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0); - } - - // adjust start for beam origin being in middle of a segment - // Lazarus: This isn't right... this causes cable start point to be well above muzzle - // when target is closeby. f should be vector from muzzle to target, not - // the forward viewing direction. PLUS... 8 isn't right... the model is - // actually 32 units long, so use 16.. fixed below. -// VectorMA (start, 8, f, start); - - // adjust end z for end spot since the monster is currently dead - VectorCopy (self->enemy->s.origin, end); - end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2; - - // Lazarus fix - VectorSubtract(end,start,f); - VectorNormalize(f); - VectorMA(start,16,f,start); - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_MEDIC_CABLE_ATTACK); - WRITE_SHORT (self - g_edicts); - WRITE_COORD (start); - WRITE_COORD (end); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); -} - -void medic_hook_retract (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0); - if(self->enemy) - { - self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING; - M_SetEffects (self->enemy); - } -} - -mframe_t medic_frames_attackCable [] = -{ - ai_move, 2, NULL, - ai_move, 3, NULL, - ai_move, 5, NULL, - ai_move, 4.4, NULL, - ai_charge, 4.7, NULL, - ai_charge, 5, NULL, - ai_charge, 6, NULL, - ai_charge, 4, NULL, - ai_charge, 0, NULL, - ai_move, 0, medic_hook_launch, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, 0, medic_cable_attack, - ai_move, -15, medic_hook_retract, - ai_move, -1.5, NULL, - ai_move, -1.2, NULL, - ai_move, -3, NULL, - ai_move, -2, NULL, - ai_move, 0.3, NULL, - ai_move, 0.7, NULL, - ai_move, 1.2, NULL, - ai_move, 1.3, NULL -}; -mmove_t medic_move_attackCable = {FRAME_attack33, FRAME_attack60, medic_frames_attackCable, medic_run}; - - -void medic_attack(edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_MEDIC) - self->monsterinfo.currentmove = &medic_move_attackCable; - else - self->monsterinfo.currentmove = &medic_move_attackBlaster; -} - -bool medic_checkattack (edict_t *self) -{ - if (!(self->monsterinfo.aiflags & AI_MEDIC)) - { - if( medic_FindDeadMonster(self) ) - return false; - } - - if (self->monsterinfo.aiflags & AI_MEDIC) - { - float r; - vec3_t forward, right, offset, start; - trace_t tr; - - // if we have 5 seconds or less before a timeout, - // look for a hint_path to the target - if ( (self->timestamp < level.time + 5) && - (self->monsterinfo.last_hint_time + 5 < level.time) ) - { - // check for hint_paths. - self->monsterinfo.last_hint_time = level.time; - if(monsterlost_checkhint(self)) - { - if(developer->value) - gi.dprintf("medic at %s using hint_paths to find %s\n", - vtos(self->s.origin), self->enemy->classname); - self->timestamp = level.time + MEDIC_TRY_TIME; - return false; - } - } - - // if we ran out of time, give up - if (self->timestamp < level.time) - { - if(developer->value) - gi.dprintf("medic at %s timed out, abort heal\n",vtos(self->s.origin)); - abortHeal (self, true); - self->timestamp = 0; - return false; - } - - // if our target went away - if ((!self->enemy) || (!self->enemy->inuse)) { - abortHeal (self,false); - return false; - } - // if target is embedded in a solid - if (embedded(self->enemy)) - { - abortHeal (self,false); - return false; - } - r = realrange(self,self->enemy); - if (r > MEDIC_MAX_HEAL_DISTANCE+10) { - self->monsterinfo.attack_state = AS_STRAIGHT; -// abortHeal(self,false); - return false; - } else if(r < MEDIC_MIN_DISTANCE) { - abortHeal(self,false); - return false; - } - // Lazarus 1.6.2.3: if point-to-point vector from cable to - // target is blocked by a solid - AngleVectors (self->s.angles, forward, right, NULL); - // Offset [8] has the largest displacement to the left... not a sure - // thing but this one should be the most severe test. - VectorCopy (medic_cable_offsets[8], offset); - G_ProjectSource (self->s.origin, offset, forward, right, start); - tr = gi.trace(start,NULL,NULL,self->enemy->s.origin,self,MASK_SHOT|MASK_WATER); - if (tr.fraction < 1.0 && tr.ent != self->enemy) - return false; - medic_attack(self); - return true; - } - - // Lazarus: NEVER attack other monsters - if ((self->enemy) && (self->enemy->svflags & SVF_MONSTER)) - { - self->enemy = self->oldenemy; - self->oldenemy = NULL; - if(self->enemy && self->enemy->inuse) - { - if(visible(self,self->enemy)) - FoundTarget(self); - else - HuntTarget(self); - } - return false; - } - - return M_CheckAttack (self); -} - - -/*QUAKED monster_medic (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_medic (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_MEDIC; - - if (world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - G_FreeEdict (self); - return; - } - sound_idle1 = gi.soundindex ("medic/idle.wav"); - sound_pain1 = gi.soundindex ("medic/medpain1.wav"); - sound_pain2 = gi.soundindex ("medic/medpain2.wav"); - sound_die = gi.soundindex ("medic/meddeth1.wav"); - sound_sight = gi.soundindex ("medic/medsght1.wav"); - sound_search = gi.soundindex ("medic/medsrch1.wav"); - sound_hook_launch = gi.soundindex ("medic/medatck2.wav"); - sound_hook_hit = gi.soundindex ("medic/medatck3.wav"); - sound_hook_heal = gi.soundindex ("medic/medatck4.wav"); - sound_hook_retract = gi.soundindex ("medic/medatck5.wav"); - - gi.soundindex ("medic/medatck1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/medic/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/medic/tris.md2"); - VectorSet (self->mins, -24, -24, -24); - VectorSet (self->maxs, 24, 24, 32); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 300; - if(!self->gib_health) - self->gib_health = -130; - if(!self->mass) - self->mass = 400; - - self->pain = medic_pain; - self->die = medic_die; - - self->monsterinfo.stand = medic_stand; - self->monsterinfo.walk = medic_walk; - self->monsterinfo.run = medic_run; - self->monsterinfo.dodge = medic_dodge; - self->monsterinfo.attack = medic_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = medic_sight; - self->monsterinfo.idle = medic_idle; - self->monsterinfo.search = medic_search; - self->monsterinfo.checkattack = medic_checkattack; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.15; - - gi.linkentity (self); - self->monsterinfo.currentmove = &medic_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&medic_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Medic"; - self->monsterinfo.scale = MODEL_SCALE; - - walkmonster_start (self); -} diff --git a/server/monsters/m_medic.h b/server/monsters/m_medic.h deleted file mode 100644 index 1e4b47c7..00000000 --- a/server/monsters/m_medic.h +++ /dev/null @@ -1,243 +0,0 @@ -// G:\quake2\baseq2\models/monsters/medic - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_walk1 0 -#define FRAME_walk2 1 -#define FRAME_walk3 2 -#define FRAME_walk4 3 -#define FRAME_walk5 4 -#define FRAME_walk6 5 -#define FRAME_walk7 6 -#define FRAME_walk8 7 -#define FRAME_walk9 8 -#define FRAME_walk10 9 -#define FRAME_walk11 10 -#define FRAME_walk12 11 -#define FRAME_wait1 12 -#define FRAME_wait2 13 -#define FRAME_wait3 14 -#define FRAME_wait4 15 -#define FRAME_wait5 16 -#define FRAME_wait6 17 -#define FRAME_wait7 18 -#define FRAME_wait8 19 -#define FRAME_wait9 20 -#define FRAME_wait10 21 -#define FRAME_wait11 22 -#define FRAME_wait12 23 -#define FRAME_wait13 24 -#define FRAME_wait14 25 -#define FRAME_wait15 26 -#define FRAME_wait16 27 -#define FRAME_wait17 28 -#define FRAME_wait18 29 -#define FRAME_wait19 30 -#define FRAME_wait20 31 -#define FRAME_wait21 32 -#define FRAME_wait22 33 -#define FRAME_wait23 34 -#define FRAME_wait24 35 -#define FRAME_wait25 36 -#define FRAME_wait26 37 -#define FRAME_wait27 38 -#define FRAME_wait28 39 -#define FRAME_wait29 40 -#define FRAME_wait30 41 -#define FRAME_wait31 42 -#define FRAME_wait32 43 -#define FRAME_wait33 44 -#define FRAME_wait34 45 -#define FRAME_wait35 46 -#define FRAME_wait36 47 -#define FRAME_wait37 48 -#define FRAME_wait38 49 -#define FRAME_wait39 50 -#define FRAME_wait40 51 -#define FRAME_wait41 52 -#define FRAME_wait42 53 -#define FRAME_wait43 54 -#define FRAME_wait44 55 -#define FRAME_wait45 56 -#define FRAME_wait46 57 -#define FRAME_wait47 58 -#define FRAME_wait48 59 -#define FRAME_wait49 60 -#define FRAME_wait50 61 -#define FRAME_wait51 62 -#define FRAME_wait52 63 -#define FRAME_wait53 64 -#define FRAME_wait54 65 -#define FRAME_wait55 66 -#define FRAME_wait56 67 -#define FRAME_wait57 68 -#define FRAME_wait58 69 -#define FRAME_wait59 70 -#define FRAME_wait60 71 -#define FRAME_wait61 72 -#define FRAME_wait62 73 -#define FRAME_wait63 74 -#define FRAME_wait64 75 -#define FRAME_wait65 76 -#define FRAME_wait66 77 -#define FRAME_wait67 78 -#define FRAME_wait68 79 -#define FRAME_wait69 80 -#define FRAME_wait70 81 -#define FRAME_wait71 82 -#define FRAME_wait72 83 -#define FRAME_wait73 84 -#define FRAME_wait74 85 -#define FRAME_wait75 86 -#define FRAME_wait76 87 -#define FRAME_wait77 88 -#define FRAME_wait78 89 -#define FRAME_wait79 90 -#define FRAME_wait80 91 -#define FRAME_wait81 92 -#define FRAME_wait82 93 -#define FRAME_wait83 94 -#define FRAME_wait84 95 -#define FRAME_wait85 96 -#define FRAME_wait86 97 -#define FRAME_wait87 98 -#define FRAME_wait88 99 -#define FRAME_wait89 100 -#define FRAME_wait90 101 -#define FRAME_run1 102 -#define FRAME_run2 103 -#define FRAME_run3 104 -#define FRAME_run4 105 -#define FRAME_run5 106 -#define FRAME_run6 107 -#define FRAME_paina1 108 -#define FRAME_paina2 109 -#define FRAME_paina3 110 -#define FRAME_paina4 111 -#define FRAME_paina5 112 -#define FRAME_paina6 113 -#define FRAME_paina7 114 -#define FRAME_paina8 115 -#define FRAME_painb1 116 -#define FRAME_painb2 117 -#define FRAME_painb3 118 -#define FRAME_painb4 119 -#define FRAME_painb5 120 -#define FRAME_painb6 121 -#define FRAME_painb7 122 -#define FRAME_painb8 123 -#define FRAME_painb9 124 -#define FRAME_painb10 125 -#define FRAME_painb11 126 -#define FRAME_painb12 127 -#define FRAME_painb13 128 -#define FRAME_painb14 129 -#define FRAME_painb15 130 -#define FRAME_duck1 131 -#define FRAME_duck2 132 -#define FRAME_duck3 133 -#define FRAME_duck4 134 -#define FRAME_duck5 135 -#define FRAME_duck6 136 -#define FRAME_duck7 137 -#define FRAME_duck8 138 -#define FRAME_duck9 139 -#define FRAME_duck10 140 -#define FRAME_duck11 141 -#define FRAME_duck12 142 -#define FRAME_duck13 143 -#define FRAME_duck14 144 -#define FRAME_duck15 145 -#define FRAME_duck16 146 -#define FRAME_death1 147 -#define FRAME_death2 148 -#define FRAME_death3 149 -#define FRAME_death4 150 -#define FRAME_death5 151 -#define FRAME_death6 152 -#define FRAME_death7 153 -#define FRAME_death8 154 -#define FRAME_death9 155 -#define FRAME_death10 156 -#define FRAME_death11 157 -#define FRAME_death12 158 -#define FRAME_death13 159 -#define FRAME_death14 160 -#define FRAME_death15 161 -#define FRAME_death16 162 -#define FRAME_death17 163 -#define FRAME_death18 164 -#define FRAME_death19 165 -#define FRAME_death20 166 -#define FRAME_death21 167 -#define FRAME_death22 168 -#define FRAME_death23 169 -#define FRAME_death24 170 -#define FRAME_death25 171 -#define FRAME_death26 172 -#define FRAME_death27 173 -#define FRAME_death28 174 -#define FRAME_death29 175 -#define FRAME_death30 176 -#define FRAME_attack1 177 -#define FRAME_attack2 178 -#define FRAME_attack3 179 -#define FRAME_attack4 180 -#define FRAME_attack5 181 -#define FRAME_attack6 182 -#define FRAME_attack7 183 -#define FRAME_attack8 184 -#define FRAME_attack9 185 -#define FRAME_attack10 186 -#define FRAME_attack11 187 -#define FRAME_attack12 188 -#define FRAME_attack13 189 -#define FRAME_attack14 190 -#define FRAME_attack15 191 -#define FRAME_attack16 192 -#define FRAME_attack17 193 -#define FRAME_attack18 194 -#define FRAME_attack19 195 -#define FRAME_attack20 196 -#define FRAME_attack21 197 -#define FRAME_attack22 198 -#define FRAME_attack23 199 -#define FRAME_attack24 200 -#define FRAME_attack25 201 -#define FRAME_attack26 202 -#define FRAME_attack27 203 -#define FRAME_attack28 204 -#define FRAME_attack29 205 -#define FRAME_attack30 206 -#define FRAME_attack31 207 -#define FRAME_attack32 208 -#define FRAME_attack33 209 -#define FRAME_attack34 210 -#define FRAME_attack35 211 -#define FRAME_attack36 212 -#define FRAME_attack37 213 -#define FRAME_attack38 214 -#define FRAME_attack39 215 -#define FRAME_attack40 216 -#define FRAME_attack41 217 -#define FRAME_attack42 218 -#define FRAME_attack43 219 -#define FRAME_attack44 220 -#define FRAME_attack45 221 -#define FRAME_attack46 222 -#define FRAME_attack47 223 -#define FRAME_attack48 224 -#define FRAME_attack49 225 -#define FRAME_attack50 226 -#define FRAME_attack51 227 -#define FRAME_attack52 228 -#define FRAME_attack53 229 -#define FRAME_attack54 230 -#define FRAME_attack55 231 -#define FRAME_attack56 232 -#define FRAME_attack57 233 -#define FRAME_attack58 234 -#define FRAME_attack59 235 -#define FRAME_attack60 236 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_move.c b/server/monsters/m_move.c deleted file mode 100644 index ce9a6688..00000000 --- a/server/monsters/m_move.c +++ /dev/null @@ -1,896 +0,0 @@ -// m_move.c -- monster movement - -#include "g_local.h" - -#define STEPSIZE 18 - -/* -============= -M_CheckBottom - -Returns false if any part of the bottom of the entity is off an edge that -is not a staircase. - -============= -*/ -int c_yes, c_no; - -bool M_CheckBottom (edict_t *ent) -{ - vec3_t mins, maxs, start, stop; - trace_t trace; - int x, y; - float mid, bottom; - - VectorAdd (ent->s.origin, ent->mins, mins); - VectorAdd (ent->s.origin, ent->maxs, maxs); - -// if all of the points under the corners are solid world, don't bother -// with the tougher checks -// the corners must be within 16 of the midpoint - start[2] = mins[2] - 1; - for (x=0 ; x<=1 ; x++) - for (y=0 ; y<=1 ; y++) - { - start[0] = x ? maxs[0] : mins[0]; - start[1] = y ? maxs[1] : mins[1]; - if (gi.pointcontents (start) != CONTENTS_SOLID) - goto realcheck; - } - - c_yes++; - return true; // we got out easy - -realcheck: - c_no++; -// -// check it for real... -// - start[2] = mins[2]; - -// the midpoint must be within 16 of the bottom - start[0] = stop[0] = (mins[0] + maxs[0])*0.5; - start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*STEPSIZE; - trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); - - if (trace.fraction == 1.0) - return false; - mid = bottom = trace.endpos[2]; - -// the corners must be within 16 of the midpoint - for (x=0 ; x<=1 ; x++) - for (y=0 ; y<=1 ; y++) - { - start[0] = stop[0] = x ? maxs[0] : mins[0]; - start[1] = stop[1] = y ? maxs[1] : mins[1]; - - trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); - - if (trace.fraction != 1.0 && trace.endpos[2] > bottom) - bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) - return false; - } - - c_yes++; - return true; -} - - -/* -============= -SV_movestep - -Called by monster program code. -The move will be adjusted for slopes and stairs, but if the move isn't -possible, no move is done, false is returned, and -pr_global_struct->trace_normal is set to the normal of the blocking wall -============= -*/ -//FIXME since we need to test end position contents here, can we avoid doing -//it again later in catagorize position? -bool SV_movestep (edict_t *ent, vec3_t move, bool relink) -{ - float dz; - vec3_t oldorg, neworg, end; - trace_t trace; - int i; - float stepsize; - float jumpheight; - vec3_t test; - int contents; - - bool canjump; - float d1, d2; - int jump; // 1=jump up, -1=jump down - vec3_t forward, up; - vec3_t dir; - vec_t dist; - vec_t g1, g2; - edict_t *grenade; - edict_t *target; - - // try the move - VectorCopy (ent->s.origin, oldorg); - VectorAdd (ent->s.origin, move, neworg); - - AngleVectors(ent->s.angles,forward,NULL,up); - if(ent->enemy) - target = ent->enemy; - else if(ent->movetarget) - target = ent->movetarget; - else - target = NULL; - - // flying monsters don't step up - if ( ent->flags & (FL_SWIM | FL_FLY) ) - { - // try one move with vertical motion, then one without - for (i=0 ; i<2 ; i++) - { - VectorAdd (ent->s.origin, move, neworg); - if (i == 0 && ent->enemy) - { - if (!ent->goalentity) - ent->goalentity = ent->enemy; - dz = ent->s.origin[2] - ent->goalentity->s.origin[2]; - if (ent->goalentity->client) - { - if (dz > 40) - neworg[2] -= 8; - if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2))) - if (dz < 30) - neworg[2] += 8; - } - else - { - if (dz > 8) - neworg[2] -= 8; - else if (dz > 0) - neworg[2] -= dz; - else if (dz < -8) - neworg[2] += 8; - else - neworg[2] += dz; - } - } - trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID); - - // fly monsters don't enter water voluntarily - if (ent->flags & FL_FLY) - { - if (!ent->waterlevel) - { - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - test[2] = trace.endpos[2] + ent->mins[2] + 1; - contents = gi.pointcontents(test); - if (contents & MASK_WATER) - return false; - } - } - - // swim monsters don't exit water voluntarily - if (ent->flags & FL_SWIM) - { - if (ent->waterlevel < 2) - { - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - test[2] = trace.endpos[2] + ent->mins[2] + 1; - contents = gi.pointcontents(test); - if (!(contents & MASK_WATER)) - return false; - } - } - - if (trace.fraction == 1) - { - VectorCopy (trace.endpos, ent->s.origin); - if (relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - return true; - } - - if (!ent->enemy) - break; - } - - return false; - } - - // push down from a step height above the wished position - if (!(ent->monsterinfo.aiflags & AI_NOSTEP)) - stepsize = STEPSIZE; - else - stepsize = 1; - - neworg[2] += stepsize; - VectorCopy (neworg, end); - end[2] -= stepsize*2; - - trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); - - // Determine whether monster is capable of and/or should jump - jump = 0; - if((ent->monsterinfo.jump) && !(ent->monsterinfo.aiflags & AI_DUCKED)) - { - // Don't jump if path is blocked by monster or player. Otherwise, - // monster might attempt to jump OVER the monster/player, which - // ends up looking a bit goofy. Also don't jump if the monster's - // movement isn't deliberate (target=NULL) - if(trace.ent && (trace.ent->client || (trace.ent->svflags & SVF_MONSTER))) - canjump = false; - else if(target) - { - // Never jump unless it places monster closer to his goal - vec3_t dir; - VectorSubtract(target->s.origin, oldorg, dir); - d1 = VectorLength(dir); - VectorSubtract(target->s.origin, trace.endpos, dir); - d2 = VectorLength(dir); - if(d2 < d1) - canjump = true; - else - canjump = false; - } - else - canjump = false; - } - else - canjump = false; - - if (trace.allsolid) - { - if(canjump && (ent->monsterinfo.jumpup > 0)) - { - neworg[2] += ent->monsterinfo.jumpup - stepsize; - trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); - if (!trace.allsolid && !trace.startsolid && trace.fraction > 0 && (trace.plane.normal[2] > 0.9)) - { - if(!trace.ent || (!trace.ent->client && !(trace.ent->svflags & SVF_MONSTER) && !(trace.ent->svflags & SVF_DEADMONSTER))) - { - // Good plane to jump on. Make sure monster is more or less facing - // the obstacle to avoid cutting-corners jumps - trace_t tr; - vec3_t p2; - - VectorMA(ent->s.origin,1024,forward,p2); - tr = gi.trace(ent->s.origin,ent->mins,ent->maxs,p2,ent,MASK_MONSTERSOLID); - if(DotProduct(tr.plane.normal,forward) < -0.95) - { - jump = 1; - jumpheight = trace.endpos[2] - ent->s.origin[2]; - } - else - return false; - } - } - else - return false; - } - else - return false; - } - - if (trace.startsolid) - { - neworg[2] -= stepsize; - trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); - if (trace.allsolid || trace.startsolid) - return false; - } - - - // don't go in to water - // Lazarus: misc_actors don't go swimming, but wading is fine - if (ent->monsterinfo.aiflags & AI_ACTOR) - { - // First check for lava/slime under feet - but only if we're not already in - // a liquid - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - if (ent->waterlevel == 0) - { - test[2] = trace.endpos[2] + ent->mins[2] + 1; - contents = gi.pointcontents(test); - if (contents & (CONTENTS_LAVA | CONTENTS_SLIME)) - return false; - } - test[2] = trace.endpos[2] + ent->viewheight - 1; - contents = gi.pointcontents(test); - if (contents & MASK_WATER) - return false; - } - else if (ent->waterlevel == 0) - { - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - test[2] = trace.endpos[2] + ent->mins[2] + 1; - contents = gi.pointcontents(test); - - if (contents & MASK_WATER) - return false; - } - - // Lazarus: Don't intentionally move closer to a grenade, - // but don't perform this check if we're already evading some - // other problem (maybe even this grenade) - if(!(ent->monsterinfo.aiflags & AI_CHASE_THING)) - { - grenade = NULL; - while( (grenade=findradius(grenade,neworg,128)) != NULL) - { - if(!grenade->inuse) - continue; - if(!grenade->classname) - continue; - if((grenade->class_id == ENTITY_GRENADE) || (grenade->class_id == ENTITY_HANDGRENADE)) - { - VectorSubtract(grenade->s.origin,oldorg,dir); - g1 = VectorLength(dir); - VectorSubtract(grenade->s.origin,neworg,dir); - g2 = VectorLength(dir); - if(g2 < g1) - return false; - } - } - } - // Lazarus: Don't intentionally walk into lasers. - dist = VectorLength(move); - if(dist > 0.) - { - edict_t *e; - trace_t laser_trace; - vec_t delta; - vec3_t laser_mins, laser_maxs; - vec3_t laser_start, laser_end; - vec3_t monster_mins, monster_maxs; - - for(i=game.maxclients+1; iinuse) - continue; - if(!e->classname) - continue; - if(e->class_id != ENTITY_TARGET_LASER) - continue; - if(e->svflags & SVF_NOCLIENT) - continue; - if( (e->style == 2) || (e->style == 3)) - continue; - if(!gi.inPVS(ent->s.origin,e->s.origin)) - continue; - // Check to see if monster is ALREADY in the path of this laser. - // If so, allow the move so he can get out. - VectorMA(e->s.origin,2048,e->movedir,laser_end); - laser_trace = gi.trace(e->s.origin,NULL,NULL,laser_end,NULL,CONTENTS_SOLID|CONTENTS_MONSTER); - if(laser_trace.ent == ent) - continue; - VectorCopy(laser_trace.endpos,laser_end); - laser_mins[0] = min(e->s.origin[0],laser_end[0]); - laser_mins[1] = min(e->s.origin[1],laser_end[1]); - laser_mins[2] = min(e->s.origin[2],laser_end[2]); - laser_maxs[0] = max(e->s.origin[0],laser_end[0]); - laser_maxs[1] = max(e->s.origin[1],laser_end[1]); - laser_maxs[2] = max(e->s.origin[2],laser_end[2]); - monster_mins[0] = min(oldorg[0],trace.endpos[0]) + ent->mins[0]; - monster_mins[1] = min(oldorg[1],trace.endpos[1]) + ent->mins[1]; - monster_mins[2] = min(oldorg[2],trace.endpos[2]) + ent->mins[2]; - monster_maxs[0] = max(oldorg[0],trace.endpos[0]) + ent->maxs[0]; - monster_maxs[1] = max(oldorg[1],trace.endpos[1]) + ent->maxs[1]; - monster_maxs[2] = max(oldorg[2],trace.endpos[2]) + ent->maxs[2]; - if( monster_maxs[0] < laser_mins[0] ) continue; - if( monster_maxs[1] < laser_mins[1] ) continue; - if( monster_maxs[2] < laser_mins[2] ) continue; - if( monster_mins[0] > laser_maxs[0] ) continue; - if( monster_mins[1] > laser_maxs[1] ) continue; - if( monster_mins[2] > laser_maxs[2] ) continue; - // If we arrive here, some part of the bounding box surrounding - // monster's total movement intersects laser bounding box. - // If laser is parallel to x, y, or z, we definitely - // know this move will put monster in path of laser - if ( (e->movedir[0] == 1.) || (e->movedir[1] == 1.) || (e->movedir[2] == 1.)) - return false; - // Shift psuedo laser towards monster's current position up to - // the total distance he's proposing moving. - delta = min(16,dist); - VectorCopy(move,dir); - VectorNormalize(dir); - while(delta < dist+15.875) - { - if(delta > dist) delta = dist; - VectorMA(e->s.origin, -delta,dir,laser_start); - VectorMA(e->s.old_origin,-delta,dir,laser_end); - laser_trace = gi.trace(laser_start,NULL,NULL,laser_end,world,CONTENTS_SOLID|CONTENTS_MONSTER); - if(laser_trace.ent == ent) - return false; - delta += 16; - } - } - } - if ((trace.fraction == 1) && !jump && canjump && (ent->monsterinfo.jumpdn > 0)) - { - end[2] = oldorg[2] + move[2] - ent->monsterinfo.jumpdn; - trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID | MASK_WATER); - if(trace.fraction < 1 && (trace.plane.normal[2] > 0.9) && (trace.contents & MASK_SOLID) && (neworg[2] - 16 > trace.endpos[2])) - { - if(!trace.ent || (!trace.ent->client && !(trace.ent->svflags & SVF_MONSTER) && !(trace.ent->svflags & SVF_DEADMONSTER))) - jump = -1; - } - } - - - if ((trace.fraction == 1) && !jump) - { - // if monster had the ground pulled out, go ahead and fall - if ( ent->flags & FL_PARTIALGROUND ) - { - VectorAdd (ent->s.origin, move, ent->s.origin); - if (relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - ent->groundentity = NULL; - return true; - } - return false; // walked off an edge - } - - // check point traces down for dangling corners - VectorCopy (trace.endpos, ent->s.origin); - - if(!jump) - { - bool skip = false; - // if monster CAN jump down, and a position just a bit forward would be - // a good jump-down spot, allow (briefly) !M_CheckBottom - if (canjump && target && (target->s.origin[2] < ent->s.origin[2]) && (ent->monsterinfo.jumpdn > 0)) - { - vec3_t p1, p2; - trace_t tr; - - VectorMA(oldorg,48,forward,p1); - tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, p1, ent, MASK_MONSTERSOLID); - if(tr.fraction == 1) - { - p2[0] = p1[0]; - p2[1] = p1[1]; - p2[2] = p1[2] - ent->monsterinfo.jumpdn; - tr = gi.trace(p1,ent->mins,ent->maxs,p2,ent,MASK_MONSTERSOLID | MASK_WATER); - if(tr.fraction < 1 && (tr.plane.normal[2] > 0.9) && (tr.contents & MASK_SOLID) && (p1[2] - 16 > tr.endpos[2])) - { - if(!tr.ent || (!tr.ent->client && !(tr.ent->svflags & SVF_MONSTER) && !(tr.ent->svflags & SVF_DEADMONSTER))) - { - VectorSubtract(target->s.origin, tr.endpos, dir); - d2 = VectorLength(dir); - if(d2 < d1) - skip = true; - } - } - } - - } - if (!skip) - { - if (!M_CheckBottom (ent)) - { - if ( ent->flags & FL_PARTIALGROUND ) - { // entity had floor mostly pulled out from underneath it - // and is trying to correct - if (relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - return true; - } - VectorCopy (oldorg, ent->s.origin); - return false; - } - } - } - - if ( ent->flags & FL_PARTIALGROUND ) - { - ent->flags &= ~FL_PARTIALGROUND; - } - ent->groundentity = trace.ent; - if(trace.ent) - ent->groundentity_linkcount = trace.ent->linkcount; - -// the move is ok - if(jump) - { - VectorScale(move, 10, ent->velocity); - if(jump > 0) - { - ent->monsterinfo.jump(ent); - ent->velocity[2] = 2.5*jumpheight + 80; - } - else - { - ent->velocity[2] = max(ent->velocity[2],100); - if(oldorg[2] - ent->s.origin[2] > 48) - ent->s.origin[2] = oldorg[2] + ent->velocity[2]*FRAMETIME; - } - if(relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - } - else if (relink) - { - gi.linkentity (ent); - G_TouchTriggers (ent); - } - return true; -} - - -//============================================================================ - -/* -=============== -M_ChangeYaw - -=============== -*/ -void M_ChangeYaw (edict_t *ent) -{ - float ideal; - float current; - float move; - float speed; - - current = anglemod(ent->s.angles[YAW]); - ideal = ent->ideal_yaw; - - if (current == ideal) - return; - - move = ideal - current; - speed = ent->yaw_speed; - 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; - } - - ent->s.angles[YAW] = anglemod (current + move); -} - - -/* -====================== -SV_StepDirection - -Turns to the movement direction, and walks the current distance if -facing it. - -====================== -*/ -bool SV_StepDirection (edict_t *ent, float yaw, float dist) -{ - vec3_t move, oldorigin; - float delta; - - ent->ideal_yaw = yaw; - M_ChangeYaw (ent); - - yaw = yaw*M_PI*2 / 360; - move[0] = cos(yaw)*dist; - move[1] = sin(yaw)*dist; - move[2] = 0; - - VectorCopy (ent->s.origin, oldorigin); - if (SV_movestep (ent, move, false)) - { - delta = ent->s.angles[YAW] - ent->ideal_yaw; - if (delta > 45 && delta < 315) - { // not turned far enough, so don't take the step - VectorCopy (oldorigin, ent->s.origin); - } - gi.linkentity (ent); - G_TouchTriggers (ent); - return true; - } - gi.linkentity (ent); - G_TouchTriggers (ent); - return false; -} - -/* -====================== -SV_FixCheckBottom - -====================== -*/ -void SV_FixCheckBottom (edict_t *ent) -{ - ent->flags |= FL_PARTIALGROUND; -} - - - -/* -================ -SV_NewChaseDir - -================ -*/ -#define DI_NODIR -1 -void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) -{ - float deltax,deltay; - float d[3]; - float tdir, olddir, turnaround; - - //FIXME: how did we get here with no enemy - if (!enemy) - return; - - if(actor->flags & FL_ROBOT) - olddir = anglemod( (int)(actor->ideal_yaw+0.5) ); - else - olddir = anglemod( (int)(actor->ideal_yaw/45)*45 ); - turnaround = anglemod(olddir - 180); - - deltax = enemy->s.origin[0] - actor->s.origin[0]; - deltay = enemy->s.origin[1] - actor->s.origin[1]; - - if(actor->flags & FL_ROBOT) - { - d[1] = d[2] = olddir; - } - else - { - if (deltax>10) - d[1]= 0; - else if (deltax<-10) - d[1]= 180; - else - d[1]= DI_NODIR; - if (deltay<-10) - d[2]= 270; - else if (deltay>10) - d[2]= 90; - else - d[2]= DI_NODIR; - } - -// try direct route - if (d[1] != DI_NODIR && d[2] != DI_NODIR) - { - if(actor->flags & FL_ROBOT) - tdir = d[1]; - else - { - if (d[1] == 0) - tdir = d[2] == 90 ? 45 : 315; - else - tdir = d[2] == 90 ? 135 : 215; - } - if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) - return; - } - - // Robots give up if direct path doesn't work - if(actor->flags & FL_ROBOT) - { - actor->ideal_yaw = olddir; // can't move - if (!M_CheckBottom (actor)) - SV_FixCheckBottom (actor); - } - -// try other directions - if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax)) - { - tdir=d[1]; - d[1]=d[2]; - d[2]=tdir; - } - if (d[1]!=DI_NODIR && d[1]!=turnaround - && SV_StepDirection(actor, d[1], dist)) - return; - - if (d[2]!=DI_NODIR && d[2]!=turnaround - && SV_StepDirection(actor, d[2], dist)) - return; - -//ROGUE - if(actor->monsterinfo.blocked) - { - if ((actor->inuse) && (actor->health > 0)) - { - if((actor->monsterinfo.blocked)(actor, dist)) - return; - } - } -//ROGUE - -/* there is no direct path to the player, so pick another direction */ - - if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist)) - return; - - if (rand()&1) /*randomly determine direction of search*/ - { - for (tdir=0 ; tdir<=315 ; tdir += 45) - if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) - return; - } - else - { - for (tdir=315 ; tdir >=0 ; tdir -= 45) - if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) - return; - } - - if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) ) - return; - - actor->ideal_yaw = olddir; // can't move - -// if a bridge was pulled out from underneath a monster, it may not have -// a valid standing position at all - - if (!M_CheckBottom (actor)) - SV_FixCheckBottom (actor); -} - -/* -====================== -SV_CloseEnough - -====================== -*/ -bool SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) -{ - int i; - - for (i=0 ; i<3 ; i++) - { - if (goal->absmin[i] > ent->absmax[i] + dist) - return false; - if (goal->absmax[i] < ent->absmin[i] - dist) - return false; - } - return true; -} - - -/* -====================== -M_MoveToGoal -====================== -*/ -mmove_t actor_move_run; -mmove_t actor_move_stand; -mmove_t actor_move_walk; -void M_MoveToGoal (edict_t *ent, float dist) -{ - edict_t *goal; - - goal = ent->goalentity; - - if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) - return; - - // Lazarus range checks - if (!(ent->monsterinfo.aiflags & (AI_CHASE_THING | AI_CHICKEN))) - { - if (ent->enemy && (ent->monsterinfo.min_range > 0) && ((goal==ent->enemy) || !goal) ) { - float dist; - dist = realrange(ent,ent->enemy); - if(dist < ent->monsterinfo.min_range) - { - ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE); - ent->monsterinfo.rangetime = level.time + 0.5; - ent->monsterinfo.stand(ent); - return; - } - } - if ((ent->enemy) && (level.time > ent->monsterinfo.rangetime + 0.5) && ((goal==ent->enemy) || !goal) ) - { - float dist; - dist = realrange(ent,ent->enemy); - if((dist < ent->monsterinfo.ideal_range[0]) && (rand() & 3)) - { - ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE); - ent->monsterinfo.rangetime = level.time + 1.0; - ent->monsterinfo.stand(ent); - return; - } - if((dist < ent->monsterinfo.ideal_range[1]) && (dist > ent->monsterinfo.ideal_range[0]) && (rand() & 1)) - { - ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE); - ent->monsterinfo.rangetime = level.time + 0.2; - ent->monsterinfo.stand(ent); - return; - } - } - } - - if( (ent->monsterinfo.aiflags & AI_FOLLOW_LEADER) && - (ent->movetarget) && - (ent->movetarget->inuse) && - (ent->movetarget->health > 0) ) { - - if(ent->enemy) - ent->monsterinfo.currentmove = &actor_move_run; - else - { - float R; - - R = realrange(ent,ent->movetarget); - if(R > ACTOR_FOLLOW_RUN_RANGE) - ent->monsterinfo.currentmove = &actor_move_run; - else if(R < ACTOR_FOLLOW_STAND_RANGE && ent->movetarget->client) { - ent->monsterinfo.pausetime = level.time + 0.5; - ent->monsterinfo.currentmove = &actor_move_stand; - return; - } - else - ent->monsterinfo.currentmove = &actor_move_walk; - } - } - -// If the next step hits the enemy, return immediately. Don't do this for -// AI_CHASE_THING, since we want monster to actually touch or pass through -// "thing" - if (ent->enemy && !(ent->monsterinfo.aiflags & AI_CHASE_THING) && SV_CloseEnough (ent, ent->enemy, dist) ) - return; - -// bump around... - if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist)) - { - if (ent->inuse) - SV_NewChaseDir (ent, goal, dist); - } -} - - -/* -=============== -M_walkmove -=============== -*/ -bool M_walkmove (edict_t *ent, float yaw, float dist) -{ - vec3_t move; - - if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) - return false; - - yaw = yaw*M_PI*2 / 360; - - move[0] = cos(yaw)*dist; - move[1] = sin(yaw)*dist; - move[2] = 0; - - return SV_movestep(ent, move, true); -} - diff --git a/server/monsters/m_mutant.c b/server/monsters/m_mutant.c deleted file mode 100644 index 9f37f9b0..00000000 --- a/server/monsters/m_mutant.c +++ /dev/null @@ -1,719 +0,0 @@ -/* -============================================================================== - -mutant - -============================================================================== -*/ - -#include "g_local.h" -#include "m_mutant.h" - - -static int sound_swing; -static int sound_hit; -static int sound_hit2; -static int sound_death; -static int sound_idle; -static int sound_pain1; -static int sound_pain2; -static int sound_sight; -static int sound_search; -static int sound_step1; -static int sound_step2; -static int sound_step3; -static int sound_thud; - -// -// SOUNDS -// - -void mutant_step (edict_t *self) -{ - int n; - n = (rand() + 1) % 3; - if (n == 0) - gi.sound (self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0); - else if (n == 1) - gi.sound (self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_step3, 1, ATTN_NORM, 0); -} - -void mutant_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - -void mutant_search (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); -} - -void mutant_swing (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0); -} - - -// -// STAND -// - -mframe_t mutant_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 10 - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 20 - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 30 - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 40 - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 50 - - ai_stand, 0, NULL -}; -mmove_t mutant_move_stand = {FRAME_stand101, FRAME_stand151, mutant_frames_stand, NULL}; - -void mutant_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_stand; -} - - -// -// IDLE -// - -void mutant_idle_loop (edict_t *self) -{ - if (random() < 0.75) - self->monsterinfo.nextframe = FRAME_stand155; -} - -mframe_t mutant_frames_idle [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // scratch loop start - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, mutant_idle_loop, // scratch loop end - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t mutant_move_idle = {FRAME_stand152, FRAME_stand164, mutant_frames_idle, mutant_stand}; - -void mutant_idle (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_idle; - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - - -// -// WALK -// - -void mutant_walk (edict_t *self); - -mframe_t mutant_frames_walk [] = -{ - ai_walk, 3, NULL, - ai_walk, 1, NULL, - ai_walk, 5, NULL, - ai_walk, 10, NULL, - ai_walk, 13, NULL, - ai_walk, 10, NULL, - ai_walk, 0, NULL, - ai_walk, 5, NULL, - ai_walk, 6, NULL, - ai_walk, 16, NULL, - ai_walk, 15, NULL, - ai_walk, 6, NULL -}; -mmove_t mutant_move_walk = {FRAME_walk05, FRAME_walk16, mutant_frames_walk, NULL}; - -void mutant_walk_loop (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_walk; -} - -mframe_t mutant_frames_start_walk [] = -{ - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, -2, NULL, - ai_walk, 1, NULL -}; -mmove_t mutant_move_start_walk = {FRAME_walk01, FRAME_walk04, mutant_frames_start_walk, mutant_walk_loop}; - -void mutant_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_start_walk; -} - - -// -// RUN -// - -mframe_t mutant_frames_run [] = -{ - ai_run, 40, NULL, - ai_run, 40, mutant_step, - ai_run, 24, NULL, - ai_run, 5, mutant_step, - ai_run, 17, NULL, - ai_run, 10, NULL -}; -mmove_t mutant_move_run = {FRAME_run03, FRAME_run08, mutant_frames_run, NULL}; - -void mutant_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &mutant_move_stand; - else - self->monsterinfo.currentmove = &mutant_move_run; -} - - -// -// MELEE -// - -void mutant_hit_left (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8); - if (fire_hit (self, aim, (10 + (rand() %5)), 100)) - gi.sound (self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); -} - -void mutant_hit_right (edict_t *self) -{ - vec3_t aim; - - VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8); - if (fire_hit (self, aim, (10 + (rand() %5)), 100)) - gi.sound (self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); -} - -void mutant_check_refire (edict_t *self) -{ - if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0) - return; - - if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) - self->monsterinfo.nextframe = FRAME_attack09; -} - -mframe_t mutant_frames_attack [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, mutant_hit_left, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, mutant_hit_right, - ai_charge, 0, mutant_check_refire -}; -mmove_t mutant_move_attack = {FRAME_attack09, FRAME_attack15, mutant_frames_attack, mutant_run}; - -void mutant_melee (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_attack; -} - - -// -// ATTACK -// - -void mutant_jump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (self->health <= 0) - { - self->touch = NULL; - return; - } - - if (other->takedamage) - { - if (VectorLength(self->velocity) > 400) - { - vec3_t point; - vec3_t normal; - int damage; - - VectorCopy (self->velocity, normal); - VectorNormalize(normal); - VectorMA (self->s.origin, self->maxs[0], normal, point); - damage = 40 + 10 * random(); - T_Damage (other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_UNKNOWN); - } - } - - if (!M_CheckBottom (self)) - { - if (self->groundentity) - { - self->monsterinfo.nextframe = FRAME_attack02; - self->touch = NULL; - } - return; - } - - self->touch = NULL; -} - -void mutant_jump_takeoff (edict_t *self) -{ - vec3_t forward; - - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); - AngleVectors (self->s.angles, forward, NULL, NULL); - self->s.origin[2] += 1; - VectorScale (forward, 600, self->velocity); - self->velocity[2] = 250; - self->groundentity = NULL; - self->monsterinfo.aiflags |= AI_DUCKED; - self->monsterinfo.attack_finished = level.time + 3; - self->touch = mutant_jump_touch; -} - -void mutant_check_landing (edict_t *self) -{ - if (self->groundentity) - { - gi.sound (self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0); - self->monsterinfo.attack_finished = 0; - self->monsterinfo.aiflags &= ~AI_DUCKED; - return; - } - - if (level.time > self->monsterinfo.attack_finished) - self->monsterinfo.nextframe = FRAME_attack02; - else - self->monsterinfo.nextframe = FRAME_attack05; -} - -mframe_t mutant_frames_jump [] = -{ - ai_charge, 0, NULL, - ai_charge, 17, NULL, - ai_charge, 15, mutant_jump_takeoff, - ai_charge, 15, NULL, - ai_charge, 15, mutant_check_landing, - ai_charge, 0, NULL, - ai_charge, 3, NULL, - ai_charge, 0, NULL -}; -mmove_t mutant_move_jump = {FRAME_attack01, FRAME_attack08, mutant_frames_jump, mutant_run}; - -void mutant_jump (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_jump; -} - - -// -// CHECKATTACK -// - -bool mutant_check_melee (edict_t *self) -{ - if (range (self, self->enemy) == RANGE_MELEE) - return true; - return false; -} - -bool mutant_check_jump (edict_t *self) -{ - vec3_t v; - float distance; - vec_t speed=0; - - if (monsterjump->value) - { - if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2]) + - self->monsterinfo.jumpdn ) - return false; - - if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2]) - - self->monsterinfo.jumpup ) - return false; - if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2])) - speed = max(self->velocity[2],200); - } - else - { - if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2])) - return false; - - if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2])) - return false; - } - - v[0] = self->s.origin[0] - self->enemy->s.origin[0]; - v[1] = self->s.origin[1] - self->enemy->s.origin[1]; - v[2] = 0; - distance = VectorLength(v); - - if (distance < 100) - return false; - if (distance > 100) - { - if (random() < 0.9) - return false; - } - if(speed) - self->velocity[2] = speed; - return true; -} - -bool mutant_checkattack (edict_t *self) -{ - if (!self->enemy || self->enemy->health <= 0) - return false; - - if (mutant_check_melee(self)) - { - self->monsterinfo.attack_state = AS_MELEE; - return true; - } - - if (mutant_check_jump(self)) - { - self->monsterinfo.attack_state = AS_MISSILE; - // FIXME play a jump sound here - return true; - } - - return false; -} - - -// -// PAIN -// - -mframe_t mutant_frames_pain1 [] = -{ - ai_move, 4, NULL, - ai_move, -3, NULL, - ai_move, -8, NULL, - ai_move, 2, NULL, - ai_move, 5, NULL -}; -mmove_t mutant_move_pain1 = {FRAME_pain101, FRAME_pain105, mutant_frames_pain1, mutant_run}; - -mframe_t mutant_frames_pain2 [] = -{ - ai_move, -24,NULL, - ai_move, 11, NULL, - ai_move, 5, NULL, - ai_move, -2, NULL, - ai_move, 6, NULL, - ai_move, 4, NULL -}; -mmove_t mutant_move_pain2 = {FRAME_pain201, FRAME_pain206, mutant_frames_pain2, mutant_run}; - -mframe_t mutant_frames_pain3 [] = -{ - ai_move, -22,NULL, - ai_move, 3, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 6, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL -}; -mmove_t mutant_move_pain3 = {FRAME_pain301, FRAME_pain311, mutant_frames_pain3, mutant_run}; - -void mutant_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - float r; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - r = random(); - if (r < 0.33) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &mutant_move_pain1; - } - else if (r < 0.66) - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &mutant_move_pain2; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - self->monsterinfo.currentmove = &mutant_move_pain3; - } -} - - -// -// DEATH -// - -void mutant_dead (edict_t *self) -{ - // Lazarus: Stupid... if flies aren't set by M_FlyCheck, monster_think - // will cause us to come back here over and over and over - // until flies ARE set or monster is gibbed. - // This line fixes that: - self->nextthink = 0; - - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } - -} - -mframe_t mutant_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t mutant_move_death1 = {FRAME_death101, FRAME_death109, mutant_frames_death1, mutant_dead}; - -mframe_t mutant_frames_death2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t mutant_move_death2 = {FRAME_death201, FRAME_death210, mutant_frames_death2, mutant_dead}; - -void mutant_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->s.skin = 1; - - if (random() < 0.5) - self->monsterinfo.currentmove = &mutant_move_death1; - else - self->monsterinfo.currentmove = &mutant_move_death2; -} - -mframe_t mutant_frames_fake_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t mutant_move_fake_jump = {FRAME_run03, FRAME_run08, mutant_frames_fake_jump, mutant_run}; - -void mutant_fake_jump (edict_t *self) -{ - self->monsterinfo.currentmove = &mutant_move_fake_jump; -} - - -// -// SPAWN -// - -/*QUAKED monster_mutant (1 .5 0) (-32 -32 -24) (32 32 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_mutant (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_MUTANT; - self->spawnflags |= SF_MONSTER_KNOWS_MIRRORS; - - sound_swing = gi.soundindex ("mutant/mutatck1.wav"); - sound_hit = gi.soundindex ("mutant/mutatck2.wav"); - sound_hit2 = gi.soundindex ("mutant/mutatck3.wav"); - sound_death = gi.soundindex ("mutant/mutdeth1.wav"); - sound_idle = gi.soundindex ("mutant/mutidle1.wav"); - sound_pain1 = gi.soundindex ("mutant/mutpain1.wav"); - sound_pain2 = gi.soundindex ("mutant/mutpain2.wav"); - sound_sight = gi.soundindex ("mutant/mutsght1.wav"); - sound_search = gi.soundindex ("mutant/mutsrch1.wav"); - sound_step1 = gi.soundindex ("mutant/step1.wav"); - sound_step2 = gi.soundindex ("mutant/step2.wav"); - sound_step3 = gi.soundindex ("mutant/step3.wav"); - sound_thud = gi.soundindex ("mutant/thud1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/mutant/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/mutant/tris.md2"); - VectorSet (self->mins, -32, -32, -24); - VectorSet (self->maxs, 32, 32, 48); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 300; - if(!self->gib_health) - self->gib_health = -120; - if(!self->mass) - self->mass = 300; - - self->pain = mutant_pain; - self->die = mutant_die; - - self->monsterinfo.stand = mutant_stand; - self->monsterinfo.walk = mutant_walk; - self->monsterinfo.run = mutant_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = mutant_jump; - self->monsterinfo.melee = mutant_melee; - self->monsterinfo.sight = mutant_sight; - self->monsterinfo.search = mutant_search; - self->monsterinfo.idle = mutant_idle; - self->monsterinfo.checkattack = mutant_checkattack; - if(monsterjump->value) - { - self->monsterinfo.jump = mutant_fake_jump; - self->monsterinfo.jumpup = 96; - self->monsterinfo.jumpdn = 160; - } - - gi.linkentity (self); - self->monsterinfo.currentmove = &mutant_move_stand; - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.90; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&mutant_move_death1, - &mutant_move_death2, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Mutant"; - self->monsterinfo.scale = MODEL_SCALE; - walkmonster_start (self); -} diff --git a/server/monsters/m_mutant.h b/server/monsters/m_mutant.h deleted file mode 100644 index 7afd6930..00000000 --- a/server/monsters/m_mutant.h +++ /dev/null @@ -1,155 +0,0 @@ -// G:\quake2\baseq2\models/monsters/mutant - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_attack01 0 -#define FRAME_attack02 1 -#define FRAME_attack03 2 -#define FRAME_attack04 3 -#define FRAME_attack05 4 -#define FRAME_attack06 5 -#define FRAME_attack07 6 -#define FRAME_attack08 7 -#define FRAME_attack09 8 -#define FRAME_attack10 9 -#define FRAME_attack11 10 -#define FRAME_attack12 11 -#define FRAME_attack13 12 -#define FRAME_attack14 13 -#define FRAME_attack15 14 -#define FRAME_death101 15 -#define FRAME_death102 16 -#define FRAME_death103 17 -#define FRAME_death104 18 -#define FRAME_death105 19 -#define FRAME_death106 20 -#define FRAME_death107 21 -#define FRAME_death108 22 -#define FRAME_death109 23 -#define FRAME_death201 24 -#define FRAME_death202 25 -#define FRAME_death203 26 -#define FRAME_death204 27 -#define FRAME_death205 28 -#define FRAME_death206 29 -#define FRAME_death207 30 -#define FRAME_death208 31 -#define FRAME_death209 32 -#define FRAME_death210 33 -#define FRAME_pain101 34 -#define FRAME_pain102 35 -#define FRAME_pain103 36 -#define FRAME_pain104 37 -#define FRAME_pain105 38 -#define FRAME_pain201 39 -#define FRAME_pain202 40 -#define FRAME_pain203 41 -#define FRAME_pain204 42 -#define FRAME_pain205 43 -#define FRAME_pain206 44 -#define FRAME_pain301 45 -#define FRAME_pain302 46 -#define FRAME_pain303 47 -#define FRAME_pain304 48 -#define FRAME_pain305 49 -#define FRAME_pain306 50 -#define FRAME_pain307 51 -#define FRAME_pain308 52 -#define FRAME_pain309 53 -#define FRAME_pain310 54 -#define FRAME_pain311 55 -#define FRAME_run03 56 -#define FRAME_run04 57 -#define FRAME_run05 58 -#define FRAME_run06 59 -#define FRAME_run07 60 -#define FRAME_run08 61 -#define FRAME_stand101 62 -#define FRAME_stand102 63 -#define FRAME_stand103 64 -#define FRAME_stand104 65 -#define FRAME_stand105 66 -#define FRAME_stand106 67 -#define FRAME_stand107 68 -#define FRAME_stand108 69 -#define FRAME_stand109 70 -#define FRAME_stand110 71 -#define FRAME_stand111 72 -#define FRAME_stand112 73 -#define FRAME_stand113 74 -#define FRAME_stand114 75 -#define FRAME_stand115 76 -#define FRAME_stand116 77 -#define FRAME_stand117 78 -#define FRAME_stand118 79 -#define FRAME_stand119 80 -#define FRAME_stand120 81 -#define FRAME_stand121 82 -#define FRAME_stand122 83 -#define FRAME_stand123 84 -#define FRAME_stand124 85 -#define FRAME_stand125 86 -#define FRAME_stand126 87 -#define FRAME_stand127 88 -#define FRAME_stand128 89 -#define FRAME_stand129 90 -#define FRAME_stand130 91 -#define FRAME_stand131 92 -#define FRAME_stand132 93 -#define FRAME_stand133 94 -#define FRAME_stand134 95 -#define FRAME_stand135 96 -#define FRAME_stand136 97 -#define FRAME_stand137 98 -#define FRAME_stand138 99 -#define FRAME_stand139 100 -#define FRAME_stand140 101 -#define FRAME_stand141 102 -#define FRAME_stand142 103 -#define FRAME_stand143 104 -#define FRAME_stand144 105 -#define FRAME_stand145 106 -#define FRAME_stand146 107 -#define FRAME_stand147 108 -#define FRAME_stand148 109 -#define FRAME_stand149 110 -#define FRAME_stand150 111 -#define FRAME_stand151 112 -#define FRAME_stand152 113 -#define FRAME_stand153 114 -#define FRAME_stand154 115 -#define FRAME_stand155 116 -#define FRAME_stand156 117 -#define FRAME_stand157 118 -#define FRAME_stand158 119 -#define FRAME_stand159 120 -#define FRAME_stand160 121 -#define FRAME_stand161 122 -#define FRAME_stand162 123 -#define FRAME_stand163 124 -#define FRAME_stand164 125 -#define FRAME_walk01 126 -#define FRAME_walk02 127 -#define FRAME_walk03 128 -#define FRAME_walk04 129 -#define FRAME_walk05 130 -#define FRAME_walk06 131 -#define FRAME_walk07 132 -#define FRAME_walk08 133 -#define FRAME_walk09 134 -#define FRAME_walk10 135 -#define FRAME_walk11 136 -#define FRAME_walk12 137 -#define FRAME_walk13 138 -#define FRAME_walk14 139 -#define FRAME_walk15 140 -#define FRAME_walk16 141 -#define FRAME_walk17 142 -#define FRAME_walk18 143 -#define FRAME_walk19 144 -#define FRAME_walk20 145 -#define FRAME_walk21 146 -#define FRAME_walk22 147 -#define FRAME_walk23 148 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_parasite.c b/server/monsters/m_parasite.c deleted file mode 100644 index d44e2253..00000000 --- a/server/monsters/m_parasite.c +++ /dev/null @@ -1,600 +0,0 @@ -/* -============================================================================== - -parasite - -============================================================================== -*/ - -#include "g_local.h" -#include "m_parasite.h" - - -static int sound_pain1; -static int sound_pain2; -static int sound_die; -static int sound_launch; -static int sound_impact; -static int sound_suck; -static int sound_reelin; -static int sound_sight; -static int sound_tap; -static int sound_scratch; -static int sound_search; - - -void parasite_stand (edict_t *self); -void parasite_start_run (edict_t *self); -void parasite_run (edict_t *self); -void parasite_walk (edict_t *self); -void parasite_start_walk (edict_t *self); -void parasite_end_fidget (edict_t *self); -void parasite_do_fidget (edict_t *self); -void parasite_refidget (edict_t *self); - - -void parasite_launch (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_launch, 1, ATTN_NORM, 0); -} - -void parasite_reel_in (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_reelin, 1, ATTN_NORM, 0); -} - -void parasite_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0); -} - -void parasite_tap (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_tap, 1, ATTN_IDLE, 0); -} - -void parasite_scratch (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_scratch, 1, ATTN_IDLE, 0); -} - -void parasite_search (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_search, 1, ATTN_IDLE, 0); -} - - -mframe_t parasite_frames_start_fidget [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t parasite_move_start_fidget = {FRAME_stand18, FRAME_stand21, parasite_frames_start_fidget, parasite_do_fidget}; - -mframe_t parasite_frames_fidget [] = -{ - ai_stand, 0, parasite_scratch, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, parasite_scratch, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t parasite_move_fidget = {FRAME_stand22, FRAME_stand27, parasite_frames_fidget, parasite_refidget}; - -mframe_t parasite_frames_end_fidget [] = -{ - ai_stand, 0, parasite_scratch, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t parasite_move_end_fidget = {FRAME_stand28, FRAME_stand35, parasite_frames_end_fidget, parasite_stand}; - -void parasite_end_fidget (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_end_fidget; -} - -void parasite_do_fidget (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_fidget; -} - -void parasite_refidget (edict_t *self) -{ - if (random() <= 0.8) - self->monsterinfo.currentmove = ¶site_move_fidget; - else - self->monsterinfo.currentmove = ¶site_move_end_fidget; -} - -void parasite_idle (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_start_fidget; -} - - -mframe_t parasite_frames_stand [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, parasite_tap, - ai_stand, 0, NULL, - ai_stand, 0, parasite_tap, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, parasite_tap, - ai_stand, 0, NULL, - ai_stand, 0, parasite_tap, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, parasite_tap, - ai_stand, 0, NULL, - ai_stand, 0, parasite_tap -}; -mmove_t parasite_move_stand = {FRAME_stand01, FRAME_stand17, parasite_frames_stand, parasite_stand}; - -void parasite_stand (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_stand; -} - - -mframe_t parasite_frames_run [] = -{ - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 22, NULL, - ai_run, 19, NULL, - ai_run, 24, NULL, - ai_run, 28, NULL, - ai_run, 25, NULL -}; -mmove_t parasite_move_run = {FRAME_run03, FRAME_run09, parasite_frames_run, NULL}; - -mframe_t parasite_frames_start_run [] = -{ - ai_run, 0, NULL, - ai_run, 30, NULL, -}; -mmove_t parasite_move_start_run = {FRAME_run01, FRAME_run02, parasite_frames_start_run, parasite_run}; - -mframe_t parasite_frames_stop_run [] = -{ - ai_run, 20, NULL, - ai_run, 20, NULL, - ai_run, 12, NULL, - ai_run, 10, NULL, - ai_run, 0, NULL, - ai_run, 0, NULL -}; -mmove_t parasite_move_stop_run = {FRAME_run10, FRAME_run15, parasite_frames_stop_run, NULL}; - -void parasite_start_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = ¶site_move_stand; - else - self->monsterinfo.currentmove = ¶site_move_start_run; -} - -void parasite_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = ¶site_move_stand; - else - self->monsterinfo.currentmove = ¶site_move_run; -} - - -mframe_t parasite_frames_walk [] = -{ - ai_walk, 30, NULL, - ai_walk, 30, NULL, - ai_walk, 22, NULL, - ai_walk, 19, NULL, - ai_walk, 24, NULL, - ai_walk, 28, NULL, - ai_walk, 25, NULL -}; -mmove_t parasite_move_walk = {FRAME_run03, FRAME_run09, parasite_frames_walk, parasite_walk}; - -mframe_t parasite_frames_start_walk [] = -{ - ai_walk, 0, NULL, - ai_walk, 30, parasite_walk -}; -mmove_t parasite_move_start_walk = {FRAME_run01, FRAME_run02, parasite_frames_start_walk, NULL}; - -mframe_t parasite_frames_stop_walk [] = -{ - ai_walk, 20, NULL, - ai_walk, 20, NULL, - ai_walk, 12, NULL, - ai_walk, 10, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL -}; -mmove_t parasite_move_stop_walk = {FRAME_run10, FRAME_run15, parasite_frames_stop_walk, NULL}; - -void parasite_start_walk (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_start_walk; -} - -void parasite_walk (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_walk; -} - - -mframe_t parasite_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 6, NULL, - ai_move, 16, NULL, - ai_move, -6, NULL, - ai_move, -7, NULL, - ai_move, 0, NULL -}; -mmove_t parasite_move_pain1 = {FRAME_pain101, FRAME_pain111, parasite_frames_pain1, parasite_start_run}; - -void parasite_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); - - self->monsterinfo.currentmove = ¶site_move_pain1; -} - - -//static bool parasite_drain_attack_ok (vec3_t start, vec3_t end) -bool parasite_drain_attack_ok (vec3_t start, vec3_t end) -{ - vec3_t dir, angles; - - // check for max distance - VectorSubtract (start, end, dir); - if (VectorLength(dir) > 256) - return false; - - // check for min/max pitch - vectoangles (dir, angles); - if (angles[0] < -180) - angles[0] += 360; - if (fabs(angles[0]) > 30) - return false; - - return true; -} - -void parasite_drain_attack (edict_t *self) -{ - vec3_t offset, start, f, r, end, dir; - trace_t tr; - int damage; - - AngleVectors (self->s.angles, f, r, NULL); - VectorSet (offset, 24, 0, 6); - G_ProjectSource (self->s.origin, offset, f, r, start); - - VectorCopy (self->enemy->s.origin, end); - if (!parasite_drain_attack_ok(start, end)) - { - end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; - if (!parasite_drain_attack_ok(start, end)) - { - end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; - if (!parasite_drain_attack_ok(start, end)) - return; - } - } - VectorCopy (self->enemy->s.origin, end); - - // Lazarus: Original code can foul up if parasite is near and facing a solid. - // "start" may be embedded in the solid, since it is outside the parasite's - // bbox. In this case cable will appear to go through a solid. -// tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); - VectorCopy (self->s.origin,offset); - offset[2] += 6; - tr = gi.trace (offset, NULL, NULL, end, self, MASK_SHOT); - // end Lazarus fix - - if (tr.ent != self->enemy) - return; - - if (self->s.frame == FRAME_drain03) - { - damage = 5; - gi.sound (self->enemy, CHAN_AUTO, sound_impact, 1, ATTN_NORM, 0); - } - else - { - if (self->s.frame == FRAME_drain04) - gi.sound (self, CHAN_WEAPON, sound_suck, 1, ATTN_NORM, 0); - damage = 2; - } - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_PARASITE_ATTACK); - WRITE_SHORT (self - g_edicts); - WRITE_COORD (start); - WRITE_COORD (end); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - - VectorSubtract (start, end, dir); - T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); -} - -mframe_t parasite_frames_drain [] = -{ - ai_charge, 0, parasite_launch, - ai_charge, 0, NULL, - ai_charge, 15, parasite_drain_attack, // Target hits - ai_charge, 0, parasite_drain_attack, // drain - ai_charge, 0, parasite_drain_attack, // drain - ai_charge, 0, parasite_drain_attack, // drain - ai_charge, 0, parasite_drain_attack, // drain - ai_charge, -2, parasite_drain_attack, // drain - ai_charge, -2, parasite_drain_attack, // drain - ai_charge, -3, parasite_drain_attack, // drain - ai_charge, -2, parasite_drain_attack, // drain - ai_charge, 0, parasite_drain_attack, // drain - ai_charge, -1, parasite_drain_attack, // drain - ai_charge, 0, parasite_reel_in, // let go - ai_charge, -2, NULL, - ai_charge, -2, NULL, - ai_charge, -3, NULL, - ai_charge, 0, NULL -}; -mmove_t parasite_move_drain = {FRAME_drain01, FRAME_drain18, parasite_frames_drain, parasite_start_run}; - - -mframe_t parasite_frames_break [] = -{ - ai_charge, 0, NULL, - ai_charge, -3, NULL, - ai_charge, 1, NULL, - ai_charge, 2, NULL, - ai_charge, -3, NULL, - ai_charge, 1, NULL, - ai_charge, 1, NULL, - ai_charge, 3, NULL, - ai_charge, 0, NULL, - ai_charge, -18, NULL, - ai_charge, 3, NULL, - ai_charge, 9, NULL, - ai_charge, 6, NULL, - ai_charge, 0, NULL, - ai_charge, -18, NULL, - ai_charge, 0, NULL, - ai_charge, 8, NULL, - ai_charge, 9, NULL, - ai_charge, 0, NULL, - ai_charge, -18, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // airborne - ai_charge, 0, NULL, // airborne - ai_charge, 0, NULL, // slides - ai_charge, 0, NULL, // slides - ai_charge, 0, NULL, // slides - ai_charge, 0, NULL, // slides - ai_charge, 4, NULL, - ai_charge, 11, NULL, - ai_charge, -2, NULL, - ai_charge, -5, NULL, - ai_charge, 1, NULL -}; -mmove_t parasite_move_break = {FRAME_break01, FRAME_break32, parasite_frames_break, parasite_start_run}; - -/* -=== -Break Stuff Ends -=== -*/ - -void parasite_attack (edict_t *self) -{ -// if (random() <= 0.2) -// self->monsterinfo.currentmove = ¶site_move_break; -// else - self->monsterinfo.currentmove = ¶site_move_drain; -} - - - -/* -=== -Death Stuff Starts -=== -*/ - -void parasite_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t parasite_frames_death [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t parasite_move_death = {FRAME_death101, FRAME_death107, parasite_frames_death, parasite_dead}; - -void parasite_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 2; n++) - ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->monsterinfo.currentmove = ¶site_move_death; -} - -/* -=== -End Death Stuff -=== -*/ -mframe_t parasite_frames_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t parasite_move_jump = { FRAME_run01, FRAME_run08, parasite_frames_jump, parasite_run }; - -void parasite_jump (edict_t *self) -{ - self->monsterinfo.currentmove = ¶site_move_jump; -} - -/*QUAKED monster_parasite (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_parasite (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_PARASITE; - - sound_pain1 = gi.soundindex ("parasite/parpain1.wav"); - sound_pain2 = gi.soundindex ("parasite/parpain2.wav"); - sound_die = gi.soundindex ("parasite/pardeth1.wav"); - sound_launch = gi.soundindex("parasite/paratck1.wav"); - sound_impact = gi.soundindex("parasite/paratck2.wav"); - sound_suck = gi.soundindex("parasite/paratck3.wav"); - sound_reelin = gi.soundindex("parasite/paratck4.wav"); - sound_sight = gi.soundindex("parasite/parsght1.wav"); - sound_tap = gi.soundindex("parasite/paridle1.wav"); - sound_scratch = gi.soundindex("parasite/paridle2.wav"); - sound_search = gi.soundindex("parasite/parsrch1.wav"); - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/parasite/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/parasite/tris.md2"); - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 24); - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 175; - if(!self->gib_health) - self->gib_health = -50; - if(!self->mass) - self->mass = 250; - - self->pain = parasite_pain; - self->die = parasite_die; - - self->monsterinfo.stand = parasite_stand; - self->monsterinfo.walk = parasite_start_walk; - self->monsterinfo.run = parasite_start_run; - self->monsterinfo.attack = parasite_attack; - self->monsterinfo.sight = parasite_sight; - self->monsterinfo.idle = parasite_idle; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.35; - if(monsterjump->value) - { - self->monsterinfo.jump = parasite_jump; - self->monsterinfo.jumpup = 32; - self->monsterinfo.jumpdn = 160; - } - - - gi.linkentity (self); - self->monsterinfo.currentmove = ¶site_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {¶site_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Parasite"; - self->monsterinfo.scale = MODEL_SCALE; - walkmonster_start (self); -} diff --git a/server/monsters/m_parasite.h b/server/monsters/m_parasite.h deleted file mode 100644 index d895ce1d..00000000 --- a/server/monsters/m_parasite.h +++ /dev/null @@ -1,124 +0,0 @@ -// G:\quake2\baseq2\models/monsters/parasite - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_break01 0 -#define FRAME_break02 1 -#define FRAME_break03 2 -#define FRAME_break04 3 -#define FRAME_break05 4 -#define FRAME_break06 5 -#define FRAME_break07 6 -#define FRAME_break08 7 -#define FRAME_break09 8 -#define FRAME_break10 9 -#define FRAME_break11 10 -#define FRAME_break12 11 -#define FRAME_break13 12 -#define FRAME_break14 13 -#define FRAME_break15 14 -#define FRAME_break16 15 -#define FRAME_break17 16 -#define FRAME_break18 17 -#define FRAME_break19 18 -#define FRAME_break20 19 -#define FRAME_break21 20 -#define FRAME_break22 21 -#define FRAME_break23 22 -#define FRAME_break24 23 -#define FRAME_break25 24 -#define FRAME_break26 25 -#define FRAME_break27 26 -#define FRAME_break28 27 -#define FRAME_break29 28 -#define FRAME_break30 29 -#define FRAME_break31 30 -#define FRAME_break32 31 -#define FRAME_death101 32 -#define FRAME_death102 33 -#define FRAME_death103 34 -#define FRAME_death104 35 -#define FRAME_death105 36 -#define FRAME_death106 37 -#define FRAME_death107 38 -#define FRAME_drain01 39 -#define FRAME_drain02 40 -#define FRAME_drain03 41 -#define FRAME_drain04 42 -#define FRAME_drain05 43 -#define FRAME_drain06 44 -#define FRAME_drain07 45 -#define FRAME_drain08 46 -#define FRAME_drain09 47 -#define FRAME_drain10 48 -#define FRAME_drain11 49 -#define FRAME_drain12 50 -#define FRAME_drain13 51 -#define FRAME_drain14 52 -#define FRAME_drain15 53 -#define FRAME_drain16 54 -#define FRAME_drain17 55 -#define FRAME_drain18 56 -#define FRAME_pain101 57 -#define FRAME_pain102 58 -#define FRAME_pain103 59 -#define FRAME_pain104 60 -#define FRAME_pain105 61 -#define FRAME_pain106 62 -#define FRAME_pain107 63 -#define FRAME_pain108 64 -#define FRAME_pain109 65 -#define FRAME_pain110 66 -#define FRAME_pain111 67 -#define FRAME_run01 68 -#define FRAME_run02 69 -#define FRAME_run03 70 -#define FRAME_run04 71 -#define FRAME_run05 72 -#define FRAME_run06 73 -#define FRAME_run07 74 -#define FRAME_run08 75 -#define FRAME_run09 76 -#define FRAME_run10 77 -#define FRAME_run11 78 -#define FRAME_run12 79 -#define FRAME_run13 80 -#define FRAME_run14 81 -#define FRAME_run15 82 -#define FRAME_stand01 83 -#define FRAME_stand02 84 -#define FRAME_stand03 85 -#define FRAME_stand04 86 -#define FRAME_stand05 87 -#define FRAME_stand06 88 -#define FRAME_stand07 89 -#define FRAME_stand08 90 -#define FRAME_stand09 91 -#define FRAME_stand10 92 -#define FRAME_stand11 93 -#define FRAME_stand12 94 -#define FRAME_stand13 95 -#define FRAME_stand14 96 -#define FRAME_stand15 97 -#define FRAME_stand16 98 -#define FRAME_stand17 99 -#define FRAME_stand18 100 -#define FRAME_stand19 101 -#define FRAME_stand20 102 -#define FRAME_stand21 103 -#define FRAME_stand22 104 -#define FRAME_stand23 105 -#define FRAME_stand24 106 -#define FRAME_stand25 107 -#define FRAME_stand26 108 -#define FRAME_stand27 109 -#define FRAME_stand28 110 -#define FRAME_stand29 111 -#define FRAME_stand30 112 -#define FRAME_stand31 113 -#define FRAME_stand32 114 -#define FRAME_stand33 115 -#define FRAME_stand34 116 -#define FRAME_stand35 117 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_rider.h b/server/monsters/m_rider.h deleted file mode 100644 index f47af79c..00000000 --- a/server/monsters/m_rider.h +++ /dev/null @@ -1,66 +0,0 @@ -// G:\quake2\baseq2\models/monsters/boss3/rider - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_stand201 0 -#define FRAME_stand202 1 -#define FRAME_stand203 2 -#define FRAME_stand204 3 -#define FRAME_stand205 4 -#define FRAME_stand206 5 -#define FRAME_stand207 6 -#define FRAME_stand208 7 -#define FRAME_stand209 8 -#define FRAME_stand210 9 -#define FRAME_stand211 10 -#define FRAME_stand212 11 -#define FRAME_stand213 12 -#define FRAME_stand214 13 -#define FRAME_stand215 14 -#define FRAME_stand216 15 -#define FRAME_stand217 16 -#define FRAME_stand218 17 -#define FRAME_stand219 18 -#define FRAME_stand220 19 -#define FRAME_stand221 20 -#define FRAME_stand222 21 -#define FRAME_stand223 22 -#define FRAME_stand224 23 -#define FRAME_stand225 24 -#define FRAME_stand226 25 -#define FRAME_stand227 26 -#define FRAME_stand228 27 -#define FRAME_stand229 28 -#define FRAME_stand230 29 -#define FRAME_stand231 30 -#define FRAME_stand232 31 -#define FRAME_stand233 32 -#define FRAME_stand234 33 -#define FRAME_stand235 34 -#define FRAME_stand236 35 -#define FRAME_stand237 36 -#define FRAME_stand238 37 -#define FRAME_stand239 38 -#define FRAME_stand240 39 -#define FRAME_stand241 40 -#define FRAME_stand242 41 -#define FRAME_stand243 42 -#define FRAME_stand244 43 -#define FRAME_stand245 44 -#define FRAME_stand246 45 -#define FRAME_stand247 46 -#define FRAME_stand248 47 -#define FRAME_stand249 48 -#define FRAME_stand250 49 -#define FRAME_stand251 50 -#define FRAME_stand252 51 -#define FRAME_stand253 52 -#define FRAME_stand254 53 -#define FRAME_stand255 54 -#define FRAME_stand256 55 -#define FRAME_stand257 56 -#define FRAME_stand258 57 -#define FRAME_stand259 58 -#define FRAME_stand260 59 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_soldier.c b/server/monsters/m_soldier.c deleted file mode 100644 index f81f1287..00000000 --- a/server/monsters/m_soldier.c +++ /dev/null @@ -1,1374 +0,0 @@ -/*============================================================================== - -SOLDIER - -============================================================================== -*/ - -#include "g_local.h" -#include "m_soldier.h" - - -static int sound_idle; -static int sound_sight1; -static int sound_sight2; -static int sound_pain_light; -static int sound_pain; -static int sound_pain_ss; -static int sound_death_light; -static int sound_death; -static int sound_death_ss; -static int sound_cock; - - -void soldier_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - { - if (random() > 0.8) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); - } -} - -void soldier_cock (edict_t *self) -{ - if (self->s.frame == FRAME_stand322) - gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0); - else - gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0); -} - - -// STAND - -void soldier_stand (edict_t *self); - -mframe_t soldier_frames_stand1 [] = -{ - ai_stand, 0, soldier_idle, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand}; - -mframe_t soldier_frames_stand3 [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, soldier_cock, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand}; - -#if 0 -mframe_t soldier_frames_stand4 [] = -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 4, NULL, - ai_stand, 1, NULL, - ai_stand, -1, NULL, - ai_stand, -2, NULL, - - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL}; -#endif - -void soldier_stand (edict_t *self) -{ - if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8)) - self->monsterinfo.currentmove = &soldier_move_stand1; - else - self->monsterinfo.currentmove = &soldier_move_stand3; -} - - -// -// WALK -// - -void soldier_walk1_random (edict_t *self) -{ - if (random() > 0.1) - self->monsterinfo.nextframe = FRAME_walk101; -} - -mframe_t soldier_frames_walk1 [] = -{ - ai_walk, 3, NULL, - ai_walk, 6, NULL, - ai_walk, 2, NULL, - ai_walk, 2, NULL, - ai_walk, 2, NULL, - ai_walk, 1, NULL, - ai_walk, 6, NULL, - ai_walk, 5, NULL, - ai_walk, 3, NULL, - ai_walk, -1, soldier_walk1_random, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL -}; -mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL}; - -mframe_t soldier_frames_walk2 [] = -{ - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 9, NULL, - ai_walk, 8, NULL, - ai_walk, 5, NULL, - ai_walk, 1, NULL, - ai_walk, 3, NULL, - ai_walk, 7, NULL, - ai_walk, 6, NULL, - ai_walk, 7, NULL -}; -mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL}; - -void soldier_walk (edict_t *self) -{ - if (random() < 0.5) - self->monsterinfo.currentmove = &soldier_move_walk1; - else - self->monsterinfo.currentmove = &soldier_move_walk2; -} - - -// -// RUN -// - -void soldier_run (edict_t *self); - -mframe_t soldier_frames_start_run [] = -{ - ai_run, 7, NULL, - ai_run, 5, NULL -}; -mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run}; - -mframe_t soldier_frames_run [] = -{ - ai_run, 10, NULL, - ai_run, 11, NULL, - ai_run, 11, NULL, - ai_run, 16, NULL, - ai_run, 10, NULL, - ai_run, 15, NULL -}; -mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL}; - -void soldier_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - self->monsterinfo.currentmove = &soldier_move_stand1; - return; - } - - if (self->monsterinfo.currentmove == &soldier_move_walk1 || - self->monsterinfo.currentmove == &soldier_move_walk2 || - self->monsterinfo.currentmove == &soldier_move_start_run) - { - self->monsterinfo.currentmove = &soldier_move_run; - } - else - { - self->monsterinfo.currentmove = &soldier_move_start_run; - } -} - - -// -// PAIN -// - -mframe_t soldier_frames_pain1 [] = -{ - ai_move, -3, NULL, - ai_move, 4, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run}; - -mframe_t soldier_frames_pain2 [] = -{ - ai_move, -13, NULL, - ai_move, -1, NULL, - ai_move, 2, NULL, - ai_move, 4, NULL, - ai_move, 2, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL -}; -mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run}; - -mframe_t soldier_frames_pain3 [] = -{ - ai_move, -8, NULL, - ai_move, 10, NULL, - ai_move, -4, NULL, - ai_move, -1, NULL, - ai_move, -3, NULL, - ai_move, 0, NULL, - ai_move, 3, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 1, NULL, - ai_move, 2, NULL, - ai_move, 4, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL -}; -mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run}; - -mframe_t soldier_frames_pain4 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -10, NULL, - ai_move, -6, NULL, - ai_move, 8, NULL, - ai_move, 4, NULL, - ai_move, 1, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 5, NULL, - ai_move, 2, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run}; - - -void soldier_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - float r; - int n; - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - { - if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3))) - self->monsterinfo.currentmove = &soldier_move_pain4; - return; - } - - self->pain_debounce_time = level.time + 3; - - n = self->s.skin | 1; - if (n == 1) - gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0); - else if (n == 3) - gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0); - - if (self->velocity[2] > 100) - { - self->monsterinfo.currentmove = &soldier_move_pain4; - return; - } - - if (skill->value == 3) - return; // no pain anims in nightmare - - r = random(); - - if (r < 0.33) - self->monsterinfo.currentmove = &soldier_move_pain1; - else if (r < 0.66) - self->monsterinfo.currentmove = &soldier_move_pain2; - else - self->monsterinfo.currentmove = &soldier_move_pain3; -} - - -// -// ATTACK -// - -static int blaster_flash [] = {MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8}; -static int shotgun_flash [] = {MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8}; -static int machinegun_flash [] = {MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8}; - -void soldier_fire (edict_t *self, int flash_number) -{ - vec3_t start; - vec3_t forward, right, up; - vec3_t aim; - vec3_t dir; - vec3_t end; - float r, u; - int flash_index; - - if (self->s.skin < 2) - flash_index = blaster_flash[flash_number]; - else if (self->s.skin < 4) - flash_index = shotgun_flash[flash_number]; - else - flash_index = machinegun_flash[flash_number]; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start); - - if (flash_number == 5 || flash_number == 6) - { - VectorCopy (forward, aim); - } - else - { - VectorCopy (self->enemy->s.origin, end); - end[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (end, start, aim); - // Lazarus: Accuracy is skill level dependent - if(skill->value < 3) - { - vectoangles (aim, dir); - AngleVectors (dir, forward, right, up); - - r = crandom()*(1000 - 333*skill->value); - u = crandom()*(500 - 167*skill->value); - VectorMA (start, 8192, forward, end); - VectorMA (end, r, right, end); - VectorMA (end, u, up, end); - - VectorSubtract (end, start, aim); - } - VectorNormalize (aim); - } - - if (self->s.skin <= 1) - { - // Lazarus: make bolt speed skill level dependent - monster_fire_blaster (self, start, aim, 5, 600 + 100*skill->value, flash_index, EF_BLASTER); - } - else if (self->s.skin <= 3) - { - monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index); - } - else - { - if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) - self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME; - - monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index); - - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; - } -} - -// ATTACK1 (blaster/shotgun) - -void soldier_fire1 (edict_t *self) -{ - soldier_fire (self, 0); -} - -void soldier_attack1_refire1 (edict_t *self) -{ - if (self->s.skin > 1) - return; - - if (self->enemy->health <= 0) - return; - - if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) - self->monsterinfo.nextframe = FRAME_attak102; - else - self->monsterinfo.nextframe = FRAME_attak110; -} - -void soldier_attack1_refire2 (edict_t *self) -{ - if (self->s.skin < 2) - return; - - if (self->enemy->health <= 0) - return; - - if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) - self->monsterinfo.nextframe = FRAME_attak102; -} - -mframe_t soldier_frames_attack1 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_fire1, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_attack1_refire1, - ai_charge, 0, NULL, - ai_charge, 0, soldier_cock, - ai_charge, 0, soldier_attack1_refire2, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run}; - -// ATTACK2 (blaster/shotgun) - -void soldier_fire2 (edict_t *self) -{ - soldier_fire (self, 1); -} - -void soldier_attack2_refire1 (edict_t *self) -{ - if (self->s.skin > 1) - return; - - if (self->enemy->health <= 0) - return; - - if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) - self->monsterinfo.nextframe = FRAME_attak204; - else - self->monsterinfo.nextframe = FRAME_attak216; -} - -void soldier_attack2_refire2 (edict_t *self) -{ - if (self->s.skin < 2) - return; - - if (self->enemy->health <= 0) - return; - - if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) - self->monsterinfo.nextframe = FRAME_attak204; -} - -mframe_t soldier_frames_attack2 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_fire2, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_attack2_refire1, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_cock, - ai_charge, 0, NULL, - ai_charge, 0, soldier_attack2_refire2, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run}; - -// ATTACK3 (duck and shoot) - -void soldier_duck_down (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_DUCKED) - return; - self->monsterinfo.aiflags |= AI_DUCKED; - self->maxs[2] -= 32; - self->takedamage = DAMAGE_YES; - self->monsterinfo.pausetime = level.time + 1; - gi.linkentity (self); -} - -void soldier_duck_up (edict_t *self) -{ - self->monsterinfo.aiflags &= ~AI_DUCKED; - self->maxs[2] += 32; - self->takedamage = DAMAGE_AIM; - gi.linkentity (self); -} - -void soldier_fire3 (edict_t *self) -{ - soldier_duck_down (self); - soldier_fire (self, 2); -} - -void soldier_attack3_refire (edict_t *self) -{ - if ((level.time + 0.4) < self->monsterinfo.pausetime) - self->monsterinfo.nextframe = FRAME_attak303; -} - -mframe_t soldier_frames_attack3 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_fire3, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_attack3_refire, - ai_charge, 0, soldier_duck_up, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run}; - -// ATTACK4 (machinegun) - -void soldier_fire4 (edict_t *self) -{ - soldier_fire (self, 3); -// -// if (self->enemy->health <= 0) -// return; -// -// if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) -// self->monsterinfo.nextframe = FRAME_attak402; -} - -mframe_t soldier_frames_attack4 [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_fire4, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run}; - -#if 0 -// ATTACK5 (prone) - -void soldier_fire5 (edict_t *self) -{ - soldier_fire (self, 4); -} - -void soldier_attack5_refire (edict_t *self) -{ - if (self->enemy->health <= 0) - return; - - if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) - self->monsterinfo.nextframe = FRAME_attak505; -} - -mframe_t soldier_frames_attack5 [] = -{ - ai_charge, 8, NULL, - ai_charge, 8, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_fire5, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, soldier_attack5_refire -}; -mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run}; -#endif - -// ATTACK6 (run & shoot) - -void soldier_fire8 (edict_t *self) -{ - soldier_fire (self, 7); -} - -void soldier_attack6_refire (edict_t *self) -{ - if (self->enemy->health <= 0) - return; - - if (range(self, self->enemy) < RANGE_MID) - return; - - if (skill->value == 3) - self->monsterinfo.nextframe = FRAME_runs03; -} - -mframe_t soldier_frames_attack6 [] = -{ - ai_charge, 10, NULL, - ai_charge, 4, NULL, - ai_charge, 12, NULL, - ai_charge, 11, soldier_fire8, - ai_charge, 13, NULL, - ai_charge, 18, NULL, - ai_charge, 15, NULL, - ai_charge, 14, NULL, - ai_charge, 11, NULL, - ai_charge, 8, NULL, - ai_charge, 11, NULL, - ai_charge, 12, NULL, - ai_charge, 12, NULL, - ai_charge, 17, soldier_attack6_refire -}; -mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run}; - -void soldier_attack(edict_t *self) -{ - if (self->s.skin < 4) - { - if (random() < 0.5) - self->monsterinfo.currentmove = &soldier_move_attack1; - else - self->monsterinfo.currentmove = &soldier_move_attack2; - } - else - { - self->monsterinfo.currentmove = &soldier_move_attack4; - } -} - - -// -// SIGHT -// - -void soldier_sight(edict_t *self, edict_t *other) -{ - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0); - - if ((skill->value > 0) && (range(self, self->enemy) >= RANGE_MID)) - { - if (random() > 0.5) - self->monsterinfo.currentmove = &soldier_move_attack6; - } -} - -// -// DUCK -// - -void soldier_duck_hold (edict_t *self) -{ - if (level.time >= self->monsterinfo.pausetime) - self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - else - self->monsterinfo.aiflags |= AI_HOLD_FRAME; -} - -mframe_t soldier_frames_duck [] = -{ - ai_move, 5, soldier_duck_down, - ai_move, -1, soldier_duck_hold, - ai_move, 1, NULL, - ai_move, 0, soldier_duck_up, - ai_move, 5, NULL -}; -mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run}; - -void soldier_dodge (edict_t *self, edict_t *attacker, float eta) -{ - float r; - - r = random(); - if (r > 0.25) - return; - - if (!self->enemy) - self->enemy = attacker; - - if (skill->value == 0) - { - self->monsterinfo.currentmove = &soldier_move_duck; - return; - } - - self->monsterinfo.pausetime = level.time + eta + 0.3; - r = random(); - - if (skill->value == 1) - { - if (r > 0.33) - self->monsterinfo.currentmove = &soldier_move_duck; - else - self->monsterinfo.currentmove = &soldier_move_attack3; - return; - } - - if (skill->value >= 2) - { - if (r > 0.66) - self->monsterinfo.currentmove = &soldier_move_duck; - else - self->monsterinfo.currentmove = &soldier_move_attack3; - return; - } - - self->monsterinfo.currentmove = &soldier_move_attack3; -} - -// -// DEATH -// - -void soldier_fire6 (edict_t *self) -{ - soldier_fire (self, 5); -} - -void soldier_fire7 (edict_t *self) -{ - soldier_fire (self, 6); -} - -void soldier_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, -8); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t soldier_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, -10, NULL, - ai_move, -10, NULL, - ai_move, -10, NULL, - ai_move, -5, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, soldier_fire6, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, soldier_fire7, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead}; - -mframe_t soldier_frames_death2 [] = -{ - ai_move, -5, NULL, - ai_move, -5, NULL, - ai_move, -5, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead}; - -mframe_t soldier_frames_death3 [] = -{ - ai_move, -5, NULL, - ai_move, -5, NULL, - ai_move, -5, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, -}; -mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead}; - -mframe_t soldier_frames_death4 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead}; - -mframe_t soldier_frames_death5 [] = -{ - ai_move, -5, NULL, - ai_move, -5, NULL, - ai_move, -5, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead}; - -mframe_t soldier_frames_death6 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead}; - -void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB) ) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 3; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - self->s.skin |= 1; - - if (self->s.skin == 1) - gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0); - else if (self->s.skin == 3) - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - else // (self->s.skin == 5) - gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0); - - if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4) - { - // head shot - self->monsterinfo.currentmove = &soldier_move_death3; - return; - } - - n = rand() % 5; - if (n == 0) - self->monsterinfo.currentmove = &soldier_move_death1; - else if (n == 1) - self->monsterinfo.currentmove = &soldier_move_death2; - else if (n == 2) - self->monsterinfo.currentmove = &soldier_move_death4; - else if (n == 3) - self->monsterinfo.currentmove = &soldier_move_death5; - else - self->monsterinfo.currentmove = &soldier_move_death6; -} - - -mframe_t soldier_frames_jump [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t soldier_move_jump = { FRAME_run01, FRAME_run08, soldier_frames_jump, soldier_run }; - -void soldier_jump (edict_t *self) -{ - self->monsterinfo.currentmove = &soldier_move_jump; -} - -// -// SPAWN -// - -void SP_monster_soldier_x (edict_t *self) -{ - - // Lazarus: special purpose skins - if ( self->style ) - PatchMonsterModel("models/monsters/soldier/tris.md2"); - - self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2"); - self->monsterinfo.scale = MODEL_SCALE; - VectorSet (self->mins, -16, -16, -24); - VectorSet (self->maxs, 16, 16, 32); - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - sound_idle = gi.soundindex ("soldier/solidle1.wav"); - sound_sight1 = gi.soundindex ("soldier/solsght1.wav"); - sound_sight2 = gi.soundindex ("soldier/solsrch1.wav"); - sound_cock = gi.soundindex ("infantry/infatck3.wav"); - - if(!self->mass) - self->mass = 100; - - self->pain = soldier_pain; - self->die = soldier_die; - - self->monsterinfo.stand = soldier_stand; - self->monsterinfo.walk = soldier_walk; - self->monsterinfo.run = soldier_run; - self->monsterinfo.dodge = soldier_dodge; - self->monsterinfo.attack = soldier_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = soldier_sight; - if(monsterjump->value) - { - self->monsterinfo.jump = soldier_jump; - self->monsterinfo.jumpup = 48; - self->monsterinfo.jumpdn = 160; - } - - // DWH - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - // end DWH - - gi.linkentity (self); - - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.40; - - if(self->health < 0) - { - mmove_t *deathmoves[] = {&soldier_move_death1, - &soldier_move_death2, - &soldier_move_death3, - &soldier_move_death4, - &soldier_move_death5, - &soldier_move_death6, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - walkmonster_start (self); -} - - -/*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_soldier_light (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_SOLDIER_LIGHT; - - sound_pain_light = gi.soundindex ("soldier/solpain2.wav"); - sound_death_light = gi.soundindex ("soldier/soldeth2.wav"); - gi.modelindex ("models/objects/laser/tris.md2"); - gi.soundindex ("misc/lasfly.wav"); - gi.soundindex ("soldier/solatck2.wav"); - self->common_name = "Light Guard"; - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 20; - if(!self->gib_health) - self->gib_health = -30; - - // Lazarus: custom skins - self->s.skin = 0 + 6*self->style; - SP_monster_soldier_x (self); - -} - -/*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_soldier (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_SOLDIER; - - sound_pain = gi.soundindex ("soldier/solpain1.wav"); - sound_death = gi.soundindex ("soldier/soldeth1.wav"); - gi.soundindex ("soldier/solatck1.wav"); - self->common_name = "Shotgun Guard"; - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 30; - if(!self->gib_health) - self->gib_health = -30; - - // Lazarus: custom skins - self->s.skin = 2 + 6*self->style; - SP_monster_soldier_x (self); - -} - -/*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight -*/ -void SP_monster_soldier_ss (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_SOLDIER_SS; - - sound_pain_ss = gi.soundindex ("soldier/solpain3.wav"); - sound_death_ss = gi.soundindex ("soldier/soldeth3.wav"); - gi.soundindex ("soldier/solatck3.wav"); - self->common_name = "Machinegun Guard"; - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 40; - if(!self->gib_health) - self->gib_health = -30; - - // Lazarus: custom skins - self->s.skin = 4 + 6*self->style; - SP_monster_soldier_x (self); - -} - diff --git a/server/monsters/m_soldier.h b/server/monsters/m_soldier.h deleted file mode 100644 index a14b8cc4..00000000 --- a/server/monsters/m_soldier.h +++ /dev/null @@ -1,481 +0,0 @@ -// G:\quake2\baseq2\models/monsters/soldier - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_attak101 0 -#define FRAME_attak102 1 -#define FRAME_attak103 2 -#define FRAME_attak104 3 -#define FRAME_attak105 4 -#define FRAME_attak106 5 -#define FRAME_attak107 6 -#define FRAME_attak108 7 -#define FRAME_attak109 8 -#define FRAME_attak110 9 -#define FRAME_attak111 10 -#define FRAME_attak112 11 -#define FRAME_attak201 12 -#define FRAME_attak202 13 -#define FRAME_attak203 14 -#define FRAME_attak204 15 -#define FRAME_attak205 16 -#define FRAME_attak206 17 -#define FRAME_attak207 18 -#define FRAME_attak208 19 -#define FRAME_attak209 20 -#define FRAME_attak210 21 -#define FRAME_attak211 22 -#define FRAME_attak212 23 -#define FRAME_attak213 24 -#define FRAME_attak214 25 -#define FRAME_attak215 26 -#define FRAME_attak216 27 -#define FRAME_attak217 28 -#define FRAME_attak218 29 -#define FRAME_attak301 30 -#define FRAME_attak302 31 -#define FRAME_attak303 32 -#define FRAME_attak304 33 -#define FRAME_attak305 34 -#define FRAME_attak306 35 -#define FRAME_attak307 36 -#define FRAME_attak308 37 -#define FRAME_attak309 38 -#define FRAME_attak401 39 -#define FRAME_attak402 40 -#define FRAME_attak403 41 -#define FRAME_attak404 42 -#define FRAME_attak405 43 -#define FRAME_attak406 44 -#define FRAME_duck01 45 -#define FRAME_duck02 46 -#define FRAME_duck03 47 -#define FRAME_duck04 48 -#define FRAME_duck05 49 -#define FRAME_pain101 50 -#define FRAME_pain102 51 -#define FRAME_pain103 52 -#define FRAME_pain104 53 -#define FRAME_pain105 54 -#define FRAME_pain201 55 -#define FRAME_pain202 56 -#define FRAME_pain203 57 -#define FRAME_pain204 58 -#define FRAME_pain205 59 -#define FRAME_pain206 60 -#define FRAME_pain207 61 -#define FRAME_pain301 62 -#define FRAME_pain302 63 -#define FRAME_pain303 64 -#define FRAME_pain304 65 -#define FRAME_pain305 66 -#define FRAME_pain306 67 -#define FRAME_pain307 68 -#define FRAME_pain308 69 -#define FRAME_pain309 70 -#define FRAME_pain310 71 -#define FRAME_pain311 72 -#define FRAME_pain312 73 -#define FRAME_pain313 74 -#define FRAME_pain314 75 -#define FRAME_pain315 76 -#define FRAME_pain316 77 -#define FRAME_pain317 78 -#define FRAME_pain318 79 -#define FRAME_pain401 80 -#define FRAME_pain402 81 -#define FRAME_pain403 82 -#define FRAME_pain404 83 -#define FRAME_pain405 84 -#define FRAME_pain406 85 -#define FRAME_pain407 86 -#define FRAME_pain408 87 -#define FRAME_pain409 88 -#define FRAME_pain410 89 -#define FRAME_pain411 90 -#define FRAME_pain412 91 -#define FRAME_pain413 92 -#define FRAME_pain414 93 -#define FRAME_pain415 94 -#define FRAME_pain416 95 -#define FRAME_pain417 96 -#define FRAME_run01 97 -#define FRAME_run02 98 -#define FRAME_run03 99 -#define FRAME_run04 100 -#define FRAME_run05 101 -#define FRAME_run06 102 -#define FRAME_run07 103 -#define FRAME_run08 104 -#define FRAME_run09 105 -#define FRAME_run10 106 -#define FRAME_run11 107 -#define FRAME_run12 108 -#define FRAME_runs01 109 -#define FRAME_runs02 110 -#define FRAME_runs03 111 -#define FRAME_runs04 112 -#define FRAME_runs05 113 -#define FRAME_runs06 114 -#define FRAME_runs07 115 -#define FRAME_runs08 116 -#define FRAME_runs09 117 -#define FRAME_runs10 118 -#define FRAME_runs11 119 -#define FRAME_runs12 120 -#define FRAME_runs13 121 -#define FRAME_runs14 122 -#define FRAME_runs15 123 -#define FRAME_runs16 124 -#define FRAME_runs17 125 -#define FRAME_runs18 126 -#define FRAME_runt01 127 -#define FRAME_runt02 128 -#define FRAME_runt03 129 -#define FRAME_runt04 130 -#define FRAME_runt05 131 -#define FRAME_runt06 132 -#define FRAME_runt07 133 -#define FRAME_runt08 134 -#define FRAME_runt09 135 -#define FRAME_runt10 136 -#define FRAME_runt11 137 -#define FRAME_runt12 138 -#define FRAME_runt13 139 -#define FRAME_runt14 140 -#define FRAME_runt15 141 -#define FRAME_runt16 142 -#define FRAME_runt17 143 -#define FRAME_runt18 144 -#define FRAME_runt19 145 -#define FRAME_stand101 146 -#define FRAME_stand102 147 -#define FRAME_stand103 148 -#define FRAME_stand104 149 -#define FRAME_stand105 150 -#define FRAME_stand106 151 -#define FRAME_stand107 152 -#define FRAME_stand108 153 -#define FRAME_stand109 154 -#define FRAME_stand110 155 -#define FRAME_stand111 156 -#define FRAME_stand112 157 -#define FRAME_stand113 158 -#define FRAME_stand114 159 -#define FRAME_stand115 160 -#define FRAME_stand116 161 -#define FRAME_stand117 162 -#define FRAME_stand118 163 -#define FRAME_stand119 164 -#define FRAME_stand120 165 -#define FRAME_stand121 166 -#define FRAME_stand122 167 -#define FRAME_stand123 168 -#define FRAME_stand124 169 -#define FRAME_stand125 170 -#define FRAME_stand126 171 -#define FRAME_stand127 172 -#define FRAME_stand128 173 -#define FRAME_stand129 174 -#define FRAME_stand130 175 -#define FRAME_stand301 176 -#define FRAME_stand302 177 -#define FRAME_stand303 178 -#define FRAME_stand304 179 -#define FRAME_stand305 180 -#define FRAME_stand306 181 -#define FRAME_stand307 182 -#define FRAME_stand308 183 -#define FRAME_stand309 184 -#define FRAME_stand310 185 -#define FRAME_stand311 186 -#define FRAME_stand312 187 -#define FRAME_stand313 188 -#define FRAME_stand314 189 -#define FRAME_stand315 190 -#define FRAME_stand316 191 -#define FRAME_stand317 192 -#define FRAME_stand318 193 -#define FRAME_stand319 194 -#define FRAME_stand320 195 -#define FRAME_stand321 196 -#define FRAME_stand322 197 -#define FRAME_stand323 198 -#define FRAME_stand324 199 -#define FRAME_stand325 200 -#define FRAME_stand326 201 -#define FRAME_stand327 202 -#define FRAME_stand328 203 -#define FRAME_stand329 204 -#define FRAME_stand330 205 -#define FRAME_stand331 206 -#define FRAME_stand332 207 -#define FRAME_stand333 208 -#define FRAME_stand334 209 -#define FRAME_stand335 210 -#define FRAME_stand336 211 -#define FRAME_stand337 212 -#define FRAME_stand338 213 -#define FRAME_stand339 214 -#define FRAME_walk101 215 -#define FRAME_walk102 216 -#define FRAME_walk103 217 -#define FRAME_walk104 218 -#define FRAME_walk105 219 -#define FRAME_walk106 220 -#define FRAME_walk107 221 -#define FRAME_walk108 222 -#define FRAME_walk109 223 -#define FRAME_walk110 224 -#define FRAME_walk111 225 -#define FRAME_walk112 226 -#define FRAME_walk113 227 -#define FRAME_walk114 228 -#define FRAME_walk115 229 -#define FRAME_walk116 230 -#define FRAME_walk117 231 -#define FRAME_walk118 232 -#define FRAME_walk119 233 -#define FRAME_walk120 234 -#define FRAME_walk121 235 -#define FRAME_walk122 236 -#define FRAME_walk123 237 -#define FRAME_walk124 238 -#define FRAME_walk125 239 -#define FRAME_walk126 240 -#define FRAME_walk127 241 -#define FRAME_walk128 242 -#define FRAME_walk129 243 -#define FRAME_walk130 244 -#define FRAME_walk131 245 -#define FRAME_walk132 246 -#define FRAME_walk133 247 -#define FRAME_walk201 248 -#define FRAME_walk202 249 -#define FRAME_walk203 250 -#define FRAME_walk204 251 -#define FRAME_walk205 252 -#define FRAME_walk206 253 -#define FRAME_walk207 254 -#define FRAME_walk208 255 -#define FRAME_walk209 256 -#define FRAME_walk210 257 -#define FRAME_walk211 258 -#define FRAME_walk212 259 -#define FRAME_walk213 260 -#define FRAME_walk214 261 -#define FRAME_walk215 262 -#define FRAME_walk216 263 -#define FRAME_walk217 264 -#define FRAME_walk218 265 -#define FRAME_walk219 266 -#define FRAME_walk220 267 -#define FRAME_walk221 268 -#define FRAME_walk222 269 -#define FRAME_walk223 270 -#define FRAME_walk224 271 -#define FRAME_death101 272 -#define FRAME_death102 273 -#define FRAME_death103 274 -#define FRAME_death104 275 -#define FRAME_death105 276 -#define FRAME_death106 277 -#define FRAME_death107 278 -#define FRAME_death108 279 -#define FRAME_death109 280 -#define FRAME_death110 281 -#define FRAME_death111 282 -#define FRAME_death112 283 -#define FRAME_death113 284 -#define FRAME_death114 285 -#define FRAME_death115 286 -#define FRAME_death116 287 -#define FRAME_death117 288 -#define FRAME_death118 289 -#define FRAME_death119 290 -#define FRAME_death120 291 -#define FRAME_death121 292 -#define FRAME_death122 293 -#define FRAME_death123 294 -#define FRAME_death124 295 -#define FRAME_death125 296 -#define FRAME_death126 297 -#define FRAME_death127 298 -#define FRAME_death128 299 -#define FRAME_death129 300 -#define FRAME_death130 301 -#define FRAME_death131 302 -#define FRAME_death132 303 -#define FRAME_death133 304 -#define FRAME_death134 305 -#define FRAME_death135 306 -#define FRAME_death136 307 -#define FRAME_death201 308 -#define FRAME_death202 309 -#define FRAME_death203 310 -#define FRAME_death204 311 -#define FRAME_death205 312 -#define FRAME_death206 313 -#define FRAME_death207 314 -#define FRAME_death208 315 -#define FRAME_death209 316 -#define FRAME_death210 317 -#define FRAME_death211 318 -#define FRAME_death212 319 -#define FRAME_death213 320 -#define FRAME_death214 321 -#define FRAME_death215 322 -#define FRAME_death216 323 -#define FRAME_death217 324 -#define FRAME_death218 325 -#define FRAME_death219 326 -#define FRAME_death220 327 -#define FRAME_death221 328 -#define FRAME_death222 329 -#define FRAME_death223 330 -#define FRAME_death224 331 -#define FRAME_death225 332 -#define FRAME_death226 333 -#define FRAME_death227 334 -#define FRAME_death228 335 -#define FRAME_death229 336 -#define FRAME_death230 337 -#define FRAME_death231 338 -#define FRAME_death232 339 -#define FRAME_death233 340 -#define FRAME_death234 341 -#define FRAME_death235 342 -#define FRAME_death301 343 -#define FRAME_death302 344 -#define FRAME_death303 345 -#define FRAME_death304 346 -#define FRAME_death305 347 -#define FRAME_death306 348 -#define FRAME_death307 349 -#define FRAME_death308 350 -#define FRAME_death309 351 -#define FRAME_death310 352 -#define FRAME_death311 353 -#define FRAME_death312 354 -#define FRAME_death313 355 -#define FRAME_death314 356 -#define FRAME_death315 357 -#define FRAME_death316 358 -#define FRAME_death317 359 -#define FRAME_death318 360 -#define FRAME_death319 361 -#define FRAME_death320 362 -#define FRAME_death321 363 -#define FRAME_death322 364 -#define FRAME_death323 365 -#define FRAME_death324 366 -#define FRAME_death325 367 -#define FRAME_death326 368 -#define FRAME_death327 369 -#define FRAME_death328 370 -#define FRAME_death329 371 -#define FRAME_death330 372 -#define FRAME_death331 373 -#define FRAME_death332 374 -#define FRAME_death333 375 -#define FRAME_death334 376 -#define FRAME_death335 377 -#define FRAME_death336 378 -#define FRAME_death337 379 -#define FRAME_death338 380 -#define FRAME_death339 381 -#define FRAME_death340 382 -#define FRAME_death341 383 -#define FRAME_death342 384 -#define FRAME_death343 385 -#define FRAME_death344 386 -#define FRAME_death345 387 -#define FRAME_death401 388 -#define FRAME_death402 389 -#define FRAME_death403 390 -#define FRAME_death404 391 -#define FRAME_death405 392 -#define FRAME_death406 393 -#define FRAME_death407 394 -#define FRAME_death408 395 -#define FRAME_death409 396 -#define FRAME_death410 397 -#define FRAME_death411 398 -#define FRAME_death412 399 -#define FRAME_death413 400 -#define FRAME_death414 401 -#define FRAME_death415 402 -#define FRAME_death416 403 -#define FRAME_death417 404 -#define FRAME_death418 405 -#define FRAME_death419 406 -#define FRAME_death420 407 -#define FRAME_death421 408 -#define FRAME_death422 409 -#define FRAME_death423 410 -#define FRAME_death424 411 -#define FRAME_death425 412 -#define FRAME_death426 413 -#define FRAME_death427 414 -#define FRAME_death428 415 -#define FRAME_death429 416 -#define FRAME_death430 417 -#define FRAME_death431 418 -#define FRAME_death432 419 -#define FRAME_death433 420 -#define FRAME_death434 421 -#define FRAME_death435 422 -#define FRAME_death436 423 -#define FRAME_death437 424 -#define FRAME_death438 425 -#define FRAME_death439 426 -#define FRAME_death440 427 -#define FRAME_death441 428 -#define FRAME_death442 429 -#define FRAME_death443 430 -#define FRAME_death444 431 -#define FRAME_death445 432 -#define FRAME_death446 433 -#define FRAME_death447 434 -#define FRAME_death448 435 -#define FRAME_death449 436 -#define FRAME_death450 437 -#define FRAME_death451 438 -#define FRAME_death452 439 -#define FRAME_death453 440 -#define FRAME_death501 441 -#define FRAME_death502 442 -#define FRAME_death503 443 -#define FRAME_death504 444 -#define FRAME_death505 445 -#define FRAME_death506 446 -#define FRAME_death507 447 -#define FRAME_death508 448 -#define FRAME_death509 449 -#define FRAME_death510 450 -#define FRAME_death511 451 -#define FRAME_death512 452 -#define FRAME_death513 453 -#define FRAME_death514 454 -#define FRAME_death515 455 -#define FRAME_death516 456 -#define FRAME_death517 457 -#define FRAME_death518 458 -#define FRAME_death519 459 -#define FRAME_death520 460 -#define FRAME_death521 461 -#define FRAME_death522 462 -#define FRAME_death523 463 -#define FRAME_death524 464 -#define FRAME_death601 465 -#define FRAME_death602 466 -#define FRAME_death603 467 -#define FRAME_death604 468 -#define FRAME_death605 469 -#define FRAME_death606 470 -#define FRAME_death607 471 -#define FRAME_death608 472 -#define FRAME_death609 473 -#define FRAME_death610 474 - -#define MODEL_SCALE 1.200000 diff --git a/server/monsters/m_supertank.c b/server/monsters/m_supertank.c deleted file mode 100644 index 4237c8d6..00000000 --- a/server/monsters/m_supertank.c +++ /dev/null @@ -1,758 +0,0 @@ -/* -============================================================================== - -SUPERTANK - -============================================================================== -*/ - -#include "g_local.h" -#include "m_supertank.h" - -bool visible (edict_t *self, edict_t *other); - -static int sound_pain1; -static int sound_pain2; -static int sound_pain3; -static int sound_death; -static int sound_search1; -static int sound_search2; - -static int tread_sound; - -void BossExplode (edict_t *self); - -void TreadSound (edict_t *self) -{ - gi.sound (self, CHAN_VOICE, tread_sound, 1, ATTN_NORM, 0); -} - -void supertank_search (edict_t *self) -{ - if (random() < 0.5) - gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); - else - gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); -} - - -void supertank_dead (edict_t *self); -void supertankRocket (edict_t *self); -void supertankMachineGun (edict_t *self); -void supertank_reattack1(edict_t *self); - - -// -// stand -// - -mframe_t supertank_frames_stand []= -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t supertank_move_stand = {FRAME_stand_1, FRAME_stand_60, supertank_frames_stand, NULL}; - -void supertank_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &supertank_move_stand; -} - - -mframe_t supertank_frames_run [] = -{ - ai_run, 12, TreadSound, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL, - ai_run, 12, NULL -}; -mmove_t supertank_move_run = {FRAME_forwrd_1, FRAME_forwrd_18, supertank_frames_run, NULL}; - -// -// walk -// - - -mframe_t supertank_frames_forward [] = -{ - ai_walk, 4, TreadSound, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL, - ai_walk, 4, NULL -}; -mmove_t supertank_move_forward = {FRAME_forwrd_1, FRAME_forwrd_18, supertank_frames_forward, NULL}; - -void supertank_forward (edict_t *self) -{ - self->monsterinfo.currentmove = &supertank_move_forward; -} - -void supertank_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &supertank_move_forward; -} - -void supertank_run (edict_t *self) -{ - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - self->monsterinfo.currentmove = &supertank_move_stand; - else - self->monsterinfo.currentmove = &supertank_move_run; -} - -mframe_t supertank_frames_turn_right [] = -{ - ai_move, 0, TreadSound, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_turn_right = {FRAME_right_1, FRAME_right_18, supertank_frames_turn_right, supertank_run}; - -mframe_t supertank_frames_turn_left [] = -{ - ai_move, 0, TreadSound, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_turn_left = {FRAME_left_1, FRAME_left_18, supertank_frames_turn_left, supertank_run}; - - -mframe_t supertank_frames_pain3 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_pain3 = {FRAME_pain3_9, FRAME_pain3_12, supertank_frames_pain3, supertank_run}; - -mframe_t supertank_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_pain2 = {FRAME_pain2_5, FRAME_pain2_8, supertank_frames_pain2, supertank_run}; - -mframe_t supertank_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_pain1 = {FRAME_pain1_1, FRAME_pain1_4, supertank_frames_pain1, supertank_run}; - -mframe_t supertank_frames_death1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, BossExplode -}; -mmove_t supertank_move_death = {FRAME_death_1, FRAME_death_24, supertank_frames_death1, supertank_dead}; - -mframe_t supertank_frames_backward[] = -{ - ai_walk, 0, TreadSound, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL, - ai_walk, 0, NULL -}; -mmove_t supertank_move_backward = {FRAME_backwd_1, FRAME_backwd_18, supertank_frames_backward, NULL}; - -mframe_t supertank_frames_attack4[]= -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_attack4 = {FRAME_attak4_1, FRAME_attak4_6, supertank_frames_attack4, supertank_run}; - -mframe_t supertank_frames_attack3[]= -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_attack3 = {FRAME_attak3_1, FRAME_attak3_27, supertank_frames_attack3, supertank_run}; - -mframe_t supertank_frames_attack2[]= -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, supertankRocket, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, supertankRocket, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, supertankRocket, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_attack2 = {FRAME_attak2_1, FRAME_attak2_27, supertank_frames_attack2, supertank_run}; - -mframe_t supertank_frames_attack1[]= -{ - ai_charge, 0, supertankMachineGun, - ai_charge, 0, supertankMachineGun, - ai_charge, 0, supertankMachineGun, - ai_charge, 0, supertankMachineGun, - ai_charge, 0, supertankMachineGun, - ai_charge, 0, supertankMachineGun, - -}; -mmove_t supertank_move_attack1 = {FRAME_attak1_1, FRAME_attak1_6, supertank_frames_attack1, supertank_reattack1}; - -mframe_t supertank_frames_end_attack1[]= -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t supertank_move_end_attack1 = {FRAME_attak1_7, FRAME_attak1_20, supertank_frames_end_attack1, supertank_run}; - - -void supertank_reattack1(edict_t *self) -{ - if (visible(self, self->enemy)) - if (random() < 0.9) - self->monsterinfo.currentmove = &supertank_move_attack1; - else - self->monsterinfo.currentmove = &supertank_move_end_attack1; - else - self->monsterinfo.currentmove = &supertank_move_end_attack1; -} - -void supertank_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (level.time < self->pain_debounce_time) - return; - - // Lessen the chance of him going into his pain frames - if (damage <=25) - if (random()<0.2) - return; - - // Don't go into pain if he's firing his rockets - if (skill->value >= 2) - if ( (self->s.frame >= FRAME_attak2_1) && (self->s.frame <= FRAME_attak2_14) ) - return; - - self->pain_debounce_time = level.time + 3; - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (damage <= 10) - { - gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &supertank_move_pain1; - } - else if (damage <= 25) - { - gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &supertank_move_pain2; - } - else - { - gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0); - self->monsterinfo.currentmove = &supertank_move_pain3; - } -}; - - -void supertankRocket (edict_t *self) -{ - vec3_t forward, right; - vec3_t start; - vec3_t dir; - vec3_t vec; - int flash_number; - int rocketSpeed; - - if((self->spawnflags & SF_MONSTER_SPECIAL)) - rocketSpeed = 400; // DWH: Homing rockets are tougher if slow - else - rocketSpeed = 500 + (100 * skill->value); // PGM rock & roll.... :) - - if (self->s.frame == FRAME_attak2_8) - flash_number = MZ2_SUPERTANK_ROCKET_1; - else if (self->s.frame == FRAME_attak2_11) - flash_number = MZ2_SUPERTANK_ROCKET_2; - else // (self->s.frame == FRAME_attak2_14) - flash_number = MZ2_SUPERTANK_ROCKET_3; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (vec, start, dir); - VectorNormalize (dir); - monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); -} - -void supertankMachineGun (edict_t *self) -{ - vec3_t dir; - vec3_t vec; - vec3_t start; - vec3_t forward, right; - int flash_number; - - flash_number = MZ2_SUPERTANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak1_1); - - //FIXME!!! - dir[0] = 0; - dir[1] = self->s.angles[1]; - dir[2] = 0; - - AngleVectors (dir, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - if (self->enemy) - { - VectorCopy (self->enemy->s.origin, vec); - VectorMA (vec, 0, self->enemy->velocity, vec); - vec[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (vec, start, forward); - VectorNormalize (forward); - } - - monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); -} - - -void supertank_attack(edict_t *self) -{ - vec3_t vec; - float range; - //float r; - - VectorSubtract (self->enemy->s.origin, self->s.origin, vec); - range = VectorLength (vec); - - //r = random(); - - // Attack 1 == Chaingun - // Attack 2 == Rocket Launcher - - if (range <= 160) - { - self->monsterinfo.currentmove = &supertank_move_attack1; - } - else - { // fire rockets more often at distance - if (random() < 0.3) - self->monsterinfo.currentmove = &supertank_move_attack1; - else - self->monsterinfo.currentmove = &supertank_move_attack2; - } -} - - -// -// death -// - -void supertank_dead (edict_t *self) -{ - VectorSet (self->mins, -60, -60, 0); - VectorSet (self->maxs, 60, 60, 72); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); -} - - -void BossExplode (edict_t *self) -{ - vec3_t org; - int n; - - self->think = BossExplode; - VectorCopy (self->s.origin, org); - org[2] += 24 + (rand()&15); - switch (self->count++) - { - case 0: - org[0] -= 24; - org[1] -= 24; - break; - case 1: - org[0] += 24; - org[1] += 24; - break; - case 2: - org[0] += 24; - org[1] -= 24; - break; - case 3: - org[0] -= 24; - org[1] += 24; - break; - case 4: - org[0] -= 48; - org[1] -= 48; - break; - case 5: - org[0] += 48; - org[1] += 48; - break; - case 6: - org[0] -= 48; - org[1] += 48; - break; - case 7: - org[0] += 48; - org[1] -= 48; - break; - case 8: - self->s.sound = 0; - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", 500, GIB_ORGANIC); - for (n= 0; n < 8; n++) - ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", 500, GIB_METALLIC); - ThrowGib (self, "models/objects/gibs/chest/tris.md2", 500, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/gear/tris.md2", 500, GIB_METALLIC); - self->deadflag = DEAD_DEAD; - return; - } - - MESSAGE_BEGIN (svc_temp_entity); - WRITE_BYTE (TE_EXPLOSION1); - WRITE_COORD (org); - MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); - - if (level.num_reflectors) - ReflectExplosion (TE_EXPLOSION1, self->s.origin); - - self->nextthink = level.time + 0.1; -} - - -void supertank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; - gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_NO; - self->count = 0; - self->monsterinfo.currentmove = &supertank_move_death; -} - -// -// monster_supertank -// - -/*QUAKED monster_supertank (1 .5 0) (-64 -64 0) (64 64 72) Ambush Trigger_Spawn Sight -*/ -void SP_monster_supertank (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_SUPERTANK; - - // Lazarus: special purpose skins - if ( (self->spawnflags & SF_MONSTER_SPECIAL) && self->style ) - { - PatchMonsterModel("models/monsters/boss1/tris.md2"); - self->s.skin = self->style * 2; - } - - sound_pain1 = gi.soundindex ("bosstank/btkpain1.wav"); - sound_pain2 = gi.soundindex ("bosstank/btkpain2.wav"); - sound_pain3 = gi.soundindex ("bosstank/btkpain3.wav"); - sound_death = gi.soundindex ("bosstank/btkdeth1.wav"); - sound_search1 = gi.soundindex ("bosstank/btkunqv1.wav"); - sound_search2 = gi.soundindex ("bosstank/btkunqv2.wav"); - -// self->s.sound = gi.soundindex ("bosstank/btkengn1.wav"); - tread_sound = gi.soundindex ("bosstank/btkengn1.wav"); - - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - // Lazarus: special purpose skins - if ( self->style ) - { - PatchMonsterModel("models/monsters/boss1/tris.md2"); - self->s.skin = self->style * 2; - } - - self->s.modelindex = gi.modelindex ("models/monsters/boss1/tris.md2"); - VectorSet (self->mins, -64, -64, 0); - VectorSet (self->maxs, 64, 64, 112); - - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 1500; - if(!self->gib_health) - self->gib_health = -500; - if(!self->mass) - self->mass = 800; - - self->pain = supertank_pain; - self->die = supertank_die; - self->monsterinfo.stand = supertank_stand; - self->monsterinfo.walk = supertank_walk; - self->monsterinfo.run = supertank_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = supertank_attack; - self->monsterinfo.search = supertank_search; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = NULL; - - // Lazarus - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - - gi.linkentity (self); - self->monsterinfo.currentmove = &supertank_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&supertank_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->common_name = "Supertank"; - - self->monsterinfo.scale = MODEL_SCALE; - walkmonster_start(self); -} diff --git a/server/monsters/m_supertank.h b/server/monsters/m_supertank.h deleted file mode 100644 index c7581d8d..00000000 --- a/server/monsters/m_supertank.h +++ /dev/null @@ -1,260 +0,0 @@ -// G:\quake2\baseq2\models/monsters/boss1/backup - -// This file generated by ModelGen - Do NOT Modify - -#define FRAME_attak1_1 0 -#define FRAME_attak1_2 1 -#define FRAME_attak1_3 2 -#define FRAME_attak1_4 3 -#define FRAME_attak1_5 4 -#define FRAME_attak1_6 5 -#define FRAME_attak1_7 6 -#define FRAME_attak1_8 7 -#define FRAME_attak1_9 8 -#define FRAME_attak1_10 9 -#define FRAME_attak1_11 10 -#define FRAME_attak1_12 11 -#define FRAME_attak1_13 12 -#define FRAME_attak1_14 13 -#define FRAME_attak1_15 14 -#define FRAME_attak1_16 15 -#define FRAME_attak1_17 16 -#define FRAME_attak1_18 17 -#define FRAME_attak1_19 18 -#define FRAME_attak1_20 19 -#define FRAME_attak2_1 20 -#define FRAME_attak2_2 21 -#define FRAME_attak2_3 22 -#define FRAME_attak2_4 23 -#define FRAME_attak2_5 24 -#define FRAME_attak2_6 25 -#define FRAME_attak2_7 26 -#define FRAME_attak2_8 27 -#define FRAME_attak2_9 28 -#define FRAME_attak2_10 29 -#define FRAME_attak2_11 30 -#define FRAME_attak2_12 31 -#define FRAME_attak2_13 32 -#define FRAME_attak2_14 33 -#define FRAME_attak2_15 34 -#define FRAME_attak2_16 35 -#define FRAME_attak2_17 36 -#define FRAME_attak2_18 37 -#define FRAME_attak2_19 38 -#define FRAME_attak2_20 39 -#define FRAME_attak2_21 40 -#define FRAME_attak2_22 41 -#define FRAME_attak2_23 42 -#define FRAME_attak2_24 43 -#define FRAME_attak2_25 44 -#define FRAME_attak2_26 45 -#define FRAME_attak2_27 46 -#define FRAME_attak3_1 47 -#define FRAME_attak3_2 48 -#define FRAME_attak3_3 49 -#define FRAME_attak3_4 50 -#define FRAME_attak3_5 51 -#define FRAME_attak3_6 52 -#define FRAME_attak3_7 53 -#define FRAME_attak3_8 54 -#define FRAME_attak3_9 55 -#define FRAME_attak3_10 56 -#define FRAME_attak3_11 57 -#define FRAME_attak3_12 58 -#define FRAME_attak3_13 59 -#define FRAME_attak3_14 60 -#define FRAME_attak3_15 61 -#define FRAME_attak3_16 62 -#define FRAME_attak3_17 63 -#define FRAME_attak3_18 64 -#define FRAME_attak3_19 65 -#define FRAME_attak3_20 66 -#define FRAME_attak3_21 67 -#define FRAME_attak3_22 68 -#define FRAME_attak3_23 69 -#define FRAME_attak3_24 70 -#define FRAME_attak3_25 71 -#define FRAME_attak3_26 72 -#define FRAME_attak3_27 73 -#define FRAME_attak4_1 74 -#define FRAME_attak4_2 75 -#define FRAME_attak4_3 76 -#define FRAME_attak4_4 77 -#define FRAME_attak4_5 78 -#define FRAME_attak4_6 79 -#define FRAME_backwd_1 80 -#define FRAME_backwd_2 81 -#define FRAME_backwd_3 82 -#define FRAME_backwd_4 83 -#define FRAME_backwd_5 84 -#define FRAME_backwd_6 85 -#define FRAME_backwd_7 86 -#define FRAME_backwd_8 87 -#define FRAME_backwd_9 88 -#define FRAME_backwd_10 89 -#define FRAME_backwd_11 90 -#define FRAME_backwd_12 91 -#define FRAME_backwd_13 92 -#define FRAME_backwd_14 93 -#define FRAME_backwd_15 94 -#define FRAME_backwd_16 95 -#define FRAME_backwd_17 96 -#define FRAME_backwd_18 97 -#define FRAME_death_1 98 -#define FRAME_death_2 99 -#define FRAME_death_3 100 -#define FRAME_death_4 101 -#define FRAME_death_5 102 -#define FRAME_death_6 103 -#define FRAME_death_7 104 -#define FRAME_death_8 105 -#define FRAME_death_9 106 -#define FRAME_death_10 107 -#define FRAME_death_11 108 -#define FRAME_death_12 109 -#define FRAME_death_13 110 -#define FRAME_death_14 111 -#define FRAME_death_15 112 -#define FRAME_death_16 113 -#define FRAME_death_17 114 -#define FRAME_death_18 115 -#define FRAME_death_19 116 -#define FRAME_death_20 117 -#define FRAME_death_21 118 -#define FRAME_death_22 119 -#define FRAME_death_23 120 -#define FRAME_death_24 121 -#define FRAME_death_31 122 -#define FRAME_death_32 123 -#define FRAME_death_33 124 -#define FRAME_death_45 125 -#define FRAME_death_46 126 -#define FRAME_death_47 127 -#define FRAME_forwrd_1 128 -#define FRAME_forwrd_2 129 -#define FRAME_forwrd_3 130 -#define FRAME_forwrd_4 131 -#define FRAME_forwrd_5 132 -#define FRAME_forwrd_6 133 -#define FRAME_forwrd_7 134 -#define FRAME_forwrd_8 135 -#define FRAME_forwrd_9 136 -#define FRAME_forwrd_10 137 -#define FRAME_forwrd_11 138 -#define FRAME_forwrd_12 139 -#define FRAME_forwrd_13 140 -#define FRAME_forwrd_14 141 -#define FRAME_forwrd_15 142 -#define FRAME_forwrd_16 143 -#define FRAME_forwrd_17 144 -#define FRAME_forwrd_18 145 -#define FRAME_left_1 146 -#define FRAME_left_2 147 -#define FRAME_left_3 148 -#define FRAME_left_4 149 -#define FRAME_left_5 150 -#define FRAME_left_6 151 -#define FRAME_left_7 152 -#define FRAME_left_8 153 -#define FRAME_left_9 154 -#define FRAME_left_10 155 -#define FRAME_left_11 156 -#define FRAME_left_12 157 -#define FRAME_left_13 158 -#define FRAME_left_14 159 -#define FRAME_left_15 160 -#define FRAME_left_16 161 -#define FRAME_left_17 162 -#define FRAME_left_18 163 -#define FRAME_pain1_1 164 -#define FRAME_pain1_2 165 -#define FRAME_pain1_3 166 -#define FRAME_pain1_4 167 -#define FRAME_pain2_5 168 -#define FRAME_pain2_6 169 -#define FRAME_pain2_7 170 -#define FRAME_pain2_8 171 -#define FRAME_pain3_9 172 -#define FRAME_pain3_10 173 -#define FRAME_pain3_11 174 -#define FRAME_pain3_12 175 -#define FRAME_right_1 176 -#define FRAME_right_2 177 -#define FRAME_right_3 178 -#define FRAME_right_4 179 -#define FRAME_right_5 180 -#define FRAME_right_6 181 -#define FRAME_right_7 182 -#define FRAME_right_8 183 -#define FRAME_right_9 184 -#define FRAME_right_10 185 -#define FRAME_right_11 186 -#define FRAME_right_12 187 -#define FRAME_right_13 188 -#define FRAME_right_14 189 -#define FRAME_right_15 190 -#define FRAME_right_16 191 -#define FRAME_right_17 192 -#define FRAME_right_18 193 -#define FRAME_stand_1 194 -#define FRAME_stand_2 195 -#define FRAME_stand_3 196 -#define FRAME_stand_4 197 -#define FRAME_stand_5 198 -#define FRAME_stand_6 199 -#define FRAME_stand_7 200 -#define FRAME_stand_8 201 -#define FRAME_stand_9 202 -#define FRAME_stand_10 203 -#define FRAME_stand_11 204 -#define FRAME_stand_12 205 -#define FRAME_stand_13 206 -#define FRAME_stand_14 207 -#define FRAME_stand_15 208 -#define FRAME_stand_16 209 -#define FRAME_stand_17 210 -#define FRAME_stand_18 211 -#define FRAME_stand_19 212 -#define FRAME_stand_20 213 -#define FRAME_stand_21 214 -#define FRAME_stand_22 215 -#define FRAME_stand_23 216 -#define FRAME_stand_24 217 -#define FRAME_stand_25 218 -#define FRAME_stand_26 219 -#define FRAME_stand_27 220 -#define FRAME_stand_28 221 -#define FRAME_stand_29 222 -#define FRAME_stand_30 223 -#define FRAME_stand_31 224 -#define FRAME_stand_32 225 -#define FRAME_stand_33 226 -#define FRAME_stand_34 227 -#define FRAME_stand_35 228 -#define FRAME_stand_36 229 -#define FRAME_stand_37 230 -#define FRAME_stand_38 231 -#define FRAME_stand_39 232 -#define FRAME_stand_40 233 -#define FRAME_stand_41 234 -#define FRAME_stand_42 235 -#define FRAME_stand_43 236 -#define FRAME_stand_44 237 -#define FRAME_stand_45 238 -#define FRAME_stand_46 239 -#define FRAME_stand_47 240 -#define FRAME_stand_48 241 -#define FRAME_stand_49 242 -#define FRAME_stand_50 243 -#define FRAME_stand_51 244 -#define FRAME_stand_52 245 -#define FRAME_stand_53 246 -#define FRAME_stand_54 247 -#define FRAME_stand_55 248 -#define FRAME_stand_56 249 -#define FRAME_stand_57 250 -#define FRAME_stand_58 251 -#define FRAME_stand_59 252 -#define FRAME_stand_60 253 - -#define MODEL_SCALE 1.000000 diff --git a/server/monsters/m_tank.c b/server/monsters/m_tank.c deleted file mode 100644 index f74a20b3..00000000 --- a/server/monsters/m_tank.c +++ /dev/null @@ -1,956 +0,0 @@ -/* -============================================================================== - -TANK - -============================================================================== -*/ - -#include "g_local.h" -#include "m_tank.h" - - -void tank_refire_rocket (edict_t *self); -void tank_doattack_rocket (edict_t *self); -void tank_reattack_blaster (edict_t *self); - -static int sound_thud; -static int sound_pain; -static int sound_idle; -static int sound_die; -static int sound_step; -static int sound_sight; -static int sound_windup; -static int sound_strike; - -// -// misc -// - -void tank_sight (edict_t *self, edict_t *other) -{ - gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); -} - - -void tank_footstep (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); -} - -void tank_thud (edict_t *self) -{ - gi.sound (self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0); -} - -void tank_windup (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0); -} - -void tank_idle (edict_t *self) -{ - if(!(self->spawnflags & SF_MONSTER_AMBUSH)) - gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); -} - - -// -// stand -// - -mframe_t tank_frames_stand []= -{ - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL -}; -mmove_t tank_move_stand = {FRAME_stand01, FRAME_stand30, tank_frames_stand, NULL}; - -void tank_stand (edict_t *self) -{ - self->monsterinfo.currentmove = &tank_move_stand; -} - - -// -// walk -// - -void tank_walk (edict_t *self); - -mframe_t tank_frames_start_walk [] = -{ - ai_walk, 0, NULL, - ai_walk, 6, NULL, - ai_walk, 6, NULL, - ai_walk, 11, tank_footstep -}; -mmove_t tank_move_start_walk = {FRAME_walk01, FRAME_walk04, tank_frames_start_walk, tank_walk}; - -mframe_t tank_frames_walk [] = -{ - ai_walk, 4, NULL, - ai_walk, 5, NULL, - ai_walk, 3, NULL, - ai_walk, 2, NULL, - ai_walk, 5, NULL, - ai_walk, 5, NULL, - ai_walk, 4, NULL, - ai_walk, 4, tank_footstep, - ai_walk, 3, NULL, - ai_walk, 5, NULL, - ai_walk, 4, NULL, - ai_walk, 5, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 6, NULL, - ai_walk, 6, tank_footstep -}; -mmove_t tank_move_walk = {FRAME_walk05, FRAME_walk20, tank_frames_walk, NULL}; - -mframe_t tank_frames_stop_walk [] = -{ - ai_walk, 3, NULL, - ai_walk, 3, NULL, - ai_walk, 2, NULL, - ai_walk, 2, NULL, - ai_walk, 4, tank_footstep -}; -mmove_t tank_move_stop_walk = {FRAME_walk21, FRAME_walk25, tank_frames_stop_walk, tank_stand}; - -void tank_walk (edict_t *self) -{ - self->monsterinfo.currentmove = &tank_move_walk; -} - - -// -// run -// - -void tank_run (edict_t *self); - -mframe_t tank_frames_start_run [] = -{ - ai_run, 0, NULL, - ai_run, 6, NULL, - ai_run, 6, NULL, - ai_run, 11, tank_footstep -}; -mmove_t tank_move_start_run = {FRAME_walk01, FRAME_walk04, tank_frames_start_run, tank_run}; - -mframe_t tank_frames_run [] = -{ - ai_run, 4, NULL, - ai_run, 5, NULL, - ai_run, 3, NULL, - ai_run, 2, NULL, - ai_run, 5, NULL, - ai_run, 5, NULL, - ai_run, 4, NULL, - ai_run, 4, tank_footstep, - ai_run, 3, NULL, - ai_run, 5, NULL, - ai_run, 4, NULL, - ai_run, 5, NULL, - ai_run, 7, NULL, - ai_run, 7, NULL, - ai_run, 6, NULL, - ai_run, 6, tank_footstep -}; -mmove_t tank_move_run = {FRAME_walk05, FRAME_walk20, tank_frames_run, NULL}; - -mframe_t tank_frames_stop_run [] = -{ - ai_run, 3, NULL, - ai_run, 3, NULL, - ai_run, 2, NULL, - ai_run, 2, NULL, - ai_run, 4, tank_footstep -}; -mmove_t tank_move_stop_run = {FRAME_walk21, FRAME_walk25, tank_frames_stop_run, tank_walk}; - -void tank_run (edict_t *self) -{ - if (self->enemy && self->enemy->client) - self->monsterinfo.aiflags |= AI_BRUTAL; - else - self->monsterinfo.aiflags &= ~AI_BRUTAL; - - if (self->monsterinfo.aiflags & AI_STAND_GROUND) - { - self->monsterinfo.currentmove = &tank_move_stand; - return; - } - - if (self->monsterinfo.currentmove == &tank_move_walk || - self->monsterinfo.currentmove == &tank_move_start_run) - { - self->monsterinfo.currentmove = &tank_move_run; - } - else - { - self->monsterinfo.currentmove = &tank_move_start_run; - } -} - -// -// pain -// - -mframe_t tank_frames_pain1 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t tank_move_pain1 = {FRAME_pain101, FRAME_pain104, tank_frames_pain1, tank_run}; - -mframe_t tank_frames_pain2 [] = -{ - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t tank_move_pain2 = {FRAME_pain201, FRAME_pain205, tank_frames_pain2, tank_run}; - -mframe_t tank_frames_pain3 [] = -{ - ai_move, -7, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 3, NULL, - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, tank_footstep -}; -mmove_t tank_move_pain3 = {FRAME_pain301, FRAME_pain316, tank_frames_pain3, tank_run}; - - -void tank_pain (edict_t *self, edict_t *other, float kick, int damage) -{ - if (self->health < (self->max_health / 2)) - self->s.skin |= 1; - - if (damage <= 10) - return; - - if (level.time < self->pain_debounce_time) - return; - - if (damage <= 30) - if (random() > 0.2) - return; - - // If hard or nightmare, don't go into pain while attacking - if ( skill->value >= 2) - { - if ( (self->s.frame >= FRAME_attak301) && (self->s.frame <= FRAME_attak330) ) - return; - if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak116) ) - return; - } - - self->pain_debounce_time = level.time + 3; - gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); - - if (skill->value == 3) - return; // no pain anims in nightmare - - if (damage <= 30) - self->monsterinfo.currentmove = &tank_move_pain1; - else if (damage <= 60) - self->monsterinfo.currentmove = &tank_move_pain2; - else - self->monsterinfo.currentmove = &tank_move_pain3; -}; - - -// -// attacks -// - -void TankBlaster (edict_t *self) -{ - vec3_t forward, right; - vec3_t start; - vec3_t end; - vec3_t dir; - int flash_number; - - if(!self->enemy || !self->enemy->inuse) - return; - - if (self->s.frame == FRAME_attak110) - flash_number = MZ2_TANK_BLASTER_1; - else if (self->s.frame == FRAME_attak113) - flash_number = MZ2_TANK_BLASTER_2; - else // (self->s.frame == FRAME_attak116) - flash_number = MZ2_TANK_BLASTER_3; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - VectorCopy (self->enemy->s.origin, end); - end[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (end, start, dir); - monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER); -} - -void TankStrike (edict_t *self) -{ - gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0); -} - -void TankRocket (edict_t *self) -{ - trace_t trace; - vec3_t forward, right; - vec3_t start; - vec3_t dir; - vec3_t vec; - int flash_number; - // Lazarus: Added Rogue's skill level-dependent rocket speed - int rocketSpeed; - - if(!self->enemy || !self->enemy->inuse) //PGM - return; //PGM - - if (self->s.frame == FRAME_attak324) - flash_number = MZ2_TANK_ROCKET_1; - else if (self->s.frame == FRAME_attak327) - flash_number = MZ2_TANK_ROCKET_2; - else // (self->s.frame == FRAME_attak330) - flash_number = MZ2_TANK_ROCKET_3; - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - if((self->spawnflags & SF_MONSTER_SPECIAL)) - rocketSpeed = 400; // Lazarus: Homing rockets are tougher if slow - else - rocketSpeed = 500 + (100 * skill->value); // PGM rock & roll.... :) - -/* VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - VectorSubtract (vec, start, dir); - VectorNormalize (dir); */ - // Lazarus: Added Rogue stuff and homers - VectorCopy (self->enemy->s.origin, vec); - if(random() < 0.66 || (start[2] < self->enemy->absmin[2])) - { -// gi.dprintf("normal shot\n"); - vec[2] += self->enemy->viewheight; - } - else - { -// gi.dprintf("shooting at feet!\n"); - vec[2] = self->enemy->absmin[2]; - } - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (vec, start, dir); - // lead target, but not if using homers - // 20, 35, 50, 65 chance of leading - // Lazarus: Switched this around from Rogue code... it led target more often - // for Easy, which seemed backwards - if( (random() < (0.2 + skill->value * 0.15) ) && !(self->spawnflags & SF_MONSTER_SPECIAL)) - { - float dist; - float time; - - dist = VectorLength (dir); - time = dist/rocketSpeed; - VectorMA(vec, time, self->enemy->velocity, vec); - VectorSubtract(vec, start, dir); - } - - VectorNormalize(dir); - // paranoia, make sure we're not shooting a target right next to us - trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); - if(trace.ent == self->enemy || trace.ent == world) - { - if(trace.fraction > 0.5 || (trace.ent && trace.ent->client)) - monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number, - (self->spawnflags & SF_MONSTER_SPECIAL ? self->enemy : NULL) ); - } -} - -void TankMachineGun (edict_t *self) -{ - vec3_t dir; - vec3_t vec; - vec3_t start; - vec3_t forward, right; - int flash_number; - - if(!self->enemy || !self->enemy->inuse) //PGM - return; //PGM - - flash_number = MZ2_TANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak406); - - AngleVectors (self->s.angles, forward, right, NULL); - G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); - - if (self->enemy) - { - VectorCopy (self->enemy->s.origin, vec); - vec[2] += self->enemy->viewheight; - - // Lazarus fog reduction of accuracy - if(self->monsterinfo.visibility < FOG_CANSEEGOOD) - { - vec[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - vec[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); - } - - VectorSubtract (vec, start, vec); - vectoangles (vec, vec); - dir[0] = vec[0]; - } - else - { - dir[0] = 0; - } - if (self->s.frame <= FRAME_attak415) - dir[1] = self->s.angles[1] - 8 * (self->s.frame - FRAME_attak411); - else - dir[1] = self->s.angles[1] + 8 * (self->s.frame - FRAME_attak419); - dir[2] = 0; - - AngleVectors (dir, forward, NULL, NULL); - - monster_fire_bullet (self, start, forward, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); -} - - -mframe_t tank_frames_attack_blast [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, -1, NULL, - ai_charge, -2, NULL, - ai_charge, -1, NULL, - ai_charge, -1, NULL, - ai_charge, 0, NULL, - ai_charge, 0, TankBlaster, // 10 - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, TankBlaster, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, TankBlaster // 16 -}; -mmove_t tank_move_attack_blast = {FRAME_attak101, FRAME_attak116, tank_frames_attack_blast, tank_reattack_blaster}; - -mframe_t tank_frames_reattack_blast [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, TankBlaster, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, TankBlaster // 16 -}; -mmove_t tank_move_reattack_blast = {FRAME_attak111, FRAME_attak116, tank_frames_reattack_blast, tank_reattack_blaster}; - -mframe_t tank_frames_attack_post_blast [] = -{ - ai_move, 0, NULL, // 17 - ai_move, 0, NULL, - ai_move, 2, NULL, - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, -2, tank_footstep // 22 -}; -mmove_t tank_move_attack_post_blast = {FRAME_attak117, FRAME_attak122, tank_frames_attack_post_blast, tank_run}; - -void tank_reattack_blaster (edict_t *self) -{ - if (skill->value >= 2) - if (visible (self, self->enemy)) - if (self->enemy->health > 0) - if (random() <= 0.6) - { - self->monsterinfo.currentmove = &tank_move_reattack_blast; - return; - } - self->monsterinfo.currentmove = &tank_move_attack_post_blast; -} - - -void tank_poststrike (edict_t *self) -{ - self->enemy = NULL; - tank_run (self); -} - -mframe_t tank_frames_attack_strike [] = -{ - ai_move, 3, NULL, - ai_move, 2, NULL, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 6, NULL, - ai_move, 7, NULL, - ai_move, 9, tank_footstep, - ai_move, 2, NULL, - ai_move, 1, NULL, - ai_move, 2, NULL, - ai_move, 2, tank_footstep, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, -2, NULL, - ai_move, 0, tank_windup, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, TankStrike, - ai_move, 0, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -1, NULL, - ai_move, -3, NULL, - ai_move, -10, NULL, - ai_move, -10, NULL, - ai_move, -2, NULL, - ai_move, -3, NULL, - ai_move, -2, tank_footstep -}; -mmove_t tank_move_attack_strike = {FRAME_attak201, FRAME_attak238, tank_frames_attack_strike, tank_poststrike}; - -mframe_t tank_frames_attack_pre_rocket [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // 10 - - ai_charge, 0, NULL, - ai_charge, 1, NULL, - ai_charge, 2, NULL, - ai_charge, 7, NULL, - ai_charge, 7, NULL, - ai_charge, 7, tank_footstep, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // 20 - - ai_charge, -3, NULL -}; -mmove_t tank_move_attack_pre_rocket = {FRAME_attak301, FRAME_attak321, tank_frames_attack_pre_rocket, tank_doattack_rocket}; - -mframe_t tank_frames_attack_fire_rocket [] = -{ - ai_charge, -3, NULL, // Loop Start 22 - ai_charge, 0, NULL, - ai_charge, 0, TankRocket, // 24 - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, TankRocket, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, -1, TankRocket // 30 Loop End -}; -mmove_t tank_move_attack_fire_rocket = {FRAME_attak322, FRAME_attak330, tank_frames_attack_fire_rocket, tank_refire_rocket}; - -mframe_t tank_frames_attack_post_rocket [] = -{ - ai_charge, 0, NULL, // 31 - ai_charge, -1, NULL, - ai_charge, -1, NULL, - ai_charge, 0, NULL, - ai_charge, 2, NULL, - ai_charge, 3, NULL, - ai_charge, 4, NULL, - ai_charge, 2, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // 40 - - ai_charge, 0, NULL, - ai_charge, -9, NULL, - ai_charge, -8, NULL, - ai_charge, -7, NULL, - ai_charge, -1, NULL, - ai_charge, -1, tank_footstep, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, // 50 - - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t tank_move_attack_post_rocket = {FRAME_attak331, FRAME_attak353, tank_frames_attack_post_rocket, tank_run}; - -mframe_t tank_frames_attack_chain [] = -{ - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - NULL, 0, TankMachineGun, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL -}; -mmove_t tank_move_attack_chain = {FRAME_attak401, FRAME_attak429, tank_frames_attack_chain, tank_run}; - -void tank_refire_rocket (edict_t *self) -{ - // Only on hard or nightmare - if ( skill->value >= 2 ) - if (self->enemy->health > 0) - if (visible(self, self->enemy) ) - if (random() <= 0.4) - { - self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; - return; - } - self->monsterinfo.currentmove = &tank_move_attack_post_rocket; -} - -void tank_doattack_rocket (edict_t *self) -{ - self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; -} - -void tank_attack(edict_t *self) -{ - vec3_t vec; - float range; - float r; - - // PMM - if (!self->enemy || !self->enemy->inuse) - return; - - if (self->enemy->health < 0) - { - self->monsterinfo.currentmove = &tank_move_attack_strike; - self->monsterinfo.aiflags &= ~AI_BRUTAL; - return; - } - - VectorSubtract (self->enemy->s.origin, self->s.origin, vec); - range = VectorLength (vec); - - r = random(); - - if (range <= 125) - { - if (r < 0.4) - self->monsterinfo.currentmove = &tank_move_attack_chain; - else - self->monsterinfo.currentmove = &tank_move_attack_blast; - } - else if (range <= 250) - { - if (r < 0.5) - self->monsterinfo.currentmove = &tank_move_attack_chain; - else - self->monsterinfo.currentmove = &tank_move_attack_blast; - } - else - { - if (r < 0.33) - self->monsterinfo.currentmove = &tank_move_attack_chain; - else if (r < 0.66) - { - self->monsterinfo.currentmove = &tank_move_attack_pre_rocket; - self->pain_debounce_time = level.time + 5.0; // no pain for a while - } - else - self->monsterinfo.currentmove = &tank_move_attack_blast; - } -} - - -// -// death -// - -void tank_dead (edict_t *self) -{ - VectorSet (self->mins, -16, -16, -16); - VectorSet (self->maxs, 16, 16, -0); - self->movetype = MOVETYPE_TOSS; - self->svflags |= SVF_DEADMONSTER; - self->nextthink = 0; - gi.linkentity (self); - M_FlyCheck (self); - - // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) - { - self->think=FadeDieSink; - self->nextthink=level.time+corpse_fadetime->value; - } -} - -mframe_t tank_frames_death1 [] = -{ - ai_move, -7, NULL, - ai_move, -2, NULL, - ai_move, -2, NULL, - ai_move, 1, NULL, - ai_move, 3, NULL, - ai_move, 6, NULL, - ai_move, 1, NULL, - ai_move, 1, NULL, - ai_move, 2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -2, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -3, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, -4, NULL, - ai_move, -6, NULL, - ai_move, -4, NULL, - ai_move, -5, NULL, - ai_move, -7, NULL, - ai_move, -15, tank_thud, - ai_move, -5, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL, - ai_move, 0, NULL -}; -mmove_t tank_move_death = {FRAME_death101, FRAME_death132, tank_frames_death1, tank_dead}; - -void tank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - int n; - - self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; -// check for gib - if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB)) - { - gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); - for (n= 0; n < 1 /*4*/; n++) - ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); - for (n= 0; n < 4; n++) - ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); - ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); - ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); - self->deadflag = DEAD_DEAD; - return; - } - - if (self->deadflag == DEAD_DEAD) - return; - -// regular death - gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); - self->deadflag = DEAD_DEAD; - self->takedamage = DAMAGE_YES; - - self->monsterinfo.currentmove = &tank_move_death; - -} - - -// -// monster_tank -// - -/*QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight -*/ -/*QUAKED monster_tank_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight -*/ -void SP_monster_tank (edict_t *self) -{ - if (deathmatch->value) - { - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_MONSTER_TANK; - - // Lazarus: special purpose skins - if (strcmp(self->classname, "monster_tank_commander") == 0) - self->s.skin = 2; - if ( self->style ) - { - PatchMonsterModel("models/monsters/tank/tris.md2"); - self->s.skin += self->style * 4; - } - - self->s.modelindex = gi.modelindex ("models/monsters/tank/tris.md2"); - VectorSet (self->mins, -32, -32, -16); - VectorSet (self->maxs, 32, 32, 72); - self->movetype = MOVETYPE_STEP; - self->solid = SOLID_BBOX; - - sound_pain = gi.soundindex ("tank/tnkpain2.wav"); - sound_thud = gi.soundindex ("tank/tnkdeth2.wav"); - sound_idle = gi.soundindex ("tank/tnkidle1.wav"); - sound_die = gi.soundindex ("tank/death.wav"); - sound_step = gi.soundindex ("tank/step.wav"); - sound_windup = gi.soundindex ("tank/tnkatck4.wav"); - sound_strike = gi.soundindex ("tank/tnkatck5.wav"); - sound_sight = gi.soundindex ("tank/sight1.wav"); - - gi.soundindex ("tank/tnkatck1.wav"); - gi.soundindex ("tank/tnkatk2a.wav"); - gi.soundindex ("tank/tnkatk2b.wav"); - gi.soundindex ("tank/tnkatk2c.wav"); - gi.soundindex ("tank/tnkatk2d.wav"); - gi.soundindex ("tank/tnkatk2e.wav"); - gi.soundindex ("tank/tnkatck3.wav"); - - if (strcmp(self->classname, "monster_tank_commander") == 0) - { - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 1000; - if(!self->gib_health) - self->gib_health = -225; - self->common_name = "Tank Commander"; - } - else - { - // Lazarus: mapper-configurable health - if(!self->health) - self->health = 750; - if(!self->gib_health) - self->gib_health = -200; - self->common_name = "Tank"; - } - - if(!self->mass) - self->mass = 500; - - self->pain = tank_pain; - self->die = tank_die; - self->monsterinfo.stand = tank_stand; - self->monsterinfo.walk = tank_walk; - self->monsterinfo.run = tank_run; - self->monsterinfo.dodge = NULL; - self->monsterinfo.attack = tank_attack; - self->monsterinfo.melee = NULL; - self->monsterinfo.sight = tank_sight; - self->monsterinfo.idle = tank_idle; - - // Lazarus power armor - if(self->powerarmor) { - self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; - self->monsterinfo.power_armor_power = self->powerarmor; - } - if(!self->monsterinfo.flies) - self->monsterinfo.flies = 0.05; - - gi.linkentity (self); - self->monsterinfo.currentmove = &tank_move_stand; - if(self->health < 0) - { - mmove_t *deathmoves[] = {&tank_move_death, - NULL}; - M_SetDeath(self,(mmove_t **)&deathmoves); - } - self->monsterinfo.scale = MODEL_SCALE; - walkmonster_start(self); -} diff --git a/server/monsters/m_tank.h b/server/monsters/m_tank.h deleted file mode 100644 index 874b75ab..00000000 --- a/server/monsters/m_tank.h +++ /dev/null @@ -1,300 +0,0 @@ -// G:\quake2\baseq2\models/monsters/tank - -// This file generated by qdata - Do NOT Modify - -#define FRAME_stand01 0 -#define FRAME_stand02 1 -#define FRAME_stand03 2 -#define FRAME_stand04 3 -#define FRAME_stand05 4 -#define FRAME_stand06 5 -#define FRAME_stand07 6 -#define FRAME_stand08 7 -#define FRAME_stand09 8 -#define FRAME_stand10 9 -#define FRAME_stand11 10 -#define FRAME_stand12 11 -#define FRAME_stand13 12 -#define FRAME_stand14 13 -#define FRAME_stand15 14 -#define FRAME_stand16 15 -#define FRAME_stand17 16 -#define FRAME_stand18 17 -#define FRAME_stand19 18 -#define FRAME_stand20 19 -#define FRAME_stand21 20 -#define FRAME_stand22 21 -#define FRAME_stand23 22 -#define FRAME_stand24 23 -#define FRAME_stand25 24 -#define FRAME_stand26 25 -#define FRAME_stand27 26 -#define FRAME_stand28 27 -#define FRAME_stand29 28 -#define FRAME_stand30 29 -#define FRAME_walk01 30 -#define FRAME_walk02 31 -#define FRAME_walk03 32 -#define FRAME_walk04 33 -#define FRAME_walk05 34 -#define FRAME_walk06 35 -#define FRAME_walk07 36 -#define FRAME_walk08 37 -#define FRAME_walk09 38 -#define FRAME_walk10 39 -#define FRAME_walk11 40 -#define FRAME_walk12 41 -#define FRAME_walk13 42 -#define FRAME_walk14 43 -#define FRAME_walk15 44 -#define FRAME_walk16 45 -#define FRAME_walk17 46 -#define FRAME_walk18 47 -#define FRAME_walk19 48 -#define FRAME_walk20 49 -#define FRAME_walk21 50 -#define FRAME_walk22 51 -#define FRAME_walk23 52 -#define FRAME_walk24 53 -#define FRAME_walk25 54 -#define FRAME_attak101 55 -#define FRAME_attak102 56 -#define FRAME_attak103 57 -#define FRAME_attak104 58 -#define FRAME_attak105 59 -#define FRAME_attak106 60 -#define FRAME_attak107 61 -#define FRAME_attak108 62 -#define FRAME_attak109 63 -#define FRAME_attak110 64 -#define FRAME_attak111 65 -#define FRAME_attak112 66 -#define FRAME_attak113 67 -#define FRAME_attak114 68 -#define FRAME_attak115 69 -#define FRAME_attak116 70 -#define FRAME_attak117 71 -#define FRAME_attak118 72 -#define FRAME_attak119 73 -#define FRAME_attak120 74 -#define FRAME_attak121 75 -#define FRAME_attak122 76 -#define FRAME_attak201 77 -#define FRAME_attak202 78 -#define FRAME_attak203 79 -#define FRAME_attak204 80 -#define FRAME_attak205 81 -#define FRAME_attak206 82 -#define FRAME_attak207 83 -#define FRAME_attak208 84 -#define FRAME_attak209 85 -#define FRAME_attak210 86 -#define FRAME_attak211 87 -#define FRAME_attak212 88 -#define FRAME_attak213 89 -#define FRAME_attak214 90 -#define FRAME_attak215 91 -#define FRAME_attak216 92 -#define FRAME_attak217 93 -#define FRAME_attak218 94 -#define FRAME_attak219 95 -#define FRAME_attak220 96 -#define FRAME_attak221 97 -#define FRAME_attak222 98 -#define FRAME_attak223 99 -#define FRAME_attak224 100 -#define FRAME_attak225 101 -#define FRAME_attak226 102 -#define FRAME_attak227 103 -#define FRAME_attak228 104 -#define FRAME_attak229 105 -#define FRAME_attak230 106 -#define FRAME_attak231 107 -#define FRAME_attak232 108 -#define FRAME_attak233 109 -#define FRAME_attak234 110 -#define FRAME_attak235 111 -#define FRAME_attak236 112 -#define FRAME_attak237 113 -#define FRAME_attak238 114 -#define FRAME_attak301 115 -#define FRAME_attak302 116 -#define FRAME_attak303 117 -#define FRAME_attak304 118 -#define FRAME_attak305 119 -#define FRAME_attak306 120 -#define FRAME_attak307 121 -#define FRAME_attak308 122 -#define FRAME_attak309 123 -#define FRAME_attak310 124 -#define FRAME_attak311 125 -#define FRAME_attak312 126 -#define FRAME_attak313 127 -#define FRAME_attak314 128 -#define FRAME_attak315 129 -#define FRAME_attak316 130 -#define FRAME_attak317 131 -#define FRAME_attak318 132 -#define FRAME_attak319 133 -#define FRAME_attak320 134 -#define FRAME_attak321 135 -#define FRAME_attak322 136 -#define FRAME_attak323 137 -#define FRAME_attak324 138 -#define FRAME_attak325 139 -#define FRAME_attak326 140 -#define FRAME_attak327 141 -#define FRAME_attak328 142 -#define FRAME_attak329 143 -#define FRAME_attak330 144 -#define FRAME_attak331 145 -#define FRAME_attak332 146 -#define FRAME_attak333 147 -#define FRAME_attak334 148 -#define FRAME_attak335 149 -#define FRAME_attak336 150 -#define FRAME_attak337 151 -#define FRAME_attak338 152 -#define FRAME_attak339 153 -#define FRAME_attak340 154 -#define FRAME_attak341 155 -#define FRAME_attak342 156 -#define FRAME_attak343 157 -#define FRAME_attak344 158 -#define FRAME_attak345 159 -#define FRAME_attak346 160 -#define FRAME_attak347 161 -#define FRAME_attak348 162 -#define FRAME_attak349 163 -#define FRAME_attak350 164 -#define FRAME_attak351 165 -#define FRAME_attak352 166 -#define FRAME_attak353 167 -#define FRAME_attak401 168 -#define FRAME_attak402 169 -#define FRAME_attak403 170 -#define FRAME_attak404 171 -#define FRAME_attak405 172 -#define FRAME_attak406 173 -#define FRAME_attak407 174 -#define FRAME_attak408 175 -#define FRAME_attak409 176 -#define FRAME_attak410 177 -#define FRAME_attak411 178 -#define FRAME_attak412 179 -#define FRAME_attak413 180 -#define FRAME_attak414 181 -#define FRAME_attak415 182 -#define FRAME_attak416 183 -#define FRAME_attak417 184 -#define FRAME_attak418 185 -#define FRAME_attak419 186 -#define FRAME_attak420 187 -#define FRAME_attak421 188 -#define FRAME_attak422 189 -#define FRAME_attak423 190 -#define FRAME_attak424 191 -#define FRAME_attak425 192 -#define FRAME_attak426 193 -#define FRAME_attak427 194 -#define FRAME_attak428 195 -#define FRAME_attak429 196 -#define FRAME_pain101 197 -#define FRAME_pain102 198 -#define FRAME_pain103 199 -#define FRAME_pain104 200 -#define FRAME_pain201 201 -#define FRAME_pain202 202 -#define FRAME_pain203 203 -#define FRAME_pain204 204 -#define FRAME_pain205 205 -#define FRAME_pain301 206 -#define FRAME_pain302 207 -#define FRAME_pain303 208 -#define FRAME_pain304 209 -#define FRAME_pain305 210 -#define FRAME_pain306 211 -#define FRAME_pain307 212 -#define FRAME_pain308 213 -#define FRAME_pain309 214 -#define FRAME_pain310 215 -#define FRAME_pain311 216 -#define FRAME_pain312 217 -#define FRAME_pain313 218 -#define FRAME_pain314 219 -#define FRAME_pain315 220 -#define FRAME_pain316 221 -#define FRAME_death101 222 -#define FRAME_death102 223 -#define FRAME_death103 224 -#define FRAME_death104 225 -#define FRAME_death105 226 -#define FRAME_death106 227 -#define FRAME_death107 228 -#define FRAME_death108 229 -#define FRAME_death109 230 -#define FRAME_death110 231 -#define FRAME_death111 232 -#define FRAME_death112 233 -#define FRAME_death113 234 -#define FRAME_death114 235 -#define FRAME_death115 236 -#define FRAME_death116 237 -#define FRAME_death117 238 -#define FRAME_death118 239 -#define FRAME_death119 240 -#define FRAME_death120 241 -#define FRAME_death121 242 -#define FRAME_death122 243 -#define FRAME_death123 244 -#define FRAME_death124 245 -#define FRAME_death125 246 -#define FRAME_death126 247 -#define FRAME_death127 248 -#define FRAME_death128 249 -#define FRAME_death129 250 -#define FRAME_death130 251 -#define FRAME_death131 252 -#define FRAME_death132 253 -#define FRAME_recln101 254 -#define FRAME_recln102 255 -#define FRAME_recln103 256 -#define FRAME_recln104 257 -#define FRAME_recln105 258 -#define FRAME_recln106 259 -#define FRAME_recln107 260 -#define FRAME_recln108 261 -#define FRAME_recln109 262 -#define FRAME_recln110 263 -#define FRAME_recln111 264 -#define FRAME_recln112 265 -#define FRAME_recln113 266 -#define FRAME_recln114 267 -#define FRAME_recln115 268 -#define FRAME_recln116 269 -#define FRAME_recln117 270 -#define FRAME_recln118 271 -#define FRAME_recln119 272 -#define FRAME_recln120 273 -#define FRAME_recln121 274 -#define FRAME_recln122 275 -#define FRAME_recln123 276 -#define FRAME_recln124 277 -#define FRAME_recln125 278 -#define FRAME_recln126 279 -#define FRAME_recln127 280 -#define FRAME_recln128 281 -#define FRAME_recln129 282 -#define FRAME_recln130 283 -#define FRAME_recln131 284 -#define FRAME_recln132 285 -#define FRAME_recln133 286 -#define FRAME_recln134 287 -#define FRAME_recln135 288 -#define FRAME_recln136 289 -#define FRAME_recln137 290 -#define FRAME_recln138 291 -#define FRAME_recln139 292 -#define FRAME_recln140 293 - -#define MODEL_SCALE 1.000000 diff --git a/server/p_chase.c b/server/p_chase.c deleted file mode 100644 index 903f9c02..00000000 --- a/server/p_chase.c +++ /dev/null @@ -1,331 +0,0 @@ -#include "g_local.h" - -// Lazarus: removed all waterlevel-dependent stuff, which I don't get, and -// the fake crosshair, which looked... really bad - -cvar_t *tpp; -cvar_t *tpp_auto; -cvar_t *crossh; - -void ChasecamTrack (edict_t *ent); - -/* The ent is the owner of the chasecam */ -void ChasecamStart (edict_t *ent) -{ -/* This creates a tempory entity we can manipulate within this - * function */ - edict_t *chasecam; - /* Don't work on a spectator! */ - if (ent->client->resp.spectator) - return; - //Don't turn back on during intermission! - if (level.intermissiontime) - return; - /* Tell everything that looks at the toggle that our chasecam is on - * and working */ - ent->client->chasetoggle = 1; - /* Make our gun model "non-existent" so it's more realistic to the - * player using the chasecam */ - ent->client->ps.gunindex = 0; - chasecam = G_Spawn (); - chasecam->owner = ent; - chasecam->solid = SOLID_NOT; - chasecam->movetype = MOVETYPE_FLYMISSILE; - ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; // this turns off Quake2's inclination to predict where the camera is going, - // making a much smoother ride - ent->svflags |= SVF_NOCLIENT; // this line tells Quake2 not to send the unnecessary info about the camera to other players - /* Now, make the angles of the player model, (!NOT THE HUMAN VIEW!) be - * copied to the same angle of the chasecam entity */ - VectorCopy (ent->s.angles, chasecam->s.angles); - /* Clear the size of the entity, so it DOES technically have a size, - * but that of '0 0 0'-'0 0 0'. (xyz, xyz). mins = Minimum size, - * maxs = Maximum size */ - VectorClear (chasecam->mins); - VectorClear (chasecam->maxs); - /* Make the chasecam's origin (position) be the same as the player - * entity's because as the camera starts, it will force itself out - * slowly backwards from the player model */ - VectorCopy (ent->s.origin, chasecam->s.origin); - chasecam->classname = "chasecam"; - chasecam->class_id = ENTITY_CHASECAM; - chasecam->prethink = ChasecamTrack; - // Lazarus: Need think??? - chasecam->think = ChasecamTrack; - ent->client->chasecam = chasecam; - ent->client->oldplayer = G_Spawn(); - CheckChasecam_Viewent(ent); - //MakeFakeCrosshair(ent); - - // remove reflection of real player, if any - DeleteReflection(ent,-1); -} - -/* ent = chasecam */ -void ChasecamRestart (edict_t *ent) -{ -/* Keep thinking this function to check all the time whether the - * player is out of the water */ - /* If the player is dead, the camera is not wanted... Kill me and stop - * the function. (return;) */ - if (ent->owner->health <= 0) - { - G_FreeEdict(ent); - return; - } - /* If the player is still completly underwater, break the routine - unless tpp has changed!*/ -// if (ent->owner->waterlevel && !tpp->value) -// return; - //Put camera back - ChasecamStart (ent->owner); - //Remove this temporary ent - G_FreeEdict (ent); -} - -/* Here, the "ent" is referring to the client, the player that owns the -* chasecam, and the "opt" integer is telling the function whether to -* totally get rid of the camera, or to put it into the background while -* it checks if the player is out of the water or not. */ -void ChasecamRemove (edict_t *ent, int opt) -{ - /* Stop the chasecam from moving */ - VectorClear (ent->client->chasecam->velocity); - /* Make the weapon model of the player appear on screen for 1st - * person reality and aiming */ - //Don't turn back on during intermission! - if (!level.intermissiontime) - ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); - /* Make our invisible appearance the same model as the display entity - * that mimics us while in chasecam mode */ - ent->s.modelindex = ent->client->oldplayer->s.modelindex; - ent->svflags &= ~SVF_NOCLIENT; - - //DestroyFakeCrosshair (ent); - - if (opt == OPTION_BACKGROUND) - { - ent->client->chasetoggle = 0; - G_FreeEdict (ent->client->chasecam); - G_FreeEdict (ent->client->oldplayer); - ent->client->oldplayer = NULL; - ent->client->chasecam = G_Spawn (); - ent->client->chasecam->owner = ent; - ent->client->chasecam->solid = SOLID_NOT; - ent->client->chasecam->movetype = MOVETYPE_FLYMISSILE; - VectorClear (ent->client->chasecam->mins); - VectorClear (ent->client->chasecam->maxs); - ent->client->chasecam->classname = "chasecam"; - ent->client->chasecam->class_id = ENTITY_CHASECAM; - ent->client->chasecam->prethink = ChasecamRestart; // begin checking for emergence from the water - // Lazarus: Need think don't we??? - ent->client->chasecam->think = ChasecamRestart; - } - else if (opt == OPTION_OFF) - { - G_FreeEdict (ent->client->oldplayer); - ent->client->oldplayer = NULL; - ent->client->chasetoggle = 0; - G_FreeEdict (ent->client->chasecam); - ent->client->chasecam = NULL; - } -} - -/* The "ent" is the chasecam */ -void ChasecamTrack (edict_t *ent) -{ - /* Create tempory vectors and trace variables */ - trace_t tr; - vec3_t spot1, spot2, dir; - vec3_t forward, right, up,angles; - int distance; - int tot; - ent->nextthink = level.time + 0.100; - /* if our owner is under water, run the remove routine to repeatedly - * check for emergment from water */ -// if (ent->owner->waterlevel && !tpp->value) -// { -// ChasecamRemove (ent->owner, OPTION_BACKGROUND); -// return; -// } - /* get the CLIENT's angle, and break it down into direction vectors, - * of forward, right, and up. VERY useful */ - VectorCopy(ent->owner->client->v_angle,angles); - if (angles[PITCH] > 56) - angles[PITCH] = 56; - AngleVectors (angles, forward, right, up); - VectorNormalize(forward); - /* go starting at the player's origin, forward, ent->chasedist1 - * distance, and save the location in vector spot2 */ - VectorMA (ent->owner->s.origin, -ent->chasedist1, forward, spot2); - /* make spot2 a bit higher, by adding viewheight to the Z coordinate */ - spot2[2] += (ent->owner->viewheight + 16); - // jump animation lifts - if (!ent->owner->groundentity) - spot2[2] += 16; - /* make the tr traceline trace from the player model's position, to spot2, - * ignoring the player, with a mask. */ - tr = gi.trace (ent->owner->s.origin, vec3_origin, vec3_origin, spot2, ent->owner, MASK_SOLID); - /* subtract the endpoint from the start point for length and - * direction manipulation */ - VectorSubtract (tr.endpos, ent->owner->s.origin, spot1); - /* in this case, length */ - ent->chasedist1 = VectorLength (spot1); - /* go, starting from the end of the trace, 2 points forward (client - * angles) and save the location in spot2 */ - VectorMA (tr.endpos, 2, forward, spot2); - /* make spot1 the same for tempory vector modification and make spot1 - * a bit higher than spot2 */ - VectorCopy (spot2, spot1); - spot1[2] += 32; - /* another trace from spot2 to spot1, ignoring player, no masks */ - tr = gi.trace (spot2, vec3_origin, vec3_origin, spot1, ent->owner, MASK_SOLID); - /* if we hit something, copy the trace end to spot2 and lower spot2 */ - if (tr.fraction < 1.000) - { - VectorCopy (tr.endpos, spot2); - spot2[2] -= 32; - } - /* subtract endpos spot2 from startpos the camera origin, saving it to - * the dir vector, and normalize dir for a direction from the camera - * origin, to the spot2 */ - VectorSubtract (spot2, ent->s.origin, dir); - distance = VectorLength (dir); - VectorNormalize (dir); - /* another traceline */ - tr = gi.trace (ent->s.origin, vec3_origin, vec3_origin, spot2, ent->owner, MASK_SOLID); - /* if we DON'T hit anyting, do some freaky stuff */ - if (tr.fraction == 1.000) - { - /* subtract the endpos camera position, from the startpos, the - * player, and save in spot1. Normalize spot1 for a direction, and - * make that direction the angles of the chasecam for copying to the - * clients view angle which is displayed to the client. (human) */ - VectorSubtract (ent->s.origin, ent->owner->s.origin, spot1); - VectorNormalize (spot1); - VectorCopy (spot1, ent->s.angles); - /* calculate the percentages of the distances, and make sure we're - * not going too far, or too short, in relation to our panning - * speed of the chasecam entity */ - tot = (distance * 0.400); - /* if we're going too fast, make us top speed */ - if (tot > 5.200) - { - ent->velocity[0] = ((dir[0] * distance) * 5.2); - ent->velocity[1] = ((dir[1] * distance) * 5.2); - ent->velocity[2] = ((dir[2] * distance) * 5.2); - } - else - { - /* if we're NOT going top speed, but we're going faster than - * 1, relative to the total, make us as fast as we're going */ - if (tot > 1.000) - { - ent->velocity[0] = ((dir[0] * distance) * tot); - ent->velocity[1] = ((dir[1] * distance) * tot); - ent->velocity[2] = ((dir[2] * distance) * tot); - } - else - { - /* if we're not going faster than one, don't accelerate our - * speed at all, make us go slow to our destination */ - ent->velocity[0] = (dir[0] * distance); - ent->velocity[1] = (dir[1] * distance); - ent->velocity[2] = (dir[2] * distance); - } - } - /* subtract endpos,player position, from chasecam position to get - * a length to determine whether we should accelerate faster from - * the player or not */ - VectorSubtract (ent->owner->s.origin, ent->s.origin, spot1); - if (VectorLength(spot1) < 20) - { - ent->velocity[0] *= 2; - ent->velocity[1] *= 2; - ent->velocity[2] *= 2; - } - } - /* if we DID hit something in the tr.fraction call ages back, then - * make the spot2 we created, the position for the chasecamera. */ - else - VectorCopy (spot2, ent->s.origin); - /* add to the distance between the player and the camera */ - ent->chasedist1 += 2; - /* if we're too far away, give us a maximum distance */ - if (ent->chasedist1 > (60.00 + ent->owner->client->zoom)) - ent->chasedist1 = (60.00 + ent->owner->client->zoom); - /* if we haven't gone anywhere since the last think routine, and we - * are greater than 20 points in the distance calculated, add one to - * the second chasedistance variable - * The "ent->movedir" is a vector which is not used in this entity, so - * we can use this a tempory vector belonging to the chasecam, which - * can be carried through think routines. */ - if (VectorCompare(ent->movedir, ent->s.origin)) - { - if (distance > 20) - ent->chasedist2++; - } - /* if we've buggered up more than 3 times, there must be some mistake, - * so restart the camera so we re-create a chasecam, destroy the old one, - * slowly go outwards from the player, and keep thinking this routing in - * the new camera entity */ - if (ent->chasedist2 > 3) - { - G_FreeEdict (ent->owner->client->oldplayer); - ChasecamStart (ent->owner); - G_FreeEdict(ent); - return; - } - /* Copy the position of the chasecam now, and stick it to the movedir - * variable, for position checking when we rethink this function */ - VectorCopy (ent->s.origin, ent->movedir); - /* MUST LINK SINCE WE CHANGED THE ORIGIN! */ - gi.linkentity (ent); - //UpdateFakeCrosshair (ent->owner); -} - -void Cmd_Chasecam_Toggle (edict_t *ent) -{ - // Lazarus: Don't allow thirdperson when using spycam - if (!ent->deadflag && !ent->client->spycam) - { - if (ent->client->chasetoggle) - ChasecamRemove (ent, OPTION_OFF); - else - ChasecamStart (ent); - } -} - -void CheckChasecam_Viewent (edict_t *ent) -{ - vec3_t angles; - /* - Oldplayer is the fake player that everyone else sees. - Assign the same client as the ent we're following so the game - can read any vars it wants from there - */ - if (!ent->client->oldplayer->client) - ent->client->oldplayer->client = ent->client; - /* Copy the angle and model from ourselves to the old player. - Even though people can't see us we still have all this stuff */ - if ((ent->client->chasetoggle == 1) && (ent->client->oldplayer)) - { -// Lazarus -// if (ent->client->use) -// VectorCopy (ent->client->oldplayer->s.angles, angles); -// ent->client->oldplayer->s = ent->s; //Copy player related info -// if (ent->client->use) -// VectorCopy (angles, ent->client->oldplayer->s.angles); - - if (ent->client->use && !ent->client->push) - VectorCopy (ent->client->oldplayer->s.angles, angles); - ent->client->oldplayer->s = ent->s; //Copy player related info - // Lazarus: s.numbers shouldn't be the same - ent->client->oldplayer->s.number = ent->client->oldplayer - g_edicts; - if (ent->client->use && !ent->client->push) - VectorCopy (angles, ent->client->oldplayer->s.angles); - ent->client->oldplayer->flags = ent->flags; -// end Lazarus - gi.linkentity (ent->client->oldplayer); - } -} - diff --git a/server/p_client.c b/server/p_client.c index d1c06383..ecf3120c 100644 --- a/server/p_client.c +++ b/server/p_client.c @@ -6,7 +6,6 @@ #define MUD3 0.08 void ClientUserinfoChanged (edict_t *ent, char *userinfo); -void SP_misc_teleporter_dest (edict_t *ent); // // Gross, ugly, disgustuing hack section @@ -112,7 +111,6 @@ void SP_info_player_deathmatch(edict_t *self) G_FreeEdict (self); return; } - SP_misc_teleporter_dest (self); self->class_id = ENTITY_INFO_PLAYER_DEATHMATCH; } @@ -500,29 +498,10 @@ void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damag { int n; - // tpp - if (self->client->chasetoggle) - { - ChasecamRemove (self, OPTION_OFF); - self->client->pers.chasetoggle = 1; - } - else - self->client->pers.chasetoggle = 0; - // end tpp - self->client->pers.spawn_landmark = false; // paranoia check self->client->pers.spawn_levelchange = false; self->client->zooming = 0; self->client->zoomed = false; - SetSensitivities(self,true); - - if(self->client->spycam) - camera_off(self); - - if(self->turret) - turret_disengage(self->turret); - - if(self->client->textdisplay) Text_Close(self); VectorClear (self->avelocity); @@ -615,19 +594,6 @@ void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damag gi.sound (self, CHAN_VOICE, gi.soundindex(va("*death%i.wav", (rand()%4)+1)), 1, ATTN_NORM, 0); } } - -#ifdef JETPACK_MOD - if ( self->client->jetpack ) - { - Jet_BecomeExplosion( self, damage ); - /*stop jetting when dead*/ - self->client->jetpack_framenum = 0; - self->client->jetpack = false; - // DWH: force player to gib - self->health = self->gib_health-1; - } -#endif - self->deadflag = DEAD_DEAD; gi.linkentity (self); @@ -757,10 +723,6 @@ void InitClientPersistant (gclient_t *client, int style) client->pers.fire_mode = 0; // Lazarus alternate fire mode client->pers.connected = true; -// tpp - //Default chasecam to tpp setting - client->pers.chasetoggle = tpp->value; -// end tpp // Lazarus client->zooming = 0; @@ -798,9 +760,6 @@ void SaveClientData (void) ent = &g_edicts[1+i]; if (!ent->inuse) continue; - // tpp - game.clients[i].pers.chasetoggle = ent->client->pers.chasetoggle; - // end tpp game.clients[i].pers.newweapon = ent->client->newweapon; game.clients[i].pers.health = ent->health; game.clients[i].pers.max_health = ent->max_health; @@ -1145,17 +1104,6 @@ void CopyToBodyQue (edict_t *ent) void respawn (edict_t *self) { - // tpp - if (self->crosshair) - G_FreeEdict(self->crosshair); - self->crosshair = NULL; - if (self->client->oldplayer) - G_FreeEdict (self->client->oldplayer); - self->client->oldplayer = NULL; - if (self->client->chasecam) - G_FreeEdict (self->client->chasecam); - self->client->chasecam = NULL; - // end tpp if (deathmatch->value || coop->value) { // spectator's don't leave bodies @@ -1274,6 +1222,7 @@ a deathmatch. */ void PutClientInServer (edict_t *ent) { + gitem_t *newweapon; extern int nostatus; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; @@ -1281,11 +1230,6 @@ void PutClientInServer (edict_t *ent) vec3_t spawn_origin, spawn_angles, spawn_viewangles; gclient_t *client; int i; - // tpp - int chasetoggle; - gitem_t *newweapon; - char userinfo[MAX_INFO_STRING]; - // end tpp bool spawn_landmark; bool spawn_levelchange; int spawn_gunframe; @@ -1304,9 +1248,6 @@ void PutClientInServer (edict_t *ent) index = ent-g_edicts-1; client = ent->client; - // tpp - chasetoggle = client->pers.chasetoggle; - // end tpp newweapon = client->pers.newweapon; spawn_landmark = client->pers.spawn_landmark; spawn_levelchange= client->pers.spawn_levelchange; @@ -1354,11 +1295,6 @@ void PutClientInServer (edict_t *ent) { memset (&resp, 0, sizeof(resp)); } - // tpp - // A bug in Q2 that you couldn't see without thirdpp - memcpy (userinfo, client->pers.userinfo, sizeof(userinfo)); - ClientUserinfoChanged (ent, userinfo); - // end tpp // clear everything but the persistant data saved = client->pers; @@ -1370,9 +1306,6 @@ void PutClientInServer (edict_t *ent) SelectStartWeapon(client,spawn_style); client->resp = resp; - // tpp - client->pers.chasetoggle = chasetoggle; - // end tpp client->pers.newweapon = newweapon; // copy some data from the client to the entity @@ -1402,11 +1335,6 @@ void PutClientInServer (edict_t *ent) ent->watertype = 0; ent->flags &= ~FL_NO_KNOCKBACK; ent->svflags &= ~SVF_DEADMONSTER; - // tpp - ent->svflags &= ~SVF_NOCLIENT; - // turn on prediction - ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - // end tpp ent->client->spycam = NULL; ent->client->camplayer = NULL; @@ -1478,20 +1406,7 @@ void PutClientInServer (edict_t *ent) VectorCopy(ent->s.angles, client->ps.viewangles); VectorCopy (client->ps.viewangles, client->v_angle); - // spawn a spectator - if (client->pers.spectator) { - client->chase_target = NULL; - - client->resp.spectator = true; - - ent->movetype = MOVETYPE_NOCLIP; - ent->solid = SOLID_NOT; - ent->svflags |= SVF_NOCLIENT; - ent->client->ps.gunindex = 0; - gi.linkentity (ent); - return; - } else - client->resp.spectator = false; + client->resp.spectator = false; // DWH: client->flashlight = false; @@ -1504,14 +1419,7 @@ void PutClientInServer (edict_t *ent) gi.linkentity (ent); - // tpp - client->chasetoggle = 0; - // If chasetoggle set then turn on (delayed start of 5 frames - 0.5s) - if(client->pers.chasetoggle) - client->delayedstart = 5; - // end tpp - - if(spawn_levelchange && !client->pers.chasetoggle && !client->pers.newweapon) + if(spawn_levelchange && !client->pers.newweapon) { // we already had a weapon when the level changed... no need to bring it up int i; @@ -1600,8 +1508,6 @@ void ClientBegin (edict_t *ent) return; } - Fog_Off(); - stuffcmd(ent,"alias +zoomin zoomin;alias -zoomin zoominstop\n"); stuffcmd(ent,"alias +zoomout zoomout;alias -zoomout zoomoutstop\n"); stuffcmd(ent,"alias +zoom zoomon;alias -zoom zoomoff\n"); @@ -1646,35 +1552,6 @@ void ClientBegin (edict_t *ent) } } - // DWH - SetSensitivities(ent,true); - - if (game.maxclients == 1) - { - // For SP games, check for monsters who were mad at player - // in previous level and have changed levels with the player - edict_t *monster; - for(i=2; iinuse) - continue; - if(!(monster->svflags & SVF_MONSTER)) - continue; - if(monster->health <= 0) - continue; - if(monster->monsterinfo.aiflags & AI_RESPAWN_FINDPLAYER) - { - monster->monsterinfo.aiflags &= ~AI_RESPAWN_FINDPLAYER; - if(!monster->enemy) - { - monster->enemy = ent; - FoundTarget(monster); - } - } - } - } - // make sure all view stuff is valid ClientEndServerFrame (ent); } @@ -1845,19 +1722,11 @@ void ClientDisconnect (edict_t *ent) if (!ent->client) return; - // tpp - if(ent->client->chasetoggle) - ChasecamRemove(ent,OPTION_OFF); - // end tpp - // DWH ent->client->zooming = 0; ent->client->zoomed = false; - SetSensitivities(ent,true); // end DWH - if(ent->client->textdisplay) Text_Close(ent); - gi.bprintf (PRINT_HIGH, "%s disconnected\n", ent->client->pers.netname); // send effect @@ -1873,9 +1742,6 @@ void ClientDisconnect (edict_t *ent) ent->classname = "disconnected"; ent->client->pers.connected = false; - if(ent->client->spycam) - camera_off(ent); - playernum = ent-g_edicts-1; gi.configstring (CS_PLAYERSKINS+playernum, ""); @@ -1945,10 +1811,6 @@ void RemovePush(edict_t *ent) ent->client->push->activator = NULL; ent->client->push = NULL; ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - // If tpp is NOT always on, and auto-switch for func_pushables IS on, - // and we're currently in third-person view, switch it off - if(!tpp->value && tpp_auto->value && ent->client->chasetoggle) - Cmd_Chasecam_Toggle(ent); } void ClientPushPushable(edict_t *ent) @@ -1972,9 +1834,8 @@ void ClientPushPushable(edict_t *ent) } else if(dist > 0) { - if(!box->speaker) - box->s.sound = box->noise_index; - box_walkmove( box, vectoyaw(v), dist ); + if(!box->speaker) box->s.sound = box->noise_index; + //box_walkmove( box, vectoyaw(v), dist ); } else box->s.sound = 0; @@ -1982,339 +1843,6 @@ void ClientPushPushable(edict_t *ent) else RemovePush(ent); } - -void ClientSpycam(edict_t *ent) -{ - gclient_t *client = ent->client; - edict_t *camera = ent->client->spycam; - pmove_t pm; - bool is_actor; - trace_t tr; - vec3_t forward, left, up; - vec3_t dir, start; - float dist; - int i; - - memset (&pm, 0, sizeof(pm)); - if(client->ucmd.sidemove && level.time > ent->last_move_time + 1) - { - camera->flags &= ~FL_ROBOT; - if(camera->viewer == ent) - camera->viewer = NULL; - if(client->ucmd.sidemove > 0) - camera = G_FindNextCamera(camera,client->monitor); - else - camera = G_FindPrevCamera(camera,client->monitor); - - if(camera) - { - if(!camera->viewer) - camera->viewer = ent; - client->spycam = camera; - VectorAdd(camera->s.origin,camera->move_origin,ent->s.origin); - if(camera->viewmessage) - gi.centerprintf(ent,camera->viewmessage); - ent->last_move_time = level.time; - } - else - camera = client->spycam; - if(camera->monsterinfo.aiflags & AI_ACTOR) - { - camera->flags |= FL_ROBOT; - if(camera->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - camera->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; - camera->monsterinfo.old_leader = NULL; - camera->monsterinfo.leader = NULL; - camera->movetarget = camera->goalentity = NULL; - camera->monsterinfo.stand(camera); - } - } - } - if((camera->svflags & SVF_MONSTER) && (camera->monsterinfo.aiflags & AI_ACTOR)) - is_actor = true; - else - is_actor = false; - if(camera->enemy && (camera->enemy->deadflag || !camera->enemy->inuse)) - camera->enemy = NULL; - AngleVectors(camera->s.angles,forward,left,up); - - if(is_actor && !camera->enemy) - { - if((abs(client->ucmd.forwardmove) > 199) && (camera->groundentity)) - { - // walk/run - - edict_t *thing; - vec3_t end; - float dist; - - thing = camera->vehicle; - - VectorMA(camera->s.origin,8192,forward,end); - tr = gi.trace(camera->s.origin,camera->mins,camera->maxs,end,camera,MASK_SOLID); - if(client->ucmd.forwardmove < 0) - { - trace_t back; - VectorMA(camera->s.origin,-8192,forward,end); - back = gi.trace(camera->s.origin,camera->mins,camera->maxs,end,camera,MASK_SOLID); - VectorSubtract(back.endpos,camera->s.origin,end); - dist = VectorLength(end); - VectorCopy(tr.endpos,end); - } - else - { - VectorSubtract(tr.endpos,camera->s.origin,end); - dist = VectorLength(end) - 8; - VectorMA(camera->s.origin,dist,forward,end); - } - if(dist > 8) - { - if(!thing || !thing->inuse || (thing->class_id != ENTITY_THING)) - thing = camera->vehicle = SpawnThing(); - thing->touch_debounce_time = level.time + 5.0; - thing->target_ent = camera; - VectorCopy(end,thing->s.origin); - ED_CallSpawn(thing); - camera->monsterinfo.aiflags |= AI_CHASE_THING; - camera->monsterinfo.aiflags &= ~(AI_CHICKEN | AI_STAND_GROUND); - camera->monsterinfo.pausetime = 0; - camera->movetarget = camera->goalentity = thing; - camera->monsterinfo.old_leader = NULL; - camera->monsterinfo.leader = thing; - VectorSubtract (thing->s.origin, camera->s.origin, dir); - camera->ideal_yaw = vectoyaw(dir); - if(client->ucmd.forwardmove > 300) - actor_run(camera); - else if(client->ucmd.forwardmove > 199) - actor_walk(camera); - else if(client->ucmd.forwardmove < -300) - actor_run_back(camera); - else - actor_walk_back(camera); - } - else if(thing) - { - camera->monsterinfo.aiflags &= ~AI_CHASE_THING; - camera->movetarget = camera->goalentity = NULL; - G_FreeEdict(thing); - camera->vehicle = NULL; - actor_stand(camera); - } - } - if((client->ucmd.forwardmove == 0) && (camera->groundentity)) - { - // stop - edict_t *thing = camera->vehicle; - if(thing) - { - camera->monsterinfo.aiflags &= ~AI_CHASE_THING; - camera->movetarget = camera->goalentity = NULL; - G_FreeEdict(thing); - camera->vehicle = NULL; - actor_stand(camera); - } - } - - if(client->ucmd.upmove) - { - if((client->ucmd.upmove > 0) && camera->groundentity && !camera->waterlevel) - { - // jump - if(client->ucmd.forwardmove > 300) - VectorScale(forward,400,camera->velocity); - else if(client->ucmd.forwardmove > 199) - VectorScale(forward,200,camera->velocity); - else if(client->ucmd.forwardmove < -300) - VectorScale(forward,-400,camera->velocity); - else if(client->ucmd.forwardmove < -199) - VectorScale(forward,-200,camera->velocity); - camera->velocity[2] = 250; - camera->monsterinfo.savemove = camera->monsterinfo.currentmove; - actor_jump(camera); - camera->groundentity = NULL; - } - else if((client->ucmd.upmove < 0) && (camera->groundentity) && !(camera->monsterinfo.aiflags & AI_CROUCH)) - { - // crouch - if( (camera->monsterinfo.currentmove == &actor_move_walk) || - (camera->monsterinfo.currentmove == &actor_move_run) || - (camera->monsterinfo.currentmove == &actor_move_run_bad) ) - { - camera->monsterinfo.currentmove = &actor_move_crouchwalk; - camera->maxs[2] -= 28; - camera->viewheight -= 28; - camera->move_origin[2] -= 28; - camera->monsterinfo.aiflags |= AI_CROUCH; - } - else if( (camera->monsterinfo.currentmove == &actor_move_walk_back) || - (camera->monsterinfo.currentmove == &actor_move_run_back) ) - { - camera->monsterinfo.currentmove = &actor_move_crouchwalk_back; - camera->maxs[2] -= 28; - camera->viewheight -= 28; - camera->move_origin[2] -= 28; - camera->monsterinfo.aiflags |= AI_CROUCH; - } - else if (camera->monsterinfo.currentmove == &actor_move_stand) - { - camera->monsterinfo.currentmove = &actor_move_crouch; - camera->maxs[2] -= 28; - camera->viewheight -= 28; - camera->move_origin[2] -= 28; - camera->monsterinfo.aiflags |= AI_CROUCH; - } - } - } - if( (client->ucmd.upmove >= 0) && (camera->monsterinfo.aiflags & AI_CROUCH)) - { - // come out of crouch - camera->maxs[2] += 28; - camera->viewheight += 28; - camera->move_origin[2] += 28; - camera->monsterinfo.aiflags &= ~AI_CROUCH; - if(camera->monsterinfo.currentmove == &actor_move_crouchwalk) - actor_walk(camera); - else if(camera->monsterinfo.currentmove == &actor_move_crouchwalk_back) - actor_walk_back(camera); - else if(camera->monsterinfo.currentmove == &actor_move_crouch) - actor_stand(camera); - } - } - - client->ps.pmove.pm_type = PM_FREEZE; - if(camera->viewer == ent) { - if( (client->old_owner_angles[0] != client->ucmd.angles[0]) || - (client->old_owner_angles[1] != client->ucmd.angles[1]) ) - { - // Give game a bit of time to catch up after player - // causes ucmd pitch angle to roll over... otherwise - // we'll hit on the above test even though player - // hasn't hit +lookup/+lookdown - float delta; - delta = level.time - camera->touch_debounce_time; - if( delta < 0 || delta > 1.0) - { - if(is_actor) - { - float diff; - diff = SHORT2ANGLE(client->ucmd.angles[1] - client->old_owner_angles[1]); - if(diff < -180) - diff += 360; - if(diff > 180) - diff -= 360; - camera->ideal_yaw += diff; - if((abs(diff) > 100) && camera->vehicle) - { - vec3_t angles; - vec3_t end, f; - VectorSet(angles,0,camera->ideal_yaw,0); - AngleVectors(angles,f,NULL,NULL); - VectorMA(camera->s.origin,8192,f,end); - tr = gi.trace(camera->s.origin,camera->mins,camera->maxs,end,camera,MASK_SOLID); - VectorCopy(tr.endpos,camera->vehicle->s.origin); - camera->vehicle->touch_debounce_time = level.time + 5.0; - gi.linkentity(camera->vehicle); - } - ai_turn(camera,0.); - diff = SHORT2ANGLE(client->ucmd.angles[0]-client->old_owner_angles[0]); - if(diff < -180) - diff += 360; - if(diff > 180) - diff -= 360; - camera->move_angles[0] += diff; - client->old_owner_angles[0] = client->ucmd.angles[0]; - client->old_owner_angles[1] = client->ucmd.angles[1]; - } - } - } - if ( client->ucmd.buttons & BUTTON_ATTACK && camera->sounds >= 0 ) { - if (level.time >= camera->monsterinfo.attack_finished) { - client->latched_buttons &= ~BUTTON_ATTACK; - if(camera->class_id == ENTITY_TURRET_BREACH) - { - if(camera->sounds==5 || camera->sounds==6) - camera->monsterinfo.attack_finished = level.time; - else - camera->monsterinfo.attack_finished = level.time + 1.0; - turret_breach_fire(camera); - } - else if(is_actor) - { - int weapon = camera->actor_weapon[camera->actor_current_weapon]; - if(!camera->enemy) - { - edict_t *target; - target = LookingAt(ent,0,NULL,NULL); - if(target && target->takedamage && (target != client->camplayer)) - { - if(camera->vehicle) - { - // Currently following "thing" - turn that off - camera->monsterinfo.aiflags &= ~AI_CHASE_THING; - camera->movetarget = camera->goalentity = NULL; - G_FreeEdict(camera->vehicle); - camera->vehicle = NULL; - } - camera->enemy = target; - actor_fire(camera); - camera->enemy = NULL; - if(camera->monsterinfo.aiflags & AI_HOLD_FRAME) - camera->monsterinfo.attack_finished = level.time + FRAMETIME; - else - camera->monsterinfo.attack_finished = level.time + 1.0; - } - } - } - } - } - if(client->zoomed) { - camera->touch_debounce_time = - max(camera->touch_debounce_time, level.time + 1.0); - } - } - - VectorMA(camera->s.origin, camera->move_origin[0],forward,start); - VectorMA(start, -camera->move_origin[1],left, start); - VectorMA(start, camera->move_origin[2],up, start); - - tr = gi.trace(camera->s.origin, NULL, NULL, start, camera, MASK_SOLID); - if(tr.fraction < 1.0) - { - VectorSubtract(tr.endpos,camera->s.origin,dir); - dist = VectorNormalize(dir) - 2; - if(dist < 0) dist = 0.; - VectorMA(camera->s.origin,dist,dir,start); - } - VectorCopy(start,ent->s.origin); - VectorCopy(camera->velocity,ent->velocity); - - client->resp.cmd_angles[0] = SHORT2ANGLE(client->ucmd.angles[0]); - client->resp.cmd_angles[1] = SHORT2ANGLE(client->ucmd.angles[1]); - client->resp.cmd_angles[2] = SHORT2ANGLE(client->ucmd.angles[2]); - - memset (&pm, 0, sizeof(pm)); - pm.s = client->ps.pmove; - for (i=0 ; i<3 ; i++) { - pm.s.origin[i] = ent->s.origin[i]*8; - client->ps.pmove.delta_angles[i] = - ANGLE2SHORT(client->ps.viewangles[i] - client->resp.cmd_angles[i]); - } - if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s))) - pm.snapinitial = true; - pm.cmd = client->ucmd; - pm.trace = PM_trace; // adds default parms - pm.pointcontents = gi.pointcontents; - - gi.Pmove (&pm); - - gi.linkentity (ent); -// client->old_owner_angles[0] = client->ucmd.angles[0]; -// client->old_owner_angles[1] = client->ucmd.angles[1]; - - G_TouchTriggers (ent); // we'll only allow touching trigger_look with "Cam Owner" SF - -} /* ============== ClientThink @@ -2353,8 +1881,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) if( (ent->in_mud) || (ent->client->push) || (ent->vehicle) || - (ent->client->chasetoggle) || - (ent->turret) || (ent->client->spycam) || (ground_speed > 0) ) ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; @@ -2373,101 +1899,11 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) } VectorCopy(ent->s.origin,view); view[2] += ent->viewheight; - Fog(view); - -// MUD - get mud level - if(level.mud_puddles) - { - edict_t *mud; - - ent->in_mud = 0; - for(i=game.maxclients+1; iin_mud; i++) - { - mud = &g_edicts[i]; - if(!mud->inuse) continue; - if(!(mud->svflags & SVF_MUD)) continue; - if(ent->absmin[0] > mud->absmax[0]) continue; - if(ent->absmin[1] > mud->absmax[1]) continue; - if(ent->absmin[2] > mud->absmax[2]) continue; - if(ent->absmax[0] < mud->absmin[0]) continue; - if(ent->absmax[1] < mud->absmin[1]) continue; - if(ent->absmax[2] < mud->absmin[2]) continue; - ent->in_mud = 1; - if(ent->s.origin[2] < mud->absmax[2]) - ent->in_mud = 2; - if(ent->s.origin[2] + ent->viewheight < mud->absmax[2]) - ent->in_mud = 3; - } - } - -// USE - special actions taken when +use is pressed - if(!client->use && (ucmd->buttons & BUTTON_USE)) - { - // use key was NOT pressed, but now is - client->use = 1; - if(client->spycam) - camera_off(ent); - else - { - edict_t *viewing; - vec3_t intersect; - float range; - - viewing = LookingAt(ent,0,intersect,&range); - if(viewing && viewing->classname) - { - if(viewing->class_id == ENTITY_CRANE_CONTROL) - crane_control_action(viewing,ent,intersect); - if(viewing->class_id == ENTITY_TARGET_LOCK_DIGIT) - lock_digit_increment(viewing,ent); - if((viewing->class_id == ENTITY_FUNC_TRAINBUTTON) && (viewing->spawnflags & 1)) - trainbutton_use(viewing,ent,ent); - if((viewing->class_id == ENTITY_FUNC_MONITOR) && (range <= 100)) { - use_camera(viewing,ent,ent); - if(client->spycam && client->spycam->viewer == ent) { - client->old_owner_angles[0] = ucmd->angles[0]; - client->old_owner_angles[1] = ucmd->angles[1]; - } - } - if(viewing->monsterinfo.aiflags & AI_ACTOR) - { - if(viewing->monsterinfo.aiflags & AI_FOLLOW_LEADER) - { - viewing->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER; - viewing->monsterinfo.old_leader = NULL; - viewing->monsterinfo.leader = NULL; - viewing->movetarget = viewing->goalentity = NULL; - viewing->monsterinfo.stand(viewing); - } - else - { - vec3_t dir; - viewing->monsterinfo.aiflags |= AI_FOLLOW_LEADER; - viewing->monsterinfo.leader = ent; - VectorSubtract(ent->s.origin,viewing->s.origin,dir); - viewing->ideal_yaw = vectoyaw(dir); - if(fabs(viewing->s.angles[YAW] - viewing->ideal_yaw) < 90) - actor_salute(viewing); - } - } - } - } - } - - if(ucmd->buttons & BUTTON_USE) - client->use = 1; - else - client->use = 0; if( client->push ) { // currently pushing or pulling a func_pushable - if( !client->use ) - { - // whoops - released USE key - RemovePush(ent); - } - else if( (!ent->groundentity) && (ent->waterlevel==0 || client->push->waterlevel == 0 ) ) + if( (!ent->groundentity) && (ent->waterlevel==0 || client->push->waterlevel == 0 ) ) { // oops, we fall down RemovePush(ent); @@ -2485,19 +1921,9 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) } } - if(ent->turret && ucmd->upmove > 10) - turret_disengage(ent->turret); - -// INTERMISSION + // INTERMISSION if (level.intermissiontime) { - // tpp - if (client->chasetoggle) - ChasecamRemove (ent, OPTION_OFF); - // end tpp - // Lazarus spycam - if (client->spycam) - camera_off(ent); client->ps.pmove.pm_type = PM_FREEZE; // can exit intermission after five seconds if (level.time > level.intermissiontime + 5.0 @@ -2530,35 +1956,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) return; } -// THIRDPERSON VIEW in/out -// if NOT pushing something AND in third person AND use key is pressed, -// move viewpoint in/out - if(client->chasetoggle && !client->push) { - if ((ucmd->buttons & BUTTON_USE) && (!deathmatch->value)) - { - client->use = 1; - if ((ucmd->forwardmove < 0) && (client->zoom < 100)) - client->zoom++; - else if ((ucmd->forwardmove > 0) && (client->zoom > -40)) - client->zoom--; - ucmd->forwardmove = 0; - ucmd->sidemove = 0; - } - else if (client->use) - { - //client->zoom = 0; - if (client->oldplayer) - { - // set angles - for (i=0 ; i<3 ; i++) - { - ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->client->oldplayer->s.angles[i] - ent->client->resp.cmd_angles[i]); - } - } - client->use = 0; - } - } - // ZOOM if (client->zooming) { client->pers.hand = 2; @@ -2586,117 +1983,25 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) } } -// SPYCAM - if (client->spycam) { - ClientSpycam(ent); - return; // no movement while in cam - } // END SPYCAM - pm_passent = ent; - // Lazarus: developer item movement - if(client->use && client->shift_dir) - ShiftItem(ent, client->shift_dir); + // set up for pmove + memset (&pm, 0, sizeof(pm)); - if (client->chase_target) { + if (ent->movetype == MOVETYPE_NOCLIP) + client->ps.pmove.pm_type = PM_SPECTATOR; + else if (ent->s.modelindex != MAX_MODELS-1) + client->ps.pmove.pm_type = PM_GIB; + else if (ent->deadflag) + client->ps.pmove.pm_type = PM_DEAD; + else + client->ps.pmove.pm_type = PM_NORMAL; + if(level.time > ent->gravity_debounce_time) + client->ps.pmove.gravity = sv_gravity->value; + else + client->ps.pmove.gravity = 0; - client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); - client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); - client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); - - } else { - - // set up for pmove - memset (&pm, 0, sizeof(pm)); - - if (ent->movetype == MOVETYPE_NOCLIP) - client->ps.pmove.pm_type = PM_SPECTATOR; - else if (ent->s.modelindex != MAX_MODELS-1) - client->ps.pmove.pm_type = PM_GIB; - else if (ent->deadflag) - client->ps.pmove.pm_type = PM_DEAD; - else - client->ps.pmove.pm_type = PM_NORMAL; - - if(level.time > ent->gravity_debounce_time) - client->ps.pmove.gravity = sv_gravity->value; - else - client->ps.pmove.gravity = 0; - -#ifdef JETPACK_MOD - if ( client->jetpack ) - { - if( (ucmd->upmove != 0) || (ucmd->forwardmove != 0) || (ucmd->sidemove != 0) ) - { - if(ucmd->upmove > 0 || !ent->groundentity) - { - if(!client->jetpack_thrusting) - { - gi.sound (ent, CHAN_AUTO, gi.soundindex("jetpack/rev.wav"), 1, ATTN_NORM, 0); - client->jetpack_start_thrust = level.framenum; - } - client->jetpack_thrusting = true; - } - else - client->jetpack_thrusting = false; - } - else - client->jetpack_thrusting = false; - - if(client->jetpack_framenum + client->pers.inventory[fuel_index] > level.framenum) - { - if(jetpack_weenie->value) - { - Jet_ApplyJet( ent, ucmd ); - if(client->jetpack_framenum < level.framenum) - { - if(!client->jetpack_infinite) - client->pers.inventory[fuel_index] -= 10; - client->jetpack_framenum = level.framenum + 10; - } - } - else - { - if(client->jetpack_thrusting) - Jet_ApplyJet( ent, ucmd ); - if(client->jetpack_framenum <= level.framenum) - { - if(client->jetpack_thrusting) - { - if(!client->jetpack_infinite) - client->pers.inventory[fuel_index] -= 11; - client->jetpack_framenum = level.framenum + 10; - } - else - { - if(!client->jetpack_infinite) - client->pers.inventory[fuel_index]--; - client->jetpack_framenum = level.framenum + 10; - } - } - if(ucmd->upmove == 0) - { - // accelerate to 75% gravity in 2 seconds - float gravity; - float g_max = 0.75 * sv_gravity->value; - - gravity = g_max * (level.framenum - client->jetpack_last_thrust)/20; - if(gravity > g_max) gravity = g_max; - client->ps.pmove.gravity = (short)gravity; - } - else - client->jetpack_last_thrust = level.framenum; - } - } - else - { - client->jetpack = false; - ent->s.frame = FRAME_jump2; // reset from stand to avoid goofiness - } - } -#endif // #ifdef JETPACK_MOD - - pm.s = client->ps.pmove; + pm.s = client->ps.pmove; for (i=0 ; i<3 ; i++) { @@ -2737,15 +2042,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); -#ifdef JETPACK_MOD - if ( client->jetpack && jetpack_weenie->value ) - { - if( pm.groundentity ) // are we on ground - if ( Jet_AvoidGround(ent) ) // then lift us if possible - pm.groundentity = NULL; // now we are no longer on ground - } -#endif - // MUD - "correct" Pmove physics if(pm.waterlevel && ent->in_mud) { @@ -2821,7 +2117,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) ent->in_mud = 0; // end MUD - if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0) && !client->jetpack) + if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0)) { gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0); PlayerNoise(ent, ent->s.origin, PNOISE_SELF); @@ -2866,11 +2162,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) VectorCopy (pm.viewangles, client->ps.viewangles); } -#ifdef JETPACK_MOD - if ( client->jetpack && !(ucmd->buttons & BUTTONS_ATTACK)) - ent->s.frame = FRAME_stand20; -#endif - gi.linkentity (ent); if (ent->movetype != MOVETYPE_NOCLIP) @@ -2896,7 +2187,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) other->touch (other, ent, NULL, NULL); } } - } client->oldbuttons = client->buttons; client->buttons = ucmd->buttons; @@ -2913,12 +2203,6 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) client->latched_buttons = 0; - if (client->chase_target) { - client->chase_target = NULL; - client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; - } else - GetChaseTarget(ent); - } else if (!client->weapon_thunk) { client->weapon_thunk = true; Think_Weapon (ent); @@ -2929,29 +2213,14 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd) if (ucmd->upmove >= 10) { if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) { client->ps.pmove.pm_flags |= PMF_JUMP_HELD; - if (client->chase_target) - ChaseNext(ent); - else - GetChaseTarget(ent); } } else client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; } - // update chase cam if being followed - for (i = 1; i <= maxclients->value; i++) { - other = g_edicts + i; - if (other->inuse && other->client->chase_target == ent) - UpdateChaseCam(other); - } - if(client->push != NULL) { - if(client->use && - ( (ucmd->forwardmove != 0) || (ucmd->sidemove != 0) ) ) - ClientPushPushable(ent); - else - client->push->s.sound = 0; + client->push->s.sound = 0; } } @@ -2979,13 +2248,6 @@ void ClientBeginServerFrame (edict_t *ent) if(client->spycam) client = client->camplayer->client; - // tpp - if (client->delayedstart > 0) - client->delayedstart--; - if (client->delayedstart == 1) - ChasecamStart (ent); - // end tpp - if (deathmatch->value && client->pers.spectator != client->resp.spectator && (level.time - client->respawn_time) >= 5) { @@ -3004,18 +2266,6 @@ void ClientBeginServerFrame (edict_t *ent) // wait for any button just going down if ( level.time > client->respawn_time) { - // tpp - if (ent->crosshair) - G_FreeEdict(ent->crosshair); - ent->crosshair = NULL; - if (ent->client->oldplayer) - G_FreeEdict (ent->client->oldplayer); - ent->client->oldplayer = NULL; - if (ent->client->chasecam) - G_FreeEdict (ent->client->chasecam); - ent->client->chasecam = NULL; - // end tpp - // in deathmatch, only wait for attack button if (deathmatch->value) buttonMask = BUTTONS_ATTACK; @@ -3031,13 +2281,6 @@ void ClientBeginServerFrame (edict_t *ent) } return; } - - // add player trail so monsters can follow - // Lazarus: Don't add player trail for players in camera or notarget players - if (!deathmatch->value && !client->spycam && !(ent->flags & FL_NOTARGET)) - if (!visible (ent, PlayerTrail_LastSpot() ) ) - PlayerTrail_Add (ent->s.old_origin); - client->latched_buttons = 0; } diff --git a/server/p_hud.c b/server/p_hud.c index 02fb8539..ee687083 100644 --- a/server/p_hud.c +++ b/server/p_hud.c @@ -1,14 +1,5 @@ #include "g_local.h" -#ifdef WESQ2 -int gNumTargets; -int gNumCharges; -float gTargetSpacing; -vec3_t gWorld; -PRESSURE_TEMP *PT; -EXPLOSIVE *TNT; -#endif - /* ====================================================================== @@ -46,10 +37,6 @@ void MoveClientToIntermission (edict_t *ent) ent->s.sound = 0; ent->solid = SOLID_NOT; -#ifdef JETPACK_MOD - ent->client->jetpack_framenum = 0; -#endif - // add the layout if (deathmatch->value || coop->value) @@ -268,9 +255,6 @@ void Cmd_Score_f (edict_t *ent) if (ent->client->menu) PMenu_Close(ent); - if (ent->client->textdisplay) - Text_Close(ent); - if (!deathmatch->value && !coop->value) return; @@ -437,53 +421,6 @@ G_SetStats extern void WhatsIt(edict_t *ent); void G_SetStats (edict_t *ent) { - -#ifdef WESQ2 - int i; - int N; - float dist, dx, dy, dz; - float DSum, P, T; - - if(gNumTargets) { - N = 0; - DSum = 0; - for(i=0; is.origin[0] - PT[i].loc[0]); if(dx > gTargetSpacing) continue; - dy = fabs(ent->s.origin[1] - PT[i].loc[1]); if(dy > gTargetSpacing) continue; - dz = fabs(ent->s.origin[2] - PT[i].loc[2]); if(dz > gTargetSpacing) continue; - dist = sqrt( dx*dx + dy*dy + dz*dz ); - if(dist > gTargetSpacing) continue; - DSum += dist; - P = PT[i].pressure; // only holds if only 1 target found - T = PT[i].temperature; - N++; - } - if(N > 1) { - P = 0; T = 0; - for(i=0; is.origin[0] - PT[i].loc[0]); if(dx > gTargetSpacing) continue; - dy = fabs(ent->s.origin[1] - PT[i].loc[1]); if(dy > gTargetSpacing) continue; - dz = fabs(ent->s.origin[2] - PT[i].loc[2]); if(dz > gTargetSpacing) continue; - dist = sqrt( dx*dx + dy*dy + dz*dz ); - if(dist > gTargetSpacing) continue; - P += PT[i].pressure * (DSum - dist)/DSum; - T += PT[i].temperature * (DSum - dist)/DSum; - } - } - if(N) { - ent->client->ps.stats[STAT_PRESSURE_ICON] = gi.imageindex("i_press"); - ent->client->ps.stats[STAT_PRESSURE] = (int)(P*10+5)/10; - ent->client->ps.stats[STAT_TEMPERATURE_ICON] = gi.imageindex("i_temp"); - ent->client->ps.stats[STAT_TEMPERATURE] = (int)(T*10+5)/10; - } - else { - ent->client->ps.stats[STAT_PRESSURE_ICON] = 0; - ent->client->ps.stats[STAT_TEMPERATURE_ICON] = 0; - } - } - -#else - gitem_t *item; int index, cells; int power_armor_type; @@ -574,16 +511,6 @@ void G_SetStats (edict_t *ent) ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_rebreather"); ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum)/10; } -#ifdef JETPACK_MOD - else if ( (ent->client->jetpack) && - (!ent->client->jetpack_infinite) && - (ent->client->pers.inventory[fuel_index] >= 0) && - (ent->client->pers.inventory[fuel_index] < 100000)) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_jet"); - ent->client->ps.stats[STAT_TIMER] = ent->client->pers.inventory[fuel_index]; - } -#endif else if (level.freeze) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_freeze"); @@ -605,8 +532,6 @@ void G_SetStats (edict_t *ent) ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item; -#endif - // Lazarus vehicle/tracktrain if(ent->vehicle && !(ent->vehicle->spawnflags & 16)) { @@ -665,8 +590,6 @@ void G_SetStats (edict_t *ent) if(!ent->client->ps.stats[STAT_LAYOUTS] && ent->client->whatsit) ent->client->ps.stats[STAT_LAYOUTS] |= 1; -#ifndef WESQ2 - // // frags // @@ -689,26 +612,6 @@ void G_SetStats (edict_t *ent) ent->client->ps.stats[STAT_ZOOM] = gi.imageindex("zoom"); else ent->client->ps.stats[STAT_ZOOM] = 0; -#endif -} - -/* -=============== -G_CheckChaseStats -=============== -*/ -void G_CheckChaseStats (edict_t *ent) -{ - int i; - gclient_t *cl; - - for (i = 1; i <= maxclients->value; i++) { - cl = g_edicts[i].client; - if (!g_edicts[i].inuse || cl->chase_target != ent) - continue; - memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats)); - G_SetSpectatorStats(g_edicts + i); - } } /* @@ -720,8 +623,7 @@ void G_SetSpectatorStats (edict_t *ent) { gclient_t *cl = ent->client; - if (!cl->chase_target) - G_SetStats (ent); + G_SetStats (ent); cl->ps.stats[STAT_SPECTATOR] = 1; @@ -732,10 +634,6 @@ void G_SetSpectatorStats (edict_t *ent) if (cl->showinventory && cl->pers.health > 0) cl->ps.stats[STAT_LAYOUTS] |= 2; - if (cl->chase_target && cl->chase_target->inuse) - cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS + - (cl->chase_target - g_edicts) - 1; - else - cl->ps.stats[STAT_CHASE] = 0; + cl->ps.stats[STAT_CHASE] = 0; } diff --git a/server/p_text.c b/server/p_text.c deleted file mode 100644 index ea904f39..00000000 --- a/server/p_text.c +++ /dev/null @@ -1,628 +0,0 @@ -#include "g_local.h" -#include "pak.h" - -#define MAX_LINES 24 -#define MAX_LINE_LENGTH 35 - -text_t text[MAX_LINES]; - -void Text_Open(edict_t *ent) -{ - if (!ent->client) - return; - ent->client->showscores = true; - ent->client->inmenu = true; - ent->client->textdisplay->last_update = 0; - Text_Update(ent); -} - -void Text_Close(edict_t *ent) -{ - if(!ent->client) return; - if(!ent->client->textdisplay) return; - if(ent->client->textdisplay->buffer) - { - free(ent->client->textdisplay->buffer); - ent->client->textdisplay->buffer = NULL; - } - free(ent->client->textdisplay); - ent->client->textdisplay = NULL; - ent->client->showscores = false; -} - -void Text_BuildDisplay(texthnd_t *hnd) -{ - int i, imax, n; - char *p1, *p2, *p3; - - for(i=0; ipage_length+2; i++) - text[i].text = NULL; - - if(!(hnd->flags & 2)) - { - text[hnd->page_length+1].text = "Esc to quit"; - if(hnd->nlines > hnd->page_length) - text[hnd->page_length].text = "Use [ and ] to scroll"; - } - - p1 = hnd->buffer+hnd->start_char; - p3 = hnd->buffer+hnd->size-1; - if(hnd->curline > 0) - { - // Scan for hnd->curline'th 0 byte, point to following character - n = hnd->curline; - while(p1 < p3 && n) - { - if(*p1==0) n--; - p1++; - } - } - - i = 0; - p2 = p1; - text[i].text = p2; - if(hnd->nlines > hnd->page_length) - imax = hnd->page_length-2; - else - imax = hnd->page_length-1; - while(p2 <= p3 && i < imax) - { - if(*p2 == 0 && p2 < p3) - { - i++; - p2++; - text[i].text = p2; - } - else - p2++; - } -} - -void Text_Update(edict_t *ent) -{ - int align; - int i; - int x0, y0; - text_t *p; - int x, xlast; - char *t, *tnext; - bool alt = false; - char string[2048]; - texthnd_t *hnd; - - - if (!ent->client->textdisplay) { - gi.dprintf("warning: ent has no text display\n"); - return; - } - - hnd = ent->client->textdisplay; - if(hnd->last_update + 2*FRAMETIME > level.time) return; - hnd->last_update = level.time; - - - x0 = (35 - hnd->page_width)*4; - y0 = (22 - hnd->page_length)*4; - - if(!(hnd->flags & 2)) - { - sprintf(string,"xv %d yv %d picn %s ", - x0, y0, hnd->background_image); - } - xlast = 9999; - for (i = 0, p = hnd->lines; i < hnd->page_length+2; i++, p++) { - if (!p->text || !*(p->text)) - continue; // blank line - t = p->text; - if (*t == '*') { - alt = true; - t++; - } - align = TEXT_LEFT; - if (*t == '\\') - { - tnext = t; - tnext++; - if(*tnext == 'c') - { - align = TEXT_CENTER; - t++; - t++; - } - if (*tnext == 'r') - { - align = TEXT_RIGHT; - t++; - t++; - } - } - if(strlen(t)) - { - sprintf(string + strlen(string), "yv %d ", y0 + 24 + i * 8); - if (align == TEXT_CENTER) - x = x0 + 20 + (hnd->page_width-1-strlen(t))*4; - else if (align == TEXT_RIGHT) - x = x0 + 20 + (hnd->page_width-1-strlen(t))*8; - else - x = x0 + 20; - if(x != xlast) - { - sprintf(string + strlen(string), "xv %d ",x); - xlast = x; - } - if (alt) { - sprintf(string + strlen(string), "string2 \"%s\" ", t); - } else { - sprintf(string + strlen(string), "string \"%s\" ", t); - } - } - alt = false; - } - - MESSAGE_BEGIN (svc_layout); - WRITE_STRING (string); - MESSAGE_SEND (MSG_ONE_R, NULL, ent ); -} - -void Text_Next(edict_t *ent) -{ - int current; - int displayed_lines; - texthnd_t *hnd; - - if (!ent->client->textdisplay) { - gi.dprintf("warning: ent has no text display\n"); - return; - } - - hnd = ent->client->textdisplay; - - displayed_lines = hnd->page_length; - if(hnd->nlines > hnd->page_length) displayed_lines--; - if(hnd->curline+displayed_lines+1 < hnd->nlines) - { - current = hnd->curline; -/// hnd->curline = min(hnd->curline+MAX_LINES/2,hnd->nlines-displayed_lines-1); - hnd->curline = hnd->curline+hnd->page_length-1; - if(hnd->curline > current) - { - Text_BuildDisplay(hnd); - Text_Update(ent); - } - } -} - -void Text_Prev(edict_t *ent) -{ - texthnd_t *hnd; - - if (!ent->client->textdisplay) { - gi.dprintf("warning: ent has no text display\n"); - return; - } - - hnd = ent->client->textdisplay; - - if(hnd->curline > 0) - { -/// hnd->curline = max(0, hnd->curline-MAX_LINES/2); - hnd->curline = max(0, hnd->curline-hnd->page_length+1); - Text_BuildDisplay(hnd); - Text_Update(ent); - } -} - - -void Do_Text_Display(edict_t *activator, int flags, char *message) -{ - int L; - char *p1, *p2, *p3; - char sound[64]; - texthnd_t *hnd; - byte *temp_buffer; - int line_length; - int new_line_length; - bool alt, centered, right_justified; - bool linebreak; - bool do_linebreaks; - - hnd = malloc(sizeof(*hnd)); - // If a file, open and read it - if(flags & 1) - { - char filename[256]; - file_t *f; - - strcat(filename,"\\maps\\"); - strcat(filename, message); - - f = gi.Fs.Open(filename, "rb" ); - if(!f) - { - gi.dprintf("File not found:%s\n",filename); - return; - } - gi.Fs.Seek(f, 0, SEEK_END); - L = gi.Fs.Tell (f); - gi.Fs.Seek(f, 0, SEEK_SET); - hnd->allocated = L+128; - hnd->buffer = malloc(hnd->allocated); - if(!hnd->buffer) - { - gi.dprintf("Memory allocation failure on target_text\n"); - Text_Close(activator); - return; - } - memset(hnd->buffer, 0, hnd->allocated); - gi.Fs.Read(f, hnd->buffer, L); - gi.Fs.Close(f); - } - else - { - L = strlen(message); - hnd->allocated = L+128; - hnd->buffer = malloc(hnd->allocated); - if(!hnd->buffer) - { - gi.dprintf("Memory allocation failure\n"); - Text_Close(activator); - return; - } - memset(hnd->buffer,0,hnd->allocated); - memcpy(hnd->buffer,message,L); - } - - hnd->size = strlen(hnd->buffer) + 1; - - // Default page length: - hnd->page_length = MAX_LINES-2; - hnd->page_width = MAX_LINE_LENGTH; - strcpy(hnd->background_image,"textdisplay"); - hnd->start_char = 0; - do_linebreaks = true; - - // If 1st line starts with $, read page length, width, and image name - p1 = hnd->buffer; - if(*p1 == '$') - { - p3 = p1; - while((p3 < hnd->buffer+hnd->size) && (*p3 != 13)) - p3++; - - p2 = strstr(p1,"L="); - if(p2 && (p2 < p3)) - { - p2 += 2; - sscanf(p2,"%d",&hnd->page_length); - hnd->page_length += 1; - } - p2 = strstr(p1,"W="); - if(p2 && (p2 < p3)) - { - p2 += 2; - sscanf(p2,"%d",&hnd->page_width); - } - p2 = strstr(p1,"I="); - if(p2 && (p2 < p3)) - { - p2 += 2; - sscanf(p2,"%s",hnd->background_image); - } - p3++; - if(*p3 == 10) p3++; - hnd->start_char = p3-p1; - do_linebreaks = false; - } - - // Eliminate all 's so lines are delineated with 's only - p1 = hnd->buffer+hnd->start_char; - while(p1 < hnd->buffer+hnd->size) - { - if(*p1 == 13) - { - for(p2=p1, p3=p1+1; p2buffer+hnd->size; p2++, p3++) - *p2 = *p3; - hnd->size--; - } - else - p1++; - } - // Count number of lines and replace all line feeds with 0's - hnd->nlines = 1; - for(p1 = hnd->buffer+hnd->start_char; p1 < hnd->buffer+hnd->size; p1++) - { - if(*p1 == 10) - { - hnd->nlines++; - *p1 = 0; - } - } - // Line break stuff - if(!do_linebreaks) - goto done_linebreaks; - - line_length = 0; - p1 = hnd->buffer+hnd->start_char; - alt = false; - centered = false; - right_justified = false; - while(p1 < hnd->buffer+hnd->size) - { - // Don't count control characters - if(line_length == 0) { - if(*p1 == '*') { - p1++; - alt = true; - } else { - alt = false; - } - if(*p1 == '\\') { - p1++; - if(*p1 == 'c') { - p1++; - centered = true; - right_justified = false; - } else if(*p1 == 'r') { - p1++; - centered = false; - right_justified = true; - } else { - centered = false; - right_justified = false; - } - } else { - centered = false; - right_justified = false; - } - } - if((line_length == 0) && (*p1 == '\\')) p1 += 2; - if(*p1 != 0) line_length++; - linebreak = false; - if(line_length > hnd->page_width) - { - if(*p1 == 32) - { - // We're at a space... good deal, just replace space with - // a line-break 0 and move on - *p1 = 0; - hnd->nlines++; - linebreak = true; - } - else - { - // back up from current position to last space character and - // replace with a 0 (but don't go past previous 0) - p2 = p1; - while(p1 > hnd->buffer+hnd->start_char && *p1 != 0) - { - if(*p1 == 32) - { - *p1 = 0; - hnd->nlines++; - linebreak = true; - } - else - p1--; - } - if(!linebreak) { - // Must be an ugly Mad Dog test trying my patience - say - // a 40-character line with no spaces. Back up one space, - // add a hyphen then a 0. - hnd->size += 2; - if(hnd->size >= hnd->allocated) { - hnd->allocated += 128; - temp_buffer = hnd->buffer; - hnd->buffer = malloc(hnd->allocated); - if(!hnd->buffer) - { - gi.dprintf("Memory allocation failure\n"); - Text_Close(activator); - return; - } - memset(hnd->buffer,0,hnd->allocated); - memcpy(hnd->buffer,temp_buffer,hnd->size); - p1 = hnd->buffer + (p2-temp_buffer); - p2 = p1; - free(temp_buffer); - } - p1 = p2-1; - p2 = hnd->buffer + hnd->size; - p3 = p2 - 2; - while(p3 >= p1) { - *p2 = *p3; - p2--; - p3--; - } - *p1 = '-'; - p1++; - *p1 = 0; - hnd->nlines++; - linebreak = true; - } - } - } - if(linebreak && alt) { - // We broke a line and the line was green text. Insert another - // '*' at beginning of next line - hnd->size += 1; - if(hnd->size > hnd->allocated) { - hnd->allocated += 128; - temp_buffer = hnd->buffer; - hnd->buffer = malloc(hnd->allocated); - if(!hnd->buffer) - { - gi.dprintf("Memory allocation failure\n"); - Text_Close(activator); - return; - } - memset(hnd->buffer,0,hnd->allocated); - memcpy(hnd->buffer,temp_buffer,hnd->size); - p2 = p1; - p1 = hnd->buffer + (p2-temp_buffer); - free(temp_buffer); - } - p2 = hnd->buffer + hnd->size; - p3 = p2 - 1; - while(p3 >= p1) { - *p2 = *p3; - p2--; - p3--; - } - p2 = p1+1; - *p2 = '*'; - } - if(linebreak && (centered || right_justified)) { - // We broke a line and the line had other than left justification. Insert another - // '\c' or '\r' at beginning of next line - hnd->size += 2; - if(hnd->size > hnd->allocated) { - hnd->allocated += 128; - temp_buffer = hnd->buffer; - hnd->buffer = malloc(hnd->allocated); - if(!hnd->buffer) - { - gi.dprintf("Memory allocation failure\n"); - Text_Close(activator); - return; - } - memset(hnd->buffer,0,hnd->allocated); - memcpy(hnd->buffer,temp_buffer,hnd->size); - p2 = p1; - p1 = hnd->buffer + (p2-temp_buffer); - free(temp_buffer); - } - p2 = hnd->buffer + hnd->size; - p3 = p2 - 2; - while(p3 >= p1) { - *p2 = *p3; - p2--; - p3--; - } - p2 = p1+1; - if(alt) p2++; - *p2 = '\\'; - p2++; - if(centered) - *p2 = 'c'; - else - *p2 = 'r'; - } - if(*p1=='\\') { - p2 = p1+1; - if(*p2=='n') { - *p1 = 0; - p3 = p2 + 1; - while(p3 < hnd->buffer + hnd->size) { - *p2 = *p3; - p2++; - p3++; - } - hnd->nlines++; - linebreak = true; - centered = false; - right_justified = false; - alt = false; - } - } - // If we're at a 0, check to see if subsequent words will fit on this line - if((!linebreak) && (*p1 == 0) && (p1 < hnd->buffer+hnd->size-1) && - (line_length < hnd->page_width) ) - { - // Don't do this if 2 consecutive 0's are found (end of paragraph) - // or if 1st character in next line is '*' or '\' - p2 = p1; - p2--; - if(*p2 != 0) - { - p2++; - p2++; - if(*p2 != 0 && *p2 != '*' && *p2 != '\\' && p2 < hnd->buffer+hnd->size) - { - new_line_length = line_length+2; - while(p2 < hnd->buffer+hnd->size && *p2 != 32 && *p2 != 0) - { - new_line_length++; - p2++; - } - if(new_line_length <= hnd->page_width) - { - *p1 = 32; - line_length++; // include the space that was a 0 - hnd->nlines--; - } - } - } - } - if(*p1 == 0) line_length = 0; - p1++; - } - -done_linebreaks: - - // Finally, scan for a \a code (embedded audio). If present remove that line - // and play the sound - p1 = hnd->buffer+hnd->start_char; - while(p1 < hnd->buffer+hnd->size) - { - if((*p1 == 0) || (p1 == hnd->buffer+hnd->start_char)) - { - if(*p1 == 0) - p1++; - if(*p1 == '\\') - { - p1++; - if(*p1 == 'a') - { - strcpy(sound,p1+1); - p1--; - p2=p1; - while(*p2 != 0) - p2++; - p2++; - memcpy(p1,p2,hnd->buffer+hnd->size-p2+1); - hnd->nlines--; - // Found one (only one is allowed) - gi.sound (activator, CHAN_AUTO, gi.soundindex (sound), 1, ATTN_NORM, 0); - } - } - } - p1++; - } - - hnd->curline = 0; - hnd->flags = flags; - Text_BuildDisplay(hnd); - hnd->lines = text; - activator->client->textdisplay = hnd; - Text_Open(activator); - -} - -void Use_Target_Text(edict_t *self, edict_t *other, edict_t *activator) -{ - - if(!activator || !activator->client) return; - activator->client->showinventory = false; - activator->client->showscores = false; - activator->client->showhelp = false; - - Text_Close(activator); - - Do_Text_Display(activator, self->spawnflags, self->message); - -} - -void SP_target_text(edict_t *self) -{ - if(!self->message) - { - gi.dprintf("target_text with no message at %s\n", - vtos(self->s.origin)); - G_FreeEdict (self); - return; - } - self->class_id = ENTITY_TARGET_TEXT; - self->use = Use_Target_Text; -} - - diff --git a/server/p_text.h b/server/p_text.h deleted file mode 100644 index 250b8a79..00000000 --- a/server/p_text.h +++ /dev/null @@ -1,32 +0,0 @@ - -enum { - TEXT_LEFT, - TEXT_CENTER, - TEXT_RIGHT -}; - -typedef struct texthnd_s { - struct text_s *lines; - int nlines; - int curline; - int size; - int flags; - int allocated; - int page_length; - int page_width; - float last_update; - char background_image[32]; - int start_char; - byte *buffer; -} texthnd_t; - -typedef struct text_s { - char *text; -} text_t; - -void Text_Open(edict_t *ent); -void Text_Close(edict_t *ent); -void Text_Update(edict_t *ent); -void Text_Next(edict_t *ent); -void Text_Prev(edict_t *ent); - diff --git a/server/p_trail.c b/server/p_trail.c deleted file mode 100644 index 2243e4e0..00000000 --- a/server/p_trail.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "g_local.h" - - -/* -============================================================================== - -PLAYER TRAIL - -============================================================================== - -This is a circular list containing the a list of points of where -the player has been recently. It is used by monsters for pursuit. - -.origin the spot -.owner forward link -.aiment backward link -*/ - - -#define TRAIL_LENGTH 8 - -edict_t *trail[TRAIL_LENGTH]; -int trail_head; -bool trail_active = false; - -#define NEXT(n) (((n) + 1) & (TRAIL_LENGTH - 1)) -#define PREV(n) (((n) - 1) & (TRAIL_LENGTH - 1)) - - -void PlayerTrail_Init (void) -{ - int n; - - if (deathmatch->value /* FIXME || coop */) - return; - - for (n = 0; n < TRAIL_LENGTH; n++) - { - trail[n] = G_Spawn(); - trail[n]->classname = "player_trail"; - } - - trail_head = 0; - trail_active = true; -} - - -void PlayerTrail_Add (vec3_t spot) -{ - vec3_t temp; - - if (!trail_active) - return; - - VectorCopy (spot, trail[trail_head]->s.origin); - - trail[trail_head]->timestamp = level.time; - - VectorSubtract (spot, trail[PREV(trail_head)]->s.origin, temp); - trail[trail_head]->s.angles[1] = vectoyaw (temp); - trail_head = NEXT(trail_head); -} - - -void PlayerTrail_New (vec3_t spot) -{ - if (!trail_active) - return; - - PlayerTrail_Init (); - PlayerTrail_Add (spot); -} - - -edict_t *PlayerTrail_PickFirst (edict_t *self) -{ - int marker; - int n; - - if (!trail_active) - return NULL; - - for (marker = trail_head, n = TRAIL_LENGTH; n; n--) - { - if(trail[marker]->timestamp <= self->monsterinfo.trail_time) - marker = NEXT(marker); - else - break; - } - - if (visible(self, trail[marker])) - { - return trail[marker]; - } - - if (visible(self, trail[PREV(marker)])) - { - return trail[PREV(marker)]; - } - - return trail[marker]; -} - -edict_t *PlayerTrail_PickNext (edict_t *self) -{ - int marker; - int n; - - if (!trail_active) - return NULL; - - for (marker = trail_head, n = TRAIL_LENGTH; n; n--) - { - if(trail[marker]->timestamp <= self->monsterinfo.trail_time) - marker = NEXT(marker); - else - break; - } - - return trail[marker]; -} - -edict_t *PlayerTrail_LastSpot (void) -{ - return trail[PREV(trail_head)]; -} diff --git a/server/p_view.c b/server/p_view.c index 6fd86c29..6a5b9853 100644 --- a/server/p_view.c +++ b/server/p_view.c @@ -303,14 +303,7 @@ void SV_CalcViewOffset (edict_t *ent) // absolutely bound offsets // so the view can never be outside the player box - if(ent->client->chasetoggle) { - VectorSet (v, 0, 0, 0); - if(ent->client->chasecam != NULL) { - ent->client->ps.pmove.origin[0] = ent->client->chasecam->s.origin[0]*8; - ent->client->ps.pmove.origin[1] = ent->client->chasecam->s.origin[1]*8; - ent->client->ps.pmove.origin[2] = ent->client->chasecam->s.origin[2]*8; - } - } else if(ent->client->spycam) { + if(ent->client->spycam) { VectorSet (v, 0, 0, 0); VectorCopy (ent->client->spycam->s.angles, ent->client->ps.viewangles); if(ent->client->spycam->svflags & SVF_MONSTER) @@ -421,14 +414,7 @@ void SV_CalcBlend (edict_t *ent) ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0; // add for contents - if (ent->client->chasetoggle) - { - VectorCopy (ent->client->chasecam->s.origin, vieworg); - } - else - { - VectorAdd (ent->s.origin, ent->client->ps.viewoffset, vieworg); - } + VectorAdd (ent->s.origin, ent->client->ps.viewoffset, vieworg); contents = gi.pointcontents (vieworg); if (contents & (CONTENTS_LAVA|CONTENTS_SLIME|CONTENTS_WATER) ) ent->client->ps.rdflags |= RDF_UNDERWATER; @@ -460,23 +446,6 @@ void SV_CalcBlend (edict_t *ent) } // add for powerups -#ifdef JETPACK_MOD - if ( ent->client->jetpack ) - { - remaining = ent->client->pers.inventory[fuel_index]; - // beginning to fade if 4 secs or less - if (remaining > 40) - { - if ( ((level.framenum % 6) == 0) && ( level.framenum - ent->client->jetpack_activation > 30 ) ) - { - if (ent->client->jetpack_thrusting && (level.framenum - ent->client->jetpack_start_thrust > 10)) - gi.sound (ent, CHAN_AUTO, gi.soundindex("jetpack/revrun.wav"), 1, ATTN_NORM, 0); - gi.sound (ent, CHAN_GIZMO, gi.soundindex("jetpack/running.wav"), 1, ATTN_NORM, 0); - } - } - } -#endif // #ifdef JETPACK_MOD - if (ent->client->quad_framenum > level.framenum) { remaining = ent->client->quad_framenum - level.framenum; @@ -646,9 +615,6 @@ void P_FallingDamage (edict_t *ent) if (ent->movetype == MOVETYPE_NOCLIP) return; - if (ent->client->jetpack && ent->client->ucmd.upmove > 0) - return; - if ((ent->client->oldvelocity[2] < 0) && (ent->velocity[2] > ent->client->oldvelocity[2]) && (!ent->groundentity)) { delta = ent->client->oldvelocity[2]; @@ -670,17 +636,7 @@ void P_FallingDamage (edict_t *ent) if (ent->waterlevel == 1) delta *= 0.5; - if (delta < 1) - return; - - // Lazarus: Changed here to NOT play footstep sounds if ent isn't on the ground. - // So player will no longer play footstep sounds when descending a ladder. - if (delta < 15 ) - { - if (!(ent->watertype & CONTENTS_MUD) && !ent->vehicle && !ent->turret && ent->groundentity) - FootStep(ent); - return; - } + if (delta < 1) return; ent->client->fall_value = delta*0.5; if (ent->client->fall_value > 40) @@ -691,15 +647,6 @@ void P_FallingDamage (edict_t *ent) { if (ent->health > 0) { - -/* This change plays the correct sexed sounds while in - third person view - - if (delta >= 55) - ent->s.event = EV_FALLFAR; - else - ent->s.event = EV_FALL; -*/ if (delta >= 55) gi.sound(ent,CHAN_VOICE,gi.soundindex("*fall1.wav"),1.0,ATTN_NORM,0); else @@ -821,18 +768,6 @@ void P_WorldEffects (void) // if (waterlevel == 3) { -#ifdef JETPACK_MOD - if ( current_player->client->jetpack ) - { - if ( (current_player->watertype & (CONTENTS_LAVA|CONTENTS_SLIME)) && !(current_player->flags & FL_GODMODE ) ) // blow up in lava/slime - T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->health+1, 0, DAMAGE_NO_ARMOR, 0); - else - { - gitem_t *jetpack = FindItem("jetpack"); - Use_Jet (current_player, jetpack); // shut down in water - } - } -#endif // breather or envirosuit give air if (breather || envirosuit) { @@ -1025,12 +960,7 @@ void G_SetClientEvent (edict_t *ent) if ( ent->groundentity ) { - if (!ent->waterlevel && ( xyspeed > 225) && !ent->vehicle) - { - if ( (int)(current_client->bobtime+bobmove) != bobcycle ) - FootStep(ent); - } - else if( ent->in_mud && (ent->waterlevel == 1) && (xyspeed > 40)) + if( ent->in_mud && (ent->waterlevel == 1) && (xyspeed > 40)) { if ( (level.framenum % 10) == 0 ) { @@ -1040,12 +970,6 @@ void G_SetClientEvent (edict_t *ent) gi.sound(ent, CHAN_BODY, gi.soundindex("mud/wade_mud2.wav"), 1, ATTN_NORM, 0); } } - else if( world->effects & FX_WORLDSPAWN_STEPSOUNDS ) - { - if( ( (ent->waterlevel == 1) || (ent->waterlevel == 2) ) && ( xyspeed > 100 ) ) - if ( (int)(current_client->bobtime+bobmove) != bobcycle ) - FootStep(ent); - } } else { @@ -1065,23 +989,12 @@ void G_SetClientEvent (edict_t *ent) int r; r = rand() & 1 + ent->client->leftfoot*2; ent->client->leftfoot = 1 - ent->client->leftfoot; - if(qFMOD_Footsteps) + switch (r) { - switch (r){ - case 0: PlayFootstep(ent,FOOTSTEP_LADDER1); break; - case 1: PlayFootstep(ent,FOOTSTEP_LADDER3); break; - case 2: PlayFootstep(ent,FOOTSTEP_LADDER2); break; - case 3: PlayFootstep(ent,FOOTSTEP_LADDER4); break; - } - } - else - { - switch (r){ - case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder1.wav"),1.0,ATTN_NORM,0); break; - case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder3.wav"),1.0,ATTN_NORM,0); break; - case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder2.wav"),1.0,ATTN_NORM,0); break; - case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder4.wav"),1.0,ATTN_NORM,0); break; - } + case 0: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder1.wav"),1.0,ATTN_NORM,0); break; + case 1: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder3.wav"),1.0,ATTN_NORM,0); break; + case 2: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder2.wav"),1.0,ATTN_NORM,0); break; + case 3: gi.sound(ent,CHAN_VOICE,gi.soundindex("player/pl_ladder4.wav"),1.0,ATTN_NORM,0); break; } } } @@ -1120,8 +1033,6 @@ void G_SetClientSound (edict_t *ent) if (ent->waterlevel && (ent->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) ) ent->s.sound = snd_fry; - else if ( ent->client->jetpack && (ent->client->pers.inventory[fuel_index] < 40 )) - ent->s.sound = gi.soundindex("jetpack/stutter.wav"); else if (strcmp(weap, "weapon_railgun") == 0) ent->s.sound = gi.soundindex("weapons/rg_hum.wav"); else if (strcmp(weap, "weapon_bfg") == 0) @@ -1372,8 +1283,6 @@ void ClientEndServerFrame (edict_t *ent) G_SetSpectatorStats(ent); else G_SetStats (ent); - G_CheckChaseStats(ent); - G_SetClientEvent (ent); G_SetClientEffects (ent); @@ -1396,8 +1305,6 @@ void ClientEndServerFrame (edict_t *ent) { if (ent->client->menu) PMenu_Update(ent); - else if (ent->client->textdisplay) - Text_Update(ent); else DeathmatchScoreboardMessage (ent, ent->enemy); MESSAGE_SEND (MSG_ONE, NULL, ent ); @@ -1405,11 +1312,5 @@ void ClientEndServerFrame (edict_t *ent) else if(ent->client->whatsit) WhatsIt(ent); } - - // tpp - if (ent->client->chasetoggle == 1) - CheckChasecam_Viewent(ent); - // end tpp - } diff --git a/server/p_weapon.c b/server/p_weapon.c index 59baae07..587bd8d8 100644 --- a/server/p_weapon.c +++ b/server/p_weapon.c @@ -58,17 +58,6 @@ void PlayerNoise(edict_t *who, vec3_t where, int type) if (who->flags & FL_NOTARGET) return; - if (who->flags & FL_DISGUISED) - { - if (type == PNOISE_WEAPON) - { - level.disguise_violator = who; - level.disguise_violation_framenum = level.framenum + 5; - } - else - return; - } - if (!who->mynoise) { noise = G_Spawn(); @@ -217,9 +206,7 @@ void ChangeWeapon (edict_t *ent) ent->client->weaponstate = WEAPON_ACTIVATING; ent->client->ps.gunframe = 0; - // DWH: Don't display weapon if in 3rd person - if(!ent->client->chasetoggle) - ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); + ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); // DWH: change weapon model index if necessary if(ITEM_INDEX(ent->client->pers.weapon) == noweapon_index) @@ -311,16 +298,6 @@ void Think_Weapon (edict_t *ent) if (level.freeze) return; - if (ent->flags & FL_TURRET_OWNER) - { - if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTONS_ATTACK) ) - { - ent->client->latched_buttons &= ~BUTTONS_ATTACK; - turret_breach_fire(ent->turret); - } - return; - } - // call active weapon think routine if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) { @@ -666,7 +643,8 @@ void weapon_grenade_fire (edict_t *ent, bool held) timer = ent->client->grenade_time - level.time; speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); - fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); + +//fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--; @@ -828,9 +806,7 @@ void weapon_grenadelauncher_fire (edict_t *ent) VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; - fire_grenade (ent, start, forward, damage, 600, 2.5, radius); - // temporary crap to test grenade bounce -// fire_grenade (ent, start, forward, damage, 600, 25, radius); +//fire_grenade (ent, start, forward, damage, 600, 2.5, radius); MESSAGE_BEGIN (svc_muzzleflash); WRITE_SHORT (ent-g_edicts); @@ -940,10 +916,9 @@ void Weapon_RocketLauncher_Fire (edict_t *ent) } target = rocket_target(ent, start, forward); - fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage, target); +//fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage, target); } - else - fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage, NULL); +//else fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage, NULL); // send muzzle flash MESSAGE_BEGIN (svc_muzzleflash); @@ -989,6 +964,129 @@ BLASTER / HYPERBLASTER ====================================================================== */ +/* +================= +fire_blaster + +Fires a single blaster bolt. Used by the blaster and hyper blaster. +================= +*/ +void blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + int mod; + + if (other == self->owner) + return; + + if (surf && (surf->flags & SURF_SKY)) + { + G_FreeEdict (self); + return; + } + + if (self->owner->client) + PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); + + if (other->takedamage) + { + if (self->spawnflags & 1) + mod = MOD_HYPERBLASTER; + else + mod = MOD_BLASTER; + T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); + } + else + { + MESSAGE_BEGIN (svc_temp_entity); + WRITE_BYTE (TE_BLASTER); + WRITE_COORD (self->s.origin); + if (!plane) WRITE_DIR (vec3_origin); + else WRITE_DIR (plane->normal); + MESSAGE_SEND (MSG_PVS, self->s.origin, NULL); + } + + G_FreeEdict (self); +} + +/* +================= +check_dodge + +This is a support routine used when a client is firing +a non-instant attack weapon. It checks to see if a +monster's dodge function should be called. +================= +*/ +static void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed) +{ + vec3_t end; + vec3_t v; + trace_t tr; + float eta; + + // easy mode only ducks one quarter the time + if (skill->value == 0) + { + if (random() > 0.25) + return; + } + VectorMA (start, 8192, dir, end); + tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); + if ((tr.ent) && (tr.ent->svflags & SVF_MONSTER) && (tr.ent->health > 0) && (tr.ent->monsterinfo.dodge) && infront(tr.ent, self)) + { + VectorSubtract (tr.endpos, start, v); + eta = (VectorLength(v) - tr.ent->maxs[0]) / speed; + tr.ent->monsterinfo.dodge (tr.ent, self, eta); + } +} + +void fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, bool hyper) +{ + edict_t *bolt; + trace_t tr; + + VectorNormalize (dir); + + bolt = G_Spawn(); + bolt->svflags = SVF_DEADMONSTER; + // yes, I know it looks weird that projectiles are deadmonsters + // what this means is that when prediction is used against the object + // (blaster/hyperblaster shots), the player won't be solid clipped against + // the object. Right now trying to run into a firing hyperblaster + // is very jerky since you are predicted 'against' the shots. + VectorCopy (start, bolt->s.origin); + VectorCopy (start, bolt->s.old_origin); + vectoangles (dir, bolt->s.angles); + VectorScale (dir, speed, bolt->velocity); + bolt->movetype = MOVETYPE_FLYMISSILE; + bolt->clipmask = MASK_SHOT; + bolt->solid = SOLID_BBOX; + bolt->s.effects |= effect; + VectorClear (bolt->mins); + VectorClear (bolt->maxs); + bolt->s.modelindex = gi.modelindex ("models/shell9mm.mdl"); + bolt->s.sound = gi.soundindex ("misc/lasfly.wav"); + bolt->owner = self; + bolt->touch = blaster_touch; + bolt->nextthink = level.time + 2; + bolt->think = G_FreeEdict; + bolt->dmg = damage; + bolt->classname = "bolt"; + + gi.linkentity (bolt); + + if (self->client) + check_dodge (self, bolt->s.origin, dir, speed); + + tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); + if (tr.fraction < 1.0) + { + VectorMA (bolt->s.origin, -10, dir, bolt->s.origin); + bolt->touch (bolt, tr.ent, NULL, NULL); + } + +} + void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, bool hyper, int effect) { vec3_t forward, right; @@ -1010,8 +1108,7 @@ void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, bool hyper, int ef // send muzzle flash MESSAGE_BEGIN (svc_muzzleflash); WRITE_SHORT (ent-g_edicts); - if (hyper) WRITE_BYTE (MZ_HYPERBLASTER | is_silenced); - else WRITE_BYTE (MZ_BLASTER | is_silenced); + WRITE_BYTE (MZ_HYPERBLASTER | is_silenced); MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); PlayerNoise(ent, start, PNOISE_WEAPON); @@ -1038,577 +1135,10 @@ void Weapon_Blaster (edict_t *ent) Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); } - -void Weapon_HyperBlaster_Fire (edict_t *ent) -{ - float rotation; - vec3_t offset; - int effect; - int damage; - - ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); - - if (!(ent->client->buttons & BUTTONS_ATTACK)) - { - ent->client->ps.gunframe++; - } - else - { - if (! ent->client->pers.inventory[ent->client->ammo_index] ) - { - if (level.time >= ent->pain_debounce_time) - { - gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); - ent->pain_debounce_time = level.time + 1; - } - NoAmmoWeaponChange (ent); - } - else - { - rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6; - offset[1] = -4 * sin(rotation); - offset[0] = 0; - offset[2] = 4 * cos(rotation); - - if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) - effect = EF_HYPERBLASTER; - else - effect = 0; - if (deathmatch->value) - damage = 15; - else - damage = 20; - Blaster_Fire (ent, offset, damage, true, effect); - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index]--; - - ent->client->anim_priority = ANIM_ATTACK; - if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) - { - ent->s.frame = FRAME_crattak1 - 1; - ent->client->anim_end = FRAME_crattak9; - } - else - { - ent->s.frame = FRAME_attack1 - 1; - ent->client->anim_end = FRAME_attack8; - } - } - - ent->client->ps.gunframe++; - if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index]) - ent->client->ps.gunframe = 6; - } - - if (ent->client->ps.gunframe == 12) - { - gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); - ent->client->weapon_sound = 0; - } - -} - -void Weapon_HyperBlaster (edict_t *ent) -{ - static int pause_frames[] = {0}; - static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; - - Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); -} - -/* -====================================================================== - -MACHINEGUN / CHAINGUN - -====================================================================== -*/ - -void Machinegun_Fire (edict_t *ent) -{ - int i; - vec3_t start; - vec3_t forward, right; - vec3_t angles; - int damage = 8; - int kick = 2; - vec3_t offset; - - if (!(ent->client->buttons & BUTTONS_ATTACK)) - { - ent->client->machinegun_shots = 0; - ent->client->ps.gunframe++; - return; - } - - if (ent->client->ps.gunframe == 5) - ent->client->ps.gunframe = 4; - else - ent->client->ps.gunframe = 5; - - if (ent->client->pers.inventory[ent->client->ammo_index] < 1) - { - ent->client->ps.gunframe = 6; - if (level.time >= ent->pain_debounce_time) - { - gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); - ent->pain_debounce_time = level.time + 1; - } - NoAmmoWeaponChange (ent); - return; - } - - if (is_quad) - { - damage *= 4; - kick *= 4; - } - - for (i=1 ; i<3 ; i++) - { - ent->client->kick_origin[i] = crandom() * 0.35; - ent->client->kick_angles[i] = crandom() * 0.7; - } - ent->client->kick_origin[0] = crandom() * 0.35; - ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; - - // raise the gun as it is firing - if (!deathmatch->value) - { - ent->client->machinegun_shots++; - if (ent->client->machinegun_shots > 9) - ent->client->machinegun_shots = 9; - } - - // get start / end positions - VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); - AngleVectors (angles, forward, right, NULL); - VectorSet(offset, 0, 8, ent->viewheight-8); - P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); - fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); - - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (ent-g_edicts); - WRITE_BYTE (MZ_MACHINEGUN | is_silenced); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - PlayerNoise(ent, start, PNOISE_WEAPON); - - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index]--; - - ent->client->anim_priority = ANIM_ATTACK; - if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) - { - ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); - ent->client->anim_end = FRAME_crattak9; - } - else - { - ent->s.frame = FRAME_attack1 - (int) (random()+0.25); - ent->client->anim_end = FRAME_attack8; - } -} - -void Weapon_Machinegun (edict_t *ent) -{ - static int pause_frames[] = {23, 45, 0}; - static int fire_frames[] = {4, 5, 0}; - - Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); -} - -void Chaingun_Fire (edict_t *ent) -{ - int i; - int shots; - vec3_t start; - vec3_t forward, right, up; - float r, u; - vec3_t offset; - int damage; - int kick = 2; - - if (deathmatch->value) - damage = 6; - else - damage = 8; - - if (ent->client->ps.gunframe == 5) - gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); - - if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTONS_ATTACK)) - { - ent->client->ps.gunframe = 32; - ent->client->weapon_sound = 0; - return; - } - else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTONS_ATTACK) - && ent->client->pers.inventory[ent->client->ammo_index]) - { - ent->client->ps.gunframe = 15; - } - else - { - ent->client->ps.gunframe++; - } - - if (ent->client->ps.gunframe == 22) - { - ent->client->weapon_sound = 0; - gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); - } - else - { - ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); - } - - ent->client->anim_priority = ANIM_ATTACK; - if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) - { - ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); - ent->client->anim_end = FRAME_crattak9; - } - else - { - ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); - ent->client->anim_end = FRAME_attack8; - } - - if (ent->client->ps.gunframe <= 9) - shots = 1; - else if (ent->client->ps.gunframe <= 14) - { - if (ent->client->buttons & BUTTONS_ATTACK) - shots = 2; - else - shots = 1; - } - else - shots = 3; - - if (ent->client->pers.inventory[ent->client->ammo_index] < shots) - shots = ent->client->pers.inventory[ent->client->ammo_index]; - - if (!shots) - { - if (level.time >= ent->pain_debounce_time) - { - gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); - ent->pain_debounce_time = level.time + 1; - } - NoAmmoWeaponChange (ent); - return; - } - - if (is_quad) - { - damage *= 4; - kick *= 4; - } - - for (i=0 ; i<3 ; i++) - { - ent->client->kick_origin[i] = crandom() * 0.35; - ent->client->kick_angles[i] = crandom() * 0.7; - } - - for (i=0 ; iclient->v_angle, forward, right, up); - r = 7 + crandom()*4; - u = crandom()*4; - VectorSet(offset, 0, r, u + ent->viewheight-8); - P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); - - fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); - } - - // send muzzle flash - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (ent-g_edicts); - WRITE_BYTE ((MZ_CHAINGUN1 + shots - 1) | is_silenced); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - PlayerNoise(ent, start, PNOISE_WEAPON); - - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index] -= shots; -} - - -void Weapon_Chaingun (edict_t *ent) -{ - static int pause_frames[] = {38, 43, 51, 61, 0}; - static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; - - Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); -} - - -/* -====================================================================== - -SHOTGUN / SUPERSHOTGUN - -====================================================================== -*/ - -void weapon_shotgun_fire (edict_t *ent) -{ - vec3_t start; - vec3_t forward, right; - vec3_t offset; - int damage = 4; - int kick = 8; - - if (ent->client->ps.gunframe == 9) - { - ent->client->ps.gunframe++; - return; - } - - AngleVectors (ent->client->v_angle, forward, right, NULL); - - VectorScale (forward, -2, ent->client->kick_origin); - ent->client->kick_angles[0] = -2; - - VectorSet(offset, 0, 8, ent->viewheight-8); - P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); - - if (is_quad) - { - damage *= 4; - kick *= 4; - } - - if (deathmatch->value) - fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN); - else - fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); - - // send muzzle flash - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (ent-g_edicts); - WRITE_BYTE (MZ_SHOTGUN | is_silenced); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - ent->client->ps.gunframe++; - PlayerNoise(ent, start, PNOISE_WEAPON); - - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index]--; -} - -void Weapon_Shotgun (edict_t *ent) -{ - static int pause_frames[] = {22, 28, 34, 0}; - static int fire_frames[] = {8, 9, 0}; - - Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); -} - - -void weapon_supershotgun_fire (edict_t *ent) -{ - vec3_t start; - vec3_t forward, right; - vec3_t offset; - vec3_t v; - int damage = 6; - int kick = 12; - - AngleVectors (ent->client->v_angle, forward, right, NULL); - - VectorScale (forward, -2, ent->client->kick_origin); - ent->client->kick_angles[0] = -2; - - VectorSet(offset, 0, 8, ent->viewheight-8); - P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); - - if (is_quad) - { - damage *= 4; - kick *= 4; - } - - v[PITCH] = ent->client->v_angle[PITCH]; - v[YAW] = ent->client->v_angle[YAW] - 5; - v[ROLL] = ent->client->v_angle[ROLL]; - AngleVectors (v, forward, NULL, NULL); - fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); - v[YAW] = ent->client->v_angle[YAW] + 5; - AngleVectors (v, forward, NULL, NULL); - fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); - - // send muzzle flash - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (ent-g_edicts); - WRITE_BYTE (MZ_SSHOTGUN | is_silenced); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - ent->client->ps.gunframe++; - PlayerNoise(ent, start, PNOISE_WEAPON); - - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index] -= 2; -} - -void Weapon_SuperShotgun (edict_t *ent) -{ - static int pause_frames[] = {29, 42, 57, 0}; - static int fire_frames[] = {7, 0}; - - Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); -} - - - -/* -====================================================================== - -RAILGUN - -====================================================================== -*/ - -void weapon_railgun_fire (edict_t *ent) -{ - vec3_t start; - vec3_t forward, right; - vec3_t offset; - int damage; - int kick; - - if (deathmatch->value) - { // normal damage is too extreme in dm - damage = 100; - kick = 200; - } - else - { - damage = 150; - kick = 250; - } - - if (is_quad) - { - damage *= 4; - kick *= 4; - } - - AngleVectors (ent->client->v_angle, forward, right, NULL); - - VectorScale (forward, -3, ent->client->kick_origin); - ent->client->kick_angles[0] = -3; - - VectorSet(offset, 0, 7, ent->viewheight-8); - P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); - fire_rail (ent, start, forward, damage, kick); - - // send muzzle flash - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (ent-g_edicts); - WRITE_BYTE (MZ_RAILGUN | is_silenced); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - ent->client->ps.gunframe++; - PlayerNoise(ent, start, PNOISE_WEAPON); - - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index]--; -} - - -void Weapon_Railgun (edict_t *ent) -{ - static int pause_frames[] = {56, 0}; - static int fire_frames[] = {4, 0}; - - Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); -} - - -/* -====================================================================== - -BFG10K - -====================================================================== -*/ - -void weapon_bfg_fire (edict_t *ent) -{ - vec3_t offset, start; - vec3_t forward, right; - int damage; - float damage_radius = 1000; - - if (deathmatch->value) - damage = 200; - else - damage = 500; - - if (ent->client->ps.gunframe == 9) - { - // send muzzle flash - MESSAGE_BEGIN (svc_muzzleflash); - WRITE_SHORT (ent-g_edicts); - WRITE_BYTE (MZ_BFG | is_silenced); - MESSAGE_SEND (MSG_PVS, ent->s.origin, NULL); - - ent->client->ps.gunframe++; - - PlayerNoise(ent, start, PNOISE_WEAPON); - return; - } - - // cells can go down during windup (from power armor hits), so - // check again and abort firing if we don't have enough now - if (ent->client->pers.inventory[ent->client->ammo_index] < 50) - { - ent->client->ps.gunframe++; - return; - } - - if (is_quad) - damage *= 4; - - AngleVectors (ent->client->v_angle, forward, right, NULL); - - VectorScale (forward, -2, ent->client->kick_origin); - - // make a big pitch kick with an inverse fall - ent->client->v_dmg_pitch = -40; - ent->client->v_dmg_roll = crandom()*8; - ent->client->v_dmg_time = level.time + DAMAGE_TIME; - - VectorSet(offset, 8, 8, ent->viewheight-8); - P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); - fire_bfg (ent, start, forward, damage, 400, damage_radius); - - ent->client->ps.gunframe++; - - PlayerNoise(ent, start, PNOISE_WEAPON); - - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index] -= 50; -} - -void Weapon_BFG (edict_t *ent) -{ - static int pause_frames[] = {39, 45, 50, 55, 0}; - static int fire_frames[] = {9, 17, 0}; - - Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); -} - //====================================================================== void Weapon_Null(edict_t *ent) { - if (ent->client->newweapon) - ChangeWeapon(ent); + if (ent->client->newweapon) ChangeWeapon(ent); } //====================================================================== void kick_attack (edict_t * ent ) diff --git a/server/pak.h b/server/pak.h deleted file mode 100644 index a96656a8..00000000 --- a/server/pak.h +++ /dev/null @@ -1,13 +0,0 @@ -typedef struct -{ - char id[4]; // Should be 'PACK' - int dstart; // Offest in the file to the directory - int dsize; // Size in bytes of the directory, same as num_items*64 -} pak_header_t; - -typedef struct -{ - char name[56]; // The name of the item, normal C string - int start; // Offset in .pak file to start of item - int size; // Size of item in bytes -} pak_item_t; diff --git a/server/server.dsp b/server/server.dsp index 171b1fc4..7ec109d6 100644 --- a/server/server.dsp +++ b/server/server.dsp @@ -114,243 +114,39 @@ SOURCE="$(InputPath)" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" # Begin Source File -SOURCE=.\global\g_ai.c +SOURCE=.\g_cmds.c # End Source File # Begin Source File -SOURCE=.\ents\g_camera.c +SOURCE=.\g_items.c # End Source File # Begin Source File -SOURCE=.\global\g_chase.c +SOURCE=.\g_main.c # End Source File # Begin Source File -SOURCE=.\global\g_cmds.c +SOURCE=.\g_misc.c # End Source File # Begin Source File -SOURCE=.\global\g_combat.c +SOURCE=.\g_phys.c # End Source File # Begin Source File -SOURCE=.\ents\g_crane.c +SOURCE=.\g_save.c # End Source File # Begin Source File -SOURCE=.\ents\g_fog.c +SOURCE=.\g_spawn.c # End Source File # Begin Source File -SOURCE=.\ents\g_func.c +SOURCE=.\g_svcmds.c # End Source File # Begin Source File -SOURCE=.\ents\g_items.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_jetpack.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_lights.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_lock.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_main.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_misc.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_model.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\g_monster.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_mtrain.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_newai.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_pendulum.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_phys.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_reflect.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_save.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_sound.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_spawn.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_svcmds.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_target.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_thing.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_tracktrain.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_trigger.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_turret.c -# End Source File -# Begin Source File - -SOURCE=.\global\g_utils.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_vehicle.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_weapon.c -# End Source File -# Begin Source File - -SOURCE=.\ents\g_wes.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_actor.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_actor_weap.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_berserk.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss2.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss3.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss31.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss32.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_brain.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_chick.c -# End Source File -# Begin Source File - -SOURCE=.\m_flash.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_flipper.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_float.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_flyer.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_gladiator.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_gunner.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_hover.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_infantry.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_insane.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_medic.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_move.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_mutant.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_parasite.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_soldier.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_supertank.c -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_tank.c -# End Source File -# Begin Source File - -SOURCE=.\p_chase.c +SOURCE=.\g_utils.c # End Source File # Begin Source File @@ -366,14 +162,6 @@ SOURCE=.\p_menu.c # End Source File # Begin Source File -SOURCE=.\p_text.c -# End Source File -# Begin Source File - -SOURCE=.\p_trail.c -# End Source File -# Begin Source File - SOURCE=.\p_view.c # End Source File # Begin Source File @@ -390,120 +178,16 @@ SOURCE=..\common\const.h # End Source File # Begin Source File -SOURCE=.\global\fmod.h -# End Source File -# Begin Source File - SOURCE=.\g_local.h # End Source File # Begin Source File -SOURCE=.\game.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_actor.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_berserk.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss2.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss31.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_boss32.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_brain.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_chick.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_flipper.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_float.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_flyer.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_gladiator.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_gunner.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_hover.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_infantry.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_insane.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_medic.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_mutant.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_parasite.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_player.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_rider.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_soldier.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_supertank.h -# End Source File -# Begin Source File - -SOURCE=.\monsters\m_tank.h +SOURCE=.\m_player.h # End Source File # Begin Source File SOURCE=.\p_menu.h # End Source File -# Begin Source File - -SOURCE=.\p_text.h -# End Source File -# Begin Source File - -SOURCE=.\pak.h -# End Source File # End Group # Begin Group "Resource Files"