]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/t_plats.qc
Merge branch 'TimePath/experiments/csqc_prediction' into Mario/qc_physics
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / t_plats.qc
index 774255bae6135c16a42430884e1c623e505a3256..7b2bc9973eacc411b47d6b7c015163fd717b13a5 100644 (file)
@@ -1,3 +1,24 @@
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../dpdefs/progsdefs.qh"
+    #include "../dpdefs/dpextensions.qh"
+    #include "../warpzonelib/mathlib.qh"
+    #include "../warpzonelib/common.qh"
+    #include "../warpzonelib/util_server.qh"
+    #include "../common/constants.qh"
+    #include "../common/util.qh"
+    #include "../common/weapons/weapons.qh"
+    #include "constants.qh"
+    #include "defs.qh"
+    #include "../common/notifications.qh"
+    #include "../common/deathtypes.qh"
+    #include "command/common.qh"
+    #include "../csqcmodellib/sv_model.qh"
+#endif
+
+#ifdef SVQC
+
 .float dmgtime2;
 void generic_plat_blocked()
 {
@@ -37,24 +58,24 @@ void plat_spawn_inside_trigger()
 
        tmin = self.absmin + '25 25 0';
        tmax = self.absmax - '25 25 -8';
-       tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
+       tmin.z = tmax.z - (self.pos1_z - self.pos2_z + 8);
        if (self.spawnflags & PLAT_LOW_TRIGGER)
-               tmax_z = tmin_z + 8;
+               tmax.z = tmin.z + 8;
 
-       if (self.size_x <= 50)
+       if (self.size.x <= 50)
        {
-               tmin_x = (self.mins_x + self.maxs_x) / 2;
-               tmax_x = tmin_x + 1;
+               tmin.x = (self.mins.x + self.maxs.x) / 2;
+               tmax.x = tmin.x + 1;
        }
-       if (self.size_y <= 50)
+       if (self.size.y <= 50)
        {
-               tmin_y = (self.mins_y + self.maxs_y) / 2;
-               tmax_y = tmin_y + 1;
+               tmin.y = (self.mins.y + self.maxs.y) / 2;
+               tmax.y = tmin.y + 1;
        }
 
-       if(tmin_x < tmax_x)
-               if(tmin_y < tmax_y)
-                       if(tmin_z < tmax_z)
+       if(tmin.x < tmax.x)
+               if(tmin.y < tmax.y)
+                       if(tmin.z < tmax.z)
                        {
                                setsize (trigger, tmin, tmax);
                                return;
@@ -95,7 +116,7 @@ void plat_go_up()
 
 void plat_center_touch()
 {
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
 
        if (other.health <= 0)
@@ -110,7 +131,7 @@ void plat_center_touch()
 
 void plat_outside_touch()
 {
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
 
        if (other.health <= 0)
@@ -196,15 +217,15 @@ float set_platmovetype(entity e, string s)
 
        if(n > 2)
                if(argv(2) == "force")
-                       return TRUE; // no checking, return immediately
+                       return true; // no checking, return immediately
 
        if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end))
        {
                objerror("Invalid platform move type; platform would go in reverse, which is not allowed.");
-               return FALSE;
+               return false;
        }
 
-       return TRUE;
+       return true;
 }
 
 void spawnfunc_path_corner()
@@ -258,7 +279,7 @@ void spawnfunc_func_plat()
        self.angles = '0 0 0';
 
        self.classname = "plat";
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
        setsize (self, self.mins , self.maxs);
@@ -270,11 +291,11 @@ void spawnfunc_func_plat()
        if (!self.lip)
                self.lip = 16;
        if (!self.height)
-               self.height = self.size_z - self.lip;
+               self.height = self.size.z - self.lip;
 
        self.pos1 = self.origin;
        self.pos2 = self.origin;
-       self.pos2_z = self.origin_z - self.height;
+       self.pos2_z = self.origin.z - self.height;
 
        self.reset = plat_reset;
        plat_reset();
@@ -309,13 +330,13 @@ void train_wait()
                else // linear movement
                        ang = targ.origin - (self.origin - self.view_ofs); // use the origin of the next path_corner
                ang = vectoangles(ang);
-               ang_x = -ang_x; // flip up / down orientation
+               ang.x = -ang.x; // flip up / down orientation
 
                if(self.wait > 0) // slow turning
                        SUB_CalcAngleMove(ang, TSPEED_TIME, self.ltime - time + self.wait, train_wait);
                else // instant turning
                        SUB_CalcAngleMove(ang, TSPEED_TIME, 0.0000001, train_wait);
-               self.train_wait_turning = TRUE;
+               self.train_wait_turning = true;
                return;
        }
 
