]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
A few trillion lines of untested junk, committing now so it doesn't become quadrillions
authorMario <zacjardine@y7mail.com>
Thu, 19 Feb 2015 04:19:19 +0000 (15:19 +1100)
committerMario <zacjardine@y7mail.com>
Thu, 19 Feb 2015 04:19:19 +0000 (15:19 +1100)
37 files changed:
qcsrc/client/laser.qc [deleted file]
qcsrc/client/main.qc
qcsrc/client/movetypes.qc
qcsrc/client/movetypes.qh
qcsrc/client/particles.qc
qcsrc/client/particles.qh
qcsrc/client/progs.src
qcsrc/client/target_music.qc [deleted file]
qcsrc/client/target_music.qh [deleted file]
qcsrc/common/constants.qh
qcsrc/common/physics.qc
qcsrc/common/physics.qh
qcsrc/common/triggers/func/conveyor.qc
qcsrc/common/triggers/func/include.qh
qcsrc/common/triggers/func/plat.qc
qcsrc/common/triggers/func/pointparticles.qc
qcsrc/common/triggers/func/pointparticles.qh [new file with mode: 0644]
qcsrc/common/triggers/func/rainsnow.qc
qcsrc/common/triggers/func/rainsnow.qh [new file with mode: 0644]
qcsrc/common/triggers/func/stardust.qc
qcsrc/common/triggers/misc/corner.qc
qcsrc/common/triggers/misc/corner.qh [new file with mode: 0644]
qcsrc/common/triggers/misc/follow.qc
qcsrc/common/triggers/misc/include.qh
qcsrc/common/triggers/misc/laser.qc
qcsrc/common/triggers/misc/laser.qh [new file with mode: 0644]
qcsrc/common/triggers/platforms.qc
qcsrc/common/triggers/target/include.qh
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/target/music.qh
qcsrc/common/triggers/trigger/include.qc
qcsrc/common/triggers/trigger/include.qh
qcsrc/common/triggers/trigger/keylock.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/keylock.qh [new file with mode: 0644]
qcsrc/server/campaign.qc
qcsrc/server/g_damage.qc
qcsrc/server/item_key.qc

diff --git a/qcsrc/client/laser.qc b/qcsrc/client/laser.qc
deleted file mode 100644 (file)
index a74c668..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../common/buffs.qh"
-       #include "../csqcmodellib/interpolate.qh"
-       #include "main.qh"
-       #include "../csqcmodellib/cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
-
-// a laser goes from origin in direction angles
-// it has color 'colormod'
-// and stops when something is in the way
-.int cnt; // end effect
-.vector colormod;
-.int state; // on-off
-.int count; // flags for the laser
-.vector velocity;
-.float alpha;
-.float scale; // scaling factor of the thickness
-.float modelscale; // scaling factor of the dlight
-
-void Draw_Laser()
-{
-       if(!self.state)
-               return;
-       InterpolateOrigin_Do();
-       if(self.count & 0x80)
-       {
-               if(self.count & 0x10)
-               {
-                       trace_endpos = self.velocity;
-                       trace_dphitq3surfaceflags = 0;
-               }
-               else
-                       traceline(self.origin, self.velocity, 0, self);
-       }
-       else
-       {
-               if(self.count & 0x10)
-               {
-                       makevectors(self.angles);
-                       trace_endpos = self.origin + v_forward * 1048576;
-                       trace_dphitq3surfaceflags = Q3SURFACEFLAG_SKY;
-               }
-               else
-               {
-                       makevectors(self.angles);
-                       traceline(self.origin, self.origin + v_forward * 32768, 0, self);
-                       if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
-                               trace_endpos = self.origin + v_forward * 1048576;
-               }
-       }
-       if(self.scale != 0)
-       {
-               if(self.alpha)
-               {
-                       Draw_CylindricLine(self.origin, trace_endpos, self.scale, "particles/laserbeam", 0, time * 3, self.colormod, self.alpha, DRAWFLAG_NORMAL, view_origin);
-               }
-               else
-               {
-                       Draw_CylindricLine(self.origin, trace_endpos, self.scale, "particles/laserbeam", 0, time * 3, self.colormod, 0.5, DRAWFLAG_ADDITIVE, view_origin);
-               }
-       }
-       if (!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
-       {
-               if(self.cnt >= 0)
-                       pointparticles(self.cnt, trace_endpos, trace_plane_normal, drawframetime * 1000);
-               if(self.colormod != '0 0 0' && self.modelscale != 0)
-                       adddynamiclight(trace_endpos + trace_plane_normal * 1, self.modelscale, self.colormod * 5);
-       }
-}
-
-void Ent_Laser()
-{
-       InterpolateOrigin_Undo();
-
-       // 30 bytes, or 13 bytes for just moving
-       int f = ReadByte();
-       self.count = (f & 0xF0);
-
-       if(self.count & 0x80)
-               self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
-       else
-               self.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
-
-       if(f & 1)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-       }
-       if(f & 8)
-       {
-               self.colormod_x = ReadByte() / 255.0;
-               self.colormod_y = ReadByte() / 255.0;
-               self.colormod_z = ReadByte() / 255.0;
-               if(f & 0x40)
-                       self.alpha = ReadByte() / 255.0;
-               else
-                       self.alpha = 0;
-               self.scale = 2;
-               self.modelscale = 50;
-               if(f & 0x20)
-               {
-                       self.scale *= ReadByte() / 16.0; // beam radius
-                       self.modelscale *= ReadByte() / 16.0; // dlight radius
-               }
-               if((f & 0x80) || !(f & 0x10))
-                       self.cnt = ReadShort() - 1; // effect number
-               else
-                       self.cnt = 0;
-       }
-       if(f & 2)
-       {
-               if(f & 0x80)
-               {
-                       self.velocity_x = ReadCoord();
-                       self.velocity_y = ReadCoord();
-                       self.velocity_z = ReadCoord();
-               }
-               else
-               {
-                       self.angles_x = ReadAngle();
-                       self.angles_y = ReadAngle();
-               }
-       }
-       if(f & 4)
-               self.state = ReadByte();
-       InterpolateOrigin_Note();
-       self.draw = Draw_Laser;
-}
index 3903cb42716563c9020979a58f04f5a56c1098a1..afca059b16b08593169657151f2b2a3b08e3505e 100644 (file)
@@ -3,7 +3,6 @@
 #include "particles.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
-#include "target_music.qh"
 #include "tturrets.qh"
 #include "tuba.qh"
 #include "wall.qh"
@@ -854,6 +853,8 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_PLAT: ent_plat(); break;
                case ENT_CLIENT_PLAT_TRIGGER: ent_plat_trigger(); break;
                case ENT_CLIENT_SWAMP: ent_swamp(); break;
