diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index 7b427d32..928f285e 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -383,22 +383,27 @@ COMMANDN(jump, jumpn, ARG_DOWN); COMMAND(attack, ARG_DOWN); COMMAND(showscores, ARG_DOWN); -void fixplayer1range() +void fixcamerarange(physent *cam) { const float MAXPITCH = 90.0f; - if(player1->pitch>MAXPITCH) player1->pitch = MAXPITCH; - if(player1->pitch<-MAXPITCH) player1->pitch = -MAXPITCH; - while(player1->yaw<0.0f) player1->yaw += 360.0f; - while(player1->yaw>=360.0f) player1->yaw -= 360.0f; + if(cam->pitch>MAXPITCH) cam->pitch = MAXPITCH; + if(cam->pitch<-MAXPITCH) cam->pitch = -MAXPITCH; + while(cam->yaw<0.0f) cam->yaw += 360.0f; + while(cam->yaw>=360.0f) cam->yaw -= 360.0f; }; void mousemove(int dx, int dy) { - if(player1->state==CS_DEAD || intermission) return; + if(intermission) return; const float SENSF = 33.0f; // try match quake sens - player1->yaw += (dx/SENSF)*(sensitivity/(float)sensitivityscale); - player1->pitch -= (dy/SENSF)*(sensitivity/(float)sensitivityscale)*(invmouse ? -1 : 1); - fixplayer1range(); + camera1->yaw += (dx/SENSF)*(sensitivity/(float)sensitivityscale); + camera1->pitch -= (dy/SENSF)*(sensitivity/(float)sensitivityscale)*(invmouse ? -1 : 1); + fixcamerarange(); + if(camera1!=player1 && player1->state!=CS_DEAD) + { + player1->yaw = camera1->yaw; + player1->pitch = camera1->pitch; + }; }; // damage arriving from the network, monsters, yourself, all ends up here. diff --git a/source/src/cube.h b/source/src/cube.h index 5c999626..520bcad8 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -300,7 +300,7 @@ struct model struct mapmodelinfo { int rad, h, zoff; string name; model *m; }; -enum { ENT_PLAYER = 0, ENT_BOT, ENT_BOUNCE }; +enum { ENT_PLAYER = 0, ENT_BOT, ENT_CAMERA, ENT_BOUNCE }; enum { CS_ALIVE = 0, CS_DEAD, CS_LAGGED, CS_EDITING }; @@ -539,6 +539,7 @@ extern sqr *world, *wmip[]; // map data, the mips are sequential 2D extern header hdr; // current map header extern int sfactor, ssize; // ssize = 2^sfactor extern int cubicsize, mipsize; // cubicsize = ssize^2 +extern physent *camera1; // camera representing perspective of player, usually player1 extern playerent *player1; // special client ent that receives input and acts as camera extern vector players; // all the other clients (in multiplayer) extern vector bounceents; diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 43cee263..cb3168d6 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -105,7 +105,7 @@ VAR(flrceil,0,0,2); void cursorupdate() // called every frame from hud { - flrceil = ((int)(player1->pitch>=0))*2; + flrceil = ((int)(camera1->pitch>=0))*2; volatile float x = worldpos.x; // volatile needed to prevent msvc7 optimizer bug? volatile float y = worldpos.y; @@ -119,8 +119,8 @@ void cursorupdate() // called every frame fr if(fabs(sheight(s,s,z)-z)>1) // selected wall { - x += x>player1->o.x ? 0.5f : -0.5f; // find right wall cube - y += y>player1->o.y ? 0.5f : -0.5f; + x += x>camera1->o.x ? 0.5f : -0.5f; // find right wall cube + y += y>camera1->o.y ? 0.5f : -0.5f; cx = (int)x; cy = (int)y; @@ -461,7 +461,7 @@ void edittag(int tag) void newent(char *what, char *a1, char *a2, char *a3, char *a4) { EDITSEL; - newentity(sel.x, sel.y, (int)player1->o.z, what, ATOI(a1), ATOI(a2), ATOI(a3), ATOI(a4)); + newentity(sel.x, sel.y, (int)camera1->o.z, what, ATOI(a1), ATOI(a2), ATOI(a3), ATOI(a4)); }; COMMANDN(select, selectpos, ARG_4INT); diff --git a/source/src/main.cpp b/source/src/main.cpp index c9a06172..61484236 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -342,14 +342,14 @@ int main(int argc, char **argv) frames++; fps = (1000.0f/elapsed+fps*10)/11; - computeraytable(player1->o.x, player1->o.y); + computeraytable(camera1->o.x, camera1->o.y); SDL_GL_SwapBuffers(); extern void updatevol(); updatevol(); if(framesinmap++<5) // cheap hack to get rid of initial sparklies, even when triple buffering etc. { - player1->yaw += 5; + camera1->yaw += 5; gl_drawframe(scr_w, scr_h, 1.0f, fps); - player1->yaw -= 5; + camera1->yaw -= 5; }; gl_drawframe(scr_w, scr_h, fpshighfps ? fps/highfps : 1.0f), fps); //SDL_Delay(100); diff --git a/source/src/menus.cpp b/source/src/menus.cpp index edff8a8f..1764df13 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -105,17 +105,9 @@ void rendermenumdl() float t = (lastmillis-player1->lastaction)/1000.0f; if(t >= 1.6f) t = 1.6f; - if(player1->state==CS_DEAD) - { - player1->pitch = (float) sin(t)*(-70.0f-player1->oldpitch)+player1->oldpitch; - glTranslatef(player1->o.x, -(player1->eyeheight-sin(t)*7.0f-player1->o.z), player1->o.y); - } - else - { - glTranslatef(player1->o.x, player1->o.z, player1->o.y); - } - glRotatef(player1->yaw+90+180, 0, -1, 0); - glRotatef(player1->pitch, 0, 0, 1); + glTranslatef(camera1->o.x, camera1->o.z, camera1->o.y); + glRotatef(camera1->yaw+90+180, 0, -1, 0); + glRotatef(camera1->pitch, 0, 0, 1); bool isplayermodel = !strncmp(m.mdl, "playermodels", strlen("playermodels")); diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 9894186d..efa436f1 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -115,7 +115,7 @@ bool collide(physent *d, bool spawn, float drop, float rise) loopv(players) // collide with other players { playerent *o = players[i]; - if(!o || o==d) continue; + if(!o || o==d || (o==player1 && d->type==ENT_CAMERA)) continue; if(!plcollide(d, o, headspace, hi, lo)) return false; }; @@ -261,6 +261,7 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) pl->o.y += f*d.y; pl->o.z += f*d.z; if(collide(pl, false, drop, rise)) continue; + if(pl->type==ENT_CAMERA) return; // player stuck, try slide along y axis pl->o.x -= f*d.x; if(collide(pl, false, drop, rise)) @@ -304,7 +305,9 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) if(pl->roll>maxroll) pl->roll = (float)maxroll; if(pl->roll<-maxroll) pl->roll = (float)-maxroll; }; - + + if(pl->type==ENT_CAMERA) return; + // play sounds on water transitions if(!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; } diff --git a/source/src/protos.h b/source/src/protos.h index 0eb8c965..579eb07e 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -103,7 +103,7 @@ extern const char *modestr(int n); extern void zapplayer(playerent *&d); extern playerent *getclient(int cn); extern void timeupdate(int timeremain); -extern void fixplayer1range(); +extern void fixcamerarange(physent *cam = camera1); extern void respawnself(); // EDIT: AH extern void ctf_death(); //game mode extras @@ -211,6 +211,7 @@ extern void demoblend(int damage); // physics extern void moveplayer(physent *pl, int moveres, bool local); +extern void moveplayer(physent *pl, int moveres, bool local, int curtime); extern bool collide(physent *d, bool spawn, float drop, float rise); extern void entinmap(physent *d); extern void setentphysics(int mml, int mmr); diff --git a/source/src/renderextras.cpp b/source/src/renderextras.cpp index cc38c165..cfed184f 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderextras.cpp @@ -320,7 +320,7 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat readmatrices(); if(editmode) { - if(cursordepth==1.0f) worldpos = player1->o; + if(cursordepth==1.0f) worldpos = camera1->o; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); cursorupdate(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -533,7 +533,7 @@ void addshotline(dynent *d, vec &from, vec &to) shotline *s = &shotlines[i]; if(s->inuse) continue; int start = 10; - if(player1->o.dist(to) <= 10.0f) start = 8; + if(camera1->o.dist(to) <= 10.0f) start = 8; else start = 5; vec unitv; diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 30ecf114..c88e75cf 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -57,6 +57,8 @@ void gl_init(int w, int h, int bpp, int depth, int fsaa) gluDeleteQuadric(qsphere); if(fsaa) glEnable(GL_MULTISAMPLE); + + camera1 = player1; }; Texture *crosshair = NULL; @@ -261,33 +263,41 @@ VARF(gamma, 30, 100, 300, }; }); -void trypitch(int i) { player1->pitch = (float)i; } +physent *camera1 = NULL; + +void trypitch(int i) { camera1->pitch = (float)i; } COMMAND(trypitch, ARG_1INT); +void recomputecamera() +{ + if(editmode || player1->state!=CS_DEAD) + { + camera1 = player1; + } + else + { + static physent deathcam; + if(camera1==&deathcam) return; + deathcam = *(physent *)player1; + deathcam.reset(); + deathcam.type = ENT_CAMERA; + deathcam.roll = 0; + deathcam.move = -1; + camera1 = &deathcam; + + loopi(10) moveplayer(camera1, 10, true, 50); + }; +}; + 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); + + glRotated(camera1->roll,0.0,0.0,1.0); + glRotated(camera1->pitch,-1.0,0.0,0.0); + glRotated(camera1->yaw,0.0,1.0,0.0); - glTranslated(-player1->o.x, player1->eyeheight-sin(t)*7.0f-player1->o.z, -player1->o.y); - //glTranslated(-player1->o.x, -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->o.z, -player1->o.y); - }; + glTranslated(-camera1->o.x, -camera1->o.z, -camera1->o.y); }; VAR(fov, 90, 105, 120); @@ -323,7 +333,7 @@ void drawhudgun(int w, int h, float aspect, int farplane) glDisable(GL_CULL_FACE); }; -bool outsidemap(dynent *pl) +bool outsidemap(physent *pl) { if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) return true; sqr *s = S((int)pl->o.x, (int)pl->o.y); @@ -334,11 +344,13 @@ bool outsidemap(dynent *pl) void gl_drawframe(int w, int h, float changelod, float curfps) { + recomputecamera(); + float hf = hdr.waterlevel-0.3f; float fovy = (float)fov*h/w; float aspect = w/(float)h; - bool underwater = player1->o.zo.z>16)/256.0f, ((fogcolour>>8)&255)/256.0f, (fogcolour&255)/256.0f, 1.0f }; @@ -353,7 +365,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) glFogi(GL_FOG_END, (fog+96)/8); }; - glClear((outsidemap(player1) ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); + glClear((outsidemap(camera1) ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -367,8 +379,8 @@ void gl_drawframe(int w, int h, float changelod, float curfps) resetcubes(); - render_world(player1->o.x, player1->o.y, player1->o.z, changelod, - (int)player1->yaw, (int)player1->pitch, (float)fov, w, h); + render_world(camera1->o.x, camera1->o.y, camera1->o.z, changelod, + (int)camera1->yaw, (int)camera1->pitch, (float)fov, w, h); finishstrips(); setupworld(); @@ -376,8 +388,8 @@ void gl_drawframe(int w, int h, float changelod, float curfps) renderstripssky(); glLoadIdentity(); - glRotated(player1->pitch, -1.0, 0.0, 0.0); - glRotated(player1->yaw, 0.0, 1.0, 0.0); + glRotated(camera1->pitch, -1.0, 0.0, 0.0); + glRotated(camera1->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); diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index c98f06d9..34e1ea26 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -90,7 +90,7 @@ void rendermodel(char *mdl, int anim, int tex, float rad, float x, float y, floa model *m = loadmodel(mdl); if(!m) return; - if(rad > 0 && isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; + if(rad > 0 && isoccluded(camera1->o.x, camera1->o.y, x-rad, z-rad, rad*2)) return; int ix = (int)x; int iy = (int)z; diff --git a/source/src/savegamedemo.cpp b/source/src/savegamedemo.cpp index 90720aef..306b596d 100644 --- a/source/src/savegamedemo.cpp +++ b/source/src/savegamedemo.cpp @@ -319,7 +319,7 @@ void demoplaybackstep() catmulrom(z->o, a->o, b->o, c->o, bf, player1->o); catmulrom(*(vec *)&z->yaw, *(vec *)&a->yaw, *(vec *)&b->yaw, *(vec *)&c->yaw, bf, *(vec *)&player1->yaw); }; - fixplayer1range(); + fixcamerarange(player1); }; break; }; diff --git a/source/src/sound.cpp b/source/src/sound.cpp index 17c25723..fa085f38 100644 --- a/source/src/sound.cpp +++ b/source/src/sound.cpp @@ -163,12 +163,12 @@ void updatechanvol(int chan, vec *loc) if(loc) { vec v; - float dist = player1->o.dist(*loc, v); + float dist = camera1->o.dist(*loc, v); vol -= (int)(dist*3*soundvol/255); // simple mono distance attenuation if(vol<0) vol = 0; if(stereo && (v.x != 0 || v.y != 0)) { - float yaw = -atan2f(v.x, v.y) - player1->yaw*RAD; // relative angle of sound along X-Y axis + float yaw = -atan2f(v.x, v.y) - camera1->yaw*RAD; // relative angle of sound along X-Y axis pan = int(255.9f*(0.5f*sinf(yaw)+0.5f)); // range is from 0 (left) to 255 (right) }; }; diff --git a/source/src/world.cpp b/source/src/world.cpp index 37b19faf..f744033b 100644 --- a/source/src/world.cpp +++ b/source/src/world.cpp @@ -176,7 +176,7 @@ int closestent() // used for delent and edit mode ent display entity &e = ents[i]; if(e.type==NOTUSED) continue; vec v(e.x, e.y, e.z); - float dist = v.dist(player1->o); + float dist = v.dist(camera1->o); if(distyaw; + e.attr1 = (int)camera1->yaw; break; }; addmsg(SV_EDITENT, "ri9", ents.length(), type, e.x, e.y, e.z, e.attr1, e.attr2, e.attr3, e.attr4); diff --git a/source/src/worldocull.cpp b/source/src/worldocull.cpp index 3b65ce2e..c39907da 100644 --- a/source/src/worldocull.cpp +++ b/source/src/worldocull.cpp @@ -21,10 +21,10 @@ void computeraytable(float vx, float vy) odist = getvar("fog")*1.5f; - float apitch = (float)fabs(player1->state==CS_DEAD ? -90.0f : player1->pitch); + float apitch = (float)fabs(player1->state==CS_DEAD ? -90.0f : camera1->pitch); float af = getvar("fov")/2+apitch/1.5f+3; - float byaw = (player1->yaw-90+af)/360*PI2; - float syaw = (player1->yaw-90-af)/360*PI2; + float byaw = (camera1->yaw-90+af)/360*PI2; + float syaw = (camera1->yaw-90-af)/360*PI2; loopi(NUMRAYS) { diff --git a/source/src/worldrender.cpp b/source/src/worldrender.cpp index add591be..80e67783 100644 --- a/source/src/worldrender.cpp +++ b/source/src/worldrender.cpp @@ -117,7 +117,7 @@ void render_seg_new(float vx, float vy, float vh, int mip, int x, int y, int xs, float fsize = (float)(1<occluded = isoccluded(player1->o.x, player1->o.y, (float)(ox<occluded = isoccluded(camera1->o.x, camera1->o.y, (float)(ox<>mip;