]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/triggers/triggers.qc
Add strfree to reduce explicit use of strunzone/string_null
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / triggers.qc
index 1e7715a91b58a70ef8472f980ea8a9a094c16214..0957699b37ad4ef9594e33f930c95b26397030e9 100644 (file)
@@ -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()
+void DelayThink(entity this)
 {
 {
-       activator = self.enemy;
-       SUB_UseTargets ();
-       remove(self);
+       SUB_UseTargets (this, this.enemy, NULL);
+       delete(this);
 }
 
 void FixSize(entity e)
 }
 
 void FixSize(entity e)
@@ -21,257 +21,272 @@ void FixSize(entity e)
 }
 
 #ifdef SVQC
 }
 
 #ifdef SVQC
-void trigger_common_write(bool withtarget)
+
+bool autocvar_g_triggers_debug = true;
+
+void trigger_init(entity this)
+{
+       string m = this.model;
+       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);
+       }
+
+       if(autocvar_g_triggers_debug)
+               BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
+}
+
+void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
 {
 {
-       WriteByte(MSG_ENTITY, self.warpzone_isboxy);
-       WriteByte(MSG_ENTITY, self.scale);
+       setSendEntity(this, sendfunc);
+       this.SendFlags = 0xFFFFFF;
+}
+
+void trigger_common_write(entity this, bool withtarget)
+{
+       int f = 0;
+       if(this.warpzone_isboxy)
+               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)
        {
 
        if(withtarget)
        {
-               WriteString(MSG_ENTITY, self.target);
-               WriteString(MSG_ENTITY, self.target2);
-               WriteString(MSG_ENTITY, self.target3);
-               WriteString(MSG_ENTITY, self.target4);
-               WriteString(MSG_ENTITY, self.targetname);
-               WriteString(MSG_ENTITY, self.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);
        }
 
        }
 
-       WriteCoord(MSG_ENTITY, self.origin_x);
-       WriteCoord(MSG_ENTITY, self.origin_y);
-       WriteCoord(MSG_ENTITY, self.origin_z);
+       if(f & 4)
+               WriteVector(MSG_ENTITY, this.origin);
 
 
-       WriteCoord(MSG_ENTITY, self.mins_x);
-       WriteCoord(MSG_ENTITY, self.mins_y);
-       WriteCoord(MSG_ENTITY, self.mins_z);
-       WriteCoord(MSG_ENTITY, self.maxs_x);
-       WriteCoord(MSG_ENTITY, self.maxs_y);
-       WriteCoord(MSG_ENTITY, self.maxs_z);
+       if(f & 8)
+               WriteVector(MSG_ENTITY, this.movedir);
 
 
-       WriteCoord(MSG_ENTITY, self.movedir_x);
-       WriteCoord(MSG_ENTITY, self.movedir_y);
-       WriteCoord(MSG_ENTITY, self.movedir_z);
+       if(f & 16)
+               WriteVector(MSG_ENTITY, this.angles);
 
 
-       WriteCoord(MSG_ENTITY, self.angles_x);
-       WriteCoord(MSG_ENTITY, self.angles_y);
-       WriteCoord(MSG_ENTITY, self.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)
 
 }
 
 #elif defined(CSQC)
 
-void trigger_common_read(bool withtarget)
+void trigger_common_read(entity this, bool withtarget)
 {
 {
-       self.warpzone_isboxy = ReadByte();
-       self.scale = ReadByte();
+       int f = ReadByte();
+       this.warpzone_isboxy = (f & 1);
 
        if(withtarget)
        {
 
        if(withtarget)
        {
-               self.target = strzone(ReadString());
-               self.target2 = strzone(ReadString());
-               self.target3 = strzone(ReadString());
-               self.target4 = strzone(ReadString());
-               self.targetname = strzone(ReadString());
-               self.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);
        }
 
        }
 
-       self.origin_x = ReadCoord();
-       self.origin_y = ReadCoord();
-       self.origin_z = ReadCoord();
-       setorigin(self, self.origin);
-
-       self.mins_x = ReadCoord();
-       self.mins_y = ReadCoord();
-       self.mins_z = ReadCoord();
-       self.maxs_x = ReadCoord();
-       self.maxs_y = ReadCoord();
-       self.maxs_z = ReadCoord();
-       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();
+       if(f & 4)
+               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 = ReadVector();
+       this.maxs = ReadVector();
+       this.scale = ReadByte() / 16;
+       setsize(this, this.mins, this.maxs);
 }
 
 }
 
