2 void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
4 void SUB_UseTargets(entity this, entity actor, entity trigger);
6 void DelayThink(entity this)
8 SUB_UseTargets (this, this.enemy, NULL);
12 void FixSize(entity e)
14 e.mins_x = rint(e.mins_x);
15 e.mins_y = rint(e.mins_y);
16 e.mins_z = rint(e.mins_z);
18 e.maxs_x = rint(e.maxs_x);
19 e.maxs_y = rint(e.maxs_y);
20 e.maxs_z = rint(e.maxs_z);
24 void generic_setactive(entity this, int act)
26 if(act == ACTIVE_TOGGLE)
28 if(this.active == ACTIVE_ACTIVE)
30 this.active = ACTIVE_NOT;
34 this.active = ACTIVE_ACTIVE;
43 void generic_netlinked_setactive(entity this, int act)
45 int old_status = this.active;
46 generic_setactive(this, act);
48 if (this.active != old_status)
50 this.SendFlags |= SF_TRIGGER_UPDATE;
54 void generic_netlinked_reset(entity this)
58 if(this.spawnflags & START_ENABLED)
60 this.active = ACTIVE_ACTIVE;
64 this.active = ACTIVE_NOT;
69 this.active = ACTIVE_ACTIVE;
72 this.SendFlags |= SF_TRIGGER_UPDATE;
75 // Compatibility with old maps
76 void generic_netlinked_legacy_use(entity this, entity actor, entity trigger)
78 LOG_WARNF("Entity %s was (de)activated by a trigger, please update map to use relays", this.targetname);
79 this.setactive(this, ACTIVE_TOGGLE);
82 bool autocvar_g_triggers_debug = true;
84 void trigger_init(entity this)
86 string m = this.model;
88 if(autocvar_g_triggers_debug)
93 _setmodel(this, m); // no precision needed
95 setorigin(this, this.origin);
97 setsize(this, this.mins * this.scale, this.maxs * this.scale);
99 setsize(this, this.mins, this.maxs);
102 if(autocvar_g_triggers_debug)
103 BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
106 void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
108 setSendEntity(this, sendfunc);
109 this.SendFlags = 0xFFFFFF;
112 void trigger_common_write(entity this, bool withtarget)
115 if(this.warpzone_isboxy)
117 if(this.origin != '0 0 0')
119 if(this.movedir != '0 0 0')
121 if(this.angles != '0 0 0')
122 BITSET_ASSIGN(f, 16);
123 WriteByte(MSG_ENTITY, f);
127 // probably some way to clean this up...
129 if(this.target && this.target != "") targbits |= BIT(0);
130 if(this.target2 && this.target2 != "") targbits |= BIT(1);
131 if(this.target3 && this.target3 != "") targbits |= BIT(2);
132 if(this.target4 && this.target4 != "") targbits |= BIT(3);
133 if(this.targetname && this.targetname != "") targbits |= BIT(4);
134 if(this.killtarget && this.killtarget != "") targbits |= BIT(5);
136 WriteByte(MSG_ENTITY, targbits);
138 if(targbits & BIT(0))
139 WriteString(MSG_ENTITY, this.target);
140 if(targbits & BIT(1))
141 WriteString(MSG_ENTITY, this.target2);
142 if(targbits & BIT(2))
143 WriteString(MSG_ENTITY, this.target3);
144 if(targbits & BIT(3))
145 WriteString(MSG_ENTITY, this.target4);
146 if(targbits & BIT(4))
147 WriteString(MSG_ENTITY, this.targetname);
148 if(targbits & BIT(5))
149 WriteString(MSG_ENTITY, this.killtarget);
153 WriteVector(MSG_ENTITY, this.origin);
156 WriteVector(MSG_ENTITY, this.movedir);
159 WriteVector(MSG_ENTITY, this.angles);
161 WriteShort(MSG_ENTITY, this.modelindex);
162 WriteVector(MSG_ENTITY, this.mins);
163 WriteVector(MSG_ENTITY, this.maxs);
164 WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
169 void trigger_common_read(entity this, bool withtarget)
172 this.warpzone_isboxy = (f & 1);
176 strfree(this.target);
177 strfree(this.target2);
178 strfree(this.target3);
179 strfree(this.target4);
180 strfree(this.targetname);
181 strfree(this.killtarget);
183 int targbits = ReadByte();
185 this.target = ((targbits & BIT(0)) ? strzone(ReadString()) : string_null);
186 this.target2 = ((targbits & BIT(1)) ? strzone(ReadString()) : string_null);
187 this.target3 = ((targbits & BIT(2)) ? strzone(ReadString()) : string_null);
188 this.target4 = ((targbits & BIT(3)) ? strzone(ReadString()) : string_null);
189 this.targetname = ((targbits & BIT(4)) ? strzone(ReadString()) : string_null);
190 this.killtarget = ((targbits & BIT(5)) ? strzone(ReadString()) : string_null);
194 this.origin = ReadVector();
196 this.origin = '0 0 0';
197 setorigin(this, this.origin);
200 this.movedir = ReadVector();
202 this.movedir = '0 0 0';
205 this.angles = ReadVector();
207 this.angles = '0 0 0';
209 this.modelindex = ReadShort();
210 this.mins = ReadVector();
211 this.maxs = ReadVector();
212 this.scale = ReadByte() / 16;
213 setsize(this, this.mins, this.maxs);
216 void trigger_remove_generic(entity this)
218 strfree(this.target);
219 strfree(this.target2);
220 strfree(this.target3);
221 strfree(this.target4);
222 strfree(this.targetname);
223 strfree(this.killtarget);
229 ==============================
232 the global "activator" should be set to the entity that initiated the firing.
234 If this.delay is set, a DelayedUse entity will be created that will actually
235 do the SUB_UseTargets after that many seconds have passed.
237 Centerprints any this.message to the activator.
239 Removes all entities with a targetname that match this.killtarget,
240 and removes them, so some events can remove other triggers.
242 Search for (string)targetname in all entities that
243 match (string)this.target and call their .use function
245 ==============================
248 void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse)
255 // create a temp object to fire at a later time
256 entity t = new(DelayedUse);
257 t.nextthink = time + this.delay;
258 setthink(t, DelayThink);
260 t.message = this.message;
261 t.killtarget = this.killtarget;
262 t.target = this.target;
263 t.target2 = this.target2;
264 t.target3 = this.target3;
265 t.target4 = this.target4;
266 t.antiwall_flag = this.antiwall_flag;
277 if(IS_PLAYER(actor) && this.message != "")
278 if(IS_REAL_CLIENT(actor))
280 centerprint(actor, this.message);
281 if (this.noise == "")
282 play2(actor, SND(TALK));
286 // kill the killtagets
291 for(entity t = NULL; (t = find(t, targetname, s)); )
300 if(this.target_random)
301 RandomSelection_Init();
303 for(int i = 0; i < 4; ++i)
308 case 0: s = this.target; break;
309 case 1: s = this.target2; break;
310 case 2: s = this.target3; break;
311 case 3: s = this.target4; break;
315 // Flag to set func_clientwall state
316 // 1 == deactivate, 2 == activate, 0 == do nothing
317 int aw_flag = this.antiwall_flag;
318 for(entity t = NULL; (t = find(t, targetname, s)); )
320 if(t.use && (t.sub_target_used != time || !preventReuse))
322 if(this.target_random)
324 RandomSelection_AddEnt(t, 1, 0);
328 if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
329 t.antiwall_flag = aw_flag;
331 t.use(t, actor, this);
333 t.sub_target_used = time;
340 if(this.target_random && RandomSelection_chosen_ent)
342 RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
344 RandomSelection_chosen_ent.sub_target_used = time;
348 void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); }
349 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); }