mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-15 00:41:21 +00:00
709 lines
17 KiB
C
709 lines
17 KiB
C
#include "g_local.h"
|
|
|
|
|
|
extern qboolean is_quad;
|
|
extern byte is_silenced;
|
|
|
|
void playQuadSound (edict_t *ent);
|
|
void Weapon_Generic (edict_t *ent,
|
|
int FRAME_ACTIVATE_LAST,
|
|
int FRAME_FIRE_LAST,
|
|
int FRAME_IDLE_LAST,
|
|
int FRAME_DEACTIVATE_LAST,
|
|
int *pause_frames,
|
|
int *fire_frames,
|
|
void (*fire)(edict_t *ent));
|
|
void NoAmmoWeaponChange (edict_t *ent);
|
|
void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed);
|
|
void barrel_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf);
|
|
|
|
void Grenade_Explode (edict_t *ent);
|
|
void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result);
|
|
|
|
//#ifdef USE_ZAERO_ITEMS_WEAPONS
|
|
void zCam_TrackEntity (struct edict_s *player, struct edict_s *track, qboolean playerVisiable, qboolean playerOffset);
|
|
void zCam_Stop (struct edict_s *player);
|
|
//#endif // USE_ZAERO_ITEMS_WEAPONS
|
|
|
|
void fire_empnuke(edict_t *ent, vec3_t center, int radius);
|
|
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
misc_securitycamera
|
|
|
|
This is where the visor locates too...
|
|
|
|
======================================================================
|
|
*/
|
|
//#ifdef USE_ZAERO_ITEMS_WEAPONS
|
|
void use_securitycamera (edict_t *self, edict_t *other, edict_t *activator)
|
|
{
|
|
self->active = !self->active;
|
|
}
|
|
|
|
#define CAMERA_FRAME_FIRST 0
|
|
#define CAMERA_FRAME_LAST 59
|
|
void securitycamera_think (edict_t *self)
|
|
{
|
|
if (self->active)
|
|
{
|
|
self->s.frame++;
|
|
if (self->s.frame > CAMERA_FRAME_LAST)
|
|
self->s.frame = CAMERA_FRAME_FIRST;
|
|
}
|
|
|
|
if (self->timeout > level.time)
|
|
{
|
|
self->s.effects |= EF_COLOR_SHELL;
|
|
self->s.renderfx |= RF_SHELL_GREEN;
|
|
}
|
|
else
|
|
{
|
|
self->s.effects &= ~EF_COLOR_SHELL;
|
|
self->s.renderfx &= ~RF_SHELL_GREEN;
|
|
}
|
|
|
|
self->nextthink = level.time + FRAMETIME;
|
|
}
|
|
|
|
void camera_pain (edict_t *self, edict_t *other, float kick, int damage)
|
|
{
|
|
self->timeout = level.time + FRAMETIME * 2;
|
|
}
|
|
|
|
void SP_misc_securitycamera (edict_t *self)
|
|
{
|
|
vec3_t offset, forward, up;
|
|
|
|
// no message? error
|
|
if (!self->message)
|
|
{
|
|
gi.error("misc_securitycamera w/o message");
|
|
G_FreeEdict(self);
|
|
return;
|
|
}
|
|
|
|
self->solid = SOLID_BBOX;
|
|
self->movetype = MOVETYPE_NONE;
|
|
self->s.modelindex = gi.modelindex("models/objects/camera/tris.md2");
|
|
|
|
// set the bounding box
|
|
VectorSet(self->mins, -16, -16, -32);
|
|
VectorSet(self->maxs, 16, 16, 0);
|
|
|
|
// set the angle of direction
|
|
VectorCopy(self->mangle, self->move_angles);
|
|
VectorSet(self->s.angles, 0, self->mangle[YAW], 0);
|
|
|
|
// get an offset
|
|
AngleVectors(self->s.angles, forward, NULL, up);
|
|
VectorSet(offset, 0, 0, 0);
|
|
VectorMA(offset, 8, forward, offset);
|
|
VectorMA(offset, -32, up, offset);
|
|
VectorAdd(self->s.origin, offset, self->move_origin);
|
|
|
|
if (self->targetname)
|
|
{
|
|
self->use = use_securitycamera;
|
|
self->active = false;
|
|
}
|
|
else
|
|
{
|
|
self->active = true;
|
|
}
|
|
self->think = securitycamera_think;
|
|
self->nextthink = level.time + FRAMETIME;
|
|
self->health = 1000; // Knightmare- was 1
|
|
self->takedamage = DAMAGE_IMMORTAL; // health will not be deducted
|
|
self->pain = camera_pain;
|
|
|
|
self->common_name = "Security Camera";
|
|
self->class_id = ENTITY_MISC_SECURITYCAMERA;
|
|
|
|
gi.linkentity(self);
|
|
}
|
|
|
|
char *camera_statusbar =
|
|
"xv 26 yb -75 string \"Tracking %s\" "
|
|
// timer
|
|
"if 24 " // was "if 20"
|
|
" xv 246 "
|
|
" num 3 25 " // was " num 3 21"
|
|
" xv 296 "
|
|
" pic 24 " // was " pic 20"
|
|
"endif "
|
|
;
|
|
|
|
void updateVisorHud (edict_t *ent)
|
|
{
|
|
static char buf[1024];
|
|
|
|
gi.WriteByte (svc_layout);
|
|
// sprintf(buf, camera_statusbar, ent->client->zCameraTrack->message);
|
|
Com_sprintf(buf, sizeof(buf), camera_statusbar, ent->client->zCameraTrack->message);
|
|
gi.WriteString(buf);
|
|
}
|
|
|
|
void startVisorStatic (edict_t *ent)
|
|
{
|
|
ent->client->zCameraStaticFramenum = level.time + FRAMETIME * 2;
|
|
}
|
|
|
|
void startVisor (edict_t *ent, edict_t *e)
|
|
{
|
|
// don't do anything if we're already at the destination camera
|
|
if (e == ent->client->zCameraTrack)
|
|
return;
|
|
|
|
// no more time?
|
|
if (ent->client->pers.visorFrames <= 0)
|
|
{
|
|
gi.cprintf (ent, PRINT_HIGH, "No time left for visor\n");
|
|
return;
|
|
}
|
|
|
|
// look thru the camera
|
|
zCam_TrackEntity (ent, e, true, true);
|
|
|
|
startVisorStatic (ent);
|
|
updateVisorHud (ent);
|
|
gi.unicast (ent, true); // reliably send to ent
|
|
ent->client->showscores = true;
|
|
|
|
// play activation sound
|
|
gi.sound (ent, CHAN_AUTO, gi.soundindex("items/visor/act.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void stopCamera (edict_t *self)
|
|
{
|
|
zCam_Stop (self);
|
|
self->client->showscores = false;
|
|
gi.sound (self, CHAN_AUTO, gi.soundindex("items/visor/deact.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
edict_t *findNextCamera (edict_t *old)
|
|
{
|
|
edict_t *e = NULL;
|
|
|
|
// first of all, are there *any* cameras?
|
|
e = G_Find(NULL, FOFS(classname), "misc_securitycamera");
|
|
if (e == NULL)
|
|
return NULL;
|
|
|
|
// start with the current and try to find another good camera
|
|
e = old;
|
|
while(1)
|
|
{
|
|
e = G_Find(e, FOFS(classname), "misc_securitycamera");
|
|
if (e == NULL)
|
|
continue; // loop back around
|
|
|
|
if (e == old)
|
|
return e;
|
|
|
|
if (!e->active)
|
|
continue;
|
|
|
|
return e;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void Use_Visor (edict_t *ent, gitem_t *item)
|
|
{
|
|
if (ent->client->zCameraTrack == NULL)
|
|
{
|
|
edict_t *e = findNextCamera(NULL);
|
|
if (e == NULL)
|
|
{
|
|
gi.cprintf(ent, PRINT_HIGH, "No cameras are available\n");
|
|
return;
|
|
}
|
|
|
|
if (ent->client->pers.visorFrames == 0)
|
|
ent->client->pers.visorFrames = (sk_visor_time->value * 10);
|
|
startVisor (ent, e);
|
|
}
|
|
else
|
|
{
|
|
edict_t *e = findNextCamera(ent->client->zCameraTrack);
|
|
if (e != NULL &&
|
|
e != ent->client->zCameraTrack)
|
|
{
|
|
ent->client->zCameraTrack = e;
|
|
// play sound
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("items/visor/act.wav"), 1, ATTN_NORM, 0);
|
|
startVisorStatic (ent);
|
|
updateVisorHud (ent);
|
|
gi.unicast (ent, true); // reliably send to ent
|
|
}
|
|
}
|
|
}
|
|
//#endif // USE_ZAERO_ITEMS_WEAPONS
|
|
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
EMP Nuke
|
|
|
|
======================================================================
|
|
*/
|
|
void weapon_EMPNuke_fire (edict_t *ent)
|
|
{
|
|
fire_empnuke (ent, ent->s.origin, 1024);
|
|
// fire_empnuke (ent, ent->s.origin, sk_empnuke_radius->value);
|
|
|
|
ent->client->pers.inventory[ent->client->ammo_index]--;
|
|
|
|
if (ent->client->pers.inventory[ent->client->ammo_index])
|
|
{
|
|
ent->client->weaponstate = WEAPON_ACTIVATING;
|
|
ent->client->ps.gunframe = 0;
|
|
}
|
|
else
|
|
{
|
|
NoAmmoWeaponChange (ent);
|
|
ChangeWeapon(ent);
|
|
}
|
|
}
|
|
|
|
|
|
void Weapon_EMPNuke (edict_t *ent)
|
|
{
|
|
static int pause_frames[] = {25, 34, 43, 0};
|
|
static int fire_frames[] = {16, 0};
|
|
|
|
#ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows...
|
|
if (deathmatch->value)
|
|
#endif
|
|
{
|
|
if (ent->client->ps.gunframe == 0)
|
|
{
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_act.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
else if (ent->client->ps.gunframe == 11)
|
|
{
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_spin.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
else if (ent->client->ps.gunframe == 35)
|
|
{
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_idle.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
}
|
|
|
|
Weapon_Generic (ent, 9, 16, 43, 47, pause_frames, fire_frames, weapon_EMPNuke_fire);
|
|
}
|
|
|
|
|
|
void empnukeFinish (edict_t *ent)
|
|
{
|
|
// gi.sound(ent, CHAN_VOICE, gi.soundindex("items/empnuke/empdie.wav"), 1, ATTN_NORM, 0);
|
|
G_FreeEdict(ent);
|
|
}
|
|
|
|
|
|
void empBlastAnim (edict_t *ent)
|
|
{
|
|
ent->s.frame++;
|
|
ent->s.skinnum++;
|
|
|
|
if (ent->s.frame > 5)
|
|
{
|
|
ent->svflags |= SVF_NOCLIENT;
|
|
ent->s.modelindex = 0;
|
|
ent->s.frame = 0;
|
|
ent->s.skinnum = 0;
|
|
|
|
// ent->s.sound = gi.soundindex ("items/empnuke/empactive.wav");
|
|
|
|
ent->think = empnukeFinish;
|
|
ent->nextthink = level.time + 30;
|
|
}
|
|
else
|
|
{
|
|
ent->nextthink = level.time + FRAMETIME;
|
|
}
|
|
}
|
|
|
|
|
|
void fire_empnuke (edict_t *ent, vec3_t center, int radius)
|
|
{
|
|
edict_t *empnuke;
|
|
|
|
// gi.sound(ent, CHAN_VOICE, gi.soundindex("items/empnuke/empfire.wav"), 1, ATTN_NORM, 0);
|
|
gi.sound(ent, CHAN_VOICE, gi.soundindex("items/empnuke/emp_trg.wav"), 1, ATTN_NORM, 0);
|
|
|
|
empnuke = G_Spawn();
|
|
empnuke->owner = ent;
|
|
empnuke->dmg = radius;
|
|
VectorCopy(center, empnuke->s.origin);
|
|
empnuke->classname = "EMPNukeCenter";
|
|
/// empnuke->svflags |= SVF_NOCLIENT;
|
|
empnuke->movetype = MOVETYPE_NONE;
|
|
empnuke->s.modelindex = gi.modelindex("models/objects/b_explode/tris.md2");
|
|
empnuke->s.skinnum = 0;
|
|
// empnuke->s.renderfx = RF_TRANSLUCENT | RF_FULLBRIGHT;
|
|
// empnuke->s.renderfx = RF_TRANSLUCENT;
|
|
empnuke->moreflags |= FL2_DO_NOT_REFLECT; // Knightmare- do not reflect flag
|
|
|
|
empnuke->think = empBlastAnim;
|
|
empnuke->nextthink = level.time + FRAMETIME;
|
|
|
|
// empnuke->think = G_FreeEdict;
|
|
// empnuke->nextthink = level.time + 30;
|
|
|
|
empnuke->common_name = "EMP Nuke Center";
|
|
empnuke->class_id = ENTITY_Z_EMPNUKECENTER;
|
|
|
|
gi.linkentity (empnuke);
|
|
|
|
// gi.sound(empnuke, CHAN_VOICE, gi.soundindex("items/empnuke/emp_exp.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
|
|
qboolean EMPNukeCheck (edict_t *ent, vec3_t pos)
|
|
{
|
|
edict_t *check = NULL;
|
|
|
|
while ((check = G_Find (check, FOFS(classname), "EMPNukeCenter")) != NULL)
|
|
{
|
|
vec3_t v;
|
|
|
|
if (check->owner != ent)
|
|
{
|
|
VectorSubtract (check->s.origin, pos, v);
|
|
if (VectorLength(v) <= check->dmg)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
Plasma Shield
|
|
|
|
======================================================================
|
|
*/
|
|
//#ifdef USE_ZAERO_ITEMS_WEAPONS
|
|
void PlasmaShield_die (edict_t *self)
|
|
{
|
|
#ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows...
|
|
if (deathmatch->value)
|
|
#endif
|
|
{
|
|
gi.sound(self, CHAN_VOICE, gi.soundindex("items/plasmashield/psdie.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
G_FreeEdict(self);
|
|
}
|
|
|
|
|
|
void PlasmaShield_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
|
{
|
|
PlasmaShield_die(self);
|
|
}
|
|
|
|
|
|
void Use_PlasmaShield (edict_t *ent, gitem_t *item)
|
|
{
|
|
int ammoIdx = ITEM_INDEX(item);
|
|
edict_t *PlasmaShield;
|
|
vec3_t forward, right, up, frontbottomleft, backtopright;
|
|
|
|
if (!ent->client->pers.inventory[ammoIdx])
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (EMPNukeCheck(ent, ent->s.origin))
|
|
{
|
|
gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0);
|
|
return;
|
|
}
|
|
|
|
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
|
|
ent->client->pers.inventory[ammoIdx]--;
|
|
|
|
#ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows...
|
|
if (deathmatch->value)
|
|
#endif
|
|
{
|
|
gi.sound(ent, CHAN_VOICE, gi.soundindex("items/plasmashield/psfire.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
PlasmaShield = G_Spawn();
|
|
// PlasmaShield->owner = ent;
|
|
PlasmaShield->classname = "PlasmaShield";
|
|
PlasmaShield->movetype = MOVETYPE_PUSH;
|
|
PlasmaShield->solid = SOLID_BBOX;
|
|
PlasmaShield->s.modelindex = gi.modelindex("sprites/plasmashield.sp2");
|
|
PlasmaShield->s.effects |= EF_POWERSCREEN;
|
|
PlasmaShield->s.sound = gi.soundindex ("items/plasmashield/psactive.wav");
|
|
|
|
AngleVectors (ent->client->v_angle, forward, right, up);
|
|
vectoangles (forward, PlasmaShield->s.angles);
|
|
|
|
VectorMA (ent->s.origin, 50, forward, PlasmaShield->s.origin);
|
|
|
|
// fudge the bbox
|
|
VectorScale(forward, 10, frontbottomleft);
|
|
VectorMA(frontbottomleft, -30, right, frontbottomleft);
|
|
VectorMA(frontbottomleft, -30, up, frontbottomleft);
|
|
|
|
VectorScale(forward, 5, backtopright);
|
|
VectorMA(backtopright, 30, right, backtopright);
|
|
VectorMA(backtopright, 50, up, backtopright);
|
|
|
|
ClearBounds (PlasmaShield->mins, PlasmaShield->maxs);
|
|
|
|
AddPointToBounds (frontbottomleft, PlasmaShield->mins, PlasmaShield->maxs);
|
|
AddPointToBounds (backtopright, PlasmaShield->mins, PlasmaShield->maxs);
|
|
|
|
PlasmaShield->health = PlasmaShield->max_health = sk_plasmashield_health->value; // was 4000
|
|
PlasmaShield->die = PlasmaShield_killed;
|
|
PlasmaShield->takedamage = DAMAGE_YES;
|
|
|
|
PlasmaShield->think = PlasmaShield_die;
|
|
PlasmaShield->nextthink = level.time + sk_plasmashield_life->value; // was 10
|
|
|
|
PlasmaShield->common_name = "Plasma Shield";
|
|
PlasmaShield->class_id = ENTITY_Z_PLASMASHIELD;
|
|
|
|
|
|
gi.linkentity (PlasmaShield);
|
|
}
|
|
//#endif // USE_ZAERO_ITEMS_WEAPONS
|
|
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
misc_crate
|
|
|
|
======================================================================
|
|
*/
|
|
|
|
void setupCrate (edict_t *self)
|
|
{
|
|
self->solid = SOLID_BBOX;
|
|
self->movetype = MOVETYPE_FALLFLOAT;
|
|
// self->movetype = MOVETYPE_STEP;
|
|
|
|
if (!self->mass)
|
|
self->mass = 400;
|
|
|
|
self->touch = barrel_touch;
|
|
self->think = M_droptofloor;
|
|
self->nextthink = level.time + 2 * FRAMETIME;
|
|
|
|
self->common_name = "Pushable Crate";
|
|
self->class_id = ENTITY_MISC_CRATE;
|
|
|
|
gi.linkentity(self);
|
|
}
|
|
|
|
void SP_misc_crate (edict_t *self)
|
|
{
|
|
// setup specific to this size
|
|
self->s.modelindex = gi.modelindex("models/objects/crate/crate64.md2");
|
|
VectorSet (self->mins, -32, -32, 0);
|
|
VectorSet (self->maxs, 32, 32, 64);
|
|
|
|
// generic crate setup
|
|
setupCrate(self);
|
|
}
|
|
|
|
void SP_misc_crate_medium (edict_t *self)
|
|
{
|
|
// setup specific to this size
|
|
self->s.modelindex = gi.modelindex("models/objects/crate/crate48.md2");
|
|
VectorSet (self->mins, -24, -24, 0);
|
|
VectorSet (self->maxs, 24, 24, 48);
|
|
|
|
// generic crate setup
|
|
setupCrate(self);
|
|
}
|
|
|
|
void SP_misc_crate_small (edict_t *self)
|
|
{
|
|
// setup specific to this size
|
|
self->s.modelindex = gi.modelindex("models/objects/crate/crate32.md2");
|
|
VectorSet (self->mins, -16, -16, 0);
|
|
VectorSet (self->maxs, 16, 16, 32);
|
|
|
|
// generic crate setup
|
|
setupCrate(self);
|
|
}
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
misc_seat
|
|
|
|
======================================================================
|
|
*/
|
|
|
|
void SP_misc_seat (edict_t *self)
|
|
{
|
|
self->s.modelindex = gi.modelindex("models/objects/seat/tris.md2");
|
|
VectorSet(self->mins, -16, -16, 0);
|
|
VectorSet(self->maxs, 16, 16, 40);
|
|
|
|
// make this pushable
|
|
setupCrate(self);
|
|
|
|
self->common_name = "Ejection Seat";
|
|
self->class_id = ENTITY_MISC_SEAT;
|
|
}
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
misc_commdish
|
|
|
|
======================================================================
|
|
*/
|
|
|
|
void Anim_CommDish (edict_t *self)
|
|
{
|
|
self->s.frame++;
|
|
|
|
if (self->s.frame >= 98)
|
|
{
|
|
self->s.frame = 98;
|
|
}
|
|
else
|
|
{
|
|
self->nextthink = level.time + FRAMETIME;
|
|
}
|
|
}
|
|
|
|
void Use_CommDish (edict_t *ent, edict_t *other, edict_t *activator)
|
|
{
|
|
ent->nextthink = level.time + FRAMETIME;
|
|
ent->think = Anim_CommDish;
|
|
ent->use = NULL;
|
|
gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/commdish.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void SP_misc_commdish (edict_t *self)
|
|
{
|
|
if (deathmatch->value)
|
|
{ // auto-remove for deathmatch
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
|
|
self->class_id = ENTITY_MISC_COMMDISH;
|
|
|
|
self->solid = SOLID_BBOX;
|
|
self->movetype = MOVETYPE_STEP;
|
|
|
|
self->model = "models/objects/satdish/tris.md2";
|
|
self->s.modelindex = gi.modelindex (self->model);
|
|
VectorSet (self->mins, -100, -100, 0);
|
|
VectorSet (self->maxs, 100, 100, 275);
|
|
|
|
self->monsterinfo.aiflags = AI_NOSTEP;
|
|
|
|
self->think = M_droptofloor;
|
|
self->nextthink = level.time + 2 * FRAMETIME;
|
|
self->use = Use_CommDish;
|
|
|
|
gi.linkentity (self);
|
|
}
|
|
|
|
/*
|
|
======================================================================
|
|
|
|
func_barrier
|
|
|
|
======================================================================
|
|
*/
|
|
|
|
qboolean thruBarrier (edict_t *targ, edict_t *inflictor)
|
|
{
|
|
trace_t tr;
|
|
edict_t *e = inflictor;
|
|
while(e)
|
|
{
|
|
tr = gi.trace(e->s.origin, NULL, NULL, targ->s.origin, e, MASK_SHOT);
|
|
if (!tr.ent || tr.fraction >= 1.0)
|
|
return false;
|
|
|
|
if (tr.ent == targ)
|
|
return false;
|
|
|
|
if (tr.ent->classname && Q_stricmp(tr.ent->classname, "func_barrier") == 0)
|
|
return true;
|
|
|
|
if (e == tr.ent)
|
|
break;
|
|
|
|
e = tr.ent;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void barrier_think (edict_t *self)
|
|
{
|
|
if (self->timeout > level.time)
|
|
{
|
|
self->svflags &= ~SVF_NOCLIENT;
|
|
}
|
|
else
|
|
{
|
|
self->svflags |= SVF_NOCLIENT;
|
|
}
|
|
|
|
self->nextthink = level.time + FRAMETIME;
|
|
}
|
|
|
|
void barrier_pain (edict_t *self, edict_t *other, float kick, int damage)
|
|
{
|
|
self->timeout = level.time + FRAMETIME * 2;
|
|
if (self->damage_debounce_time < level.time)
|
|
{
|
|
gi.sound (self, CHAN_AUTO, gi.soundindex("weapons/lashit.wav"), 1, ATTN_NORM, 0);
|
|
self->damage_debounce_time = level.time + FRAMETIME * 2;
|
|
}
|
|
}
|
|
void barrier_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
|
{
|
|
if (other == world)
|
|
return;
|
|
|
|
self->timeout = level.time + FRAMETIME * 2;
|
|
if (self->touch_debounce_time < level.time)
|
|
{
|
|
gi.sound (self, CHAN_AUTO, gi.soundindex("weapons/lashit.wav"), 1, ATTN_NORM, 0);
|
|
self->touch_debounce_time = level.time + FRAMETIME * 2;
|
|
}
|
|
}
|
|
|
|
void SP_func_barrier (edict_t *self)
|
|
{
|
|
self->class_id = ENTITY_FUNC_BARRIER;
|
|
|
|
self->solid = SOLID_BBOX;
|
|
self->movetype = MOVETYPE_NONE;
|
|
self->s.modelindex = gi.modelindex("models/objects/wall/tris.md2");
|
|
self->svflags = SVF_NOCLIENT;
|
|
self->s.effects = EF_BFG;
|
|
|
|
self->think = barrier_think;
|
|
self->nextthink = level.time + FRAMETIME;
|
|
self->touch = barrier_touch;
|
|
self->health = 1000; // Knightmare- was 1
|
|
self->takedamage = DAMAGE_IMMORTAL; // health will not be deducted
|
|
self->pain = barrier_pain;
|
|
|
|
gi.linkentity(self);
|
|
}
|