0bad196abf3a57a79a4fbac2637170f35321bdf6
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / func / door_secret.qc
1 #include "door_secret.qh"
2 #ifdef SVQC
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);
10
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
16
17 void fd_secret_use(entity this, entity actor, entity trigger)
18 {
19         float temp;
20         string message_save;
21
22         this.health = 10000;
23         if(!this.bot_attack)
24                 IL_PUSH(g_bot_targets, this);
25         this.bot_attack = true;
26
27         // exit if still moving around...
28         if (this.origin != this.oldorigin)
29                 return;
30
31         message_save = this.message;
32         this.message = ""; // no more message
33         SUB_UseTargets(this, actor, trigger);                           // fire all targets / killtargets
34         this.message = message_save;
35
36         this.velocity = '0 0 0';
37
38         // Make a sound, wait a little...
39
40         if (this.noise1 != "")
41                 _sound(this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
42         this.nextthink = this.ltime + 0.1;
43
44         temp = 1 - (this.spawnflags & SECRET_1ST_LEFT); // 1 or -1
45         makevectors(this.mangle);
46
47         if (!this.t_width)
48         {
49                 if (this.spawnflags & SECRET_1ST_DOWN)
50                         this.t_width = fabs(v_up * this.size);
51                 else
52                         this.t_width = fabs(v_right * this.size);
53         }
54
55         if (!this.t_length)
56                 this.t_length = fabs(v_forward * this.size);
57
58         if (this.spawnflags & SECRET_1ST_DOWN)
59                 this.dest1 = this.origin - v_up * this.t_width;
60         else
61                 this.dest1 = this.origin + v_right * (this.t_width * temp);
62
63         this.dest2 = this.dest1 + v_forward * this.t_length;
64         SUB_CalcMove(this, this.dest1, TSPEED_LINEAR, this.speed, fd_secret_move1);
65         if (this.noise2 != "")
66                 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
67 }
68
69 void fd_secret_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
70 {
71         fd_secret_use(this, NULL, NULL);
72 }
73
74 // Wait after first movement...
75 void fd_secret_move1(entity this)
76 {
77         this.nextthink = this.ltime + 1.0;
78         setthink(this, fd_secret_move2);
79         if (this.noise3 != "")
80                 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
81 }
82
83 // Start moving sideways w/sound...
84 void fd_secret_move2(entity this)
85 {
86         if (this.noise2 != "")
87                 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
88         SUB_CalcMove(this, this.dest2, TSPEED_LINEAR, this.speed, fd_secret_move3);
89 }
90
91 // Wait here until time to go back...
92 void fd_secret_move3(entity this)
93 {
94         if (this.noise3 != "")
95                 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
96         if (!(this.spawnflags & SECRET_OPEN_ONCE))
97         {
98                 this.nextthink = this.ltime + this.wait;
99                 setthink(this, fd_secret_move4);
100         }
101 }
102
103 // Move backward...
104 void fd_secret_move4(entity this)
105 {
106         if (this.noise2 != "")
107                 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
108         SUB_CalcMove(this, this.dest1, TSPEED_LINEAR, this.speed, fd_secret_move5);
109 }
110
111 // Wait 1 second...
112 void fd_secret_move5(entity this)
113 {
114         this.nextthink = this.ltime + 1.0;
115         setthink(this, fd_secret_move6);
116         if (this.noise3 != "")
117                 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
118 }
119
120 void fd_secret_move6(entity this)
121 {
122         if (this.noise2 != "")
123                 _sound(this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
124         SUB_CalcMove(this, this.oldorigin, TSPEED_LINEAR, this.speed, fd_secret_done);
125 }
126
127 void fd_secret_done(entity this)
128 {
129         if (this.spawnflags&SECRET_YES_SHOOT)
130         {
131                 this.health = 10000;
132                 this.takedamage = DAMAGE_YES;
133                 //this.th_pain = fd_secret_use;
134         }
135         if (this.noise3 != "")
136                 _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
137 }
138
139 .float door_finished;
140
141 void secret_blocked(entity this, entity blocker)
142 {
143         if (time < this.door_finished)
144                 return;
145         this.door_finished = time + 0.5;
146         //T_Damage (other, this, this, this.dmg, this.dmg, this.deathtype, DT_IMPACT, (this.absmin + this.absmax) * 0.5, '0 0 0', Obituary_Generic);
147 }
148
149 /*
150 ==============
151 secret_touch
152
153 Prints messages
154 ================
155 */
156 void secret_touch(entity this, entity toucher)
157 {
158         if (!toucher.iscreature)
159                 return;
160         if (this.door_finished > time)
161                 return;
162
163         this.door_finished = time + 2;
164
165         if (this.message)
166         {
167                 if (IS_CLIENT(toucher))
168                         centerprint(toucher, this.message);
169                 play2(toucher, this.noise);
170         }
171 }
172
173 void secret_reset(entity this)
174 {
175         if (this.spawnflags & SECRET_YES_SHOOT)
176         {
177                 this.health = 10000;
178                 this.takedamage = DAMAGE_YES;
179         }
180         setorigin(this, this.oldorigin);
181         setthink(this, func_null);
182         this.nextthink = 0;
183 }
184
185 /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
186 Basic secret door. Slides back, then to the side. Angle determines direction.
187 wait  = # of seconds before coming back
188 1st_left = 1st move is left of arrow
189 1st_down = 1st move is down from arrow
190 always_shoot = even if targeted, keep shootable
191 t_width = override WIDTH to move back (or height if going down)
192 t_length = override LENGTH to move sideways
193 "dmg"           damage to inflict when blocked (2 default)
194
195 If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
196 "sounds"
197 1) medieval
198 2) metal
199 3) base
200 */
201
202 spawnfunc(func_door_secret)
203 {
204         /*if (!this.deathtype) // map makers can override this
205                 this.deathtype = " got in the way";*/
206
207         if (!this.dmg) this.dmg = 2;
208
209         // Magic formula...
210         this.mangle = this.angles;
211         this.angles = '0 0 0';
212         this.classname = "door";
213         if (!InitMovingBrushTrigger(this)) return;
214         this.effects |= EF_LOWPRECISION;
215
216         if (this.noise == "") this.noise = "misc/talk.wav";
217         precache_sound(this.noise);
218
219         settouch(this, secret_touch);
220         setblocked(this, secret_blocked);
221         this.speed = 50;
222         this.use = fd_secret_use;
223         IFTARGETED
224         {
225         }
226         else
227                 this.spawnflags |= SECRET_YES_SHOOT;
228
229         if (this.spawnflags & SECRET_YES_SHOOT)
230         {
231                 this.health = 10000;
232                 this.takedamage = DAMAGE_YES;
233                 this.event_damage = fd_secret_damage;
234         }
235         this.oldorigin = this.origin;
236         if (!this.wait) this.wait = 5; // seconds before closing
237
238         this.reset = secret_reset;
239         this.reset(this);
240 }
241 #endif