]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/item_key.qc
item_key1/item_key2 work now with func_door, new entity: trigger_keylock
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / item_key.qc
1 /*
2 TODO:
3 - add an unlock sound (here to trigger_keylock and to func_door)
4 - display available keys on the HUD
5 - make more tests
6 - think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
7 - should keys have a trigger?
8 */
9
10 /*
11 ================================
12 item_key1 / item_key2
13 ================================
14 */
15
16 /*
17 Key touch handler.
18 */
19 void item_key_touch(void) {
20         local entity p;
21         
22         if (other.owner)
23                 p = other.owner;
24         else
25                 p = other;
26         
27         if (p.classname != "player")
28                 return;
29                 
30         // player already picked up this key
31         if (p.itemkeys & self.itemkeys)
32                 return;
33         
34         p.itemkeys |= self.itemkeys;
35         play2(other, self.noise);
36         
37         if (self.message) {
38                 centerprint(p, self.message);
39         }
40 };
41
42 /*
43 Spawn a key with given model, key code and color.
44 */
45 void spawn_item_key(float key_code) {
46         self.itemkeys = key_code;
47         precache_model(self.model);
48         
49         if (self.spawnflags & 1)
50                 self.noalign = 1;
51         
52         if (self.noalign)
53                 self.movetype = MOVETYPE_NONE;
54         else
55                 self.movetype = MOVETYPE_TOSS;
56                 
57         if (!self.noise)
58                 self.noise = "misc/itempickup.wav";
59         
60         precache_sound(self.noise);
61                 
62         self.mdl = self.model;
63         self.effects = EF_LOWPRECISION;
64         setmodel(self, self.model);
65         //setsize(self, '-16 -16 -24', '16 16 32');
66         setorigin(self, self.origin + '0 0 32');
67         setsize(self, '-16 -16 -56', '16 16 0');
68         self.modelflags |= MF_ROTATE;
69         self.solid = SOLID_TRIGGER;
70         
71         if (!self.noalign)
72         {
73                 // first nudge it off the floor a little bit to avoid math errors
74                 setorigin(self, self.origin + '0 0 1');
75                 // note droptofloor returns FALSE if stuck/or would fall too far
76                 droptofloor();
77         }
78
79         self.touch = item_key_touch;
80 };
81
82
83 /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
84 SILVER key.
85 -----------KEYS------------
86 colormod: color of the key (default: '.9 .9 .9').
87 message: message to print when player picks up this key.
88 model: custom model to use.
89 noise: custom sound to play when player picks up the key.
90 -------- SPAWNFLAGS --------
91 FLOATING: the item will float in air, instead of aligning to the floor by falling
92 ---------NOTES----------
93 */
94 void spawnfunc_item_key1(void) {
95         if (!self.model)
96                 self.model = "models/keys/key.md3";
97         
98         if (!self.colormod)
99                 self.colormod = '.9 .9 .9';
100         
101         if (!self.message)
102                 self.message = "You've picked up the silver key!";
103                 
104         spawn_item_key(KEYS_SILVER_KEY);
105 };
106
107 /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
108 GOLDEN key.
109 -----------KEYS------------
110 colormod: color of the key (default: '1 .9 0').
111 message: message to print when player picks up this key.
112 model: custom model to use.
113 noise: custom sound to play when player picks up the key.
114 -------- SPAWNFLAGS --------
115 FLOATING: the item will float in air, instead of aligning to the floor by falling
116 ---------NOTES----------
117 */
118 void spawnfunc_item_key2(void) {
119         if (!self.model)
120                 self.model = "models/keys/key.md3";
121                 
122         if (!self.colormod)
123                 self.colormod = '1 .9 0';
124         
125         if (!self.message)
126                 self.message = "You've picked up the gold key!";
127                 
128         spawn_item_key(KEYS_GOLD_KEY);
129 };
130
131
132 /*
133 ================================
134 trigger_keylock
135 ================================
136 */
137
138 /*
139 trigger givent targets
140 */
141 void trigger_keylock_trigger(string s) {
142         local entity t, stemp, otemp, atemp;
143         
144         stemp = self;
145         otemp = other;
146         atemp = activator;
147         
148         
149         for(t = world; (t = find(t, targetname, s)); )
150                 if (t.use) {
151                         self = t;
152                         other = stemp;
153                         activator = atemp;
154                         self.use();
155                 }
156         
157         self = stemp;
158         other = otemp;
159         activator = atemp;
160 };
161
162 /*
163 kill killtarget of trigger keylock.
164 */
165 void trigger_keylock_kill(string s) {
166         local entity t, stemp, otemp, atemp;
167         
168         stemp = self;
169         otemp = other;
170         atemp = activator;
171
172         for(t = world; (t = find(t, targetname, s)); )
173                 if (t.use) {
174                         remove(t);
175                 }
176         
177         self = stemp;
178         other = otemp;
179         activator = atemp;
180 };
181
182 void trigger_keylock_touch(void) {
183         local float key_used, silver_key_missing, gold_key_missing, started_delay;
184         local entity p;
185         
186         key_used = FALSE;
187         silver_key_missing = FALSE;
188         gold_key_missing = FALSE;
189         started_delay = FALSE;
190         
191         if (other.owner)
192                 p = other.owner;
193         else
194                 p = other;
195         
196         // only player may trigger the lock
197         if (p.classname != "player")
198                 return;
199         
200         
201         // check silver key
202         if (self.itemkeys & KEYS_SILVER_KEY) {
203                 // lock still requires the SILVER key
204                 if (p.itemkeys & KEYS_SILVER_KEY) {
205                         self.itemkeys &~= KEYS_SILVER_KEY;
206                         key_used = TRUE;
207                 } else {
208                         silver_key_missing = TRUE;
209                 }
210         }
211         
212         // check gold key
213         if (self.itemkeys & KEYS_GOLD_KEY) {
214                 // lock still requires the GOLD key
215                 if (p.itemkeys & KEYS_GOLD_KEY) {
216                         self.itemkeys &~= KEYS_GOLD_KEY;
217                         key_used = TRUE;
218                 } else {
219                         gold_key_missing = TRUE;
220                 }
221         }
222         
223         
224         activator = other;
225         
226         if (silver_key_missing) {
227                 // silver key is missing
228                 if (self.delay <= time) {
229                         if (self.target4) {
230                                 trigger_keylock_trigger(self.target4);
231                                 started_delay = TRUE;
232                                 self.delay = time + self.wait;
233                         }
234                 }
235         }
236                 
237         if (gold_key_missing) {
238                 // gold key is missing
239                 if (self.delay <= time || started_delay) {
240                         if (self.target3) {
241                                 trigger_keylock_trigger(self.target3);
242                                 started_delay = TRUE;
243                                 self.delay = time + self.wait;
244                         }
245                 }
246                 
247         }
248         
249         if (silver_key_missing || gold_key_missing) {
250                 // at least one of the keys is missing
251                 
252                 if (key_used) {
253                         // one key was given, but an other one is missing!
254                         play2(other, self.noise1);
255                         if (silver_key_missing)
256                                 centerprint(other, "You also need the silver key!");
257                         else if (gold_key_missing)
258                                 centerprint(other, "You also need the gold key!");
259                         p.key_door_messagetime = time + 2;
260                 } else {
261                         if (p.key_door_messagetime <= time) {
262                                 play2(other, self.noise2);
263                                 centerprint(other, self.message2);
264                                 p.key_door_messagetime = time + 2;
265                         }
266                 }
267                 
268                 if (self.delay <= time || started_delay == TRUE) {
269                         if (self.target2) {
270                                 trigger_keylock_trigger(self.target2);
271                                 started_delay = TRUE;
272                                 self.delay = time + self.wait;
273                         }
274                 
275                 }
276         } else {
277                 // all keys were given!
278                 play2(other, self.noise);
279                 centerprint(other, self.message);
280                 
281                 if (self.target)
282                         trigger_keylock_trigger(self.target);
283                         
284                 if (self.killtarget)
285                         trigger_keylock_kill(self.killtarget);
286                 
287                 remove(self);
288         }
289         
290 };
291
292 /*QUAKED trigger_keylock (.0 .5 .8) ? - - - GOLD_KEY SILVER_KEY
293 Keylock trigger.  Must target other entities.
294 This trigger will trigger target entities when all required keys are provided.
295 -------- KEYS --------
296 wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
297 sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav
298 target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
299 target2: trigger all entities with this targetname when triggered without giving it all the required keys.
300 target3: trigger all entities with this targetname when triggered with GOLD_KEY missing (requires GOLD_KEY spawnflag)
301 target4: trigger all entities with this targetname when triggered with SILVER_KEY missing (requires SILVER_KEY spawnflag)
302 message: print this message to the player who activated the trigger when all needed keys have been given.
303 message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
304 noise: sound to play when lock gets unlocked (default: see sounds)
305 noise1: sound to play when only one of the needed key was used (default: misc/decreasevalue.wav)
306 noise2: sound to play when a key is missing (default: misc/talk.wav)
307 killtarget: remove all entities with this targetname when triggered with all the needed keys.
308 -------- SPAWNFLAGS --------
309 GOLD_KEY: causes the door to open only if the activator holds a gold key.
310 SILVER_KEY: causes the door to open only if the activator holds a silver key.
311 ---------NOTES----------
312 If spawned without any key specified, this trigger will remove itself.
313 message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
314 */
315 void spawnfunc_trigger_keylock(void) {
316         if (!(self.spawnflags & (SPAWNFLAGS_SILVER_KEY | SPAWNFLAGS_GOLD_KEY))) {
317                 remove(self);
318                 return;
319         }
320
321         // give the trigger the silver key      
322         if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
323                 self.itemkeys |= KEYS_SILVER_KEY;
324         
325         // give the trigger the gold key
326         if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
327                 self.itemkeys |= KEYS_GOLD_KEY;
328
329         if (!self.message2) {
330                 // generate default missing key message
331                 if (self.itemkeys & (KEYS_GOLD_KEY | KEYS_SILVER_KEY) == KEYS_GOLD_KEY | KEYS_SILVER_KEY) {
332                         self.message2 = "Silver key and gold key required!";
333                 } else if (self.itemkeys & KEYS_GOLD_KEY) {
334                         self.message2 = "Gold key required!";
335                 } else if (self.itemkeys & KEYS_SILVER_KEY) {
336                         self.message2 = "Silver key required!";
337                 }
338         }
339         
340         if (!self.message) {
341                 self.message = "Unlocked!";
342         }
343         
344         if (!self.noise) {
345                 if (self.sounds == 1) {
346                         self.noise = "misc/secret.wav";
347                 } else if (self.sounds == 2) {
348                         self.noise = "misc/talk.wav";
349                 } else { //if (self.sounds == 3) {
350                         self.noise = "misc/trigger1.wav";
351                 }
352         }
353                 
354         if (!self.noise1)
355                 self.noise1 = "misc/decreasevalue.wav";
356                 
357         if (!self.noise2)
358                 self.noise2 = "misc/talk.wav";
359         
360         if (!self.wait)
361                 self.wait = 5;
362         
363         precache_sound(self.noise);
364         precache_sound(self.noise1);
365         precache_sound(self.noise2);
366         
367         EXACTTRIGGER_INIT;
368         
369         self.touch = trigger_keylock_touch;
370 };
371