From a5b368163020f529173ca18c80c5a051f1059dbb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 Oct 2020 09:31:15 +0200 Subject: [PATCH] - foundation for a better collision info management. The way this is handled is the main reason why Build maps are size limited, but since it is extremely invasive it needs to be taken out of the game code piece by piece, this is the framework for doing this for Duke. --- source/build/include/build.h | 2 ++ source/games/duke/src/actors.cpp | 8 ++--- source/games/duke/src/actors_d.cpp | 39 +++++++++++---------- source/games/duke/src/actors_r.cpp | 42 +++++++++++------------ source/games/duke/src/dispatch.cpp | 3 +- source/games/duke/src/duke3d.h | 2 +- source/games/duke/src/dukeactor.h | 25 +++++++++++++- source/games/duke/src/types.h | 54 ++++++++++++++++++++++++++++++ 8 files changed, 123 insertions(+), 52 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index 7c2bf24cf..56a5669d0 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -926,6 +926,7 @@ extern void(*PolymostProcessVoxels_Callback)(void); // Names taken from DukeGDX enum EHitBits { + kHitNone = 0, kHitTypeMask = 0xE000, kHitIndexMask = 0x1FFF, kHitSector = 0x4000, @@ -933,6 +934,7 @@ enum EHitBits kHitSprite = 0xC000, }; + #include "iterators.h" #endif // build_h_ diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 7a01e17b4..2169f78f0 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -226,14 +226,12 @@ void clearcamera(player_struct* ps) int ssp(DDukeActor* const actor, unsigned int cliptype) //The set sprite function { - int movetype; + Collision c; - movetype = fi.movesprite(actor->GetIndex(), + return movesprite_ex(actor, (actor->s.xvel * (sintable[(actor->s.ang + 512) & 2047])) >> 14, (actor->s.xvel * (sintable[actor->s.ang & 2047])) >> 14, actor->s.zvel, - cliptype); - - return (movetype == 0); + cliptype, c) == kHitNone; } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index c11b67717..0d57798b2 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -538,13 +538,14 @@ SKIPWALLCHECK: // //--------------------------------------------------------------------------- -int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigned int cliptype) + +int movesprite_ex_d(DDukeActor* actor, int xchange, int ychange, int zchange, unsigned int cliptype, Collision &result) { int daz, h, oldx, oldy; short retval, dasectnum, cd; - auto spri = &sprite[spritenum]; - int bg = badguy(spri); + auto spri = &actor->s; + int bg = badguy(actor); if (spri->statnum == 5 || (bg && spri->xrepeat < 4)) { @@ -552,14 +553,14 @@ int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigne spri->y += (ychange * TICSPERFRAME) >> 2; spri->z += (zchange * TICSPERFRAME) >> 2; if (bg) - setsprite(spritenum, spri->x, spri->y, spri->z); - return 0; + setsprite(actor, spri->x, spri->y, spri->z); + return result.setNone(); } dasectnum = spri->sectnum; daz = spri->z; - h = ((tilesiz[spri->picnum].y * spri->yrepeat) << 1); + h = ((tileHeight(spri->picnum) * spri->yrepeat) << 1); daz -= h; if (bg) @@ -573,7 +574,7 @@ int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigne { if (spri->picnum == LIZMAN) cd = 292; - else if (actorflag(spritenum, SFLAG_BADGUY)) + else if (actorflag(actor->GetIndex(), SFLAG_BADGUY)) cd = spri->clipdist << 2; else cd = 192; @@ -583,7 +584,7 @@ int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigne // conditional code from hell... if (dasectnum < 0 || (dasectnum >= 0 && - ((hittype[spritenum].actorstayput >= 0 && hittype[spritenum].actorstayput != dasectnum) || + ((actor->actorstayput >= 0 && actor->actorstayput != dasectnum) || ((spri->picnum == BOSS2) && spri->pal == 0 && sector[dasectnum].lotag != 3) || ((spri->picnum == BOSS1 || spri->picnum == BOSS2) && sector[dasectnum].lotag == ST_1_ABOVE_WATER) || (sector[dasectnum].lotag == ST_1_ABOVE_WATER && (spri->picnum == LIZMAN || (spri->picnum == LIZTROOP && spri->zvel == 0))) @@ -594,17 +595,17 @@ int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigne spri->y = oldy; if (sector[dasectnum].lotag == ST_1_ABOVE_WATER && spri->picnum == LIZMAN) spri->ang = (krand()&2047); - else if ((hittype[spritenum].temp_data[0]&3) == 1 && spri->picnum != COMMANDER) + else if ((actor->temp_data[0]&3) == 1 && spri->picnum != COMMANDER) spri->ang = (krand()&2047); - setsprite(spritenum,oldx,oldy,spri->z); + setsprite(actor,oldx,oldy,spri->z); if (dasectnum < 0) dasectnum = 0; - return (16384+dasectnum); + return result.setSector(dasectnum); } - if ((retval&49152) >= 32768 && (hittype[spritenum].cgg==0)) spri->ang += 768; + if ((retval & kHitTypeMask) != kHitSector && (actor->cgg == 0)) spri->ang += 768; } else { - if (spri->statnum == 4) + if (spri->statnum == STAT_PROJECTILE) retval = clipmove(&spri->x, &spri->y, &daz, &dasectnum, ((xchange * TICSPERFRAME) << 11), ((ychange * TICSPERFRAME) << 11), 8L, (4 << 8), (4 << 8), cliptype); else @@ -614,17 +615,15 @@ int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigne if (dasectnum >= 0) if ((dasectnum != spri->sectnum)) - changespritesect(spritenum, dasectnum); + changespritesect(actor, dasectnum); daz = spri->z + ((zchange * TICSPERFRAME) >> 3); - if ((daz > hittype[spritenum].ceilingz) && (daz <= hittype[spritenum].floorz)) + if ((daz > actor->ceilingz) && (daz <= actor->floorz)) spri->z = daz; - else - if (retval == 0) - return(16384 + dasectnum); + else if (retval == 0) + return result.setSector(dasectnum); - return(retval); + return result.setFromEngine(retval); } - //--------------------------------------------------------------------------- // // diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index aad1e3123..32304e89c 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -375,14 +375,12 @@ SKIPWALLCHECK: // //--------------------------------------------------------------------------- -int movesprite_r(short spritenum, int xchange, int ychange, int zchange, unsigned int cliptype) +int movesprite_ex_r(DDukeActor* actor, int xchange, int ychange, int zchange, unsigned int cliptype, Collision &result) { int daz, h, oldx, oldy; short retval, dasectnum, cd; - char bg; - - auto spri = &sprite[spritenum]; - bg = badguy(&sprite[spritenum]); + auto spri = &actor->s; + int bg = badguy(actor); if (spri->statnum == 5 || (bg && spri->xrepeat < 4)) { @@ -390,14 +388,14 @@ int movesprite_r(short spritenum, int xchange, int ychange, int zchange, unsigne spri->y += (ychange * TICSPERFRAME) >> 2; spri->z += (zchange * TICSPERFRAME) >> 2; if (bg) - setsprite(spritenum, spri->x, spri->y, spri->z); - return 0; + setsprite(actor, spri->x, spri->y, spri->z); + return result.setNone(); } dasectnum = spri->sectnum; daz = spri->z; - h = ((tilesiz[spri->picnum].y * spri->yrepeat) << 1); + h = ((tileHeight(spri->picnum) * spri->yrepeat) << 1); daz -= h; if (bg) @@ -407,48 +405,46 @@ int movesprite_r(short spritenum, int xchange, int ychange, int zchange, unsigne if (spri->xrepeat > 60) retval = clipmove(&spri->x, &spri->y, &daz, &dasectnum, ((xchange * TICSPERFRAME) << 11), ((ychange * TICSPERFRAME) << 11), 1024L, (4 << 8), (4 << 8), cliptype); - else + else { cd = 192; retval = clipmove(&spri->x, &spri->y, &daz, &dasectnum, ((xchange * TICSPERFRAME) << 11), ((ychange * TICSPERFRAME) << 11), cd, (4 << 8), (4 << 8), cliptype); } - if (dasectnum < 0 || (dasectnum >= 0 && - hittype[spritenum].actorstayput >= 0 && hittype[spritenum].actorstayput != dasectnum)) + if (dasectnum < 0 || (dasectnum >= 0 && actor->actorstayput >= 0 && actor->actorstayput != dasectnum)) { spri->x = oldx; spri->y = oldy; if (sector[dasectnum].lotag == ST_1_ABOVE_WATER) spri->ang = (krand() & 2047); - else if ((hittype[spritenum].temp_data[0] & 3) == 1) + else if ((actor->temp_data[0] & 3) == 1) spri->ang = (krand() & 2047); - setsprite(spritenum, oldx, oldy, spri->z); + setsprite(actor, oldx, oldy, spri->z); if (dasectnum < 0) dasectnum = 0; - return (16384 + dasectnum); + return result.setSector(dasectnum); } - if ((retval & 49152) >= 32768 && (hittype[spritenum].cgg == 0)) spri->ang += 768; + if ((retval & kHitTypeMask) != kHitSector && (actor->cgg == 0)) spri->ang += 768; } else { - if (spri->statnum == 4) + if (spri->statnum == STAT_PROJECTILE) retval = clipmove(&spri->x, &spri->y, &daz, &dasectnum, ((xchange * TICSPERFRAME) << 11), ((ychange * TICSPERFRAME) << 11), 8L, (4 << 8), (4 << 8), cliptype); else retval = - clipmove(&spri->x, &spri->y, &daz, &dasectnum, ((xchange * TICSPERFRAME) << 11), ((ychange * TICSPERFRAME) << 11), 128L, (4 << 8), (4 << 8), cliptype); + clipmove(&spri->x, &spri->y, &daz, &dasectnum, ((xchange * TICSPERFRAME) << 11), ((ychange * TICSPERFRAME) << 11), 128, (4 << 8), (4 << 8), cliptype); } if (dasectnum >= 0) if ((dasectnum != spri->sectnum)) - changespritesect(spritenum, dasectnum); + changespritesect(actor, dasectnum); daz = spri->z + ((zchange * TICSPERFRAME) >> 3); - if ((daz > hittype[spritenum].ceilingz) && (daz <= hittype[spritenum].floorz)) + if ((daz > actor->ceilingz) && (daz <= actor->floorz)) spri->z = daz; - else - if (retval == 0) - return(16384 + dasectnum); + else if (retval == 0) + return result.setSector(dasectnum); - return(retval); + return result.setFromEngine(retval); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/dispatch.cpp b/source/games/duke/src/dispatch.cpp index e1cb71262..ce6aca306 100644 --- a/source/games/duke/src/dispatch.cpp +++ b/source/games/duke/src/dispatch.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "ns.h" #include "global.h" +#include "dukeactor.h" BEGIN_DUKE_NS @@ -65,8 +66,6 @@ void addweapon_d(struct player_struct* p, int weapon); void addweapon_r(struct player_struct* p, int weapon); void hitradius_d(short i, int r, int hp1, int hp2, int hp3, int hp4); void hitradius_r(short i, int r, int hp1, int hp2, int hp3, int hp4); -int movesprite_d(short spritenum, int xchange, int ychange, int zchange, unsigned int cliptype); -int movesprite_r(short spritenum, int xchange, int ychange, int zchange, unsigned int cliptype); void lotsofmoney_d(spritetype* s, short n); void lotsofmail_d(spritetype* s, short n); void lotsofpaper_d(spritetype* s, short n); diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 76b5e29af..240dbbc30 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -88,7 +88,7 @@ struct Dispatcher bool (*floorspace)(int sectnum); void (*addweapon)(struct player_struct *p, int weapon); void (*hitradius)(short i, int r, int hp1, int hp2, int hp3, int hp4); - int (*movesprite)(short spritenum, int xchange, int ychange, int zchange, unsigned int cliptype); + int (*movesprite)(int spritenum, int xchange, int ychange, int zchange, unsigned int cliptype); void (*lotsofmoney)(spritetype *s, short n); void (*lotsofmail)(spritetype *s, short n); void (*lotsofpaper)(spritetype *s, short n); diff --git a/source/games/duke/src/dukeactor.h b/source/games/duke/src/dukeactor.h index 83ac4ff04..de7f7f7c9 100644 --- a/source/games/duke/src/dukeactor.h +++ b/source/games/duke/src/dukeactor.h @@ -68,7 +68,6 @@ public: } }; - inline DDukeActor* player_struct::GetActor() { return &hittype[i]; @@ -213,5 +212,29 @@ inline int ssp(int i, unsigned int cliptype) //The set sprite function return ssp(&hittype[i], cliptype); } +int movesprite_ex_d(DDukeActor* actor, int xchange, int ychange, int zchange, unsigned int cliptype, Collision& result); +int movesprite_ex_r(DDukeActor* actor, int xchange, int ychange, int zchange, unsigned int cliptype, Collision& result); + +inline int movesprite_d(int actor, int xchange, int ychange, int zchange, unsigned int cliptype) +{ + Collision c; + movesprite_ex_d(&hittype[actor], xchange, ychange, zchange, cliptype, c); + return c.legacyVal; +} + +inline int movesprite_r(int actor, int xchange, int ychange, int zchange, unsigned int cliptype) +{ + Collision c; + movesprite_ex_r(&hittype[actor], xchange, ychange, zchange, cliptype, c); + return c.legacyVal; +} + +inline int movesprite_ex(DDukeActor* actor, int xchange, int ychange, int zchange, unsigned int cliptype, Collision& result) +{ + auto f = isRR() ? movesprite_ex_r : movesprite_ex_d; + return f(actor, xchange, ychange, zchange, cliptype, result); +} + + END_DUKE_NS diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index 0ffd23f8d..d62fcae1f 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -278,5 +278,59 @@ struct player_struct }; +// Wrapper around the insane collision info mess from Build. +struct Collision +{ + int type; + int index; + int legacyVal; // should be removed later, but needed for converting back for unadjusted code. + DDukeActor* actor; + + int setNone() + { + type = kHitNone; + index = -1; + legacyVal = 0; + actor = nullptr; + return kHitNone; + } + + int setSector(int num) + { + type = kHitSector; + index = num; + legacyVal = type | index; + actor = nullptr; + return kHitSector; + } + int setWall(int num) + { + type = kHitWall; + index = num; + legacyVal = type | index; + actor = nullptr; + return kHitWall; + } + int setSprite(DDukeActor* num) + { + type = kHitSprite; + index = -1; + legacyVal = type | int(num - hittype); + actor = num; + return kHitSprite; + } + + int setFromEngine(int value) + { + legacyVal = value; + type = value & kHitTypeMask; + if (type == 0) { index = -1; actor = nullptr; } + else if (type != kHitSprite) { index = value & kHitIndexMask; actor = nullptr; } + else { index = -1; actor = &hittype[value & kHitIndexMask]; } + return type; + } +}; + + END_DUKE_NS