@@ -324,7 +345,7 @@ void train_wait()
 
        if(self.wait < 0 || self.train_wait_turning) // no waiting or we already waited while turning
        {
-               self.train_wait_turning = FALSE;
+               self.train_wait_turning = false;
                train_next();
        }
        else
@@ -414,18 +435,18 @@ void spawnfunc_func_train()
        if (!self.speed)
                self.speed = 100;
 
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+
        if (self.spawnflags & 2)
        {
-               self.platmovetype_turn = TRUE;
+               self.platmovetype_turn = true;
                self.view_ofs = '0 0 0'; // don't offset a rotating train, origin works differently now
        }
        else
                self.view_ofs = self.mins;
 
-       if not(InitMovingBrushTrigger())
-               return;
-       self.effects |= EF_LOWPRECISION;
-
        // wait for targets to spawn
        InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION);
 
@@ -448,9 +469,9 @@ void spawnfunc_func_train()
 
 void func_rotating_setactive(float astate)
 {
-       
+
        if (astate == ACTIVE_TOGGLE)
-       {               
+       {
                if(self.active == ACTIVE_ACTIVE)
                        self.active = ACTIVE_NOT;
                else
@@ -458,8 +479,8 @@ void func_rotating_setactive(float astate)
        }
        else
                self.active = astate;
-               
-       if(self.active  == ACTIVE_NOT)          
+
+       if(self.active  == ACTIVE_NOT)
                self.avelocity = '0 0 0';
        else
                self.avelocity = self.pos1;
@@ -480,10 +501,10 @@ void spawnfunc_func_rotating()
                precache_sound(self.noise);
                ambientsound(self.origin, self.noise, VOL_BASE, ATTEN_IDLE);
        }
-       
+
        self.active = ACTIVE_ACTIVE;
        self.setactive = func_rotating_setactive;
-       
+
        if (!self.speed)
                self.speed = 100;
        // FIXME: test if this turns the right way, then remove this comment (negate as needed)
@@ -495,9 +516,9 @@ void spawnfunc_func_rotating()
        // FIXME: test if this turns the right way, then remove this comment (negate as needed)
        else // Z
                self.avelocity = '0 1 0' * self.speed;
-       
+
        self.pos1 = self.avelocity;
-    
+
     if(self.dmg && (self.message == ""))
         self.message = " was squished";
     if(self.dmg && (self.message2 == ""))
@@ -509,7 +530,7 @@ void spawnfunc_func_rotating()
 
     self.dmgtime2 = time;
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        // no EF_LOWPRECISION here, as rounding angles is bad
 
@@ -527,16 +548,16 @@ void func_bobbing_controller_think()
 {
        vector v;
        self.nextthink = time + 0.1;
-       
-       if not (self.owner.active == ACTIVE_ACTIVE)
+
+       if(self.owner.active != ACTIVE_ACTIVE)
        {
-               self.owner.velocity = '0 0 0';          
+               self.owner.velocity = '0 0 0';
                return;
        }
-               
+
        // calculate sinewave using makevectors
        makevectors((self.nextthink * self.owner.cnt + self.owner.phase * 360) * '0 1 0');
-       v = self.owner.destvec + self.owner.movedir * v_forward_y;
+       v = self.owner.destvec + self.owner.movedir * v_forward.y;
        if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed
                // * 10 so it will arrive in 0.1 sec
                self.owner.velocity = (v - self.owner.origin) * 10;
@@ -588,7 +609,7 @@ void spawnfunc_func_bobbing()
        else // Z
                self.movedir = '0 0 1' * self.height;
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        // wait for targets to spawn
@@ -612,7 +633,7 @@ void func_pendulum_controller_think()
        float v;
        self.nextthink = time + 0.1;
 
-       if not (self.owner.active == ACTIVE_ACTIVE)
+       if (!(self.owner.active == ACTIVE_ACTIVE))
        {
                self.owner.avelocity_x = 0;
                return;
@@ -620,11 +641,11 @@ void func_pendulum_controller_think()
 
        // calculate sinewave using makevectors
        makevectors((self.nextthink * self.owner.freq + self.owner.phase) * '0 360 0');
-       v = self.owner.speed * v_forward_y + self.cnt;
+       v = self.owner.speed * v_forward.y + self.cnt;
        if(self.owner.classname == "func_pendulum") // don't brake stuff if the func_bobbing was killtarget'ed
        {
                // * 10 so it will arrive in 0.1 sec
-               self.owner.avelocity_z = (remainder(v - self.owner.angles_z, 360)) * 10;
+               self.owner.avelocity_z = (remainder(v - self.owner.angles.z, 360)) * 10;
        }
 }
 
@@ -656,17 +677,17 @@ void spawnfunc_func_pendulum()
        self.blocked = generic_plat_blocked;
 
        self.avelocity_z = 0.0000001;
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        if(!self.freq)
        {
                // find pendulum length (same formula as Q3A)
-               self.freq = 1 / (M_PI * 2) * sqrt(autocvar_sv_gravity / (3 * max(8, fabs(self.mins_z))));
+               self.freq = 1 / (M_PI * 2) * sqrt(autocvar_sv_gravity / (3 * max(8, fabs(self.mins.z))));
        }
 
        // copy initial angle
-       self.cnt = self.angles_z;
+       self.cnt = self.angles.z;
 
        // wait for targets to spawn
        controller = spawn();
@@ -745,7 +766,7 @@ void button_reset()
 
 void button_use()
 {
-       if not (self.active == ACTIVE_ACTIVE)
+       if(self.active != ACTIVE_ACTIVE)
                return;
 
        self.enemy = activator;
@@ -756,7 +777,7 @@ void button_touch()
 {
        if (!other)
                return;
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
        if(other.velocity * self.movedir < 0)
                return;
@@ -788,7 +809,7 @@ When a button is touched, it moves some distance in the direction of it's angle,
 "speed"                override the default 40 speed
 "wait"         override the default 1 second wait (-1 = never return)
 "lip"          override the default 4 pixel lip remaining at end of move
-"health"       if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the MinstaGib laser
+"health"       if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the InstaGib laser
 "sounds"
 0) steam metal
 1) wooden clunk
@@ -799,7 +820,7 @@ void spawnfunc_func_button()
 {
        SetMovedir ();
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
 
@@ -991,23 +1012,17 @@ ACTIVATION FUNCTIONS
 */
 
 float door_check_keys(void) {
-       local entity door;
-       
-       
-       if (self.owner)
-               door = self.owner;
-       else
-               door = self;
-       
+       entity door = self.owner ? self.owner : self;
+
        // no key needed
-       if not(door.itemkeys)
-               return TRUE;
+       if (!door.itemkeys)
+               return true;
 
        // this door require a key
        // only a player can have a key
-       if not(IS_PLAYER(other))
-               return FALSE;
-       
+       if (!IS_PLAYER(other))
+               return false;
+
        if (item_keys_usekey(door, other)) {
                // some keys were used
                if (other.key_door_messagetime <= time) {
@@ -1028,9 +1043,9 @@ float door_check_keys(void) {
                // door is now unlocked
                play2(other, "misc/talk.wav");
                Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
-               return TRUE;
+               return true;
        } else
-               return FALSE;
+               return false;
 }
 
 
@@ -1099,7 +1114,7 @@ void door_use()
        entity oself;
 
        //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
-       
+
        if (self.owner)
        {
                oself = self;
@@ -1113,16 +1128,16 @@ void door_use()
 void door_trigger_touch()
 {
        if (other.health < 1)
-               if not(other.iscreature && other.deadflag == DEAD_NO)
+               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;
@@ -1139,12 +1154,12 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
        self.health = self.health - damage;
-       
+
        if (self.itemkeys) {
                // don't allow opening doors through damage if keys are required
                return;
        }
-       
+
        if (self.health <= 0)
        {
                oself = self;
@@ -1166,7 +1181,7 @@ Prints messages
 */
 void door_touch()
 {
-       if not(IS_PLAYER(other))
+       if (!IS_PLAYER(other))
                return;
        if (self.owner.attack_finished_single > time)
                return;
@@ -1176,7 +1191,7 @@ void door_touch()
        if (!(self.owner.dmg) && (self.owner.message != ""))
        {
                if (IS_CLIENT(other))
-                       centerprint(other, self.message);
+                       centerprint(other, self.owner.message);
                play2(other, "misc/talk.wav");
        }
 }
@@ -1323,19 +1338,19 @@ 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;
-       return TRUE;
+       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;
+       return true;
 }
 
 /*
@@ -1394,18 +1409,18 @@ void LinkDoors()
                        self.targetname = t.targetname;
                if((t.message != "") && (self.message == ""))
                        self.message = t.message;
-               if (t.absmin_x < cmins_x)
-                       cmins_x = t.absmin_x;
-               if (t.absmin_y < cmins_y)
-                       cmins_y = t.absmin_y;
-               if (t.absmin_z < cmins_z)
-                       cmins_z = t.absmin_z;
-               if (t.absmax_x > cmaxs_x)
-                       cmaxs_x = t.absmax_x;
-               if (t.absmax_y > cmaxs_y)
-                       cmaxs_y = t.absmax_y;
-               if (t.absmax_z > cmaxs_z)
-                       cmaxs_z = t.absmax_z;
+               if (t.absmin.x < cmins.x)
+                       cmins.x = t.absmin.x;
+               if (t.absmin.y < cmins.y)
+                       cmins.y = t.absmin.y;
+               if (t.absmin.z < cmins.z)
+                       cmins.z = t.absmin.z;
+               if (t.absmax.x > cmaxs.x)
+                       cmaxs.x = t.absmax.x;
+               if (t.absmax.y > cmaxs.y)
+                       cmaxs.y = t.absmax.y;
+               if (t.absmax.z > cmaxs.z)
+                       cmaxs.z = t.absmax.z;
                if(t.enemy == self)
                        break;
        }
@@ -1480,8 +1495,8 @@ void door_reset()
 }
 
 // spawnflags require key (for now only func_door)
-#define SPAWNFLAGS_GOLD_KEY 8
-#define SPAWNFLAGS_SILVER_KEY 16
+const float SPAWNFLAGS_GOLD_KEY = 8;
+const float SPAWNFLAGS_SILVER_KEY = 16;
 void spawnfunc_func_door()
 {
        // Quake 1 keys compatibility
@@ -1489,13 +1504,13 @@ void spawnfunc_func_door()
                self.itemkeys |= ITEM_KEY_BIT(0);
        if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
                self.itemkeys |= ITEM_KEY_BIT(1);
-               
+
        //if (!self.deathtype) // map makers can override this
        //      self.deathtype = " got in the way";
        SetMovedir ();
 
        self.max_health = self.health;
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
        self.classname = "door";
@@ -1614,14 +1629,14 @@ void spawnfunc_func_door_rotating()
        else // Z
                self.movedir = '0 1 0';
 
-       if (self.angles_y==0) self.angles_y = 90;
+       if (self.angles.y ==0) self.angles_y = 90;
 
-       self.movedir = self.movedir * self.angles_y;
+       self.movedir = self.movedir * self.angles.y;
        self.angles = '0 0 0';
 
        self.max_health = self.health;
        self.avelocity = self.movedir;
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.velocity = '0 0 0';
        //self.effects |= EF_LOWPRECISION;
@@ -1708,7 +1723,7 @@ void fd_secret_use()
        string message_save;
 
        self.health = 10000;
-       self.bot_attack = TRUE;
+       self.bot_attack = true;
 
        // exit if still moving around...
        if (self.origin != self.oldorigin)
@@ -1839,7 +1854,7 @@ Prints messages
 */
 void secret_touch()
 {
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
        if (self.attack_finished_single > time)
                return;
@@ -1895,7 +1910,7 @@ void spawnfunc_func_door_secret()
        self.mangle = self.angles;
        self.angles = '0 0 0';
        self.classname = "door";
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
 
@@ -1940,9 +1955,9 @@ void func_fourier_controller_think()
        float n, i, t;
 
        self.nextthink = time + 0.1;
-       if not (self.owner.active == ACTIVE_ACTIVE)
+       if(self.owner.active != ACTIVE_ACTIVE)
        {
-               self.owner.velocity = '0 0 0';          
+               self.owner.velocity = '0 0 0';
                return;
        }
 
@@ -1955,7 +1970,7 @@ void func_fourier_controller_think()
        for(i = 0; i < n; ++i)
        {
                makevectors((t * stof(argv(i*5)) + stof(argv(i*5+1)) * 360) * '0 1 0');
-               v = v + ('1 0 0' * stof(argv(i*5+2)) + '0 1 0' * stof(argv(i*5+3)) + '0 0 1' * stof(argv(i*5+4))) * self.owner.height * v_forward_y;
+               v = v + ('1 0 0' * stof(argv(i*5+2)) + '0 1 0' * stof(argv(i*5+3)) + '0 0 1' * stof(argv(i*5+4))) * self.owner.height * v_forward.y;
        }
 
        if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed
@@ -1991,7 +2006,7 @@ void spawnfunc_func_fourier()
        if(self.netname == "")
                self.netname = "1 0 0 0 1";
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        self.active = ACTIVE_ACTIVE;
@@ -2073,9 +2088,9 @@ void func_vectormamamam_controller_think()
 {
        self.nextthink = time + 0.1;
 
-       if not (self.owner.active == ACTIVE_ACTIVE)
+       if(self.owner.active != ACTIVE_ACTIVE)
        {
-               self.owner.velocity = '0 0 0';          
+               self.owner.velocity = '0 0 0';
                return;
        }
 
@@ -2154,7 +2169,7 @@ void spawnfunc_func_vectormamamam()
        if(self.netname == "")
                self.netname = "1 0 0 0 1";
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        // wait for targets to spawn
@@ -2169,8 +2184,15 @@ void spawnfunc_func_vectormamamam()
        InitializeEntity(self, func_vectormamamam_findtarget, INITPRIO_FINDTARGET);
 }
 
+#endif
+
 void conveyor_think()
 {
+#ifdef CSQC
+       float dt = time - self.move_time;
+       self.move_time = time;
+       if(dt <= 0) { return; }
+#endif
        entity e;
 
        // set myself as current conveyor where possible
@@ -2181,7 +2203,11 @@ void conveyor_think()
        {
                for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
                        if(!e.conveyor.state)
+#ifdef SVQC
                                if(isPushable(e))
+#elif defined(CSQC)
+                               if(e.isplayermodel)
+#endif
                                {
                                        vector emin = e.absmin;
                                        vector emax = e.absmax;
@@ -2197,12 +2223,19 @@ void conveyor_think()
 
                for(e = world; (e = findentity(e, conveyor, self)); )
                {
+#ifdef SVQC
                        if(IS_CLIENT(e)) // doing it via velocity has quite some advantages
                                continue; // done in SV_PlayerPhysics
+#elif defined(CSQC)
+                       if(e.isplayermodel)
+                               continue;
+#endif
 
-                       setorigin(e, e.origin + self.movedir * sys_frametime);
+                       setorigin(e, e.origin + self.movedir * PHYS_INPUT_FRAMETIME);
                        move_out_of_solid(e);
+#ifdef SVQC
                        UpdateCSQCProjectile(e);
+#endif
                        /*
                        // stupid conveyor code
                        tracebox(e.origin, e.mins, e.maxs, e.origin + self.movedir * sys_frametime, MOVE_NORMAL, e);
@@ -2212,17 +2245,61 @@ void conveyor_think()
                }
        }
 
+#ifdef SVQC
        self.nextthink = time;
+#endif
 }
 
+#ifdef SVQC
+
 void conveyor_use()
 {
        self.state = !self.state;
+
+       self.SendFlags |= 2;
 }
 
 void conveyor_reset()
 {
        self.state = (self.spawnflags & 1);
+
+       self.SendFlags |= 2;
+}
+
+float conveyor_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & 1)
+       {
+               WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+               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);
+
+               WriteByte(MSG_ENTITY, self.speed);
+               WriteByte(MSG_ENTITY, self.state);
+
+               WriteString(MSG_ENTITY, self.targetname);
+               WriteString(MSG_ENTITY, self.target);
+       }
+
+       if(sf & 2)
+               WriteByte(MSG_ENTITY, self.state);
+
+       return true;
 }
 
 void conveyor_init()
@@ -2240,6 +2317,10 @@ void conveyor_init()
        }
        else
                self.state = 1;
+
+       Net_LinkEntity(self, 0, false, conveyor_send);
+
+       self.SendFlags |= 1;
 }
 
 void spawnfunc_trigger_conveyor()
@@ -2256,3 +2337,56 @@ void spawnfunc_func_conveyor()
        self.movetype = MOVETYPE_NONE;
        conveyor_init();
 }
+
+#elif defined(CSQC)
+
+void conveyor_init()
+{
+       self.draw = conveyor_think;
+       self.drawmask = MASK_NORMAL;
+
+       self.movetype = MOVETYPE_NONE;
+       self.model = "";
+       self.solid = SOLID_TRIGGER;
+       self.move_origin = self.origin;
+       self.move_time = time;
+}
+
+void ent_conveyor()
+{
+       float sf = ReadByte();
+
+       if(sf & 1)
+       {
+               self.warpzone_isboxy = 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.speed = ReadByte();
+               self.state = ReadByte();
+
+               self.targetname = strzone(ReadString());
+               self.target = strzone(ReadString());
+
+               conveyor_init();
+       }
+
+       if(sf & 2)
+               self.state = ReadByte();
+}
+
+#endif