quake2-rerelease-dll/rerelease/xatrix/g_xatrix_func.cpp
2023-08-07 14:48:30 -05:00

178 lines
4.2 KiB
C++

// Copyright (c) ZeniMax Media Inc.
// Licensed under the GNU General Public License 2.0.
#include "../g_local.h"
/*QUAKED rotating_light (0 .5 .8) (-8 -8 -8) (8 8 8) START_OFF ALARM
"health" if set, the light may be killed.
*/
// RAFAEL
// note to self
// the lights will take damage from explosions
// this could leave a player in total darkness very bad
constexpr spawnflags_t SPAWNFLAG_ROTATING_LIGHT_START_OFF = 1_spawnflag;
constexpr spawnflags_t SPAWNFLAG_ROTATING_LIGHT_ALARM = 2_spawnflag;
THINK(rotating_light_alarm) (edict_t *self) -> void
{
if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_START_OFF))
{
self->think = nullptr;
self->nextthink = 0_ms;
}
else
{
gi.sound(self, CHAN_NO_PHS_ADD | CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0);
self->nextthink = level.time + 1_sec;
}
}
DIE(rotating_light_killed) (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, const vec3_t &point, const mod_t &mod) -> void
{
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_WELDING_SPARKS);
gi.WriteByte(30);
gi.WritePosition(self->s.origin);
gi.WriteDir(vec3_origin);
gi.WriteByte(irandom(0xe0, 0xe8));
gi.multicast(self->s.origin, MULTICAST_PVS, false);
self->s.effects &= ~EF_SPINNINGLIGHTS;
self->use = nullptr;
self->think = G_FreeEdict;
self->nextthink = level.time + FRAME_TIME_S;
}
USE(rotating_light_use) (edict_t *self, edict_t *other, edict_t *activator) -> void
{
if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_START_OFF))
{
self->spawnflags &= ~SPAWNFLAG_ROTATING_LIGHT_START_OFF;
self->s.effects |= EF_SPINNINGLIGHTS;
if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_ALARM))
{
self->think = rotating_light_alarm;
self->nextthink = level.time + FRAME_TIME_S;
}
}
else
{
self->spawnflags |= SPAWNFLAG_ROTATING_LIGHT_START_OFF;
self->s.effects &= ~EF_SPINNINGLIGHTS;
}
}
void SP_rotating_light(edict_t *self)
{
self->movetype = MOVETYPE_STOP;
self->solid = SOLID_BBOX;
self->s.modelindex = gi.modelindex("models/objects/light/tris.md2");
self->s.frame = 0;
self->use = rotating_light_use;
if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_START_OFF))
self->s.effects &= ~EF_SPINNINGLIGHTS;
else
{
self->s.effects |= EF_SPINNINGLIGHTS;
}
if (!self->speed)
self->speed = 32;
// this is a real cheap way
// to set the radius of the light
// self->s.frame = self->speed;
if (!self->health)
{
self->health = 10;
self->max_health = self->health;
self->die = rotating_light_killed;
self->takedamage = true;
}
else
{
self->max_health = self->health;
self->die = rotating_light_killed;
self->takedamage = true;
}
if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_ALARM))
{
self->moveinfo.sound_start = gi.soundindex("misc/alarm.wav");
}
gi.linkentity(self);
}
/*QUAKED func_object_repair (1 .5 0) (-8 -8 -8) (8 8 8)
object to be repaired.
The default delay is 1 second
"delay" the delay in seconds for spark to occur
*/
THINK(object_repair_fx) (edict_t *ent) -> void
{
ent->nextthink = level.time + gtime_t::from_sec(ent->delay);
if (ent->health <= 100)
ent->health++;
else
{
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_WELDING_SPARKS);
gi.WriteByte(10);
gi.WritePosition(ent->s.origin);
gi.WriteDir(vec3_origin);
gi.WriteByte(irandom(0xe0, 0xe8));
gi.multicast(ent->s.origin, MULTICAST_PVS, false);
}
}
THINK(object_repair_dead) (edict_t *ent) -> void
{
G_UseTargets(ent, ent);
ent->nextthink = level.time + 10_hz;
ent->think = object_repair_fx;
}
THINK(object_repair_sparks) (edict_t *ent) -> void
{
if (ent->health <= 0)
{
ent->nextthink = level.time + 10_hz;
ent->think = object_repair_dead;
return;
}
ent->nextthink = level.time + gtime_t::from_sec(ent->delay);
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_WELDING_SPARKS);
gi.WriteByte(10);
gi.WritePosition(ent->s.origin);
gi.WriteDir(vec3_origin);
gi.WriteByte(irandom(0xe0, 0xe8));
gi.multicast(ent->s.origin, MULTICAST_PVS, false);
}
void SP_object_repair(edict_t *ent)
{
ent->movetype = MOVETYPE_NONE;
ent->solid = SOLID_BBOX;
ent->classname = "object_repair";
ent->mins = { -8, -8, 8 };
ent->maxs = { 8, 8, 8 };
ent->think = object_repair_sparks;
ent->nextthink = level.time + 1_sec;
ent->health = 100;
if (!ent->delay)
ent->delay = 1.0;
}