3 void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
5 void SUB_UseTargets(entity this, entity actor, entity trigger);
7 void DelayThink(entity this)
9 SUB_UseTargets (this, this.enemy, NULL);
13 void FixSize(entity e)
15 e.mins_x = rint(e.mins_x);
16 e.mins_y = rint(e.mins_y);
17 e.mins_z = rint(e.mins_z);
19 e.maxs_x = rint(e.maxs_x);
20 e.maxs_y = rint(e.maxs_y);
21 e.maxs_z = rint(e.maxs_z);
25 void generic_setactive(entity this, int act)
27 if(act == ACTIVE_TOGGLE)
29 if(this.active == ACTIVE_ACTIVE)
31 this.active = ACTIVE_NOT;
35 this.active = ACTIVE_ACTIVE;
44 void generic_netlinked_setactive(entity this, int act)
46 int old_status = this.active;
47 generic_setactive(this, act);
49 if (this.active != old_status)
51 this.SendFlags |= SF_TRIGGER_UPDATE;
55 void generic_netlinked_reset(entity this)
59 if(this.spawnflags & START_ENABLED)
61 this.active = ACTIVE_ACTIVE;
65 this.active = ACTIVE_NOT;
70 this.active = ACTIVE_ACTIVE;
73 this.SendFlags |= SF_TRIGGER_UPDATE;
76 // Compatibility with old maps
77 void generic_netlinked_legacy_use(entity this, entity actor, entity trigger)
79 //LOG_WARNF("Entity %s was (de)activated by a trigger, please update map to use relays", this.targetname);
80 this.setactive(this, ACTIVE_TOGGLE);
83 bool autocvar_g_triggers_debug = true;
85 void trigger_init(entity this)
87 string m = this.model;
89 if(autocvar_g_triggers_debug)
94 _setmodel(this, m); // no precision needed
96 setorigin(this, this.origin);
98 setsize(this, this.mins * this.scale, this.maxs * this.scale);
100 setsize(this, this.mins, this.maxs);
103 if(autocvar_g_triggers_debug)
104 BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
107 void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
109 setSendEntity(this, sendfunc);
110 this.SendFlags = 0xFFFFFF;
113 void trigger_common_write(entity this, bool withtarget)
116 if(this.warpzone_isboxy)
118 if(this.origin != '0 0 0')
120 if(this.movedir != '0 0 0')
122 if(this.angles != '0 0 0')
123 BITSET_ASSIGN(f, 16);
124 WriteByte(MSG_ENTITY, f);
128 // probably some way to clean this up...
130 if(this.target && this.target != "") targbits |= BIT(0);
131 if(this.target2 && this.target2 != "") targbits |= BIT(1);
132 if(this.target3 && this.target3 != "") targbits |= BIT(2);
133 if(this.target4 && this.target4 != "") targbits |= BIT(3);
134 if(this.targetname && this.targetname != "") targbits |= BIT(4);
135 if(this.killtarget && this.killtarget != "") targbits |= BIT(5);
137 WriteByte(MSG_ENTITY, targbits);
139 if(targbits & BIT(0))
140 WriteString(MSG_ENTITY, this.target);
141 if(targbits & BIT(1))
142 WriteString(MSG_ENTITY, this.target2);
143 if(targbits & BIT(2))
144 WriteString(MSG_ENTITY, this.target3);
145 if(targbits & BIT(3))
146 WriteString(MSG_ENTITY, this.target4);
147 if(targbits & BIT(4))
148 WriteString(MSG_ENTITY, this.targetname);
149 if(targbits & BIT(5))
150 WriteString(MSG_ENTITY, this.killtarget);
154 WriteVector(MSG_ENTITY, this.origin);
157 WriteVector(MSG_ENTITY, this.movedir);
160 WriteVector(MSG_ENTITY, this.angles);
162 WriteShort(MSG_ENTITY, this.modelindex);
163 WriteVector(MSG_ENTITY, this.mins);
164 WriteVector(MSG_ENTITY, this.maxs);
165 WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
170 void trigger_common_read(entity this, bool withtarget)
173 this.warpzone_isboxy = (f & 1);
177 strfree(this.target);
178 strfree(this.target2);
179 strfree(this.target3);
180 strfree(this.target4);
181 strfree(this.targetname);
182 strfree(this.killtarget);
184 int targbits = ReadByte();
186 this.target = ((targbits & BIT(0)) ? strzone(ReadString()) : string_null);
187 this.target2 = ((targbits & BIT(1)) ? strzone(ReadString()) : string_null);
188 this.target3 = ((targbits & BIT(2)) ? strzone(ReadString()) : string_null);
189 this.target4 = ((targbits & BIT(3)) ? strzone(ReadString()) : string_null);
190 this.targetname = ((targbits & BIT(4)) ? strzone(ReadString()) : string_null);
191 this.killtarget = ((targbits & BIT(5)) ? strzone(ReadString()) : string_null);
195 this.origin = ReadVector();
197 this.origin = '0 0 0';
198 setorigin(this, this.origin);
201 this.movedir = ReadVector();
203 this.movedir = '0 0 0';
206 this.angles = ReadVector();
208 this.angles = '0 0 0';
210 this.modelindex = ReadShort();
211 this.mins = ReadVector();
212 this.maxs = ReadVector();
213 this.scale = ReadByte() / 16;
214 setsize(this, this.mins, this.maxs);
217 void trigger_remove_generic(entity this)
219 strfree(this.target);
220 strfree(this.target2);
221 strfree(this.target3);
222 strfree(this.target4);
223 strfree(this.targetname);
224 strfree(this.killtarget);
230 ==============================
233 the global "activator" should be set to the entity that initiated the firing.
235 If this.delay is set, a DelayedUse entity will be created that will actually
236 do the SUB_UseTargets after that many seconds have passed.
238 Centerprints any this.message to the activator.
240 Removes all entities with a targetname that match this.killtarget,
241 and removes them, so some events can remove other triggers.
243 Search for (string)targetname in all entities that
244 match (string)this.target and call their .use function
246 ==============================
249 void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse)
256 // create a temp object to fire at a later time
257 entity t = new(DelayedUse);
258 t.nextthink = time + this.delay;
259 setthink(t, DelayThink);
261 t.message = this.message;
262 t.killtarget = this.killtarget;
263 t.target = this.target;
264 t.target2 = this.target2;
265 t.target3 = this.target3;
266 t.target4 = this.target4;
267 t.antiwall_flag = this.antiwall_flag;
278 if(IS_PLAYER(actor) && this.message != "")
279 if(IS_REAL_CLIENT(actor))
281 centerprint(actor, this.message);
282 if (this.noise == "")
283 play2(actor, SND(TALK));
287 // kill the killtagets
292 for(entity t = NULL; (t = find(t, targetname, s)); )
301 if(this.target_random)
302 RandomSelection_Init();
304 for(int i = 0; i < 4; ++i)
309 case 0: s = this.target; break;
310 case 1: s = this.target2; break;
311 case 2: s = this.target3; break;
312 case 3: s = this.target4; break;
316 // Flag to set func_clientwall state
317 // 1 == deactivate, 2 == activate, 0 == do nothing
318 int aw_flag = this.antiwall_flag;
319 for(entity t = NULL; (t = find(t, targetname, s)); )
321 if(t.use && (t.sub_target_used != time || !preventReuse))
323 if(this.target_random)
325 RandomSelection_AddEnt(t, 1, 0);
329 if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
330 t.antiwall_flag = aw_flag;
332 t.use(t, actor, this);
334 t.sub_target_used = time;
341 if(this.target_random && RandomSelection_chosen_ent)
343 RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
345 RandomSelection_chosen_ent.sub_target_used = time;
349 void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); }
350 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); }