//------------------------------------------------------------------------- /* 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" BEGIN_BLD_NS #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); void _consoleSysMsg(const char* pMessage, ...); #define ThrowError(...) \ { \ _SetErrorLoc(__FILE__,__LINE__); \ _ThrowError(__VA_ARGS__); \ } // print error to console only #define consoleSysMsg(...) \ { \ _SetErrorLoc(__FILE__,__LINE__); \ _consoleSysMsg(__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 kLensSize 80 #define kViewEffectMax 19 #define kNoTile -1 // defined by NoOne: // ------------------------------- #define kMaxPAL 5 #define kFreeQAVEntry 108 // MEDIUM ///////////////////////////////////////////////////// enum { kMediumNormal = 0, kMediumWater = 1, kMediumGoo = 2, }; // STATNUMS ///////////////////////////////////////////////////// enum { kStatNothing = -1, kStatDecoration = 0, kStatFX = 1, kStatExplosion = 2, kStatItem = 3, kStatThing = 4, kStatProjectile = 5, kStatDude = 6, kStatInactive = 7, // inactive (ambush) dudes kStatRespawn = 8, kStatPurge = 9, kStatMarker = 10, kStatTraps = 11, kStatAmbience = 12, kStatSpares = 13, kStatFlare = 14, kStatDebris = 15, kStatPathMarker = 16, kStatModernDudeTargetChanger = 20, // gModernMap only kStatFree = 1024, }; // POWERUPS ///////////////////////////////////////////////////// enum { kPwUpFeatherFall = 12, kPwUpShadowCloak = 13, kPwUpDeathMask = 14, kPwUpJumpBoots = 15, kPwUpTwoGuns = 17, kPwUpDivingSuit = 18, kPwUpGasMask = 19, kPwUpCrystalBall = 21, kPwUpDoppleganger = 23, kPwUpReflectShots = 24, kPwUpBeastVision = 25, kPwUpShadowCloakUseless = 26, kPwUpDeliriumShroom = 28, kPwUpGrowShroom = 29, kPwUpShrinkShroom = 30, kPwUpDeathMaskUseless = 31, kPwUpAsbestArmor = 39, kMaxPowerUps = 51, }; // SPRITE TYPES ///////////////////////////////////////////////// enum { kSpriteDecoration = 0, // markers kMarkerSPStart = 1, kMarkerMPStart = 2, kMarkerOff = 3, kMarkerOn = 4, kMarkerAxis = 5, kMarkerLowLink = 6, kMarkerUpLink = 7, kMarkerWarpDest = 8, kMarkerUpWater = 9, kMarkerLowWater = 10, kMarkerUpStack = 11, kMarkerLowStack = 12, kMarkerUpGoo = 13, kMarkerLowGoo = 14, kMarkerPath = 15, kMarkerDudeSpawn = 18, kMarkerEarthQuake = 19, // switches kSwitchBase = 20, kSwitchToggle = 20, kSwitchOneWay = 21, kSwitchCombo = 22, kSwitchPadlock = 23, kSwitchMax = 24, // modern types (gModernMap only) kModernCustomDudeSpawn = 24, kModernRandomTX = 25, kModernSequentialTX = 26, kModernSeqSpawner = 27, kModernObjPropertiesChanger = 28, kModernObjPicnumChanger = 29, kModernObjSizeChanger = 31, kModernDudeTargetChanger = 33, kModernSectorFXChanger = 34, kModernObjDataChanger = 35, kModernSpriteDamager = 36, kModernObjDataAccumulator = 37, kModernEffectSpawner = 38, kModernWindGenerator = 39, kModernConcussSprite = 712, /// WIP kModernPlayerControl = 500, /// WIP // decorations kDecorationTorch = 30, kDecorationCandle = 32, // (weapons) kItemWeaponBase = 40, kModernRandom = 40, // gModernMap only kItemWeaponSawedoff = 41, kItemWeaponTommygun = 42, kItemWeaponVoodooDoll = 44, kItemWeaponLifeLeech = 50, kItemWeaponMax = 51, // items (ammos) kItemAmmoBase = 60, kItemAmmoSawedoffFew = 67, kItemAmmoTommygunFew = 69, kAmmoItemVoodooDoll = 70, kModernRandom2 = 80, // gModernMap Only kItemAmmoMax = 81, kItemBase = 100, // items (keys) kItemKeyBase = kItemBase, kItemKeySkull = kItemKeyBase, kItemKeyEye = 101, kItemKeyFire = 102, kItemKeyDagger = 103, kItemKeySpider = 104, kItemKeyMoon = 105, kItemKeyKey7 = 106, kItemKeyMax = 107, // items (health) kItemHealthDoctorBag = 107, kItemHealthMedPouch = 108, kItemHealthLifeEssense = 109, kItemHealthLifeSeed = 110, kItemHealthRedPotion = 111, // items (misc) kItemFeatherFall = 112, kItemShadowCloak = 113, // ltdInvisibility kItemDeathMask = 114, // invulnerability kItemJumpBoots = 115, kItemTwoGuns = 117, kItemDivingSuit = 118, kItemGasMask = 119, kItemCrystalBall = 121, kItemReflectShots = 124, kItemBeastVision = 125, kItemShroomDelirium = 128, kItemShroomGrow = 129, // gModernMap only kItemShroomShrink = 130, // gModernMap only kItemArmorAsbest = 139, kItemArmorBasic = 140, kItemArmorBody = 141, kItemArmorFire = 142, kItemArmorSpirit = 143, kItemArmorSuper = 144, kItemFlagABase = 145, kItemFlagBBase = 146, kItemFlagA = 147, kItemFlagB = 148, kItemModernMapLevel = 150, // once picked up, draws whole minimap kItemMax = 151, // dudes kDudeBase = 200, kDudeCultistTommy = 201, kDudeCultistShotgun = 202, kDudeZombieAxeNormal = 203, kDudeZombieButcher = 204, kDudeZombieAxeBuried = 205, kDudeGargoyleFlesh = 206, kDudeGargoyleStone = 207, kDudeGargoyleStatueFlesh = 208, kDudeGargoyleStatueStone = 209, kDudePhantasm = 210, kDudeHellHound = 211, kDudeHand = 212, kDudeSpiderBrown = 213, kDudeSpiderRed = 214, kDudeSpiderBlack = 215, kDudeSpiderMother = 216, kDudeGillBeast = 217, kDudeBoneEel = 218, kDudeBat = 219, kDudeRat = 220, kDudePodGreen = 221, kDudeTentacleGreen = 222, kDudePodFire = 223, kDudeTentacleFire = 224, kDudePodMother = 225, kDudeTentacleMother = 226, kDudeCerberusTwoHead = 227, kDudeCerberusOneHead = 228, kDudeTchernobog = 229, kDudeCultistTommyProne = 230, kDudePlayer1 = 231, kDudePlayer2 = 232, kDudePlayer3 = 233, kDudePlayer4 = 234, kDudePlayer5 = 235, kDudePlayer6 = 236, kDudePlayer7 = 237, kDudePlayer8 = 238, kDudeBurningInnocent = 239, kDudeBurningCultist = 240, kDudeBurningZombieAxe = 241, kDudeBurningZombieButcher = 242, kDudeCultistReserved = 243, // unused kDudeZombieAxeLaying = 244, kDudeInnocent = 245, kDudeCultistShotgunProne = 246, kDudeCultistTesla = 247, kDudeCultistTNT = 248, kDudeCultistBeast = 249, kDudeTinyCaleb = 250, kDudeBeast = 251, kDudeBurningTinyCaleb = 252, kDudeBurningBeast = 253, kDudeVanillaMax = 254, kDudeModernCustom = kDudeVanillaMax, // gModern map only kDudeModernCustomBurning = 255, // gModern map only kDudeMax = 256, kMissileBase = 300, kMissileButcherKnife = kMissileBase, kMissileFlareRegular = 301, kMissileTeslaAlt = 302, kMissileFlareAlt = 303, kMissileFlameSpray = 304, kMissileFireball = 305, kMissileTeslaRegular = 306, kMissileEctoSkull = 307, kMissileFlameHound = 308, kMissilePukeGreen = 309, kMissileArcGargoyle = 311, kMissileFireballNapam = 312, kMissileFireballCerberus = 313, kMissileFireballTchernobog = 314, kMissileLifeLeechRegular = 315, kMissileLifeLeechAltNormal = 316, kMissileLifeLeechAltSmall = 317, kMissileMax = 318, // things kThingBase = 400, kThingTNTBarrel = 400, kThingArmedProxBomb = 401, kThingArmedRemoteBomb = 402, kThingCrateFace = 405, kThingGlassWindow = 406, kThingFluorescent = 407, kThingWallCrack = 408, kThingSpiderWeb = 410, kThingMetalGrate = 411, kThingFlammableTree = 412, kTrapMachinegun = 413, // not really a thing, should be in traps instead kThingFallingRock = 414, kThingKickablePail = 415, kThingObjectGib = 416, kThingObjectExplode = 417, kThingArmedTNTStick = 418, kThingArmedTNTBundle = 419, kThingArmedSpray = 420, kThingBone = 421, kThingDripWater = 423, kThingDripBlood = 424, kThingBloodBits = 425, kThingBloodChunks = 426, kThingZombieHead = 427, kThingNapalmBall = 428, kThingPodGreenBall = 429, kThingPodFireBall = 430, kThingDroppedLifeLeech = 431, kThingVoodooHead = 432, // unused kModernThingTNTProx = 433, // gModernMap only - detects only players kModernThingThrowableRock = 434, // gModernMap only - does small damage if hits target kModernThingEnemyLifeLeech = 435, // gModernMap only - the same as normal, except it aims in specified target only kThingMax = 436, // traps kTrapFlame = 452, kTrapSawCircular = 454, kTrapZapSwitchable = 456, kTrapExploder = 459, // generators kGenTrigger = 700, kGenDripWater = 701, kGenDripBlood = 702, kGenMissileFireball = 703, kGenMissileEctoSkull = 704, // does not work in vanilla kGenModernMissileUniversal = 704, // gModernMap only kGenDart = 705, kGenBubble = 706, kGenBubbleMulti = 707, // sound sprites kGenSound = 708, kSoundSector = 709, kSoundPlayer = 711, }; // WALL TYPES ///////////////////////////////////////////////// enum { kWallBase = 500, kWallStack = 501, kWallGib = 511, kWallMax = 512, }; // SECTOR TYPES ///////////////////////////////////////////////// enum { kSectorBase = 600, kSectorZMotion = 600, kSectorZMotionSprite = 602, kSectorTeleport = 604, kSectorPath = 612, kSectorRotateStep = 613, kSectorSlideMarked = 614, kSectorRotateMarked = 615, kSectorSlide = 616, kSectorRotate = 617, kSectorDamage = 618, kSectorCounter = 619, kSectorMax = 620, }; // 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 kPhysDebrisSwim 0x0016 // *debris* can swim underwater (instead of drowning) #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 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 // 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, }; #define NEG_ALPHA_TO_BLEND(alpha, blend, orientation) do { \ if (alpha < 0) { blend = -alpha; alpha = 0; orientation |= RS_TRANS1; } \ } while (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_ExtInit(void); void G_LoadGroupsInDir(const char *dirname); void G_DoAutoload(const char *dirname); extern void G_LoadGroups(); 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 int gameHandleEvents(void) { netGetPackets(); return handleevents(); } # define FORMAT_UPGRADE_ELIGIBLE extern FileReader S_OpenAudio(const char *fn, char searchfirst, uint8_t ismusic); #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; } template inline void SetBitString(T *pArray, int nIndex) { static_assert(sizeof(T) == 1, "Bit array element too large"); pArray[nIndex>>3] |= 1<<(nIndex&7); } template inline void ClearBitString(T *pArray, int nIndex) { static_assert(sizeof(T) == 1, "Bit array element too large"); pArray[nIndex >> 3] &= ~(1 << (nIndex & 7)); } template inline char TestBitString(T *pArray, int nIndex) { static_assert(sizeof(T) == 1, "Bit array element too large"); return pArray[nIndex>>3] & (1<<(nIndex&7)); } // This is to override the namepace prioritization without altering the actual calls. inline int scale(int a, int b, int c) { return ::scale(a, b, c); } 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; } // the point of this is to prevent re-running a function or calculation passed to potentialValue // without making a new variable under each individual circumstance inline void SetIfGreater(int32_t* variable, int32_t potentialValue) { if (potentialValue > * variable) * variable = potentialValue; } 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); END_BLD_NS