]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/item_key.qc
Merge branch 'master' into terencehill/dynamic_hud
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / item_key.qc
1 #include "item_key.qh"
2
3 #include "../common/triggers/subs.qh"
4 #include "../common/monsters/all.qh"
5 #include "../common/notifications/all.qh"
6 #include "../common/util.qh"
7 #include "../lib/warpzone/util_server.qh"
8
9 /*
10 TODO:
11 - add an unlock sound (here to trigger_keylock and to func_door)
12 - display available keys on the HUD
13 - make more tests
14 - think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
15 - should keys have a trigger?
16 */
17
18 bool item_keys_usekey(entity l, entity p)
19 {
20         float valid = l.itemkeys & p.itemkeys;
21
22         if (!valid) {
23                 // other has none of the needed keys
24                 return false;
25         } else if (l.itemkeys == valid) {
26                 // ALL needed keys were given
27                 l.itemkeys = 0;
28                 return true;
29         } else {
30                 // only some of the needed keys were given
31                 l.itemkeys &= ~valid;
32                 return true;
33         }
34 }
35
36 string item_keys_keylist(float keylist) {
37         // no keys
38         if (!keylist)
39                 return "";
40
41         // one key
42         if ((keylist & (keylist-1)) == 0)
43                 return strcat("the ", item_keys_names[lowestbit(keylist)]);
44
45         string n = "";
46         int base = 0;
47         while (keylist) {
48                 int l = lowestbit(keylist);
49                 if (n)
50                         n = strcat(n, ", the ", item_keys_names[base + l]);
51                 else
52                         n = strcat("the ", item_keys_names[base + l]);
53
54                 keylist = bitshift(keylist,  -(l + 1));
55                 base+= l + 1;
56         }
57
58         return n;
59 }
60
61
62 /*
63 ================================
64 item_key
65 ================================
66 */
67
68 /**
69  * Key touch handler.
70  */
71 void item_key_touch()
72 {SELFPARAM();
73         if (!IS_PLAYER(other))
74                 return;
75
76         // player already picked up this key
77         if (other.itemkeys & self.itemkeys)
78                 return;
79
80         other.itemkeys |= self.itemkeys;
81         play2(other, self.noise);
82
83         centerprint(other, self.message);
84
85         string oldmsg = self.message;
86         self.message = "";
87         activator = other;
88         SUB_UseTargets();
89         self.message = oldmsg;
90 };
91
92 /**
93  * Spawn a key with given model, key code and color.
94  */
95 void spawn_item_key()
96 {SELFPARAM();
97         precache_model(self.model);
98
99         if (self.spawnflags & 1) // FLOATING
100                 self.noalign = 1;
101
102         if (self.noalign)
103                 self.movetype = MOVETYPE_NONE;
104         else
105                 self.movetype = MOVETYPE_TOSS;
106
107         precache_sound(self.noise);
108
109         self.mdl = self.model;
110         self.effects = EF_LOWPRECISION;
111         _setmodel(self, self.model);
112         //setsize(self, '-16 -16 -24', '16 16 32');
113         setorigin(self, self.origin + '0 0 32');
114         setsize(self, '-16 -16 -56', '16 16 0');
115         self.modelflags |= MF_ROTATE;
116         self.solid = SOLID_TRIGGER;
117
118         if (!self.noalign)
119         {
120                 // first nudge it off the floor a little bit to avoid math errors
121                 setorigin(self, self.origin + '0 0 1');
122                 // note droptofloor returns false if stuck/or would fall too far
123                 droptofloor();
124         }
125
126         self.touch = item_key_touch;
127 };
128
129
130 /*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
131 A key entity.
132 The itemkeys should contain one of the following key IDs:
133 1 - GOLD key -
134 2 - SILVER key
135 4 - BRONZE key
136 8 - RED keycard
137 16 - BLUE keycard
138 32 - GREEN keycard
139 Custom keys:
140 ... - last key is 1<<23
141 Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those.
142 -----------KEYS------------
143 colormod: color of the key (default: '.9 .9 .9').
144 itemkeys: a key Id.
145 message: message to print when player picks up this key.
146 model: custom key model to use.
147 netname: the display name of the key.
148 noise: custom sound to play when player picks up the key.
149 -------- SPAWNFLAGS --------
150 FLOATING: the item will float in air, instead of aligning to the floor by falling
151 ---------NOTES----------
152 This is the only correct way to put keys on the map!
153
154 itemkeys MUST always have exactly one bit set.
155 */
156 spawnfunc(item_key)
157 {
158         string _netname;
159         vector _colormod;
160
161         // reject this entity if more than one key was set!
162         if (self.itemkeys>0 && (self.itemkeys & (self.itemkeys-1)) != 0) {
163                 objerror("item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
164                 remove(self);
165                 return;
166         }
167
168         // find default netname and colormod
169         switch(self.itemkeys) {
170         case BIT(0):
171                 _netname = "GOLD key";
172                 _colormod = '1 .9 0';
173                 break;
174
175         case BIT(1):
176                 _netname = "SILVER key";
177                 _colormod = '.9 .9 .9';
178                 break;
179
180         case BIT(2):
181                 _netname = "BRONZE key";
182                 _colormod = '.6 .25 0';
183                 break;
184
185         case BIT(3):
186                 _netname = "RED keycard";
187                 _colormod = '.9 0 0';
188                 break;
189
190         case BIT(4):
191                 _netname = "BLUE keycard";
192                 _colormod = '0 0 .9';
193                 break;
194
195         case BIT(5):
196                 _netname = "GREEN keycard";
197                 _colormod = '0 .9 0';
198                 break;
199
200         default:
201                 _netname = "FLUFFY PINK keycard";
202                 _colormod = '1 1 1';
203
204                 if (self.netname == "") {
205                         objerror("item_key doesn't have a default name for this key and a custom one was not specified!");
206                         remove(self);
207                         return;
208                 }
209                 break;
210
211         }
212
213         // find default model
214         string _model = string_null;
215         if (self.itemkeys <= ITEM_KEY_BIT(2)) {
216                 _model = "models/keys/key.md3";
217         } else if (self.itemkeys >= ITEM_KEY_BIT(3) && self.itemkeys <= ITEM_KEY_BIT(5)) {
218                 _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
219         } else if (self.model == "") {
220                 objerror("item_key doesn't have a default model for this key and a custom one was not specified!");
221                 remove(self);
222                 return;
223         }
224
225         // set defailt netname
226         if (self.netname == "")
227                 self.netname = _netname;
228
229         // set default colormod
230         if (!self.colormod)
231                 self.colormod = _colormod;
232
233         // set default model
234         if (self.model == "")
235                 self.model = _model;
236
237         // set default pickup message
238         if (self.message == "")
239                 self.message = strzone(strcat("You've picked up the ", self.netname, "!"));
240
241         if (self.noise == "")
242                 self.noise = strzone(SND(ITEMPICKUP));
243
244         // save the name for later
245         item_keys_names[lowestbit(self.itemkeys)] = self.netname;
246
247         // put the key on the map
248         spawn_item_key();
249 }
250
251 /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
252 SILVER key.
253 -----------KEYS------------
254 colormod: color of the key (default: '.9 .9 .9').
255 message: message to print when player picks up this key.
256 model: custom model to use.
257 noise: custom sound to play when player picks up the key.
258 -------- SPAWNFLAGS --------
259 FLOATING: the item will float in air, instead of aligning to the floor by falling
260 ---------NOTES----------
261 Don't use this entity on new maps! Use item_key instead.
262 */
263 spawnfunc(item_key1)
264 {
265         this.classname = "item_key";
266         this.itemkeys = ITEM_KEY_BIT(1);
267         spawnfunc_item_key(this);
268 };
269
270 /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
271 GOLD key.
272 -----------KEYS------------
273 colormod: color of the key (default: '1 .9 0').
274 message: message to print when player picks up this key.
275 model: custom model to use.
276 noise: custom sound to play when player picks up the key.
277 -------- SPAWNFLAGS --------
278 FLOATING: the item will float in air, instead of aligning to the floor by falling
279 ---------NOTES----------
280 Don't use this entity on new maps! Use item_key instead.
281 */
282 spawnfunc(item_key2)
283 {
284         this.classname = "item_key";
285         this.itemkeys = ITEM_KEY_BIT(0);
286         spawnfunc_item_key(this);
287 };