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