3 bool isPushable(entity e)
20 case "bullet": // antilagged bullets can't hit this either
23 if (e.projectiledeathtype)
27 if(e.flags & FL_PROJECTILE)
35 void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
37 void SUB_UseTargets(entity this, entity actor, entity trigger);
39 void DelayThink(entity this)
41 SUB_UseTargets (this, this.enemy, NULL);
46 void generic_setactive(entity this, int act)
48 if(act == ACTIVE_TOGGLE)
50 if(this.active == ACTIVE_ACTIVE)
52 this.active = ACTIVE_NOT;
56 this.active = ACTIVE_ACTIVE;
65 void generic_netlinked_setactive(entity this, int act)
67 int old_status = this.active;
68 generic_setactive(this, act);
70 if (this.active != old_status)
72 this.SendFlags |= SF_TRIGGER_UPDATE;
76 void generic_netlinked_reset(entity this)
78 if(this.targetname && this.targetname != "")
80 if(this.spawnflags & START_ENABLED)
82 this.active = ACTIVE_ACTIVE;
86 this.active = ACTIVE_NOT;
91 this.active = ACTIVE_ACTIVE;
94 this.SendFlags |= SF_TRIGGER_UPDATE;
97 // Compatibility with old maps
98 void generic_netlinked_legacy_use(entity this, entity actor, entity trigger)
100 //LOG_WARNF("Entity %s was (de)activated by a trigger, please update map to use relays", this.targetname);
101 this.setactive(this, ACTIVE_TOGGLE);
104 bool autocvar_g_triggers_debug = true;
106 void trigger_init(entity this)
108 string m = this.model;
110 if(autocvar_g_triggers_debug)
115 _setmodel(this, m); // no precision needed
117 setorigin(this, this.origin);
119 setsize(this, this.mins * this.scale, this.maxs * this.scale);
121 setsize(this, this.mins, this.maxs);
124 if(autocvar_g_triggers_debug)
125 BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
128 void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
130 setSendEntity(this, sendfunc);
131 this.SendFlags = 0xFFFFFF;
134 void trigger_common_write(entity this, bool withtarget)
137 if(this.warpzone_isboxy)
139 if(this.origin != '0 0 0')
141 if(this.movedir != '0 0 0')
143 if(this.angles != '0 0 0')
144 BITSET_ASSIGN(f, 16);
145 WriteByte(MSG_ENTITY, f);
149 // probably some way to clean this up...
151 if(this.target && this.target != "") targbits |= BIT(0);
152 if(this.target2 && this.target2 != "") targbits |= BIT(1);
153 if(this.target3 && this.target3 != "") targbits |= BIT(2);
154 if(this.target4 && this.target4 != "") targbits |= BIT(3);
155 if(this.targetname && this.targetname != "") targbits |= BIT(4);
156 if(this.killtarget && this.killtarget != "") targbits |= BIT(5);
158 WriteByte(MSG_ENTITY, targbits);
160 if(targbits & BIT(0))
161 WriteString(MSG_ENTITY, this.target);
162 if(targbits & BIT(1))
163 WriteString(MSG_ENTITY, this.target2);
164 if(targbits & BIT(2))
165 WriteString(MSG_ENTITY, this.target3);
166 if(targbits & BIT(3))
167 WriteString(MSG_ENTITY, this.target4);
168 if(targbits & BIT(4))
169 WriteString(MSG_ENTITY, this.targetname);
170 if(targbits & BIT(5))
171 WriteString(MSG_ENTITY, this.killtarget);
175 WriteVector(MSG_ENTITY, this.origin);
178 WriteVector(MSG_ENTITY, this.movedir);
181 WriteVector(MSG_ENTITY, this.angles);
183 WriteShort(MSG_ENTITY, this.modelindex);
184 WriteVector(MSG_ENTITY, this.mins);
185 WriteVector(MSG_ENTITY, this.maxs);
186 WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
191 void trigger_common_read(entity this, bool withtarget)
194 this.warpzone_isboxy = (f & 1);
198 strfree(this.target);
199 strfree(this.target2);
200 strfree(this.target3);
201 strfree(this.target4);
202 strfree(this.targetname);
203 strfree(this.killtarget);
205 int targbits = ReadByte();
207 this.target = ((targbits & BIT(0)) ? strzone(ReadString()) : string_null);
208 this.target2 = ((targbits & BIT(1)) ? strzone(ReadString()) : string_null);
209 this.target3 = ((targbits & BIT(2)) ? strzone(ReadString()) : string_null);
210 this.target4 = ((targbits & BIT(3)) ? strzone(ReadString()) : string_null);
211 this.targetname = ((targbits & BIT(4)) ? strzone(ReadString()) : string_null);
212 this.killtarget = ((targbits & BIT(5)) ? strzone(ReadString()) : string_null);
216 this.origin = ReadVector();
218 this.origin = '0 0 0';
219 setorigin(this, this.origin);
222 this.movedir = ReadVector();
224 this.movedir = '0 0 0';
227 this.angles = ReadVector();
229 this.angles = '0 0 0';
231 this.modelindex = ReadShort();
232 this.mins = ReadVector();
233 this.maxs = ReadVector();
234 this.scale = ReadByte() / 16;
235 setsize(this, this.mins, this.maxs);
238 void trigger_remove_generic(entity this)
240 strfree(this.target);
241 strfree(this.target2);
242 strfree(this.target3);
243 strfree(this.target4);
244 strfree(this.targetname);
245 strfree(this.killtarget);
251 ==============================
254 the global "activator" should be set to the entity that initiated the firing.
256 If this.delay is set, a DelayedUse entity will be created that will actually
257 do the SUB_UseTargets after that many seconds have passed.
259 Centerprints any this.message to the activator.
261 Removes all entities with a targetname that match this.killtarget,
262 and removes them, so some events can remove other triggers.
264 Search for (string)targetname in all entities that
265 match (string)this.target and call their .use function
267 ==============================
270 void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse, int skiptargets)
277 // create a temp object to fire at a later time
278 entity t = new_pure(DelayedUse);
279 t.nextthink = time + this.delay;
280 setthink(t, DelayThink);
282 t.message = this.message;
283 t.killtarget = this.killtarget;
284 if(!(skiptargets & BIT(1))) t.target = this.target;
285 if(!(skiptargets & BIT(2))) t.target2 = this.target2;
286 if(!(skiptargets & BIT(3))) t.target3 = this.target3;
287 if(!(skiptargets & BIT(4))) t.target4 = this.target4;
288 t.antiwall_flag = this.antiwall_flag;
299 if(IS_PLAYER(actor) && this.message != "")
300 if(IS_REAL_CLIENT(actor))
302 centerprint(actor, this.message);
303 if (this.noise == "")
304 play2(actor, SND(TALK));
308 // kill the killtagets
313 for(entity t = NULL; (t = find(t, targetname, s)); )
322 if(this.target_random)
323 RandomSelection_Init();
325 for(int i = 0; i < 4; ++i)
327 if(skiptargets & BIT(i + 1))
332 case 0: s = this.target; break;
333 case 1: s = this.target2; break;
334 case 2: s = this.target3; break;
335 case 3: s = this.target4; break;
339 for(entity t = NULL; (t = find(t, targetname, s)); )
341 if(t != this && t.use && (t.sub_target_used != time || !preventReuse))
343 if(this.target_random)
345 RandomSelection_AddEnt(t, 1, 0);
349 t.use(t, actor, this);
351 t.sub_target_used = time;
358 if(this.target_random && RandomSelection_chosen_ent)
360 RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
362 RandomSelection_chosen_ent.sub_target_used = time;
366 void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false, 0); }
367 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true, 0); }
368 void SUB_UseTargets_SkipTargets(entity this, entity actor, entity trigger, int skiptargets) { SUB_UseTargets_Ex(this, actor, trigger, false, skiptargets); }