diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 5c6776e72..fb849c2b1 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1045,6 +1045,7 @@ set (PCH_SOURCES core/gameconfigfile.cpp core/gamecvars.cpp core/gamecontrol.cpp + core/gamefuncs.cpp core/gameinput.cpp core/interpolate.cpp core/inputstate.cpp diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp new file mode 100644 index 000000000..884968943 --- /dev/null +++ b/source/core/gamefuncs.cpp @@ -0,0 +1,147 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2021 Christoph Oelckers & Mitchell Richters + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +//------------------------------------------------------------------------- + +#include "gamefuncs.h" + + +//--------------------------------------------------------------------------- +// +// Unified chasecam function for all games. +// +//--------------------------------------------------------------------------- + +int cameradist, cameraclock; + +bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnum, binangle ang, fixedhoriz horiz, double const smoothratio) +{ + hitdata_t hitinfo; + binangle daang; + short bakcstat; + int newdist; + + assert(*psectnum >= 0 && *psectnum < MAXSECTORS); + + // Calculate new pos to shoot backwards, using averaged values from the big three. + int nx = xs_CRoundToInt(-ang.fcos() * (4352. / 3.)); + int ny = xs_CRoundToInt(-ang.fsin() * (4352. / 3.)); + int nz = xs_CRoundToInt(horiz.asq16() * (17. / 6144.)); + + vec3_t pvect = { *px, *py, *pz }; + bakcstat = pspr->cstat; + pspr->cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN); + updatesectorz(*px, *py, *pz, psectnum); + hitscan(&pvect, *psectnum, nx, ny, nz, &hitinfo, CLIPMASK1); + pspr->cstat = bakcstat; + + int hx = hitinfo.pos.x - *px; + int hy = hitinfo.pos.y - *py; + + if (*psectnum < 0) + { + return false; + } + + assert(*psectnum >= 0 && *psectnum < MAXSECTORS); + + // If something is in the way, make pp->camera_dist lower if necessary + if (abs(nx) + abs(ny) > abs(hx) + abs(hy)) + { + if (hitinfo.wall >= 0) + { + // Push you a little bit off the wall + *psectnum = hitinfo.sect; + daang = bvectangbam(wall[wall[hitinfo.wall].point2].x - wall[hitinfo.wall].x, + wall[wall[hitinfo.wall].point2].y - wall[hitinfo.wall].y); + newdist = nx * daang.bsin() + ny * -daang.bcos(); + + if (abs(nx) > abs(ny)) + hx -= MulScale(nx, newdist, 28); + else + hy -= MulScale(ny, newdist, 28); + } + else if (hitinfo.sprite < 0) + { + // Push you off the ceiling/floor + *psectnum = hitinfo.sect; + + if (abs(nx) > abs(ny)) + hx -= (nx >> 5); + else + hy -= (ny >> 5); + } + else + { + // If you hit a sprite that's not a wall sprite - try again. + spritetype* hspr = &sprite[hitinfo.sprite]; + + if (!(hspr->cstat & CSTAT_SPRITE_ALIGNMENT_WALL)) + { + bakcstat = hspr->cstat; + hspr->cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN); + calcChaseCamPos(px, py, pz, pspr, psectnum, ang, horiz, smoothratio); + hspr->cstat = bakcstat; + return false; + } + else + { + // same as wall calculation. + daang = buildang(pspr->ang - 512); + newdist = nx * daang.bsin() + ny * -daang.bcos(); + + if (abs(nx) > abs(ny)) + hx -= MulScale(nx, newdist, 28); + else + hy -= MulScale(ny, newdist, 28); + } + } + + if (abs(nx) > abs(ny)) + newdist = DivScale(hx, nx, 16); + else + newdist = DivScale(hy, ny, 16); + + if (newdist < cameradist) + cameradist = newdist; + } + + // Actually move you! (Camerdist is 65536 if nothing is in the way) + *px += MulScale(nx, cameradist, 16); + *py += MulScale(ny, cameradist, 16); + *pz += MulScale(nz, cameradist, 16); + + // Caculate clock using GameTicRate so it increases the same rate on all speed computers. + int myclock = PlayClock + MulScale(120 / GameTicRate, smoothratio, 16); + if (cameraclock == INT_MIN) + { + // Third person view was just started. + cameraclock = myclock; + } + + // Slowly increase cameradist until it reaches 65536. + cameradist = min(cameradist + ((myclock - cameraclock) << 10), 65536); + cameraclock = myclock; + + // Make sure psectnum is correct. + updatesectorz(*px, *py, *pz, psectnum); + + return true; +} diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h new file mode 100644 index 000000000..0c646aa86 --- /dev/null +++ b/source/core/gamefuncs.h @@ -0,0 +1,9 @@ +#pragma once + +#include "gamecontrol.h" +#include "buildtypes.h" +#include "binaryangle.h" + +extern int cameradist, cameraclock; + +bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnum, binangle ang, fixedhoriz horiz, double const smoothratio); \ No newline at end of file diff --git a/source/games/blood/src/view.cpp b/source/games/blood/src/view.cpp index e41ff6df3..2048fc333 100644 --- a/source/games/blood/src/view.cpp +++ b/source/games/blood/src/view.cpp @@ -40,6 +40,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_font.h" #include "statusbar.h" #include "automap.h" +#include "gamefuncs.h" #include "v_draw.h" #include "glbackend/glbackend.h" @@ -196,8 +197,7 @@ void viewInit(void) } int othercameradist = 1280; -int cameradist = -1; -int othercameraclock, cameraclock; +int othercameraclock; void CalcOtherPosition(spritetype *pSprite, int *pX, int *pY, int *pZ, int *vsectnum, int nAng, fixed_t zm, int smoothratio) { @@ -245,53 +245,6 @@ void CalcOtherPosition(spritetype *pSprite, int *pX, int *pY, int *pZ, int *vsec pSprite->cstat = bakCstat; } -void CalcPosition(spritetype *pSprite, int *pX, int *pY, int *pZ, int *vsectnum, int nAng, fixed_t zm, int smoothratio) -{ - int vX = MulScale(-Cos(nAng), 1280, 30); - int vY = MulScale(-Sin(nAng), 1280, 30); - int vZ = FixedToInt(MulScale(zm, 1280, 3))-(16<<8); - int bakCstat = pSprite->cstat; - pSprite->cstat &= ~256; - assert(*vsectnum >= 0 && *vsectnum < kMaxSectors); - FindSector(*pX, *pY, *pZ, vsectnum); - short nHSector; - int hX, hY; - hitscangoal.x = hitscangoal.y = 0x1fffffff; - vec3_t pos = { *pX, *pY, *pZ }; - hitdata_t hitdata; - hitscan(&pos, *vsectnum, vX, vY, vZ, &hitdata, CLIPMASK1); - nHSector = hitdata.sect; - hX = hitdata.pos.x; - hY = hitdata.pos.y; - int dX = hX-*pX; - int dY = hY-*pY; - if (abs(vX)+abs(vY) > abs(dX)+abs(dY)) - { - *vsectnum = nHSector; - dX -= Sgn(vX)<<6; - dY -= Sgn(vY)<<6; - int nDist; - if (abs(vX) > abs(vY)) - { - nDist = ClipHigh(DivScale(dX,vX, 16), cameradist); - } - else - { - nDist = ClipHigh(DivScale(dY,vY, 16), cameradist); - } - cameradist = nDist; - } - *pX += MulScale(vX, cameradist, 16); - *pY += MulScale(vY, cameradist, 16); - *pZ += MulScale(vZ, cameradist, 16); - int myclock = PlayClock + MulScale(4, smoothratio, 16); - cameradist = ClipHigh(cameradist+((myclock-cameraclock)<<10), 65536); - cameraclock = myclock; - assert(*vsectnum >= 0 && *vsectnum < kMaxSectors); - FindSector(*pX, *pY, *pZ, vsectnum); - pSprite->cstat = bakCstat; -} - // by NoOne: show warning msgs in game instead of throwing errors (in some cases) void viewSetSystemMessage(const char* pMessage, ...) { char buffer[1024]; va_list args; va_start(args, pMessage); @@ -633,11 +586,11 @@ void viewDrawScreen(bool sceneonly) } cZ += xs_CRoundToInt(cH.asq16() / 6553.6); cameradist = -1; - cameraclock = PlayClock +MulScale(4, (int)gInterpolate, 16); + cameraclock = PlayClock + MulScale(4, (int)gInterpolate, 16); } else { - CalcPosition(gView->pSprite, (int*)&cX, (int*)&cY, (int*)&cZ, &nSectnum, cA.asbuild(), cH.asq16(), (int)gInterpolate); + calcChaseCamPos((int*)&cX, (int*)&cY, (int*)&cZ, gView->pSprite, (short*)&nSectnum, cA, cH, gInterpolate); } CheckLink((int*)&cX, (int*)&cY, (int*)&cZ, &nSectnum); int v78 = interpolateang(gScreenTiltO, gScreenTilt, gInterpolate); diff --git a/source/games/duke/src/ccmds.cpp b/source/games/duke/src/ccmds.cpp index ed4ae4578..09bac2261 100644 --- a/source/games/duke/src/ccmds.cpp +++ b/source/games/duke/src/ccmds.cpp @@ -34,6 +34,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) #include "cheathandler.h" #include "c_dispatch.h" #include "gamestate.h" +#include "gamefuncs.h" #include "dukeactor.h" BEGIN_DUKE_NS diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index a27c8b6b1..29a56af54 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -126,7 +126,6 @@ void playerLookUp(int snum, ESyncBits actions); void playerLookDown(int snum, ESyncBits actions); void playerAimUp(int snum, ESyncBits actions); void playerAimDown(int snum, ESyncBits actions); -bool view(struct player_struct* pp, int* vx, int* vy, int* vz, short* vsectnum, int ang, fixed_t q16horiz, double smoothratio); void tracers(int x1, int y1, int z1, int x2, int y2, int z2, int n); DDukeActor* aim(DDukeActor* s, int aang); void checkweapons(struct player_struct* const p); diff --git a/source/games/duke/src/global.cpp b/source/games/duke/src/global.cpp index e3bbad1c8..d6ea7a92b 100644 --- a/source/games/duke/src/global.cpp +++ b/source/games/duke/src/global.cpp @@ -80,7 +80,6 @@ uint8_t enemysizecheat /*raat607*/, ufospawnsminion, pistonsound, chickenphase / //------------------------------------------------------------------------- // not serialized -int cameradist = 0, cameraclock = 0; // only for 3rd person view int otherp; // internal helper int actor_tog; // cheat helper int playerswhenstarted; // why is this needed? diff --git a/source/games/duke/src/global.h b/source/games/duke/src/global.h index 18579aeb9..d492d754e 100644 --- a/source/games/duke/src/global.h +++ b/source/games/duke/src/global.h @@ -46,8 +46,6 @@ struct DukeGameInfo extern DukeGameInfo gs; -extern int cameraclock; -extern int cameradist; extern int otherp; // transient helper, MP only extern int actor_tog; // cheat state extern intptr_t apScriptGameEvent[]; diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index cb731e9e2..32eda7fb8 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -1064,75 +1064,4 @@ void shootbloodsplat(DDukeActor* actor, int p, int sx, int sy, int sz, int sa, i } } - -//--------------------------------------------------------------------------- -// -// view - as in third person view (stupid name for this function) -// -//--------------------------------------------------------------------------- - -bool view(struct player_struct* pp, int* vx, int* vy, int* vz, short* vsectnum, int ang, fixed_t q16horiz, double smoothratio) -{ - spritetype* sp; - int i, nx, ny, nz, hx, hy, hitx, hity, hitz; - short bakcstat, hitsect, hitwall, daang; - DDukeActor* hitsprt; - - nx = -bcos(ang, -4); - ny = -bsin(ang, -4); - nz = q16horiz >> 9; - - sp = &pp->GetActor()->s; - - bakcstat = sp->cstat; - sp->cstat &= (short)~0x101; - - updatesectorz(*vx, *vy, *vz, vsectnum); - hitscan(*vx, *vy, *vz, *vsectnum, nx, ny, nz, &hitsect, &hitwall, &hitsprt, &hitx, &hity, &hitz, CLIPMASK1); - - if (*vsectnum < 0) - { - sp->cstat = bakcstat; - return false; - } - - hx = hitx - (*vx); hy = hity - (*vy); - if (abs(nx) + abs(ny) > abs(hx) + abs(hy)) - { - *vsectnum = hitsect; - if (hitwall >= 0) - { - daang = getangle(wall[wall[hitwall].point2].x - wall[hitwall].x, - wall[wall[hitwall].point2].y - wall[hitwall].y); - - i = nx * bsin(daang) + ny * -bcos(daang); - if (abs(nx) > abs(ny)) hx -= MulScale(nx, i, 28); - else hy -= MulScale(ny, i, 28); - } - else if (!hitsprt) - { - if (abs(nx) > abs(ny)) hx -= (nx >> 5); - else hy -= (ny >> 5); - } - if (abs(nx) > abs(ny)) i = DivScale(hx, nx, 16); - else i = DivScale(hy, ny, 16); - if (i < cameradist) cameradist = i; - } - *vx = (*vx) + MulScale(nx, cameradist, 16); - *vy = (*vy) + MulScale(ny, cameradist, 16); - *vz = (*vz) + MulScale(nz, cameradist, 16); - - int myclock = PlayClock + int(TICSPERFRAME/65536. * smoothratio); - if (cameraclock == INT_MIN) cameraclock = myclock; // third person view was just started. - - cameradist = min(cameradist + ((myclock - cameraclock) << 10), 65536); - cameraclock = myclock; - - updatesectorz(*vx, *vy, *vz, vsectnum); - - sp->cstat = bakcstat; - return true; -} - - END_DUKE_NS diff --git a/source/games/duke/src/render.cpp b/source/games/duke/src/render.cpp index 802f8b6f2..321e2bc31 100644 --- a/source/games/duke/src/render.cpp +++ b/source/games/duke/src/render.cpp @@ -587,10 +587,10 @@ void displayrooms(int snum, double smoothratio) { cposz -= isRR() ? 3840 : 3072; - if (!view(p, &cposx, &cposy, &cposz, §, cang.asbuild(), choriz.asq16(), smoothratio)) + if (!calcChaseCamPos(&cposx, &cposy, &cposz, &p->GetActor()->s, §, cang, choriz, smoothratio)) { cposz += isRR() ? 3840 : 3072; - view(p, &cposx, &cposy, &cposz, §, cang.asbuild(), choriz.asq16(), smoothratio); + calcChaseCamPos(&cposx, &cposy, &cposz, &p->GetActor()->s, §, cang, choriz, smoothratio); } } diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp index d5ed427f4..0110fb5e5 100644 --- a/source/games/sw/src/draw.cpp +++ b/source/games/sw/src/draw.cpp @@ -38,6 +38,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "mytypes.h" #include "gamecontrol.h" +#include "gamefuncs.h" #include "network.h" #include "pal.h" #include "player.h" @@ -925,133 +926,6 @@ post_analyzesprites(void) } #endif - -bool -BackView(int *nx, int *ny, int *nz, short *vsect, binangle *nang, fixed_t q16horiz) -{ - vec3_t n = { *nx, *ny, *nz }; - SPRITEp sp; - hitdata_t hitinfo; - int i, vx, vy, vz, hx, hy; - short bakcstat, daang; - PLAYERp pp = &Player[screenpeek]; - short ang; - - ASSERT(*vsect >= 0 && *vsect < MAXSECTORS); - - ang = nang->asbuild() + pp->view_outside_dang; - - // Calculate the vector (nx,ny,nz) to shoot backwards - vx = -bcos(ang, -3); - vy = -bsin(ang, -3); - vz = q16horiz >> 8; - - // Player sprite of current view - sp = &sprite[pp->PlayerSprite]; - - bakcstat = sp->cstat; - RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); - - // Make sure sector passed to FAFhitscan is correct - //COVERupdatesector(*nx, *ny, vsect); - - hitscan(&n, *vsect, vx, vy, vz, - &hitinfo, CLIPMASK_PLAYER); - - if (*vsect < 0) - { - sp->cstat = bakcstat; - return false; - } - - ASSERT(*vsect >= 0 && *vsect < MAXSECTORS); - - sp->cstat = bakcstat; // Restore cstat - - hx = hitinfo.pos.x - (*nx); - hy = hitinfo.pos.y - (*ny); - - // If something is in the way, make pp->camera_dist lower if necessary - if (abs(vx) + abs(vy) > abs(hx) + abs(hy)) - { - if (hitinfo.wall >= 0) // Push you a little bit off the wall - { - *vsect = hitinfo.sect; - - daang = getangle(wall[wall[hitinfo.wall].point2].x - wall[hitinfo.wall].x, - wall[wall[hitinfo.wall].point2].y - wall[hitinfo.wall].y); - - i = vx * bsin(daang) + vy * -bcos(daang); - if (abs(vx) > abs(vy)) - hx -= MulScale(vx, i, 28); - else - hy -= MulScale(vy, i, 28); - } - else if (hitinfo.sprite < 0) // Push you off the ceiling/floor - { - *vsect = hitinfo.sect; - - if (abs(vx) > abs(vy)) - hx -= (vx >> 5); - else - hy -= (vy >> 5); - } - else - { - SPRITEp hsp = &sprite[hitinfo.sprite]; - int flag_backup; - - // if you hit a sprite that's not a wall sprite - try again - if (!TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL)) - { - flag_backup = hsp->cstat; - RESET(hsp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); - ASSERT(*vsect >= 0 && *vsect < MAXSECTORS); - BackView(nx, ny, nz, vsect, nang, q16horiz); - hsp->cstat = flag_backup; - return false; - } - else - { - // same as wall calculation - daang = NORM_ANGLE(sp->ang-512); - - i = vx * bsin(daang) + vy * -bcos(daang); - if (abs(vx) > abs(vy)) - hx -= MulScale(vx, i, 28); - else - hy -= MulScale(vy, i, 28); - } - - } - - if (abs(vx) > abs(vy)) - i = IntToFixed(hx) / vx; - else - i = IntToFixed(hy) / vy; - - if (i < pp->camera_dist) - pp->camera_dist = i; - } - - // Actually move you! (Camerdist is 65536 if nothing is in the way) - *nx = (*nx) + MulScale(vx, pp->camera_dist, 16); - *ny = (*ny) + MulScale(vy, pp->camera_dist, 16); - *nz = (*nz) + MulScale(vz, pp->camera_dist, 16); - - // Slowly increase pp->camera_dist until it reaches 65536 - // Synctics is a timer variable so it increases the same rate - // on all speed computers - pp->camera_dist = min(pp->camera_dist + (3 << 10), 65536); - //pp->camera_dist = min(pp->camera_dist + (synctics << 10), 65536); - - // Make sure vsect is correct - updatesectorz(*nx, *ny, *nz, vsect); - - *nang += buildang(pp->view_outside_dang); - return true; -} - void CircleCamera(int *nx, int *ny, int *nz, short *vsect, binangle *nang, fixed_t q16horiz) { @@ -1705,10 +1579,10 @@ drawscreen(PLAYERp pp, double smoothratio) { tz -= 8448; - if (!BackView(&tx, &ty, &tz, &tsectnum, &tang, thoriz.asq16())) + if (!calcChaseCamPos(&tx, &ty, &tz, &sprite[pp->PlayerSprite], &tsectnum, tang, thoriz, smoothratio)) { tz += 8448; - BackView(&tx, &ty, &tz, &tsectnum, &tang, thoriz.asq16()); + calcChaseCamPos(&tx, &ty, &tz, &sprite[pp->PlayerSprite], &tsectnum, tang, thoriz, smoothratio); } } else diff --git a/source/games/sw/src/game.h b/source/games/sw/src/game.h index f33c4da8f..d0f8051ce 100644 --- a/source/games/sw/src/game.h +++ b/source/games/sw/src/game.h @@ -839,7 +839,6 @@ struct PLAYERstruct SPRITEp hi_sp, lo_sp; SPRITEp last_camera_sp; - int camera_dist; // view mode dist int circle_camera_dist; int six,siy,siz; // save player interp position for PlayerSprite short siang; diff --git a/source/games/sw/src/osdcmds.cpp b/source/games/sw/src/osdcmds.cpp index d4c785d6a..0dbdc4617 100644 --- a/source/games/sw/src/osdcmds.cpp +++ b/source/games/sw/src/osdcmds.cpp @@ -44,6 +44,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "jsector.h" #include "network.h" #include "gamestate.h" +#include "gamefuncs.h" #include "player.h" BEGIN_SW_NS @@ -99,22 +100,14 @@ void GameInterface::ToggleThirdPerson() { if (gamestate != GS_LEVEL) return; auto pp = &Player[myconnectindex]; - if (inputState.ShiftPressed()) + if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) { - if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) - pp->view_outside_dang = NORM_ANGLE(pp->view_outside_dang + 256); + RESET(pp->Flags, PF_VIEW_FROM_OUTSIDE); } else { - if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) - { - RESET(pp->Flags, PF_VIEW_FROM_OUTSIDE); - } - else - { - SET(pp->Flags, PF_VIEW_FROM_OUTSIDE); - pp->camera_dist = 0; - } + SET(pp->Flags, PF_VIEW_FROM_OUTSIDE); + cameradist = 0; } }