]> 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 CSQC
244 void trigger_touch_generic(void() touchfunc)
245 {
246         entity e;
247         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
248         if(e.isplayermodel || e.classname == "csqcprojectile")
249         {
250                 vector emin = e.absmin, emax = e.absmax;
251                 if(self.solid == SOLID_BSP)
252                 {
253                         emin -= '1 1 1';
254                         emax += '1 1 1';
255                 }
256                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
257                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
258                 {
259                         other = e;
260                         touchfunc();
261                 }
262         }
263 }
264 void trigger_draw_generic()
265 {
266         float dt = time - self.move_time;
267         self.move_time = time;
268         if(dt <= 0) { return; }
269
270         if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
271 }
272 #endif