-void trigger_remove_generic()
+void trigger_remove_generic(entity this)
 {
 {
-       if(self.target) { strunzone(self.target); }
-       self.target = string_null;
-
-       if(self.target2) { strunzone(self.target2); }
-       self.target2 = string_null;
-
-       if(self.target3) { strunzone(self.target3); }
-       self.target3 = string_null;
-
-       if(self.target4) { strunzone(self.target4); }
-       self.target4 = string_null;
-
-       if(self.targetname) { strunzone(self.targetname); }
-       self.target = string_null;
-
-       if(self.killtarget) { strunzone(self.killtarget); }
-       self.killtarget = string_null;
+       strfree(this.target);
+       strfree(this.target2);
+       strfree(this.target3);
+       strfree(this.target4);
+       strfree(this.targetname);
+       strfree(this.killtarget);
 }
 #endif
 
 }
 #endif
 
+
 /*
 ==============================
 SUB_UseTargets
 
 the global "activator" should be set to the entity that initiated the firing.
 
 /*
 ==============================
 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.
 
 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
 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 t, stemp, otemp, act;
-       string s;
-       float i;
 
 
+void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse)
+{
 //
 // check for a delay
 //
 //
 // check for a delay
 //
-       if (self.delay)
+       if (this.delay)
        {
        // create a temp object to fire at a later time
        {
        // create a temp object to fire at a later time
-               t = spawn();
-               t.classname = "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;
        }
 
                return;
        }
 
+       string s;
 
 //
 // print the message
 //
 #ifdef SVQC
 
 //
 // 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, "misc/talk.wav");
+               centerprint(actor, this.message);
+               if (this.noise == "")
+                       play2(actor, SND(TALK));
        }
 
 //
 // kill the killtagets
 //
        }
 
 //
 // kill the killtagets
 //
-       s = self.killtarget;
+       s = this.killtarget;
        if (s != "")
        {
        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
 //
        }
 #endif
 
 //
 // fire targets
 //
-       act = activator;
-       stemp = self;
-       otemp = other;
 
 
-       if(stemp.target_random)
+       if(this.target_random)
                RandomSelection_Init();
 
                RandomSelection_Init();
 
-       for(i = 0; i < 4; ++i)
+       for(int i = 0; i < 4; ++i)
        {
                switch(i)
                {
                        default:
        {
                switch(i)
                {
                        default:
-                       case 0: s = stemp.target; break;
-                       case 1: s = stemp.target2; break;
-                       case 2: s = stemp.target3; break;
-                       case 3: s = stemp.target4; break;
+                       case 0: s = this.target; break;
+                       case 1: s = this.target2; break;
+                       case 2: s = this.target3; break;
+                       case 3: s = this.target4; break;
                }
                if (s != "")
                {
                        // Flag to set func_clientwall state
                        // 1 == deactivate, 2 == activate, 0 == do nothing
                }
                if (s != "")
                {
                        // 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(stemp.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;
-                                       self = t;
-                                       other = stemp;
-                                       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;
+                                       }
                                }
                        }
                }
        }
 
                                }
                        }
                }
        }
 
-       if(stemp.target_random && RandomSelection_chosen_ent)
-       {
-               self = RandomSelection_chosen_ent;
-               other = stemp;
-               activator = act;
-               self.use();
-       }
-
-       activator = act;
-       self = stemp;
-       other = otemp;
-}
-
-#ifdef CSQC
-void trigger_touch_generic(void() touchfunc)
-{
-       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")
+       if(this.target_random && RandomSelection_chosen_ent)
        {
        {
-               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()
-{
-       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); }