]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
The end of the start
authorMario <zacjardine@y7mail.com>
Wed, 28 Jan 2015 09:39:38 +0000 (20:39 +1100)
committerMario <zacjardine@y7mail.com>
Wed, 28 Jan 2015 09:39:38 +0000 (20:39 +1100)
18 files changed:
qcsrc/client/Main.qc
qcsrc/client/bgmscript.qh
qcsrc/client/effects.qc
qcsrc/client/progs.src
qcsrc/common/constants.qh
qcsrc/common/net_notice.qc
qcsrc/common/triggers/f_door.qc
qcsrc/common/triggers/f_door.qh
qcsrc/common/triggers/include.qc
qcsrc/common/triggers/include.qh
qcsrc/server/constants.qh
qcsrc/server/defs.qh
qcsrc/server/g_subs.qc
qcsrc/server/g_triggers.qc [deleted file]
qcsrc/server/item_key.qh
qcsrc/server/miscfunctions.qc
qcsrc/server/progs.src
qcsrc/server/tturrets/system/system_misc.qc

index fcb25246f560c9e1b5455a4c48ad0d3d625fc981..f163ad73a030f0250211151642786cbdbd6ac187 100644 (file)
@@ -351,6 +351,14 @@ void trigger_touch_generic(void() touchfunc)
                }
        }
 }
+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); }
+}
 
 void Ent_RemoveEntCS()
 {
@@ -855,6 +863,8 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_TRIGGER_PUSH: ent_trigger_push(); break;
                case ENT_CLIENT_TARGET_PUSH: ent_target_push(); break;
                case ENT_CLIENT_CONVEYOR: ent_conveyor(); break;
+               case ENT_CLIENT_DOOR: ent_door(); break;
+               case ENT_CLIENT_DOOR_TRIGGER: ent_door_trigger(); break;
 
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
index 713cf5798cd61184eaa2b1ecee096b9e4e36a569..e3183055283dbf5d8168bb55187be120f12c7099 100644 (file)
@@ -1,9 +1,3 @@
-.string bgmscript;
-.float bgmscriptattack;
-.float bgmscriptdecay;
-.float bgmscriptsustain;
-.float bgmscriptrelease;
-
 .float just_toggled;
 
 void BGMScript_InitEntity(entity e);
index c35a3a94a7577dc7724a3ebe0330e08cf6c19bf3..4aa65f3ec53919f4c6555da115a7543e4d2b47d3 100644 (file)
@@ -5,9 +5,6 @@
 .string fx_texture;
 .float  fx_lifetime;
 
-void SUB_Remove()
-{ remove(self); }
-
 void b_draw()
 {
     //Draw_CylindricLine(self.fx_start, self.fx_end, self.fx_with, self.fx_texture, 0, time * 3, '1 1 1', 0.7, DRAWFLAG_ADDITIVE, view_origin);
index e414576c364d7745a8820bb58aec0dfedd366442..0e6a4e96283402d33fc4a2319a90cd2db4e1bb48 100644 (file)
@@ -62,6 +62,8 @@ vehicles/vehicles.qh
 weapons/projectile.qh // TODO
 player_skeleton.qh
 
+../common/triggers/include.qh
+
 sortlist.qc
 miscfunctions.qc
 ../server/t_items.qh
@@ -131,6 +133,8 @@ command/cl_cmd.qc
 ../common/buffs.qc
 ../common/physics.qc
 
+../common/triggers/include.qc
+
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/mathlib.qc
 ../warpzonelib/common.qc
index 28cf97f5d7e5e5dfc0fc195fbefe6acedd8e9c4f..054364f12a99faaa5bf40608f4419db5e081f3a5 100644 (file)
@@ -104,6 +104,8 @@ const float ENT_CLIENT_LADDER = 61;
 const float ENT_CLIENT_TRIGGER_PUSH = 62;
 const float ENT_CLIENT_TARGET_PUSH = 63;
 const float ENT_CLIENT_CONVEYOR = 64;
+const float ENT_CLIENT_DOOR = 65;
+const float ENT_CLIENT_DOOR_TRIGGER = 66;
 
 const float ENT_CLIENT_HEALING_ORB = 80;
 
index caaae8b4967bfa70c214d998ab05efc5aeacb94b..e9d86420fb7ebbc1ee4aaca9d5546c0175f60b1b 100644 (file)
@@ -45,9 +45,6 @@ void sv_notice_toall(string _notice, float _howlong, float _modal)
 #endif // SVQC
 
 #ifdef CSQC
-void SUB_Remove()
-{ remove(self); }
-
 void cl_notice_read()
 {
     entity _notice;
index 172628b607f57f385e1e1759e19a4d08b8fd81c5..a1b1440ab66d3c72c787cb1bf8cc77bf9da040f9 100644 (file)
@@ -27,19 +27,25 @@ void() door_rotating_go_up;
 
 void door_blocked()
 {
+       if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO))
+       { // KIll Kill Kill!!
+#ifdef SVQC
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+       }
+       else
+       {
+#ifdef SVQC
+               if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
 
-    if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
-        Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-    } else {
-
-        if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
-            Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-
-         //Dont chamge direction for dead or dying stuff
-        if(other.deadflag != DEAD_NO && (other.takedamage == DAMAGE_NO)) {
-            if (self.wait >= 0)
-            {
-                if (self.state == STATE_DOWN)
+                //Dont chamge direction for dead or dying stuff
+               if(PHYS_DEAD(other) && (other.takedamage == DAMAGE_NO))
+               {
+                       if (self.wait >= 0)
+                       {
+                               if (self.state == STATE_DOWN)
                        if (self.classname == "door")
                        {
                                door_go_up ();
@@ -47,7 +53,7 @@ void door_blocked()
                        {
                                door_rotating_go_up ();
                        }
-                else
+                               else
                        if (self.classname == "door")
                        {
                                door_go_down ();
@@ -55,13 +61,17 @@ void door_blocked()
                        {
                                door_rotating_go_down ();
                        }
-            }
-        } else {
-            //gib dying stuff just to make sure
-            if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
-                Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-        }
-    }
+                       }
+               }
+#ifdef SVQC
+               else
+               {
+                       //gib dying stuff just to make sure
+                       if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+#endif
+       }
 }
 
 void door_hit_top()
@@ -134,7 +144,8 @@ ACTIVATION FUNCTIONS
 =============================================================================
 */
 
-float door_check_keys(void) {
+float door_check_keys(void)
+{
        local entity door;
 
 
@@ -152,28 +163,41 @@ float door_check_keys(void) {
        if (!IS_PLAYER(other))
                return FALSE;
 
-       if (item_keys_usekey(door, other)) {
+       if (item_keys_usekey(door, other))
+       {
                // some keys were used
-               if (other.key_door_messagetime <= time) {
+               if (other.key_door_messagetime <= time)
+               {
+#ifdef SVQC
                        play2(other, "misc/talk.wav");
                        Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
+#endif
                        other.key_door_messagetime = time + 2;
                }
-       } else {
+       }
+       else
+       {
                // no keys were used
-               if (other.key_door_messagetime <= time) {
+               if (other.key_door_messagetime <= time)
+               {
+#ifdef SVQC
                        play2(other, "misc/talk.wav");
                        Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
+#endif
                        other.key_door_messagetime = time + 2;
                }
        }
 
-       if (door.itemkeys) {
+       if (door.itemkeys)
+       {
+#ifdef SVQC
                // door is now unlocked
                play2(other, "misc/talk.wav");
                Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
+#endif
                return TRUE;
-       } else
+       }
+       else
                return FALSE;
 }
 
@@ -222,11 +246,11 @@ void door_fire()
                        if ((self.spawnflags & 2) && other.trigger_reverse!=0 && self.lip!=666 && self.state == STATE_BOTTOM)
                        {
                                self.lip = 666; // self.lip is used to remember reverse opening direction for door_rotating
-                               self.pos2 = '0 0 0' - self.pos2;
+                               self.pos2 = '0 0 0' - self.pos2;
                        }
                        // if BIDIR_IN_DOWN (==8) is set, prevent the door from reoping during closing if it is triggered from the wrong side
                        if (!((self.spawnflags & 2) &&  (self.spawnflags & 8) && self.state == STATE_DOWN
-                           && (((self.lip==666) && (other.trigger_reverse==0)) || ((self.lip!=666) && (other.trigger_reverse!=0)))))
+                               && (((self.lip==666) && (other.trigger_reverse==0)) || ((self.lip!=666) && (other.trigger_reverse!=0)))))
                        {
                                door_rotating_go_up ();
                        }
@@ -251,27 +275,6 @@ void door_use()
        }
 }
 
-void door_trigger_touch()
-{
-       if (other.health < 1)
-               if (!(other.iscreature && other.deadflag == DEAD_NO))
-                       return;
-
-       if (time < self.attack_finished_single)
-               return;
-
-       // check if door is locked
-       if (!door_check_keys())
-               return;
-
-       self.attack_finished_single = time + 1;
-
-       activator = other;
-
-       self = self.owner;
-       door_use ();
-}
-
 void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
        entity oself;
@@ -280,7 +283,8 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp
                        return;
        self.health = self.health - damage;
 
-       if (self.itemkeys) {
+       if (self.itemkeys)
+       {
                // don't allow opening doors through damage if keys are required
                return;
        }
@@ -314,39 +318,52 @@ void door_touch()
 
        self.owner.attack_finished_single = time + 2;
 
+#ifdef SVQC
        if (!(self.owner.dmg) && (self.owner.message != ""))
        {
                if (IS_CLIENT(other))
                        centerprint(other, self.owner.message);
                play2(other, "misc/talk.wav");
        }
+#endif
 }
 
 void door_generic_plat_blocked()
 {
 
-    if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
-        Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-    } else {
-
-        if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
-            Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-
-         //Dont chamge direction for dead or dying stuff
-        if(other.deadflag != DEAD_NO && (other.takedamage == DAMAGE_NO)) {
-            if (self.wait >= 0)
-            {
-                if (self.state == STATE_DOWN)
-                    door_rotating_go_up ();
-                else
-                    door_rotating_go_down ();
-            }
-        } else {
-            //gib dying stuff just to make sure
-            if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
-                Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-        }
-    }
+       if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
+#ifdef SVQC
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+       }
+       else
+       {
+
+#ifdef SVQC
+               if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+
+                //Dont chamge direction for dead or dying stuff
+               if(PHYS_DEAD(other) && (other.takedamage == DAMAGE_NO))
+               {
+                       if (self.wait >= 0)
+                       {
+                               if (self.state == STATE_DOWN)
+                                       door_rotating_go_up ();
+                               else
+                                       door_rotating_go_down ();
+                       }
+               }
+#ifdef SVQC
+               else
+               {
+                       //gib dying stuff just to make sure
+                       if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+#endif
+       }
 }
 
 void door_rotating_hit_top()
@@ -410,17 +427,68 @@ void door_rotating_go_up()
 
 
 /*
-=============================================================================
+=========================================
+door trigger
 
-SPAWNING FUNCTIONS
-
-=============================================================================
+Spawned if a door lacks a real activator
+=========================================
 */
 
-entity spawn_field(vector fmins, vector fmaxs)
+void door_trigger_touch()
+{
+       if (other.health < 1)
+#ifdef SVQC
+               if (!(other.iscreature && !PHYS_DEAD(other)))
+#elif defined(CSQC)
+               if(!(IS_CLIENT(other) && !PHYS_DEAD(other)))
+                       return;
+#endif
+
+       if (time < self.attack_finished_single)
+               return;
+
+       // check if door is locked
+       if (!door_check_keys())
+               return;
+
+       self.attack_finished_single = time + 1;
+
+       activator = other;
+
+       self = self.owner;
+       door_use ();
+}
+
+#ifdef SVQC
+
+float door_trigger_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR_TRIGGER);
+
+       WriteShort(MSG_ENTITY, num_for_edict(self.owner));
+       WriteCoord(MSG_ENTITY, self.origin_x);
+       WriteCoord(MSG_ENTITY, self.origin_y);
+       WriteCoord(MSG_ENTITY, self.origin_z);
+
+       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);
+
+       return TRUE;
+}
+
+void door_trigger_link(entity trig)
+{
+       Net_LinkEntity(trig, FALSE, 0, door_trigger_send);
+}
+
+void spawn_field(vector fmins, vector fmaxs)
 {
        entity  trigger;
-       vector  t1, t2;
+       vector  t1 = fmins, t2 = fmaxs;
 
        trigger = spawn();
        trigger.classname = "doortriggerfield";
@@ -429,12 +497,47 @@ entity spawn_field(vector fmins, vector fmaxs)
        trigger.owner = self;
        trigger.touch = door_trigger_touch;
 
-       t1 = fmins;
-       t2 = fmaxs;
        setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
-       return (trigger);
+       door_trigger_link(trigger);
+}
+
+#elif defined(CSQC)
+
+void ent_door_trigger()
+{
+       float entnum = ReadShort();
+       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.owner = findfloat(world, sv_entnum, entnum); // if owner doesn't exist, it shouldn't matter much
+       self.classname = "doortriggerfield";
+       self.movetype = MOVETYPE_NONE;
+       self.solid = SOLID_TRIGGER;
+       self.trigger_touch = door_trigger_touch;
+       self.draw = trigger_draw_generic;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
 }
 
