Added pm_watersinkspeed cvar.

Misc bugfixes, mostly hexen2-related. tibet5 bug is finally fixed.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4635 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-04-06 15:16:39 +00:00
parent 8f7931b860
commit 2e98386da2
22 changed files with 155 additions and 52 deletions

View File

@ -1680,7 +1680,7 @@ droid-dbg:
$(foreach a, $(DROID_ARCH), $(MAKE) FTE_TARGET=droid gl-dbg DROID_ARCH=$a; )
@$(foreach a, $(DROID_ARCH), mkdir -p droid/libs/$a; )
-@$(foreach a, $(DROID_ARCH), cp $(DEBUG_DIR)/gl_droid-$a/libftedroid.so droid/libs/$a/libftedroid.so; )
@cd droid && $(ANT) debug && $(ANT) debug install
@cd droid && $(ANT) debug #&& $(ANT) debug install
cp droid/bin/FTEDroid-debug.apk $(DEBUG_DIR)/FTEDroid.apk
droid-help:

View File

@ -1788,10 +1788,9 @@ void CL_CheckServerInfo(void)
movevars.walljump = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_walljump")));
movevars.ktjump = Q_atof(Info_ValueForKey(cl.serverinfo, "pm_ktjump"));
s = Info_ValueForKey(cl.serverinfo, "pm_stepheight");
if (*s)
movevars.stepheight = Q_atof(s);
else
movevars.stepheight = PM_DEFAULTSTEPHEIGHT;
movevars.stepheight = *s?Q_atof(s):PM_DEFAULTSTEPHEIGHT;
s = Info_ValueForKey(cl.serverinfo, "pm_watersinkspeed");
movevars.watersinkspeed = *s?Q_atof(s):60;
// Initialize cl.maxpitch & cl.minpitch
if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)

View File

