Fix a couple of bugs+omissions in csqctest.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6184 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-02-07 14:34:22 +00:00
parent 73f6df016c
commit f08b39318a
22 changed files with 155 additions and 5425 deletions

View file

@ -1,334 +0,0 @@
//note that this file uses various engine pastes and is thus subject to the terms of the GNU GPL.
//use with caution
float lastclientthink, sv_maxspeed, sv_friction, sv_accelerate, sv_stopspeed;
float sv_edgefriction, cl_rollangle, cl_divspeed;
vector phys_origin; //in/out
float phys_movetype; //in
float phys_health; //in
float phys_fixangle; //in
float phys_onground; //in/out
float phys_waterjump; //in/out
vector phys_angles; //out
vector phys_v_angles; //in
vector phys_velocity; //in/out
vector phys_movement; //in
vector phys_punchangle; //in/out
float phys_gravity; //in (should be sv_gravity * self.gravity)
#define bound(min,val,max) if (val < min) val = min; else if (val > max) val = max
#define sv_stepheight 22
var void() thinkfunc;
float(entity ent, float ftime) SV_FlyMove =
{
}
void() WalkMove =
{
float clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity;
vector upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity;
// SV_CheckVelocity(ent);
// do a regular slide move unless it looks like you ran into a step
oldonground = phys_onground;
phys_onground = false;
start_origin = phys_origin;
start_velocity = phys_velocity;
clip = SV_FlyMove (ent, sv.frametime, NULL);
SV_SetOnGround (ent);
SV_CheckVelocity(ent);
VectorCopy(phys_origin, originalmove_origin);
VectorCopy(phys_velocity, originalmove_velocity);
originalmove_clip = clip;
originalmove_flags = (int)ent->fields.server->flags;
originalmove_groundentity = phys_groundentity;
if (phys_waterjump)
return;
// if (sv_nostep.integer)
// return;
// if move didn't block on a step, return
if (clip & 2)
{
// if move was not trying to move into the step, return
if (fabs(start_velocity[0]) < 0.03125 && fabs(start_velocity[1]) < 0.03125)
return;
if (phys_movetype != MOVETYPE_FLY)
{
// return if gibbed by a trigger
if (phys_movetype != MOVETYPE_WALK)
return;
// only step up while jumping if that is enabled
// if (!(sv_jumpstep.integer && sv_gameplayfix_stepwhilejumping.integer))
if (!oldonground && phys_waterlevel == 0)
return;
}
// try moving up and forward to go up a step
// back to start pos
VectorCopy (start_origin, phys_origin);
VectorCopy (start_velocity, phys_velocity);
// move up
VectorClear (upmove);
upmove[2] = sv_stepheight;
// FIXME: don't link?
SV_PushEntity(ent, upmove);
// move forward
phys_velocity[2] = 0;
clip = SV_FlyMove (ent, sv.frametime, stepnormal);
phys_velocity[2] += start_velocity[2];
// SV_CheckVelocity(ent);
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if (clip
&& fabs(originalmove_origin[1] - phys_origin[1]) < 0.03125
&& fabs(originalmove_origin[0] - phys_origin[0]) < 0.03125)
{
//Con_Printf("wall\n");
// stepping up didn't make any progress, revert to original move
VectorCopy(originalmove_origin, phys_origin);
VectorCopy(originalmove_velocity, phys_velocity);
//clip = originalmove_clip;
phys_flags = originalmove_flags;
phys_groundentity = originalmove_groundentity;
// now try to unstick if needed
//clip = SV_TryUnstick (ent, oldvel);
return;
}
//Con_Printf("step - ");
// extra friction based on view angle
if (clip & 2 && sv_wallfriction.integer)
SV_WallFriction (ent, stepnormal);
}
// skip out if stepdown is enabled, moving downward, not in water, and the move started onground and ended offground
// else if (!(sv_gameplayfix_stepdown.integer && phys_waterlevel < 2 && start_velocity[2] < (1.0 / 32.0) && oldonground && !((int)ent->fields.server->flags & FL_ONGROUND)))
// return;
/*
// move down
VectorClear (downmove);
downmove[2] = -sv_stepheight + start_velocity[2]*sv.frametime;
// FIXME: don't link?
downtrace = SV_PushEntity (ent, downmove);
if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7)
{
// LordHavoc: disabled this check so you can walk on monsters/players
//if (phys_solid == SOLID_BSP)
{
//Con_Printf("onground\n");
phys_onground = true;
phys_groundentity = PRVM_EDICT_TO_PROG(downtrace.ent);
}
}
else
{
//Con_Printf("slope\n");
// 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
VectorCopy(originalmove_origin, ent->fields.server->origin);
VectorCopy(originalmove_velocity, ent->fields.server->velocity);
//clip = originalmove_clip;
ent->fields.server->flags = originalmove_flags;
ent->fields.server->groundentity = originalmove_groundentity;
}
SV_SetOnGround (ent);
SV_CheckVelocity(ent);
*/
};
// LordHavoc:
// Highly optimized port of SV_ClientThink from engine code to QuakeC.
// note that the engine will call this function if it finds it,
// so modify for your own mods and enjoy...
void() RunPlayerPhysics =
{
local vector wishvel, wishdir, v;
local float wishspeed, f;
if (phys_movetype == MOVETYPE_NONE)
return;
if (phys_punchangle != '0 0 0')
{
f = vlen(phys_punchangle) - 10 * frametime;
if (f > 0)
phys_punchangle = normalize(phys_punchangle) * f;
else
phys_punchangle = '0 0 0';
}
// if dead, behave differently
if (phys_health <= 0)
return;
// show 1/3 the pitch angle and all the roll angle
phys_angles_z = bound(-1, phys_velocity * v_right * cl_divspeed, 1) * cl_rollangle;
if (!phys_fixangle)
{
phys_angles_x = (phys_v_angle_x + phys_punchangle_x) * 0.333 * autocvar(r_meshpitch, -1);
phys_angles_y = phys_v_angle_y + phys_punchangle_y;
}
if (phys_waterjump)
{
phys_velocity_x = phys_movedir_x;
phys_velocity_y = phys_movedir_y;
if (time > phys_teleport_time || phys_waterlevel == 0)
{
phys_waterjump = false;
phys_teleport_time = 0;
}
return;
}
makevectors(phys_v_angle);
// swim
if (phys_waterlevel >= 2)
if (phys_movetype != MOVETYPE_NOCLIP)
{
phys_onground = false;
if (phys_movement == '0 0 0')
wishvel = '0 0 -60'; // drift towards bottom
else
wishvel = v_forward * phys_movement_x + v_right * phys_movement_y + '0 0 1' * phys_movement_z;
wishspeed = vlen (wishvel);
if (wishspeed > sv_maxspeed)
wishspeed = sv_maxspeed;
wishspeed = wishspeed * 0.7;
// water friction
if (phys_velocity != '0 0 0')
{
f = vlen(phys_velocity) * (1 - frametime * sv_friction);
if (f > 0)
phys_velocity = normalize(phys_velocity) * f;
else
phys_velocity = '0 0 0';
}
else
f = 0;
// water acceleration
if (wishspeed <= f)
return;
f = min(wishspeed - f, sv_accelerate * wishspeed * frametime);
phys_velocity = phys_velocity + normalize(wishvel) * f;
return;
}
// hack to not let you back into teleporter
if (time < phys_teleport_time && phys_movement_x < 0)
wishvel = v_right * phys_movement_y;
else
{
if (phys_onground)
makevectors (phys_v_angle_y * '0 1 0');
wishvel = v_forward * phys_movement_x + v_right * phys_movement_y;
}
if (phys_movetype != MOVETYPE_WALK)
wishvel_z = phys_movement_z;
else
wishvel_z = 0;
wishdir = normalize(wishvel);
wishspeed = vlen(wishvel);
if (wishspeed > sv_maxspeed)
wishspeed = sv_maxspeed;
if (phys_movetype == MOVETYPE_NOCLIP) // noclip
{
phys_onground = false;
phys_velocity = wishdir * wishspeed;
}
else if (phys_onground) // walking
{
// friction
if (phys_velocity_x || phys_velocity_y)
{
v = phys_velocity;
v_z = 0;
f = vlen(v);
// if the leading edge is over a dropoff, increase friction
v = phys_origin + normalize(v) * 16 + '0 0 1' * phys_mins_z;
traceline(v, v + '0 0 -34', TRUE, self);
// apply friction
if (trace_fraction == 1.0)
{
if (f < sv_stopspeed)
f = 1 - frametime * (sv_stopspeed / f) * sv_friction * sv_edgefriction;
else
f = 1 - frametime * sv_friction * sv_edgefriction;
}
else
{
if (f < sv_stopspeed)
f = 1 - frametime * (sv_stopspeed / f) * sv_friction;
else
f = 1 - frametime * sv_friction;
}
if (f < 0)
phys_velocity = '0 0 0';
else
phys_velocity = phys_velocity * f;
}
// acceleration
f = wishspeed - (phys_velocity * wishdir);
if (f > 0)
phys_velocity = phys_velocity + wishdir * min(f, sv_accelerate * frametime * wishspeed);
}
else // airborn
{
if (wishspeed < 30)
f = wishspeed - (phys_velocity * wishdir);
else
f = 30 - (phys_velocity * wishdir);
if (f > 0)
phys_velocity = phys_velocity + wishdir * (min(f, sv_accelerate) * wishspeed * frametime);
}
PlayerPreThink();
if (thinkfunc)
thinkfunc();
if (!SV_CheckWater (ent) && !phys_waterjump) )
phys_velocity_z -= phys_gravity * frametime;
// SV_CheckStuck (ent);
SV_WalkMove (ent);
PlayerPostThink();
}