+#endif
+#ifdef SVQC
+/*
+=============
+LinkDoors
+
+
+=============
+*/
+
 entity LinkDoors_nextent(entity cur, entity near, entity pass)
 {
        while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy))
@@ -446,35 +549,24 @@ entity LinkDoors_nextent(entity cur, entity near, entity pass)
 float LinkDoors_isconnected(entity e1, entity e2, entity pass)
 {
        float DELTA = 4;
-       if (e1.absmin_x > e2.absmax_x + DELTA)
-               return FALSE;
-       if (e1.absmin_y > e2.absmax_y + DELTA)
-               return FALSE;
-       if (e1.absmin_z > e2.absmax_z + DELTA)
-               return FALSE;
-       if (e2.absmin_x > e1.absmax_x + DELTA)
-               return FALSE;
-       if (e2.absmin_y > e1.absmax_y + DELTA)
-               return FALSE;
-       if (e2.absmin_z > e1.absmax_z + DELTA)
-               return FALSE;
+       if((e1.absmin_x > e2.absmax_x + DELTA)
+       || (e1.absmin_y > e2.absmax_y + DELTA)
+       || (e1.absmin_z > e2.absmax_z + DELTA)
+       || (e2.absmin_x > e1.absmax_x + DELTA)
+       || (e2.absmin_y > e1.absmax_y + DELTA)
+       || (e2.absmin_z > e1.absmax_z + DELTA)
+       ) { return FALSE; }
        return TRUE;
 }
 
-
-/*
-=============
-LinkDoors
-
-
-=============
-*/
-
+void door_link();
 void LinkDoors()
 {
        entity  t;
        vector  cmins, cmaxs;
 
+       door_link();
+
        if (self.enemy)
                return;         // already linked by another door
        if (self.spawnflags & 4)
@@ -487,7 +579,7 @@ void LinkDoors()
                        return;
                if (self.items)
                        return;
-               self.trigger_field = spawn_field(self.absmin, self.absmax);
+               spawn_field(self.absmin, self.absmax);
 
                return;         // don't want to link this door
        }
@@ -555,7 +647,7 @@ void LinkDoors()
        if (self.items)
                return;
 
-       self.trigger_field = spawn_field(cmins, cmaxs);
+       spawn_field(cmins, cmaxs);
 }
 
 
@@ -588,6 +680,55 @@ FIXME: only one sound set available at the time being
 
 */
 
+float door_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR);
+
+       WriteShort(MSG_ENTITY, num_for_edict(self));
+       WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+       WriteByte(MSG_ENTITY, self.skin);
+       WriteByte(MSG_ENTITY, self.speed);
+       WriteByte(MSG_ENTITY, self.scale);
+       WriteCoord(MSG_ENTITY, self.origin_x);
+       WriteCoord(MSG_ENTITY, self.origin_y);
+       WriteCoord(MSG_ENTITY, self.origin_z);
+
+       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);
+
+       WriteCoord(MSG_ENTITY, self.movedir_x);
+       WriteCoord(MSG_ENTITY, self.movedir_y);
+       WriteCoord(MSG_ENTITY, self.movedir_z);
+
+       WriteCoord(MSG_ENTITY, self.angles_x);
+       WriteCoord(MSG_ENTITY, self.angles_y);
+       WriteCoord(MSG_ENTITY, self.angles_z);
+
+       WriteCoord(MSG_ENTITY, self.pos1_x);
+       WriteCoord(MSG_ENTITY, self.pos1_y);
+       WriteCoord(MSG_ENTITY, self.pos1_z);
+       WriteCoord(MSG_ENTITY, self.pos2_x);
+       WriteCoord(MSG_ENTITY, self.pos2_y);
+       WriteCoord(MSG_ENTITY, self.pos2_z);
+
+       WriteCoord(MSG_ENTITY, self.size_x);
+       WriteCoord(MSG_ENTITY, self.size_y);
+       WriteCoord(MSG_ENTITY, self.size_z);
+
+       WriteByte(MSG_ENTITY, self.wait);
+
+       return TRUE;
+}
+
+void door_link()
+{
+       Net_LinkEntity(self, FALSE, 0, door_send);
+}
+
 void door_init_startopen()
 {
        setorigin (self, self.pos2);
@@ -624,9 +765,9 @@ void spawnfunc_func_door()
        self.blocked = door_blocked;
        self.use = door_use;
 
-    if(self.dmg && (self.message == ""))
+       if(self.dmg && (self.message == ""))
                self.message = "was squished";
-    if(self.dmg && (self.message2 == ""))
+       if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
 
        if (self.sounds > 0)
@@ -671,3 +812,59 @@ void spawnfunc_func_door()
 
        self.reset = door_reset;
 }
+
+#elif defined(CSQC)
+
+void door_draw()
+{
+       float dt = time - self.move_time;
+       self.move_time = time;
+       if(dt <= 0) { return; }
+
+       trigger_touch_generic(door_touch);
+}
+
+void ent_door()
+{
+       self.sv_entnum = ReadShort();
+       self.warpzone_isboxy = ReadByte();
+       self.skin = ReadByte();
+       self.speed = ReadByte();
+       self.scale = ReadByte();
+       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();
+       self.pos1_x = ReadCoord();
+       self.pos1_y = ReadCoord();
+       self.pos1_z = ReadCoord();
+       self.pos2_x = ReadCoord();
+       self.pos2_y = ReadCoord();
+       self.pos2_z = ReadCoord();
+       self.size_x = ReadCoord();
+       self.size_y = ReadCoord();
+       self.size_z = ReadCoord();
+       self.wait = ReadByte();
+
+       self.classname = "door";
+       self.movetype = MOVETYPE_PUSH;
+       self.solid = SOLID_TRIGGER;
+       self.draw = door_draw;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
+}
+
+#endif
index 21046b1fe141372adc57c5cc4b951f8f19c7fc39..cc508e8d987d47c07ddd2a4d9f386324ba30e4dd 100644 (file)
@@ -3,8 +3,16 @@ const float DOOR_START_OPEN = 1;
 const float DOOR_DONT_LINK = 4;
 const float DOOR_TOGGLE = 32;
 
+const float DOOR_NOSPLASH = 256; // generic anti-splashdamage spawnflag
+
 const float SPAWNFLAGS_GOLD_KEY = 8;
 const float SPAWNFLAGS_SILVER_KEY = 16;
 
-// door properties
-.entity trigger_field;
+#ifdef CSQC
+// stuff for preload
+void ent_door();
+void ent_door_trigger();
+
+// abused
+.float attack_finished_single;
+#endif
index a5b279ec413496f6e12ca67f3a456c08349add57..8a00609151902105d8355f808971b8232a92bba7 100644 (file)
@@ -1 +1,3 @@
+#include "subs.qc"
+#include "triggers.qc"
 #include "f_door.qc"
index ecdddbd1cf099ff3277b1355f0c21e79fcba705d..d819fcead65efd878f6b897713f0189f9bc8873c 100644 (file)
@@ -1 +1,7 @@
+#ifdef CSQC
+#include "../../server/item_key.qh"
+#endif
 #include "f_door.qh"
+#include "triggers.qh"
+#include "subs.qh"
+#include "triggers.qh"
index ada2acd1adf3a183c76aed99298521e4711a8b83..e9d944c44f3e7eb485d054ef98fd43c44371e6f1 100644 (file)
@@ -19,5 +19,3 @@ const float MSG_ENTITY = 5; // csqc
 const float NUM_PLAYERSKINS_TEAMPLAY = 3;
 
 const float ASSAULT_VALUE_INACTIVE = 1000;
-
-const float DOOR_NOSPLASH = 256; // generic anti-splashdamage spawnflag
index 870c61c75b6f5bc00747dc9a0510d0db163bd3c6..752bc99cd4d80c7a50ed0479396428bb89fb0e4c 100644 (file)
@@ -41,8 +41,6 @@ float g_jetpack;
 float sv_clones;
 float sv_foginterval;
 
-entity activator;
-
 float player_count;
 float currentbots;
 float bots_would_leave;
@@ -65,21 +63,6 @@ float server_is_dedicated;
 //.string      map;
 
 //.float       worldtype;
-.float delay;
-.float wait;
-.float lip;
-//.float       light_lev;
-.float speed;
-//.float       style;
-//.float       skill;
-.float sounds;
-.string  platmovetype;
-.float platmovetype_start, platmovetype_end;
-
-.string killtarget;
-
-.vector        pos1, pos2;
-.vector        mangle;
 
 .float pain_finished;                  //Added by Supajoe
 .float pain_frame;                     //"
@@ -89,14 +72,7 @@ float server_is_dedicated;
 .float invincible_finished;
 .float superweapons_finished;
 
-.vector                finaldest, finalangle;          //plat.qc stuff
-.void()                think1;
-.float state;
-.float         t_length, t_width;
-
-.vector destvec;               // for rain
-.vector destvec2;              // for train
-.float cnt;            // for rain
+.float cnt; // used in too many places
 .float count;
 //.float cnt2;
 
@@ -108,15 +84,6 @@ float server_is_dedicated;
 .float fade_time;
 .float fade_rate;
 
-// player animation state
-.float animstate_startframe;
-.float animstate_numframes;
-.float animstate_framerate;
-.float animstate_starttime;
-.float animstate_endtime;
-.float animstate_override;
-.float animstate_looping;
-
 // weapon animation vectors:
 .vector anim_fire1;
 .vector anim_fire2;
@@ -205,20 +172,11 @@ const float WS_READY                      = 4; // idle frame
 
 void weapon_defaultspawnfunc(float wpn);
 
-.vector dest1, dest2;
-
 float gameover;
 float intermission_running;
 float intermission_exittime;
 float alreadychangedlevel;
 
