1 #include "door_secret.qh"
3 void fd_secret_move1(entity this);
4 void fd_secret_move2(entity this);
5 void fd_secret_move3(entity this);
6 void fd_secret_move4(entity this);
7 void fd_secret_move5(entity this);
8 void fd_secret_move6(entity this);
9 void fd_secret_done(entity this);
11 const float SECRET_OPEN_ONCE = 1; // stays open
12 const float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
13 const float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
14 const float SECRET_NO_SHOOT = 8; // only opened by trigger
15 const float SECRET_YES_SHOOT = 16; // shootable even if targeted
17 void fd_secret_use(entity this, entity actor, entity trigger)
23 if (!this.bot_attack) {
24 IL_PUSH(g_bot_targets, this);
26 this.bot_attack = true;
28 // exit if still moving around...
29 if (this.origin != this.oldorigin) {
33 message_save = this.message;
34 this.message = ""; // no more message
35 SUB_UseTargets(this, actor, trigger); // fire all targets / killtargets
36 this.message = message_save;
38 this.velocity = '0 0 0';
40 // Make a sound, wait a little...
42 if (this.noise1 != "") {
43 _sound(this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
45 this.nextthink = this.ltime + 0.1;
47 temp = 1 - (this.spawnflags & SECRET_1ST_LEFT); // 1 or -1
48 makevectors(this.mangle);
51 if (this.spawnflags & SECRET_1ST_DOWN) {
52 this.t_width = fabs(v_up * this.size);
54 this.t_width = fabs(v_right * this.size);
59 this.t_length = fabs(v_forward * this.size);
62 if (this.spawnflags & SECRET_1ST_DOWN) {
63 this.dest1 = this.origin - v_up * this.t_width;
65 this.dest1 = this.origin + v_right * (this.t_width * temp);
68 this.dest2 = this.dest1 + v_forward * this.t_length;
69 SUB_CalcMove(this, this.dest1, TSPEED_LINEAR, this.speed, fd_secret_move1);
70 if (this.noise2 != "") {
71 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
75 void fd_secret_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
77 fd_secret_use(this, NULL, NULL);
80 // Wait after first movement...
81 void fd_secret_move1(entity this)
83 this.nextthink = this.ltime + 1.0;
84 setthink(this, fd_secret_move2);
85 if (this.noise3 != "") {
86 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
90 // Start moving sideways w/sound...
91 void fd_secret_move2(entity this)
93 if (this.noise2 != "") {
94 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
96 SUB_CalcMove(this, this.dest2, TSPEED_LINEAR, this.speed, fd_secret_move3);
99 // Wait here until time to go back...
100 void fd_secret_move3(entity this)
102 if (this.noise3 != "") {
103 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
105 if (!(this.spawnflags & SECRET_OPEN_ONCE)) {
106 this.nextthink = this.ltime + this.wait;
107 setthink(this, fd_secret_move4);
112 void fd_secret_move4(entity this)
114 if (this.noise2 != "") {
115 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
117 SUB_CalcMove(this, this.dest1, TSPEED_LINEAR, this.speed, fd_secret_move5);
121 void fd_secret_move5(entity this)
123 this.nextthink = this.ltime + 1.0;
124 setthink(this, fd_secret_move6);
125 if (this.noise3 != "") {
126 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
130 void fd_secret_move6(entity this)
132 if (this.noise2 != "") {
133 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
135 SUB_CalcMove(this, this.oldorigin, TSPEED_LINEAR, this.speed, fd_secret_done);
138 void fd_secret_done(entity this)
140 if (this.spawnflags & SECRET_YES_SHOOT) {
142 this.takedamage = DAMAGE_YES;
143 // this.th_pain = fd_secret_use;
145 if (this.noise3 != "") {
146 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
150 .float door_finished;
152 void secret_blocked(entity this, entity blocker)
154 if (time < this.door_finished) {
157 this.door_finished = time + 0.5;
158 // T_Damage (other, this, this, this.dmg, this.dmg, this.deathtype, DT_IMPACT, (this.absmin + this.absmax) * 0.5, '0 0 0', Obituary_Generic);
168 void secret_touch(entity this, entity toucher)
170 if (!toucher.iscreature) {
173 if (this.door_finished > time) {
177 this.door_finished = time + 2;
180 if (IS_CLIENT(toucher)) {
181 centerprint(toucher, this.message);
183 play2(toucher, this.noise);
187 void secret_reset(entity this)
189 if (this.spawnflags & SECRET_YES_SHOOT) {
191 this.takedamage = DAMAGE_YES;
193 setorigin(this, this.oldorigin);
194 setthink(this, func_null);
198 /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
199 Basic secret door. Slides back, then to the side. Angle determines direction.
200 wait = # of seconds before coming back
201 1st_left = 1st move is left of arrow
202 1st_down = 1st move is down from arrow
203 always_shoot = even if targeted, keep shootable
204 t_width = override WIDTH to move back (or height if going down)
205 t_length = override LENGTH to move sideways
206 "dmg" damage to inflict when blocked (2 default)
208 If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
215 spawnfunc(func_door_secret)
217 /*if (!this.deathtype) // map makers can override this
218 this.deathtype = " got in the way";*/
220 if (!this.dmg) { this.dmg = 2; }
223 this.mangle = this.angles;
224 this.angles = '0 0 0';
225 this.classname = "door";
226 if (!InitMovingBrushTrigger(this)) { return; }
227 this.effects |= EF_LOWPRECISION;
229 if (this.noise == "") { this.noise = "misc/talk.wav"; }
230 precache_sound(this.noise);
232 settouch(this, secret_touch);
233 setblocked(this, secret_blocked);
235 this.use = fd_secret_use;
236 if (THIS_TARGETED) {} else {
237 this.spawnflags |= SECRET_YES_SHOOT;
240 if (this.spawnflags & SECRET_YES_SHOOT) {
242 this.takedamage = DAMAGE_YES;
243 this.event_damage = fd_secret_damage;
245 this.oldorigin = this.origin;
247 this.wait = 5; // seconds before closing
249 this.reset = secret_reset;