+#include "triggers.qh"
void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
void SUB_UseTargets(entity this, entity actor, entity trigger);
-void DelayThink()
-{SELFPARAM();
+void DelayThink(entity this)
+{
SUB_UseTargets (this, this.enemy, NULL);
- remove(this);
+ delete(this);
}
void FixSize(entity e)
#ifdef SVQC
+bool autocvar_g_triggers_debug = true;
+
void trigger_init(entity this)
{
string m = this.model;
- WITHSELF(this, WarpZoneLib_ExactTrigger_Init());
- if(m != "")
- {
- precache_model(m);
- _setmodel(this, m); // no precision needed
+ EXACTTRIGGER_INIT;
+ if(autocvar_g_triggers_debug)
+ {
+ if(m != "")
+ {
+ precache_model(m);
+ _setmodel(this, m); // no precision needed
+ }
+ setorigin(this, this.origin);
+ if(this.scale)
+ setsize(this, this.mins * this.scale, this.maxs * this.scale);
+ else
+ setsize(this, this.mins, this.maxs);
}
- setorigin(this, this.origin);
- if(this.scale)
- setsize(this, this.mins * this.scale, this.maxs * this.scale);
- else
- setsize(this, this.mins, this.maxs);
- BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
+ if(autocvar_g_triggers_debug)
+ BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
}
void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
{
- this.SendEntity = SendEntity_self;
- this.SendEntity3 = sendfunc;
+ setSendEntity(this, sendfunc);
this.SendFlags = 0xFFFFFF;
}
BITSET_ASSIGN(f, 1);
if(this.origin != '0 0 0')
BITSET_ASSIGN(f, 4);
+ if(this.movedir != '0 0 0')
+ BITSET_ASSIGN(f, 8);
+ if(this.angles != '0 0 0')
+ BITSET_ASSIGN(f, 16);
WriteByte(MSG_ENTITY, f);
if(withtarget)
{
- WriteString(MSG_ENTITY, this.target);
- WriteString(MSG_ENTITY, this.target2);
- WriteString(MSG_ENTITY, this.target3);
- WriteString(MSG_ENTITY, this.target4);
- WriteString(MSG_ENTITY, this.targetname);
- WriteString(MSG_ENTITY, this.killtarget);
+ // probably some way to clean this up...
+ int targbits = 0;
+ if(this.target && this.target != "") targbits |= BIT(0);
+ if(this.target2 && this.target2 != "") targbits |= BIT(1);
+ if(this.target3 && this.target3 != "") targbits |= BIT(2);
+ if(this.target4 && this.target4 != "") targbits |= BIT(3);
+ if(this.targetname && this.targetname != "") targbits |= BIT(4);
+ if(this.killtarget && this.killtarget != "") targbits |= BIT(5);
+
+ WriteByte(MSG_ENTITY, targbits);
+
+ if(targbits & BIT(0))
+ WriteString(MSG_ENTITY, this.target);
+ if(targbits & BIT(1))
+ WriteString(MSG_ENTITY, this.target2);
+ if(targbits & BIT(2))
+ WriteString(MSG_ENTITY, this.target3);
+ if(targbits & BIT(3))
+ WriteString(MSG_ENTITY, this.target4);
+ if(targbits & BIT(4))
+ WriteString(MSG_ENTITY, this.targetname);
+ if(targbits & BIT(5))
+ WriteString(MSG_ENTITY, this.killtarget);
}
if(f & 4)
- {
- WriteCoord(MSG_ENTITY, this.origin.x);
- WriteCoord(MSG_ENTITY, this.origin.y);
- WriteCoord(MSG_ENTITY, this.origin.z);
- }
+ WriteVector(MSG_ENTITY, this.origin);
- WriteShort(MSG_ENTITY, this.modelindex);
- WriteCoord(MSG_ENTITY, this.mins.x);
- WriteCoord(MSG_ENTITY, this.mins.y);
- WriteCoord(MSG_ENTITY, this.mins.z);
- WriteCoord(MSG_ENTITY, this.maxs.x);
- WriteCoord(MSG_ENTITY, this.maxs.y);
- WriteCoord(MSG_ENTITY, this.maxs.z);
- WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
+ if(f & 8)
+ WriteVector(MSG_ENTITY, this.movedir);
- WriteCoord(MSG_ENTITY, this.movedir_x);
- WriteCoord(MSG_ENTITY, this.movedir_y);
- WriteCoord(MSG_ENTITY, this.movedir_z);
+ if(f & 16)
+ WriteVector(MSG_ENTITY, this.angles);
- WriteCoord(MSG_ENTITY, this.angles_x);
- WriteCoord(MSG_ENTITY, this.angles_y);
- WriteCoord(MSG_ENTITY, this.angles_z);
+ WriteShort(MSG_ENTITY, this.modelindex);
+ WriteVector(MSG_ENTITY, this.mins);
+ WriteVector(MSG_ENTITY, this.maxs);
+ WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
}
#elif defined(CSQC)
-void trigger_common_read(bool withtarget)
-{SELFPARAM();
+void trigger_common_read(entity this, bool withtarget)
+{
int f = ReadByte();
this.warpzone_isboxy = (f & 1);
if(withtarget)
{
- if(this.target) { strunzone(this.target); }
- this.target = strzone(ReadString());
- if(this.target2) { strunzone(this.target2); }
- this.target2 = strzone(ReadString());
- if(this.target3) { strunzone(this.target3); }
- this.target3 = strzone(ReadString());
- if(this.target4) { strunzone(this.target4); }
- this.target4 = strzone(ReadString());
- if(this.targetname) { strunzone(this.targetname); }
- this.targetname = strzone(ReadString());
- if(this.killtarget) { strunzone(this.killtarget); }
- this.killtarget = strzone(ReadString());
+ strfree(this.target);
+ strfree(this.target2);
+ strfree(this.target3);
+ strfree(this.target4);
+ strfree(this.targetname);
+ strfree(this.killtarget);
+
+ int targbits = ReadByte();
+
+ this.target = ((targbits & BIT(0)) ? strzone(ReadString()) : string_null);
+ this.target2 = ((targbits & BIT(1)) ? strzone(ReadString()) : string_null);
+ this.target3 = ((targbits & BIT(2)) ? strzone(ReadString()) : string_null);
+ this.target4 = ((targbits & BIT(3)) ? strzone(ReadString()) : string_null);
+ this.targetname = ((targbits & BIT(4)) ? strzone(ReadString()) : string_null);
+ this.killtarget = ((targbits & BIT(5)) ? strzone(ReadString()) : string_null);
}
if(f & 4)
- {
- this.origin_x = ReadCoord();
- this.origin_y = ReadCoord();
- this.origin_z = ReadCoord();
- }
+ this.origin = ReadVector();
else
this.origin = '0 0 0';
setorigin(this, this.origin);
+ if(f & 8)
+ this.movedir = ReadVector();
+ else
+ this.movedir = '0 0 0';
+
+ if(f & 16)
+ this.angles = ReadVector();
+ else
+ this.angles = '0 0 0';
+
this.modelindex = ReadShort();
- this.mins_x = ReadCoord();
- this.mins_y = ReadCoord();
- this.mins_z = ReadCoord();
- this.maxs_x = ReadCoord();
- this.maxs_y = ReadCoord();
- this.maxs_z = ReadCoord();
+ this.mins = ReadVector();
+ this.maxs = ReadVector();
this.scale = ReadByte() / 16;
setsize(this, this.mins, this.maxs);
-
- this.movedir_x = ReadCoord();
- this.movedir_y = ReadCoord();
- this.movedir_z = ReadCoord();
-
- this.angles_x = ReadCoord();
- this.angles_y = ReadCoord();
- this.angles_z = ReadCoord();
}
void trigger_remove_generic(entity this)
{
- if(this.target) { strunzone(this.target); }
- this.target = string_null;
-
- if(this.target2) { strunzone(this.target2); }
- this.target2 = string_null;
-
- if(this.target3) { strunzone(this.target3); }
- this.target3 = string_null;
-
- if(this.target4) { strunzone(this.target4); }
- this.target4 = string_null;
-
- if(this.targetname) { strunzone(this.targetname); }
- this.target = string_null;
-
- if(this.killtarget) { strunzone(this.killtarget); }
- this.killtarget = string_null;
+ strfree(this.target);
+ strfree(this.target2);
+ strfree(this.target3);
+ strfree(this.target4);
+ strfree(this.targetname);
+ strfree(this.killtarget);
}
#endif
+
/*
==============================
SUB_UseTargets
the global "activator" should be set to the entity that initiated the firing.
-If self.delay is set, a DelayedUse entity will be created that will actually
+If this.delay is set, a DelayedUse entity will be created that will actually
do the SUB_UseTargets after that many seconds have passed.
-Centerprints any self.message to the activator.
+Centerprints any this.message to the activator.
-Removes all entities with a targetname that match self.killtarget,
+Removes all entities with a targetname that match this.killtarget,
and removes them, so some events can remove other triggers.
Search for (string)targetname in all entities that
-match (string)self.target and call their .use function
+match (string)this.target and call their .use function
==============================
*/
-void SUB_UseTargets(entity this, entity actor, entity trigger)
+
+void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse)
{
//
// check for a delay
// create a temp object to fire at a later time
entity t = new(DelayedUse);
t.nextthink = time + this.delay;
- t.think = DelayThink;
+ setthink(t, DelayThink);
t.enemy = actor;
t.message = this.message;
t.killtarget = this.killtarget;
t.target2 = this.target2;
t.target3 = this.target3;
t.target4 = this.target4;
+ t.antiwall_flag = this.antiwall_flag;
return;
}
s = this.killtarget;
if (s != "")
{
- for(entity t = world; (t = find(t, targetname, s)); )
- remove(t);
+ for(entity t = NULL; (t = find(t, targetname, s)); )
+ delete(t);
}
#endif
// Flag to set func_clientwall state
// 1 == deactivate, 2 == activate, 0 == do nothing
int aw_flag = this.antiwall_flag;
- for(entity t = world; (t = find(t, targetname, s)); )
+ for(entity t = NULL; (t = find(t, targetname, s)); )
{
- if(t.use)
+ if(t.use && (t.sub_target_used != time || !preventReuse))
{
if(this.target_random)
{
- RandomSelection_Add(t, 0, string_null, 1, 0);
+ RandomSelection_AddEnt(t, 1, 0);
}
else
{
t.antiwall_flag = aw_flag;
t.use(t, actor, this);
+ if(preventReuse)
+ t.sub_target_used = time;
}
}
}
}
if(this.target_random && RandomSelection_chosen_ent)
- RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
-}
-
-void SUB_UseTargets_self()
-{SELFPARAM();
- SUB_UseTargets(this, NULL, NULL);
-}
-
-#ifdef CSQC
-void trigger_touch_generic(entity this, void() touchfunc)
-{
- entity e;
- for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
- if(e.classname == "csqcprojectile")
{
- vector emin = e.absmin, emax = e.absmax;
- if(this.solid == SOLID_BSP)
- {
- emin -= '1 1 1';
- emax += '1 1 1';
- }
- if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
- if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, e)) // accurate
- {
- other = e;
- WITHSELF(this, touchfunc());
- }
+ RandomSelection_chosen_ent.use(RandomSelection_chosen_ent, actor, this);
+ if(preventReuse)
+ RandomSelection_chosen_ent.sub_target_used = time;
}
}
-void trigger_draw_generic(entity this)
-{
- float dt = time - this.move_time;
- this.move_time = time;
- if(dt <= 0) { return; }
- if(this.trigger_touch) { trigger_touch_generic(this, this.trigger_touch); }
-}
-#endif
+void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); }
+void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); }