-// Keys player is holding
-.float itemkeys;
-// message delay for func_door locked by keys and key locks
-// this field is used on player entities
-.float key_door_messagetime;
-
-
 .float version;
 
 //swamp
@@ -454,16 +412,6 @@ void W_Porto_Remove (entity p);
 // may be useful to all weapons
 .float bulletcounter;
 
-void target_voicescript_next(entity pl);
-void target_voicescript_clear(entity pl);
-
-.string target2;
-.string target3;
-.string target4;
-.string curvetarget;
-.float target_random;
-.float trigger_reverse;
-
 // Nexball
 .entity ballcarried; // Also used for keepaway
 .float metertime;
index fd0dc7861e20b1cee25cdfaa0545231952d78d57..871a20bbda648d2c7019644bef46f40a0b3fb412 100644 (file)
@@ -1,10 +1,3 @@
-void SUB_NullThink(void) { }
-
-void()  SUB_CalcMoveDone;
-void() SUB_CalcAngleMoveDone;
-//void() SUB_UseTargets;
-void() SUB_Remove;
-
 void spawnfunc_info_null (void)
 {
        remove(self);
@@ -55,387 +48,6 @@ void updateanim(entity e)
        //print(ftos(time), " -> ", ftos(e.frame), "\n");
 }
 
