Draw: purge SELFPARAM
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / triggers.qc
1 void SUB_DontUseTargets() { }
2
3 void() SUB_UseTargets;
4
5 void DelayThink()
6 {SELFPARAM();
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 {SELFPARAM();
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 {SELFPARAM();
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 {SELFPARAM();
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 {SELFPARAM();
141         entity t, 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, SND(TALK));
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         otemp = other;
195
196         if(this.target_random)
197                 RandomSelection_Init();
198
199         for(i = 0; i < 4; ++i)
200         {
201                 switch(i)
202                 {
203                         default:
204                         case 0: s = this.target; break;
205                         case 1: s = this.target2; break;
206                         case 2: s = this.target3; break;
207                         case 3: s = this.target4; break;
208                 }
209                 if (s != "")
210                 {
211                         // Flag to set func_clientwall state
212                         // 1 == deactivate, 2 == activate, 0 == do nothing
213                         float aw_flag = self.antiwall_flag;
214                         for(t = world; (t = find(t, targetname, s)); )
215                         if(t.use)
216                         {
217                                 if(this.target_random)
218                                 {
219                                         RandomSelection_Add(t, 0, string_null, 1, 0);
220                                 }
221                                 else
222                                 {
223                                         if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
224                                                 t.antiwall_flag = aw_flag;
225                                         setself(t);
226                                         other = this;
227                                         activator = act;
228                                         self.use();
229                                 }
230                         }
231                 }
232         }
233
234         if(this.target_random && RandomSelection_chosen_ent)
235         {
236                 setself(RandomSelection_chosen_ent);
237                 other = this;
238                 activator = act;
239                 self.use();
240         }
241
242         activator = act;
243         setself(this);
244         other = otemp;
245 }
246
247 #ifdef CSQC
248 void trigger_touch_generic(void() touchfunc)
249 {SELFPARAM();
250         entity e;
251         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
252         if(e.isplayermodel || e.classname == "csqcprojectile")
253         {
254                 vector emin = e.absmin, emax = e.absmax;
255                 if(self.solid == SOLID_BSP)
256                 {
257                         emin -= '1 1 1';
258                         emax += '1 1 1';
259                 }
260                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
261                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
262                 {
263                         other = e;
264                         touchfunc();
265                 }
266         }
267 }
268 void trigger_draw_generic(entity this)
269 {
270         float dt = time - self.move_time;
271         self.move_time = time;
272         if(dt <= 0) { return; }
273
274         if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
275 }
276 #endif