]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/triggers.qc
1f5139896d19eea55fa89b5c5d8085a9f2b37e9f
[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                 t.antiwall_flag = this.antiwall_flag;
207                 return;
208         }
209
210         string s;
211
212 //
213 // print the message
214 //
215 #ifdef SVQC
216         if(this)
217         if(IS_PLAYER(actor) && this.message != "")
218         if(IS_REAL_CLIENT(actor))
219         {
220                 centerprint(actor, this.message);
221                 if (this.noise == "")
222                         play2(actor, SND(TALK));
223         }
224
225 //
226 // kill the killtagets
227 //
228         s = this.killtarget;
229         if (s != "")
230         {
231                 for(entity t = NULL; (t = find(t, targetname, s)); )
232                         delete(t);
233         }
234 #endif
235
236 //
237 // fire targets
238 //
239
240         if(this.target_random)
241                 RandomSelection_Init();
242
243         for(int i = 0; i < 4; ++i)
244         {
245                 switch(i)
246                 {
247                         default:
248                         case 0: s = this.target; break;
249                         case 1: s = this.target2; break;
250                         case 2: s = this.target3; break;
251                         case 3: s = this.target4; break;
252                 }
253                 if (s != "")
254                 {
255                         // Flag to set func_clientwall state
256                         // 1 == deactivate, 2 == activate, 0 == do nothing
257                         int aw_flag = this.antiwall_flag;
258                         for(entity t = NULL; (t = find(t, targetname, s)); )
259                         {
260                                 if(t.use && (t.sub_target_used != time || !preventReuse))
261                                 {
262                                         if(this.target_random)
263                                         {
264                                                 RandomSelection_AddEnt(t, 1, 0);
265                                         }
266                                         else
267                                         {
268                                                 if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
269                                                         t.antiwall_flag = aw_flag;
270
271                                                 t.use(t, actor, this);
272                                                 if(preventReuse)
273                                                         t.sub_target_used = time;
274                                         }
275                                 }
276                         }
277                 }
278         }
279
280         if(this.target_random && RandomSelection_chosen_ent)
281         {
282                 RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
283                 if(preventReuse)
284                         RandomSelection_chosen_ent.sub_target_used = time;
285         }
286 }
287
288 void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); }
289 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); }
290
291 void SUB_UseTargets_self(entity this)
292 {
293         SUB_UseTargets(this, NULL, NULL);
294 }