View file

@ -1,27 +0,0 @@
float movement_time;
float movement_type;
vector movement_angles;
vector movement_velocity;
vector movement_origin;
vector movement_quantities;
float movement_buttons;
float movement_gravity;
float movement_maxspeed;
void() RunPlayerPhysics =
{
local vector vel;
local float speed;
makevectors(movement_angles);
vel = v_forward*movement_quantities_x +
v_right*movement_quantities_y +
v_up*movement_quantities_z;
vel = movement_velocity+vel*movement_time;
speed = vlen(vel);
if (speed > maxspeed)
vel = vel * (maxspeed/speed);
};

View file

@ -22,6 +22,7 @@ Any fields that are read need to be the same between csqc and ssqc code somehow.
#define movevars_stopspeed 100
#define movevars_maxspeed 320
#define movevars_jumpheight 270
#define movevars_watersinkspeed 60
.float pmove_flags;
@ -118,7 +119,7 @@ void(void) PMove_Move = //move forwards (preferably on the level) (does step ups
self.origin = trace_endpos;
self.groundentity = trace_ent;
continue;
}
}
@ -132,26 +133,6 @@ void(void) PMove_Move = //move forwards (preferably on the level) (does step ups
break;
}
};
/*
void(vector dest) PMove_StepMove =
{
//we hit something...
//step up
src = trace_endpos;
trace_endpos_z += movevars_stepheight;
tracebox(src, self.mins, self.maxs, dest, false, self);
stepped = trace_endpos_z - src_z;
dest_z += stepped;
//move forwards
tracebox(trace_endpos, self.mins, self.maxs, dest, false, self);
//move down
dest_z -= stepped;
tracebox(trace_endpos, self.mins, self.maxs, dest, false, self);
}
*/
void() PMove_ApplyFriction =
{
float newspeed, oldspeed;
@ -174,9 +155,9 @@ void() PMove_ApplyFriction =
void(vector wishdir, float wishspeed, float accel) PMove_Accelerate =
{
float addspeed, accelspeed;
float d;
d = self.velocity*wishdir;
addspeed = wishspeed - (d);
float curspeed;
curspeed = self.velocity*wishdir; //This is wrong, but allows us to replicate many of Quake's old physics bugs... yay...
addspeed = wishspeed - (curspeed);
if (addspeed <= 0)
return;
accelspeed = accel*input_timelength*wishspeed;
@ -240,13 +221,17 @@ void() PMove_InAirAccelerate =
}
};
void() PMove_NoclipAccelerate =
void(float scale) PMove_NoclipAccelerate =
{
vector desireddir;
float desiredspeed;
desireddir = v_forward*input_movevalues_x + v_right*input_movevalues_y+v_up*input_movevalues_z;
desiredspeed = vlen(desireddir);
if (input_buttons & 2)
desireddir_z = max(movevars_maxspeed, desireddir_z); //should be water:100, slime:80, lava:50, but lets just bake smartjump in here instead (we don't have the client's cl_upspeed value in ssqc though).
else if (desireddir == '0 0 0' && scale<1)
desireddir_z = -movevars_watersinkspeed;
desiredspeed = vlen(desireddir)*scale;
desireddir = normalize(desireddir);
PMove_ApplyFriction();
@ -256,7 +241,7 @@ void() PMove_NoclipAccelerate =
void() PMove_Categorise =
{
//if we're moving up, we're not on the ground
if (self.velocity_z > 0)
if (0)//self.velocity_z > 0)
{
self.pmove_flags &= ~PMF_ONGROUND;
}
@ -274,12 +259,28 @@ void() PMove_Categorise =
self.groundentity = trace_ent;
}
}
self.waterlevel = 0;
float c = pointcontents(self.origin + [0,0,1]);
self.watertype = c;
if (c <= CONTENT_WATER)
{
self.waterlevel = 1;
c = pointcontents(self.origin + [0,0,(self.maxs_z+self.mins_z)*0.5]);
if (c <= CONTENT_WATER)
{
self.watertype = c;
self.waterlevel = 2;
//don't bother checking eyes. who cares.
}
}
};
float roundcoordf(float f)
{ //round this coord like the networking will... ish...
//coord rounding is often client-specific. which makes life fun.
return rint(f*8)/8;
return f;//rint(f*8)/8;
}
vector roundcoordv(vector v)
{
@ -322,6 +323,12 @@ static void Pmove_Nudge(void)
void(entity ent) PMove =
{
if (stof(serverkey("test_qwphys")) && checkbuiltin(runstandardplayerphysics))
{
runstandardplayerphysics(ent);
return;
}
self = ent;
makevectors(input_angles);
@ -332,28 +339,35 @@ void(entity ent) PMove =
PMove_Categorise();
self.movetype = MOVETYPE_WALK;
// self.movetype = MOVETYPE_WALK;
if (input_timelength >= 0)
{
switch(self.movetype)
{
case MOVETYPE_WALK:
if (self.waterlevel >= 2)
{
PMove_NoclipAccelerate(0.7);
self.velocity = self.velocity - 0.8*self.waterlevel*input_timelength*self.velocity; //water friction.
}
else
PMove_InAirAccelerate();
PMove_Move();
break;
case MOVETYPE_FLY:
PMove_NoclipAccelerate();
PMove_NoclipAccelerate(1.0);
PMove_Move();
break;
case MOVETYPE_NOCLIP:
PMove_NoclipAccelerate();
PMove_NoclipAccelerate(1.0);
self.origin += self.velocity*input_timelength;
break;
case MOVETYPE_NONE:
break;
}
dotouch(self.groundentity);
touchtriggers(self);
}
else print(sprintf("timelength %g\n", input_timelength));
@ -362,6 +376,10 @@ void(entity ent) PMove =
self.flags |= FL_ONGROUND;
else
self.flags &= ~FL_ONGROUND;
#ifdef CSQC
cprint(sprintf("onground: %g", self.pmove_flags & PMF_ONGROUND));
#endif
};
#endif

View file

@ -1,11 +0,0 @@
//This file contains the system globals for the default pmove code
noref float input_timelength;
noref vector input_angles;
noref vector input_movevalues;
noref float input_buttons;
noref float input_impulse;
//float input_lightlevel;
//float input_weapon;
//float input_servertime;

View file

@ -1,42 +0,0 @@
void() SV_PlayerPhysics =
{
if (time != lastclientthink)
{
lastclientthink = time;
sv_maxspeed = cvar("sv_maxspeed");
sv_friction = cvar("sv_friction");
sv_accelerate = cvar("sv_accelerate");
sv_stopspeed = cvar("sv_stopspeed");
sv_edgefriction = cvar("edgefriction");
// LordHavoc: this * 4 is an optimization
cl_rollangle = cvar("cl_rollangle") * 4;
// LordHavoc: this 1 / is an optimization
cl_divspeed = 1 / cvar("cl_rollspeed");
}
phys_movetype = self.movetype;
phys_health = self.health;
phys_fixangle = self.fixangle;
phys_onground = self.flags & FL_ONGROUND;
phys_waterjump = self.flags * FL_WATERJUMP;
// phys_angles = self.angles;
phys_v_angles = self.v_angles;
phys_velocity = self.velocity;
phys_movement = self.movement;
phys_punchangle = self.punchangle;
RunPlayerPhysics();
if (phys_onground)
self.flags = self.flags | FL_ONGROUND;
else
self.flags = self.flags - (self.flags & FL_ONGROUND);
if (phys_waterjump)
self.flags = self.flags | FL_WATERJUMP;
else
self.flags = self.flags - (self.flags & FL_WATERJUMP);
self.angles = phys_angles;
self.velocity = phys_velocity;
self.punchangle = phys_punchangle;
};

View file

@ -39,7 +39,7 @@ enum {
#define SVE_INVIS 128
#define SVE_GOD 64
#define SVE_QUAD 32
#define SVE_NOPRED 16
#define SVE_MOVETYPE 16
#define SVE_WEAPONSMASK 15
.float removetime;

View file

@ -9,6 +9,8 @@ static string editvalue;
static entity tempent;
void() editor_lights_add =
{
__using(dynamiclight_get);
float l;
if (!tempent)
tempent = spawn();
@ -45,6 +47,8 @@ static string fldname[8] = {
};
static string(float fld, float foredit) readfield =
{
__using(dynamiclight_get);
switch(fld)
{
case 1:

View file

@ -9,11 +9,11 @@ enum
};
void(float action, vector pos, float radius, float quant) terrain_edit = #278;
float(float keyc, float unic) editor_terrain_key =
{
vector v, o;
__using terrain_edit;
if (keyc == '[')
{
v = (vector)getviewprop(VF_ANGLES);

View file

@ -215,13 +215,6 @@ void(entity ve) DoThatViewModelThing =
ve.angles = '0 0 0';
};
void() drawloadingscreen =
{
//work in progress here
// drawfill('0 0', '320 240', '1 1 1', 1);
// drawstring('0 0', "loading screen", '1 1', '1 1 1', 1);
};
void(float apilevel, string enginename, float engineversion) CSQC_Init =
{
__using renderflags;
@ -238,8 +231,6 @@ void(float apilevel, string enginename, float engineversion) CSQC_Init =
viewentity = spawn();
viewentity.renderflags = RF_VIEWMODEL|RF_DEPTHHACK;
drawloadingscreen ();
regcommands();
if (checkextension("EXT_CSQC_1"))
@ -460,3 +451,13 @@ void(float width, float height, float do2d) CSQC_UpdateView =
}
};
void(float vwidth, float vheight, float notmenu) CSQC_UpdateViewLoading =
{
print("in CSQC_UpdateViewLoading\n");
drawfill([0,0],[vwidth,vheight], [0,1,0],1, 0);
const vector tsize = '24 24';
string text = "CSQCTest is Loading!\nPlease wait...";
vector pos = ([vwidth,vheight]-[8,stringwidth(text,TRUE,tsize)])*0.5;
drawstring(pos, text, tsize, '1 1 1',1,0);
};

View file

@ -44,6 +44,8 @@ static void() FindPlayerSkins =
if (c_skinlist >= 0)
search_end(c_skinlist);
c_skinlist = -1;
if (str != "")
c_skinlist = search_begin(strcat("models/players/", str, "/upper_*.skin"), true, true);
if (c_skinlist < 0)

View file

@ -48,7 +48,7 @@ static float() Player_Interpolate =
#ifdef Q4PMODELS
case MF_QUAKE4:
Q4PM_Draw();
break;
return PREDRAW_NEXT;
#endif
#ifdef HLPMODELS
case MF_HLPM:
@ -410,6 +410,24 @@ float(float isnew) RefreshPlayer =
#endif
if (self.modelstyle == MF_BAD)
Player_SetQ1Model();
switch(self.modelstyle)
{
case MF_BAD: dprint(sprintf("%S: player model not known\n", newskin)); break;
#ifdef MD3PMODELS
case MF_QUAKE3: dprint(sprintf("%S: quake3 player model loaded\n", newskin)); break;
#endif
#ifdef Q4PMODELS
case MF_QUAKE4: dprint(sprintf("%S: quake4 player model loaded\n", newskin)); break;
#endif
#ifdef HLPMODELS
case MF_HLPM: dprint(sprintf("%S: halflife player model loaded\n", newskin)); break;
#endif
#ifdef XM
case MF_XM: dprint(sprintf("%S: xonotic player model loaded\n", newskin)); break;
#endif
case MF_QUAKE: dprint(sprintf("%S: quake player model loaded\n", newskin)); break;
}
}
}
@ -450,6 +468,12 @@ nonstatic void(float isnew) ParsePlayer =
self.colormap = self.entnum;
self.sveffects = readbyte();
if (self.sveffects & SVE_MOVETYPE)
self.movetype = readbyte();
else
self.movetype = MOVETYPE_WALK;
self.pmove_flags = (self.movetype&~63)>>6;
self.movetype &= 63;
RefreshPlayer(isnew);
};

View file

@ -133,11 +133,8 @@ void(entity ent, float endframe) Pred_RunMovement =
return;
}
#ifdef WORKINDP
//DP handily corrupts this for us, so waste some more cpu cycles to compensate
if (isdp)
Pred_ResetPlayerPrediction();
#endif
//rewind to our last-known-good position
Pred_ResetPlayerPrediction(ent);
if (getstatf(STAT_HEALTH) <= 0)
{
@ -160,7 +157,9 @@ void(entity ent, float endframe) Pred_RunMovement =
return;
}
while(pmoveframe < endframe)
if (getinputstate(pmoveframe-1))
self.pmove_flags = PMF_JUMP_HELD;
while(pmoveframe <= endframe)
{
if (!getinputstate(pmoveframe))
{

View file

@ -806,7 +806,7 @@ nonstatic float(string modname) Anim_ReadAnimationFile =
file = fopen(str, FILE_READ);
if (file < 0)
{
print("fopen ", modname, " failed\n");
print(sprintf("fopen %S failed\n", str));
return -1;
}

View file

@ -83,13 +83,13 @@ void() Q4PM_Draw =
if (!self.skeletonindex)
{
self.skeletonindex = skel_create(self.modelindex);
self.skeletonindex = skel_create(self.modelindex, FALSE);
if (!self.skeletonindex)
return;
}
ideal = anglequadrant();
aimang_x = self.angles_y;
aimang_y = self.angles_y;
aimang_z = self.angles_x*-3;
self.angles_x = 0;
@ -103,12 +103,12 @@ void() Q4PM_Draw =
fw = (move * v_forward)/(320);
rt = (move * v_right)/(320);
aimang_x -= self.angles_y;
aimang_y = 0;
if (aimang_x > 180)
aimang_x -= 360;
if (aimang_x < -180)
aimang_x += 360;
aimang_y -= self.angles_y;
aimang_x = 0;
if (aimang_y > 180)
aimang_y -= 360;
if (aimang_y < -180)
aimang_y += 360;
makevectors(aimang*0.333);
if (fw*fw > 0)
@ -137,7 +137,6 @@ void() Q4PM_Draw =
self.aweight[ANIM_IDLE] += frametime*4;
self.atime[ANIM_IDLE] += frametime;
tweight = self.aweight[ANIM_FORWARD]+self.aweight[ANIM_BACK]+self.aweight[ANIM_LEFT]+self.aweight[ANIM_RIGHT]+self.aweight[ANIM_IDLE];
if (tweight > 1)
{
@ -154,7 +153,7 @@ void() Q4PM_Draw =
self.atime[ANIM_IDLE] += frametime;
}
self.origin_z += self.mins_z;
self.origin_z -= 24;//self.mins_z;
setmodel(self, self.model);
for (i = 0; i < ANIM_MAX; i++)
{
@ -173,6 +172,11 @@ void() Q4PM_Draw =
//obliterate the bone movement, so that it doesn't move forwards.
skel_get_bonerel(self.skeletonindex, 1);
skel_set_bone(self.skeletonindex, 1, '0 0 0', v_forward*(64/72), v_right*(64/72), v_up*(64/72));
self.renderflags = 0;
addentity(self);
self.origin = self.lastorg;
};
float(string skinname) Q4PM_SetModel =
@ -181,7 +185,10 @@ float(string skinname) Q4PM_SetModel =
//check to see if it exists
if not (whichpack(mname))
{
print(sprintf("File %s doesn't exist\n", mname));
return false;
}
anim[ANIM_IDLE] = getmodelindex("models/characters/player/idle.md5anim");
anim[ANIM_FORWARD] = getmodelindex("models/characters/player/run.md5anim");

View file

@ -2,12 +2,7 @@
#define CSQC
optsall.qc
#ifdef QSS
csqc_api.qc
//qsextensions.qc
#else
fteextensions.qc
#endif
cs/defs.qc
common/classes.qc
@ -16,7 +11,6 @@ common/econstants.qc
cs/constants.qc
cs/playerframes.inc
common/pmovedefs.qc
common/pmove.qc
common/makeallstatic.qc

File diff suppressed because it is too large Load diff

View file

@ -1,270 +0,0 @@
//definitions that id Software left out
//these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed)
float MOVE_NORMAL = 0; // same as FALSE
float MOVE_NOMONSTERS = 1; // same as TRUE
float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
//checkextension function
//idea: expected by almost everyone
//darkplaces implementation: LordHavoc
float(string s) checkextension = #99;
//description:
//check if (cvar("pr_checkextension")) before calling this, this is the only
//guarenteed extension to be present in the extension system, it allows you
//to check if an extension is available, by name, to check for an extension
//use code like this:
//// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere)
//if (cvar("pr_checkextension"))
//if (checkextension("DP_SV_SETCOLOR"))
// ext_setcolor = TRUE;
//from then on you can check ext_setcolor to know if that extension is available
//EXT_BITSHIFT
//IDEA: Spike
float(float number, float quantity) bitshift = #218;
//Shifts 'number' 'quantity' bits to the left. So a shift of 1 bit essentually doubles the value while a shift of -1 bit halves. 2 quadrouples and so on.
//The function acts on floats, but casts as integers. The maximum reliable bit stored in a float is 1e23. Adding a twenty fourth bit is possible, but can result in some of the lower bits becoming corrupted.
//EXT_DIMENSION_GHOST
//IDEA: ?????FIXME?????
.float dimension_ghost;
.float dimension_ghost_alpha;
//depends on EXT_DIMENSION_VISIBLE
//provides an alternate mask for entities to see this one.
//entities seen with this mask and not the dimension_seen mask will have thier alpha value multiplied by thier dimension_ghost_alpha.
//they default to 255 upon entity creation.
//EXT_DIMENSION_PHYSICS
//IDEA: ?????FIXME?????, Spike
.float dimension_hit;
.float dimension_solid;
//Controls which entities are allowed to collide with other entities.
//dimension_solid is the mask of dimensions in which an entity is solid.
//dimension_hit is the mask of dimensions which will not pass through dimension_solid.
//most of the time they will be the same.
//if one entity walks into annother, they must be able to ignore the other even if thier masks say not.
//they default to 255 upon entity creation.
//EXT_DIMENSION_VISIBLE
//IDEA: ?????FIXME?????, Spike
.float dimension_see;
.float dimension_seen;
float dimension_send;
//Controls which players see which entities/players.
//You always see yourself.
//the dimension_seen mask is the mask of dimensions which an entity can be seen, while dimension_see is which dimensions an entity can see into.
//dimension_send is set around the sound and various particle effect builtins, and will be sent only to players who's dimension_see matches.
//note that this can be used for sound directed at a single player, per-class pickups, and other cool stuff.
//they default to 255 upon entity creation - note that saved games will need to be fixed-up if there are no values set on any entity after load.
//FRIK_FILE
//idea: FrikaC
//darkplaces implementation: LordHavoc
//builtin definitions:
float(string s) stof = #81; // get numerical value from a string
float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
void(float fhandle) fclose = #111; // closes a file
string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
float(string s) strlen = #114; // returns how many characters are in a string
string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
#ifdef WORKINDP
string(string s, float start, float length) substring_frik = #116; // returns a section of a string as a tempstring
string(string s, float start, float length) substring_fte = #116; // returns a section of a string as a tempstring
string(string s, float start, float length) substring =
{
if not (ext_fte_strings)
{
if (length < 0)
length = strlen(s) - start + length+1;
return substring_frik(s, start, length);
}
return substring_fte(s, start, length);
};
#else
string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
#endif
vector(string s) stov = #117; // returns vector value from a string
string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
//constants:
float FILE_READ = 0;
float FILE_APPEND = 1;
float FILE_WRITE = 2;
//cvars:
//pr_zone_min_strings : default 64 (64k), min 64 (64k), max 8192 (8mb)
//description:
//provides text file access functions and string manipulation functions, note that you may want to set pr_zone_min_strings in the worldspawn function if 64k is not enough string zone space.
//KRIMZON_SV_PARSECLIENTCOMMAND
//idea: KrimZon
//darkplaces implementation: KrimZon, LordHavoc
//engine-called QC prototypes:
//void(string s) SV_ParseClientCommand;
//builtin definitions:
void(entity e, string s) clientcommand = #440;
float(string s) tokenize = #441;
string(float n) argv = #442;
//description:
//provides QC the ability to completely control server interpretation of client commands ("say" and "color" for example, clientcommand is necessary for this and substring (FRIK_FILE) is useful) as well as adding new commands (tokenize, argv, and stof (FRIK_FILE) are useful for this)), whenever a clc_stringcmd is received the QC function is called, and it is up to the QC to decide what (if anything) to do with it
//NEH_CMD_PLAY2
//idea: Nehahra
//darkplaces implementation: LordHavoc
//description:
//shows that the engine supports the "play2" console command (plays a sound without spatialization).
//NEH_RESTOREGAME
//idea: Nehahra
//darkplaces implementation: LordHavoc
//engine-called QC prototypes:
//void() RestoreGame;
//description:
//when a savegame is loaded, this function is called
//NEXUIZ_PLAYERMODEL
//idea: Nexuiz
//darkplaces implementation: Black
//console commands:
//playermodel <name> - FIXME: EXAMPLE NEEDED
//playerskin <name> - FIXME: EXAMPLE NEEDED
//field definitions:
.string playermodel; // name of player model sent by client
.string playerskin; // name of player skin sent by client
//description:
//these client properties are used by Nexuiz.
//NXQ_GFX_LETTERBOX
//idea: nxQuake
//darkplaces implementation: LordHavoc
//description:
//shows that the engine supports the "r_letterbox" console variable, set to values in the range 0-100 this restricts the view vertically (and turns off sbar and crosshair), value is a 0-100 percentage of how much to constrict the view, <=0 = normal view height, 25 = 75% of normal view height, 50 = 50%, 75 = 25%, >=100 = no view
//PRYDON_CLIENTCURSOR
//idea: FrikaC
//darkplaces implementation: LordHavoc
//effects bit:
float EF_SELECTABLE = 16384; // allows cursor to highlight entity (brighten)
//field definitions:
.float cursor_active; // true if cl_prydoncursor mode is on
.vector cursor_screen; // screen position of cursor as -1 to +1 in _x and _y (_z unused)
.vector cursor_trace_start; // position of camera
.vector cursor_trace_endpos; // position of cursor in world (as traced from camera)
.entity cursor_trace_ent; // entity the cursor is pointing at (server forces this to world if the entity is currently free at time of receipt)
//cvar definitions:
//cl_prydoncursor (0/1+, default 0, 1 and above use cursors named gfx/prydoncursor%03i.lmp - or .tga and such if DP_GFX_EXTERNALTEXTURES is implemented)
//description:
//shows that the engine supports the cl_prydoncursor cvar, this puts a clientside mouse pointer on the screen and feeds input to the server for the QuakeC to use as it sees fit.
//the mouse pointer triggers button4 if cursor is at left edge of screen, button5 if at right edge of screen, button6 if at top edge of screen, button7 if at bottom edge of screen.
//the clientside trace skips transparent entities (except those marked EF_SELECTABLE).
//the selected entity highlights only if EF_SELECTABLE is set, a typical selection method would be doubling the brightness of the entity by some means (such as colormod[] *= 2).
//intended to be used by Prydon Gate.
//QSG_FILE
//IDEA: ?????FIXME?????
//Same as FRIK_FILE, but definitions numbers aren't the same.
//TENEBRAE_GFX_DLIGHTS
//idea: Tenebrae
//darkplaces implementation: LordHavoc
//fields:
.float light_lev; // radius (does not affect brightness), typical value 350
.vector color; // color (does not affect radius), typical value '1 1 1' (bright white), can be up to '255 255 255' (nuclear blast)
.float style; // light style (like normal light entities, flickering torches or switchable, etc)
.float pflags; // flags (see PFLAGS_ constants)
.vector angles; // orientation of the light
.float skin; // cubemap filter number, can be 1-255 (0 is assumed to be none, and tenebrae only allows 16-255), this selects a projective light filter, a value of 1 loads cubemaps/1posx.tga and cubemaps/1negx.tga and posy, negy, posz, and negz, similar to skybox but some sides need to be rotated or flipped
//constants:
float PFLAGS_NOSHADOW = 1; // light does not cast shadows
float PFLAGS_CORONA = 2; // light has a corona flare
float PFLAGS_FULLDYNAMIC = 128; // light enable (without this set no light is produced!)
//description:
//more powerful dynamic light settings
//warning: it is best not to use cubemaps on a light entity that has a model, as using a skin number that a model does not have will cause issues in glquake, and produce warnings in darkplaces (use developer 1 to see them)
//changes compared to tenebrae (because they're too 'leet' for standards):
//EF_FULLDYNAMIC effects flag replaced by PFLAGS_FULLDYNAMIC flag (EF_FULLDYNAMIC conflicts with EF_NODRAW)
//TEI_MOVRELATIVESTATIC
//IDEA: Tei
//movetype definitions:
float MOVETYPE_RELATIVESTATIC = 12;
//Same as MOVETYPE_FOLLOW but it doesn't take owner's angles into account
//e.g. entity will not rotate around owner.
//TEI_SHOWLMP2
//IDEA: Tei
void (string slot, string picfile, float x, float y, float org, entity to) ShowPicEnt = #108; //Show pic to player
void (string slot, entity to) HidePicEnt = #109; //Hide pic from player
//Shows/hides pics to/from the player.
//You can do fantastic huds with it, but don't forget it's better to use it only in singleplayer.
//Cause netplay will suck.
//TQ_DLIGHTS
//IDEA: Tomaz
//field definition:
.float glow_size;
.float glow_red;
.float glow_green;
.float glow_blue;
//Customizable glowing light effect on the entity, glow_red, glow_green and glow_blue is the color in the range 0-1.
//glow_size is is the size of the glow (duh) in the range 0-1024.
//TQ_PLASMA
//IDEA: Tomaz
//temp entity definitions:
float TE_PLASMA = 16;
//New weapon effect.
//TQ_RAILTRAIL
//IDEA: id Software, code by TerribleOne modified by Tomaz
//temp entity definitions:
float TE_RAILTRAIL = 17;
//New weapontrail effect.
//TQ_SLOWMO
//IDEA: Tomaz
//Same as DP_SV_SLOWMO
//TW_SV_STEPCONTROL
//idea: Transfusion
//darkplaces implementation: LordHavoc
//cvars:
//sv_jumpstep (0/1, default 1)
//sv_stepheight (default 18)
//description:
//sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be.
//ZQ_QC_CHECKBUILTIN
//IDEA: Tonik
float(float num, ...) checkbuiltin = #23040;
float(float first, float last) checkbuiltinrange = #23041;
//ZQuake (and Betwix :) provides a way to check for the presence of a QC extension by builtin number rather than by name. E.g. to see if the engine supports DP_QC_TRACEBOX (builtin #90), you can use
// if (checkbuiltin(90)) {...}
//instead of
// if (checkextension("DP_QC_TRACEBOX")) {...}
//Several (up to 8) extension numbers may be checked in one call to checkbuiltin(). TRUE will be returned if all of the extensions are supported, FALSE otherwise.
//E.g.
// if (checkbuiltin(94,95,96)) {...}
//is equivalent to
// if (checkextension("DP_QC_MINMAXBOUND")) {...}
//Another way to check several contiguous builtin numbers in one call:
// if (checkbuiltinrange(94,96)) {...}

View file

@ -1,6 +1,8 @@
//#define WORKINDP //use workarounds for DP.
//which engines do we want to support?
#define FTE
#define QSS
//#define FTEDEPENDANT //explicitly depend upon FTE-only extensions (mostly prototype EXT_CSQC_1 features).
//#define DP
#define OWNPLAYERPHYSICS //run our own prediction code, instead of the engine-supplied default
#define AUTOCVAR
@ -16,20 +18,16 @@
#undef MD3PMODELS
#endif
#ifdef WORKINDP
# warning "WORKINDP defined: Mod will only work properly in DP"
# ifdef FTEDEPENDANT
# undef FTEDEPENDANT
#ifdef DP
#define WORKINDP //do various workarounds for DP. don't use any opcode extensions
#elifdef QSS
#pragma TARGET QSS //FTE also supports this.
#define NOT_DP //mute deprecation warnings about DP, we don't care.
#else
#pragma TARGET FTE //neither of the other engines are targetted, go crazy with it.
#define NOT_QSS //mute deprecation warnings about QSS, we don't care.
#define NOT_DP //mute deprecation warnings about DP, we don't care.
#endif
#endif
#ifdef FTEDEPENDANT
# warning "FTEDEPENDANT defined: Mod will only work properly in FTE"
# pragma TARGET FTE
#endif

File diff suppressed because it is too large Load diff

View file

@ -474,6 +474,7 @@ float(entity to, float fl) SendPlayer =
{
float ef;
float f;
float mt;
//encode the current weapon in the lower 4 bits.
for (f = 1, ef = 0; ef < 16; ef=ef+1,f*=2)
@ -488,9 +489,12 @@ float(entity to, float fl) SendPlayer =
ef |= 64;
if (self.items & IT_QUAD)
ef |= 32;
//and the final bit takes an indication to switch of prediction.
if (self.movetype != MOVETYPE_WALK)
ef |= 16; //tells the csqc to stop trying to predict (I can't be bothered to send the real movetype)
//and the final bit takes an indication to switch off prediction.
mt = self.movetype;
if (self.pmove_flags&1)
mt |= 128;
if (mt != MOVETYPE_WALK)
ef |= 16;
WriteByte(MSG_ENTITY, CLASS_PLAYER);
@ -504,6 +508,8 @@ float(entity to, float fl) SendPlayer =
WriteShort(MSG_ENTITY, self.velocity_y);
WriteShort(MSG_ENTITY, self.velocity_z);
WriteByte(MSG_ENTITY, ef);
if (ef & 16)
WriteByte(MSG_ENTITY, mt);
return TRUE;
};
@ -903,8 +909,8 @@ void() WaterMove =
self.dmgtime = 0;
}
if (! (self.flags & FL_WATERJUMP) )
self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
// if (! (self.flags & FL_WATERJUMP) )
// self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
};
void() CheckWaterJump =