@ -1113,7 +1113,7 @@ void CL_PredictMovePNum (int seat)
VectorCopy (tostate->velocity, pv->simvel);
VectorCopy (tostate->origin, pv->simorg);
if (pv->viewentity && pv->viewentity != pv->playernum+1)
if (pv->viewentity && pv->viewentity != pv->playernum+1 && pv->cam_locked)
VectorCopy(tostate->viewangles, pv->simangles);
//Con_DPrintf("%f %f %f\n", fromtime, simtime, totime);
}
@ -1143,7 +1143,7 @@ void CL_PredictMovePNum (int seat)
pv->simvel[i] = (1-f)*fromstate->velocity[i] + f*tostate->velocity[i];
if (pv->viewentity && pv->viewentity != pv->playernum+1)
if (pv->viewentity && pv->viewentity != pv->playernum+1 && pv->cam_locked)
{
pv->simangles[i] = LerpAngles360(fromstate->viewangles[i], tostate->viewangles[i], f);// * (360.0/65535);
// pv->viewangles[i] = LerpAngles16(fromstate->command.angles[i], tostate->command.angles[i], f) * (360.0/65535);

View File

@ -173,13 +173,15 @@ typedef struct
int entity;
short tag;
qbyte active;
qbyte flags;
qbyte bflags;
qbyte type;
qbyte skin;
unsigned int rflags;
struct model_s *model;
float endtime;
float alpha;
vec3_t start, end;
vec3_t offset; //when attached, this is the offset from the owning entity. probably only z is meaningful.
int particleeffect;
trailstate_t *trailstate;
trailstate_t *emitstate;
@ -362,10 +364,10 @@ void CL_ShutdownTEnts (void)
void CL_ClearTEntParticleState (void)
{
int i;
for (i = 0; i < beams_running; i++)
for (i = 0; i < cl_beams_max; i++)
{
pe->DelinkTrailstate(&(cl_beams[i].trailstate));
pe->DelinkTrailstate(&(cl_beams[i].emitstate));
P_DelinkTrailstate(&(cl_beams[i].trailstate));
P_DelinkTrailstate(&(cl_beams[i].emitstate));
}
}
@ -758,7 +760,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
b->model = m;
b->particleeffect = btype;
b->tag = -1;
b->flags |= /*STREAM_ATTACHED|*/1;
b->bflags |= /*STREAM_ATTACHED|*/1;
b->endtime = cl.time + 0.2;
b->alpha = 1;
VectorCopy (start, b->start);
@ -787,6 +789,28 @@ void CL_ParseBeam (int tent)
CL_AddBeam(tent, ent, start, end);
}
//finds the latest non-lerped position
float *CL_FindLatestEntityOrigin(int entnum)
{
int i;
packet_entities_t *pe;
int framenum = cl.validsequence & UPDATE_MASK;
pe = &cl.inframes[framenum].packet_entities;
for (i = 0; i < pe->num_entities; i++)
{
if (pe->entities[i].number == entnum)
return pe->entities[i].origin;
}
if (entnum > 0 && entnum <= MAX_CLIENTS)
{
entnum--;
if (cl.inframes[framenum].playerstate[entnum].messagenum == cl.parsecount)
return cl.inframes[framenum].playerstate[entnum].origin;
}
return NULL;
}
void CL_ParseStream (int type)
{
int ent;
@ -823,7 +847,7 @@ void CL_ParseStream (int type)
b->entity = ent;
b->tag = tag;
b->flags = flags;
b->bflags = flags;
b->model = NULL;
b->particleeffect = -1;
b->endtime = cl.time + duration;
@ -832,21 +856,32 @@ void CL_ParseStream (int type)
VectorCopy (start, b->start);
VectorCopy (end, b->end);
if (b->bflags & STREAM_ATTACHED)
{
float *entorg = CL_FindLatestEntityOrigin(ent);
if (!entorg)
b->bflags &= ~STREAM_ATTACHED; //not found, attached isn't valid.
else
{
VectorSubtract(b->start, entorg, b->offset);
}
}
switch(type)
{
case TEH2_STREAM_LIGHTNING_SMALL:
b->model = Mod_ForName("models/stltng2.mdl", MLV_WARN);
b->flags |= 2;
b->bflags |= 2;
b->particleeffect = P_FindParticleType("te_stream_lightning_small");
break;
case TEH2_STREAM_LIGHTNING:
b->model = Mod_ForName("models/stlghtng.mdl", MLV_WARN);
b->flags |= 2;
b->bflags |= 2;
b->particleeffect = P_FindParticleType("te_stream_lightning");
break;
case TEH2_STREAM_ICECHUNKS:
b->model = Mod_ForName("models/stice.mdl", MLV_WARN);
b->flags |= 2;
b->bflags |= 2;
b->particleeffect = P_FindParticleType("te_stream_icechunks");
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, 0, 20);
break;
@ -858,11 +893,17 @@ void CL_ParseStream (int type)
b2 = CL_NewBeam(ent, tag+128);
if (b2)
{
P_DelinkTrailstate(&b2->trailstate);
P_DelinkTrailstate(&b2->emitstate);
memcpy(b2, b, sizeof(*b2));
b2->trailstate = NULL;
b2->emitstate = NULL;
b2->model = Mod_ForName("models/stsunsf2.mdl", MLV_WARN);
b2->alpha = 0.5;
b2->rflags = RF_TRANSLUCENT;
}
}
//FIXME: we don't add the blob corners+smoke
break;
case TEH2_STREAM_SUNSTAFF2:
b->model = Mod_ForName("models/stsunsf1.mdl", MLV_WARN);
@ -1908,8 +1949,13 @@ void CL_RefreshCustomTEnts(void)
{
int i;
for (i = 0; i < sizeof(customtenttype)/sizeof(customtenttype[0]); i++)
{
customtenttype[i].particleeffecttype = (!*customtenttype[i].name)?-1:P_FindParticleType(customtenttype[i].name);
// if (customtenttype[i].particleeffecttype == P_INVALID && *customtenttype[i].name)
// Con_DPrintf("%s was not loaded\n", customtenttype[i].name);
}
if (cl.particle_ssprecaches)
{
for (i = 0; i <= MAX_SSPARTICLESPRE; i++)
@ -2109,6 +2155,10 @@ void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, model_t *model, int startframe
ex->numframes = framecount;
ex->framerate = framerate;
ex->alpha = alpha;
ex->skinnum = 0;
if (model->type == mod_alias)
ex->flags |= RF_TRANSLUCENT;
if (randspin)
{
@ -3099,7 +3149,7 @@ void CL_UpdateBeams (void)
lastrunningbeam = bnum;
// if coming from the player, update the start position
if ((b->flags & 1) && b->entity > 0 && b->entity <= cl.allocated_client_slots)
if ((b->bflags & 1) && b->entity > 0 && b->entity <= cl.allocated_client_slots)
{
for (j = 0; j < cl.splitclients; j++)
{
@ -3179,19 +3229,18 @@ void CL_UpdateBeams (void)
}
}
}
else if (b->flags & STREAM_ATTACHED)
else if (b->bflags & STREAM_ATTACHED)
{
player_state_t *pl;
st = CL_FindPacketEntity(b->entity);
if (st)
{
VectorCopy(st->origin, b->start);
VectorAdd(st->origin, b->offset, b->start);
}
else if (b->entity <= cl.allocated_client_slots && b->entity > 0)
{
pl = &cl.inframes[cl.parsecount&UPDATE_MASK].playerstate[b->entity-1];
VectorCopy(pl->origin, b->start);
b->start[2]+=16;
VectorAdd(pl->origin, b->offset, b->start);
}
}
@ -3228,7 +3277,7 @@ void CL_UpdateBeams (void)
VectorCopy (b->start, org);
d = VectorNormalize(dist);
if(b->flags & 2)
if(b->bflags & 2)
{
offset = (int)(cl.time*40)%30;
for(i = 0; i < 3; i++)
@ -3247,6 +3296,7 @@ void CL_UpdateBeams (void)
ent->drawflags |= MLS_ABSLIGHT;
ent->abslight = 64 + 128 * bound(0, cl_shaftlight.value, 1);
ent->shaderRGBAf[3] = b->alpha;
ent->flags = b->rflags;
ent->angles[0] = -pitch;
ent->angles[1] = yaw;

View File

@ -757,6 +757,7 @@ static void P_ResetToDefaults(part_type_t *ptype)
skytris_t *st;
part_type_t *torun;
char tnamebuf[sizeof(ptype->name)];
char tconfbuf[sizeof(ptype->config)];
// go with a lazy clear of list.. mark everything as DEAD and let
// the beam rendering handle removing nodes
@ -795,6 +796,7 @@ static void P_ResetToDefaults(part_type_t *ptype)
beamsegs = ptype->beams;
st = ptype->skytris;
strcpy(tnamebuf, ptype->name);
strcpy(tconfbuf, ptype->config);
//free uneeded info
if (ptype->ramp)
@ -810,6 +812,7 @@ static void P_ResetToDefaults(part_type_t *ptype)
ptype->beams = beamsegs;
ptype->skytris = st;
strcpy(ptype->name, tnamebuf);
strcpy(ptype->config, tconfbuf);
ptype->assoc=P_INVALID;
ptype->inwater = P_INVALID;
ptype->cliptype = P_INVALID;

View File

@ -185,7 +185,11 @@ void P_Shutdown(void)
{
if (pe)
{
CL_ClearTEntParticleState();
CL_ClearLerpEntsParticleState();
#ifdef Q2CLIENT
CLQ2_ClearParticleState();
#endif
pe->ShutdownParticles();
}
pe = NULL;

View File

@ -2849,6 +2849,7 @@ void Cmd_WriteConfig_f(void)
if (!*filename)
{
snprintf(fname, sizeof(fname), "fte.cfg");
FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname));
FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
}
@ -2862,12 +2863,13 @@ void Cmd_WriteConfig_f(void)
snprintf(fname, sizeof(fname), "configs/%s", filename);
COM_DefaultExtension(fname, ".cfg", sizeof(fname));
FS_NativePath(fname, FS_BASEGAMEONLY, sysname, sizeof(sysname));
FS_CreatePath(fname, FS_BASEGAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_BASEGAMEONLY);
}
if (!f)
{
Con_Printf ("Couldn't write config %s\n",fname);
Con_Printf ("Couldn't write config %s\n", sysname);
return;
}
@ -2889,7 +2891,6 @@ void Cmd_WriteConfig_f(void)
Cvar_Saved();
FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Wrote %s\n",sysname);
}