+               case ENT_CLIENT_CORNER: ent_corner(); break;
+               case ENT_CLIENT_KEYLOCK: ent_keylock(); break;
 
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
index 92fb64ab72196b7386720d648f7775463dc0c3e2..19a5d41e83ae68033677fe5204dea36e50275fb7 100644 (file)
@@ -24,7 +24,7 @@ void _Movetype_CheckVelocity() // SV_CheckVelocity
 float _Movetype_CheckWater(entity ent) // SV_CheckWater
 {
        vector point = ent.move_origin;
-       point.z += (ent.mins.z + 1);
+       point_z += (ent.mins_z + 1);
 
        int nativecontents = pointcontents(point);
 
@@ -44,11 +44,11 @@ float _Movetype_CheckWater(entity ent) // SV_CheckWater
        {
                ent.move_watertype = nativecontents;
                ent.move_waterlevel = 1;
-               point.y = (ent.origin.y + ((ent.mins.z + ent.maxs.y) * 0.5));
+               point_y = (ent.origin_y + ((ent.mins_z + ent.maxs_y) * 0.5));
                if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
                {
                        ent.move_waterlevel = 2;
-                       point.y = ent.origin.y + ent.view_ofs.y;
+                       point_y = ent.origin_y + ent.view_ofs_y;
                        if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
                                ent.move_waterlevel = 3;
                }
@@ -170,21 +170,21 @@ void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict
 
        if(self.move_flags & FL_ITEM)
        {
-               mi.x -= 15;
-               mi.y -= 15;
-               mi.z -= 1;
-               ma.x += 15;
-               ma.y += 15;
-               ma.z += 1;
+               mi_x -= 15;
+               mi_y -= 15;
+               mi_z -= 1;
+               ma_x += 15;
+               ma_y += 15;
+               ma_z += 1;
        }
        else
        {
-               mi.x -= 1;
-               mi.y -= 1;
-               mi.z -= 1;
-               ma.x += 1;
-               ma.y += 1;
-               ma.z += 1;
+               mi_x -= 1;
+               mi_y -= 1;
+               mi_z -= 1;
+               ma_x += 1;
+               ma_y += 1;
+               ma_z += 1;
        }
 
        self.absmin = mi;
@@ -242,9 +242,9 @@ vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVeloci
 {
        vel = vel - ((vel * norm) * norm) * f;
 
-       if(vel.x > -0.1 && vel.x < 0.1) vel.x = 0;
-       if(vel.y > -0.1 && vel.y < 0.1) vel.y = 0;
-       if(vel.z > -0.1 && vel.z < 0.1) vel.z = 0;
+       if(vel_x > -0.1 && vel_x < 0.1) vel_x = 0;
+       if(vel_y > -0.1 && vel_y < 0.1) vel_y = 0;
+       if(vel_z > -0.1 && vel_z < 0.1) vel_z = 0;
 
        return vel;
 }
@@ -284,12 +284,342 @@ float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
        return trace_fraction;
 }
 
-const float MAX_CLIP_PLANES = 5;
+
+.float ltime;
+.void() blocked;
+void _Movetype_VectorAngles_FLU(vector myangles)
+{
+       float angle, sr, sp, sy, cr, cp, cy;
+
+       angle = myangles_y * (M_PI*2 / 360);
+       sy = sin(angle);
+       cy = cos(angle);
+       angle = myangles_x * (M_PI*2 / 360);
+       sp = sin(angle);
+       cp = cos(angle);
+       if(v_forward)
+       {
+               v_forward_x = cp*cy;
+               v_forward_y = cp*sy;
+               v_forward_z = -sp;
+       }
+       if(v_right || v_up)
+       {
+               if(myangles_z)
+               {
+                       angle = myangles_z * (M_PI*2 / 360);
+                       sr = sin(angle);
+                       cr = cos(angle);
+                       if(v_right)
+                       {
+                               v_right_x = sr*sp*cy+cr*-sy;
+                               v_right_y = sr*sp*sy+cr*cy;
+                               v_right_z = sr*cp;
+                       }
+                       if(v_up)
+                       {
+                               v_up_x = cr*sp*cy+-sr*-sy;
+                               v_up_y = cr*sp*sy+-sr*cy;
+                               v_up_z = cr*cp;
+                       }
+               }
+               else
+               {
+                       if(v_right)
+                       {
+                               v_right_x = -sy;
+                               v_right_y = cy;
+                               v_right_z = 0;
+                       }
+                       if(v_up)
+                       {
+                               v_up_x = sp*cy;
+                               v_up_y = sp*sy;
+                               v_up_z = cp;
+                       }
+               }
+       }
+}
+
+void _Movetype_PushMove(float dt) // SV_PushMove
+{
+       float pushltime;
+       //int pusherowner;
+       //int i;
+       //int num_moved;
+       //int numcheckentities;
+       int savesolid;
+       bool rotated;
+       vector move1, moveangle;
+       vector a;
+       vector pushorig, pushang;
+       vector org;
+       vector move;
+       entity oldself;
+
+       if(!vlen(self.move_velocity) && !vlen(self.move_avelocity))
+       {
+               self.ltime += dt;
+               return;
+       }
+
+       switch(self.solid)
+       {
+       // LordHavoc: valid pusher types
+       case SOLID_BSP:
+       case SOLID_BBOX:
+       case SOLID_SLIDEBOX:
+       case SOLID_CORPSE: // LordHavoc: this would be weird...
+               break;
+       // LordHavoc: no collisions
+       case SOLID_NOT:
+       case SOLID_TRIGGER:
+               
+               self.move_origin = self.move_origin + self.move_velocity * dt;
+               self.move_angles_x -= 360.0 * floor(self.move_angles_x * (1.0 / 360.0));
+               self.move_angles_y -= 360.0 * floor(self.move_angles_y * (1.0 / 360.0));
+               self.move_angles_z -= 360.0 * floor(self.move_angles_z * (1.0 / 360.0));
+               self.ltime += dt;
+               _Movetype_LinkEdict(true);
+               return;
+       default:
+               printf("_Movetype_PushMove: entity %e with classname %s, unrecognized solid type %d\n", num_for_edict(self), self.classname, self.solid);
+               return;
+       }
+       if(!self.modelindex || self.model == "null")
+       {
+               printf("_Movetype_PushMove: entity %e with classname %s, unusable modelindex %f\n", num_for_edict(self), self.classname, self.modelindex);
+               return;
+       }
+       //pusherowner = self.owner;
+
+       rotated = (self.move_angles * self.move_avelocity) > 0;
+
+       move1 = self.move_velocity * dt;
+       moveangle = self.move_avelocity * dt;
+
+       a = -moveangle;
+
+       // sets v_forward, v_right and v_up
+       _Movetype_VectorAngles_FLU(a);
+
+       pushorig = self.move_origin;
+       pushang = self.move_angles;
+       pushltime = self.ltime;
+
+// move the pusher to its final position
+
+       self.move_origin = self.move_origin + self.move_velocity * dt;
+       self.move_angles = self.move_angles + self.move_avelocity * dt;
+       self.ltime += dt;
+       _Movetype_LinkEdict(true);
+
+       //pushermodel = SV_GetModelFromEdict(pusher);
+       //Matrix4x4_CreateFromQuakeEntity(&pusherfinalmatrix, PRVM_serveredictvector(pusher, origin)[0], PRVM_serveredictvector(pusher, origin)[1], PRVM_serveredictvector(pusher, origin)[2],
+         //PRVM_serveredictvector(pusher, angles)[0], PRVM_serveredictvector(pusher, angles)[1], PRVM_serveredictvector(pusher, angles)[2], 1);
+       //Matrix4x4_Invert_Simple(&pusherfinalimatrix, &pusherfinalmatrix);
+
+       savesolid = self.solid;
+
+// see if any solid entities are inside the final position
+       //num_moved = 0;
+
+       entity e;
+       if(self.move_movetype != MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
+       for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
+       {
+               if(e.owner == self)
+                       continue;
+
+               if(self.owner == e)
+                       continue;
+
+               //Con_Printf("%i %s ", PRVM_NUM_FOR_EDICT(check), PRVM_GetString(PRVM_serveredictstring(check, classname)));
+
+               // tell any MOVETYPE_STEP entity that it may need to check for water transitions
+               //check->priv.server->waterposition_forceupdate = true;
+
+               //int checkcontents = pointcontents(e.move_origin);
+
+               // if the entity is standing on the pusher, it will definitely be moved
+               // if the entity is not standing on the pusher, but is in the pusher's
+               // final position, move it
+               if(!(e.move_flags & FL_ONGROUND) || e.move_groundentity != self)
+               {
+                       //vector pushermins = self.mins;
+                       //vector pushermaxs = self.maxs;
+                       //vector checkorigin = e.origin;
+                       //vector checkmins = e.mins;
+                       //vector checkmaxs = e.maxs;
+                       //Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, 
+                               //&pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents, collision_extendmovelength.value);
+                       tracebox(e.move_origin, e.mins, e.maxs, self.move_origin, MOVE_NOMONSTERS, e);
+                       if(!trace_startsolid)
+                       {
+                               //Con_Printf("- not in solid\n");
+                               continue;
+                       }
+               }
+               vector pivot = e.mins + 0.5 * (e.maxs - e.mins);
+               //VectorClear(pivot);
+
+               if(rotated)
+               {
+                       vector org2;
+                       org = e.move_origin - self.move_origin;
+                       org += pivot;
+                       org2_x = (org * v_forward);
+                       org2_y = (org * v_right);
+                       org2_z = (org * v_up);
+                       move = org2 - org;
+                       move += move1;
+               }
+               else
+                       move = move1;
+
+               //Con_Printf("- pushing %f %f %f\n", move[0], move[1], move[2]);
+
+               //VectorCopy (PRVM_serveredictvector(check, origin), check->priv.server->moved_from);
+               //VectorCopy (PRVM_serveredictvector(check, angles), check->priv.server->moved_fromangles);
+               //moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check);
+
+               // physics objects need better collisions than this code can do
+               /*if(e.move_movetype == MOVETYPE_PHYSICS)
+               {
+                       e.move_origin += move;
+                       oldself = self;
+                       self = e;
+                       _Movetype_LinkEdict(false);
+                       _Movetype_LinkEdict_TouchAreaGrid();
+                       self = oldself;
+                       continue;
+               }*/
+
+               // try moving the contacted entity
+               self.solid = SOLID_NOT;
+               oldself = self;
+               self = e;
+               if(!_Movetype_PushEntity(move, true))
+               {
+                       // entity "check" got teleported
+                       self.angles_y += trace_fraction * moveangle_y;
+                       oldself.solid = savesolid;
+                       continue; // pushed enough
+               }
+               self = oldself;
+               // FIXME: turn players specially
+               e.angles_y += trace_fraction * moveangle_y;
+               self.solid = savesolid;
+               //Con_Printf("%s:%d frac %f startsolid %d bmodelstartsolid %d allsolid %d\n", __FILE__, __LINE__, trace.fraction, trace.startsolid, trace.bmodelstartsolid, trace.allsolid);
+
+               // this trace.fraction < 1 check causes items to fall off of pushers
+               // if they pass under or through a wall
+               // the groundentity check causes items to fall off of ledges
+               if(e.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || e.move_groundentity != self))
+                       e.move_flags &= ~FL_ONGROUND;
+
+               // if it is still inside the pusher, block
+               //vector pushermins = self.mins;
+               //vector pushermaxs = self.maxs;
+               //vector checkorigin = e.move_origin;
+               //vector checkmins = e.mins;
+               //vector checkmaxs = e.maxs; 
+               //Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, 
+                               //&pusherfinalmatrix, &pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents, collision_extendmovelength.value);
+               tracebox(e.move_origin, e.mins, e.maxs, self.move_origin, MOVE_NOMONSTERS, e);
+               if(trace_startsolid)
+               {
+                       /*vector move2;
+                       if(SV_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
+                       {
+                               // hack to invoke all necessary movement triggers
+                               move2 = '0 0 0';
+                               if(!_Movetype_PushEntity(move2, true))
+                               {
+                                       // entity "check" got teleported
+                                       continue;
+                               }
+                               // we could fix it
+                               continue;
+                       }*/
+
+                       // still inside pusher, so it's really blocked
+
+                       // fail the move
+                       if(e.mins_x == e.maxs_x)
+                               continue;
+                       if(e.solid == SOLID_NOT || e.solid == SOLID_TRIGGER)
+                       {
+                               // corpse
+                               e.mins_x = e.mins_y = 0;
+                               e.maxs = e.mins;
+                               continue;
+                       }
+
+                       self.move_origin = pushorig;
+                       self.move_angles = pushang;
+                       self.ltime = pushltime;
+                       _Movetype_LinkEdict(true);
+
+                       // move back any entities we already moved
+                       /*for (i = 0;i < num_moved;i++)
+                       {
+                               prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
+                               VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin));
+                               VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles));
+                               SV_LinkEdict(ed);
+                       }*/
+
+                       // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
+                       if(self.blocked)
+                       {
+                               self.move_time = time;
+                               other = e;
+                               self.blocked();
+                       }
+                       break;
+               }
+       }
+       self.move_angles_x -= 360.0 * floor(self.move_angles_x * (1.0 / 360.0));
+       self.move_angles_y -= 360.0 * floor(self.move_angles_y * (1.0 / 360.0));
+       self.move_angles_z -= 360.0 * floor(self.move_angles_z * (1.0 / 360.0));
+}
+
+void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher
+{
+       float oldltime, movetime;
+
+       oldltime = self.ltime;
+
+       if (self.nextthink < self.ltime + dt)
+       {
+               movetime = self.nextthink - self.ltime;
+               if (movetime < 0)
+                       movetime = 0;
+       }
+       else
+               movetime = dt;
+
+       if (movetime)
+               // advances PRVM_serveredictfloat(ent, ltime) if not blocked
+               _Movetype_PushMove(movetime);
+
+       if (self.nextthink > oldltime && self.nextthink <= self.ltime)
+       {
+               self.nextthink = 0;
+               //time = dt;
+               self.move_time = time;
+               other = world;
+               if(self.think)
+                       self.think();
+       }
+}
+
 void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
 {
        if(self.move_flags & FL_ONGROUND)
        {
-               if(self.move_velocity.z >= 1/32)
+               if(self.move_velocity_z >= 1/32)
                        self.move_flags &= ~FL_ONGROUND;
                else if(!self.move_groundentity)
                        return;
@@ -367,7 +697,7 @@ void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
                        self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
 
                        d = trace_plane_normal * self.move_velocity;
-                       if(trace_plane_normal.z > 0.7 && d < bouncestop && d > -bouncestop)
+                       if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)
                        {
                                self.move_flags |= FL_ONGROUND;
                                self.move_groundentity = trace_ent;
@@ -380,7 +710,7 @@ void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
                else
                {
                        self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
-                       if(trace_plane_normal.z > 0.7)
+                       if(trace_plane_normal_z > 0.7)
                        {
                                self.move_flags |= FL_ONGROUND;
                                self.move_groundentity = trace_ent;
@@ -422,7 +752,7 @@ void _Movetype_Physics_Frame(float movedt)
        {
                case MOVETYPE_PUSH:
                case MOVETYPE_FAKEPUSH:
-                       error("SV_Physics_Pusher not implemented");
+                       _Movetype_Physics_Pusher(movedt);
                        break;
                case MOVETYPE_NONE:
                        break;
index f209771460cbd1b22f079fc6668a2f7daed83678..b4dea1de12beaad58e19cbfebd7acc94ea740c34 100644 (file)
@@ -23,6 +23,10 @@ void Movetype_Physics_MatchTicrate(float tr, bool sloppy);
 void Movetype_Physics_MatchServer(bool sloppy);
 void Movetype_Physics_NoMatchServer();
 
+float _Movetype_UnstickEntity();
+
+const int MAX_CLIP_PLANES = 5;
+
 const int MOVETYPE_NONE                                = 0;
 const int MOVETYPE_ANGLENOCLIP     = 1;
 const int MOVETYPE_ANGLECLIP       = 2;
index 6d2ddf87d5a431b3cf4c901b60881d868fb0e25b..59b9b75f46c7b4c781f319c3ce1bbd801577ca7e 100644 (file)
@@ -1,218 +1,5 @@
 #include "particles.qh"
 
-void Draw_PointParticles()
-{
-       float n, i, fail;
-       vector p;
-       vector sz;
-       vector o;
-       o = self.origin;
-       sz = self.maxs - self.mins;
-       n = BGMScript(self);
-       if(self.absolute == 2)
-       {
-               if(n >= 0)
-                       n = self.just_toggled ? self.impulse : 0;
-               else
-                       n = self.impulse * drawframetime;
-       }
-       else
-       {
-               n *= self.impulse * drawframetime;
-               if(self.just_toggled)
-                       if(n < 1)
-                               n = 1;
-       }
-       if(n == 0)
-               return;
-       fail = 0;
-       for(i = random(); i <= n && fail <= 64*n; ++i)
-       {
-               p = o + self.mins;
-               p.x += random() * sz.x;
-               p.y += random() * sz.y;
-               p.z += random() * sz.z;
-               if(WarpZoneLib_BoxTouchesBrush(p, p, self, world))
-               {
-                       if(self.movedir != '0 0 0')
-                       {
-                               traceline(p, p + normalize(self.movedir) * 4096, 0, world);
-                               p = trace_endpos;
-                               pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count);
-                       }
-                       else
-                       {
-                               pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count);
-                       }
-                       if(self.noise != "")
-                       {
-                               setorigin(self, p);
-                               sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
-                       }
-                       self.just_toggled = 0;
-               }
-               else if(self.absolute)
-               {
-                       ++fail;
-                       --i;
-               }
-       }
-       setorigin(self, o);
-}
-
-void Ent_PointParticles_Remove()
-{
-       if(self.noise)
-               strunzone(self.noise);
-       self.noise = string_null;
-       if(self.bgmscript)
-               strunzone(self.bgmscript);
-       self.bgmscript = string_null;
-}
-
-void Ent_PointParticles()
-{
-       float i;
-       vector v;
-       int f = ReadByte();
-       if(f & 2)
-       {
-               i = ReadCoord(); // density (<0: point, >0: volume)
-               if(i && !self.impulse && self.cnt) // self.cnt check is so it only happens if the ent already existed
-                       self.just_toggled = 1;
-               self.impulse = i;
-       }
-       if(f & 4)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-       }
-       if(f & 1)
-       {
-               self.modelindex = ReadShort();
-               if(f & 0x80)
-               {
-                       if(self.modelindex)
-                       {
-                               self.mins_x = ReadCoord();
-                               self.mins_y = ReadCoord();
-                               self.mins_z = ReadCoord();
-                               self.maxs_x = ReadCoord();
-                               self.maxs_y = ReadCoord();
-                               self.maxs_z = ReadCoord();
-                       }
-                       else
-                       {
-                               self.mins    = '0 0 0';
-                               self.maxs_x = ReadCoord();
-                               self.maxs_y = ReadCoord();
-                               self.maxs_z = ReadCoord();
-                       }
-               }
-               else
-               {
-                       self.mins = self.maxs = '0 0 0';
-               }
-
-               self.cnt = ReadShort(); // effect number
-
-               if(f & 0x20)
-               {
-                       self.velocity = decompressShortVector(ReadShort());
-                       self.movedir = decompressShortVector(ReadShort());
-               }
-               else
-               {
-                       self.velocity = self.movedir = '0 0 0';
-               }
-               if(f & 0x40)
-               {
-                       self.waterlevel = ReadShort() / 16.0;
-                       self.count = ReadByte() / 16.0;
-               }
-               else
-               {
-                       self.waterlevel = 0;
-                       self.count = 1;
-               }
-               if(self.noise)
-                       strunzone(self.noise);
-               if(self.bgmscript)
-                       strunzone(self.bgmscript);
-               self.noise = strzone(ReadString());
-               if(self.noise != "")
-               {
-                       self.atten = ReadByte() / 64.0;
-                       self.volume = ReadByte() / 255.0;
-               }
-               self.bgmscript = strzone(ReadString());
-               if(self.bgmscript != "")
-               {
-                       self.bgmscriptattack = ReadByte() / 64.0;
-                       self.bgmscriptdecay = ReadByte() / 64.0;
-                       self.bgmscriptsustain = ReadByte() / 255.0;
-                       self.bgmscriptrelease = ReadByte() / 64.0;
-               }
-               BGMScript_InitEntity(self);
-       }
-
-       if(f & 2)
-       {
-               self.absolute = (self.impulse >= 0);
-               if(!self.absolute)
-               {
-                       v = self.maxs - self.mins;
-                       self.impulse *= -v.x * v.y * v.z / 262144; // relative: particles per 64^3 cube
-               }
-       }
-
-       if(f & 0x10)
-               self.absolute = 2;
-
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-       self.solid = SOLID_NOT;
-       self.draw = Draw_PointParticles;
-       self.entremove = Ent_PointParticles_Remove;
-}
-
-void Draw_Rain()
-{
-    te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
-}
-
-void Draw_Snow()
-{
-    te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
-}
-
-void Ent_RainOrSnow()
-{
-       self.impulse = ReadByte(); // Rain, Snow, or Whatever
-       self.origin_x = ReadCoord();
-       self.origin_y = ReadCoord();
-       self.origin_z = ReadCoord();
-       self.maxs_x = ReadCoord();
-       self.maxs_y = ReadCoord();
-       self.maxs_z = ReadCoord();
-       self.velocity = decompressShortVector(ReadShort());
-       self.count = ReadShort() * 10;
-       self.glow_color = ReadByte(); // color
-
-       self.mins    = -0.5 * self.maxs;
-       self.maxs    =  0.5 * self.maxs;
-       self.origin  = self.origin - self.mins;
-
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-       self.solid = SOLID_NOT;
-       if(self.impulse)
-               self.draw = Draw_Rain;
-       else
-               self.draw = Draw_Snow;
-}
-
 void Net_ReadVortexBeamParticle()
 {
        vector shotorg, endpos;
index 12c999ba2bec219d5fb0adb0089aa66a271bfec1..a70aef86d703752b3e42b98e393558c64e9e3fed 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef PARTICLES_H
 #define PARTICLES_H
-
 .int dphitcontentsmask;
 
 .int cnt; // effect number
 .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
 .vector movedir; // trace direction
 
-void Draw_PointParticles();
-
-void Ent_PointParticles_Remove();
-
-void Ent_PointParticles();
-
 .float glow_color; // palette index
 
-void Draw_Rain();
-
-void Draw_Snow();
-
-void Ent_RainOrSnow();
-
 void Net_ReadVortexBeamParticle();
 #endif
index bd6d82f806e7ad38a74808f12af71d4e14807e09..098fbbdd54ad30b3bc923bf1aa0924eed6c054ae 100644 (file)
@@ -13,7 +13,6 @@ gibs.qc
 hook.qc
 hud_config.qc
 hud.qc
-laser.qc
 main.qc
 mapvoting.qc
 miscfunctions.qc
@@ -27,7 +26,6 @@ rubble.qc
 scoreboard.qc
 shownames.qc
 sortlist.qc
-target_music.qc
 teamradar.qc
 tturrets.qc
 tuba.qc
diff --git a/qcsrc/client/target_music.qc b/qcsrc/client/target_music.qc
deleted file mode 100644 (file)
index 662a673..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-#include "target_music.qh"
-
-void TargetMusic_Advance()
-{
-       // run AFTER all the thinks!
-       entity best, e;
-       float vol, vol0;
-       best = music_default;
-       if(music_target && time < music_target.lifetime)
-               best = music_target;
-       if(music_trigger)
-               best = music_trigger;
-       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); ) if(e.noise)
-       {
-               vol0 = e.lastvol;
-               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
-               {
-                       vol0 = -1;
-               }
-               if(e == best)
-               {
-                       // increase volume
-                       if(e.fade_time > 0)
-                               e.state = bound(0, e.state + frametime / e.fade_time, 1);
-                       else
-                               e.state = 1;
-               }
-               else
-               {
-                       // decrease volume
-                       if(e.fade_rate > 0)
-                               e.state = bound(0, e.state - frametime / e.fade_rate, 1);
-                       else
-                               e.state = 0;
-               }
-               vol = e.state * e.volume * autocvar_bgmvolume;
-               if(vol != vol0)
-               {
-                       if(vol0 < 0)
-                               sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
-                       else
-                               sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
-                       e.lastvol = vol;
-               }
-       }
-       music_trigger = world;
-
-       if(best)
-               bgmtime = getsoundtime(best, CH_BGM_SINGLE);
-       else
-               bgmtime = gettime(GETTIME_CDTRACK);
-}
-
-void Net_TargetMusic()
-{
-       int id = ReadShort();
-       float vol = ReadByte() / 255.0;
-       float fai = ReadByte() / 16.0;
-       float fao = ReadByte() / 16.0;
-       float tim = ReadByte();
-       string noi = ReadString();
-
-       entity e;
-       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); )
-       {
-               if(e.count == id)
-                       break;
-       }
-       if(!e)
-       {
-               e = spawn();
-               e.enttype = ENT_CLIENT_TRIGGER_MUSIC;
-               e.count = id;
-       }
-       if(e.noise != noi)
-       {
-               if(e.noise)
-                       strunzone(e.noise);
-               e.noise = strzone(noi);
-               precache_sound(e.noise);
-               sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
-               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
-               {
-                       dprintf("Cannot initialize sound %s\n", e.noise);
-                       strunzone(e.noise);
-                       e.noise = string_null;
-               }
-       }
-       e.volume = vol;
-       e.fade_time = fai;
-       e.fade_rate = fao;
-       if(vol > 0)
-       {
-               if(tim == 0)
-               {
-                       music_default = e;
-                       if(!music_disabled)
-                       {
-                               e.state = 2;
-                               cvar_settemp("music_playlist_index", "-1"); // don't use playlists
-                               localcmd("cd stop\n"); // just in case
-                               music_disabled = 1;
-                       }
-               }
-               else
-               {
-                       music_target = e;
-                       e.lifetime = time + tim;
-               }
-       }
-}
-
-void Ent_TriggerMusic_Think()
-{
-       if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
-       {
-               music_trigger = self;
-       }
-       self.nextthink = time;
-}
-
-void Ent_TriggerMusic_Remove()
-{
-       if(self.noise)
-               strunzone(self.noise);
-       self.noise = string_null;
-}
-
-void Ent_ReadTriggerMusic()
-{
-       int f = ReadByte();
-       if(f & 4)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-       }
-       if(f & 1)
-       {
-               self.modelindex = ReadShort();
-               if(self.modelindex)
-               {
-                       self.mins_x = ReadCoord();
-                       self.mins_y = ReadCoord();
-                       self.mins_z = ReadCoord();
-                       self.maxs_x = ReadCoord();
-                       self.maxs_y = ReadCoord();
-                       self.maxs_z = ReadCoord();
-               }
-               else
-               {
-                       self.mins    = '0 0 0';
-                       self.maxs_x = ReadCoord();
-                       self.maxs_y = ReadCoord();
-                       self.maxs_z = ReadCoord();
-               }
-
-               self.volume = ReadByte() / 255.0;
-               self.fade_time = ReadByte() / 16.0;
-               self.fade_rate = ReadByte() / 16.0;
-               string s = self.noise;
-               if(self.noise)
-                       strunzone(self.noise);
-               self.noise = strzone(ReadString());
-               if(self.noise != s)
-               {
-                       precache_sound(self.noise);
-                       sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
-                       if(getsoundtime(self, CH_BGM_SINGLE) < 0)
-                       {
-                               dprintf("Cannot initialize sound %s\n", self.noise);
-                               strunzone(self.noise);
-                               self.noise = string_null;
-                       }
-               }
-       }
-
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-       self.cnt = 1;
-       self.think = Ent_TriggerMusic_Think;
-       self.nextthink = time;
-}
diff --git a/qcsrc/client/target_music.qh b/qcsrc/client/target_music.qh
deleted file mode 100644 (file)
index c685214..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef TARGET_MUSIC_H
-#define TARGET_MUSIC_H
-
-float music_disabled;
-entity music_default;
-entity music_target;
-entity music_trigger;
-// FIXME also control bgmvolume here, to not require a target_music for the default track.
-
-.int state;
-.float lastvol;
-
-void TargetMusic_Advance();
-
-void Net_TargetMusic();
-
-void Ent_TriggerMusic_Think();
-
-void Ent_TriggerMusic_Remove();
-
-void Ent_ReadTriggerMusic();
-#endif
index 7f594be060b7cf505cf8218aed37de88eab7e39c..47d153c67863a722912cef27e076d961c744b58f 100644 (file)
@@ -112,6 +112,8 @@ const int ENT_CLIENT_DOOR_TRIGGER = 66;
 const int ENT_CLIENT_PLAT = 67;
 const int ENT_CLIENT_PLAT_TRIGGER = 68;
 const int ENT_CLIENT_SWAMP = 69;
