#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); }