-/*
-==================
-SUB_Remove
-
-Remove self
-==================
-*/
-void SUB_Remove (void)
-{
-       remove (self);
-}
-
-/*
-==================
-SUB_Friction
-
-Applies some friction to self
-==================
-*/
-.float friction;
-void SUB_Friction (void)
-{
-       self.nextthink = time;
-       if(self.flags & FL_ONGROUND)
-               self.velocity = self.velocity * (1 - frametime * self.friction);
-}
-
-/*
-==================
-SUB_VanishOrRemove
-
-Makes client invisible or removes non-client
-==================
-*/
-void SUB_VanishOrRemove (entity ent)
-{
-       if (IS_CLIENT(ent))
-       {
-               // vanish
-               ent.alpha = -1;
-               ent.effects = 0;
-               ent.glow_size = 0;
-               ent.pflags = 0;
-       }
-       else
-       {
-               // remove
-               remove (ent);
-       }
-}
-
-void SUB_SetFade_Think (void)
-{
-       if(self.alpha == 0)
-               self.alpha = 1;
-       self.think = SUB_SetFade_Think;
-       self.nextthink = time;
-       self.alpha -= frametime * self.fade_rate;
-       if (self.alpha < 0.01)
-               SUB_VanishOrRemove(self);
-       else
-               self.nextthink = time;
-}
-
-/*
-==================
-SUB_SetFade
-
-Fade 'ent' out when time >= 'when'
-==================
-*/
-void SUB_SetFade (entity ent, float when, float fadetime)
-{
-       ent.fade_rate = 1/fadetime;
-       ent.think = SUB_SetFade_Think;
-       ent.nextthink = when;
-}
-
-/*
-=============
-SUB_CalcMove
-
-calculate self.velocity and self.nextthink to reach dest from
-self.origin traveling at speed
-===============
-*/
-void SUB_CalcMoveDone (void)
-{
-       // After moving, set origin to exact final destination
-
-       setorigin (self, self.finaldest);
-       self.velocity = '0 0 0';
-       self.nextthink = -1;
-       if (self.think1)
-               self.think1 ();
-}
-
-.float platmovetype_turn;
-void SUB_CalcMove_controller_think (void)
-{
-       entity oldself;
-       float traveltime;
-       float phasepos;
-       float nexttick;
-       vector delta;
-       vector delta2;
-       vector veloc;
-       vector angloc;
-       vector nextpos;
-       delta = self.destvec;
-       delta2 = self.destvec2;
-       if(time < self.animstate_endtime) {
-               nexttick = time + sys_frametime;
-
-               traveltime = self.animstate_endtime - self.animstate_starttime;
-               phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
-               phasepos = cubic_speedfunc(self.platmovetype_start, self.platmovetype_end, phasepos);
-               nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
-               // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
-
-               if(self.owner.platmovetype_turn)
-               {
-                       vector destangle;
-                       destangle = delta + 2 * delta2 * phasepos;
-                       destangle = vectoangles(destangle);
-                       destangle_x = -destangle_x; // flip up / down orientation
-
-                       // take the shortest distance for the angles
-                       self.owner.angles_x -= 360 * floor((self.owner.angles_x - destangle_x) / 360 + 0.5);
-                       self.owner.angles_y -= 360 * floor((self.owner.angles_y - destangle_y) / 360 + 0.5);
-                       self.owner.angles_z -= 360 * floor((self.owner.angles_z - destangle_z) / 360 + 0.5);
-                       angloc = destangle - self.owner.angles;
-                       angloc = angloc * (1 / sys_frametime); // so it arrives for the next frame
-                       self.owner.avelocity = angloc;
-               }
-               if(nexttick < self.animstate_endtime)
-                       veloc = nextpos - self.owner.origin;
-               else
-                       veloc = self.finaldest - self.owner.origin;
-               veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
-
-               self.owner.velocity = veloc;
-               self.nextthink = nexttick;
-       } else {
-               // derivative: delta + 2 * delta2 (e.g. for angle positioning)
-               oldself = self;
-               self.owner.think = self.think1;
-               self = self.owner;
-               remove(oldself);
-               self.think();
-       }
-}
-
-void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector control, vector dest)
-{
-       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
-       // 2 * control * t - 2 * control * t * t + dest * t * t
-       // 2 * control * t + (dest - 2 * control) * t * t
-
-       controller.origin = org; // starting point
-       control -= org;
-       dest -= org;
-
-       controller.destvec = 2 * control; // control point
-       controller.destvec2 = dest - 2 * control; // quadratic part required to reach end point
-       // also: initial d/dphasepos origin = 2 * control, final speed = 2 * (dest - control)
-}
-
-void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector dest)
-{
-       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
-       // 2 * control * t - 2 * control * t * t + dest * t * t
-       // 2 * control * t + (dest - 2 * control) * t * t
-
-       controller.origin = org; // starting point
-       dest -= org;
-
-       controller.destvec = dest; // end point
-       controller.destvec2 = '0 0 0';
-}
-
-float TSPEED_TIME = -1;
-float TSPEED_LINEAR = 0;
-float TSPEED_START = 1;
-float TSPEED_END = 2;
-// TODO average too?
-
-void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       float   traveltime;
-       entity controller;
-
-       if (!tspeed)
-               objerror ("No speed is defined!");
-
-       self.think1 = func;
-       self.finaldest = tdest;
-       self.think = SUB_CalcMoveDone;
-
-       switch(tspeedtype)
-       {
-               default:
-               case TSPEED_START:
-                       traveltime = 2 * vlen(tcontrol - self.origin) / tspeed;
-                       break;
-               case TSPEED_END:
-                       traveltime = 2 * vlen(tcontrol - tdest)       / tspeed;
-                       break;
-               case TSPEED_LINEAR:
-                       traveltime = vlen(tdest - self.origin)        / tspeed;
-                       break;
-               case TSPEED_TIME:
-                       traveltime = tspeed;
-                       break;
-       }
-
-       if (traveltime < 0.1) // useless anim
-       {
-               self.velocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
-
-       controller = spawn();
-       controller.classname = "SUB_CalcMove_controller";
-       controller.owner = self;
-       controller.platmovetype = self.platmovetype;
-       controller.platmovetype_start = self.platmovetype_start;
-       controller.platmovetype_end = self.platmovetype_end;
-       SUB_CalcMove_controller_setbezier(controller, self.origin, tcontrol, tdest);
-       controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit.
-       controller.animstate_starttime = time;
-       controller.animstate_endtime = time + traveltime;
-       controller.think = SUB_CalcMove_controller_think;
-       controller.think1 = self.think;
-
-       // the thinking is now done by the controller
-       self.think = SUB_NullThink; // for PushMove
-       self.nextthink = self.ltime + traveltime;
-
-       // invoke controller
-       self = controller;
-       self.think();
-       self = self.owner;
-}
-
-void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       vector  delta;
-       float   traveltime;
-
-       if (!tspeed)
-               objerror ("No speed is defined!");
-
-       self.think1 = func;
-       self.finaldest = tdest;
-       self.think = SUB_CalcMoveDone;
-
-       if (tdest == self.origin)
-       {
-               self.velocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
-
-       delta = tdest - self.origin;
-
-       switch(tspeedtype)
-       {
-               default:
-               case TSPEED_START:
-               case TSPEED_END:
-               case TSPEED_LINEAR:
-                       traveltime = vlen (delta) / tspeed;
-                       break;
-               case TSPEED_TIME:
-                       traveltime = tspeed;
-                       break;
-       }
-
-       // Very short animations don't really show off the effect
-       // of controlled animation, so let's just use linear movement.
-       // Alternatively entities can choose to specify non-controlled movement.
-        // The only currently implemented alternative movement is linear (value 1)
-       if (traveltime < 0.15 || (self.platmovetype_start == 1 && self.platmovetype_end == 1)) // is this correct?
-       {
-               self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
-               self.nextthink = self.ltime + traveltime;
-               return;
-       }
-
-       // now just run like a bezier curve...
-       SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeedtype, tspeed, func);
-}
-
-void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       entity  oldself;
-
-       oldself = self;
-       self = ent;
-
-       SUB_CalcMove (tdest, tspeedtype, tspeed, func);
-
-       self = oldself;
-}
-
-/*
-=============
-SUB_CalcAngleMove
-
-calculate self.avelocity and self.nextthink to reach destangle from
-self.angles rotating
-
-The calling function should make sure self.think is valid
-===============
-*/
-void SUB_CalcAngleMoveDone (void)
-{
-       // After rotating, set angle to exact final angle
-       self.angles = self.finalangle;
-       self.avelocity = '0 0 0';
-       self.nextthink = -1;
-       if (self.think1)
-               self.think1 ();
-}
-
-// FIXME: I fixed this function only for rotation around the main axes
-void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
-{
-       vector  delta;
-       float   traveltime;
-
-       if (!tspeed)
-               objerror ("No speed is defined!");
-
-       // take the shortest distance for the angles
-       self.angles_x -= 360 * floor((self.angles_x - destangle_x) / 360 + 0.5);
-       self.angles_y -= 360 * floor((self.angles_y - destangle_y) / 360 + 0.5);
-       self.angles_z -= 360 * floor((self.angles_z - destangle_z) / 360 + 0.5);
-       delta = destangle - self.angles;
-
-       switch(tspeedtype)
-       {
-               default:
-               case TSPEED_START:
-               case TSPEED_END:
-               case TSPEED_LINEAR:
-                       traveltime = vlen (delta) / tspeed;
-                       break;
-               case TSPEED_TIME:
-                       traveltime = tspeed;
-                       break;
-       }
-
-       self.think1 = func;
-       self.finalangle = destangle;
-       self.think = SUB_CalcAngleMoveDone;
-
-       if (traveltime < 0.1)
-       {
-               self.avelocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
-
-       self.avelocity = delta * (1 / traveltime);
-       self.nextthink = self.ltime + traveltime;
-}
-
-void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
-{
-       entity  oldself;
-
-       oldself = self;
-       self = ent;
-
-       SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func);
-
-       self = oldself;
-}
 
 /*
 ==================
diff --git a/qcsrc/server/g_triggers.qc b/qcsrc/server/g_triggers.qc
deleted file mode 100644 (file)
index c5fb08c..0000000
+++ /dev/null
@@ -1,2159 +0,0 @@
-void SUB_DontUseTargets()
-{
-}
-
-
-void() SUB_UseTargets;
-
-void DelayThink()
-{
-       activator = self.enemy;
-       SUB_UseTargets ();
-       remove(self);
-}
-
-/*
-==============================
-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
-do the SUB_UseTargets after that many seconds have passed.
-
-Centerprints any self.message to the activator.
-
-Removes all entities with a targetname that match self.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
-
-==============================
-*/
-void SUB_UseTargets()
-{
-       entity t, stemp, otemp, act;
-       string s;
-       float i;
-
-//
-// check for a delay
-//
-       if (self.delay)
-       {
-       // 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;
-               return;
-       }
-
-
-//
-// print the message
-//
-       if(self)
-       if(IS_PLAYER(activator) && self.message != "")
-       if(IS_REAL_CLIENT(activator))
-       {
-               centerprint(activator, self.message);
-               if (self.noise == "")
-                       play2(activator, "misc/talk.wav");
-       }
-
-//
-// kill the killtagets
-//
-       s = self.killtarget;
-       if (s != "")
-       {
-               for(t = world; (t = find(t, targetname, s)); )
-                       remove(t);
-       }
-
-//
-// fire targets
-//
-       act = activator;
-       stemp = self;
-       otemp = other;
-
-       if(stemp.target_random)
-               RandomSelection_Init();
-
-       for(i = 0; i < 4; ++i)
-       {
-               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;
-               }
-               if (s != "")
-               {
-                       for(t = world; (t = find(t, targetname, s)); )
-                       if(t.use)
-                       {
-                               if(stemp.target_random)
-                               {
-                                       RandomSelection_Add(t, 0, string_null, 1, 0);
-                               }
-                               else
-                               {
-                                       self = t;
-                                       other = stemp;
-                                       activator = act;
-                                       self.use();
-                               }
-                       }
-               }
-       }
-
-       if(stemp.target_random && RandomSelection_chosen_ent)
-       {
-               self = RandomSelection_chosen_ent;
-               other = stemp;
-               activator = act;
-               self.use();
-       }
-
-       activator = act;
-       self = stemp;
-       other = otemp;
-}
-
-
-//=============================================================================
-
-const float    SPAWNFLAG_NOMESSAGE = 1;
-const float    SPAWNFLAG_NOTOUCH = 1;
-
-// the wait time has passed, so set back up for another activation
-void multi_wait()
-{
-       if (self.max_health)
-       {
-               self.health = self.max_health;
-               self.takedamage = DAMAGE_YES;
-               self.solid = SOLID_BBOX;
-       }
-}
-
-
-// the trigger was just touched/killed/used
-// self.enemy should be set to the activator so it can be held through a delay
-// so wait for the delay time before firing
-void multi_trigger()
-{
-       if (self.nextthink > time)
-       {
-               return;         // allready been triggered
-       }
-
-       if (self.classname == "trigger_secret")
-       {
-               if (!IS_PLAYER(self.enemy))
-                       return;
-               found_secrets = found_secrets + 1;
-               WriteByte (MSG_ALL, SVC_FOUNDSECRET);
-       }
-
-       if (self.noise)
-               sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-
-// don't trigger again until reset
-       self.takedamage = DAMAGE_NO;
-
-       activator = self.enemy;
-       other = self.goalentity;
-       SUB_UseTargets();
-
-       if (self.wait > 0)
-       {
-               self.think = multi_wait;
-               self.nextthink = time + self.wait;
-       }
-       else if (self.wait == 0)
-       {
-               multi_wait(); // waiting finished
-       }
-       else
-       {       // we can't just remove (self) here, because this is a touch function
-               // called wheil C code is looping through area links...
-               self.touch = func_null;
-       }
-}
-
-void multi_use()
-{
-       self.goalentity = other;
-       self.enemy = activator;
-       multi_trigger();
-}
-
-void multi_touch()
-{
-       if(!(self.spawnflags & 2))
-       if(!other.iscreature)
-                       return;
-
-       if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
-                       return;
-
-// if the trigger has an angles field, check player's facing direction
-       if (self.movedir != '0 0 0')
-       {
-               makevectors (other.angles);
-               if (v_forward * self.movedir < 0)
-                       return;         // not facing the right way
-       }
-
-       EXACTTRIGGER_TOUCH;
-
-       self.enemy = other;
-       self.goalentity = other;
-       multi_trigger ();
-}
-
-void multi_eventdamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-       if (!self.takedamage)
-               return;
-       if(self.spawnflags & DOOR_NOSPLASH)
-               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
-                       return;
-       self.health = self.health - damage;
-       if (self.health <= 0)
-       {
-               self.enemy = attacker;
-               self.goalentity = inflictor;
-               multi_trigger();
-       }
-}
-
-void multi_reset()
-{
-       if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
-               self.touch = multi_touch;
-       if (self.max_health)
-       {
-               self.health = self.max_health;
-               self.takedamage = DAMAGE_YES;
-               self.solid = SOLID_BBOX;
-       }
-       self.think = func_null;
-       self.nextthink = 0;
-       self.team = self.team_saved;
-}
-
-/*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
-Variable sized repeatable trigger.  Must be targeted at one or more entities.  If "health" is set, the trigger must be killed to activate each time.
-If "delay" is set, the trigger waits some time after activating before firing.
-"wait" : Seconds between triggerings. (.2 default)
-If notouch is set, the trigger is only fired by other entities, not by touching.
-NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
-sounds
-1)     secret
-2)     beep beep
-3)     large switch
-4)
-set "message" to text string
-*/
-void spawnfunc_trigger_multiple()
-{
-       self.reset = multi_reset;
-       if (self.sounds == 1)
-       {
-               precache_sound ("misc/secret.wav");
-               self.noise = "misc/secret.wav";
-       }
-       else if (self.sounds == 2)
-       {
-               precache_sound ("misc/talk.wav");
-               self.noise = "misc/talk.wav";
-       }
-       else if (self.sounds == 3)
-       {
-               precache_sound ("misc/trigger1.wav");
-               self.noise = "misc/trigger1.wav";
-       }
-
-       if (!self.wait)
-               self.wait = 0.2;
-       else if(self.wait < -1)
-               self.wait = 0;
-       self.use = multi_use;
-
-       EXACTTRIGGER_INIT;
-
-       self.team_saved = self.team;
-
-       if (self.health)
-       {
-               if (self.spawnflags & SPAWNFLAG_NOTOUCH)
-                       objerror ("health and notouch don't make sense\n");
-               self.max_health = self.health;
-               self.event_damage = multi_eventdamage;
-               self.takedamage = DAMAGE_YES;
-               self.solid = SOLID_BBOX;
-               setorigin (self, self.origin);  // make sure it links into the world
-       }
-       else
-       {
-               if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
-               {
-                       self.touch = multi_touch;
-                       setorigin (self, self.origin);  // make sure it links into the world
-               }
-       }
-}
-
-
-/*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
-Variable sized trigger. Triggers once, then removes itself.  You must set the key "target" to the name of another object in the level that has a matching
-"targetname".  If "health" is set, the trigger must be killed to activate.
-If notouch is set, the trigger is only fired by other entities, not by touching.
-if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
-if "angle" is set, the trigger will only fire when someone is facing the direction of the angle.  Use "360" for an angle of 0.
-sounds
-1)     secret
-2)     beep beep
-3)     large switch
-4)
-set "message" to text string
-*/
-void spawnfunc_trigger_once()
-{
-       self.wait = -1;
-       spawnfunc_trigger_multiple();
-}
-
-//=============================================================================
-
-/*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
-This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
-*/
-void spawnfunc_trigger_relay()
-{
-       self.use = SUB_UseTargets;
-       self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
-}
-
-void delay_use()
-{
-    self.think = SUB_UseTargets;
-    self.nextthink = self.wait;
-}
-
-void delay_reset()
-{
-       self.think = func_null;
-       self.nextthink = 0;
-}
-
-void spawnfunc_trigger_delay()
-{
-    if(!self.wait)
-        self.wait = 1;
-
-    self.use = delay_use;
-    self.reset = delay_reset;
-}
-
-//=============================================================================
-
-
-void counter_use()
-{
-       self.count -= 1;
-       if (self.count < 0)
-               return;
-
-       if (self.count == 0)
-       {
-               if(IS_PLAYER(activator) && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
-                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COMPLETED);
-
-               self.enemy = activator;
-               multi_trigger ();
-       }
-       else
-       {
-               if(IS_PLAYER(activator) && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
-               if(self.count >= 4)
-                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COUNTER);
-               else
-                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, self.count);
-       }
-}
-
-void counter_reset()
-{
-       self.count = self.cnt;
-       multi_reset();
-}
-
-/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
-Acts as an intermediary for an action that takes multiple inputs.
-
-If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
-
-After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
-*/
-void spawnfunc_trigger_counter()
-{
-       self.wait = -1;
-       if (!self.count)
-               self.count = 2;
-       self.cnt = self.count;
-
-       self.use = counter_use;
-       self.reset = counter_reset;
-}
-
-void trigger_hurt_use()
-{
-       if(IS_PLAYER(activator))
-               self.enemy = activator;
-       else
-               self.enemy = world; // let's just destroy it, if taking over is too much work
-}
-
-.float triggerhurttime;
-void trigger_hurt_touch()
-{
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
-                       return;
-
-       // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
-       if (other.iscreature)
-       {
-               if (other.takedamage)
-               if (other.triggerhurttime < time)
-               {
-                       EXACTTRIGGER_TOUCH;
-                       other.triggerhurttime = time + 1;
-
-                       entity own;
-                       own = self.enemy;
-                       if (!IS_PLAYER(own))
-                       {
-                               own = self;
-                               self.enemy = world; // I still hate you all
-                       }
-
-                       Damage (other, self, own, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-               }
-       }
-       else if(other.damagedbytriggers)
-       {
-               if(other.takedamage)
-               {
-                       EXACTTRIGGER_TOUCH;
-                       Damage(other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-               }
-       }
-
-       return;
-}
-
-/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
-Any object touching this will be hurt
-set dmg to damage amount
-defalt dmg = 5
-*/
-.entity trigger_hurt_next;
-entity trigger_hurt_last;
-entity trigger_hurt_first;
-void spawnfunc_trigger_hurt()
-{
-       EXACTTRIGGER_INIT;
-       self.active = ACTIVE_ACTIVE;
-       self.touch = trigger_hurt_touch;
-       self.use = trigger_hurt_use;
-       self.enemy = world; // I hate you all
-       if (!self.dmg)
-               self.dmg = 1000;
-       if (self.message == "")
-               self.message = "was in the wrong place";
-       if (self.message2 == "")
-               self.message2 = "was thrown into a world of hurt by";
-       // self.message = "someone like %s always gets wrongplaced";
-
-       if(!trigger_hurt_first)
-               trigger_hurt_first = self;
-       if(trigger_hurt_last)
-               trigger_hurt_last.trigger_hurt_next = self;
-       trigger_hurt_last = self;
-}
-
-float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
-{
-       entity th;
-
-       for(th = trigger_hurt_first; th; th = th.trigger_hurt_next)
-               if(tracebox_hits_box(start, mi, ma, end, th.absmin, th.absmax))
-                       return TRUE;
-
-       return FALSE;
-}
-
-//////////////////////////////////////////////////////////////
-//
-//
-//
-//Trigger heal --a04191b92fbd93aa67214ef7e72d6d2e
-//
-//////////////////////////////////////////////////////////////
-
-.float triggerhealtime;
-void trigger_heal_touch()
-{
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
-       if (other.iscreature)
-       {
-               if (other.takedamage)
-               if (!other.deadflag)
-               if (other.triggerhealtime < time)
-               {
-                       EXACTTRIGGER_TOUCH;
-                       other.triggerhealtime = time + 1;
-
-                       if (other.health < self.max_health)
-                       {
-                               other.health = min(other.health + self.health, self.max_health);
-                               other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
-                               sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-                       }
-               }
-       }
-}
-
-void spawnfunc_trigger_heal()
-{
-       self.active = ACTIVE_ACTIVE;
-
-       EXACTTRIGGER_INIT;
-       self.touch = trigger_heal_touch;
-       if (!self.health)
-               self.health = 10;
-       if (!self.max_health)
-               self.max_health = 200; //Max health topoff for field
-       if(self.noise == "")
-               self.noise = "misc/mediumhealth.wav";
-       precache_sound(self.noise);
-}
-
-
-//////////////////////////////////////////////////////////////
-//
-//
-//
-//End trigger_heal
-//
-//////////////////////////////////////////////////////////////
-
-.entity trigger_gravity_check;
-void trigger_gravity_remove(entity own)
-{
-       if(own.trigger_gravity_check.owner == own)
-       {
-               UpdateCSQCProjectile(own);
-               own.gravity = own.trigger_gravity_check.gravity;
-               remove(own.trigger_gravity_check);
-       }
-       else
-               backtrace("Removing a trigger_gravity_check with no valid owner");
-       own.trigger_gravity_check = world;
-}
-void trigger_gravity_check_think()
-{
-       // This spawns when a player enters the gravity zone and checks if he left.
-       // Each frame, self.count is set to 2 by trigger_gravity_touch() and decreased by 1 here.
-       // It the player has left the gravity trigger, this will be allowed to reach 0 and indicate that.
-       if(self.count <= 0)
-       {
-               if(self.owner.trigger_gravity_check == self)
-                       trigger_gravity_remove(self.owner);
-               else
-                       remove(self);
-               return;
-       }
-       else
-       {
-               self.count -= 1;
-               self.nextthink = time;
-       }
-}
-
-void trigger_gravity_use()
-{
-       self.state = !self.state;
-}
-
-void trigger_gravity_touch()
-{
-       float g;
-
-       if(self.state != TRUE)
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-       g = self.gravity;
-
-       if (!(self.spawnflags & 1))
-       {
-               if(other.trigger_gravity_check)
-               {
-                       if(self == other.trigger_gravity_check.enemy)
-                       {
-                               // same?
-                               other.trigger_gravity_check.count = 2; // gravity one more frame...
-                               return;
-                       }
-
-                       // compare prio
-                       if(self.cnt > other.trigger_gravity_check.enemy.cnt)
-                               trigger_gravity_remove(other);
-                       else
-                               return;
-               }
-               other.trigger_gravity_check = spawn();
-               other.trigger_gravity_check.enemy = self;
-               other.trigger_gravity_check.owner = other;
-               other.trigger_gravity_check.gravity = other.gravity;
-               other.trigger_gravity_check.think = trigger_gravity_check_think;
-               other.trigger_gravity_check.nextthink = time;
-               other.trigger_gravity_check.count = 2;
-               if(other.gravity)
-                       g *= other.gravity;
-       }
-
-       if (other.gravity != g)
-       {
-               other.gravity = g;
-               if(self.noise != "")
-                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-               UpdateCSQCProjectile(self.owner);
-       }
-}
-
-void spawnfunc_trigger_gravity()
-{
-       if(self.gravity == 1)
-               return;
-
-       EXACTTRIGGER_INIT;
-       self.touch = trigger_gravity_touch;
-       if(self.noise != "")
-               precache_sound(self.noise);
-
-       self.state = TRUE;
-       IFTARGETED
-       {
-               self.use = trigger_gravity_use;
-               if(self.spawnflags & 2)
-                       self.state = FALSE;
-       }
-}
-
-//=============================================================================
-
-// TODO add a way to do looped sounds with sound(); then complete this entity
-.float volume, atten;
-void target_speaker_use_off();
-void target_speaker_use_activator()
-{
-       if (!IS_REAL_CLIENT(activator))
-               return;
-       string snd;
-       if(substring(self.noise, 0, 1) == "*")
-       {
-               var .string sample;
-               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
-               if(GetPlayerSoundSampleField_notFound)
-                       snd = "misc/null.wav";
-               else if(activator.sample == "")
-                       snd = "misc/null.wav";
-               else
-               {
-                       tokenize_console(activator.sample);
-                       float n;
-                       n = stof(argv(1));
-                       if(n > 0)
-                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
-                       else
-                               snd = strcat(argv(0), ".wav"); // randomization
-               }
-       }
-       else
-               snd = self.noise;
-       msg_entity = activator;
-       soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten);
-}
-void target_speaker_use_on()
-{
-       string snd;
-       if(substring(self.noise, 0, 1) == "*")
-       {
-               var .string sample;
-               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
-               if(GetPlayerSoundSampleField_notFound)
-                       snd = "misc/null.wav";
-               else if(activator.sample == "")
-                       snd = "misc/null.wav";
-               else
-               {
-                       tokenize_console(activator.sample);
-                       float n;
-                       n = stof(argv(1));
-                       if(n > 0)
-                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
-                       else
-                               snd = strcat(argv(0), ".wav"); // randomization
-               }
-       }
-       else
-               snd = self.noise;
-       sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
-       if(self.spawnflags & 3)
-               self.use = target_speaker_use_off;
-}
-void target_speaker_use_off()
-{
-       sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten);
-       self.use = target_speaker_use_on;
-}
-void target_speaker_reset()
-{
-       if(self.spawnflags & 1) // LOOPED_ON
-       {
-               if(self.use == target_speaker_use_on)
-                       target_speaker_use_on();
-       }
-       else if(self.spawnflags & 2)
-       {
-               if(self.use == target_speaker_use_off)
-                       target_speaker_use_off();
-       }
-}
-
-void spawnfunc_target_speaker()
-{
-       // TODO: "*" prefix to sound file name
-       // TODO: wait and random (just, HOW? random is not a field)
-       if(self.noise)
-               precache_sound (self.noise);
-
-       if(!self.atten && !(self.spawnflags & 4))
-       {
-               IFTARGETED
-                       self.atten = ATTEN_NORM;
-               else
-                       self.atten = ATTEN_STATIC;
-       }
-       else if(self.atten < 0)
-               self.atten = 0;
-
-       if(!self.volume)
-               self.volume = 1;
-
-       IFTARGETED
-       {
-               if(self.spawnflags & 8) // ACTIVATOR
-                       self.use = target_speaker_use_activator;
-               else if(self.spawnflags & 1) // LOOPED_ON
-               {
-                       target_speaker_use_on();
-                       self.reset = target_speaker_reset;
-               }
-               else if(self.spawnflags & 2) // LOOPED_OFF
-               {
-                       self.use = target_speaker_use_on;
-                       self.reset = target_speaker_reset;
-               }
-               else
-                       self.use = target_speaker_use_on;
-       }
-       else if(self.spawnflags & 1) // LOOPED_ON
-       {
-               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
-               remove(self);
-       }
-       else if(self.spawnflags & 2) // LOOPED_OFF
-       {
-               objerror("This sound entity can never be activated");
-       }
-       else
-       {
-               // Quake/Nexuiz fallback
-               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
-               remove(self);
-       }
-}
-
-
-void spawnfunc_func_stardust() {
-       self.effects = EF_STARDUST;
-}
-
-.string bgmscript;
-.float bgmscriptattack;
-.float bgmscriptdecay;
-.float bgmscriptsustain;
-.float bgmscriptrelease;
-float pointparticles_SendEntity(entity to, float fl)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
-
-       // optional features to save space
-       fl = fl & 0x0F;
-       if(self.spawnflags & 2)
-               fl |= 0x10; // absolute count on toggle-on
-       if(self.movedir != '0 0 0' || self.velocity != '0 0 0')
-               fl |= 0x20; // 4 bytes - saves CPU
-       if(self.waterlevel || self.count != 1)
-               fl |= 0x40; // 4 bytes - obscure features almost never used
-       if(self.mins != '0 0 0' || self.maxs != '0 0 0')
-               fl |= 0x80; // 14 bytes - saves lots of space
-
-       WriteByte(MSG_ENTITY, fl);
-       if(fl & 2)
-       {
-               if(self.state)
-                       WriteCoord(MSG_ENTITY, self.impulse);
-               else
-                       WriteCoord(MSG_ENTITY, 0); // off
-       }
-       if(fl & 4)
-       {
-               WriteCoord(MSG_ENTITY, self.origin_x);
-               WriteCoord(MSG_ENTITY, self.origin_y);
-               WriteCoord(MSG_ENTITY, self.origin_z);
-       }
-       if(fl & 1)
-       {
-               if(self.model != "null")
-               {
-                       WriteShort(MSG_ENTITY, self.modelindex);
-                       if(fl & 0x80)
-                       {
-                               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);
-                       }
-               }
-               else
-               {
-                       WriteShort(MSG_ENTITY, 0);
-                       if(fl & 0x80)
-                       {
-                               WriteCoord(MSG_ENTITY, self.maxs_x);
-                               WriteCoord(MSG_ENTITY, self.maxs_y);
-                               WriteCoord(MSG_ENTITY, self.maxs_z);
-                       }
-               }
-               WriteShort(MSG_ENTITY, self.cnt);
-               if(fl & 0x20)
-               {
-                       WriteShort(MSG_ENTITY, compressShortVector(self.velocity));
-                       WriteShort(MSG_ENTITY, compressShortVector(self.movedir));
-               }
-               if(fl & 0x40)
-               {
-                       WriteShort(MSG_ENTITY, self.waterlevel * 16.0);
-                       WriteByte(MSG_ENTITY, self.count * 16.0);
-               }
-               WriteString(MSG_ENTITY, self.noise);
-               if(self.noise != "")
-               {
-                       WriteByte(MSG_ENTITY, floor(self.atten * 64));
-                       WriteByte(MSG_ENTITY, floor(self.volume * 255));
-               }
-               WriteString(MSG_ENTITY, self.bgmscript);
-               if(self.bgmscript != "")
-               {
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptattack * 64));
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptdecay * 64));
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptsustain * 255));
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptrelease * 64));
-               }
-       }
-       return 1;
-}
-
-void pointparticles_use()
-{
-       self.state = !self.state;
-       self.SendFlags |= 2;
-}
-
-void pointparticles_think()
-{
-       if(self.origin != self.oldorigin)
-       {
-               self.SendFlags |= 4;
-               self.oldorigin = self.origin;
-       }
-       self.nextthink = time;
-}
-
-void pointparticles_reset()
-{
-       if(self.spawnflags & 1)
-               self.state = 1;
-       else
-               self.state = 0;
-}
-
-void spawnfunc_func_pointparticles()
-{
-       if(self.model != "")
-               setmodel(self, self.model);
-       if(self.noise != "")
-               precache_sound (self.noise);
-
-       if(!self.bgmscriptsustain)
-               self.bgmscriptsustain = 1;
-       else if(self.bgmscriptsustain < 0)
-               self.bgmscriptsustain = 0;
-
-       if(!self.atten)
-               self.atten = ATTEN_NORM;
-       else if(self.atten < 0)
-               self.atten = 0;
-       if(!self.volume)
-               self.volume = 1;
-       if(!self.count)
-               self.count = 1;
-       if(!self.impulse)
-               self.impulse = 1;
-
-       if(!self.modelindex)
-       {
-               setorigin(self, self.origin + self.mins);
-               setsize(self, '0 0 0', self.maxs - self.mins);
-       }
-       if(!self.cnt)
-               self.cnt = particleeffectnum(self.mdl);
-
-       Net_LinkEntity(self, (self.spawnflags & 4), 0, pointparticles_SendEntity);
-
-       IFTARGETED
-       {
-               self.use = pointparticles_use;
-               self.reset = pointparticles_reset;
-               self.reset();
-       }
-       else
-               self.state = 1;
-       self.think = pointparticles_think;
-       self.nextthink = time;
-}
-
-void spawnfunc_func_sparks()
-{
-       // self.cnt is the amount of sparks that one burst will spawn
-       if(self.cnt < 1) {
-               self.cnt = 25.0; // nice default value
-       }
-
-       // self.wait is the probability that a sparkthink will spawn a spark shower
-       // range: 0 - 1, but 0 makes little sense, so...
-       if(self.wait < 0.05) {
-               self.wait = 0.25; // nice default value
-       }
-
-       self.count = self.cnt;
-       self.mins = '0 0 0';
-       self.maxs = '0 0 0';
-       self.velocity = '0 0 -1';
-       self.mdl = "TE_SPARK";
-       self.impulse = 10 * self.wait; // by default 2.5/sec
-       self.wait = 0;
-       self.cnt = 0; // use mdl
-
-       spawnfunc_func_pointparticles();
-}
-
-float rainsnow_SendEntity(entity to, float sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_RAINSNOW);
-       WriteByte(MSG_ENTITY, self.state);
-       WriteCoord(MSG_ENTITY, self.origin_x + self.mins_x);
-       WriteCoord(MSG_ENTITY, self.origin_y + self.mins_y);
-       WriteCoord(MSG_ENTITY, self.origin_z + self.mins_z);
-       WriteCoord(MSG_ENTITY, self.maxs_x - self.mins_x);
-       WriteCoord(MSG_ENTITY, self.maxs_y - self.mins_y);
-       WriteCoord(MSG_ENTITY, self.maxs_z - self.mins_z);
-       WriteShort(MSG_ENTITY, compressShortVector(self.dest));
-       WriteShort(MSG_ENTITY, self.count);
-       WriteByte(MSG_ENTITY, self.cnt);
-       return 1;
-}
-
-/*QUAKED spawnfunc_func_rain (0 .5 .8) ?
-This is an invisible area like a trigger, which rain falls inside of.
-
-Keys:
-"velocity"
- falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
-"cnt"
- sets color of rain (default 12 - white)
-"count"
- adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-void spawnfunc_func_rain()
-{
-       self.dest = self.velocity;
-       self.velocity = '0 0 0';
-       if (!self.dest)
-               self.dest = '0 0 -700';
-       self.angles = '0 0 0';
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_NOT;
-       SetBrushEntityModel();
-       if (!self.cnt)
-               self.cnt = 12;
-       if (!self.count)
-               self.count = 2000;
-       self.count = 0.01 * self.count * (self.size_x / 1024) * (self.size_y / 1024);
-       if (self.count < 1)
-               self.count = 1;
-       if(self.count > 65535)
-               self.count = 65535;
-
-       self.state = 1; // 1 is rain, 0 is snow
-       self.Version = 1;
-
-       Net_LinkEntity(self, FALSE, 0, rainsnow_SendEntity);
-}
-
-
-/*QUAKED spawnfunc_func_snow (0 .5 .8) ?
-This is an invisible area like a trigger, which snow falls inside of.
-
-Keys:
-"velocity"
- falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
-"cnt"
- sets color of rain (default 12 - white)
-"count"
- adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-void spawnfunc_func_snow()
-{
-       self.dest = self.velocity;
-       self.velocity = '0 0 0';
-       if (!self.dest)
-               self.dest = '0 0 -300';
-       self.angles = '0 0 0';
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_NOT;
-       SetBrushEntityModel();
-       if (!self.cnt)
-               self.cnt = 12;
-       if (!self.count)
-               self.count = 2000;
-       self.count = 0.01 * self.count * (self.size_x / 1024) * (self.size_y / 1024);
-       if (self.count < 1)
-               self.count = 1;
-       if(self.count > 65535)
-               self.count = 65535;
-
-       self.state = 0; // 1 is rain, 0 is snow
-       self.Version = 1;
-
-       Net_LinkEntity(self, FALSE, 0, rainsnow_SendEntity);
-}
-
-.float modelscale;
-void misc_laser_aim()
-{
-       vector a;
-       if(self.enemy)
-       {
-               if(self.spawnflags & 2)
-               {
-                       if(self.enemy.origin != self.mangle)
-                       {
-                               self.mangle = self.enemy.origin;
-                               self.SendFlags |= 2;
-                       }
-               }
-               else
-               {
-                       a = vectoangles(self.enemy.origin - self.origin);
-                       a_x = -a_x;
-                       if(a != self.mangle)
-                       {
-                               self.mangle = a;
-                               self.SendFlags |= 2;
-                       }
-               }
-       }
-       else
-       {
-               if(self.angles != self.mangle)
-               {
-                       self.mangle = self.angles;
-                       self.SendFlags |= 2;
-               }
-       }
-       if(self.origin != self.oldorigin)
-       {
-               self.SendFlags |= 1;
-               self.oldorigin = self.origin;
-       }
-}
-
-void misc_laser_init()
-{
-       if(self.target != "")
-               self.enemy = find(world, targetname, self.target);
-}
-
-.entity pusher;
-void misc_laser_think()
-{
-       vector o;
-       entity oldself;
-       entity hitent;
-       vector hitloc;
-
-       self.nextthink = time;
-
-       if(!self.state)
-               return;
-
-       misc_laser_aim();
-
-       if(self.enemy)
-       {
-               o = self.enemy.origin;
-               if (!(self.spawnflags & 2))
-                       o = self.origin + normalize(o - self.origin) * 32768;
-       }
-       else
-       {
-               makevectors(self.mangle);
-               o = self.origin + v_forward * 32768;
-       }
-
-       if(self.dmg || self.enemy.target != "")
-       {
-               traceline(self.origin, o, MOVE_NORMAL, self);
-       }
-       hitent = trace_ent;
-       hitloc = trace_endpos;
-
-       if(self.enemy.target != "") // DETECTOR laser
-       {
-               if(trace_ent.iscreature)
-               {
-                       self.pusher = hitent;
-                       if(!self.count)
-                       {
-                               self.count = 1;
-
-                               oldself = self;
-                               self = self.enemy;
-                               activator = self.pusher;
-                               SUB_UseTargets();
-                               self = oldself;
-                       }
-               }
-               else
-               {
-                       if(self.count)
-                       {
-                               self.count = 0;
-
-                               oldself = self;
-                               self = self.enemy;
-                               activator = self.pusher;
-                               SUB_UseTargets();
-                               self = oldself;
-                       }
-               }
-       }
-
-       if(self.dmg)
-       {
-               if(self.team)
-                       if(((self.spawnflags & 8) == 0) == (self.team != hitent.team))
-                               return;
-               if(hitent.takedamage)
-                       Damage(hitent, self, self, ((self.dmg < 0) ? 100000 : (self.dmg * frametime)), DEATH_HURTTRIGGER, hitloc, '0 0 0');
-       }
-}
-
-float laser_SendEntity(entity to, float fl)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_LASER);
-       fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
-       if(self.spawnflags & 2)
-               fl |= 0x80;
-       if(self.alpha)
-               fl |= 0x40;
-       if(self.scale != 1 || self.modelscale != 1)
-               fl |= 0x20;
-       if(self.spawnflags & 4)
-               fl |= 0x10;
-       WriteByte(MSG_ENTITY, fl);
-       if(fl & 1)
-       {
-               WriteCoord(MSG_ENTITY, self.origin_x);
-               WriteCoord(MSG_ENTITY, self.origin_y);
-               WriteCoord(MSG_ENTITY, self.origin_z);
-       }
-       if(fl & 8)
-       {
-               WriteByte(MSG_ENTITY, self.colormod_x * 255.0);
-               WriteByte(MSG_ENTITY, self.colormod_y * 255.0);
-               WriteByte(MSG_ENTITY, self.colormod_z * 255.0);
-               if(fl & 0x40)
-                       WriteByte(MSG_ENTITY, self.alpha * 255.0);
-               if(fl & 0x20)
-               {
-                       WriteByte(MSG_ENTITY, bound(0, self.scale * 16.0, 255));
-                       WriteByte(MSG_ENTITY, bound(0, self.modelscale * 16.0, 255));
-               }
-               if((fl & 0x80) || !(fl & 0x10)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
-                       WriteShort(MSG_ENTITY, self.cnt + 1);
-       }
-       if(fl & 2)
-       {
-               if(fl & 0x80)
-               {
-                       WriteCoord(MSG_ENTITY, self.enemy.origin_x);
-                       WriteCoord(MSG_ENTITY, self.enemy.origin_y);
-                       WriteCoord(MSG_ENTITY, self.enemy.origin_z);
-               }
-               else
-               {
-                       WriteAngle(MSG_ENTITY, self.mangle_x);
-                       WriteAngle(MSG_ENTITY, self.mangle_y);
-               }
-       }
-       if(fl & 4)
-               WriteByte(MSG_ENTITY, self.state);
-       return 1;
-}
-
-/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED
-Any object touching the beam will be hurt
-Keys:
-"target"
- spawnfunc_target_position where the laser ends
-"mdl"
- name of beam end effect to use
-"colormod"
- color of the beam (default: red)
-"dmg"
- damage per second (-1 for a laser that kills immediately)
-*/
-void laser_use()
-{
-       self.state = !self.state;
-       self.SendFlags |= 4;
-       misc_laser_aim();
-}
-
-void laser_reset()
-{
-       if(self.spawnflags & 1)
-               self.state = 1;
-       else
-               self.state = 0;
-}
-
-void spawnfunc_misc_laser()
-{
-       if(self.mdl)
-       {
-               if(self.mdl == "none")
-                       self.cnt = -1;
-               else
-               {
-                       self.cnt = particleeffectnum(self.mdl);
-                       if(self.cnt < 0)
-                               if(self.dmg)
-                                       self.cnt = particleeffectnum("laser_deadly");
-               }
-       }
-       else if(!self.cnt)
-       {
-               if(self.dmg)
-                       self.cnt = particleeffectnum("laser_deadly");
-               else
-                       self.cnt = -1;
-       }
-       if(self.cnt < 0)
-               self.cnt = -1;
-
-       if(self.colormod == '0 0 0')
-               if(!self.alpha)
-                       self.colormod = '1 0 0';
-       if(self.message == "")
-               self.message = "saw the light";
-       if (self.message2 == "")
-               self.message2 = "was pushed into a laser by";
-       if(!self.scale)
-               self.scale = 1;
-       if(!self.modelscale)
-               self.modelscale = 1;
-       else if(self.modelscale < 0)
-               self.modelscale = 0;
-       self.think = misc_laser_think;
-       self.nextthink = time;
-       InitializeEntity(self, misc_laser_init, INITPRIO_FINDTARGET);
-
-       self.mangle = self.angles;
-
-       Net_LinkEntity(self, FALSE, 0, laser_SendEntity);
-
-       IFTARGETED
-       {
-               self.reset = laser_reset;
-               laser_reset();
-               self.use = laser_use;
-       }
-       else
-               self.state = 1;
-}
-
-// tZorks trigger impulse / gravity
-.float radius;
-.float falloff;
-.float strength;
-.float lastpushtime;
-
-// targeted (directional) mode
-void trigger_impulse_touch1()
-{
-       entity targ;
-    float pushdeltatime;
-    float str;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-    targ = find(world, targetname, self.target);
-    if(!targ)
-    {
-        objerror("trigger_force without a (valid) .target!\n");
-        remove(self);
-        return;
-    }
-
-    str = min(self.radius, vlen(self.origin - other.origin));
-
-    if(self.falloff == 1)
-        str = (str / self.radius) * self.strength;
-    else if(self.falloff == 2)
-        str = (1 - (str / self.radius)) * self.strength;
-    else
-        str = self.strength;
-
-    pushdeltatime = time - other.lastpushtime;
-    if (pushdeltatime > 0.15) pushdeltatime = 0;
-    other.lastpushtime = time;
-    if(!pushdeltatime) return;
-
-    other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
-    other.flags &= ~FL_ONGROUND;
-    UpdateCSQCProjectile(other);
-}
-
-// Directionless (accelerator/decelerator) mode
-void trigger_impulse_touch2()
-{
-    float pushdeltatime;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-    pushdeltatime = time - other.lastpushtime;
-    if (pushdeltatime > 0.15) pushdeltatime = 0;
-    other.lastpushtime = time;
-    if(!pushdeltatime) return;
-
-    // div0: ticrate independent, 1 = identity (not 20)
-    other.velocity = other.velocity * pow(self.strength, pushdeltatime);
-    UpdateCSQCProjectile(other);
-}
-
-// Spherical (gravity/repulsor) mode
-void trigger_impulse_touch3()
-{
-    float pushdeltatime;
-    float str;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-    pushdeltatime = time - other.lastpushtime;
-    if (pushdeltatime > 0.15) pushdeltatime = 0;
-    other.lastpushtime = time;
-    if(!pushdeltatime) return;
-
-    setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
-
-       str = min(self.radius, vlen(self.origin - other.origin));
-
-    if(self.falloff == 1)
-        str = (1 - str / self.radius) * self.strength; // 1 in the inside
-    else if(self.falloff == 2)
-        str = (str / self.radius) * self.strength; // 0 in the inside
-    else
-        str = self.strength;
-
-    other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
-    UpdateCSQCProjectile(other);
-}
-
-/*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
--------- KEYS --------
-target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
-         If not, this trigger acts like a damper/accelerator field.
-
-strength : This is how mutch force to add in the direction of .target each second
-           when .target is set. If not, this is hoe mutch to slow down/accelerate
-           someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
-
-radius   : If set, act as a spherical device rather then a liniar one.
-
-falloff : 0 = none, 1 = liniar, 2 = inverted liniar
-
--------- NOTES --------
-Use a brush textured with common/origin in the trigger entity to determine the origin of the force
-in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
-*/
-
-void spawnfunc_trigger_impulse()
-{
-       self.active = ACTIVE_ACTIVE;
-
-       EXACTTRIGGER_INIT;
-    if(self.radius)
-    {
-        if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
-        setorigin(self, self.origin);
-        setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
-        self.touch = trigger_impulse_touch3;
-    }
-    else
-    {
-        if(self.target)
-        {
-            if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
-            self.touch = trigger_impulse_touch1;
-        }
-        else
-        {
-            if(!self.strength) self.strength = 0.9;
-                       self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
-            self.touch = trigger_impulse_touch2;
-        }
-    }
-}
-
-/*QUAKED spawnfunc_trigger_flipflop (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
-"Flip-flop" trigger gate... lets only every second trigger event through
-*/
-void flipflop_use()
-{
-       self.state = !self.state;
-       if(self.state)
-               SUB_UseTargets();
-}
-
-void spawnfunc_trigger_flipflop()
-{
-       if(self.spawnflags & 1)
-               self.state = 1;
-       self.use = flipflop_use;
-       self.reset = spawnfunc_trigger_flipflop; // perfect resetter
-}
-
-/*QUAKED spawnfunc_trigger_monoflop (.5 .5 .5) (-8 -8 -8) (8 8 8)
-"Mono-flop" trigger gate... turns one trigger event into one "on" and one "off" event, separated by a delay of "wait"
-*/
-void monoflop_use()
-{
-       self.nextthink = time + self.wait;
-       self.enemy = activator;
-       if(self.state)
-               return;
-       self.state = 1;
-       SUB_UseTargets();
-}
-void monoflop_fixed_use()
-{
-       if(self.state)
-               return;
-       self.nextthink = time + self.wait;
-       self.state = 1;
-       self.enemy = activator;
-       SUB_UseTargets();
-}
-
-void monoflop_think()
-{
-       self.state = 0;
-       activator = self.enemy;
-       SUB_UseTargets();
-}
-
-void monoflop_reset()
-{
-       self.state = 0;
-       self.nextthink = 0;
-}
-
-void spawnfunc_trigger_monoflop()
-{
-       if(!self.wait)
-               self.wait = 1;
-       if(self.spawnflags & 1)
-               self.use = monoflop_fixed_use;
-       else
-               self.use = monoflop_use;
-       self.think = monoflop_think;
-       self.state = 0;
-       self.reset = monoflop_reset;
-}
-
-void multivibrator_send()
-{
-       float newstate;
-       float cyclestart;
-
-       cyclestart = floor((time + self.phase) / (self.wait + self.respawntime)) * (self.wait + self.respawntime) - self.phase;
-
-       newstate = (time < cyclestart + self.wait);
-
-       activator = self;
-       if(self.state != newstate)
-               SUB_UseTargets();
-       self.state = newstate;
-
-       if(self.state)
-               self.nextthink = cyclestart + self.wait + 0.01;
-       else
-               self.nextthink = cyclestart + self.wait + self.respawntime + 0.01;
-}
-
-void multivibrator_toggle()
-{
-       if(self.nextthink == 0)
-       {
-               multivibrator_send();
-       }
-       else
-       {
-               if(self.state)
-               {
-                       SUB_UseTargets();
-                       self.state = 0;
-               }
-               self.nextthink = 0;
-       }
-}
-
-void multivibrator_reset()
-{
-       if(!(self.spawnflags & 1))
-               self.nextthink = 0; // wait for a trigger event
-       else
-               self.nextthink = max(1, time);
-}
-
-/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
-"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
--------- KEYS --------
-target: trigger all entities with this targetname when it goes off
-targetname: name that identifies this entity so it can be triggered; when off, it always uses the OFF state
-phase: offset of the timing
-wait: "on" cycle time (default: 1)
-respawntime: "off" cycle time (default: same as wait)
--------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (when targeted)
-*/
-void spawnfunc_trigger_multivibrator()
-{
-       if(!self.wait)
-               self.wait = 1;
-       if(!self.respawntime)
-               self.respawntime = self.wait;
-
-       self.state = 0;
-       self.use = multivibrator_toggle;
-       self.think = multivibrator_send;
-       self.nextthink = max(1, time);
-
-       IFTARGETED
-               multivibrator_reset();
-}
-
-
-void follow_init()
-{
-       entity src, dst;
-       src = world;
-       dst = world;
-       if(self.killtarget != "")
-               src = find(world, targetname, self.killtarget);
-       if(self.target != "")
-               dst = find(world, targetname, self.target);
-
-       if(!src && !dst)
-       {
-               objerror("follow: could not find target/killtarget");
-               return;
-       }
-
-       if(self.jointtype)
-       {
-               // already done :P entity must stay
-               self.aiment = src;
-               self.enemy = dst;
-       }
-       else if(!src || !dst)
-       {
-               objerror("follow: could not find target/killtarget");
-               return;
-       }
-       else if(self.spawnflags & 1)
-       {
-               // attach
-               if(self.spawnflags & 2)
-               {
-                       setattachment(dst, src, self.message);
-               }
-               else
-               {
-                       attach_sameorigin(dst, src, self.message);
-               }
-
-               dst.solid = SOLID_NOT; // solid doesn't work with attachment
-               remove(self);
-       }
-       else
-       {
-               if(self.spawnflags & 2)
-               {
-                       dst.movetype = MOVETYPE_FOLLOW;
-                       dst.aiment = src;
-                       // dst.punchangle = '0 0 0'; // keep unchanged
-                       dst.view_ofs = dst.origin;
-                       dst.v_angle = dst.angles;
-               }
-               else
-               {
-                       follow_sameorigin(dst, src);
-               }
-
-               remove(self);
-       }
-}
-
-void spawnfunc_misc_follow()
-{
-       InitializeEntity(self, follow_init, INITPRIO_FINDTARGET);
-}
-
-
-
-void gamestart_use() {
-       activator = self;
-       SUB_UseTargets();
-       remove(self);
-}
-
-void spawnfunc_trigger_gamestart() {
-       self.use = gamestart_use;
-       self.reset2 = spawnfunc_trigger_gamestart;
-
-       if(self.wait)
-       {
-               self.think = self.use;
-               self.nextthink = game_starttime + self.wait;
-       }
-       else
-               InitializeEntity(self, gamestart_use, INITPRIO_FINDTARGET);
-}
-
-
-
-
-.entity voicescript; // attached voice script
-.float voicescript_index; // index of next voice, or -1 to use the randomized ones
-.float voicescript_nextthink; // time to play next voice
-.float voicescript_voiceend; // time when this voice ends
-
-void target_voicescript_clear(entity pl)
-{
-       pl.voicescript = world;
-}
-
-void target_voicescript_use()
-{
-       if(activator.voicescript != self)
-       {
-               activator.voicescript = self;
-               activator.voicescript_index = 0;
-               activator.voicescript_nextthink = time + self.delay;
-       }
-}
-
-void target_voicescript_next(entity pl)
-{
-       entity vs;
-       float i, n, dt;
-
-       vs = pl.voicescript;
-       if(!vs)
-               return;
-       if(vs.message == "")
-               return;
-       if (!IS_PLAYER(pl))
-               return;
-       if(gameover)
-               return;
-
-       if(time >= pl.voicescript_voiceend)
-       {
-               if(time >= pl.voicescript_nextthink)
-               {
-                       // get the next voice...
-                       n = tokenize_console(vs.message);
-
-                       if(pl.voicescript_index < vs.cnt)
-                               i = pl.voicescript_index * 2;
-                       else if(n > vs.cnt * 2)
-                               i = ((pl.voicescript_index - vs.cnt) % ((n - vs.cnt * 2 - 1) / 2)) * 2 + vs.cnt * 2 + 1;
-                       else
-                               i = -1;
-
-                       if(i >= 0)
-                       {
-                               play2(pl, strcat(vs.netname, "/", argv(i), ".wav"));
-                               dt = stof(argv(i + 1));
-                               if(dt >= 0)
-                               {
-                                       pl.voicescript_voiceend = time + dt;
-                                       pl.voicescript_nextthink = pl.voicescript_voiceend + vs.wait * (0.5 + random());
-                               }
-                               else
-                               {
-                                       pl.voicescript_voiceend = time - dt;
-                                       pl.voicescript_nextthink = pl.voicescript_voiceend;
-                               }
-
-                               pl.voicescript_index += 1;
-                       }
-                       else
-                       {
-                               pl.voicescript = world; // stop trying then
-                       }
-               }
-       }
-}
-
-void spawnfunc_target_voicescript()
-{
-       // netname: directory of the sound files
-       // message: list of "sound file" duration "sound file" duration, a *, and again a list
-       //          foo1 4.1 foo2 4.0 foo3 -3.1 * fool1 1.1 fool2 7.1 fool3 9.1 fool4 3.7
-       //          Here, a - in front of the duration means that no delay is to be
-       //          added after this message
-       // wait: average time between messages
-       // delay: initial delay before the first message
-
-       float i, n;
-       self.use = target_voicescript_use;
-
-       n = tokenize_console(self.message);
-       self.cnt = n / 2;
-       for(i = 0; i+1 < n; i += 2)
-       {
-               if(argv(i) == "*")
-               {
-                       self.cnt = i / 2;
-                       ++i;
-               }
-               precache_sound(strcat(self.netname, "/", argv(i), ".wav"));
-       }
-}
-
-
-
-void trigger_relay_teamcheck_use()
-{
-       if(activator.team)
-       {
-               if(self.spawnflags & 2)
-               {
-                       if(activator.team != self.team)
-                               SUB_UseTargets();
-               }
-               else
-               {
-                       if(activator.team == self.team)
-                               SUB_UseTargets();
-               }
-       }
-       else
-       {
-               if(self.spawnflags & 1)
-                       SUB_UseTargets();
-       }
-}
-
-void trigger_relay_teamcheck_reset()
-{
-       self.team = self.team_saved;
-}
-
-void spawnfunc_trigger_relay_teamcheck()
-{
-       self.team_saved = self.team;
-       self.use = trigger_relay_teamcheck_use;
-       self.reset = trigger_relay_teamcheck_reset;
-}
-
-
-
-void trigger_disablerelay_use()
-{
-       entity e;
-
-       float a, b;
-       a = b = 0;
-
-       for(e = world; (e = find(e, targetname, self.target)); )
-       {
-               if(e.use == SUB_UseTargets)
-               {
-                       e.use = SUB_DontUseTargets;
-                       ++a;
-               }
-               else if(e.use == SUB_DontUseTargets)
-               {
-                       e.use = SUB_UseTargets;
-                       ++b;
-               }
-       }
-
-       if((!a) == (!b))
-               print("Invalid use of trigger_disablerelay: ", ftos(a), " relays were on, ", ftos(b), " relays were off!\n");
-}
-
-void spawnfunc_trigger_disablerelay()
-{
-       self.use = trigger_disablerelay_use;
-}
-
-float magicear_matched;
-float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
-string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
-{
-       float domatch, dotrigger, matchstart, l;
-       string s, msg;
-       entity oldself;
-       string savemessage;
-
-       magicear_matched = FALSE;
-
-       dotrigger = ((IS_PLAYER(source)) && (source.deadflag == DEAD_NO) && ((ear.radius == 0) || (vlen(source.origin - ear.origin) <= ear.radius)));
-       domatch = ((ear.spawnflags & 32) || dotrigger);
-
-       if (!domatch)
-               return msgin;
-
-       if (!msgin)
-       {
-               // we are in TUBA mode!
-               if (!(ear.spawnflags & 256))
-                       return msgin;
-
-               if(!W_Tuba_HasPlayed(source, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
-                       return msgin;
-
-               magicear_matched = TRUE;
-
-               if(dotrigger)
-               {
-                       oldself = self;
-                       activator = source;
-                       self = ear;
-                       savemessage = self.message;
-                       self.message = string_null;
-                       SUB_UseTargets();
-                       self.message = savemessage;
-                       self = oldself;
-               }
-
-               if(ear.netname != "")
-                       return ear.netname;
-
-               return msgin;
-       }
-
-       if(ear.spawnflags & 256) // ENOTUBA
-               return msgin;
-
-       if(privatesay)
-       {
-               if(ear.spawnflags & 4)
-                       return msgin;
-       }
-       else
-       {
-               if(!teamsay)
-                       if(ear.spawnflags & 1)
-                               return msgin;
-               if(teamsay > 0)
-                       if(ear.spawnflags & 2)
-                               return msgin;
-               if(teamsay < 0)
-                       if(ear.spawnflags & 8)
-                               return msgin;
-       }
-
-       matchstart = -1;
-       l = strlen(ear.message);
-
-       if(ear.spawnflags & 128)
-               msg = msgin;
-       else
-               msg = strdecolorize(msgin);
-
-       if(substring(ear.message, 0, 1) == "*")
-       {
-               if(substring(ear.message, -1, 1) == "*")
-               {
-                       // two wildcards
-                       // as we need multi-replacement here...
-                       s = substring(ear.message, 1, -2);
-                       l -= 2;
-                       if(strstrofs(msg, s, 0) >= 0)
-                               matchstart = -2; // we use strreplace on s
-               }
-               else
-               {
-                       // match at start
-                       s = substring(ear.message, 1, -1);
-                       l -= 1;
-                       if(substring(msg, -l, l) == s)
-                               matchstart = strlen(msg) - l;
-               }
-       }
-       else
-       {
-               if(substring(ear.message, -1, 1) == "*")
-               {
-                       // match at end
-                       s = substring(ear.message, 0, -2);
-                       l -= 1;
-                       if(substring(msg, 0, l) == s)
-                               matchstart = 0;
-               }
-               else
-               {
-                       // full match
-                       s = ear.message;
-                       if(msg == ear.message)
-                               matchstart = 0;
-               }
-       }
-
-       if(matchstart == -1) // no match
-               return msgin;
-
-       magicear_matched = TRUE;
-
-       if(dotrigger)
-       {
-               oldself = self;
-               activator = source;
-               self = ear;
-               savemessage = self.message;
-               self.message = string_null;
-               SUB_UseTargets();
-               self.message = savemessage;
-               self = oldself;
-       }
-
-       if(ear.spawnflags & 16)
-       {
-               return ear.netname;
-       }
-       else if(ear.netname != "")
-       {
-               if(matchstart < 0)
-                       return strreplace(s, ear.netname, msg);
-               else
-                       return strcat(
-                               substring(msg, 0, matchstart),
-                               ear.netname,
-                               substring(msg, matchstart + l, -1)
-                       );
-       }
-       else
-               return msgin;
-}
-
-entity magicears;
-string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin)
-{
-       entity ear;
-       string msgout;
-       for(ear = magicears; ear; ear = ear.enemy)
-       {
-               msgout = trigger_magicear_processmessage(ear, source, teamsay, privatesay, msgin);
-               if(!(ear.spawnflags & 64))
-               if(magicear_matched)
-                       return msgout;
-               msgin = msgout;
-       }
-       return msgin;
-}
-
-void spawnfunc_trigger_magicear()
-{
-       self.enemy = magicears;
-       magicears = self;
-
-       // actually handled in "say" processing
-       // spawnflags:
-       //    1 = ignore say
-       //    2 = ignore teamsay
-       //    4 = ignore tell
-       //    8 = ignore tell to unknown player
-       //   16 = let netname replace the whole message (otherwise, netname is a word replacement if set)
-       //   32 = perform the replacement even if outside the radius or dead
-       //   64 = continue replacing/triggering even if this one matched
-       //  128 = don't decolorize message before matching
-       //  256 = message is a tuba note sequence (pitch.duration pitch.duration ...)
-       //  512 = tuba notes must be exact right pitch, no transposing
-       // message: either
-       //   *pattern*
-       // or
-       //   *pattern
-       // or
-       //   pattern*
-       // or
-       //   pattern
-       // netname:
-       //   if set, replacement for the matched text
-       // radius:
-       //   "hearing distance"
-       // target:
-       //   what to trigger
-       // movedir:
-       //   for spawnflags 256, defines 'instrument+1 mintempo maxtempo' (zero component doesn't matter)
-
-       self.movedir_x -= 1; // map to tuba instrument numbers
-}
-
-void relay_activators_use()
-{
-       entity trg, os;
-
-       os = self;
-
-       for(trg = world; (trg = find(trg, targetname, os.target)); )
-       {
-               self = trg;
-               if (trg.setactive)
-                       trg.setactive(os.cnt);
-               else
-               {
-                       //bprint("Not using setactive\n");
-                       if(os.cnt == ACTIVE_TOGGLE)
-                               if(trg.active == ACTIVE_ACTIVE)
-                                       trg.active = ACTIVE_NOT;
-                               else
-                                       trg.active = ACTIVE_ACTIVE;
-                       else
-                               trg.active = os.cnt;
-               }
-       }
-       self = os;
-}
-
-void spawnfunc_relay_activate()
-{
-       self.cnt = ACTIVE_ACTIVE;
-       self.use = relay_activators_use;
-}
-
-void spawnfunc_relay_deactivate()
-{
-       self.cnt = ACTIVE_NOT;
-       self.use = relay_activators_use;
-}
-
-void spawnfunc_relay_activatetoggle()
-{
-       self.cnt = ACTIVE_TOGGLE;
-       self.use = relay_activators_use;
-}
-
-.string chmap, gametype;
-void spawnfunc_target_changelevel_use()
-{
-       if(self.gametype != "")
-               MapInfo_SwitchGameType(MapInfo_Type_FromString(self.gametype));
-
-       if (self.chmap == "")
-               localcmd("endmatch\n");
-       else
-               localcmd(strcat("changelevel ", self.chmap, "\n"));
-}
-
-void spawnfunc_target_changelevel()
-{
-       self.use = spawnfunc_target_changelevel_use;
-}
index 24ef1e935c8f51e09f40079b01fb687d4c3f8c9c..f0569291d8d70eff2348e8b1cbe4b8bc5305b738 100644 (file)
@@ -8,7 +8,9 @@
 /**
  * list of key names.
  */
+#ifdef SVQC
 string item_keys_names[ITEM_KEY_MAX];
+#endif
 
 /**
  * Use keys from p on l.
index eacebb5ecf13fe607b36883949fcd6875e550a30..fe21d088c19d9ed732922b513488ee8d2d1e77dd 100644 (file)
@@ -1562,7 +1562,6 @@ void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
 .float nottargeted;
 #define IFTARGETED if(!self.nottargeted && self.targetname != "")
 
-void() SUB_Remove;
 void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
 {
     vector mi, ma;
index f61d2609d0cb7fa0454632b42dff431f9e9e3865..073982116cf58cd74cd108b068432ce1c88725e5 100644 (file)
@@ -80,6 +80,8 @@ anticheat.qh
 cheats.qh
 ../common/playerstats.qh
 
+../common/triggers/include.qh
+
 portals.qh
 
 g_hook.qh // TODO
@@ -143,7 +145,6 @@ t_teleporters.qc
 
 sv_main.qc
 
-g_triggers.qc
 g_models.qc
 
 // singleplayer stuff
@@ -163,8 +164,6 @@ weapons/weaponsystem.qc
 ../common/weapons/config.qc
 ../common/weapons/weapons.qc // TODO
 
-../common/triggers/include.qh
-
 t_items.qc
 cl_impulse.qc
 
index 3fdd5eb1eb040e815a8e6edaa216b2b4d70510f3..bb4b65a2c46a4fe38e33e6552a39be2e2b26b3f2 100644 (file)
@@ -229,7 +229,6 @@ void turrets_precash()
 
 
 #ifdef TURRET_DEBUG
-void SUB_Remove();
 void marker_think()
 {
     if(self.cnt)