+const int ENT_CLIENT_CORNER = 70;
+const int ENT_CLIENT_KEYLOCK = 71;
 
 const int ENT_CLIENT_HEALING_ORB = 80;
 
index e77184750eeb1117d092a05769c22acb3c8e4ecc..730cfc40abc114596c3fe7ce0c4db29aca7783af 100644 (file)
@@ -4,6 +4,8 @@
 
 #ifdef SVQC
 
+#include "../server/miscfunctions.qh"
+
 void Physics_AddStats()
 {
        // g_movementspeed hack
@@ -117,7 +119,7 @@ void PM_ClientMovement_Unstick()
                tracebox(neworigin, PL_CROUCH_MIN, PL_CROUCH_MAX, neworigin, MOVE_NORMAL, self);
                if (!trace_startsolid)
                {
-                       self.origin = neworigin;
+                       setorigin(self, neworigin);
                        return;// true;
                }
        }
@@ -188,6 +190,106 @@ void PM_ClientMovement_UpdateStatus()
                pmove_waterjumptime = 0;
 }
 
+#ifdef CSQC
+.float t_fraction;
+.vector t_plane_normal;
+.float t_startsolid;
+.vector t_endpos;
+entity t_tracebox(vector thevec1, vector tmin, vector tmax, vector thevec2, float type, entity forentity)
+{
+       entity e = spawn();
+       tracebox(thevec1, tmin, tmax, thevec2, type, forentity);
+       e.t_fraction = trace_fraction;
+       e.t_plane_normal = trace_plane_normal;
+       e.t_startsolid = trace_startsolid;
+       e.t_endpos = trace_endpos;
+
+       return e;
+}
+#endif
+
+void PM_ClientMovement_Move()
+{
+#ifdef CSQC
+
+       int bump;
+       float t;
+       float f;
+       vector neworigin = '0 0 0';
+       vector currentorigin2 = '0 0 0';
+       vector neworigin2 = '0 0 0';
+       vector primalvelocity;
+       entity trace = world, trace2 = world, trace3 = world;
+       entity oldtrace = world;
+
+       PM_ClientMovement_UpdateStatus();
+       primalvelocity = self.velocity;
+       for (bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && dotproduct(self.velocity, self.velocity) > 0; bump++)
+       {
+               neworigin = self.velocity * t;
+               trace = t_tracebox(self.origin, self.mins, self.maxs, neworigin, MOVE_NORMAL, self);
+               if(trace.t_fraction < 1 && trace.t_plane_normal_z == 0)
+               {
+                       // may be a step or wall, try stepping up
+                       // first move forward at a higher level
+                       currentorigin2 = self.origin;
+                       currentorigin2_z += PHYS_STEPHEIGHT;
+                       neworigin2 = neworigin;
+                       neworigin_z = self.origin_z + PHYS_STEPHEIGHT;
+
+                       trace2 = t_tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+                       if(!trace2.t_startsolid)
+                       {
+                               // then move down from there
+                               currentorigin2 = trace2.t_endpos;
+                               neworigin2 = trace2.t_endpos;
+                               neworigin_z = self.origin_z;
+
+                               trace3 = t_tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+                               // accept the new trace if it made some progress
+                               if(fabs(trace3.t_endpos_x - trace.t_endpos_x) >= 0.03125 || fabs(trace3.t_endpos_y - trace.t_endpos_y) >= 0.03125)
+                               {
+                                       oldtrace = trace;
+                                       trace = trace2;
+                                       trace.t_endpos = trace3.t_endpos;
+                               }
+                               else if(oldtrace) // TODO: check if we even need this
+                               {
+                                       trace = oldtrace;
+                               }
+                       }
+               }
+
+               // check if it moved at all
+               if(trace.t_fraction >= 0.001)
+                       setorigin(self, trace.t_endpos);
+
+               // check if it moved all the way
+               if(trace.t_fraction == 1)
+                       break;
+
+               // this is only really needed for nogravityonground combined with gravityunaffectedbyticrate
+               // <LordHavoc> I'm pretty sure I commented it out solely because it seemed redundant
+               // this got commented out in a change that supposedly makes the code match QW better
+               // so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block
+               if(trace.t_plane_normal_z > 0.7)
+                       SET_ONGROUND(self);
+
+               t -= t * trace.t_fraction;
+
+               f = dotproduct(self.velocity, trace.t_plane_normal);
+               self.velocity = self.velocity + trace.t_plane_normal * -f;
+       }
+       if(pmove_waterjumptime > 0)
+               self.velocity = primalvelocity;
+
+       if(trace && !wasfreed(trace)) { remove(trace); }
+       if(trace2 && !wasfreed(trace2)) { remove(trace2); }
+       if(trace3 && !wasfreed(trace3)) { remove(trace3); }
+#endif
+}
+
+#if 0
 void PM_ClientMovement_Move()
 {
 #ifdef CSQC
@@ -238,7 +340,7 @@ void PM_ClientMovement_Move()
 
                // check if it moved at all
                if (trace_fraction >= 0.001)
-                       self.origin = trace_endpos;
+                       setorigin(self, trace_endpos);
 
                // check if it moved all the way
                if (trace_fraction == 1)
@@ -260,6 +362,7 @@ void PM_ClientMovement_Move()
                self.velocity = primalvelocity;
 #endif
 }
