]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/triggers.qc
Entity debugger
[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 = new(DelayedUse);
152                 t.nextthink = time + self.delay;
153                 t.think = DelayThink;
154                 t.enemy = activator;
155                 t.message = self.message;
156                 t.killtarget = self.killtarget;
157                 t.target = self.target;
158                 t.target2 = self.target2;
159                 t.target3 = self.target3;
160                 t.target4 = self.target4;
161                 return;
162         }
163
164
165 //
166 // print the message
167 //
168 #ifdef SVQC
169         if(self)
170         if(IS_PLAYER(activator) && self.message != "")
171         if(IS_REAL_CLIENT(activator))
172         {
173                 centerprint(activator, self.message);
174                 if (self.noise == "")
175                         play2(activator, SND(TALK));
176         }
177
178 //
179 // kill the killtagets
180 //
181         s = self.killtarget;
182         if (s != "")
183         {
184                 for(t = world; (t = find(t, targetname, s)); )
185                         remove(t);
186         }
187 #endif
188
189 //
190 // fire targets
191 //
192         act = activator;
193         otemp = other;
194
195         if(this.target_random)
196                 RandomSelection_Init();
197
198         for(i = 0; i < 4; ++i)
199         {
200                 switch(i)
201                 {
202                         default:
203                         case 0: s = this.target; break;
204                         case 1: s = this.target2; break;
205                         case 2: s = this.target3; break;
206                         case 3: s = this.target4; break;
207                 }
208                 if (s != "")
209                 {
210                         // Flag to set func_clientwall state
211                         // 1 == deactivate, 2 == activate, 0 == do nothing
212                         float aw_flag = self.antiwall_flag;
213                         for(t = world; (t = find(t, targetname, s)); )
214                         if(t.use)
215                         {
216                                 if(this.target_random)
217                                 {
218                                         RandomSelection_Add(t, 0, string_null, 1, 0);
219                                 }
220                                 else
221                                 {
222                                         if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
223                                                 t.antiwall_flag = aw_flag;
224                                         setself(t);
225                                         other = this;
226                                         activator = act;
227                                         self.use();
228                                 }
229                         }
230                 }
231         }
232
233         if(this.target_random && RandomSelection_chosen_ent)
234         {
235                 setself(RandomSelection_chosen_ent);
236                 other = this;
237                 activator = act;
238                 self.use();
239         }
240
241         activator = act;
242         setself(this);
243         other = otemp;
244 }
245
246 #ifdef CSQC
247 void trigger_touch_generic(void() touchfunc)
248 {SELFPARAM();
249         entity e;
250         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
251         if(e.isplayermodel || e.classname == "csqcprojectile")
252         {
253                 vector emin = e.absmin, emax = e.absmax;
254                 if(self.solid == SOLID_BSP)
255                 {
256                         emin -= '1 1 1';
257                         emax += '1 1 1';
258                 }
259                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
260                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
261                 {
262                         other = e;
263                         touchfunc();
264                 }
265         }
266 }
267 void trigger_draw_generic(entity this)
268 {
269         float dt = time - self.move_time;
270         self.move_time = time;
271         if(dt <= 0) { return; }
272
273         if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
274 }
275 #endif