X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Ftriggers%2Ftriggers.qc;h=fbd20c84011596a6bd110e9f96e51f270413e4b8;hp=cd1d0260c01c8d2836f6e1fc369ae1208591e0a2;hb=95a5a2479a35e264473e8ba3fc4e584553da42b3;hpb=f203a8239ab58e776da8df7bce46be73d2d655a4 diff --git a/qcsrc/common/triggers/triggers.qc b/qcsrc/common/triggers/triggers.qc index cd1d0260c..fbd20c840 100644 --- a/qcsrc/common/triggers/triggers.qc +++ b/qcsrc/common/triggers/triggers.qc @@ -1,12 +1,12 @@ -void SUB_DontUseTargets() { } +#include "triggers.qh" +void SUB_DontUseTargets(entity this, entity actor, entity trigger) { } -void() SUB_UseTargets; +void SUB_UseTargets(entity this, entity actor, entity trigger); -void DelayThink() -{SELFPARAM(); - activator = self.enemy; - SUB_UseTargets (); - remove(self); +void DelayThink(entity this) +{ + SUB_UseTargets (this, this.enemy, NULL); + delete(this); } void FixSize(entity e) @@ -22,28 +22,33 @@ void FixSize(entity e) #ifdef SVQC +bool autocvar_g_triggers_debug = true; + void trigger_init(entity this) { string m = this.model; - WITH(entity, self, 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; } @@ -54,196 +59,210 @@ void trigger_common_write(entity this, bool withtarget) 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(); - self.warpzone_isboxy = (f & 1); + this.warpzone_isboxy = (f & 1); if(withtarget) { - if(self.target) { strunzone(self.target); } - self.target = strzone(ReadString()); - if(self.target2) { strunzone(self.target2); } - self.target2 = strzone(ReadString()); - if(self.target3) { strunzone(self.target3); } - self.target3 = strzone(ReadString()); - if(self.target4) { strunzone(self.target4); } - self.target4 = strzone(ReadString()); - if(self.targetname) { strunzone(self.targetname); } - self.targetname = strzone(ReadString()); - if(self.killtarget) { strunzone(self.killtarget); } - self.killtarget = strzone(ReadString()); + if(this.target) { strunzone(this.target); } + if(this.target2) { strunzone(this.target2); } + if(this.target3) { strunzone(this.target3); } + if(this.target4) { strunzone(this.target4); } + if(this.targetname) { strunzone(this.targetname); } + if(this.killtarget) { strunzone(this.killtarget); } + + int targbits = ReadByte(); + + #define X(xs,b) MACRO_BEGIN { \ + if(targbits & BIT(b)) \ + xs = strzone(ReadString()); \ + else \ + xs = string_null; \ + } MACRO_END + + X(this.target, 0); + X(this.target2, 1); + X(this.target3, 2); + X(this.target4, 3); + X(this.targetname, 4); + X(this.killtarget, 5); + #undef X } if(f & 4) - { - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.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 - self.origin = '0 0 0'; - setorigin(self, self.origin); - - self.modelindex = ReadShort(); - self.mins_x = ReadCoord(); - self.mins_y = ReadCoord(); - self.mins_z = ReadCoord(); - self.maxs_x = ReadCoord(); - self.maxs_y = ReadCoord(); - self.maxs_z = ReadCoord(); - self.scale = ReadByte() / 16; - setsize(self, self.mins, self.maxs); - - self.movedir_x = ReadCoord(); - self.movedir_y = ReadCoord(); - self.movedir_z = ReadCoord(); - - self.angles_x = ReadCoord(); - self.angles_y = ReadCoord(); - self.angles_z = ReadCoord(); + this.angles = '0 0 0'; + + this.modelindex = ReadShort(); + this.mins = ReadVector(); + this.maxs = ReadVector(); + this.scale = ReadByte() / 16; + setsize(this, this.mins, this.maxs); } -void trigger_remove_generic() -{SELFPARAM(); - if(self.target) { strunzone(self.target); } - self.target = string_null; +void trigger_remove_generic(entity this) +{ + if(this.target) { strunzone(this.target); } + this.target = string_null; - if(self.target2) { strunzone(self.target2); } - self.target2 = string_null; + if(this.target2) { strunzone(this.target2); } + this.target2 = string_null; - if(self.target3) { strunzone(self.target3); } - self.target3 = string_null; + if(this.target3) { strunzone(this.target3); } + this.target3 = string_null; - if(self.target4) { strunzone(self.target4); } - self.target4 = string_null; + if(this.target4) { strunzone(this.target4); } + this.target4 = string_null; - if(self.targetname) { strunzone(self.targetname); } - self.target = string_null; + if(this.targetname) { strunzone(this.targetname); } + this.target = string_null; - if(self.killtarget) { strunzone(self.killtarget); } - self.killtarget = string_null; + if(this.killtarget) { strunzone(this.killtarget); } + this.killtarget = string_null; } #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() -{SELFPARAM(); - entity t, otemp, act; - string s; - float i; +void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse) +{ // // check for a delay // - if (self.delay) + if (this.delay) { // create a temp object to fire at a later time - t = new(DelayedUse); - t.nextthink = time + self.delay; - t.think = DelayThink; - t.enemy = activator; - t.message = self.message; - t.killtarget = self.killtarget; - t.target = self.target; - t.target2 = self.target2; - t.target3 = self.target3; - t.target4 = self.target4; + entity t = new(DelayedUse); + t.nextthink = time + this.delay; + setthink(t, DelayThink); + t.enemy = actor; + t.message = this.message; + t.killtarget = this.killtarget; + t.target = this.target; + t.target2 = this.target2; + t.target3 = this.target3; + t.target4 = this.target4; + t.antiwall_flag = this.antiwall_flag; return; } + string s; // // print the message // #ifdef SVQC - if(self) - if(IS_PLAYER(activator) && self.message != "") - if(IS_REAL_CLIENT(activator)) + if(this) + if(IS_PLAYER(actor) && this.message != "") + if(IS_REAL_CLIENT(actor)) { - centerprint(activator, self.message); - if (self.noise == "") - play2(activator, SND(TALK)); + centerprint(actor, this.message); + if (this.noise == "") + play2(actor, SND(TALK)); } // // kill the killtagets // - s = self.killtarget; + s = this.killtarget; if (s != "") { - for(t = world; (t = find(t, targetname, s)); ) - remove(t); + for(entity t = NULL; (t = find(t, targetname, s)); ) + delete(t); } #endif // // fire targets // - act = activator; - otemp = other; if(this.target_random) RandomSelection_Init(); - for(i = 0; i < 4; ++i) + for(int i = 0; i < 4; ++i) { switch(i) { @@ -257,22 +276,24 @@ void SUB_UseTargets() { // Flag to set func_clientwall state // 1 == deactivate, 2 == activate, 0 == do nothing - float aw_flag = self.antiwall_flag; - for(t = world; (t = find(t, targetname, s)); ) - if(t.use) + int aw_flag = this.antiwall_flag; + for(entity t = NULL; (t = find(t, targetname, s)); ) { - if(this.target_random) - { - RandomSelection_Add(t, 0, string_null, 1, 0); - } - else + if(t.use && (t.sub_target_used != time || !preventReuse)) { - if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary") - t.antiwall_flag = aw_flag; - setself(t); - other = this; - activator = act; - self.use(); + if(this.target_random) + { + RandomSelection_AddEnt(t, 1, 0); + } + else + { + if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary") + t.antiwall_flag = aw_flag; + + t.use(t, actor, this); + if(preventReuse) + t.sub_target_used = time; + } } } } @@ -280,44 +301,11 @@ void SUB_UseTargets() if(this.target_random && RandomSelection_chosen_ent) { - setself(RandomSelection_chosen_ent); - other = this; - activator = act; - self.use(); - } - - activator = act; - setself(this); - other = otemp; -} - -#ifdef CSQC -void trigger_touch_generic(void() touchfunc) -{SELFPARAM(); - entity e; - for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain) - if(e.isplayermodel || e.classname == "csqcprojectile") - { - vector emin = e.absmin, emax = e.absmax; - if(self.solid == SOLID_BSP) - { - emin -= '1 1 1'; - emax += '1 1 1'; - } - if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick - if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate - { - other = e; - 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 - self.move_time; - self.move_time = time; - if(dt <= 0) { return; } - if(self.trigger_touch) { trigger_touch_generic(self.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); }