+#endif
 
 void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
 {
@@ -278,7 +381,7 @@ void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
 
        if (dot > 0) // we can't change direction while slowing down
        {
-               k *= pow(dot, PHYS_AIRCONTROL_POWER)*PHYS_INPUT_TIMELENGTH;
+               k *= pow(dot, PHYS_AIRCONTROL_POWER) * PHYS_INPUT_TIMELENGTH;
                xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY * sqrt(max(0, 1 - dot*dot)) * k/32);
                k *= PHYS_AIRCONTROL;
                self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
@@ -986,6 +1089,33 @@ void PM_check_frozen(void)
        }
 }
 
+void PM_check_hitground()
+{
+#ifdef SVQC
+       if (IS_ONGROUND(self))
+       if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
+       if (self.wasFlying)
+       {
+               self.wasFlying = 0;
+               if (self.waterlevel < WATERLEVEL_SWIMMING)
+               if (time >= self.ladder_time)
+               if (!self.hook)
+               {
+                       self.nextstep = time + 0.3 + random() * 0.1;
+                       trace_dphitq3surfaceflags = 0;
+                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
+                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
+                       {
+                               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+                                       GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+                               else
+                                       GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+                       }
+               }
+       }
+#endif
+}
+
 void PM_check_blocked(void)
 {
 #ifdef SVQC
@@ -999,12 +1129,11 @@ void PM_check_blocked(void)
 #ifdef SVQC
 float speedaward_lastsent;
 float speedaward_lastupdate;
-string GetMapname(void);
 #endif
 void PM_check_race(void)
 {
 #ifdef SVQC
-       if not(g_cts || g_race)
+       if(!(g_cts || g_race))
                return;
        if (vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed)
        {
@@ -1411,7 +1540,7 @@ void SV_WalkMove ()
 
                // try moving up and forward to go up a step
                // back to start pos
-               self.origin = start_origin;
+               setorigin(self, start_origin);
                self.velocity = start_velocity;
 
                // move up
@@ -1446,7 +1575,7 @@ void SV_WalkMove ()
                {
                        //Con_Printf("wall\n");
                        // stepping up didn't make any progress, revert to original move
-                       self.origin = originalmove_origin;
+                       setorigin(self, originalmove_origin);
                        self.velocity = originalmove_velocity;
                        self.flags = originalmove_flags;
                        self.groundentity = originalmove_groundentity;
@@ -1483,7 +1612,7 @@ void SV_WalkMove ()
                // if the push down didn't end up on good ground, use the move without
                // the step up.  This happens near wall / slope combinations, and can
                // cause the player to hop up higher on a slope too steep to climb
-               self.origin = originalmove_origin;
+               setorigin(self, originalmove_origin);
                self.velocity = originalmove_velocity;
                self.flags = originalmove_flags;
                self.groundentity = originalmove_groundentity;
@@ -1648,14 +1777,16 @@ void PM_air(float buttons_prev, float maxspd_mod)
 }
 
 // used for calculating airshots
-float PM_is_flying()
+bool IsFlying(entity a)
 {
-       if (IS_ONGROUND(self))
-               return 0;
-       if (self.waterlevel >= WATERLEVEL_SWIMMING)
-               return 0;
-       traceline(self.origin, self.origin - '0 0 48', MOVE_NORMAL, self);
-       return trace_fraction >= 1;
+       if(IS_ONGROUND(a))
+               return false;
+       if(a.waterlevel >= WATERLEVEL_SWIMMING)
+               return false;
+       traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
+       if(trace_fraction < 1)
+               return false;
+       return true;
 }
 
 void PM_Main()
@@ -1816,48 +1947,20 @@ void PM_Main()
        }
 #endif
 
-#ifdef SVQC
-       // if dead, behave differently
-       // in CSQC, physics don't handle dead player
-       if (self.deadflag)
+       if(PHYS_DEAD(self))
                goto end;
-#endif
 
 #ifdef SVQC
        if (!self.fixangle && !g_bugrigs)
                self.angles = '0 1 0' * PHYS_INPUT_ANGLES(self).y;
 #endif
 
-#ifdef SVQC
-       if (IS_ONGROUND(self))
-       if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
-       if (self.wasFlying)
-       {
-               self.wasFlying = 0;
-               if (self.waterlevel < WATERLEVEL_SWIMMING)
-               if (time >= self.ladder_time)
-               if (!self.hook)
-               {
-                       self.nextstep = time + 0.3 + random() * 0.1;
-                       trace_dphitq3surfaceflags = 0;
-                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
-                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
-                       {
-                               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
-                                       GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                               else
-                                       GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                       }
-               }
-       }
-#endif
+       PM_check_hitground();
 
-       if (PM_is_flying())
+       if(IsFlying(self))
                self.wasFlying = 1;
 
-#ifdef SVQC
        if (IS_PLAYER(self))
-#endif
                CheckPlayerJump();
 
        if (self.flags & /* FL_WATERJUMP */ 2048)
@@ -1888,13 +1991,11 @@ void PM_Main()
        else if (ITEMS(self) & IT_USING_JETPACK)
                PM_jetpack(maxspeed_mod);
 
+       else if (IS_ONGROUND(self))
+               PM_walk(buttons_prev, maxspeed_mod);
+
        else
-       {
-               if (IS_ONGROUND(self))
-                       PM_walk(buttons_prev, maxspeed_mod);
-               else
-                       PM_air(buttons_prev, maxspeed_mod);
-       }
+               PM_air(buttons_prev, maxspeed_mod);
 
 #ifdef SVQC
        if (!IS_OBSERVER(self))
@@ -1907,14 +2008,10 @@ void PM_Main()
                self.lastground = time;
 
        // conveyors: then break velocity again
-       if (self.conveyor.state)
+       if(self.conveyor.state)
                self.velocity += self.conveyor.movedir;
 
-#ifdef SVQC
-       self.lastflags = self.flags;
-#elif defined(CSQC)
-       self.lastflags = self.pmove_flags;
-#endif
+       self.lastflags = FLAGS(self);
 
        self.lastclassname = self.classname;
 }
@@ -1926,4 +2023,9 @@ void CSQC_ClientMovement_PlayerMove_Frame(void)
 #endif
 {
        PM_Main();
+
+#ifdef CSQC
+       pmove_org = self.origin;
+       pmove_vel = self.velocity;
+#endif
 }
index c256a9eb10aed7456c3f02307e74af036302dd10..c779d116c8a0a028a2f02aec0d07ac5f399462cb 100644 (file)
@@ -22,6 +22,8 @@
 .float() PlayerPhysplug;
 float AdjustAirAccelQW(float accelqw, float factor);
 
+bool IsFlying(entity a);
+
 #ifdef CSQC
 
        float PM_multijump_checkjump();
@@ -82,6 +84,8 @@ float AdjustAirAccelQW(float accelqw, float factor);
 
        #define ITEMS(s)                                                        getstati(STAT_ITEMS, 0, 24)
 
+       #define FLAGS(s)                                                        (s).pmove_flags
+
        #define PHYS_AMMO_FUEL(s)                                       getstati(STAT_FUEL)
 
        #define PHYS_FROZEN(s)                                          getstati(STAT_FROZEN)
@@ -200,6 +204,8 @@ float AdjustAirAccelQW(float accelqw, float factor);
 
        #define ITEMS(s)                                                        s.items
 
+       #define FLAGS(s)                                                        (s).flags
+
        #define PHYS_AMMO_FUEL(s)                                       s.ammo_fuel
 
        #define PHYS_FROZEN(s)                                          s.frozen
index 05f0fa09347e31734fb80b793681f0e1f9fc7c11..6ed01b0c59c91f7e47ee88f45b97b2d47e91de7a 100644 (file)
@@ -70,7 +70,7 @@ void conveyor_reset()
        self.SendFlags |= 2;
 }
 
