From b0ed15f1cd87dbffd3454fe9cbcd756ff836ca6e Mon Sep 17 00:00:00 2001 From: driAn Date: Tue, 25 Dec 2007 15:01:29 +0000 Subject: [PATCH] crouch on slopes/stairs, fixed crouch anim git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1484 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/clients2c.cpp | 2 +- source/src/entity.h | 18 ++++++++++++++++-- source/src/physics.cpp | 34 ++++++++++++++++++++++++---------- source/src/protos.h | 1 + source/src/weapon.cpp | 10 +++++----- 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 56743828..cb85ae39 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -86,7 +86,7 @@ void parsepositions(ucharbuf &p) f >>= 1; d->onladder = f&1; f >>= 2; - d->crouching = f&1; + updatecrouch(d, f&1); updatepos(d); updatelagtime(d); if(d->state==CS_LAGGED || d->state==CS_SPAWNING) d->state = CS_ALIVE; diff --git a/source/src/entity.h b/source/src/entity.h index 228466f8..233be986 100644 --- a/source/src/entity.h +++ b/source/src/entity.h @@ -97,11 +97,12 @@ struct physent float radius, eyeheight, aboveeye; // bounding box size bool inwater; bool onfloor, onladder, jumpnext, crouching; + int lastcrouch; char move, strafe; uchar state, type; physent() : o(0, 0, 0), yaw(270), pitch(0), roll(0), pitchvel(0), - state(CS_ALIVE) + state(CS_ALIVE), crouching(false), lastcrouch(0) { reset(); } @@ -115,7 +116,20 @@ struct physent onfloor = onladder = inwater = jumpnext = crouching = false; } - virtual float dyneyeheight() { return crouching ? eyeheight*3.0f/4.0f : eyeheight; } + virtual float dyneyeheight() + { + extern int lastmillis, crouchtime; + const float croucheyeheight = eyeheight*3.0f/4.0f; + const float t = (lastmillis-lastcrouch)/(float)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 + } }; struct dynent : physent // animated ent diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 8c1c013c..3b8c04ef 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -65,13 +65,14 @@ bool plcollide(physent *d, physent *o, float &headspace, float &hi, float &lo) { if(o->state!=CS_ALIVE) 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(); if(d->type==ENT_PLAYER && o->type==ENT_PLAYER ? dx*dx + dy*dy < r*r : fabs(dx)o.z-d->dyneyeheight()o.z-o->dyneyeheight()) { if(o->o.z-o->dyneyeheight()o.z-o->dyneyeheight()-1; } + if(d->o.z-deyeheighto.z-oeyeheight) { if(o->o.z-oeyeheighto.z-oeyeheight-1; } else if(o->o.z+o->aboveeye>lo) lo = o->o.z+o->aboveeye+1; - if(fabs(o->o.z-d->o.z)aboveeye+d->dyneyeheight()) { hitplayer = o; return false; } - headspace = d->o.z-o->o.z-o->aboveeye-d->dyneyeheight(); + if(fabs(o->o.z-d->o.z)aboveeye+deyeheight) { hitplayer = o; return false; } + headspace = d->o.z-o->o.z-o->aboveeye-deyeheight; if(headspace<0) headspace = 10; } return true; @@ -115,6 +116,9 @@ void mmcollide(physent *d, float &hi, float &lo) // collide with a map } } +// TESTME +VARP(crouchtime, 1, 200, 20000); + // all collision happens here // spawn is a dirty side effect used in spawning // drop & rise are supplied by the physics below to indicate gravity/push for current mini-timestep @@ -130,6 +134,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(); for(int x = x1; x<=x2; x++) for(int y = y1; y<=y2; y++) // collide with map { @@ -165,7 +170,7 @@ bool collide(physent *d, bool spawn, float drop, float rise) if(floor>lo) lo = floor; } - if(hi-lo < d->dyneyeheight()+d->aboveeye) return false; + if(hi-lo < eyeheight + d->aboveeye) return false; // Modified by Rick: plcollide now takes hi and lo in account aswell, that way we can jump/walk on players @@ -184,19 +189,19 @@ bool collide(physent *d, bool spawn, float drop, float rise) if(spawn) { - d->o.z = lo+d->dyneyeheight(); // just drop to floor (sideeffect) + d->o.z = lo+eyeheight; // just drop to floor (sideeffect) d->onfloor = true; } else { - const float spacelo = d->o.z-d->dyneyeheight()-lo; + const float spacelo = d->o.z-eyeheight-lo; if(spacelo<0) { if(spacelo>-0.01) { - d->o.z = lo+d->dyneyeheight(); // stick on step + d->o.z = lo+eyeheight; // stick on step } - else if(spacelo>-1.26f && d->type!=ENT_BOUNCE && !d->crouching) d->o.z += rise; // rise thru stair + else if(spacelo>-1.26f && d->type!=ENT_BOUNCE) d->o.z += rise; // rise thru stair else return false; } else @@ -212,7 +217,7 @@ bool collide(physent *d, bool spawn, float drop, float rise) d->vel.z = 0; // cancel out jumping velocity } - d->onfloor = d->o.z-d->dyneyeheight()-lo<0.01f; + d->onfloor = d->o.z-eyeheight-lo < (lastmillis-d->lastcrouch<=crouchtime ? 0.1f : 0.01f); } return true; } @@ -497,10 +502,19 @@ void jumpn(bool on) else player1->jumpnext = on; } +void updatecrouch(playerent *p, bool on) +{ + if(p->crouching == on) return; + p->crouching = on; + const int progress = lastmillis-p->lastcrouch; + if(progress > crouchtime) p->lastcrouch = lastmillis; // new crouch + else p->lastcrouch = lastmillis-(crouchtime-progress); // only change direction, fix progress time +} + void crouch(bool on) { if(intermission || player1->onladder || (on && !player1->onfloor && player1->timeinair > 50)) return; - player1->crouching = on; + updatecrouch(player1, on); } COMMAND(backward, ARG_DOWN); diff --git a/source/src/protos.h b/source/src/protos.h index f463367c..541c7d05 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -342,6 +342,7 @@ extern void physicsframe(); extern void mousemove(int dx, int dy); extern void fixcamerarange(physent *cam = camera1); extern float floor(short x, short y); +extern void updatecrouch(playerent *p, bool on); // sound extern void playsound(int n, physent *p = NULL, entity *ent = NULL, const vec *loc = NULL); diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index e3c37708..57325166 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -146,9 +146,10 @@ 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(); vec o(d->o); - o.z += (d->aboveeye - d->dyneyeheight())/2; - return intersect(o, vec(d->radius, d->radius, (d->aboveeye + d->dyneyeheight())/2), from, to, end); + o.z += (d->aboveeye - eyeheight)/2; + return intersect(o, vec(d->radius, d->radius, (d->aboveeye + eyeheight)/2), from, to, end); } bool intersect(entity *e, const vec &from, const vec &to, vec *end) @@ -540,8 +541,7 @@ void weapon::sendshoot(vec &from, vec &to) bool weapon::modelattacking() { - // FIXME!!! - int animtime = info.attackdelay; //min(owner->gunwait[owner->weaponsel->type], owner->weaponsel->info.attackdelay); + int animtime = min(owner->gunwait[owner->weaponsel->type], owner->weaponsel->info.attackdelay); if(lastmillis - owner->lastaction < animtime) return true; else return false; } @@ -648,7 +648,7 @@ struct grenadeent : bounceent void explode() { - static vec n(0,0,0); + static vec n(0,0,0); if(bouncestate != NADE_THROWED) owner->weapons[GUN_GRENADE]->attack(n); playsound(S_FEXPLODE, NULL, NULL, &o); newprojectile(o, o, 1, owner==player1, owner, GUN_GRENADE, millis);