]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/triggers.qc
Merge branch 'terencehill/strzone_fixes' into 'master'
[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                 if(self.target) { strunzone(self.target); }
69                 self.target = strzone(ReadString());
70                 if(self.target2) { strunzone(self.target2); }
71                 self.target2 = strzone(ReadString());
72                 if(self.target3) { strunzone(self.target3); }
73                 self.target3 = strzone(ReadString());
74                 if(self.target4) { strunzone(self.target4); }
75                 self.target4 = strzone(ReadString());
76                 if(self.targetname) { strunzone(self.targetname); }
77                 self.targetname = strzone(ReadString());
78                 if(self.killtarget) { strunzone(self.killtarget); }
79                 self.killtarget = strzone(ReadString());
80         }
81
82         self.origin_x = ReadCoord();
83         self.origin_y = ReadCoord();
84         self.origin_z = ReadCoord();
85         setorigin(self, self.origin);
86
87         self.mins_x = ReadCoord();
88         self.mins_y = ReadCoord();
89         self.mins_z = ReadCoord();
90         self.maxs_x = ReadCoord();
91         self.maxs_y = ReadCoord();
92         self.maxs_z = ReadCoord();
93         setsize(self, self.mins, self.maxs);
94
95         self.movedir_x = ReadCoord();
96         self.movedir_y = ReadCoord();
97         self.movedir_z = ReadCoord();
98
99         self.angles_x = ReadCoord();
100         self.angles_y = ReadCoord();
101         self.angles_z = ReadCoord();
102 }
103
104 void trigger_remove_generic()
105 {SELFPARAM();
106         if(self.target) { strunzone(self.target); }
107         self.target = string_null;
108
109         if(self.target2) { strunzone(self.target2); }
110         self.target2 = string_null;
111
112         if(self.target3) { strunzone(self.target3); }
113         self.target3 = string_null;
114
115         if(self.target4) { strunzone(self.target4); }
116         self.target4 = string_null;
117
118         if(self.targetname) { strunzone(self.targetname); }
119         self.target = string_null;
120
121         if(self.killtarget) { strunzone(self.killtarget); }
122         self.killtarget = string_null;
123 }
124 #endif
125
126 /*
127 ==============================
128 SUB_UseTargets
129
130 the global "activator" should be set to the entity that initiated the firing.
131
132 If self.delay is set, a DelayedUse entity will be created that will actually
133 do the SUB_UseTargets after that many seconds have passed.
134
135 Centerprints any self.message to the activator.
136
137 Removes all entities with a targetname that match self.killtarget,
138 and removes them, so some events can remove other triggers.
139
140 Search for (string)targetname in all entities that
141 match (string)self.target and call their .use function
142
143 ==============================
144 */
145 void SUB_UseTargets()
146 {SELFPARAM();
147         entity t, otemp, act;
148         string s;
149         float i;
150
151 //
152 // check for a delay
153 //
154         if (self.delay)
155         {
156         // create a temp object to fire at a later time
157                 t = new(DelayedUse);
158                 t.nextthink = time + self.delay;
159                 t.think = DelayThink;
160                 t.enemy = activator;
161                 t.message = self.message;
162                 t.killtarget = self.killtarget;
163                 t.target = self.target;
164                 t.target2 = self.target2;
165                 t.target3 = self.target3;
166                 t.target4 = self.target4;
167                 return;
168         }
169
170
171 //
172 // print the message
173 //
174 #ifdef SVQC
175         if(self)
176         if(IS_PLAYER(activator) && self.message != "")
177         if(IS_REAL_CLIENT(activator))
178         {
179                 centerprint(activator, self.message);
180                 if (self.noise == "")
181                         play2(activator, SND(TALK));
182         }
183
184 //
185 // kill the killtagets
186 //
187         s = self.killtarget;
188         if (s != "")
189         {
190                 for(t = world; (t = find(t, targetname, s)); )
191                         remove(t);
192         }
193 #endif
194
195 //
196 // fire targets
197 //
198         act = activator;
199         otemp = other;
200
201         if(this.target_random)
202                 RandomSelection_Init();
203
204         for(i = 0; i < 4; ++i)
205         {
206                 switch(i)
207                 {
208                         default:
209                         case 0: s = this.target; break;
210                         case 1: s = this.target2; break;
211                         case 2: s = this.target3; break;
212                         case 3: s = this.target4; break;
213                 }
214                 if (s != "")
215                 {
216                         // Flag to set func_clientwall state
217                         // 1 == deactivate, 2 == activate, 0 == do nothing
218                         float aw_flag = self.antiwall_flag;
219                         for(t = world; (t = find(t, targetname, s)); )
220                         if(t.use)
221                         {
222                                 if(this.target_random)
223                                 {
224                                         RandomSelection_Add(t, 0, string_null, 1, 0);
225                                 }
226                                 else
227                                 {
228                                         if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
229                                                 t.antiwall_flag = aw_flag;
230                                         setself(t);
231                                         other = this;
232                                         activator = act;
233                                         self.use();
234                                 }
235                         }
236                 }
237         }
238
239         if(this.target_random && RandomSelection_chosen_ent)
240         {
241                 setself(RandomSelection_chosen_ent);
242                 other = this;
243                 activator = act;
244                 self.use();
245         }
246
247         activator = act;
248         setself(this);
249         other = otemp;
250 }
251
252 #ifdef CSQC
253 void trigger_touch_generic(void() touchfunc)
254 {SELFPARAM();
255         entity e;
256         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
257         if(e.isplayermodel || e.classname == "csqcprojectile")
258         {
259                 vector emin = e.absmin, emax = e.absmax;
260                 if(self.solid == SOLID_BSP)
261                 {
262                         emin -= '1 1 1';
263                         emax += '1 1 1';
264                 }
265                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
266                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
267                 {
268                         other = e;
269                         touchfunc();
270                 }
271         }
272 }
273 void trigger_draw_generic(entity this)
274 {
275         float dt = time - self.move_time;
276         self.move_time = time;
277         if(dt <= 0) { return; }
278
279         if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
280 }
281 #endif