-float conveyor_send(entity to, float sf)
+bool conveyor_send(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
        WriteByte(MSG_ENTITY, sf);
index cca6f91dfad8caa5785931a22e3d014407b3e254..e49a9671e9784008b67157395e99f75b13b55a8d 100644 (file)
@@ -5,5 +5,7 @@
 #include "door.qh"
 #include "ladder.qh"
 #include "plat.qh"
+#include "rainsnow.qh"
+#include "pointparticles.qh"
 
 #endif
index b55669831341a96176d28d1f4229d502a6dd6f88..ce4e3e2e4cb87a1bf051dae70796545f47228820 100644 (file)
@@ -147,11 +147,7 @@ void spawnfunc_func_plat()
 #elif defined(CSQC)
 void plat_draw()
 {
-       float dt = time - self.move_time;
-       self.move_time = time;
-       if(dt <= 0) { return; }
-
-       setorigin(self, self.origin + self.velocity * dt);
+       Movetype_Physics_NoMatchServer();
 }
 
 void ent_plat()
index 896bd796bb168ec7ccd52599c1861c9da0bd1395..773ce6a51c40c988f17551073ff26ae374428ad7 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef CSQC
+       #include "../../../client/particles.qh"
+#endif
+
 #ifdef SVQC
 // NOTE: also contains func_sparks
 
@@ -177,4 +181,182 @@ void spawnfunc_func_sparks()
 
        spawnfunc_func_pointparticles();
 }
+#elif defined(CSQC)
+
+void Draw_PointParticles()
+{
+       float n, i, fail;
+       vector p;
+       vector sz;
+       vector o;
+       o = self.origin;
+       sz = self.maxs - self.mins;
+       n = BGMScript(self);
+       if(self.absolute == 2)
+       {
+               if(n >= 0)
+                       n = self.just_toggled ? self.impulse : 0;
+               else
+                       n = self.impulse * drawframetime;
+       }
+       else
+       {
+               n *= self.impulse * drawframetime;
+               if(self.just_toggled)
+                       if(n < 1)
+                               n = 1;
+       }
+       if(n == 0)
+               return;
+       fail = 0;
+       for(i = random(); i <= n && fail <= 64*n; ++i)
+       {
+               p = o + self.mins;
+               p.x += random() * sz.x;
+               p.y += random() * sz.y;
+               p.z += random() * sz.z;
+               if(WarpZoneLib_BoxTouchesBrush(p, p, self, world))
+               {
+                       if(self.movedir != '0 0 0')
+                       {
+                               traceline(p, p + normalize(self.movedir) * 4096, 0, world);
+                               p = trace_endpos;
+                               pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count);
+                       }
+                       else
+                       {
+                               pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count);
+                       }
+                       if(self.noise != "")
+                       {
+                               setorigin(self, p);
+                               sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
+                       }
+                       self.just_toggled = 0;
+               }
+               else if(self.absolute)
+               {
+                       ++fail;
+                       --i;
+               }
+       }
+       setorigin(self, o);
+}
+
+void Ent_PointParticles_Remove()
+{
+       if(self.noise)
+               strunzone(self.noise);
+       self.noise = string_null;
+       if(self.bgmscript)
+               strunzone(self.bgmscript);
+       self.bgmscript = string_null;
+}
+
+void Ent_PointParticles()
+{
+       float i;
+       vector v;
+       int f = ReadByte();
+       if(f & 2)
+       {
+               i = ReadCoord(); // density (<0: point, >0: volume)
+               if(i && !self.impulse && self.cnt) // self.cnt check is so it only happens if the ent already existed
+                       self.just_toggled = 1;
+               self.impulse = i;
+       }
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       if(f & 1)
+       {
+               self.modelindex = ReadShort();
+               if(f & 0x80)
+               {
+                       if(self.modelindex)
+                       {
+                               self.mins_x = ReadCoord();
+                               self.mins_y = ReadCoord();
+                               self.mins_z = ReadCoord();
+                               self.maxs_x = ReadCoord();
+                               self.maxs_y = ReadCoord();
+                               self.maxs_z = ReadCoord();
+                       }
+                       else
+                       {
+                               self.mins    = '0 0 0';
+                               self.maxs_x = ReadCoord();
+                               self.maxs_y = ReadCoord();
+                               self.maxs_z = ReadCoord();
+                       }
+               }
+               else
+               {
+                       self.mins = self.maxs = '0 0 0';
+               }
+
+               self.cnt = ReadShort(); // effect number
+
+               if(f & 0x20)
+               {
+                       self.velocity = decompressShortVector(ReadShort());
+                       self.movedir = decompressShortVector(ReadShort());
+               }
+               else
+               {
+                       self.velocity = self.movedir = '0 0 0';
+               }
+               if(f & 0x40)
+               {
+                       self.waterlevel = ReadShort() / 16.0;
+                       self.count = ReadByte() / 16.0;
+               }
+               else
+               {
+                       self.waterlevel = 0;
+                       self.count = 1;
+               }
+               if(self.noise)
+                       strunzone(self.noise);
+               if(self.bgmscript)
+                       strunzone(self.bgmscript);
+               self.noise = strzone(ReadString());
+               if(self.noise != "")
+               {
+                       self.atten = ReadByte() / 64.0;
+                       self.volume = ReadByte() / 255.0;
+               }
+               self.bgmscript = strzone(ReadString());
+               if(self.bgmscript != "")
+               {
+                       self.bgmscriptattack = ReadByte() / 64.0;
+                       self.bgmscriptdecay = ReadByte() / 64.0;
+                       self.bgmscriptsustain = ReadByte() / 255.0;
+                       self.bgmscriptrelease = ReadByte() / 64.0;
+               }
+               BGMScript_InitEntity(self);
+       }
+
+       if(f & 2)
+       {
+               self.absolute = (self.impulse >= 0);
+               if(!self.absolute)
+               {
+                       v = self.maxs - self.mins;
+                       self.impulse *= -v.x * v.y * v.z / 262144; // relative: particles per 64^3 cube
+               }
+       }
+
+       if(f & 0x10)
+               self.absolute = 2;
+
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+       self.solid = SOLID_NOT;
+       self.draw = Draw_PointParticles;
+       self.entremove = Ent_PointParticles_Remove;
+}
 #endif
