2 void fd_secret_move1(entity this);
3 void fd_secret_move2(entity this);
4 void fd_secret_move3(entity this);
5 void fd_secret_move4(entity this);
6 void fd_secret_move5(entity this);
7 void fd_secret_move6(entity this);
8 void fd_secret_done(entity this);
10 const float SECRET_OPEN_ONCE = 1; // stays open
11 const float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
12 const float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
13 const float SECRET_NO_SHOOT = 8; // only opened by trigger
14 const float SECRET_YES_SHOOT = 16; // shootable even if targeted
16 void fd_secret_use(entity this, entity actor, entity trigger)
22 this.bot_attack = true;
24 // exit if still moving around...
25 if (this.origin != this.oldorigin)
28 message_save = this.message;
29 this.message = ""; // no more message
30 SUB_UseTargets(this, actor, trigger); // fire all targets / killtargets
31 this.message = message_save;
33 this.velocity = '0 0 0';
35 // Make a sound, wait a little...
37 if (this.noise1 != "")
38 _sound(this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
39 this.SUB_NEXTTHINK = this.SUB_LTIME + 0.1;
41 temp = 1 - (this.spawnflags & SECRET_1ST_LEFT); // 1 or -1
42 makevectors(this.mangle);
46 if (this.spawnflags & SECRET_1ST_DOWN)
47 this.t_width = fabs(v_up * this.size);
49 this.t_width = fabs(v_right * this.size);
53 this.t_length = fabs(v_forward * this.size);
55 if (this.spawnflags & SECRET_1ST_DOWN)
56 this.dest1 = this.origin - v_up * this.t_width;
58 this.dest1 = this.origin + v_right * (this.t_width * temp);
60 this.dest2 = this.dest1 + v_forward * this.t_length;
61 SUB_CalcMove(this, this.dest1, TSPEED_LINEAR, this.speed, fd_secret_move1);
62 if (this.noise2 != "")
63 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
66 void fd_secret_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
68 fd_secret_use(this, NULL, NULL);
71 // Wait after first movement...
72 void fd_secret_move1(entity this)
74 this.SUB_NEXTTHINK = this.SUB_LTIME + 1.0;
75 setthink(this, fd_secret_move2);
76 if (this.noise3 != "")
77 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
80 // Start moving sideways w/sound...
81 void fd_secret_move2(entity this)
83 if (this.noise2 != "")
84 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
85 SUB_CalcMove(this, this.dest2, TSPEED_LINEAR, this.speed, fd_secret_move3);
88 // Wait here until time to go back...
89 void fd_secret_move3(entity this)
91 if (this.noise3 != "")
92 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
93 if (!(this.spawnflags & SECRET_OPEN_ONCE))
95 this.SUB_NEXTTHINK = this.SUB_LTIME + this.wait;
96 setthink(this, fd_secret_move4);
101 void fd_secret_move4(entity this)
103 if (this.noise2 != "")
104 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
105 SUB_CalcMove(this, this.dest1, TSPEED_LINEAR, this.speed, fd_secret_move5);
109 void fd_secret_move5(entity this)
111 this.SUB_NEXTTHINK = this.SUB_LTIME + 1.0;
112 setthink(this, fd_secret_move6);
113 if (this.noise3 != "")
114 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
117 void fd_secret_move6(entity this)
119 if (this.noise2 != "")
120 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
121 SUB_CalcMove(this, this.oldorigin, TSPEED_LINEAR, this.speed, fd_secret_done);
124 void fd_secret_done(entity this)
126 if (this.spawnflags&SECRET_YES_SHOOT)
129 this.takedamage = DAMAGE_YES;
130 //this.th_pain = fd_secret_use;
132 if (this.noise3 != "")
133 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
136 .float door_finished;
138 void secret_blocked(entity this, entity blocker)
140 if (time < this.door_finished)
142 this.door_finished = time + 0.5;
143 //T_Damage (other, this, this, this.dmg, this.dmg, this.deathtype, DT_IMPACT, (this.absmin + this.absmax) * 0.5, '0 0 0', Obituary_Generic);
153 void secret_touch(entity this, entity toucher)
155 if (!toucher.iscreature)
157 if (this.door_finished > time)
160 this.door_finished = time + 2;
164 if (IS_CLIENT(toucher))
165 centerprint(toucher, this.message);
166 play2(toucher, this.noise);
170 void secret_reset(entity this)
172 if (this.spawnflags & SECRET_YES_SHOOT)
175 this.takedamage = DAMAGE_YES;
177 setorigin(this, this.oldorigin);
178 setthink(this, func_null);
179 this.SUB_NEXTTHINK = 0;
182 /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
183 Basic secret door. Slides back, then to the side. Angle determines direction.
184 wait = # of seconds before coming back
185 1st_left = 1st move is left of arrow
186 1st_down = 1st move is down from arrow
187 always_shoot = even if targeted, keep shootable
188 t_width = override WIDTH to move back (or height if going down)
189 t_length = override LENGTH to move sideways
190 "dmg" damage to inflict when blocked (2 default)
192 If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
199 spawnfunc(func_door_secret)
201 /*if (!this.deathtype) // map makers can override this
202 this.deathtype = " got in the way";*/
204 if (!this.dmg) this.dmg = 2;
207 this.mangle = this.angles;
208 this.angles = '0 0 0';
209 this.classname = "door";
210 if (!InitMovingBrushTrigger(this)) return;
211 this.effects |= EF_LOWPRECISION;
213 if (this.noise == "") this.noise = "misc/talk.wav";
214 precache_sound(this.noise);
216 settouch(this, secret_touch);
217 setblocked(this, secret_blocked);
219 this.use = fd_secret_use;
224 this.spawnflags |= SECRET_YES_SHOOT;
226 if (this.spawnflags & SECRET_YES_SHOOT)
229 this.takedamage = DAMAGE_YES;
230 this.event_damage = fd_secret_damage;
232 this.oldorigin = this.origin;
233 if (!this.wait) this.wait = 5; // seconds before closing
235 this.reset = secret_reset;