From 3928c635a7e7e0b98dd312d1d223c63164594a2a Mon Sep 17 00:00:00 2001 From: driAn Date: Sat, 11 Mar 2006 20:47:11 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@216 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/clientextras.cpp | 5 +- source/src/clientgame.cpp | 8 +- source/src/clients2c.cpp | 6 +- source/src/cube.h | 10 +- source/src/main.cpp | 3 +- source/src/menus.cpp | 2 +- source/src/physics.cpp | 493 +------------------------------- source/src/renderextras.cpp | 551 +++--------------------------------- source/src/rendergl.cpp | 420 +-------------------------- source/src/rendermd2.cpp | 2 +- source/src/weapon.cpp | 191 +++++++------ 11 files changed, 166 insertions(+), 1525 deletions(-) diff --git a/source/src/clientextras.cpp b/source/src/clientextras.cpp index c0325bde..0a42cb45 100644 --- a/source/src/clientextras.cpp +++ b/source/src/clientextras.cpp @@ -16,7 +16,8 @@ void renderclient(dynent *d, bool team, char *mdlname, bool vwep, float scale) float mz = d->o.z-d->eyeheight+1.55f*scale; int basetime = -((int)d&0xFFF); if(d->state==CS_DEAD) - { + { + d->pitch = 90.0f; //if(vwep) mz = S((int)d->o.x, (int)d->o.y)->floor; int r; n = (int)d%3; r = range[n]; @@ -69,7 +70,7 @@ void renderclients() renderclient(d, isteam(player1->team, d->team), "playermodels/terrorist", false, 1.4f); } - if(d->gunselect>0 && d->gunselectgunselect>=0 && d->gunselectgunselect]); renderclient(d, isteam(player1->team, d->team), vwep, true, 1.4f); diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index d64787f6..4c91a4d9 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -316,10 +316,12 @@ void mphysents() loopv(physents) if(physents[i]) { physent *p = physents[i]; - if(p->throwed) moveplayer(p, 2, false); - if(lastmillis - p->millis >= p->lifetime) + if(p->state == NADE_THROWED) moveplayer(p, 2, false); +// printf("physent %i: %i %i %i\n", i, lastmillis, p->millis, p->timetolife); + + if(lastmillis - p->millis >= p->timetolife) { - explode_nade(physents[i]); + if(p->state==NADE_ACTIVATED || p->state==NADE_THROWED) explode_nade(physents[i]); physents.remove(i); i--; }; diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 7d82007c..738dce1e 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -183,9 +183,9 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th e.y = getint(p)/DMF; e.z = getint(p)/DMF; if(gun==GUN_SHOTGUN) createrays(s, e); - int nadesec = getint(p)*100; - printf("nadesec: %i\n", nadesec); - shootv(gun, s, e, d, nadesec); + int nademillis = getint(p)*100; + printf("nadesec: %i\n", nademillis); + shootv(gun, s, e, d, nademillis); break; }; diff --git a/source/src/cube.h b/source/src/cube.h index 7bedc2d3..1bba97c1 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -168,14 +168,14 @@ struct dynent // players & monsters md3state animstate[3]; int gravity; - bool bounce; + bool isphysent; // hack }; -struct physent : dynent // inheritance: tons of unused stuff, but makes life easier +enum { PHYSENT_NONE = 0, NADE_ACTIVATED, NADE_THROWED }; + +struct physent : dynent // nades, gibs { - int millis, lifetime; - bool throwed; - bool enabled; + int millis, timetolife, state; // see enum above dynent *owner; }; diff --git a/source/src/main.cpp b/source/src/main.cpp index 9eeec233..ec84ee33 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -164,7 +164,8 @@ int main(int argc, char **argv) !installtex(8, path(newstring("packages/misc/martin/ball2.png")), xs, ys) || !installtex(9, path(newstring("packages/misc/martin/ball3.png")), xs, ys) || !installtex(4, path(newstring("packages/misc/explosion.jpg")), xs, ys) || - !installtex(5, path(newstring("packages/misc/items.png")), xs, ys) || + !installtex(5, path(newstring("packages/misc/items.png")), xs, ys) || + !installtex(10, path(newstring("packages/misc/scope.png")), xs, ys) || !installtex(1, path(newstring("packages/misc/crosshairs/default.png")), xs, ys)) fatal("could not find core textures (hint: run cube from the parent of the bin directory)"); log("sound"); diff --git a/source/src/menus.cpp b/source/src/menus.cpp index e5dbf2e8..c12a4e47 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -2,7 +2,7 @@ #include "cube.h" -#define FIRSTMENU 90 +#define FIRSTMENU 120 struct mitem { char *text, *action, *hoveraction; }; diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 9ef01478..22c72794 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -1,965 +1,484 @@ // physics.cpp: no physics books were hurt nor consulted in the construction of this code. - // All physics computations and constants were invented on the fly and simply tweaked until - // they "felt right", and have no basis in reality. Collision detection is simplistic but - // very robust (uses discrete steps at fixed fps). - - #include "cube.h" - - bool plcollide(dynent *d, dynent *o, float &headspace) // collide with player or monster - { - if(o->state!=CS_ALIVE) return true; - const float r = o->radius+d->radius; - if(fabs(o->o.x-d->o.x)o.y-d->o.y)o.z-d->o.z)aboveeye+d->eyeheight) return false; - if(d->monsterstate) return false; // hack - headspace = d->o.z-o->o.z-o->aboveeye-d->eyeheight; - if(headspace<0) headspace = 10; - }; - return true; - }; - - bool cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by, int &bs) // recursively collide with a mipmapped corner cube - { - sqr *w = wmip[mip]; - int sz = ssize>>mip; - bool stest = SOLID(SWS(w, x+dx, y, sz)) && SOLID(SWS(w, x, y+dy, sz)); - mip++; - x /= 2; - y /= 2; - if(SWS(wmip[mip], x, y, ssize>>mip)->type==CORNER) - { - bx = x<radius; - if(fabs(e.x-d->o.x)o.y)floor+mmi.zoff+e.attr3); - if(d->o.z-d->eyeheightlo) lo = mmz+mmi.h; - }; - }; - }; - - // 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 - - bool collide(dynent *d, bool spawn, float drop, float rise) - { - const float fx1 = d->o.x-d->radius; // figure out integer cube rectangle this entity covers in map - const float fy1 = d->o.y-d->radius; - const float fx2 = d->o.x+d->radius; - const float fy2 = d->o.y+d->radius; - const int x1 = fast_f2nat(fx1); - const int y1 = fast_f2nat(fy1); - const int x2 = fast_f2nat(fx2); - const int y2 = fast_f2nat(fy2); - float hi = 127, lo = -128; - float minfloor = (d->monsterstate && !spawn && d->health>100) ? d->o.z-d->eyeheight-4.5f : -1000.0f; // big monsters are afraid of heights, unless angry :) - - for(int x = x1; x<=x2; x++) for(int y = y1; y<=y2; y++) // collide with map - { - if(OUTBORD(x,y)) return false; - sqr *s = S(x,y); - float ceil = s->ceil; - float floor = s->floor; - switch(s->type) - { - case SOLID: - return false; - - case CORNER: - { - int bx = x, by = y, bs = 1; - if(x==x1 && y==y1 && cornertest(0, x, y, -1, -1, bx, by, bs) && fx1-bx+fy1-by<=bs - || x==x2 && y==y1 && cornertest(0, x, y, 1, -1, bx, by, bs) && fx2-bx>=fy1-by - || x==x1 && y==y2 && cornertest(0, x, y, -1, 1, bx, by, bs) && fx1-bx<=fy2-by - || x==x2 && y==y2 && cornertest(0, x, y, 1, 1, bx, by, bs) && fx2-bx+fy2-by>=bs) - return false; - break; - }; - - case FHF: // FIXME: too simplistic collision with slopes, makes it feels like tiny stairs - floor -= (s->vdelta+S(x+1,y)->vdelta+S(x,y+1)->vdelta+S(x+1,y+1)->vdelta)/16.0f; - break; - - case CHF: - ceil += (s->vdelta+S(x+1,y)->vdelta+S(x,y+1)->vdelta+S(x+1,y+1)->vdelta)/16.0f; - - }; - if(ceillo) lo = floor; - if(flooreyeheight+d->aboveeye) return false; - - float headspace = 10; - loopv(players) // collide with other players - { - dynent *o = players[i]; - if(!o || o==d) continue; - if(!plcollide(d, o, headspace)) return false; - }; - if(d!=player1 && d->mtype!=M_NADE) if(!plcollide(d, player1, headspace)) return false; - headspace -= 0.01f; - - mmcollide(d, hi, lo); // collide with map models - - if(spawn) - { - d->o.z = lo+d->eyeheight; // just drop to floor (sideeffect) - d->startheight = d->o.z; //no falling damage on spawn - d->onfloor = true; - } - else - { - const float space = d->o.z-d->eyeheight-lo; - if(space<0) - { - if(space>-0.01) - { - d->o.z = lo+d->eyeheight; // stick on step - } - else if(space>-1.26f) d->o.z += rise; // rise thru stair - else return false; - } - else - { - d->o.z -= min(min(drop, space), headspace); // gravity - }; - - const float space2 = hi-(d->o.z+d->aboveeye); - if(space2<0) - { - if(space2<-0.1) return false; // hack alert! - d->o.z = hi-d->aboveeye; // glue to ceiling - d->vel.z = 0; // cancel out jumping velocity - }; - - d->onfloor = d->o.z-d->eyeheight-lo<0.01f; - }; - return true; - } - - float rad(float x) { return x*3.14159f/180; }; - - VAR(maxroll, 0, 3, 20); - - int physicsfraction = 0, physicsrepeat = 0; - const int MINFRAMETIME = 20; // physics always simulated at 50fps or better - - void physicsframe() // optimally schedule physics frames inside the graphics frames - { - if(curtime>=MINFRAMETIME) - { - int faketime = curtime+physicsfraction; - physicsrepeat = faketime/MINFRAMETIME; - physicsfraction = faketime-physicsrepeat*MINFRAMETIME; - } - else - { - physicsrepeat = 1; - }; - }; - - void selfdamage(dynent * d, int dm) - { - if(d==player1) selfdamage(dm, -1, d); - else { addmsg(1, 4, SV_DAMAGE, d, dm, d->lifesequence); playsound(S_FALL1+rnd(5), &d->o); }; - particle_splash(3, dm, 1000, d->o); //edit out? - demodamage(dm, d->o); - }; - - - // 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 - - void moveplayer(dynent *pl, int moveres, bool local, int curtime) - { - const bool water = hdr.waterlevel>pl->o.z-0.5f; - const bool floating = (editmode && local) || pl->state==CS_EDITING; - - vec d; // vector of direction we ideally want to move in - - d.x = (float)(pl->move*cos(rad(pl->yaw-90))); - d.y = (float)(pl->move*sin(rad(pl->yaw-90))); - - d.z = (float) pl->bounce ? pl->vel.z : 0; - - + d.z = (float) pl->isphysent ? pl->vel.z : 0; if(floating || water) - { - d.x *= (float)cos(rad(pl->pitch)); - d.y *= (float)cos(rad(pl->pitch)); - d.z = (float)(pl->move*sin(rad(pl->pitch))); - }; - - d.x += (float)(pl->strafe*cos(rad(pl->yaw-180))); - d.y += (float)(pl->strafe*sin(rad(pl->yaw-180))); - - const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed; - const float friction = water ? 20.0f : (pl->onfloor || floating ? 6.0f : 30.0f); - - const float fpsfric = friction/curtime*20.0f; - - vmul(pl->vel, fpsfric-1); // slowly apply friction and direction to velocity, gives a smooth movement - vadd(pl->vel, d); - vdiv(pl->vel, fpsfric); - d = pl->vel; - vmul(d, speed); // d is now frametime based velocity vector - - pl->blocked = false; - pl->moving = true; - - if(floating) // just apply velocity - { - vadd(pl->o, d); - if(pl->jumpnext) { pl->jumpnext = false; pl->vel.z = 2; } - } - else // apply velocity with collision - { - if(pl->onfloor || water) - { - if (pl->onfloor || !pl->vel.z) - { - int damage = (int)pl->startheight - (int)pl->o.z; - if (damage > 8 && local) //try adding "&& local" if falling not fixed - { - selfdamage(damage,-1,pl); - demodamage(damage, player1->o); - playsound(S_FALL1+rnd(2), &pl->o); - }; - pl->startheight=pl->o.z; - }; - - if(pl->jumpnext) - { - pl->jumpnext = false; - pl->vel.z = 1.7f; // physics impulse upwards - if(water) { pl->vel.x /= 8; pl->vel.y /= 8; }; // dampen velocity change even harder, gives correct water feel - if(local) playsoundc(S_JUMP); - else if(pl->monsterstate) playsound(S_JUMP, &pl->o); - } - else if(pl->timeinair>800) // if we land after long time must have been a high jump, make thud sound - { - if(local) playsoundc(S_LAND); - else if(pl->monsterstate) playsound(S_LAND, &pl->o); - }; - pl->timeinair = 0; - - if(pl->bounce) pl->vel.z *= 0.7f; - + if(pl->isphysent) pl->vel.z *= 0.7f; } - else - { - pl->timeinair += curtime; - }; - - const float gravity = pl->bounce ? pl->gravity : 20; + const float gravity = pl->isphysent ? pl->gravity : 20; const float f = 1.0f/moveres; - - float dropf = pl->bounce ? ((gravity-1)+pl->timeinair/14.0f) : ((gravity-1)+pl->timeinair/15.0f); // incorrect, but works fine - + float dropf = pl->isphysent ? ((gravity-1)+pl->timeinair/14.0f) : ((gravity-1)+pl->timeinair/15.0f); // incorrect, but works fine if(water) { dropf = 5; pl->timeinair = 0; }; // float slowly down in water - float drop = dropf*curtime/gravity/100/moveres; // at high fps, gravity kicks in too fast - const float rise = speed/moveres/1.2f; // extra smoothness when lifting up stairs - loopi(moveres) // discrete steps collision detection & sliding - { - // try move forward - pl->o.x += f*d.x; - pl->o.y += f*d.y; - pl->o.z += f*d.z; - if(collide(pl, false, drop, rise)) continue; - // player stuck, try slide along y axis - pl->blocked = true; - pl->o.x -= f*d.x; - if(collide(pl, false, drop, rise)) - { - d.x = 0; - - if(pl->bounce) pl->vel.x = -pl->vel.x; - + if(pl->isphysent) pl->vel.x = -pl->vel.x; continue; - }; - pl->o.x += f*d.x; - // still stuck, try x axis - pl->o.y -= f*d.y; - if(collide(pl, false, drop, rise)) - { - d.y = 0; - - if(pl->bounce) pl->vel.y = -pl->vel.y; - + if(pl->isphysent) pl->vel.y = -pl->vel.y; continue; - }; - pl->o.y += f*d.y; - // try just dropping down - pl->moving = false; - pl->o.x -= f*d.x; - pl->o.y -= f*d.y; - if(collide(pl, false, drop, rise)) - { - d.y = d.x = 0; - continue; - }; - pl->o.z -= f*d.z; - break; - }; - }; - - // detect wether player is outside map, used for skipping zbuffer clear mostly - - if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) - { - pl->outsidemap = true; - } - else - { - sqr *s = S((int)pl->o.x, (int)pl->o.y); - pl->outsidemap = SOLID(s) - || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0) - || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); - }; - - // automatically apply smooth roll when strafing - - if(pl->strafe==0) - { - pl->roll = pl->roll/(1+(float)sqrt((float)curtime)/25); - } - else - { - pl->roll += pl->strafe*curtime/-30.0f; - if(pl->roll>maxroll) pl->roll = (float)maxroll; - if(pl->roll<-maxroll) pl->roll = (float)-maxroll; - }; - - // play sounds on water transitions - - if(!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; } - else if(pl->inwater && !water) playsound(S_SPLASH1, &pl->o); - pl->inwater = water; - }; - - void moveplayer(dynent *pl, int moveres, bool local) - { - loopi(physicsrepeat) moveplayer(pl, moveres, local, i ? curtime/physicsrepeat : curtime-curtime/physicsrepeat*(physicsrepeat-1)); - }; - - void movephysent(physent *pl) - { - int moveres = 2; - bool local=true; - loopj(physicsrepeat) - { - const bool water = hdr.waterlevel>pl->o.z-0.5f; - const bool floating = (editmode && local); - - vec d; // vector of direction we ideally want to move in - - d = pl->vel; - - - const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed; - const float friction = water ? 20.0f : (pl->onfloor || floating ? 6.0f : 30.0f); - - const float fpsfric = friction/curtime*20.0f; - - vmul(pl->vel, fpsfric-1); // slowly apply friction and direction to velocity, gives a smooth movement - vadd(pl->vel, d); - vdiv(pl->vel, fpsfric); - d = pl->vel; - vmul(d, speed); // d is now frametime based velocity vector - - - /* if(floating || water) - { - d.x *= (float)cos(rad(pl->pitch)); - d.y *= (float)cos(rad(pl->pitch)); - d.z = (float)(pl->move*sin(rad(pl->pitch))); - };*/ - - /*if(pl->onfloor || water) - { - if(pl->jumpnext) - { - pl->jumpnext = false; - pl->vel.z = 1.7f; // physics impulse upwards - if(water) { pl->vel.x /= 8; pl->vel.y /= 8; }; // dampen velocity change even harder, gives correct water feel - //if(local) playsoundc(S_JUMP); - } - else if(pl->timeinair>800) // if we land after long time must have been a high jump, make thud sound - { - //if(local) playsoundc(S_LAND); - //else if(pl->monsterstate) playsound(S_LAND, &pl->o); - }; - pl->timeinair = 0; - } - else - { - pl->timeinair += curtime; - };*/ - - if(pl->onfloor) - { - pl->timeinair = 0; - vmul(pl->vel, 0.8f); - } - else - { - pl->timeinair += curtime; - pl->pitch = (lastmillis-pl->millis) % 360; - pl->yaw = pl->pitch; - }; - - - //const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed; - - const float gravity = 20; - const float f = 1.0f/moveres; - float dropf = pl->timeinair/15.0f; // incorrect, but works fine - if(water) { dropf = 5; pl->timeinair = 0; }; // float slowly down in water - const float drop = dropf*curtime/gravity/100/moveres; // at high fps, gravity kicks in too fast - const float rise = speed/moveres/1.2f; // extra smoothness when lifting up stairs - // if(pl->mtype = M_NADE)printf("%i\n", pl->onfloor); - /* d.x -= d.x/50.0f*curtime; - d.y -= d.y/50.0f*curtime;*/ - - - loopi(moveres) // discrete steps collision detection & sliding - { - // try move forward - pl->o.x += f*d.x; - pl->o.y += f*d.y; - pl->o.z += f*d.z; - if(collide(pl, false, drop, rise)) continue; - // player stuck, try slide along y axis - pl->blocked = true; - pl->o.x -= f*d.x; - if(collide(pl, false, drop, rise)) { pl->vel.x = -d.x; vmul(pl->vel, 0.8f); d.x = 0; continue; }; - pl->o.x += f*d.x; - // still stuck, try x axis - pl->o.y -= f*d.y; - if(collide(pl, false, drop, rise)) { pl->vel.y = -d.y; vmul(pl->vel, 0.8f); d.y = 0; continue; }; - pl->o.y += f*d.y; - // try just dropping down - pl->moving = false; - pl->o.x -= f*d.x; - pl->o.y -= f*d.y; - if(collide(pl, false, drop, rise)) { d.y = d.x = 0; vmul(pl->vel, 0.8f); continue; }; - pl->o.z -= f*d.z; - break; - }; - - // detect wether player is outside map, used for skipping zbuffer clear mostly - - - - if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) - { - pl->outsidemap = true; - } - else - { - sqr *s = S((int)pl->o.x, (int)pl->o.y); - pl->outsidemap = SOLID(s) - || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0) - || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); - }; - - // play sounds on water transitions - - if(!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; } - else if(pl->inwater && !water) playsound(S_SPLASH1, &pl->o); - pl->inwater = water; - }; - }; - diff --git a/source/src/renderextras.cpp b/source/src/renderextras.cpp index fbb59c27..3bfa3a30 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderextras.cpp @@ -1,998 +1,521 @@ // renderextras.cpp: misc gl render code and the HUD - - #include "cube.h" - - void line(int x1, int y1, float z1, int x2, int y2, float z2) - { - glBegin(GL_POLYGON); - glVertex3f((float)x1, z1, (float)y1); - glVertex3f((float)x1, z1, y1+0.01f); - glVertex3f((float)x2, z2, y2+0.01f); - glVertex3f((float)x2, z2, (float)y2); - glEnd(); - xtraverts += 4; - }; - - void linestyle(float width, int r, int g, int b) - { - glLineWidth(width); - glColor3ub(r,g,b); - }; - - void box(block &b, float z1, float z2, float z3, float z4) - { - glBegin(GL_POLYGON); - glVertex3f((float)b.x, z1, (float)b.y); - glVertex3f((float)b.x+b.xs, z2, (float)b.y); - glVertex3f((float)b.x+b.xs, z3, (float)b.y+b.ys); - glVertex3f((float)b.x, z4, (float)b.y+b.ys); - glEnd(); - xtraverts += 4; - }; - - void dot(int x, int y, float z) - { - const float DOF = 0.1f; - glBegin(GL_POLYGON); - glVertex3f(x-DOF, (float)z, y-DOF); - glVertex3f(x+DOF, (float)z, y-DOF); - glVertex3f(x+DOF, (float)z, y+DOF); - glVertex3f(x-DOF, (float)z, y+DOF); - glEnd(); - xtraverts += 4; - }; - - -void blendbox(int x1, int y1, int x2, int y2, bool border, int tex) - +void blendbox(int x1, int y1, int x2, int y2, bool border, int tex=-1) { - glDepthMask(GL_FALSE); - glDisable(GL_TEXTURE_2D); - if(tex>=0) - { - glBindTexture(GL_TEXTURE_2D, tex); - glEnable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - } - else - { - if(border) glColor3d(0.7, 0.7, 0.7); //glColor3d(0.5, 0.3, 0.4); - else glColor3d(1.0, 1.0, 1.0); - glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - }; - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2i(x1, y1); - glTexCoord2f(1, 0); glVertex2i(x2, y1); - glTexCoord2f(1, 1); glVertex2i(x2, y2); - glTexCoord2f(0, 1); glVertex2i(x1, y2); - glEnd(); - glDisable(GL_BLEND); - if(tex>=0) glDisable(GL_TEXTURE_2D); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glBegin(GL_POLYGON); - glColor3d(0.6, 0.6, 0.6); //glColor3d(0.2, 0.7, 0.4); - glVertex2i(x1, y1); - glVertex2i(x2, y1); - glVertex2i(x2, y2); - glVertex2i(x1, y2); - glEnd(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - xtraverts += 8; - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glDepthMask(GL_TRUE); - }; - - const int MAXSPHERES = 50; - struct sphere { vec o; float size, max; int type; sphere *next; }; - sphere spheres[MAXSPHERES], *slist = NULL, *sempty = NULL; - bool sinit = false; - - void newsphere(vec &o, float max, int type) - { - if(!sinit) - { - loopi(MAXSPHERES) - { - spheres[i].next = sempty; - sempty = &spheres[i]; - }; - sinit = true; - }; - if(sempty) - { - sphere *p = sempty; - sempty = p->next; - p->o = o; - p->max = max; - p->size = 1; - p->type = type; - p->next = slist; - slist = p; - }; - }; - - void renderspheres(int time) - { - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, 4); - - for(sphere *p, **pp = &slist; p = *pp;) - { - glPushMatrix(); - float size = p->size/p->max; - glColor4f(1.0f, 1.0f, 1.0f, 1.0f-size); - glTranslatef(p->o.x, p->o.z, p->o.y); - glRotatef(lastmillis/5.0f, 1, 1, 1); - glScalef(p->size, p->size, p->size); - glCallList(1); - glScalef(0.8f, 0.8f, 0.8f); - glCallList(1); - glPopMatrix(); - xtraverts += 12*6*2; - - if(p->size>p->max) - { - *pp = p->next; - p->next = sempty; - sempty = p; - } - else - { - p->size += time/30.0f; - pp = &p->next; - }; - }; - - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - }; - - string closeent; - char *entnames[] = - { - "none?", "light", "playerstart", - "clips", "ammobox","grenade", - "health", "armour", "quaddamage", - "mapmodel", "trigger", - "ladder", "?", "?", "?", "?", - }; - - void renderents() // show sparkly thingies for map entities in edit mode - { - closeent[0] = 0; - if(!editmode) return; - loopv(ents) - { - entity &e = ents[i]; - if(e.type==NOTUSED) continue; - vec v = { e.x, e.y, e.z }; - particle_splash(2, 2, 40, v); - }; - int e = closestent(); - if(e>=0) - { - entity &c = ents[e]; - sprintf_s(closeent)("closest entity = %s (%d, %d, %d, %d), selection = (%d, %d)", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, getvar("selxs"), getvar("selys")); - }; - }; - - void loadsky(char *basename) - { - static string lastsky = ""; - if(strcmp(lastsky, basename)==0) return; - char *side[] = { "ft", "bk", "lf", "rt", "dn", "up" }; - int texnum = 14; - loopi(6) - { - sprintf_sd(name)("packages/%s_%s.jpg", basename, side[i]); - int xs, ys; - if(!installtex(texnum+i, path(name), xs, ys, true)) conoutf("could not load sky textures"); - }; - strcpy_s(lastsky, basename); - }; - - COMMAND(loadsky, ARG_1STR); - - float cursordepth = 0.9f; - GLint viewport[4]; - GLdouble mm[16], pm[16]; - vec worldpos; - - void readmatrices() - { - glGetIntegerv(GL_VIEWPORT, viewport); - glGetDoublev(GL_MODELVIEW_MATRIX, mm); - glGetDoublev(GL_PROJECTION_MATRIX, pm); - }; - - // stupid function to cater for stupid ATI drivers that return incorrect depth values - - float depthcorrect(float d) - { - static int when = 0; - static float factor = 1; - //if(when++==5) factor = 0.992205f/d; // this magic value is tied to the fixed start spawn point in metl3 - return d*factor; - }; - - // find out the 3d target of the crosshair in the world easily and very acurately. - // sadly many very old cards and drivers appear to fuck up on gluUnProject() and give false - // coordinates, making shooting and such impossible. - // also hits map entities which is unwanted. - // could be replaced by a more acurate version of monster.cpp los() if needed - - void readdepth(int w, int h) - { - glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth); - double worldx = 0, worldy = 0, worldz = 0; - gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldz, &worldy); - worldpos.x = (float)worldx; - worldpos.y = (float)worldy; - worldpos.z = (float)worldz; - vec r = { (float)mm[0], (float)mm[4], (float)mm[8] }; - vec u = { (float)mm[1], (float)mm[5], (float)mm[9] }; - setorient(r, u); - }; - - void drawicon(float tx, float ty, int x, int y, float scale=1.0f) - { - glBindTexture(GL_TEXTURE_2D, 5); - glBegin(GL_QUADS); - tx /= 192; - ty /= 192; - float o = 1/3.0f; - int s = 120*scale; - glTexCoord2f(tx, ty); glVertex2i(x, y); - glTexCoord2f(tx+o, ty); glVertex2i(x+s, y); - glTexCoord2f(tx+o, ty+o); glVertex2i(x+s, y+s); - glTexCoord2f(tx, ty+o); glVertex2i(x, y+s); - glEnd(); - xtraverts += 4; - }; - - void invertperspective() - { - // This only generates a valid inverse matrix for matrices generated by gluPerspective() - GLdouble inv[16]; - memset(inv, 0, sizeof(inv)); - - inv[0*4+0] = 1.0/pm[0*4+0]; - inv[1*4+1] = 1.0/pm[1*4+1]; - inv[2*4+3] = 1.0/pm[3*4+2]; - inv[3*4+2] = -1.0; - inv[3*4+3] = pm[2*4+2]/pm[3*4+2]; - - glLoadMatrixd(inv); - }; - - VAR(crosshairsize, 0, 15, 50); - - int dblend = 0; - void damageblend(int n) { dblend += n; }; - - VAR(hidestats, 0, 0, 1); - VAR(crosshairfx, 0, 1, 1); - - +VAR(scoped, 0, 0, 1); void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater) - { - - readmatrices(); - if(editmode) - { - if(cursordepth==1.0f) worldpos = player1->o; - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - cursorupdate(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - }; - - glDisable(GL_DEPTH_TEST); - invertperspective(); - glPushMatrix(); - glOrtho(0, VIRTW, VIRTH, 0, -1, 1); - glEnable(GL_BLEND); - - if(dblend || underwater) - { - glDepthMask(GL_FALSE); - glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - glBegin(GL_QUADS); - if(dblend) glColor3d(0.0f, 0.9f, 0.9f); - else glColor3d(0.9f, 0.5f, 0.0f); - glVertex2i(0, 0); - glVertex2i(VIRTW, 0); - glVertex2i(VIRTW, VIRTH); - glVertex2i(0, VIRTH); - glEnd(); - glDepthMask(GL_TRUE); - dblend -= curtime/3; - if(dblend<0) dblend = 0; - }; - - glEnable(GL_TEXTURE_2D); - - char *command = getcurcommand(); - dynent *player = playerincrosshair(); - if(command) draw_textf("> %s_", 20, 1570, 2, (int)command); - else if(closeent[0]) draw_text(closeent, 20, 1570, 2); - else if(player) - { - string plinfo; - if(isteam(player->team, player1->team)) sprintf_s(plinfo)("%s (health:%i armour:%i)", player->name, player->health, player->armour); - else sprintf_s(plinfo)("%s", player->name); - draw_text(plinfo, 20, 1570, 2); - }; - - renderscores(); - if(!rendermenu()) - { - - glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); - - glBindTexture(GL_TEXTURE_2D, 1); - - glBegin(GL_QUADS); - - glColor3ub(255,255,255); - - if(crosshairfx) - + if(scoped) { - - if(player1->gunwait) glColor3ub(128,128,128); - - else if(player1->health<=25) glColor3ub(255,0,0); - - else if(player1->health<=50) glColor3ub(255,128,0); - - }; - - float chsize = (float)crosshairsize; - - glTexCoord2d(0.0, 0.0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 - chsize); - - glTexCoord2d(1.0, 0.0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 - chsize); - - glTexCoord2d(1.0, 1.0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 + chsize); - - glTexCoord2d(0.0, 1.0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 + chsize); - - glEnd(); - + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.9f); + glBindTexture(GL_TEXTURE_2D, 10); + glBegin(GL_QUADS); + glColor3ub(255,255,255); + float chsize = (float)crosshairsize; + glTexCoord2d(0.0, 0.0); glVertex2f(0, 0); + glTexCoord2d(1.0, 0.0); glVertex2f(VIRTW, 0); + glTexCoord2d(1.0, 1.0); glVertex2f(VIRTW, VIRTH); + glTexCoord2d(0.0, 1.0); glVertex2f(0, VIRTH); + glEnd(); + glDisable(GL_ALPHA_TEST); + } + else + { + glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, 1); + glBegin(GL_QUADS); + glColor3ub(255,255,255); + if(crosshairfx) + { + if(player1->gunwait) glColor3ub(128,128,128); + else if(player1->health<=25) glColor3ub(255,0,0); + else if(player1->health<=50) glColor3ub(255,128,0); + }; + float chsize = (float)crosshairsize; + glTexCoord2d(0.0, 0.0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 - chsize); + glTexCoord2d(1.0, 0.0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 - chsize); + glTexCoord2d(1.0, 1.0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 + chsize); + glTexCoord2d(0.0, 1.0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 + chsize); + glEnd(); + } }; glPopMatrix(); - - glPushMatrix(); - glOrtho(0, VIRTW*4/3, VIRTH*4/3, 0, -1, 1); - renderconsole(); - - if(!hidestats) - { - glPopMatrix(); - glPushMatrix(); - glOrtho(0, VIRTW*3/2, VIRTH*3/2, 0, -1, 1); - draw_textf("fps %d", 3200, 2320, 2, curfps); - draw_textf("lod %d", 3200, 2390, 2, lod_factor()); - draw_textf("wqd %d", 3200, 2460, 2, nquads); - draw_textf("wvt %d", 3200, 2530, 2, curvert); - draw_textf("evt %d", 3200, 2600, 2, xtraverts); - }; - - glPopMatrix(); - - if(player1->state==CS_ALIVE) - { - glPushMatrix(); - glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1); - draw_textf("%d", 90, 827, 2, player1->health); - if(player1->armour) draw_textf("%d", 390, 827, 2, player1->armour); - //draw_textf("%d", 690, 827, 2, player1->mag[player1->gunselect]); - if (player1->gunselect!=GUN_KNIFE) - { - //draw_textf("%d", 690, 827, 2, player1->mag[player1->gunselect]); - char gunstats [64]; - sprintf(gunstats,"%i/%i",player1->mag[player1->gunselect],player1->ammo[player1->gunselect]); - draw_text(gunstats, 690, 827, 2); - //clean up pointer? - //delete gunstats; - } - - glPopMatrix(); - glPushMatrix(); - glOrtho(0, VIRTW, VIRTH, 0, -1, 1); - glDisable(GL_BLEND); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(1.0f, 1.0f, 1.0f, (float) 0.2f+(sin(lastmillis/100)+1)/2); - - if(player1->health <= 20) - { - glEnable(GL_BLEND); - drawicon(64, 0, 20, 1650); //drawicon(128, 128, 20, 1650); - glDisable(GL_BLEND); - } - else drawicon(64, 0, 20, 1650); //drawicon(128, 128, 20, 1650); - if(player1->armour) drawicon((float)(128), 0, 620, 1650); //if(player1->armour) drawicon((float)(player1->armourtype*64), 0, 620, 1650); - int g = player1->gunselect; - int r = 64; - if(g>2) { g -= 3; r = 128; }; - - if(!player1->mag[player1->gunselect] && player1->gunselect != GUN_KNIFE && player1->gunselect != GUN_GRENADE) - { - glEnable(GL_BLEND); - drawicon((float)(g*64), (float)r, 1220, 1650); - glDisable(GL_BLEND); - } - else drawicon((float)(g*64), (float)r, 1220, 1650); - glPopMatrix(); - }; - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glEnable(GL_DEPTH_TEST); - }; - - #define MAXSHOTLINES 100 - struct shotline - { - vec from, to; - bool inuse; - int millis; - }; - shotline shotlines[MAXSHOTLINES]; - - void shotlinereset() { loopi(MAXSHOTLINES) shotlines[i].inuse = false; }; - - void addshotline(dynent *d, vec &from, vec &to) - { - if(d == player1) return; - if(rnd(3) != 0) return; - loopi(MAXSHOTLINES) - { - shotline *s = &shotlines[i]; - if(s->inuse) continue; - int start = 10; - vdist(_dist, _unitv, player1->o, to); - if(_dist <= 10.0f) start = 8; - else start = 5; - - vdist(dist, unitv, from, to); - vdiv(unitv, dist); - s->inuse = true; - s->from = unitv; - vmul(s->from, dist/10*start); - vadd(s->from, from); - s->to = unitv; - vmul(s->to, dist/10*-(10-start-2)); - vadd(s->to, to); - s->millis = lastmillis; - return; - }; - }; - - VAR(shotline_duration, 0, 75, 10000); - - void rendershotlines() - { - loopi(MAXSHOTLINES) - { - shotline *s = &shotlines[i]; - if(!s->inuse) continue; - if(lastmillis-s->millis > shotline_duration) { s->inuse = false; continue; } - glPushMatrix(); - glDisable(GL_TEXTURE_2D); - - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); - glDisable(GL_FOG); - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glBegin(GL_LINES); - glColor4f(1.0f, 1.0f, 0.7f, 0.5f); - glVertex3f(s->from.x, s->from.z, s->from.y); - glVertex3f(s->to.x, s->to.z, s->to.y); - glEnd(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - glEnable(GL_FOG); - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - - glEnable(GL_TEXTURE_2D); - glPopMatrix(); - }; - }; - - void renderphysents() - { - loopv(physents) - { - physent *d = physents[i]; - - if(d && d->throwed) rendermodel("weapons/grenade/static", 0, 1, 0, 0, d->o.x, d->o.z, d->o.y, d->yaw, d->pitch, false, 2.0f, 100.0f, 0, 0); - + if(d && d->state==NADE_THROWED) rendermodel("weapons/grenade/static", 0, 1, 0, 0, d->o.x, d->o.z, d->o.y, d->yaw, d->pitch, false, 2.0f, 100.0f, 0, 0); }; - }; - - diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 626bfead..76701c5d 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -1,817 +1,409 @@ // rendergl.cpp: core opengl rendering stuff -// raped line-feeds, thanks visual studio!! bastard - - #include "cube.h" - - #ifdef DARWIN - #define GL_COMBINE_EXT GL_COMBINE_ARB - #define GL_COMBINE_RGB_EXT GL_COMBINE_RGB_ARB - #define GL_SOURCE0_RBG_EXT GL_SOURCE0_RGB_ARB - #define GL_SOURCE1_RBG_EXT GL_SOURCE1_RGB_ARB - #define GL_RGB_SCALE_EXT GL_RGB_SCALE_ARB - #endif - - extern int curvert; - - bool hasoverbright = false; - - void purgetextures(); - - GLUquadricObj *qsphere = NULL; - int glmaxtexsize = 256; - - void gl_init(int w, int h) - { - //#define fogvalues 0.5f, 0.6f, 0.7f, 1.0f - - glViewport(0, 0, w, h); - glClearDepth(1.0); - glDepthFunc(GL_LESS); - glEnable(GL_DEPTH_TEST); - glShadeModel(GL_SMOOTH); - - - glEnable(GL_FOG); - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogf(GL_FOG_DENSITY, 0.25); - glHint(GL_FOG_HINT, GL_NICEST); - - - glEnable(GL_LINE_SMOOTH); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(-3.0, -3.0); - - glCullFace(GL_FRONT); - glEnable(GL_CULL_FACE); - - char *exts = (char *)glGetString(GL_EXTENSIONS); - - if(strstr(exts, "GL_EXT_texture_env_combine")) hasoverbright = true; - else conoutf("WARNING: cannot use overbright lighting, using old lighting model!"); - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glmaxtexsize); - - purgetextures(); - - if(!(qsphere = gluNewQuadric())) fatal("glu sphere"); - gluQuadricDrawStyle(qsphere, GLU_FILL); - gluQuadricOrientation(qsphere, GLU_INSIDE); - gluQuadricTexture(qsphere, GL_TRUE); - glNewList(1, GL_COMPILE); - gluSphere(qsphere, 1, 12, 6); - glEndList(); - }; - - void cleangl() - { - if(qsphere) gluDeleteQuadric(qsphere); - }; - - -bool installtex(int tnum, char *texname, int &xs, int &ys, bool clamp, bool highqual) - +bool installtex(int tnum, char *texname, int &xs, int &ys, bool clamp, bool highqual=false) { - SDL_Surface *s = IMG_Load(texname); - if(!s) { conoutf("couldn't load texture %s", (int)texname); return false; }; - - if(s->format->BitsPerPixel!=24) { conoutf("texture must be 24bpp: %s", (int)texname); return false; }; - + if(s->format->BitsPerPixel!=24 && s->format->BitsPerPixel!=32) { conoutf("texture must be 24bpp or 32bpp: %s", (int)texname); return false; }; // loopi(s->w*s->h*3) { uchar *p = (uchar *)s->pixels+i; *p = 255-*p; }; - glBindTexture(GL_TEXTURE_2D, tnum); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, highqual ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); //NEAREST); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - xs = s->w; - ys = s->h; - while(xs>glmaxtexsize || ys>glmaxtexsize) { xs /= 2; ys /= 2; }; - void *scaledimg = s->pixels; - if(xs!=s->w) - { - conoutf("warning: quality loss: scaling %s", (int)texname); // for voodoo cards under linux - scaledimg = alloc(xs*ys*3); - gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, s->pixels, xs, ys, GL_UNSIGNED_BYTE, scaledimg); - }; - - if(gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, xs, ys, GL_RGB, GL_UNSIGNED_BYTE, scaledimg)) fatal("could not build mipmaps"); - + int mode = s->format->BitsPerPixel==24 ? GL_RGB : GL_RGBA; + if(gluBuild2DMipmaps(GL_TEXTURE_2D, mode, xs, ys, mode, GL_UNSIGNED_BYTE, scaledimg)) fatal("could not build mipmaps"); if(xs!=s->w) free(scaledimg); - SDL_FreeSurface(s); - return true; - }; - - // management of texture slots - // each texture slot can have multople texture frames, of which currently only the first is used - // additional frames can be used for various shaders - - const int MAXTEX = 1000; - int texx[MAXTEX]; // ( loaded texture ) -> ( name, size ) - int texy[MAXTEX]; - string texname[MAXTEX]; - int curtex = 0; - -const int FIRSTTEX = 100; // opengl id = loaded id + FIRSTTEX - -// std 1+, sky 14+, md3's 30+,md2's 40+, menu 90+ - - +const int FIRSTTEX = 130; // opengl id = loaded id + FIRSTTEX +// std 1+, sky 14+, md3's 30+,md2's 40+, menu 120+ const int MAXFRAMES = 2; // increase to allow more complex shader defs - int mapping[256][MAXFRAMES]; // ( cube texture, frame ) -> ( opengl id, name ) - string mapname[256][MAXFRAMES]; - - void purgetextures() - { - loopi(256) loop(j,MAXFRAMES) mapping[i][j] = 0; - }; - - int curtexnum = 0; - - void texturereset() { curtexnum = 0; }; - - void texture(char *aframe, char *name) - { - int num = curtexnum++, frame = atoi(aframe); - if(num<0 || num>=256 || frame<0 || frame>=MAXFRAMES) return; - mapping[num][frame] = 1; - char *n = mapname[num][frame]; - strcpy_s(n, name); - path(n); - }; - - COMMAND(texturereset, ARG_NONE); - COMMAND(texture, ARG_2STR); - - int lookuptexture(int tex, int &xs, int &ys) - { - int frame = 0; // other frames? - int tid = mapping[tex][frame]; - - if(tid>=FIRSTTEX) - { - xs = texx[tid-FIRSTTEX]; - ys = texy[tid-FIRSTTEX]; - return tid; - }; - - xs = ys = 16; - if(!tid) return 1; // crosshair :) - - loopi(curtex) // lazily happens once per "texture" command, basically - { - if(strcmp(mapname[tex][frame], texname[i])==0) - { - mapping[tex][frame] = tid = i+FIRSTTEX; - xs = texx[i]; - ys = texy[i]; - return tid; - }; - }; - - if(curtex==MAXTEX) fatal("loaded too many textures"); - - int tnum = curtex+FIRSTTEX; - strcpy_s(texname[curtex], mapname[tex][frame]); - - sprintf_sd(name)("packages%ctextures%c%s", PATHDIV, PATHDIV, texname[curtex]); - - if(installtex(tnum, name, xs, ys)) - { - mapping[tex][frame] = tnum; - texx[curtex] = xs; - texy[curtex] = ys; - curtex++; - return tnum; - } - else - { - return mapping[tex][frame] = FIRSTTEX; // temp fix - }; - }; - - void setupworld() - { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - setarraypointers(); - - if(hasoverbright) - { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); - }; - }; - - int skyoglid; - - struct strip { int tex, start, num; }; - vector strips; - - void renderstripssky() - { - glBindTexture(GL_TEXTURE_2D, skyoglid); - loopv(strips) if(strips[i].tex==skyoglid) glDrawArrays(GL_TRIANGLE_STRIP, strips[i].start, strips[i].num); - }; - - void renderstrips() - { - int lasttex = -1; - loopv(strips) if(strips[i].tex!=skyoglid) - { - if(strips[i].tex!=lasttex) - { - glBindTexture(GL_TEXTURE_2D, strips[i].tex); - lasttex = strips[i].tex; - }; - glDrawArrays(GL_TRIANGLE_STRIP, strips[i].start, strips[i].num); - }; - }; - - void overbright(float amount) { if(hasoverbright) glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, amount ); }; - - void addstrip(int tex, int start, int n) - { - strip &s = strips.add(); - s.tex = tex; - s.start = start; - s.num = n; - }; - - VARF(gamma, 30, 100, 300, - { - float f = gamma/100.0f; - if(SDL_SetGamma(f,f,f)==-1) - { - conoutf("Could not set gamma (card/driver doesn't support it?)"); - conoutf("sdl: %s", (int)SDL_GetError()); - }; - }); - - void transplayer() - { - glLoadIdentity(); - - if(player1->state==CS_DEAD) - { - float t = (lastmillis-player1->lastaction)/1000.0f; - if(t >= 1.6f) t = 1.6f; - - player1->pitch = (float) sin(t)*(-70.0f-player1->oldpitch)+player1->oldpitch; - glRotated(player1->pitch,-1.0,0.0,0.0); - glRotated(player1->yaw,0.0,1.0,0.0); - - glTranslated(-player1->o.x, player1->eyeheight-sin(t)*7.0f-player1->o.z, -player1->o.y); - } - else - { - glRotated(player1->roll,0.0,0.0,1.0); - glRotated(player1->pitch,-1.0,0.0,0.0); - glRotated(player1->yaw,0.0,1.0,0.0); - - glTranslated(-player1->o.x, (player1->state==CS_DEAD ? player1->eyeheight-0.2f : 0)-player1->o.z, -player1->o.y); - }; - }; - - VAR(fov, 10, 105, 120); - - int xtraverts; - - VAR(fog, 64, 180, 1024); - VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF); - - VAR(hudgun,0,1,1); - - char *hudgunnames[] = { "knife", "pistol", "shotgun", "subgun", "sniper", "assault", "grenade" }; - - void drawhudmodel(int start, int end, float speed, int base) - { - sprintf_sd(mdl)("hudguns/%s", hudgunnames[player1->gunselect]); - rendermodel(mdl, start, end, 0, 1.0f, player1->o.x, player1->o.z, player1->o.y, player1->yaw+90, player1->pitch, false, 1.0f, speed, 0, base); - }; - - void drawhudgun(int w, int h, float aspect, int farplane) - { - if(!hudgun || player1->state==CS_DEAD) return; - - glEnable(GL_CULL_FACE); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective((float)100.0f*h/w, aspect, 0.3f, farplane); // fov fixed at 100° - glMatrixMode(GL_MODELVIEW); - - rendermd3gun(); - rendermenumdl(); // lazy bastard - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective((float)fov*h/w, aspect, 0.15f, farplane); - glMatrixMode(GL_MODELVIEW); - - glDisable(GL_CULL_FACE); - }; - - void gl_drawframe(int w, int h, float changelod, float curfps) - { - float hf = hdr.waterlevel-0.3f; - float fovy = (float)fov*h/w; - float aspect = w/(float)h; - bool underwater = player1->o.z>16)/256.0f, ((fogcolour>>8)&255)/256.0f, (fogcolour&255)/256.0f, 1.0f }; - glFogfv(GL_FOG_COLOR, fogc); - glClearColor(fogc[0], fogc[1], fogc[2], 1.0f); - - if(underwater) - { - fovy += (float)sin(lastmillis/1000.0)*2.0f; - aspect += (float)sin(lastmillis/1000.0+PI)*0.1f; - glFogi(GL_FOG_START, 0); - glFogi(GL_FOG_END, (fog+96)/8); - }; - - glClear((player1->outsidemap ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - int farplane = fog*5/2; - gluPerspective(fovy, aspect, 0.15f, farplane); - glMatrixMode(GL_MODELVIEW); - - transplayer(); - - glEnable(GL_TEXTURE_2D); - - int xs, ys; - skyoglid = lookuptexture(DEFAULT_SKY, xs, ys); - - resetcubes(); - - curvert = 0; - strips.setsize(0); - - render_world(player1->o.x, player1->o.y, player1->o.z, changelod, - (int)player1->yaw, (int)player1->pitch, (float)fov, w, h); - finishstrips(); - - setupworld(); - - renderstripssky(); - - glLoadIdentity(); - glRotated(player1->pitch, -1.0, 0.0, 0.0); - glRotated(player1->yaw, 0.0, 1.0, 0.0); - glRotated(90.0, 1.0, 0.0, 0.0); - glColor3f(1.0f, 1.0f, 1.0f); - glDisable(GL_FOG); - glDepthFunc(GL_GREATER); - draw_envbox(14, fog*4/3); - glDepthFunc(GL_LESS); - glEnable(GL_FOG); - - transplayer(); - - overbright(2); - - renderstrips(); - - xtraverts = 0; - - renderclients(); - - renderentities(); - - renderspheres(curtime); - renderents(); - - renderphysents(); - - rendershotlines(); - - glDisable(GL_CULL_FACE); - - drawhudgun(w, h, aspect, farplane); - - overbright(1); - int nquads = renderwater(hf); - - overbright(2); - render_particles(curtime); - overbright(1); - - glDisable(GL_FOG); - - glDisable(GL_TEXTURE_2D); - - gl_drawhud(w, h, (int)curfps, nquads, curvert, underwater); - - glEnable(GL_CULL_FACE); - glEnable(GL_FOG); - }; - - diff --git a/source/src/rendermd2.cpp b/source/src/rendermd2.cpp index 74d6340e..bc8b7c33 100644 --- a/source/src/rendermd2.cpp +++ b/source/src/rendermd2.cpp @@ -249,7 +249,7 @@ void rendermodel(char *mdl, int frame, int range, int tex, float rad, float x, f { md2 *m = loadmodel(mdl); - //if(isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; + if(isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; delayedload(m); diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index 5fdff391..05780437 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -299,20 +299,49 @@ void moveprojectiles(float time) extern float rad(float x); -bool nade_activated = false; -physent *curnade; +physent *curnade = NULL; -void thrownade(dynent *d, vec &to, physent *nade = NULL, int nadesec = 0) -{ - physent *p; - if(nade) p = nade; - else p = (physent *)gp()->alloc(sizeof(physent)); // allocate new nade +void throw_nade(dynent *d, vec &to, physent *p) +{ + if(!p || !d) return; + printf("thrownade\n"); + + p->isphysent = true; + p->gravity = 20; + p->state = NADE_THROWED; - p->owner = d; + p->timeinair = 0; + p->onfloor = false; + + p->o = d->o; + p->vel.z = sin(rad(d->pitch)); + float speed = cos(rad(d->pitch)); + p->vel.x = sin(rad(d->yaw))*speed; + p->vel.y = -cos(rad(d->yaw))*speed; + + vmul(p->vel, 1.7f); + + vec throwdir = p->vel; + vmul(throwdir, d->radius); + vadd(p->o, throwdir); + vadd(p->o, throwdir); + + vec &from = d->o; + addmsg(1, 9, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), (int)((lastmillis-p->millis)/100)); + printf("grenade: %i\n", (lastmillis-curnade->millis)/100); + if(curnade) curnade = NULL; +}; + +void *new_physent() +{ + physent *p = (physent *)gp()->alloc(sizeof(physent)); + p->yaw = 270; p->pitch = 0; - p->roll = 0; - p->maxspeed = 40; //16 max speed, 14 max with armour + p->roll = 0; + p->isphysent = true; + + p->maxspeed = 40; p->outsidemap = false; p->inwater = false; p->radius = 0.2f; @@ -327,7 +356,8 @@ void thrownade(dynent *d, vec &to, physent *nade = NULL, int nadesec = 0) p->name[0] = p->team[0] = 0; p->blocked = false; p->lifesequence = 0; - p->state = CS_ALIVE; + p->dynent::state = CS_ALIVE; + p->state = PHYSENT_NONE; p->shots = 0; p->reloading = false; p->nextprimary = 1; @@ -339,66 +369,39 @@ void thrownade(dynent *d, vec &to, physent *nade = NULL, int nadesec = 0) p->k_down = false; p->jumpnext = false; p->strafe = 0; - p->move = 0; - - p->bounce = true; - p->gravity = 20; - - p->timeinair = 0; - p->throwed = true; - p->onfloor = false; - p->lifetime = 3000; - - p->o = d->o; + p->move = 0; + + physents.add(p); + return p; +} -// float speed = sin(rad((d->pitch+90)/2.0f)); - p->vel.z = sin(rad(d->pitch)); - float speed = cos(rad(d->pitch)); - p->vel.x = sin(rad(d->yaw))*speed; - p->vel.y = -cos(rad(d->yaw))*speed; - - vmul(p->vel, 1.7f); - - vec throwdir = p->vel; - vmul(throwdir, d->radius); - vadd(p->o, throwdir); - vadd(p->o, throwdir); - - if(!nade) // add new one - { - p->millis = lastmillis; - physents.add(p); - }; -}; - -void activate_nade() -{ - physent *p = (physent *)gp()->alloc(sizeof(physent)); - p->owner = player1; +physent *new_nade(dynent *d, int millis = 0) +{ + printf("newnade\n"); + physent *p = new_physent(); + p->owner = d; p->millis = lastmillis; - p->lifetime = 3000; - p->throwed = false; - p->enabled = true; - curnade = p; - physents.add(p); - - nade_activated = true; + p->timetolife = 2000-millis; + p->state = NADE_ACTIVATED; + if(d==player1) curnade = p; + return p; }; - -extern void explode_nade(physent *i) + void explode_nade(physent *i) { - if(!i) return; - if(!i->throwed) + if(!i) return; + printf("explode\n"); + + if(i->state != NADE_THROWED) { vec o = i->owner->o; vec dist = { 0.1f, 0.1f, 0.1f }; vadd(o, dist); - thrownade(i->owner, o, i); + throw_nade(i->owner, o, i); }; newprojectile(i->o, i->o, 1, true, i->owner, GUN_GRENADE); }; -void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nadesec) // create visual effect from a shot +void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nademillis) // create visual effect from a shot { playsound(guns[gun].sound, d==player1 ? NULL : &d->o); int pspeed = 25; @@ -422,12 +425,15 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nadesec) break; case GUN_GRENADE: - pspeed = guns[gun].projspeed; + //pspeed = guns[gun].projspeed; //newprojectile(from, to, (float)pspeed, local, d, gun); - if(d==player1 && curnade) - thrownade(d, to, curnade); - else - thrownade(d, to, NULL, nadesec); + + if(d!=player1) + { + physent *p = new_nade(d, nademillis); + throw_nade(d, to, p); + } + break; case GUN_SNIPER: @@ -496,43 +502,33 @@ void spreadandrecoil(vec & from, vec & to, dynent * d) }; void shoot(dynent *d, vec &targ) -{ - bool grenade_throw = d->gunselect==GUN_GRENADE && !d->attacking && nade_activated; - int attacktime = lastmillis-d->lastaction; - if(d->reloading && (attacktimegunwait) && !grenade_throw) return; - else if(attacktimegunwait) return; +{ + int attacktime = lastmillis-d->lastaction; + + if(!d->attacking && d->gunselect==GUN_GRENADE && curnade) // throw + { + throw_nade(d, targ, curnade); + return; + } + + if(attacktimegunwait) return; d->gunwait = 0; - d->reloading = false; - if(grenade_throw) - { - d->attacking = true; - nade_activated = false; - d->gunwait = guns[d->gunselect].attackdelay; - } - else if(d->gunselect==GUN_GRENADE && d->attacking && nade_activated) return; + d->reloading = false; if(!d->attacking) { d->shots = 0; return; - }; - if(!(d->gunselect==GUN_SUBGUN || d->gunselect==GUN_ASSULT)) d->attacking = false; //makes sub/assult autos - else - { - d->shots++; - }; + }; + + if(d->gunselect!=GUN_SUBGUN && d->gunselect!=GUN_ASSULT && d->gunselect!=GUN_GRENADE) d->attacking = false; //makes sub/assult autos + else d->shots++; + d->lastaction = lastmillis; d->lastattackgun = d->gunselect; if(!d->mag[d->gunselect]) { playsoundc(S_NOAMMO); d->gunwait = 250; d->lastattackgun = -1; return; }; - if(d->gunselect==GUN_GRENADE && !grenade_throw) - { - activate_nade(); - d->attacking = true; - return; - } - if(d->gunselect) d->mag[d->gunselect]--; - + vec from = d->o; vec to = targ; from.z -= 0.2f; // below eye @@ -550,11 +546,18 @@ void shoot(dynent *d, vec &targ) }; if(d->gunselect==GUN_SHOTGUN) createrays(from, to); - //if(d->quadmillis && attacktime>200) playsoundc(S_ITEMPUP); + //if(d->quadmillis && attacktime>200) playsoundc(S_ITEMPUP); + d->gunwait = guns[d->gunselect].attackdelay; + + if(d->gunselect==GUN_GRENADE) // activate + { + if(!curnade) new_nade(player1); + return; + } + shootv(d->gunselect, from, to, d, 0); - addmsg(1, 9, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), (int) grenade_throw ? (lastmillis-curnade->millis)/100 : 0 ); - d->gunwait = guns[d->gunselect].attackdelay; + addmsg(1, 9, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), 0 ); if(guns[d->gunselect].projspeed) return;