diff --git a/qcsrc/common/triggers/func/pointparticles.qh b/qcsrc/common/triggers/func/pointparticles.qh
new file mode 100644 (file)
index 0000000..d446e72
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef CSQC
+
+void Ent_PointParticles();
+
+#endif
\ No newline at end of file
index e86b1568249f2a11aaa4e3510bdb6ddfd3d83814..deb5ee58bfd94e3598ffad20c21444111e6dfe7b 100644 (file)
@@ -89,4 +89,40 @@ void spawnfunc_func_snow()
 
        Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
 }
+#elif defined(CSQC)
+void Draw_Rain()
+{
+    te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
+}
+
+void Draw_Snow()
+{
+    te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
+}
+
+void Ent_RainOrSnow()
+{
+       self.impulse = ReadByte(); // Rain, Snow, or Whatever
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+       self.maxs_x = ReadCoord();
+       self.maxs_y = ReadCoord();
+       self.maxs_z = ReadCoord();
+       self.velocity = decompressShortVector(ReadShort());
+       self.count = ReadShort() * 10;
+       self.glow_color = ReadByte(); // color
+
+       self.mins    = -0.5 * self.maxs;
+       self.maxs    =  0.5 * self.maxs;
+       self.origin  = self.origin - self.mins;
+
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+       self.solid = SOLID_NOT;
+       if(self.impulse)
+               self.draw = Draw_Rain;
+       else
+               self.draw = Draw_Snow;
+}
 #endif
diff --git a/qcsrc/common/triggers/func/rainsnow.qh b/qcsrc/common/triggers/func/rainsnow.qh
new file mode 100644 (file)
index 0000000..5d8d923
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void Ent_RainOrSnow();
+#endif
index e8043fea78c2bcab36e33f78a88554d9b1dd003e..30c406f61e46d94f10640757ab691d351128ff2f 100644 (file)
@@ -2,5 +2,7 @@
 void spawnfunc_func_stardust()
 {
        self.effects = EF_STARDUST;
+
+       CSQCMODEL_AUTOINIT();
 }
 #endif
index 82fe6bbaf3d2c976e9783b841ceeb61dcc538d6a..5b2d8fcff9199a9a8cb400aacba0c6281b056047 100644 (file)
@@ -1,9 +1,78 @@
 #ifdef SVQC
+bool corner_send(entity to, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_CORNER);
+
+       WriteString(MSG_ENTITY, self.platmovetype);
+
+       WriteCoord(MSG_ENTITY, self.origin_x);
+       WriteCoord(MSG_ENTITY, self.origin_y);
+       WriteCoord(MSG_ENTITY, self.origin_z);
+
+       WriteString(MSG_ENTITY, self.target);
+       WriteString(MSG_ENTITY, self.target2);
+       WriteString(MSG_ENTITY, self.target3);
+       WriteString(MSG_ENTITY, self.target4);
+       WriteString(MSG_ENTITY, self.targetname);
+
+       return true;
+}
+
+void corner_link()
+{
+       Net_LinkEntity(self, false, 0, corner_send);
+}
+
 void spawnfunc_path_corner()
 {
+       corner_link();
+
        // setup values for overriding train movement
        // if a second value does not exist, both start and end speeds are the single value specified
-       if(!set_platmovetype(self, self.platmovetype))
-               return;
+       set_platmovetype(self, self.platmovetype);
+}
+#elif defined(CSQC)
+
+void corner_remove()
+{
+       if(self.target) { strunzone(self.target); }
+       self.target = string_null;
+
+       if(self.target2) { strunzone(self.target2); }
+       self.target2 = string_null;
+
+       if(self.target3) { strunzone(self.target3); }
+       self.target3 = string_null;
+
+       if(self.target4) { strunzone(self.target4); }
+       self.target4 = string_null;
+
+       if(self.targetname) { strunzone(self.targetname); }
+       self.targetname = string_null;
+
+       if(self.platmovetype) { strunzone(self.platmovetype); }
+       self.targetname = string_null;
+}
+
+void ent_corner()
+{
+       self.platmovetype = strzone(ReadString());
+
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+
+       self.target = strzone(ReadString());
+       self.target2 = strzone(ReadString());
+       self.target3 = strzone(ReadString());
+       self.target4 = strzone(ReadString());
+       self.targetname = strzone(ReadString());
+
+       self.classname = "path_corner";
+       self.drawmask = MASK_NORMAL;
+       self.entremove = corner_remove;
+
+       set_platmovetype(self, self.platmovetype);
 }
+
 #endif
diff --git a/qcsrc/common/triggers/misc/corner.qh b/qcsrc/common/triggers/misc/corner.qh
new file mode 100644 (file)
index 0000000..62b3aae
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void ent_corner();
+#endif
index aace4531ede9fe229b7b7bd817ba91018e17b442..bfeb865c1df47187ecd458688c297af5da7a3a28 100644 (file)
@@ -1,3 +1,5 @@
+// the way this entity works makes it no use to CSQC, as it removes itself instantly
+
 #ifdef SVQC
 void follow_init()
 {
index 6f43e2a89b0d99883e86ca2fa4d84c8f2351d9d2..71b2205211a9b2e2f7e8faa31df5d870e7829641 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef TRIGGERS_MISC_INCLUDE_H
 #define TRIGGERS_MISC_INCLUDE_H
 
-// nothing yet
+#include "corner.qh"
+#include "laser.qh"
 
 #endif
index 2aaf399f562e38457b049cc899faeccfc51f0a75..c67eb3207eb37c528f7e09a08273cfb332ca9601 100644 (file)
@@ -1,3 +1,13 @@
+#if defined(CSQC)
+       #include "../../../dpdefs/csprogsdefs.qh"
+       #include "../../buffs.qh"
+       #include "../../../csqcmodellib/interpolate.qh"
+       #include "../../../client/main.qh"
+       #include "../../../csqcmodellib/cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+#endif
+
 #ifdef SVQC
 .float modelscale;
 void misc_laser_aim()
@@ -254,4 +264,129 @@ void spawnfunc_misc_laser()
        else
                self.state = 1;
 }
+#elif defined(CSQC)
+
+// a laser goes from origin in direction angles
+// it has color 'colormod'
+// and stops when something is in the way
+.int cnt; // end effect
+.vector colormod;
+.int state; // on-off
+.int count; // flags for the laser
+.vector velocity;
+.float alpha;
+.float scale; // scaling factor of the thickness
+.float modelscale; // scaling factor of the dlight
+
+void Draw_Laser()
+{
+       if(!self.state)
+               return;
+       InterpolateOrigin_Do();
+       if(self.count & 0x80)
+       {
+               if(self.count & 0x10)
+               {
+                       trace_endpos = self.velocity;
+                       trace_dphitq3surfaceflags = 0;
+               }
+               else
+                       traceline(self.origin, self.velocity, 0, self);
+       }
+       else
+       {
+               if(self.count & 0x10)
+               {
+                       makevectors(self.angles);
+                       trace_endpos = self.origin + v_forward * 1048576;
+                       trace_dphitq3surfaceflags = Q3SURFACEFLAG_SKY;
+               }
+               else
+               {
+                       makevectors(self.angles);
+                       traceline(self.origin, self.origin + v_forward * 32768, 0, self);
+                       if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+                               trace_endpos = self.origin + v_forward * 1048576;
+               }
+       }
+       if(self.scale != 0)
+       {
+               if(self.alpha)
+               {
+                       Draw_CylindricLine(self.origin, trace_endpos, self.scale, "particles/laserbeam", 0, time * 3, self.colormod, self.alpha, DRAWFLAG_NORMAL, view_origin);
+               }
+               else
+               {
+                       Draw_CylindricLine(self.origin, trace_endpos, self.scale, "particles/laserbeam", 0, time * 3, self.colormod, 0.5, DRAWFLAG_ADDITIVE, view_origin);
+               }
+       }
+       if (!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
+       {
+               if(self.cnt >= 0)
+                       pointparticles(self.cnt, trace_endpos, trace_plane_normal, drawframetime * 1000);
+               if(self.colormod != '0 0 0' && self.modelscale != 0)
+                       adddynamiclight(trace_endpos + trace_plane_normal * 1, self.modelscale, self.colormod * 5);
+       }
+}
+
+void Ent_Laser()
+{
+       InterpolateOrigin_Undo();
+
+       // 30 bytes, or 13 bytes for just moving
+       int f = ReadByte();
+       self.count = (f & 0xF0);
+
+       if(self.count & 0x80)
+               self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
+       else
+               self.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
+
+       if(f & 1)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
+       }
+       if(f & 8)
+       {
+               self.colormod_x = ReadByte() / 255.0;
+               self.colormod_y = ReadByte() / 255.0;
+               self.colormod_z = ReadByte() / 255.0;
+               if(f & 0x40)
+                       self.alpha = ReadByte() / 255.0;
+               else
+                       self.alpha = 0;
+               self.scale = 2;
+               self.modelscale = 50;
+               if(f & 0x20)
+               {
+                       self.scale *= ReadByte() / 16.0; // beam radius
+                       self.modelscale *= ReadByte() / 16.0; // dlight radius
+               }
+               if((f & 0x80) || !(f & 0x10))
+                       self.cnt = ReadShort() - 1; // effect number
+               else
+                       self.cnt = 0;
+       }
+       if(f & 2)
+       {
+               if(f & 0x80)
+               {
+                       self.velocity_x = ReadCoord();
+                       self.velocity_y = ReadCoord();
+                       self.velocity_z = ReadCoord();
+               }
+               else
+               {
+                       self.angles_x = ReadAngle();
+                       self.angles_y = ReadAngle();
+               }
+       }
+       if(f & 4)
+               self.state = ReadByte();
+       InterpolateOrigin_Note();
+       self.draw = Draw_Laser;
+}
 #endif