View File

@ -229,16 +229,9 @@ static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *qu
if (write || append)
{
//this extra block is to avoid flushing fs caches needlessly
h = CreateFileW(wide, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileW(wide, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, (!read&&!append)?CREATE_ALWAYS:OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
didexist = false;
if (!read) //if we're not reading, the file will be created anew. make sure we don't just reuse it. we do want to avoid rebuilding our name->location cache though.
{
CloseHandle(h);
h = INVALID_HANDLE_VALUE;
}
}
}
if (h != INVALID_HANDLE_VALUE)

View File

@ -101,6 +101,7 @@ typedef struct {
float waterfriction;
float entgravity;
float bunnyspeedcap;
float watersinkspeed;
float ktjump;
int walljump;
qboolean slidefix;

View File

@ -843,6 +843,7 @@ enum {
TEH2_STREAM_ICECHUNKS = 30,
TEH2_STREAM_GAZE = 31,
TEH2_STREAM_FAMINE = 32,
TEH2_PARTICLEEXPLOSION = 33,
TEDP_BLOOD = 50,
TEDP_SPARK = 51,

View File

@ -1446,7 +1446,8 @@ GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char **precom
"#else\n"
"#define v_position v_position1\n"
"#endif\n"
"#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n"
"vec4 ftetransform() { return m_modelviewprojection * vec4(v_position, 1.0); }\n"
// "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n"
"uniform mat4 m_modelviewprojection;\n"
;
length[strings] = strlen(prstrings[strings]);

View File

@ -460,6 +460,7 @@ r_part ce_chunk_ice
{
model models/shard.mdl 0 1 0.25 0.5
model models/shard.mdl 1 1 0.25 0.5
rotationspeed 30
randomvel 210 70 280
spawnorg 0
gravity 800
@ -562,3 +563,18 @@ r_part ce_snow
veladd 1
gravity 200
}
//h2part.ce_rain was not loaded
//h2part.ce_quake was not loaded
//h2part.ce_ghost was not loaded
//h2part.ce_redcloud was not loaded
//h2part.ce_teleporterbody was not loaded
//h2part.ce_gravitywell was not loaded
//h2part.ce_acid_muzzfl was not loaded
//h2part.ce_flamewall was not loaded
//h2part.ce_flamewall2 was not loaded
//h2part.ce_onfire was not loaded
//h2part.ce_teleporterbody_1 was not loaded
//h2part.ce_grey_smoke_100 was not loaded
//h2part.ce_chunk_fire was not loaded

View File

@ -3063,6 +3063,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
{
extern int pr_bracelevel, tempsused;
time_t long_time;
extern QCC_type_t *pr_classtype;
int p;
@ -3076,6 +3077,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
myargc = argc;
myargv = argv;
pr_scope = NULL;
pr_classtype = NULL;
locals_marshalled = 0;
qcc_compileactive = true;

View File

@ -715,7 +715,7 @@ void NPP_NQFlush(void)
// bufferlen = 0;
// break;
case svc_setview:
// requireextension = PEXT_SETVIEW;
requireextension = PEXT_SETVIEW;
if (cldest) //catch it to work with all clients
{
@ -724,7 +724,7 @@ void NPP_NQFlush(void)
if (cldest->viewent == (cldest - svs.clients)+1)
cldest->viewent = 0; //self is the same as none
}
bufferlen = 0;
// bufferlen = 0;
break;
case svcdp_hidelmp:
requireextension = PEXT_SHOWPIC;

View File

@ -2677,14 +2677,18 @@ particle(origin, color, count)
static void QCBUILTIN PF_particle (pubprogfuncs_t *prinst, globalvars_t *pr_globals) //I said it was for compatability only.
{
float *org, *dir;
float color;
float count;
int color;
int count;
int i, v;
org = G_VECTOR(OFS_PARM0);
dir = G_VECTOR(OFS_PARM1);
color = G_FLOAT(OFS_PARM2);
count = G_FLOAT(OFS_PARM3);
count = bound(0, count, 255);
color &= 0xff;
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, svc_particle);
MSG_WriteCoord (&sv.nqmulticast, org[0]);
@ -2701,6 +2705,7 @@ static void QCBUILTIN PF_particle (pubprogfuncs_t *prinst, globalvars_t *pr_glob
}
MSG_WriteByte (&sv.nqmulticast, count);
MSG_WriteByte (&sv.nqmulticast, color);
SV_MulticastProtExt(org, MULTICAST_PVS, pr_global_struct->dimension_send, 0, 0);
#endif
//for qw users (and not fte)
/* if (*prinst->callargc >= 5)
@ -2904,6 +2909,7 @@ static void QCBUILTIN PF_particle4 (pubprogfuncs_t *prinst, globalvars_t *pr_glo
static void QCBUILTIN PF_h2particleexplosion(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//used by the ice staff
Con_Printf("H2FIXME: PF_h2particleexplosion not implemented\n");
/*
float *org;
@ -9365,7 +9371,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not")},// (EXT_CSQC)
{"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns if the client is acting as the server (aka: listen server)")},//(EXT_CSQC)
{"SetListener", PF_Fixme, 0, 0, 0, 351, D("void(vector origin, vector forward, vector right, vector up, float inwater)", "Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default.")},// (EXT_CSQC)
{"SetListener", PF_Fixme, 0, 0, 0, 351, D("void(vector origin, vector forward, vector right, vector up, optional float inwater)", "Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default.")},// (EXT_CSQC)
{"registercommand", PF_Fixme, 0, 0, 0, 352, D("void(string cmdname)", "Register the given console command, for easy console use.\nConsole commands that are later used will invoke CSQC_ConsoleCommand.")},//(EXT_CSQC)
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
{"serverkey", PF_Fixme, 0, 0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string")},//
@ -10193,7 +10199,7 @@ void PR_DumpPlatform_f(void)
{"SpectatorDisconnect", "noref void()", QW|NQ, "Called when a spectator disconnects from the game."},
{"SpectatorThink", "noref void()", QW|NQ, "Called each frame for each spectator."},
{"SV_ParseClientCommand", "noref void(string cmd)", QW|NQ, "Provides QC with a way to intercept 'cmd foo' commands from the client. Very handy. Self will be set to the sending client, while the 'cmd' argument can be tokenize()d and each element retrieved via argv(argno). Unrecognised cmds MUST be passed on to the clientcommand builtin."},
{"SV_ParseConnectionlessPacket", "noref void(string sender, string body)", QW|NQ, "Provides QC with a way to communicate between servers, or with client server browsers. Sender is the sender's ip. Body is the body of the message. You'll need to add your own password/etc support as required. Self is not valid."},
{"SV_ParseConnectionlessPacket", "noref float(string sender, string body)", QW|NQ, "Provides QC with a way to communicate between servers, or with client server browsers. Sender is the sender's ip. Body is the body of the message. You'll need to add your own password/etc support as required. Self is not valid."},
{"SV_PausedTic", "noref void(float pauseduration)", QW|NQ, "For each frame that the server is paused, this function will be called to give the gamecode a chance to unpause the server again. the pauseduration argument says how long the server has been paused for (the time global is frozen and will not increment while paused). Self is not valid."},
{"SV_ShouldPause", "noref float(float newstatus)", QW|NQ, "Called to give the qc a change to block pause/unpause requests. Return false for the pause request to be ignored. newstatus is 1 if the user is trying to pause the game. For the duration of the call, self will be set to the player who tried to pause, or to world if it was triggered by a server-side event."},
{"ClassChangeWeapon", "noref void()", H2, "Hexen2 support. Called when cl_playerclass changes. Self is set to the player who is changing class."},
@ -10224,7 +10230,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_ConsoleLink", "noref float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself."},
{"CSQC_Ent_Update", "noref void(float isnew)", CS},
{"CSQC_Ent_Remove", "noref void()", CS},
{"CSQC_Event_Sound", "noref float(float entnum, float channel, float soundname, float vol, float attenuation, vector pos, float pitchmod)", CS},
{"CSQC_Event_Sound", "noref float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod)", CS},
// {"CSQC_ServerSound", "//void()", CS},
{"CSQC_LoadResource", "noref float(string resname, string restype)", CS, "Called each time some resource is being loaded. CSQC can invoke various draw calls to provide a loading screen, until WorldLoaded is called."},
{"CSQC_Parse_TempEntity", "noref float()", CS, "Please don't use this. Use CSQC_Parse_Event and multicasts instead."},

View File

@ -206,7 +206,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldvector(colormod,NULL)\
comfieldvector(glowmod,NULL)\
comfieldvector(gravitydir,"Specifies the direction in which gravity acts. Must be normalised. '0 0 0' also means down. Use '0 0 1' if you want the player to be able to run on ceilings.")\
comfieldfunction(camera_transform,".vector(vector org, vector ang)", NULL)\
comfieldfunction(camera_transform,".vector(vector org, vector ang)", "Provides portal transform information for portal surfaces attached to this entity. Also used to open up pvs in ssqc.")\
comfieldfloat(pmove_flags,NULL)/*EXT_CSQC_1*/\
comfieldfloat(geomtype,NULL)/*DP_...PHYSICS*/\
comfieldfloat(friction,NULL)/*DP_...PHYSICS*/\

View File

@ -891,7 +891,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
}
#endif
f = FS_OpenVFS (name, "wb", FS_GAME);
f = FS_OpenVFS (name, "wb", FS_GAMEONLY);
if (!f)
{
Con_TPrintf ("ERROR: couldn't open %s.\n", name);

View File

@ -5115,6 +5115,7 @@ void SV_InitLocal (void)
extern cvar_t pm_airstep;
extern cvar_t pm_walljump;
extern cvar_t pm_slidyslopes;
extern cvar_t pm_watersinkspeed;
SV_InitOperatorCommands ();
SV_UserInit ();
@ -5167,6 +5168,7 @@ void SV_InitLocal (void)
Cvar_Register (&sv_bigcoords, cvargroup_serverphysics);
Cvar_Register (&pm_bunnyspeedcap, cvargroup_serverphysics);
Cvar_Register (&pm_watersinkspeed, cvargroup_serverphysics);
Cvar_Register (&pm_ktjump, cvargroup_serverphysics);
Cvar_Register (&pm_slidefix, cvargroup_serverphysics);
Cvar_Register (&pm_slidyslopes, cvargroup_serverphysics);

View File

@ -62,6 +62,7 @@ cvar_t sv_stepheight = CVARAFD("pm_stepheight", "", "sv_stepheight", CVAR_SERV
cvar_t pm_ktjump = CVARF("pm_ktjump", "", CVAR_SERVERINFO);
cvar_t pm_bunnyspeedcap = CVARFD("pm_bunnyspeedcap", "", CVAR_SERVERINFO, "0 or 1, ish. If the player is traveling faster than this speed while turning, their velocity will be gracefully reduced to match their current maxspeed. You can still rocket-jump to gain high velocity, but turning will reduce your speed back to the max. This can be used to disable bunny hopping.");
cvar_t pm_watersinkspeed = CVARFD("pm_watersinkspeed", "", CVAR_SERVERINFO, "This is the speed tht players will sink at while inactive in water. Empty means 60.");
cvar_t pm_slidefix = CVARF("pm_slidefix", "", CVAR_SERVERINFO);
cvar_t pm_slidyslopes = CVARF("pm_slidyslopes", "", CVAR_SERVERINFO);
cvar_t pm_airstep = CVARF("pm_airstep", "", CVAR_SERVERINFO);
@ -707,7 +708,8 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
VectorSubtract (org2, org, move2);
VectorAdd (check->v->origin, move2, check->v->origin);
check->v->flags = (int)check->v->flags & ~FL_ONGROUND;
if (check->v->movetype != MOVETYPE_WALK)
check->v->flags = (int)check->v->flags & ~FL_ONGROUND;
// may have pushed them off an edge
if (PROG_TO_WEDICT(w->progs, check->v->groundentity) != pusher)
@ -726,13 +728,34 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
// if it is ok to leave in the old position, do it
// this is only relevent for riding entities, not pushed
// FIXME: this doesn't acount for rotation
VectorSubtract (check->v->origin, move, check->v->origin);
VectorCopy (pushed_p->origin, check->v->origin);
block = World_TestEntityPosition (w, check);
if (!block)
{
pushed_p--;
continue;
}
//okay, that didn't work, try pushing the against stuff
WPhys_PushEntity(w, check, move, 0);
block = World_TestEntityPosition (w, check);
if (!block)
continue;
VectorCopy(check->v->origin, move);
for (i = 0; i < 8 && block; i++)
{
//precision errors can strike when you least expect it. lets try and reduce them.
check->v->origin[0] = check->v->origin[0] + ((i&1)?-1:1)/8.0;
check->v->origin[1] = check->v->origin[1] + ((i&2)?-1:1)/8.0;
check->v->origin[2] = check->v->origin[2] + ((i&4)?-1:1)/8.0;
block = World_TestEntityPosition (w, check);
}
if (!block)
{
World_LinkEdict (w, check, false);
continue;
}
}
// if it is sitting on top. Do not block.
@ -743,7 +766,7 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
}
//these pushes are contents brushes, and are not solid. water cannot crush. the player just enters the water.
//but, the player will be moved along with the water.
//but, the player will be moved along with the water if possible.
if (pusher->v->skin < 0)
continue;
@ -2449,9 +2472,7 @@ void SV_SetMoveVars(void)
movevars.friction = sv_friction.value;
movevars.waterfriction = sv_waterfriction.value;
movevars.entgravity = 1.0;
if (*sv_stepheight.string)
movevars.stepheight = sv_stepheight.value;
else
movevars.stepheight = PM_DEFAULTSTEPHEIGHT;
movevars.stepheight = *sv_stepheight.string?sv_stepheight.value:PM_DEFAULTSTEPHEIGHT;
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
}
#endif

View File

@ -1197,7 +1197,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
MSG_WriteByte(msg, svcfte_choosesplitclient);
MSG_WriteByte(msg, pnum);
}
if (!client->lockangles && (client->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && client->delta_sequence != -1)
if (!client->lockangles && (client->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && client->delta_sequence != -1 && !client->viewent)
{
MSG_WriteByte (msg, svcfte_setangledelta);
for (i=0 ; i < 3 ; i++)

View File

@ -89,6 +89,7 @@ extern cvar_t pm_slidefix;
extern cvar_t pm_slidyslopes;
extern cvar_t pm_airstep;
extern cvar_t pm_walljump;
extern cvar_t pm_watersinkspeed;
cvar_t sv_pushplayers = SCVAR("sv_pushplayers", "0");
//yes, realip cvars need to be fully initialised or realip will be disabled
@ -5755,6 +5756,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
movevars.airstep = (pm_airstep.value != 0);
movevars.walljump = (pm_walljump.value);
movevars.slidyslopes = (pm_slidyslopes.value!=0);
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
for (i=0 ; i<3 ; i++)
{
@ -5946,6 +5948,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
movevars.airstep = (pm_airstep.value != 0);
movevars.walljump = (pm_walljump.value);
movevars.slidyslopes = (pm_slidyslopes.value!=0);
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
if (sv_player->xv->hasted)
movevars.maxspeed*=sv_player->xv->hasted;

View File

@ -888,7 +888,7 @@ wedict_t *World_TestEntityPosition (world_t *w, wedict_t *ent)
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, ent->v->origin, ((ent->v->solid == SOLID_NOT || ent->v->solid == SOLID_TRIGGER)?MOVE_NOMONSTERS:0), ent);
if (trace.startsolid)
return w->edicts;
return trace.ent?trace.ent:w->edicts;
return NULL;
}
@ -1731,7 +1731,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
clip.maxs = maxs;
clip.type = type;
clip.passedict = passedict;
clip.hullnum = hullnum;
clip.hullnum = 0;//hullnum; //BUG: hexen2's SV_ClipMoveToEntity's move_ent argument is set inconsistantly. This has the effect that the SOLID_BSP's .hull field is used instead of the SOLID_BBOX entity. We can't fix this because hexen2 depends upon it - this is the 'tibet5' bug.
#ifdef Q2SERVER
clip.q2passedict = NULL;
#endif