//------------------------------------------------------------------------- /* Copyright (C) 2010-2019 EDuke32 developers and contributors Copyright (C) 2019 Nuke.YKT This file is part of NBlood. NBlood is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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. */ //------------------------------------------------------------------------- #pragma once #include "baselayer.h" #include "build.h" #include "cache1d.h" #include "common.h" #include "pragmas.h" #include "misc.h" #include "network.h" extern int g_useCwd; #ifndef APPNAME #define APPNAME "NBlood" #endif #ifndef APPBASENAME #define APPBASENAME "nblood" #endif #define BLOODWIDESCREENDEF "blood_widescreen.def" #define BYTEVERSION 102 #define EXEVERSION 101 void _SetErrorLoc(const char *pzFile, int nLine); void _ThrowError(const char *pzFormat, ...); void __dassert(const char *pzExpr, const char *pzFile, int nLine); void QuitGame(void); #define ThrowError(...) \ { \ _SetErrorLoc(__FILE__,__LINE__); \ _ThrowError(__VA_ARGS__); \ } #define dassert(x) if (!(x)) __dassert(#x,__FILE__,__LINE__) #define kMaxSectors MAXSECTORS #define kMaxWalls MAXWALLS #define kMaxSprites MAXSPRITES #define kMaxTiles MAXTILES #define kMaxStatus MAXSTATUS #define kMaxPlayers 8 #define kMaxViewSprites maxspritesonscreen #define kMaxVoxels MAXVOXELS #define kTicRate 120 #define kTicsPerFrame 4 #define kTicsPerSec (kTicRate/kTicsPerFrame) #define TILTBUFFER 4078 #define kExplodeMax 8 #define kDudeBase 200 #define kDudePlayer1 231 #define kDudePlayer8 238 #define kDudeMax 260 #define kMissileBase 300 #define kMissileMax 318 #define kThingBase 400 #define kThingMax 436 #define kMaxPowerUps 51 #define kStatRespawn 8 #define kStatMarker 10 #define kStatGDXDudeTargetChanger 20 #define kStatFree 1024 #define kLensSize 80 #define kViewEffectMax 19 #define kNoTile -1 // defined by NoOne: // ------------------------------- #define kMaxPAL 5 #define kItemBase 100 #define kWeaponItemBase 40 #define kItemMax 151 // marker sprite types #define kMarkerSPStart 1 #define kMarkerMPStart 2 #define kMarkerOff 3 #define kMarkerOn 4 #define kMarkerAxis 5 #define kMarkerLowLink 6 #define kMarkerUpLink 7 #define kMarkerWarpDest 8 #define kMarkerUpWater 9 #define kMarkerLowWater 10 #define kMarkerUpStack 11 #define kMarkerLowStack 12 #define kMarkerUpGoo 13 #define kMarkerLowGoo 14 #define kMarkerPath 15 // sprite attributes #define kHitagAutoAim 0x0008 #define kHitagRespawn 0x0010 #define kHitagFree 0x0020 #define kHitagSmoke 0x0100 // sprite physics attributes #define kPhysMove 0x0001 // affected by movement physics #define kPhysGravity 0x0002 // affected by gravity #define kPhysFalling 0x0004 // currently in z-motion // additional physics attributes for debris sprites #define kPhysDebrisFly 0x0008 // *debris* affected by negative gravity (fly instead of falling, DO NOT mess with kHitagAutoAim) #define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons #define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions // *modern types only hitag* #define kModernTypeFlag0 0x0 #define kModernTypeFlag1 0x1 #define kModernTypeFlag2 0x2 #define kModernTypeFlag3 0x3 // sector types #define kSecBase 600 #define kSecZMotion kSectorBase #define kSecZSprite 602 #define kSecWarp 603 #define kSecTeleport 604 #define kSecPath 612 #define kSecRotateStep 613 #define kSecSlideMarked 614 #define kSecRotateMarked 615 #define kSecSlide 616 #define kSecRotate 617 #define kSecDamage 618 #define kSecCounter 619 #define kSecMax 620 // sector cstat #define kSecCParallax 0x01 #define kSecCSloped 0x02 #define kSecCSwapXY 0x04 #define kSecCExpand 0x08 #define kSecCFlipX 0x10 #define kSecCFlipY 0x20 #define kSecCFlipMask 0x34 #define kSecCRelAlign 0x40 #define kSecCFloorShade 0x8000 // switch types #define kSwitchBase 20 #define kSwitchToggle 20 #define kSwitchOneWay 21 #define kSwitchCombo 22 #define kSwitchPadlock 23 #define kSwitchMax 24 // projectile types #define kProjectileEctoSkull 307 // custom level end #define kGDXChannelEndLevelCustom 6 // GDX types #define kGDXTypeBase 24 #define kGDXCustomDudeSpawn 24 #define kGDXRandomTX 25 #define kGDXSequentialTX 26 #define kGDXSeqSpawner 27 #define kGDXObjPropertiesChanger 28 #define kGDXObjPicnumChanger 29 #define kGDXObjSizeChanger 31 #define kGDXDudeTargetChanger 33 #define kGDXSectorFXChanger 34 #define kGDXObjDataChanger 35 #define kGDXSpriteDamager 36 #define kGDXObjDataAccumulator 37 #define kGDXEffectSpawner 38 #define kGDXWindGenerator 39 #define kModernConcussSprite 712 #define kGDXThingTNTProx 433 // detects only players #define kGDXThingThrowableRock 434 // does small damage if hits target #define kGDXThingCustomDudeLifeLeech 435 // the same as normal, except it aims in specified target #define kCustomDude 254 #define kCustomDudeBurning 255 #define kGDXItemMapLevel 150 // once picked up, draws whole minimap // ai state types #define kAiStateOther -1 #define kAiStateIdle 0 #define kAiStateGenIdle 1 #define kAiStateMove 2 #define kAiStateSearch 3 #define kAiStateChase 4 #define kAiStateRecoil 5 #define kAng5 28 #define kAng15 85 #define kAng30 170 #define kAng45 256 #define kAng60 341 #define kAng90 512 #define kAng120 682 #define kAng180 1024 #define kAng360 2048 // ------------------------------- // NUKE-TODO: #define OSDTEXT_DEFAULT "^00" #define OSDTEXT_DARKRED "^00" #define OSDTEXT_GREEN "^00" #define OSDTEXT_RED "^00" #define OSDTEXT_YELLOW "^00" #define OSDTEXT_BRIGHT "^S0" #define OSD_ERROR OSDTEXT_DARKRED OSDTEXT_BRIGHT enum BLOOD_GLOBALFLAGS { BLOOD_FORCE_WIDELOADSCREEN = 1<<0, }; enum searchpathtypes_t { SEARCHPATH_REMOVE = 1<<0, }; extern char *g_grpNamePtr; extern int loaddefinitions_game(const char *fn, int32_t preload); extern void G_AddSearchPaths(void); extern void G_CleanupSearchPaths(void); extern void G_ExtPreInit(int32_t argc, char const * const * argv); extern void G_ExtInit(void); void G_LoadGroupsInDir(const char *dirname); void G_DoAutoload(const char *dirname); extern void G_LoadGroups(int32_t autoload); extern void G_SetupGlobalPsky(void); #define G_ModDirSnprintf(buf, size, basename, ...) \ (((g_modDir[0] != '/') ? Bsnprintf(buf, size, "%s/" basename, g_modDir, ##__VA_ARGS__) : Bsnprintf(buf, size, basename, ##__VA_ARGS__)) \ >= ((int32_t)size) - 1) #define G_ModDirSnprintfLite(buf, size, basename) \ ((g_modDir[0] != '/') ? Bsnprintf(buf, size, "%s/%s", g_modDir, basename) : Bsnprintf(buf, size, "%s", basename)) static inline void G_HandleAsync(void) { handleevents(); netGetPackets(); } #if defined HAVE_FLAC || defined HAVE_VORBIS # define FORMAT_UPGRADE_ELIGIBLE extern int32_t S_OpenAudio(const char *fn, char searchfirst, uint8_t ismusic); #else # define S_OpenAudio(fn, searchfirst, ismusic) kopen4loadfrommod(fn, searchfirst) #endif #pragma pack(push,1) #if 0 struct sectortype { short wallptr, wallnum; int ceilingz, floorz; unsigned short ceilingstat, floorstat; short ceilingpicnum, ceilingheinum; signed char ceilingshade; char ceilingpal, ceilingxpanning, ceilingypanning; short floorpicnum, floorheinum; signed char floorshade; char floorpal, floorxpanning, floorypanning; char visibility, filler; unsigned short lotag; short hitag, extra; }; struct walltype { int x, y; short point2, nextwall, nextsector; unsigned short cstat; short picnum, overpicnum; signed char shade; char pal, xrepeat, yrepeat, xpanning, ypanning; short lotag, hitag, extra; }; struct spritetype { int x, y, z; short cstat, picnum; signed char shade; char pal, clipdist, filler; unsigned char xrepeat, yrepeat; signed char xoffset, yoffset; short sectnum, statnum; short ang, owner, index, yvel, zvel; short type, hitag, extra; }; struct PICANM { unsigned int animframes : 5; unsigned int at0_5 : 1; unsigned int animtype : 2; signed int xoffset : 8; signed int yoffset : 8; unsigned int animspeed : 4; unsigned int at3_4 : 3; // type unsigned int at3_7 : 1; // filler }; #endif struct LOCATION { int x, y, z; int ang; }; struct POINT2D { int x, y; }; struct POINT3D { int x, y, z; }; struct VECTOR2D { int dx, dy; }; struct Aim { int dx, dy, dz; }; #pragma pack(pop) inline int ksgnf(float f) { if (f < 0) return -1; if (f > 0) return 1; return 0; } inline int IncBy(int a, int b) { a += b; int q = a % b; a -= q; if (q < 0) a -= b; return a; } inline int DecBy(int a, int b) { a--; int q = a % b; a -= q; if (q < 0) a -= b; return a; } #if 0 inline float IncByF(float a, float b) { a += b; float q = fmod(a, b); a -= q; if (q < 0) a -= b; return a; } inline float DecByF(float a, float b) { //a--; a -= fabs(b)*0.001; float q = fmod(a, b); a -= q; if (q < 0) a -= b; return a; } #endif inline int ClipLow(int a, int b) { if (a < b) return b; return a; } inline int ClipHigh(int a, int b) { if (a >= b) return b; return a; } inline int ClipRange(int a, int b, int c) { if (a < b) return b; if (a > c) return c; return a; } inline float ClipRangeF(float a, float b, float c) { if (a < b) return b; if (a > c) return c; return a; } inline int interpolate(int a, int b, int c) { return a+mulscale16(b-a,c); } inline int interpolateang(int a, int b, int c) { return a+mulscale16(((b-a+1024)&2047)-1024, c); } inline fix16_t interpolateangfix16(fix16_t a, fix16_t b, int c) { return a+mulscale16(((b-a+0x4000000)&0x7ffffff)-0x4000000, c); } inline char Chance(int a1) { return wrand() < (a1>>1); } inline unsigned int Random(int a1) { return mulscale(wrand(), a1, 15); } inline int Random2(int a1) { return mulscale(wrand(), a1, 14)-a1; } inline int Random3(int a1) { return mulscale(wrand()+wrand(), a1, 15) - a1; } inline unsigned int QRandom(int a1) { return mulscale(qrand(), a1, 15); } inline int QRandom2(int a1) { return mulscale(qrand(), a1, 14)-a1; } inline void SetBitString(char *pArray, int nIndex) { pArray[nIndex>>3] |= 1<<(nIndex&7); } inline void ClearBitString(char *pArray, int nIndex) { pArray[nIndex >> 3] &= ~(1 << (nIndex & 7)); } inline char TestBitString(char *pArray, int nIndex) { return pArray[nIndex>>3] & (1<<(nIndex&7)); } inline int scale(int a1, int a2, int a3, int a4, int a5) { return a4 + (a5-a4) * (a1-a2) / (a3-a2); } inline int mulscale16r(int a, int b) { int64_t acc = 1<<(16-1); acc += ((int64_t)a) * b; return (int)(acc>>16); } inline int mulscale30r(int a, int b) { int64_t acc = 1<<(30-1); acc += ((int64_t)a) * b; return (int)(acc>>30); } inline int dmulscale30r(int a, int b, int c, int d) { int64_t acc = 1<<(30-1); acc += ((int64_t)a) * b; acc += ((int64_t)c) * d; return (int)(acc>>30); } inline int approxDist(int dx, int dy) { dx = klabs(dx); dy = klabs(dy); if (dx > dy) dy = (3*dy)>>3; else dx = (3*dx)>>3; return dx+dy; } class Rect { public: int x0, y0, x1, y1; Rect(int _x0, int _y0, int _x1, int _y1) { x0 = _x0; y0 = _y0; x1 = _x1; y1 = _y1; } bool isValid(void) const { return x0 < x1 && y0 < y1; } char isEmpty(void) const { return !isValid(); } bool operator!(void) const { return isEmpty(); } Rect & operator&=(Rect &pOther) { x0 = ClipLow(x0, pOther.x0); y0 = ClipLow(y0, pOther.y0); x1 = ClipHigh(x1, pOther.x1); y1 = ClipHigh(y1, pOther.y1); return *this; } void offset(int dx, int dy) { x0 += dx; y0 += dy; x1 += dx; y1 += dy; } int height() { return y1 - y0; } int width() { return x1 - x0; } bool inside(Rect& other) { return (x0 <= other.x0 && x1 >= other.x1 && y0 <= other.y0 && y1 >= other.y1); } bool inside(int x, int y) { return (x0 <= x && x1 > x && y0 <= y && y1 > y); } }; class BitReader { public: int nBitPos; int nSize; char *pBuffer; BitReader(char *_pBuffer, int _nSize, int _nBitPos) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = _nBitPos; nSize -= nBitPos>>3; } BitReader(char *_pBuffer, int _nSize) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = 0; } int readBit() { if (nSize <= 0) ThrowError("Buffer overflow"); int bit = ((*pBuffer)>>nBitPos)&1; if (++nBitPos >= 8) { nBitPos = 0; pBuffer++; nSize--; } return bit; } void skipBits(int nBits) { nBitPos += nBits; pBuffer += nBitPos>>3; nSize -= nBitPos>>3; nBitPos &= 7; if ((nSize == 0 && nBitPos > 0) || nSize < 0) ThrowError("Buffer overflow"); } unsigned int readUnsigned(int nBits) { unsigned int n = 0; dassert(nBits <= 32); for (int i = 0; i < nBits; i++) n += readBit()<>= 32-nBits; return n; } }; class BitWriter { public: int nBitPos; int nSize; char *pBuffer; BitWriter(char *_pBuffer, int _nSize, int _nBitPos) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = _nBitPos; memset(pBuffer, 0, nSize); nSize -= nBitPos>>3; } BitWriter(char *_pBuffer, int _nSize) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = 0; memset(pBuffer, 0, nSize); } void writeBit(int bit) { if (nSize <= 0) ThrowError("Buffer overflow"); *pBuffer |= bit<= 8) { nBitPos = 0; pBuffer++; nSize--; } } void skipBits(int nBits) { nBitPos += nBits; pBuffer += nBitPos>>3; nSize -= nBitPos>>3; nBitPos &= 7; if ((nSize == 0 && nBitPos > 0) || nSize < 0) ThrowError("Buffer overflow"); } void write(int nValue, int nBits) { dassert(nBits <= 32); for (int i = 0; i < nBits; i++) writeBit((nValue>>i)&1); } }; void G_AddGroup(const char* buffer); void G_AddPath(const char* buffer);