]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/triggers.qc
Merge branch 'master' into Mario/qc_physics_prehax
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / triggers.qc
1 void SUB_DontUseTargets() { }
2
3 void() SUB_UseTargets;
4
5 void DelayThink()
6 {
7         activator = self.enemy;
8         SUB_UseTargets ();
9         remove(self);
10 }
11
12 void FixSize(entity e)
13 {
14         e.mins_x = rint(e.mins_x);
15         e.mins_y = rint(e.mins_y);
16         e.mins_z = rint(e.mins_z);
17
18         e.maxs_x = rint(e.maxs_x);
19         e.maxs_y = rint(e.maxs_y);
20         e.maxs_z = rint(e.maxs_z);
21 }
22
23 #ifdef SVQC
24 void trigger_common_write(bool withtarget)
25 {
26         WriteByte(MSG_ENTITY, self.warpzone_isboxy);
27         WriteByte(MSG_ENTITY, self.scale);
28
29         if(withtarget)
30         {
31                 WriteString(MSG_ENTITY, self.target);
32                 WriteString(MSG_ENTITY, self.target2);
33                 WriteString(MSG_ENTITY, self.target3);
34                 WriteString(MSG_ENTITY, self.target4);
35                 WriteString(MSG_ENTITY, self.targetname);
36                 WriteString(MSG_ENTITY, self.killtarget);
37         }
38
39         WriteCoord(MSG_ENTITY, self.origin_x);
40         WriteCoord(MSG_ENTITY, self.origin_y);
41         WriteCoord(MSG_ENTITY, self.origin_z);
42
43         WriteCoord(MSG_ENTITY, self.mins_x);
44         WriteCoord(MSG_ENTITY, self.mins_y);
45         WriteCoord(MSG_ENTITY, self.mins_z);
46         WriteCoord(MSG_ENTITY, self.maxs_x);
47         WriteCoord(MSG_ENTITY, self.maxs_y);
48         WriteCoord(MSG_ENTITY, self.maxs_z);
49
50         WriteCoord(MSG_ENTITY, self.movedir_x);
51         WriteCoord(MSG_ENTITY, self.movedir_y);
52         WriteCoord(MSG_ENTITY, self.movedir_z);
53
54         WriteCoord(MSG_ENTITY, self.angles_x);
55         WriteCoord(MSG_ENTITY, self.angles_y);
56         WriteCoord(MSG_ENTITY, self.angles_z);
57 }
58
59 #elif defined(CSQC)
60
61 void trigger_common_read(bool withtarget)
62 {
63         self.warpzone_isboxy = ReadByte();
64         self.scale = ReadByte();
65
66         if(withtarget)
67         {
68                 self.target = strzone(ReadString());
69                 self.target2 = strzone(ReadString());
70                 self.target3 = strzone(ReadString());
71                 self.target4 = strzone(ReadString());
72                 self.targetname = strzone(ReadString());
73                 self.killtarget = strzone(ReadString());
74         }
75
76         self.origin_x = ReadCoord();
77         self.origin_y = ReadCoord();
78         self.origin_z = ReadCoord();
79         setorigin(self, self.origin);
80
81         self.mins_x = ReadCoord();
82         self.mins_y = ReadCoord();
83         self.mins_z = ReadCoord();
84         self.maxs_x = ReadCoord();
85         self.maxs_y = ReadCoord();
86         self.maxs_z = ReadCoord();
87         setsize(self, self.mins, self.maxs);
88
89         self.movedir_x = ReadCoord();
90         self.movedir_y = ReadCoord();
91         self.movedir_z = ReadCoord();
92
93         self.angles_x = ReadCoord();
94         self.angles_y = ReadCoord();
95         self.angles_z = ReadCoord();
96 }
97
98 void trigger_remove_generic()
99 {
100         if(self.target) { strunzone(self.target); }
101         self.target = string_null;
102
103         if(self.target2) { strunzone(self.target2); }
104         self.target2 = string_null;
105
106         if(self.target3) { strunzone(self.target3); }
107         self.target3 = string_null;
108
109         if(self.target4) { strunzone(self.target4); }
110         self.target4 = string_null;
111
112         if(self.targetname) { strunzone(self.targetname); }
113         self.target = string_null;
114
115         if(self.killtarget) { strunzone(self.killtarget); }
116         self.killtarget = string_null;
117 }
118 #endif
119
120 /*
121 ==============================
122 SUB_UseTargets
123
124 the global "activator" should be set to the entity that initiated the firing.
125
126 If self.delay is set, a DelayedUse entity will be created that will actually
127 do the SUB_UseTargets after that many seconds have passed.
128
129 Centerprints any self.message to the activator.
130
131 Removes all entities with a targetname that match self.killtarget,
132 and removes them, so some events can remove other triggers.
133
134 Search for (string)targetname in all entities that
135 match (string)self.target and call their .use function
136
137 ==============================
138 */
139 void SUB_UseTargets()
140 {
141         entity t, stemp, otemp, act;
142         string s;
143         float i;
144
145 //
146 // check for a delay
147 //
148         if (self.delay)
149         {
150         // create a temp object to fire at a later time
151                 t = spawn();
152                 t.classname = "DelayedUse";
153                 t.nextthink = time + self.delay;
154                 t.think = DelayThink;
155                 t.enemy = activator;
156                 t.message = self.message;
157                 t.killtarget = self.killtarget;
158                 t.target = self.target;
159                 t.target2 = self.target2;
160                 t.target3 = self.target3;
161                 t.target4 = self.target4;
162                 return;
163         }
164
165
166 //
167 // print the message
168 //
169 #ifdef SVQC
170         if(self)
171         if(IS_PLAYER(activator) && self.message != "")
172         if(IS_REAL_CLIENT(activator))
173         {
174                 centerprint(activator, self.message);
175                 if (self.noise == "")
176                         play2(activator, "misc/talk.wav");
177         }
178
179 //
180 // kill the killtagets
181 //
182         s = self.killtarget;
183         if (s != "")
184         {
185                 for(t = world; (t = find(t, targetname, s)); )
186                         remove(t);
187         }
188 #endif
189
190 //
191 // fire targets
192 //
193         act = activator;
194         stemp = self;
195         otemp = other;
196
197         if(stemp.target_random)
198                 RandomSelection_Init();
199
200         for(i = 0; i < 4; ++i)
201         {
202                 switch(i)
203                 {
204                         default:
205                         case 0: s = stemp.target; break;
206                         case 1: s = stemp.target2; break;
207                         case 2: s = stemp.target3; break;
208                         case 3: s = stemp.target4; break;
209                 }
210                 if (s != "")
211                 {
212                         for(t = world; (t = find(t, targetname, s)); )
213                         if(t.use)
214                         {
215                                 if(stemp.target_random)
216                                 {
217                                         RandomSelection_Add(t, 0, string_null, 1, 0);
218                                 }
219                                 else
220                                 {
221                                         self = t;
222                                         other = stemp;
223                                         activator = act;
224                                         self.use();
225                                 }
226                         }
227                 }
228         }
229
230         if(stemp.target_random && RandomSelection_chosen_ent)
231         {
232                 self = RandomSelection_chosen_ent;
233                 other = stemp;
234                 activator = act;
235                 self.use();
236         }
237
238         activator = act;
239         self = stemp;
240         other = otemp;
241 }
242
243 #ifdef SVQC
244 void trigger_think_generic()
245 {
246         self.nextthink = time;
247
248         entity e;
249         if(self.trigger_touch)
250         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
251         {
252                 vector emin = e.absmin, emax = e.absmax;
253                 if(self.solid == SOLID_BSP)
254                 {
255                         emin -= '1 1 1';
256                         emax += '1 1 1';
257                 }
258                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
259                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
260                 {
261                         other = e;
262                         self.trigger_touch();
263                 }
264         }
265 }
266 #endif
267
268 #ifdef CSQC
269 void trigger_touch_generic(void() touchfunc)
270 {
271         entity e;
272         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
273         if(e.isplayermodel || e.classname == "csqcprojectile")
274         {
275                 vector emin = e.absmin, emax = e.absmax;
276                 if(self.solid == SOLID_BSP)
277                 {
278                         emin -= '1 1 1';
279                         emax += '1 1 1';
280                 }
281                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
282                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
283                 {
284                         other = e;
285                         touchfunc();
286                 }
287         }
288 }
289 void trigger_draw_generic()
290 {
291         float dt = time - self.move_time;
292         self.move_time = time;
293         if(dt <= 0) { return; }
294
295         if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
296 }
297 #endif