fe33e790655cc18b867e31219527f1cfcacea01c
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / trigger / keylock.qc
1 /**
2  * trigger given targets
3  */
4 void trigger_keylock_trigger(string s)
5 {SELFPARAM();
6         entity otemp = other;
7         entity atemp = activator;
8
9         entity t;
10         for(t = world; (t = find(t, targetname, s)); )
11                 if(t.use)
12                 {
13                         setself(t);
14                         other = this;
15                         activator = atemp;
16                         self.use();
17                 }
18
19         setself(this);
20         other = otemp;
21         activator = atemp;
22 }
23
24 /**
25  * kill killtarget of trigger keylock.
26  */
27 void trigger_keylock_kill(string s)
28 {
29         entity t;
30         for(t = world; (t = find(t, targetname, s)); )
31                 remove(t);
32 }
33
34 void trigger_keylock_touch()
35 {SELFPARAM();
36         bool key_used = false;
37         bool started_delay = false;
38
39         // only player may trigger the lock
40         if(!IS_PLAYER(other))
41                 return;
42
43         // check silver key
44         if(self.itemkeys)
45                 key_used = item_keys_usekey(self, other);
46
47         activator = other;
48
49         if(self.itemkeys)
50         {
51 #ifdef SVQC
52                 // at least one of the keys is missing
53                 if(key_used)
54                 {
55                         // one or more keys were given, but others are still missing!
56                         play2(other, self.noise1);
57                         Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(self.itemkeys));
58                         other.key_door_messagetime = time + 2;
59                 }
60                 else if(other.key_door_messagetime <= time)
61                 {
62                         // no keys were given
63                         play2(other, self.noise2);
64                         Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(self.itemkeys));
65                         other.key_door_messagetime = time + 2;
66                 }
67 #endif
68
69                 // trigger target2
70                 if(self.delay <= time || started_delay == true)
71                 if(self.target2)
72                 {
73                         trigger_keylock_trigger(self.target2);
74                         started_delay = true;
75                         self.delay = time + self.wait;
76                 }
77         }
78         else
79         {
80 #ifdef SVQC
81                 // all keys were given!
82                 play2(other, self.noise);
83                 centerprint(other, self.message);
84 #endif
85
86                 if(self.target)
87                         trigger_keylock_trigger(self.target);
88
89                 if(self.killtarget)
90                         trigger_keylock_kill(self.killtarget);
91
92                 remove(self);
93         }
94
95 }
96
97 #ifdef SVQC
98 bool trigger_keylock_send(entity to, int sf)
99 {SELFPARAM();
100         WriteHeader(MSG_ENTITY, ENT_CLIENT_KEYLOCK);
101
102         WriteInt24_t(MSG_ENTITY, self.itemkeys);
103         WriteByte(MSG_ENTITY, self.height);
104
105         trigger_common_write(true);
106
107         return true;
108 }
109
110 void trigger_keylock_link()
111 {
112         // uncomment to network keylocks
113         //Net_LinkEntity(self, false, 0, trigger_keylock_send);
114 }
115
116 /*QUAKED trigger_keylock (.0 .5 .8) ?
117 Keylock trigger.  Must target other entities.
118 This trigger will trigger target entities when all required keys are provided.
119 -------- KEYS --------
120 itemkeys: A bit field with key IDs that are needed to open this lock.
121 sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default)
122 target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
123 target2: trigger all entities with this targetname when triggered without giving it all the required keys.
124 killtarget: remove all entities with this targetname when triggered with all the needed keys.
125 message: print this message to the player who activated the trigger when all needed keys have been given.
126 message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
127 noise: sound to play when lock gets unlocked (default: see sounds)
128 noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav)
129 noise2: sound to play when a key is missing (default: misc/talk.wav)
130 wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
131 ---------NOTES----------
132 If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
133 message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
134 */
135 spawnfunc(trigger_keylock)
136 {
137         if(!self.itemkeys) { remove(self); return; }
138
139         // set unlocked message
140         if(self.message == "")
141                 self.message = "Unlocked!";
142
143         // set default unlock noise
144         if(self.noise == "")
145         {
146                 if(self.sounds == 1)
147                         self.noise = "misc/secret.wav";
148                 else if(self.sounds == 2)
149                         self.noise = strzone(SND(TALK));
150                 else //if (self.sounds == 3) {
151                         self.noise = "misc/trigger1.wav";
152         }
153
154         // set default use key sound
155         if(self.noise1 == "")
156                 self.noise1 = "misc/decreasevalue.wav";
157
158         // set closed sourd
159         if(self.noise2 == "")
160                 self.noise2 = SND(TALK);
161
162         // delay between triggering message2 and trigger2
163         if(!self.wait) { self.wait = 5; }
164
165         // precache sounds
166         precache_sound(self.noise);
167         precache_sound(self.noise1);
168         precache_sound(self.noise2);
169
170         EXACTTRIGGER_INIT;
171
172         self.touch = trigger_keylock_touch;
173
174         trigger_keylock_link();
175 }
176 #elif defined(CSQC)
177 void keylock_remove()
178 {SELFPARAM();
179         if(self.target) { strunzone(self.target); }
180         self.target = string_null;
181
182         if(self.target2) { strunzone(self.target2); }
183         self.target2 = string_null;
184
185         if(self.target3) { strunzone(self.target3); }
186         self.target3 = string_null;
187
188         if(self.target4) { strunzone(self.target4); }
189         self.target4 = string_null;
190
191         if(self.killtarget) { strunzone(self.killtarget); }
192         self.killtarget = string_null;
193
194         if(self.targetname) { strunzone(self.targetname); }
195         self.targetname = string_null;
196 }
197
198 void ent_keylock()
199 {SELFPARAM();
200         self.itemkeys = ReadInt24_t();
201         self.height = ReadByte();
202
203         trigger_common_read(true);
204
205         self.classname = "trigger_keylock";
206         self.drawmask = MASK_NORMAL;
207         self.draw = trigger_draw_generic;
208         self.trigger_touch = trigger_keylock_touch;
209         self.entremove = keylock_remove;
210 }
211 #endif