thirtyflightsofloving/awaken2/g_newfnc.c
Knightmare66 115428abd6 Added missing skinnum field to model_spawn in 3ZB2 and Awakening2 game DLLs.
Added custom attenuation support to func_plat2 in 3ZB2 and all func_ entities in Awakening2 game DLLs.
Added support for sounds = 1 for silent func_door_secret and func_door_secret2 in 3ZB2 and Awakening game DLLs.
2021-03-11 02:33:38 -05:00

457 lines
12 KiB
C

#include "g_local.h"
//void plat_CalcMove (edict_t *ent, vec3_t dest, void(*func)(edict_t*));
void Move_Calc (edict_t *ent, vec3_t dest, void(*func)(edict_t*));
void fd_secret_move1(edict_t *self);
void fd_secret_move2(edict_t *self);
void fd_secret_move3(edict_t *self);
void fd_secret_move4(edict_t *self);
void fd_secret_move5(edict_t *self);
void fd_secret_move6(edict_t *self);
void fd_secret_done(edict_t *self);
/*
=============================================================================
SECRET DOORS
=============================================================================
*/
#define SEC_OPEN_ONCE 1 // stays open
#define SEC_1ST_LEFT 2 // 1st move is left of arrow
#define SEC_1ST_DOWN 4 // 1st move is down from arrow
#define SEC_NO_SHOOT 8 // only opened by trigger
#define SEC_YES_SHOOT 16 // shootable even if targeted
#define SEC_MOVE_RIGHT 32
#define SEC_MOVE_FORWARD 64
#define STATE_TOP 0
#define STATE_BOTTOM 1
#define STATE_UP 2
#define STATE_DOWN 3
#define STATE_LOWEST 4
void fd_secret_use (edict_t *self, edict_t *other, edict_t *activator)
{
edict_t *ent;
// gi.dprintf("fd_secret_use\n");
if (self->flags & FL_TEAMSLAVE)
return;
// Knightmare- added sound
if (self->moveinfo.sound_start)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, self->attenuation, 0); // was ATTN_STATIC
if (self->moveinfo.sound_middle) {
self->s.sound = self->moveinfo.sound_middle;
#ifdef LOOP_SOUND_ATTENUATION
self->s.attenuation = self->attenuation;
#endif
}
// trigger all paired doors
for (ent = self ; ent ; ent = ent->teamchain)
{
// Move_Calc(ent, ent->moveinfo.start_origin, fd_secret_move1);
if (self->moveinfo.state == STATE_LOWEST)
{
ent->moveinfo.state = STATE_DOWN;
Move_Calc (ent, ent->pos1, fd_secret_move1);
door_use_areaportals (self, true);
}
else if (self->moveinfo.state == STATE_TOP) // Knightmare added
{
ent->moveinfo.state = STATE_UP;
Move_Calc (ent, ent->pos1, fd_secret_move5);
}
}
}
void fd_secret_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
// gi.dprintf("fd_secret_killed\n");
self->health = self->max_health;
self->takedamage = DAMAGE_NO;
if (self->flags & FL_TEAMSLAVE && self->teammaster && self->teammaster->takedamage != DAMAGE_NO)
fd_secret_killed (self->teammaster, inflictor, attacker, damage, point);
else
fd_secret_use (self, inflictor, attacker);
}
// Wait after first movement...
void fd_secret_move1 (edict_t *self)
{
// gi.dprintf("fd_secret_move1\n");
self->nextthink = level.time + 1.0;
self->think = fd_secret_move2;
self->moveinfo.state = STATE_BOTTOM;
// Knightmare- added sound
self->s.sound = 0;
if (self->moveinfo.sound_end)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, self->attenuation, 0); // was ATTN_STATIC
}
// Start moving sideways w/sound...
void fd_secret_move2 (edict_t *self)
{
// gi.dprintf("fd_secret_move2\n");
// Knightmare- added sound
if (self->moveinfo.sound_start)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, self->attenuation, 0); // was ATTN_STATIC
if (self->moveinfo.sound_middle) {
self->s.sound = self->moveinfo.sound_middle;
#ifdef LOOP_SOUND_ATTENUATION
self->s.attenuation = self->attenuation;
#endif
}
self->moveinfo.state = STATE_UP;
Move_Calc (self, self->pos2, fd_secret_move3); // was self->moveinfo.end_origin
}
// Wait here until time to go back...
void fd_secret_move3(edict_t *self)
{
// gi.dprintf("fd_secret_move3\n");
if (!(self->spawnflags & SEC_OPEN_ONCE))
{
self->nextthink = level.time + self->wait;
self->think = fd_secret_move4;
}
self->moveinfo.state = STATE_TOP;
// added sound
self->s.sound = 0;
if (self->moveinfo.sound_end)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, self->attenuation, 0); // was ATTN_STATIC
}
// Move backward...
void fd_secret_move4 (edict_t *self)
{
// gi.dprintf("fd_secret_move4\n");
// Knightmare- added sound
if (self->moveinfo.sound_start)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, self->attenuation, 0); // was ATTN_STATIC
if (self->moveinfo.sound_middle) {
self->s.sound = self->moveinfo.sound_middle;
#ifdef LOOP_SOUND_ATTENUATION
self->s.attenuation = self->attenuation;
#endif
}
self->moveinfo.state = STATE_UP;
Move_Calc (self, self->pos1, fd_secret_move5); // was self->moveinfo.start_origin
}
// Wait 1 second...
void fd_secret_move5 (edict_t *self)
{
// gi.dprintf("fd_secret_move5\n");
self->nextthink = level.time + 1.0;
self->think = fd_secret_move6;
self->moveinfo.state = STATE_BOTTOM;
// Knightmare- added sound
self->s.sound = 0;
if (self->moveinfo.sound_end)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, self->attenuation, 0); // was ATTN_STATIC
}
void fd_secret_move6 (edict_t *self)
{
// gi.dprintf("fd_secret_move6\n");
// Knightmare- added sound
if (self->moveinfo.sound_start)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, self->attenuation, 0); // was ATTN_STATIC
if (self->moveinfo.sound_middle) {
self->s.sound = self->moveinfo.sound_middle;
#ifdef LOOP_SOUND_ATTENUATION
self->s.attenuation = self->attenuation;
#endif
}
self->moveinfo.state = STATE_DOWN;
Move_Calc (self, self->pos0, fd_secret_done); // was self->move_origin
}
void fd_secret_done (edict_t *self)
{
// gi.dprintf("fd_secret_done\n");
if (!self->targetname || self->spawnflags & SEC_YES_SHOOT)
{
self->health = 1;
self->takedamage = DAMAGE_YES;
self->die = fd_secret_killed;
}
self->moveinfo.state = STATE_LOWEST;
// Knightmare- added sound
self->s.sound = 0;
if (self->moveinfo.sound_end)
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_end, 1, self->attenuation, 0); // was ATTN_STATIC
door_use_areaportals (self, false);
}
void secret_blocked (edict_t *self, edict_t *other)
{
if (!(self->flags & FL_TEAMSLAVE))
T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 0, 0, MOD_CRUSH);
// if (time < self->attack_finished)
// return;
// self->attack_finished = time + 0.5;
// T_Damage (other, self, self, self->dmg);
}
/*
================
secret_touch
Prints messages
================
*/
void secret_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
if (other->health <= 0)
return;
if (!(other->client))
return;
if (self->monsterinfo.attack_finished > level.time)
return;
self->monsterinfo.attack_finished = level.time + 2;
if (self->message)
{
gi.centerprintf (other, self->message);
// fixme - put this sound back??
// gi.sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
}
}
/*QUAKED func_door_secret2 (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot slide_right slide_forward
Basic secret door. Slides back, then to the left. Angle determines direction.
FLAGS:
open_once = not implemented yet
1st_left = 1st move is left/right of arrow
1st_down = 1st move is forwards/backwards
no_shoot = not implemented yet
always_shoot = even if targeted, keep shootable
reverse_left = the sideways move will be to right of arrow
reverse_back = the to/fro move will be forward
VALUES:
wait = # of seconds before coming back (5 default)
dmg = damage to inflict when blocked (2 default)
*/
void SP_func_door_secret2 (edict_t *ent)
{
vec3_t forward, right, up;
// float lrSize, fbSize;
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");
}
else
{
ent->moveinfo.sound_start = 0;
ent->moveinfo.sound_middle = 0;
ent->moveinfo.sound_end = 0;
}
if (ent->attenuation <= 0) // Knightmare added
ent->attenuation = ATTN_STATIC;
if (!ent->dmg)
ent->dmg = 2;
AngleVectors(ent->s.angles, forward, right, up);
VectorCopy (ent->s.origin, ent->pos0);
VectorCopy(ent->s.origin, ent->move_origin);
VectorCopy(ent->s.angles, ent->move_angles);
G_SetMovedir (ent->s.angles, ent->movedir);
ent->movetype = MOVETYPE_PUSH;
ent->solid = SOLID_BSP;
gi.setmodel (ent, ent->model);
if (ent->move_angles[1] == 0 || ent->move_angles[1] == 180)
{
// lrSize = ent->size[1];
// fbSize = ent->size[0];
if (!ent->width)
ent->width = ent->size[1] - 2; // was lrSize
if (!ent->length)
ent->length = ent->size[0] - 2; // was fbSize
}
else if (ent->move_angles[1] == 90 || ent->move_angles[1] == 270)
{
// lrSize = ent->size[0];
// fbSize = ent->size[1];
if (!ent->width)
ent->width = ent->size[0] - 2; // was lrSize
if (!ent->length)
ent->length = ent->size[1] - 2; // was fbSize
}
else
{
gi.dprintf("Secret door not at 0, 90, 180, 270!\n");
}
if (ent->spawnflags & SEC_MOVE_FORWARD) {
VectorScale (forward, ent->length, forward); // was fbSize
}
else {
VectorScale (forward, ent->length * -1 , forward); // was fbSize
}
if (ent->spawnflags & SEC_MOVE_RIGHT) {
VectorScale (right, ent->width, right); // was lrSize
}
else {
VectorScale (right, ent->width * -1, right); // was lrSize
}
if (ent->spawnflags & SEC_1ST_DOWN) {
VectorAdd (ent->s.origin, forward, ent->pos1); // was ent->moveinfo.start_origin
VectorAdd (ent->pos1, right, ent->pos2); // was ent->moveinfo.end_origin
}
else {
VectorAdd (ent->s.origin, right, ent->pos1); // was ent->moveinfo.start_origin
VectorAdd (ent->pos1, forward, ent->pos2); // was ent->moveinfo.end_origin
}
ent->touch = secret_touch;
ent->blocked = secret_blocked;
ent->use = fd_secret_use;
ent->moveinfo.speed = 50;
ent->moveinfo.accel = 50;
ent->moveinfo.decel = 50;
ent->moveinfo.state = STATE_LOWEST;
if (!ent->targetname || ent->spawnflags & SEC_YES_SHOOT)
{
ent->health = 1;
ent->max_health = ent->health;
ent->takedamage = DAMAGE_YES;
ent->die = fd_secret_killed;
}
if (!ent->wait)
ent->wait = 5; // 5 seconds before closing
gi.linkentity(ent);
}
// ==================================================
#define FWALL_START_ON 1
void force_wall_think (edict_t *self)
{
if (!self->wait)
{
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_FORCEWALL);
gi.WritePosition (self->pos1);
gi.WritePosition (self->pos2);
gi.WriteByte (self->style);
gi.multicast (self->offset, MULTICAST_PVS);
}
self->think = force_wall_think;
self->nextthink = level.time + 0.1;
}
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;
gi.linkentity( self );
}
else
{
self->wait = 0;
self->think = force_wall_think;
self->nextthink = level.time + 0.1;
self->solid = SOLID_BSP;
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)
{
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;
ent->wait = 1;
if (ent->spawnflags & FWALL_START_ON)
{
ent->solid = SOLID_BSP;
ent->think = force_wall_think;
ent->nextthink = level.time + 0.1;
}
else
ent->solid = SOLID_NOT;
ent->use = force_wall_use;
ent->svflags = SVF_NOCLIENT;
gi.linkentity(ent);
}