]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/triggers.qc
Move more stuff around
[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 void trigger_setnextthink(entity e, float dtime)
24 {
25 #ifdef CSQC
26         e.nextthink = time + dtime;
27 #else
28         e.nextthink = dtime;
29 #endif
30 }
31
32 #ifdef SVQC
33 void trigger_common_write(bool withtarget)
34 {
35         WriteByte(MSG_ENTITY, self.warpzone_isboxy);
36         WriteByte(MSG_ENTITY, self.scale);
37
38         if(withtarget)
39         {
40                 WriteString(MSG_ENTITY, self.target);
41                 WriteString(MSG_ENTITY, self.target2);
42                 WriteString(MSG_ENTITY, self.target3);
43                 WriteString(MSG_ENTITY, self.target4);
44                 WriteString(MSG_ENTITY, self.targetname);
45                 WriteString(MSG_ENTITY, self.killtarget);
46         }
47
48         WriteCoord(MSG_ENTITY, self.origin_x);
49         WriteCoord(MSG_ENTITY, self.origin_y);
50         WriteCoord(MSG_ENTITY, self.origin_z);
51
52         WriteCoord(MSG_ENTITY, self.mins_x);
53         WriteCoord(MSG_ENTITY, self.mins_y);
54         WriteCoord(MSG_ENTITY, self.mins_z);
55
56         WriteCoord(MSG_ENTITY, self.movedir_x);
57         WriteCoord(MSG_ENTITY, self.movedir_y);
58         WriteCoord(MSG_ENTITY, self.movedir_z);
59
60         WriteCoord(MSG_ENTITY, self.angles_x);
61         WriteCoord(MSG_ENTITY, self.angles_y);
62         WriteCoord(MSG_ENTITY, self.angles_z);
63 }
64
65 #elif defined(CSQC)
66
67 void trigger_common_read(bool withtarget)
68 {
69         self.warpzone_isboxy = ReadByte();
70         self.scale = ReadByte();
71
72         if(withtarget)
73         {
74                 self.target = strzone(ReadString());
75                 self.target2 = strzone(ReadString());
76                 self.target3 = strzone(ReadString());
77                 self.target4 = strzone(ReadString());
78                 self.targetname = strzone(ReadString());
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 {
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 {
147         entity t, stemp, 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 = spawn();
158                 t.classname = "DelayedUse";
159                 t.nextthink = time + self.delay;
160                 t.think = DelayThink;
161                 t.enemy = activator;
162                 t.message = self.message;
163                 t.killtarget = self.killtarget;
164                 t.target = self.target;
165                 t.target2 = self.target2;
166                 t.target3 = self.target3;
167                 t.target4 = self.target4;
168                 return;
169         }
170
171
172 //
173 // print the message
174 //
175 #ifdef SVQC
176         if(self)
177         if(IS_PLAYER(activator) && self.message != "")
178         if(IS_REAL_CLIENT(activator))
179         {
180                 centerprint(activator, self.message);
181                 if (self.noise == "")
182                         play2(activator, "misc/talk.wav");
183         }
184
185 //
186 // kill the killtagets
187 //
188         s = self.killtarget;
189         if (s != "")
190         {
191                 for(t = world; (t = find(t, targetname, s)); )
192                         remove(t);
193         }
194 #endif
195
196 //
197 // fire targets
198 //
199         act = activator;
200         stemp = self;
201         otemp = other;
202
203         if(stemp.target_random)
204                 RandomSelection_Init();
205
206         for(i = 0; i < 4; ++i)
207         {
208                 switch(i)
209                 {
210                         default:
211                         case 0: s = stemp.target; break;
212                         case 1: s = stemp.target2; break;
213                         case 2: s = stemp.target3; break;
214                         case 3: s = stemp.target4; break;
215                 }
216                 if (s != "")
217                 {
218                         for(t = world; (t = find(t, targetname, s)); )
219                         if(t.use)
220                         {
221                                 if(stemp.target_random)
222                                 {
223                                         RandomSelection_Add(t, 0, string_null, 1, 0);
224                                 }
225                                 else
226                                 {
227                                         self = t;
228                                         other = stemp;
229                                         activator = act;
230                                         self.use();
231                                 }
232                         }
233                 }
234         }
235
236         if(stemp.target_random && RandomSelection_chosen_ent)
237         {
238                 self = RandomSelection_chosen_ent;
239                 other = stemp;
240                 activator = act;
241                 self.use();
242         }
243
244         activator = act;
245         self = stemp;
246         other = otemp;
247 }
248
249 #ifdef CSQC
250 void trigger_touch_generic(void() touchfunc)
251 {
252         entity e;
253         for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
254         if(e.isplayermodel)
255         {
256                 vector emin = e.absmin, emax = e.absmax;
257                 if(self.solid == SOLID_BSP)
258                 {
259                         emin -= '1 1 1';
260                         emax += '1 1 1';
261                 }
262                 if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
263                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
264                 {
265                         other = e;
266                         touchfunc();
267                 }
268         }
269 }
270 void trigger_draw_generic()
271 {
272         float dt = time - self.move_time;
273         self.move_time = time;
274         if(dt <= 0) { return; }
275
276         setorigin(self, self.origin + self.velocity * frametime);
277
278         if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
279 }
280 #endif