View file

@ -81,23 +81,23 @@ void(vector org, vector vec) LaunchLaser =
vec = normalize(vec);
newmis = spawn();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLY;
newmis.solid = SOLID_BBOX;
newmis.effects = EF_DIMLIGHT;
entity mis = spawn();
mis.owner = self;
mis.movetype = MOVETYPE_FLY;
mis.solid = SOLID_BBOX;
mis.effects = EF_DIMLIGHT;
setmodel (newmis, "progs/laser.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setmodel (mis, "progs/laser.mdl");
setsize (mis, '0 0 0', '0 0 0');
setorigin (newmis, org);
setorigin (mis, org);
newmis.velocity = vec * 600;
newmis.angles = vectoangles(newmis.velocity);
mis.velocity = vec * 600;
mis.angles = vectoangles(mis.velocity);
newmis.nextthink = time + 5;
newmis.think = SUB_Remove;
newmis.touch = Laser_Touch;
mis.nextthink = time + 5;
mis.think = SUB_Remove;
mis.touch = Laser_Touch;
};

View file

@ -3,16 +3,12 @@
//#define QWSSQC
#define SSQC
optsall.qc
#if defined(QSS) && !defined(QWSSQC)
qsextensions.qc
#endif
fteextensions.qc
ssqc_api.qc
ss/defs.qc
common/econstants.qc
common/classes.qc
common/pmovedefs.qc
common/pmove.qc
ss/subs.qc