diff --git a/source/src/bot/ac_bot_ai.cpp b/source/src/bot/ac_bot_ai.cpp index 24ec4ef6..dacb7f4b 100644 --- a/source/src/bot/ac_bot_ai.cpp +++ b/source/src/bot/ac_bot_ai.cpp @@ -120,7 +120,7 @@ entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight) { sScore = 0; entity &e = ents[i]; - vec o(e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight()); + vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); if (!ents[i].spawned) continue; if (OUTBORD(e.x, e.y)) continue; @@ -234,7 +234,7 @@ entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight) m_vGoal.x = pNewTargetEnt->x; m_vGoal.y = pNewTargetEnt->y; - m_vGoal.z = S(pNewTargetEnt->x, pNewTargetEnt->y)->floor+player1->dyneyeheight(); + m_vGoal.z = S(pNewTargetEnt->x, pNewTargetEnt->y)->floor+player1->eyeheight; } return pNewTargetEnt; @@ -245,7 +245,7 @@ bool CACBot::HeadToTargetEnt() if (m_pTargetEnt) { vec o(m_pTargetEnt->x, m_pTargetEnt->y, - S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->dyneyeheight()); + S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight); if (m_pTargetEnt->spawned && (!UnderWater(m_pMyEnt->o) || !UnderWater(o))) diff --git a/source/src/bot/bot_ai.cpp b/source/src/bot/bot_ai.cpp index 0a81584e..234977fd 100644 --- a/source/src/bot/bot_ai.cpp +++ b/source/src/bot/bot_ai.cpp @@ -982,7 +982,7 @@ void CBot::DoCombatNav() { // Bot has already found an entity, still valid? vec v(m_pTargetEnt->x, m_pTargetEnt->y, - S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->dyneyeheight()); + S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight); if ((GetDistance(v) > 25.0f) || !IsVisible(m_pTargetEnt)) m_pTargetEnt = NULL; } @@ -1003,7 +1003,7 @@ void CBot::DoCombatNav() { condebug("Combat ent"); vec v(m_pTargetEnt->x, m_pTargetEnt->y, - S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->dyneyeheight()); + S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight); debugbeam(m_pMyEnt->o, v); diff --git a/source/src/bot/bot_waypoint.cpp b/source/src/bot/bot_waypoint.cpp index dc4b2a7c..bc90c56c 100644 --- a/source/src/bot/bot_waypoint.cpp +++ b/source/src/bot/bot_waypoint.cpp @@ -1712,7 +1712,7 @@ void CCubeWaypointClass::StartFlood() if (e.type == TELEPORT) { - vec telepos = { e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight() }, teledestpos = g_vecZero; + vec telepos = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }, teledestpos = g_vecZero; // Find the teleport destination int n = -1, tag = e.attr1, beenhere = -1; @@ -1725,7 +1725,7 @@ void CCubeWaypointClass::StartFlood() { teledestpos.x = ents[n].x; teledestpos.y = ents[n].y; - teledestpos.z = S(ents[n].x, ents[n].y)->floor+player1->dyneyeheight(); + teledestpos.z = S(ents[n].x, ents[n].y)->floor+player1->eyeheight; break; } } @@ -1764,7 +1764,7 @@ void CCubeWaypointClass::StartFlood() } else if (e.type == CARROT) { - vec pos = { e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight() }; + vec pos = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; int flags = (W_FL_FLOOD | W_FL_TRIGGER); if (S(e.x, e.y)->tag) flags |= W_FL_INTAG; @@ -1832,7 +1832,7 @@ void CCubeWaypointClass::CreateWPsAtTeleporters() if (e.type != TELEPORT) continue; if (OUTBORD(e.x, e.y)) continue; - vec telepos = { e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight() }, teledestpos = g_vecZero; + vec telepos = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }, teledestpos = g_vecZero; // Find the teleport destination int n = -1, tag = e.attr1, beenhere = -1; @@ -1845,7 +1845,7 @@ void CCubeWaypointClass::CreateWPsAtTeleporters() { teledestpos.x = ents[n].x; teledestpos.y = ents[n].y; - teledestpos.z = S(ents[n].x, ents[n].y)->floor+player1->dyneyeheight(); + teledestpos.z = S(ents[n].x, ents[n].y)->floor+player1->eyeheight; break; } } @@ -1877,7 +1877,7 @@ void CCubeWaypointClass::CreateWPsAtTriggers() if (e.type != CARROT) continue; if (OUTBORD(e.x, e.y)) continue; - vec pos = { e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight() }; + vec pos = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; node_s *wp = AddWaypoint(pos, false); @@ -2398,7 +2398,7 @@ bool CBot::HeadToWaypoint() { // Check if bot has to jump vec from = m_pMyEnt->o; - from.z -= (m_pMyEnt->dyneyeheight() - 1.25f); + from.z -= (m_pMyEnt->eyeheight - 1.25f); float flEndDist; if (!IsVisible(from, FORWARD, 3.0f, false, &flEndDist) && (GetDistance(from, m_pCurrentWaypoint->pNode->v_origin) > flEndDist)) diff --git a/source/src/bot/botmanager.cpp b/source/src/bot/botmanager.cpp index b64e779a..e9fb1c91 100644 --- a/source/src/bot/botmanager.cpp +++ b/source/src/bot/botmanager.cpp @@ -858,7 +858,7 @@ void CBotManager::PickNextTrigger() #endif if (OUTBORD(e.x, e.y)) continue; - vec o(e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight()); + vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); node_s *pWptNearEnt = NULL; @@ -1186,7 +1186,7 @@ void drawbeamtocarrots() loopv(ents) { entity &e = ents[i]; - vec o = { e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight() }; + vec o = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; if ((e.type != CARROT) || !e.spawned) continue; particle_trail(1, 500, player1->o, o); } @@ -1199,7 +1199,7 @@ void drawbeamtoteleporters() loopv(ents) { entity &e = ents[i]; - vec o = { e.x, e.y, S(e.x, e.y)->floor+player1->dyneyeheight() }; + vec o = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; if (e.type != TELEPORT) continue; particle_trail(1, 500, player1->o, o); } @@ -1253,7 +1253,7 @@ void testvisible(int iDir) } vec from = player1->o; - from.z -= (player1->dyneyeheight() - 1.25f); + from.z -= (player1->eyeheight - 1.25f); end = from; makevec(&angles, player1->pitch, player1->yaw, player1->roll); angles.x=0; diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 37dff2fc..3ddc558b 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -37,7 +37,7 @@ void updatepos(playerent *d) const float dx = player1->o.x-d->o.x; const float dy = player1->o.y-d->o.y; const float dz = player1->o.z-d->o.z; - const float rz = player1->aboveeye+d->dyneyeheight(); + const float rz = player1->aboveeye+d->eyeheight; const float fx = (float)fabs(dx), fy = (float)fabs(dy), fz = (float)fabs(dz); if(fxstate!=CS_DEAD) { diff --git a/source/src/entities.cpp b/source/src/entities.cpp index 6e0fa31d..901a9e16 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -3,8 +3,6 @@ #include "pch.h" #include "cube.h" -const int physent::crouchtime = 200; - vector ents; const char *entnames[] = @@ -188,7 +186,7 @@ void checkitems(playerent *d) { if(editmode || d->state!=CS_ALIVE) return; d->onladder = false; - float eyeheight = d->dyneyeheight(); + float eyeheight = d->eyeheight; loopv(ents) { entity &e = ents[i]; @@ -388,7 +386,7 @@ void flagdropped(int flag, short x, short y, short z) p.o.y = y; p.o.z = z; p.vel.z = -0.8f; - p.aboveeye = p.eyeheight = 0.4f; + p.aboveeye = p.eyeheight = p.maxeyeheight = 0.4f; p.radius = 0.1f; bool oldcancollide = false; diff --git a/source/src/entity.h b/source/src/entity.h index 368a30ce..e5699a82 100644 --- a/source/src/entity.h +++ b/source/src/entity.h @@ -97,17 +97,16 @@ struct physent float pitchvel; float maxspeed; // cubes per second, 24 for player int timeinair; // used for fake gravity - float radius, eyeheight, aboveeye; // bounding box size + float radius, eyeheight, maxeyeheight, aboveeye; // bounding box size bool inwater; bool onfloor, onladder, jumpnext, crouching, trycrouch, cancollide, stuck; - int lastcrouch, lastsplash; + int lastsplash; char move, strafe; uchar state, type; - static const int crouchtime; - float lastspacehi; + float eyeheightvel; physent() : o(0, 0, 0), deltapos(0, 0, 0), newpos(0, 0, 0), yaw(270), pitch(0), roll(0), pitchvel(0), - crouching(false), trycrouch(false), cancollide(true), stuck(false), lastcrouch(0), lastsplash(0), state(CS_ALIVE) + crouching(false), trycrouch(false), cancollide(true), stuck(false), lastsplash(0), state(CS_ALIVE) { reset(); } @@ -121,27 +120,12 @@ struct physent void reset() { - vel.x = vel.y = vel.z = lastspacehi = 0.0f; + vel.x = vel.y = vel.z = eyeheightvel = 0.0f; move = strafe = 0; - timeinair = lastcrouch = lastsplash = 0; + timeinair = lastsplash = 0; onfloor = onladder = inwater = jumpnext = crouching = trycrouch = stuck = false; } - virtual float dyneyeheight() const - { - extern int lastmillis; - const float croucheyeheight = eyeheight*3.0f/4.0f; - const float t = (lastmillis-lastcrouch)/(float)physent::crouchtime; - - if(lastcrouch && t < 1.0f && t >= 0.0f) // crouch move in progress - { - if(crouching) return eyeheight - t*(eyeheight-croucheyeheight); // crouch - else return croucheyeheight + t*(eyeheight-croucheyeheight); // uncrouch - } - else if(crouching) return croucheyeheight; // fully crouching - return eyeheight; // not crouching - } - virtual void oncollision() {}; virtual void onmoved(const vec &dist) {}; }; @@ -355,7 +339,7 @@ struct playerent : dynent, playerstate int spectatemode, followplayercn; int eardamagemillis; int respawnoffset, lastteamchange; - virtual float dyneyeheight() const { return (state==CS_DEAD || state==CS_SPECTATE) && spectatemode==SM_FLY ? 1.0f : physent::dyneyeheight(); } + //virtual float eyeheight const { return (state==CS_DEAD || state==CS_SPECTATE) && spectatemode==SM_FLY ? 1.0f : physent::eyeheight; } bool allowmove() { return state!=CS_DEAD || spectatemode==SM_FLY; } weapon *weapons[NUMGUNS]; @@ -373,7 +357,7 @@ struct playerent : dynent, playerstate { type = ENT_PLAYER; name[0] = team[0] = 0; - eyeheight = 4.5f; + eyeheight = maxeyeheight = 4.5f; aboveeye = 0.7f; radius = 1.1f; maxspeed = 16.0f; @@ -498,7 +482,7 @@ struct bounceent : physent // nades, gibs type = ENT_BOUNCE; maxspeed = 40; radius = 0.2f; - eyeheight = 0.3f; + eyeheight = maxeyeheight = 0.3f; aboveeye = 0.0f; } diff --git a/source/src/physics.cpp b/source/src/physics.cpp index db8a7155..9920b4d4 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -76,7 +76,7 @@ bool plcollide(physent *d, physent *o, float &headspace, float &hi, float &lo) { if(o->state!=CS_ALIVE || !o->cancollide) return true; const float r = o->radius+d->radius, dx = o->o.x-d->o.x, dy = o->o.y-d->o.y; - const float deyeheight = d->dyneyeheight(), oeyeheight = o->dyneyeheight(); + const float deyeheight = d->eyeheight, oeyeheight = o->eyeheight; if(d->type==ENT_PLAYER && o->type==ENT_PLAYER ? dx*dx + dy*dy < r*r : fabs(dx)o.z-deyeheighto.z-oeyeheight) { if(o->o.z-oeyeheighto.z-oeyeheight-1; } @@ -109,7 +109,7 @@ bool cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by, int &bs bool mmcollide(physent *d, float &hi, float &lo) // collide with a mapmodel { - const float eyeheight = d->dyneyeheight(); + const float eyeheight = d->eyeheight; const float playerheight = eyeheight + d->aboveeye; loopv(ents) { @@ -160,7 +160,7 @@ bool collide(physent *d, bool spawn, float drop, float rise) const int x2 = int(fx2); const int y2 = int(fy2); float hi = 127, lo = -128; - const float eyeheight = d->dyneyeheight(); + const float eyeheight = d->eyeheight; const float playerheight = eyeheight + d->aboveeye; for(int x = x1; x<=x2; x++) for(int y = y1; y<=y2; y++) // collide with map @@ -244,8 +244,8 @@ bool collide(physent *d, bool spawn, float drop, float rise) d->vel.z = 0; // cancel out jumping velocity } - d->onfloor = d->o.z-eyeheight-lo < (lastmillis-d->lastcrouch<=physent::crouchtime ? 0.1f : 0.01f); - d->lastspacehi = spacehi; + const float floorclamp = d->crouching ? 0.1f : 0.01f; + d->onfloor = d->o.z-eyeheight-lo < floorclamp; } return true; } @@ -259,6 +259,36 @@ float floor(short x, short y) VARP(maxroll, 0, 0, 20); VAR(recoilbackfade, 0, 100, 1000); +void resizephysent(physent *pl, int moveres, int curtime, float min, float max) +{ + float drop = 0.0f, rise = 0.0f; + const bool water = hdr.waterlevel>pl->o.z; + const float speed = curtime*pl->maxspeed/(water ? 2000.0f : 1000.0f); + float h = pl->eyeheightvel; + h *= speed; + + loopi(moveres) + { + const float f = 1.0f/moveres; + pl->eyeheight += f*h; + if(!collide(pl, false, drop, rise)) + { + pl->eyeheight -= f*h; // collided, revert mini-step + break; + } + if(pl->eyeheighteyeheight = min; + break; + } + if(pl->eyeheight>max) + { + pl->eyeheight = max; + break; + } + } +} + // main physics routine, moves a player/monster for a curtime step // moveres indicated the physics precision (which is lower for monsters and multiplayer prediction) // local is false for multiplayer prediction @@ -317,9 +347,6 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) int move = pl->onladder && !pl->onfloor && pl->move == -1 ? 0 : pl->move; // movement on ladder water = hdr.waterlevel>pl->o.z-0.5f; - // test local crouch - if(pl == player1 && !(intermission || player1->onladder || (pl->trycrouch && !player1->onfloor && player1->timeinair > 50))) updatecrouch(player1, player1->trycrouch); - const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed*(pl->crouching ? 0.5f : 1.0f); const float friction = water ? 20.0f : (pl->onfloor || editfly || specfly ? 6.0f : (pl->onladder ? 1.5f : 30.0f)); const float fpsfric = max(friction/curtime*20.0f, 1.0f); @@ -537,6 +564,14 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) // Added by Rick: Easy hack to store previous locations of all players/monsters/bots if(pl->type==ENT_PLAYER || pl->type==ENT_BOT) ((playerent *)pl)->history.update(pl->o, lastmillis); // End add + + // apply volume-resize when crouching + if(pl->type==ENT_PLAYER) + { + if(pl==player1 && !(intermission || player1->onladder || (pl->trycrouch && !player1->onfloor && player1->timeinair > 50))) updatecrouch(player1, player1->trycrouch); + const float croucheyeheight = pl->maxeyeheight*3.0f/4.0f; + resizephysent(pl, moveres, curtime, croucheyeheight, pl->maxeyeheight); + } } const int PHYSFPS = 200; @@ -629,11 +664,9 @@ void jumpn(bool on) void updatecrouch(playerent *p, bool on) { if(p->crouching == on) return; - if(p==player1 && p->lastspacehi<1.0f && !on) return; + const float crouchspeed = 5.625f; p->crouching = on; - const int progress = lastmillis-p->lastcrouch; - if(progress > physent::crouchtime) p->lastcrouch = lastmillis; // new crouch - else p->lastcrouch = lastmillis-(physent::crouchtime-progress); // only change direction, fix progress time + p->eyeheightvel = on ? -crouchspeed : crouchspeed; } void crouch(bool on) { player1->trycrouch = on; } diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index 42e598e4..2952ac88 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -340,7 +340,7 @@ void rendermodel(const char *mdl, int anim, int tex, float rad, const vec &o, fl if(stenciling && d && !raycubelos(camera1->o, o, d->radius)) { vec target(o); - target.z += d->dyneyeheight(); + target.z += d->eyeheight; if(!raycubelos(camera1->o, target, d->radius)) return; } @@ -504,7 +504,7 @@ void renderclient(playerent *d, const char *mdlname, const char *vwepname, int t int anim = ANIM_IDLE|ANIM_LOOP; float speed = 0.0; vec o(d->o); - o.z -= d->dyneyeheight(); + o.z -= d->eyeheight; int basetime = -((int)(size_t)d&0xFFF); if(d->state==CS_DEAD) { diff --git a/source/src/sound.cpp b/source/src/sound.cpp index 9ff2d9dc..2bf4cf90 100644 --- a/source/src/sound.cpp +++ b/source/src/sound.cpp @@ -1530,7 +1530,7 @@ void updateplayerfootsteps(playerent *p) // play footsteps int grounddist = hdr.waterlevel-S((int)p->o.x, (int)p->o.y)->floor; - bool water = p->o.z-p->dyneyeheight()+0.25fo.z-p->eyeheight+0.25fp->eyeheight) return; // don't play step sound when jumping into water int stepsound; diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index b8a3c6f5..ed5834de 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -169,7 +169,7 @@ static inline bool intersect(const vec &o, const vec &rad, const vec &from, cons bool intersect(dynent *d, const vec &from, const vec &to, vec *end) { - const float eyeheight = d->dyneyeheight(); + const float eyeheight = d->eyeheight; vec o(d->o); o.z += (d->aboveeye - eyeheight)/2; return intersect(o, vec(d->radius, d->radius, (d->aboveeye + eyeheight)/2), from, to, end); @@ -259,7 +259,7 @@ void hitpush(int damage, playerent *d, playerent *at, vec &from, vec &to, int gu float expdist(playerent *o, vec &dir, const vec &v) { vec middle = o->o; - middle.z += (o->aboveeye-o->dyneyeheight())/2; + middle.z += (o->aboveeye-o->eyeheight)/2; float dist = middle.dist(v, dir); dir.div(dist); if(dist<0) dist = 0;