diff --git a/qcsrc/common/triggers/misc/laser.qh b/qcsrc/common/triggers/misc/laser.qh
new file mode 100644 (file)
index 0000000..a77c4c5
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void Ent_Laser();
+#endif
index 0176fe9b02e3cdae931e510850b89729592f0738..c5f50c46e027bad43b35b515129f405421c8453e 100644 (file)
@@ -236,14 +236,12 @@ void plat_reset()
 #endif
 }
 
-#ifdef SVQC
 .float platmovetype_start_default, platmovetype_end_default;
-float set_platmovetype(entity e, string s)
+bool set_platmovetype(entity e, string s)
 {
        // sets platmovetype_start and platmovetype_end based on a string consisting of two values
 
-       float n;
-       n = tokenize_console(s);
+       int n = tokenize_console(s);
        if(n > 0)
                e.platmovetype_start = stof(argv(0));
        else
@@ -266,4 +264,3 @@ float set_platmovetype(entity e, string s)
 
        return true;
 }
-#endif
index cadbf3746c442f08b09a7443673edba8a445e2dd..4e44b9762b901a762436b82ba5f507ebb840cfb4 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef TRIGGERS_TARGET_INCLUDE_H
 #define TRIGGERS_TARGET_INCLUDE_H
 
-// nothing yet
+#include "music.qh"
 
 #endif
index fb38dad0ba7d380411843092201d9ac3f62b4434..136288bdc555dd4c6f20e60bb47c1de9846780de 100644 (file)
@@ -143,4 +143,188 @@ void spawnfunc_trigger_music()
 
        Net_LinkEntity(self, false, 0, trigger_music_SendEntity);
 }
+#elif defined(CSQC)
+
+void TargetMusic_Advance()
+{
+       // run AFTER all the thinks!
+       entity best, e;
+       float vol, vol0;
+       best = music_default;
+       if(music_target && time < music_target.lifetime)
+               best = music_target;
+       if(music_trigger)
+               best = music_trigger;
+       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); ) if(e.noise)
+       {
+               vol0 = e.lastvol;
+               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
+               {
+                       vol0 = -1;
+               }
+               if(e == best)
+               {
+                       // increase volume
+                       if(e.fade_time > 0)
+                               e.state = bound(0, e.state + frametime / e.fade_time, 1);
+                       else
+                               e.state = 1;
+               }
+               else
+               {
+                       // decrease volume
+                       if(e.fade_rate > 0)
+                               e.state = bound(0, e.state - frametime / e.fade_rate, 1);
+                       else
+                               e.state = 0;
+               }
+               vol = e.state * e.volume * autocvar_bgmvolume;
+               if(vol != vol0)
+               {
+                       if(vol0 < 0)
+                               sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
+                       else
+                               sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+                       e.lastvol = vol;
+               }
+       }
+       music_trigger = world;
+
+       if(best)
+               bgmtime = getsoundtime(best, CH_BGM_SINGLE);
+       else
+               bgmtime = gettime(GETTIME_CDTRACK);
+}
+
+void Net_TargetMusic()
+{
+       int id = ReadShort();
+       float vol = ReadByte() / 255.0;
+       float fai = ReadByte() / 16.0;
+       float fao = ReadByte() / 16.0;
+       float tim = ReadByte();
+       string noi = ReadString();
+
+       entity e;
+       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); )
+       {
+               if(e.count == id)
+                       break;
+       }
+       if(!e)
+       {
+               e = spawn();
+               e.enttype = ENT_CLIENT_TRIGGER_MUSIC;
+               e.count = id;
+       }
+       if(e.noise != noi)
+       {
+               if(e.noise)
+                       strunzone(e.noise);
+               e.noise = strzone(noi);
+               precache_sound(e.noise);
+               sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
+               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
+               {
+                       dprintf("Cannot initialize sound %s\n", e.noise);
+                       strunzone(e.noise);
+                       e.noise = string_null;
+               }
+       }
+       e.volume = vol;
+       e.fade_time = fai;
+       e.fade_rate = fao;
+       if(vol > 0)
+       {
+               if(tim == 0)
+               {
+                       music_default = e;
+                       if(!music_disabled)
+                       {
+                               e.state = 2;
+                               cvar_settemp("music_playlist_index", "-1"); // don't use playlists
+                               localcmd("cd stop\n"); // just in case
+                               music_disabled = 1;
+                       }
+               }
+               else
+               {
+                       music_target = e;
+                       e.lifetime = time + tim;
+               }
+       }
+}
+
+void Ent_TriggerMusic_Think()
+{
+       if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
+       {
+               music_trigger = self;
+       }
+       self.nextthink = time;
+}
+
+void Ent_TriggerMusic_Remove()
+{
+       if(self.noise)
+               strunzone(self.noise);
+       self.noise = string_null;
+}
+
+void Ent_ReadTriggerMusic()
+{
+       int f = ReadByte();
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       if(f & 1)
+       {
+               self.modelindex = ReadShort();
+               if(self.modelindex)
+               {
+                       self.mins_x = ReadCoord();
+                       self.mins_y = ReadCoord();
+                       self.mins_z = ReadCoord();
+                       self.maxs_x = ReadCoord();
+                       self.maxs_y = ReadCoord();
+                       self.maxs_z = ReadCoord();
+               }
+               else
+               {
+                       self.mins    = '0 0 0';
+                       self.maxs_x = ReadCoord();
+                       self.maxs_y = ReadCoord();
+                       self.maxs_z = ReadCoord();
+               }
+
+               self.volume = ReadByte() / 255.0;
+               self.fade_time = ReadByte() / 16.0;
+               self.fade_rate = ReadByte() / 16.0;
+               string s = self.noise;
+               if(self.noise)
+                       strunzone(self.noise);
+               self.noise = strzone(ReadString());
+               if(self.noise != s)
+               {
+                       precache_sound(self.noise);
+                       sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
+                       if(getsoundtime(self, CH_BGM_SINGLE) < 0)
+                       {
+                               dprintf("Cannot initialize sound %s\n", self.noise);
+                               strunzone(self.noise);
+                               self.noise = string_null;
+                       }
+               }
+       }
+
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+       self.cnt = 1;
+       self.think = Ent_TriggerMusic_Think;
+       self.nextthink = time;
+}
+
 #endif
index 400e4b8e53f89807879af67d4710647ef31e0041..8d014c819c288145c076484bd3e185feaf6cac42 100644 (file)
@@ -3,4 +3,25 @@
 
 .float lifetime;
 
+#ifdef CSQC
+float music_disabled;
+entity music_default;
+entity music_target;
+entity music_trigger;
+// FIXME also control bgmvolume here, to not require a target_music for the default track.
+
+.int state;
+.float lastvol;
+
+void TargetMusic_Advance();
+
+void Net_TargetMusic();
+
+void Ent_TriggerMusic_Think();
+
+void Ent_TriggerMusic_Remove();
+
+void Ent_ReadTriggerMusic();
+#endif
+
 #endif
index a71de8990a2c28caaa95e50d4d51b0c31ea4ff83..2a92f7349306e896e3052bb0ea3b332a271dd30d 100644 (file)
@@ -10,6 +10,7 @@
 #include "hurt.qc"
 #include "impulse.qc"
 #include "jumppads.qc"
+#include "keylock.qc"
 #include "magicear.qc"
 #include "monoflop.qc"
 #include "multi.qc"
index 6f4825b13dc62fffd885e0926781b562c08b07bf..5c862b950f31ed217571b8292d52d18e9c1ec27c 100644 (file)
@@ -5,5 +5,6 @@
 #include "jumppads.qh"
 #include "secret.qh"
 #include "swamp.qh"
+#include "keylock.qh"
 
 #endif
