]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/triggers.qc
Merge branch 'master' into terencehill/spectatee_status_update
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / triggers.qc
1 #include "triggers.qh"
2 void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
3
4 void SUB_UseTargets(entity this, entity actor, entity trigger);
5
6 void DelayThink(entity this)
7 {
8         SUB_UseTargets (this, this.enemy, NULL);
9         delete(this);
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
25 void trigger_init(entity this)
26 {
27         string m = this.model;
28         EXACTTRIGGER_INIT;
29         if(m != "")
30         {
31                 precache_model(m);
32                 _setmodel(this, m); // no precision needed
33         }
34         setorigin(this, this.origin);
35         if(this.scale)
36                 setsize(this, this.mins * this.scale, this.maxs * this.scale);
37         else
38                 setsize(this, this.mins, this.maxs);
39
40         BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
41 }
42
43 void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
44 {
45         setSendEntity(this, sendfunc);
46         this.SendFlags = 0xFFFFFF;
47 }
48
49 void trigger_common_write(entity this, bool withtarget)
50 {
51         int f = 0;
52         if(this.warpzone_isboxy)
53                 BITSET_ASSIGN(f, 1);
54         if(this.origin != '0 0 0')
55                 BITSET_ASSIGN(f, 4);
56         WriteByte(MSG_ENTITY, f);
57
58         if(withtarget)
59         {
60                 WriteString(MSG_ENTITY, this.target);
61                 WriteString(MSG_ENTITY, this.target2);
62                 WriteString(MSG_ENTITY, this.target3);
63                 WriteString(MSG_ENTITY, this.target4);
64                 WriteString(MSG_ENTITY, this.targetname);
65                 WriteString(MSG_ENTITY, this.killtarget);
66         }
67
68         if(f & 4)
69         {
70                 WriteCoord(MSG_ENTITY, this.origin.x);
71                 WriteCoord(MSG_ENTITY, this.origin.y);
72                 WriteCoord(MSG_ENTITY, this.origin.z);
73         }
74
75         WriteShort(MSG_ENTITY, this.modelindex);
76         WriteCoord(MSG_ENTITY, this.mins.x);
77         WriteCoord(MSG_ENTITY, this.mins.y);
78         WriteCoord(MSG_ENTITY, this.mins.z);
79         WriteCoord(MSG_ENTITY, this.maxs.x);
80         WriteCoord(MSG_ENTITY, this.maxs.y);
81         WriteCoord(MSG_ENTITY, this.maxs.z);
82         WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
83
84         WriteCoord(MSG_ENTITY, this.movedir_x);
85         WriteCoord(MSG_ENTITY, this.movedir_y);
86         WriteCoord(MSG_ENTITY, this.movedir_z);
87
88         WriteCoord(MSG_ENTITY, this.angles_x);
89         WriteCoord(MSG_ENTITY, this.angles_y);
90         WriteCoord(MSG_ENTITY, this.angles_z);
91 }
92
93 #elif defined(CSQC)
94
95 void trigger_common_read(entity this, bool withtarget)
96 {
97         int f = ReadByte();
98         this.warpzone_isboxy = (f & 1);
99
100         if(withtarget)
101         {
102                 if(this.target) { strunzone(this.target); }
103                 this.target = strzone(ReadString());
104                 if(this.target2) { strunzone(this.target2); }
105                 this.target2 = strzone(ReadString());
106                 if(this.target3) { strunzone(this.target3); }
107                 this.target3 = strzone(ReadString());
108                 if(this.target4) { strunzone(this.target4); }
109                 this.target4 = strzone(ReadString());
110                 if(this.targetname) { strunzone(this.targetname); }
111                 this.targetname = strzone(ReadString());
112                 if(this.killtarget) { strunzone(this.killtarget); }
113                 this.killtarget = strzone(ReadString());
114         }
115
116         if(f & 4)
117         {
118                 this.origin_x = ReadCoord();
119                 this.origin_y = ReadCoord();
120                 this.origin_z = ReadCoord();
121         }
122         else
123                 this.origin = '0 0 0';
124         setorigin(this, this.origin);
125
126         this.modelindex = ReadShort();
127         this.mins_x = ReadCoord();
128         this.mins_y = ReadCoord();
129         this.mins_z = ReadCoord();
130         this.maxs_x = ReadCoord();
131         this.maxs_y = ReadCoord();
132         this.maxs_z = ReadCoord();
133         this.scale = ReadByte() / 16;
134         setsize(this, this.mins, this.maxs);
135
136         this.movedir_x = ReadCoord();
137         this.movedir_y = ReadCoord();
138         this.movedir_z = ReadCoord();
139
140         this.angles_x = ReadCoord();
141         this.angles_y = ReadCoord();
142         this.angles_z = ReadCoord();
143 }
144
145 void trigger_remove_generic(entity this)
146 {
147         if(this.target) { strunzone(this.target); }
148         this.target = string_null;
149
150         if(this.target2) { strunzone(this.target2); }
151         this.target2 = string_null;
152
153         if(this.target3) { strunzone(this.target3); }
154         this.target3 = string_null;
155
156         if(this.target4) { strunzone(this.target4); }
157         this.target4 = string_null;
158
159         if(this.targetname) { strunzone(this.targetname); }
160         this.target = string_null;
161
162         if(this.killtarget) { strunzone(this.killtarget); }
163         this.killtarget = string_null;
164 }
165 #endif
166
167
168 /*
169 ==============================
170 SUB_UseTargets
171
172 the global "activator" should be set to the entity that initiated the firing.
173
174 If this.delay is set, a DelayedUse entity will be created that will actually
175 do the SUB_UseTargets after that many seconds have passed.
176
177 Centerprints any this.message to the activator.
178
179 Removes all entities with a targetname that match this.killtarget,
180 and removes them, so some events can remove other triggers.
181
182 Search for (string)targetname in all entities that
183 match (string)this.target and call their .use function
184
185 ==============================
186 */
187
188 void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse)
189 {
190 //
191 // check for a delay
192 //
193         if (this.delay)
194         {
195         // create a temp object to fire at a later time
196                 entity t = new(DelayedUse);
197                 t.nextthink = time + this.delay;
198                 setthink(t, DelayThink);
199                 t.enemy = actor;
200                 t.message = this.message;
201                 t.killtarget = this.killtarget;
202                 t.target = this.target;
203                 t.target2 = this.target2;
204                 t.target3 = this.target3;
205                 t.target4 = this.target4;
206                 return;
207         }
208
209         string s;
210
211 //
212 // print the message
213 //
214 #ifdef SVQC
215         if(this)
216         if(IS_PLAYER(actor) && this.message != "")
217         if(IS_REAL_CLIENT(actor))
218         {
219                 centerprint(actor, this.message);
220                 if (this.noise == "")
221                         play2(actor, SND(TALK));
222         }
223
224 //
225 // kill the killtagets
226 //
227         s = this.killtarget;
228         if (s != "")
229         {
230                 for(entity t = NULL; (t = find(t, targetname, s)); )
231                         delete(t);
232         }
233 #endif
234
235 //
236 // fire targets
237 //
238
239         if(this.target_random)
240                 RandomSelection_Init();
241
242         for(int i = 0; i < 4; ++i)
243         {
244                 switch(i)
245                 {
246                         default:
247                         case 0: s = this.target; break;
248                         case 1: s = this.target2; break;
249                         case 2: s = this.target3; break;
250                         case 3: s = this.target4; break;
251                 }
252                 if (s != "")
253                 {
254                         // Flag to set func_clientwall state
255                         // 1 == deactivate, 2 == activate, 0 == do nothing
256                         int aw_flag = this.antiwall_flag;
257                         for(entity t = NULL; (t = find(t, targetname, s)); )
258                         {
259                                 if(t.use && (t.sub_target_used != time || !preventReuse))
260                                 {
261                                         if(this.target_random)
262                                         {
263                                                 RandomSelection_Add(t, 0, string_null, 1, 0);
264                                         }
265                                         else
266                                         {
267                                                 if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
268                                                         t.antiwall_flag = aw_flag;
269
270                                                 t.use(t, actor, this);
271                                                 if(preventReuse)
272                                                         t.sub_target_used = time;
273                                         }
274                                 }
275                         }
276                 }
277         }
278
279         if(this.target_random && RandomSelection_chosen_ent)
280         {
281                 RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
282                 if(preventReuse)
283                         RandomSelection_chosen_ent.sub_target_used = time;
284         }
285 }
286
287 void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); }
288 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); }
289
290 void SUB_UseTargets_self(entity this)
291 {
292         SUB_UseTargets(this, NULL, NULL);
293 }