diff --git a/qcsrc/common/triggers/trigger/keylock.qc b/qcsrc/common/triggers/trigger/keylock.qc
new file mode 100644 (file)
index 0000000..729b83a
--- /dev/null
@@ -0,0 +1,256 @@
+/**
+ * trigger given targets
+ */
+void trigger_keylock_trigger(string s)
+{
+       entity stemp = self;
+       entity otemp = other;
+       entity atemp = activator;
+
+       entity t;
+       for(t = world; (t = find(t, targetname, s)); )
+               if(t.use)
+               {
+                       self = t;
+                       other = stemp;
+                       activator = atemp;
+                       self.use();
+               }
+
+       self = stemp;
+       other = otemp;
+       activator = atemp;
+}
+
+/**
+ * kill killtarget of trigger keylock.
+ */
+void trigger_keylock_kill(string s)
+{
+       entity t;
+       for(t = world; (t = find(t, targetname, s)); )
+               remove(t);
+}
+
+void trigger_keylock_touch()
+{
+       bool key_used = false;
+       bool started_delay = false;
+
+       // only player may trigger the lock
+       if(!IS_PLAYER(other))
+               return;
+
+       // check silver key
+       if(self.itemkeys)
+               key_used = item_keys_usekey(self, other);
+
+       activator = other;
+
+       if(self.itemkeys)
+       {
+#ifdef SVQC
+               // at least one of the keys is missing
+               if(key_used)
+               {
+                       // one or more keys were given, but others are still missing!
+                       play2(other, self.noise1);
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(self.itemkeys));
+                       other.key_door_messagetime = time + 2;
+               }
+               else if(other.key_door_messagetime <= time)
+               {
+                       // no keys were given
+                       play2(other, self.noise2);
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(self.itemkeys));
+                       other.key_door_messagetime = time + 2;
+               }
+#endif
+
+               // trigger target2
+               if(self.delay <= time || started_delay == true)
+               if(self.target2)
+               {
+                       trigger_keylock_trigger(self.target2);
+                       started_delay = true;
+                       self.delay = time + self.wait;
+               }
+       }
+       else
+       {
+#ifdef SVQC
+               // all keys were given!
+               play2(other, self.noise);
+               centerprint(other, self.message);
+#endif
+
+               if(self.target)
+                       trigger_keylock_trigger(self.target);
+
+               if(self.killtarget)
+                       trigger_keylock_kill(self.killtarget);
+
+               remove(self);
+       }
+
+}
+
+#ifdef SVQC
+bool trigger_keylock_send(entity to, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_KEYLOCK);
+
+       WriteString(MSG_ENTITY, self.target);
+       WriteString(MSG_ENTITY, self.target2);
+       WriteString(MSG_ENTITY, self.target3);
+       WriteString(MSG_ENTITY, self.target4);
+       WriteString(MSG_ENTITY, self.killtarget);
+       WriteString(MSG_ENTITY, self.targetname);
+
+       WriteInt24_t(MSG_ENTITY, self.itemkeys);
+       WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+       WriteByte(MSG_ENTITY, self.height);
+       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);
+
+       return true;
+}
+
+void trigger_keylock_link()
+{
+       // uncomment to network keylocks
+       //Net_LinkEntity(self, false, 0, trigger_keylock_send);
+}
+
+/*QUAKED trigger_keylock (.0 .5 .8) ?
+Keylock trigger.  Must target other entities.
+This trigger will trigger target entities when all required keys are provided.
+-------- KEYS --------
+itemkeys: A bit field with key IDs that are needed to open this lock.
+sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default)
+target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
+target2: trigger all entities with this targetname when triggered without giving it all the required keys.
+killtarget: remove all entities with this targetname when triggered with all the needed keys.
+message: print this message to the player who activated the trigger when all needed keys have been given.
+message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
+noise: sound to play when lock gets unlocked (default: see sounds)
+noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav)
+noise2: sound to play when a key is missing (default: misc/talk.wav)
+wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
+---------NOTES----------
+If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
+message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
+*/
+void spawnfunc_trigger_keylock(void)
+{
+       if(!self.itemkeys) { remove(self); return; }
+
+       // set unlocked message
+       if(self.message == "")
+               self.message = "Unlocked!";
+
+       // set default unlock noise
+       if(self.noise == "")
+       {
+               if(self.sounds == 1)
+                       self.noise = "misc/secret.wav";
+               else if(self.sounds == 2)
+                       self.noise = "misc/talk.wav";
+               else //if (self.sounds == 3) {
+                       self.noise = "misc/trigger1.wav";
+       }
+
+       // set default use key sound
+       if(self.noise1 == "")
+               self.noise1 = "misc/decreasevalue.wav";
+
+       // set closed sourd
+       if(self.noise2 == "")
+               self.noise2 = "misc/talk.wav";
+
+       // delay between triggering message2 and trigger2
+       if(!self.wait) { self.wait = 5; }
+
+       // precache sounds
+       precache_sound(self.noise);
+       precache_sound(self.noise1);
+       precache_sound(self.noise2);
+
+       EXACTTRIGGER_INIT;
+
+       self.touch = trigger_keylock_touch;
+
+       trigger_keylock_link();
+}
+#elif defined(CSQC)
+void keylock_remove()
+{
+       if(self.target) { strunzone(self.target); }
+       self.target = string_null;
+
+       if(self.target2) { strunzone(self.target2); }
+       self.target2 = string_null;
+
+       if(self.target3) { strunzone(self.target3); }
+       self.target3 = string_null;
+
+       if(self.target4) { strunzone(self.target4); }
+       self.target4 = string_null;
+
+       if(self.killtarget) { strunzone(self.killtarget); }
+       self.killtarget = string_null;
+
+       if(self.targetname) { strunzone(self.targetname); }
+       self.targetname = string_null;
+}
+
+void ent_keylock()
+{
+       self.target = strzone(ReadString());
+       self.target2 = strzone(ReadString());
+       self.target3 = strzone(ReadString());
+       self.target4 = strzone(ReadString());
+       self.killtarget = strzone(ReadString());
+       self.targetname = strzone(ReadString());
+
+       self.itemkeys = ReadInt24_t();
+       self.warpzone_isboxy = ReadByte();
+       self.height = ReadByte();
+       self.scale = ReadByte();
+
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+
+       self.mins_x = ReadCoord();
+       self.mins_y = ReadCoord();
+       self.mins_z = ReadCoord();
+       self.maxs_x = ReadCoord();
+       self.maxs_y = ReadCoord();
+       self.maxs_z = ReadCoord();
+
+       self.movedir_x = ReadCoord();
+       self.movedir_y = ReadCoord();
+       self.movedir_z = ReadCoord();
+
+       self.classname = "trigger_keylock";
+       self.drawmask = MASK_NORMAL;
+       self.draw = trigger_draw_generic;
+       self.trigger_touch = trigger_keylock_touch;
+       self.entremove = keylock_remove;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/keylock.qh b/qcsrc/common/triggers/trigger/keylock.qh
new file mode 100644 (file)
index 0000000..b21145d
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef CSQC
+void ent_keylock();
+bool item_keys_usekey(entity l, entity p)
+{
+       float valid = l.itemkeys & p.itemkeys;
+
+       if (!valid) {
+               // other has none of the needed keys
+               return false;
+       } else if (l.itemkeys == valid) {
+               // ALL needed keys were given
+               l.itemkeys = 0;
+               return true;
+       } else {
+               // only some of the needed keys were given
+               l.itemkeys &= ~valid;
+               return true;
+       }
+}
+#endif
index 2c091d56e15f19bed4cda5890861ef29fae33db2..650855989edebccc0ee31cf1aba8984b6a634b2f 100644 (file)
@@ -121,7 +121,6 @@ void CampaignPreInit()
        strunzone(title);
 }
 
-string GetMapname();
 void CampaignPostInit()
 {
        // now some sanity checks
index d170cf4c020db0b7e229777a858fb5c55afb6825..cb62b61aade688b22925030684f7a7ccafc7c72c 100644 (file)
@@ -66,18 +66,6 @@ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad
        Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity);
 }
 
-float IsFlying(entity a)
-{
-       if(a.flags & FL_ONGROUND)
-               return 0;
-       if(a.waterlevel >= WATERLEVEL_SWIMMING)
-               return 0;
-       traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
-       if(trace_fraction < 1)
-               return 0;
-       return 1;
-}
-
 void UpdateFrags(entity player, float f)
 {
        PlayerTeamScore_AddScore(player, f);
index 85159e49cf27699396c425a28b6e236bae332e43..a130b826c2ce46f3a918e637b56d50bd780a350a 100644 (file)
@@ -21,7 +21,8 @@ TODO:
 - should keys have a trigger?
 */
 
-bool item_keys_usekey(entity l, entity p) {
+bool item_keys_usekey(entity l, entity p)
+{
        float valid = l.itemkeys & p.itemkeys;
 
        if (!valid) {
@@ -282,154 +283,3 @@ void spawnfunc_item_key2(void) {
        self.itemkeys = ITEM_KEY_BIT(0);
        spawnfunc_item_key();
 };
-
-
-/*
-================================
-trigger_keylock
-================================
-*/
-
-/**
- * trigger givent targets
- */
-void trigger_keylock_trigger(string s) {
-       entity stemp = self;
-       entity otemp = other;
-       entity atemp = activator;
-
-       entity t;
-       for(t = world; (t = find(t, targetname, s)); )
-               if (t.use) {
-                       self = t;
-                       other = stemp;
-                       activator = atemp;
-                       self.use();
-               }
-
-       self = stemp;
-       other = otemp;
-       activator = atemp;
-};
-
-/**
- * kill killtarget of trigger keylock.
- */
-void trigger_keylock_kill(string s) {
-       entity t;
-       for(t = world; (t = find(t, targetname, s)); )
-               remove(t);
-};
-
-void trigger_keylock_touch(void) {
-       bool key_used = false;
-       bool started_delay = false;
-
-       // only player may trigger the lock
-       if (!IS_PLAYER(other))
-               return;
-
-
-       // check silver key
-       if (self.itemkeys)
-               key_used = item_keys_usekey(self, other);
-
-       activator = other;
-
-       if (self.itemkeys) {
-               // at least one of the keys is missing
-               if (key_used) {
-                       // one or more keys were given, but others are still missing!
-                       play2(other, self.noise1);
-                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(self.itemkeys));
-                       other.key_door_messagetime = time + 2;
-               } else if (other.key_door_messagetime <= time) {
-                       // no keys were given
-                       play2(other, self.noise2);
-                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(self.itemkeys));
-                       other.key_door_messagetime = time + 2;
-               }
-
-               // trigger target2
-               if (self.delay <= time || started_delay == true)
-               if (self.target2) {
-                       trigger_keylock_trigger(self.target2);
-                       started_delay = true;
-                       self.delay = time + self.wait;
-               }
-       } else {
-               // all keys were given!
-               play2(other, self.noise);
-               centerprint(other, self.message);
-
-               if (self.target)
-                       trigger_keylock_trigger(self.target);
-
-               if (self.killtarget)
-                       trigger_keylock_kill(self.killtarget);
-
-               remove(self);
-       }
-
-};
-
-/*QUAKED trigger_keylock (.0 .5 .8) ?
-Keylock trigger.  Must target other entities.
-This trigger will trigger target entities when all required keys are provided.
--------- KEYS --------
-itemkeys: A bit field with key IDs that are needed to open this lock.
-sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default)
-target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
-target2: trigger all entities with this targetname when triggered without giving it all the required keys.
-killtarget: remove all entities with this targetname when triggered with all the needed keys.
-message: print this message to the player who activated the trigger when all needed keys have been given.
-message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
-noise: sound to play when lock gets unlocked (default: see sounds)
-noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav)
-noise2: sound to play when a key is missing (default: misc/talk.wav)
-wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
----------NOTES----------
-If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
-message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
-*/
-void spawnfunc_trigger_keylock(void) {
-       if (!self.itemkeys) {
-               remove(self);
-               return;
-       }
-
-       // set unlocked message
-       if (self.message == "")
-               self.message = "Unlocked!";
-
-       // set default unlock noise
-       if (self.noise == "") {
-               if (self.sounds == 1)
-                       self.noise = "misc/secret.wav";
-               else if (self.sounds == 2)
-                       self.noise = "misc/talk.wav";
-               else //if (self.sounds == 3) {
-                       self.noise = "misc/trigger1.wav";
-       }
-
-       // set default use key sound
-       if (self.noise1 == "")
-               self.noise1 = "misc/decreasevalue.wav";
-
-       // set closed sourd
-       if (self.noise2 == "")
-               self.noise2 = "misc/talk.wav";
-
-       // delay between triggering message2 and trigger2
-       if (!self.wait)
-               self.wait = 5;
-
-       // precache sounds
-       precache_sound(self.noise);
-       precache_sound(self.noise1);
-       precache_sound(self.noise2);
-
-       EXACTTRIGGER_INIT;
-
-       self.touch = trigger_keylock_touch;
-}