diff --git a/source/core/gamecvars.cpp b/source/core/gamecvars.cpp index ade32becd..60e1a626b 100644 --- a/source/core/gamecvars.cpp +++ b/source/core/gamecvars.cpp @@ -84,7 +84,8 @@ CVARD(Bool, cl_exhumedoldturn, false, CVAR_ARCHIVE, "enable/disable legacy turni CVARD(Bool, cl_hudinterpolation, true, CVAR_ARCHIVE, "enable/disable HUD (weapon drawer) interpolation") CVARD(Bool, cl_bloodvanillarun, true, CVAR_ARCHIVE, "enable/disable Blood's vanilla run mode") CVARD(Bool, cl_bloodvanillabobbing, true, CVAR_ARCHIVE, "enable/disable Blood's vanilla bobbing while not using vanilla run mode") -CVARD(Bool, cl_bloodvanillaexplosions, false, CVAR_ARCHIVE, "enable/disable Blood's original explosion behavior") +CVARD(Bool, cl_bloodvanillaexplosions, false, CVAR_ARCHIVE, "enable/disable Blood's vanilla explosion behavior") +CVARD(Bool, cl_bloodvanillaenemies, false, CVAR_ARCHIVE, "enable/disable Blood's vanilla enemy behavior") CVARD(Bool, cl_bloodqavinterp, true, CVAR_ARCHIVE, "enable/disable Blood's QAV interpolation") CVARD(Bool, cl_bloodweapinterp, false, CVAR_ARCHIVE, "enable/disable Blood's weapon interpolation. Depends on 'cl_bloodqavinterp'") CVARD(Bool, cl_bloodoldweapbalance, false, CVAR_ARCHIVE, "enable/disable legacy 1.0 weapon handling for Blood") diff --git a/source/core/gamecvars.h b/source/core/gamecvars.h index 9e1e5d409..883af97d6 100644 --- a/source/core/gamecvars.h +++ b/source/core/gamecvars.h @@ -30,6 +30,7 @@ EXTERN_CVAR(Bool, cl_hudinterpolation) EXTERN_CVAR(Bool, cl_bloodvanillarun) EXTERN_CVAR(Bool, cl_bloodvanillabobbing) EXTERN_CVAR(Bool, cl_bloodvanillaexplosions) +EXTERN_CVAR(Bool, cl_bloodvanillaenemies) EXTERN_CVAR(Bool, cl_bloodqavinterp) EXTERN_CVAR(Bool, cl_bloodweapinterp) EXTERN_CVAR(Bool, cl_bloodoldweapbalance) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index f9b298559..7035739d8 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -2540,7 +2540,7 @@ void actInit(bool bSaveLoad) { if (act->s().type == kItemWeaponVoodooDoll) { - act->s().type = kAmmoItemVoodooDoll; + act->s().type = kItemAmmoVoodooDoll; break; } } @@ -2661,7 +2661,7 @@ void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int { uint8_t sectmap[(kMaxSectors + 7) >> 3]; auto pOwner = source->GetOwner(); - const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(nSector, x, y, nDist, sectmap, nullptr, newSectCheckMethod); nDist <<= 4; if (flags & 2) @@ -3092,7 +3092,7 @@ static bool actKillDudeStage1(DBloodActor* actor, DAMAGE_TYPE damageType) break; case kDudeTinyCaleb: - if (VanillaMode() || DemoRecordStatus()) + if (cl_bloodvanillaenemies || VanillaMode()) break; if (damageType == kDamageBurn && pXSprite->medium == kMediumNormal) { @@ -3936,7 +3936,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) actBurnSprite(missileActor->GetOwner(), actorHit, 360); // by NoOne: make Life Leech heal user, just like it was in 1.0x versions - if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus() && pDudeInfo != nullptr) + if (gGameOptions.weaponsV10x && !VanillaMode() && pDudeInfo != nullptr) { if (missileOwner->IsDudeActor() && missileOwner->hasX() && missileOwner->x().health != 0) actHealDude(missileOwner, nDamage >> 2, getDudeInfo(missileOwner->s().type)->startHealth); @@ -4012,7 +4012,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) break; case kMissileFireball: - case kMissileFireballNapam: + case kMissileFireballNapalm: if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo)) { if (pThingInfo && pSpriteHit->type == kThingTNTBarrel && actorHit->x().burnTime == 0) @@ -4042,7 +4042,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) actRadiusDamage(missileOwner, pMissile->x, pMissile->y, pMissile->z, pMissile->sectnum, 16, 20, 10, kDamageBullet, 6, 480); // by NoOne: allow additional bullet damage for Flare Gun - if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus()) + if (gGameOptions.weaponsV10x && !VanillaMode()) { int nDamage = (20 + Random(10)) << 4; actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); @@ -4646,11 +4646,15 @@ int MoveThing(spritetype *pSprite) assert(nSector >= 0 && nSector < kMaxSectors); int top, bottom; GetSpriteExtents(pSprite, &top, &bottom); + const int bakCompat = enginecompatibility_mode; if (xvel[nSprite] || yvel[nSprite]) { short bakCstat = pSprite->cstat; pSprite->cstat &= ~257; + if ((pSprite->owner >= 0) && !cl_bloodvanillaexplosions && !VanillaMode()) + enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy v8 = gSpriteHit[nXSprite].hit = ClipMove((int*)&pSprite->x, (int*)&pSprite->y, (int*)&pSprite->z, &nSector, xvel[nSprite]>>12, yvel[nSprite]>>12, pSprite->clipdist<<2, (pSprite->z-top)/4, (bottom-pSprite->z)/4, CLIPMASK0); + enginecompatibility_mode = bakCompat; // restore pSprite->cstat = bakCstat; assert(nSector >= 0); if (pSprite->sectnum != nSector) @@ -5012,7 +5016,7 @@ void MoveDude(spritetype *pSprite) } if (pPlayer && zvel[nSprite] > 0x155555 && !pPlayer->fallScream && pXSprite->height > 0) { - const bool playerAlive = (pXSprite->health > 0) || VanillaMode() || DemoRecordStatus(); // only trigger falling scream if player is alive or vanilla mode + const bool playerAlive = (pXSprite->health > 0) || VanillaMode(); // only trigger falling scream if player is alive or vanilla mode if (playerAlive) { pPlayer->fallScream = 1; @@ -5110,7 +5114,7 @@ void MoveDude(spritetype *pSprite) break; case kDudeBurningCultist: { - const bool fixRandomCultist = (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode() && !DemoRecordStatus(); // fix burning cultists randomly switching types underwater + const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater if (Chance(chance)) pSprite->type = kDudeCultistTommy; else @@ -5427,6 +5431,8 @@ int MoveMissile(spritetype *pSprite) int top, bottom; GetSpriteExtents(pSprite, &top, &bottom); int i = 1; + const int bakCompat = enginecompatibility_mode; + const bool isFlameSprite = (pSprite->type == kMissileFlameSpray || pSprite->type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much) while (1) { int x = pSprite->x; @@ -5434,7 +5440,10 @@ int MoveMissile(spritetype *pSprite) int z = pSprite->z; int nSector2 = pSprite->sectnum; clipmoveboxtracenum = 1; + if ((pSprite->owner >= 0) && !isFlameSprite && !cl_bloodvanillaexplosions && !VanillaMode()) + enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy int vdx = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist<<2, (z-top)/4, (bottom-z)/4, CLIPMASK0); + enginecompatibility_mode = bakCompat; // restore clipmoveboxtracenum = 3; short nSector = nSector2; if (nSector2 < 0) @@ -5547,7 +5556,7 @@ void actExplodeSprite(spritetype *pSprite) switch (pSprite->type) { - case kMissileFireballNapam: + case kMissileFireballNapalm: nType = kExplosionNapalm; seqSpawn(4, 3, nXSprite, -1); if (Chance(0x8000)) @@ -6004,7 +6013,7 @@ void actProcessSprites(void) // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions // so only allow this new checking method for dude spawned explosions short gAffectedXWalls[kMaxXWalls]; - const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(nSector, x, y, radius, sectmap, gAffectedXWalls, newSectCheckMethod); for (int i = 0; i < kMaxXWalls; i++) @@ -6197,7 +6206,7 @@ void actProcessSprites(void) if (nXSprite > 0) { XSPRITE *pXSprite = &xsprite[nXSprite]; - const bool fixBurnGlitch = IsBurningDude(pSprite) && !VanillaMode() && !DemoRecordStatus(); // if enemies are burning, always apply burning damage per tick + const bool fixBurnGlitch = !cl_bloodvanillaenemies && IsBurningDude(pSprite) && !VanillaMode(); // if enemies are burning, always apply burning damage per tick if ((pXSprite->burnTime > 0) || fixBurnGlitch) { switch (pSprite->type) @@ -6710,7 +6719,7 @@ void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite) { seqSpawn(2, 3, nXSprite, -1); sfxPlay3DSound(pMissile, 493, 0, 0); break; - case kMissileFireballNapam: + case kMissileFireballNapalm: seqSpawn(61, 3, nXSprite, nNapalmClient); sfxPlay3DSound(pMissile, 441, 0, 0); break; diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index f93c6d516..3d88c236b 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -177,7 +177,7 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange) // It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like // in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as // i don't think it will broke something in game. - if (!VanillaMode() && Crusher && isImmune(pSprite, pXSector->damageType, 16)) return true; + if (!cl_bloodvanillaenemies && !VanillaMode() && Crusher && isImmune(pSprite, pXSector->damageType, 16)) return true; fallthrough__; case kDudeZombieButcher: case kDudeSpiderBrown: @@ -1033,7 +1033,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra]; pDudeExtra->recoil = 1; } - const bool fixRandomCultist = (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode() && !DemoRecordStatus(); // fix burning cultists randomly switching types underwater + const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater switch (pSprite->type) { case kDudeCultistTommy: @@ -1110,7 +1110,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType case kDudeTinyCaleb: if (nDmgType == kDamageBurn && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) { - if (!VanillaMode() && !DemoRecordStatus()) // fix burning sprite for tiny caleb + if (!cl_bloodvanillaenemies && !VanillaMode()) // fix burning sprite for tiny caleb { pSprite->type = kDudeBurningTinyCaleb; aiNewState(actor, &tinycalebBurnGoto); @@ -1480,7 +1480,7 @@ void aiLookForTarget(spritetype *pSprite, XSPRITE *pXSprite) if (pXSprite->state) { uint8_t sectmap[(kMaxSectors+7)>>3]; - const bool newSectCheckMethod = !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(pSprite->sectnum, pSprite->x, pSprite->y, 400, sectmap, nullptr, newSectCheckMethod); int nSprite2; diff --git a/source/games/blood/src/aibeast.cpp b/source/games/blood/src/aibeast.cpp index af33c536f..f3316df08 100644 --- a/source/games/blood/src/aibeast.cpp +++ b/source/games/blood/src/aibeast.cpp @@ -95,7 +95,7 @@ void StompSeqCallback(int, DBloodActor* actor1) int nSector = pSprite->sectnum; int v1c = 5+2*gGameOptions.nDifficulty; int v10 = 25+30*gGameOptions.nDifficulty; - const bool newSectCheckMethod = !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + const bool newSectCheckMethod = !cl_bloodvanillaenemies && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(nSector, x, y, vc, sectmap, nullptr, newSectCheckMethod); char v4 = 0; int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); diff --git a/source/games/blood/src/aispid.cpp b/source/games/blood/src/aispid.cpp index 04ec9bca7..ced581fcb 100644 --- a/source/games/blood/src/aispid.cpp +++ b/source/games/blood/src/aispid.cpp @@ -42,25 +42,22 @@ AISTATE spidGoto = { kAiStateMove, 7, -1, 600, NULL, aiMoveForward, spidThinkGot AISTATE spidSearch = { kAiStateSearch, 7, -1, 1800, NULL, aiMoveForward, spidThinkSearch, &spidIdle }; AISTATE spidBite = { kAiStateChase, 6, nSpidBiteClient, 60, NULL, NULL, NULL, &spidChase }; AISTATE spidJump = { kAiStateChase, 8, nSpidJumpClient, 60, NULL, aiMoveForward, NULL, &spidChase }; -AISTATE spid13A92C = { kAiStateOther, 0, dword_279B50, 60, NULL, NULL, NULL, &spidIdle }; +AISTATE spidBirth = { kAiStateOther, 0, nSpidBirthClient, 60, NULL, NULL, NULL, &spidIdle }; -static char sub_70D30(XSPRITE *pXDude, int a2, int a3) +static char SpidPoisonPlayer(XSPRITE *pXDude, int nBlind, int max) { assert(pXDude != NULL); int nDude = pXDude->reference; spritetype *pDude = &sprite[nDude]; if (IsPlayerSprite(pDude)) { - a2 <<= 4; - a3 <<= 4; - if (IsPlayerSprite(pDude)) + nBlind <<= 4; + max <<= 4; + PLAYER *pPlayer = &gPlayer[pDude->type-kDudePlayer1]; + if (pPlayer->blindEffect < max) { - PLAYER *pPlayer = &gPlayer[pDude->type-kDudePlayer1]; - if (a3 > pPlayer->blindEffect) - { - pPlayer->blindEffect = ClipHigh(pPlayer->blindEffect+a2, a3); - return 1; - } + pPlayer->blindEffect = ClipHigh(pPlayer->blindEffect+nBlind, max); + return 1; } } return 0; @@ -93,11 +90,11 @@ void SpidBiteSeqCallback(int, DBloodActor* actor) break; case kDudeSpiderRed: actFireVector(pSprite, 0, 0, dx, dy, dz, kVectorSpiderBite); - if (Chance(0x5000)) sub_70D30(pXTarget, 4, 16); + if (Chance(0x5000)) SpidPoisonPlayer(pXTarget, 4, 16); break; case kDudeSpiderBlack: actFireVector(pSprite, 0, 0, dx, dy, dz, kVectorSpiderBite); - sub_70D30(pXTarget, 8, 16); + SpidPoisonPlayer(pXTarget, 8, 16); break; case kDudeSpiderMother: { actFireVector(pSprite, 0, 0, dx, dy, dz, kVectorSpiderBite); @@ -106,9 +103,9 @@ void SpidBiteSeqCallback(int, DBloodActor* actor) dy += Random2(2000); dz += Random2(2000); actFireVector(pSprite, 0, 0, dx, dy, dz, kVectorSpiderBite); - sub_70D30(pXTarget, 8, 16); - } + SpidPoisonPlayer(pXTarget, 8, 16); break; + } } } @@ -141,7 +138,7 @@ void SpidJumpSeqCallback(int, DBloodActor* actor) } } -void sub_71370(int, DBloodActor* actor) +void SpidBirthSeqCallback(int, DBloodActor* actor) { XSPRITE* pXSprite = &actor->x(); spritetype* pSprite = &actor->s(); @@ -249,7 +246,7 @@ static void spidThinkChase(DBloodActor* actor) if (nDist < 0x733 && nDist > 0x399 && abs(nDeltaAngle) < 85) aiNewState(actor, &spidJump); else if (Chance(0x8000)) - aiNewState(actor, &spid13A92C); + aiNewState(actor, &spidBirth); break; } diff --git a/source/games/blood/src/aistate.h b/source/games/blood/src/aistate.h index 18d13e6cf..930fce36b 100644 --- a/source/games/blood/src/aistate.h +++ b/source/games/blood/src/aistate.h @@ -313,7 +313,7 @@ extern AISTATE spidGoto; extern AISTATE spidSearch; extern AISTATE spidBite; extern AISTATE spidJump; -extern AISTATE spid13A92C; +extern AISTATE spidBirth; extern AISTATE tchernobogIdle; extern AISTATE tchernobogSearch; diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index 841e2760f..4e9ad295f 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -619,7 +619,7 @@ static void unicultThinkChase(DBloodActor* actor) mdist = 2500; fallthrough__; case kMissileFireball: - case kMissileFireballNapam: + case kMissileFireballNapalm: case kMissileFireballCerberus: case kMissileFireballTchernobog: if (mdist == defDist) mdist = 3000; @@ -834,7 +834,7 @@ static void unicultThinkChase(DBloodActor* actor) case kMissileTeslaAlt: case kMissileFlareAlt: case kMissileFireball: - case kMissileFireballNapam: + case kMissileFireballNapalm: case kMissileFireballCerberus: case kMissileFireballTchernobog: { // allow attack if dude is far from object, but target is close to it @@ -1328,7 +1328,7 @@ void scaleDamage(XSPRITE* pXSprite) { curScale[kDmgSpirit] = 32 + Random(18); break; case kMissileFireball: - case kMissileFireballNapam: + case kMissileFireballNapalm: case kMissileFireballCerberus: case kMissileFireballTchernobog: curScale[kDmgBurn] = 50; diff --git a/source/games/blood/src/common_game.h b/source/games/blood/src/common_game.h index 450a3ffb7..30768ba05 100644 --- a/source/games/blood/src/common_game.h +++ b/source/games/blood/src/common_game.h @@ -172,17 +172,35 @@ enum { // (weapons) kItemWeaponBase = 40, + kItemWeaponRandom = kItemWeaponBase, kItemWeaponSawedoff = 41, kItemWeaponTommygun = 42, + kItemWeaponFlarePistol = 43, kItemWeaponVoodooDoll = 44, + kItemWeaponTeslaCannon = 45, + kItemWeaponNapalmLauncher = 46, + kItemWeaponPitchfork = 47, + kItemWeaponSprayCan = 48, + kItemWeaponTNT = 49, kItemWeaponLifeLeech = 50, kItemWeaponMax = 51, // items (ammos) kItemAmmoBase = 60, + kItemAmmoSprayCan = kItemAmmoBase, + kItemAmmoTNTBundle = 62, + kItemAmmoTNTBox = 63, + kItemAmmoProxBombBundle = 64, + kItemAmmoRemoteBombBundle = 65, + kItemAmmoTrappedSoul = 66, kItemAmmoSawedoffFew = 67, + kItemAmmoSawedoffBox = 68, kItemAmmoTommygunFew = 69, - kAmmoItemVoodooDoll = 70, + kItemAmmoVoodooDoll = 70, + kItemAmmoTommygunDrum = 72, + kItemAmmoTeslaCharge = 73, + kItemAmmoFlares = 76, + kItemAmmoGasolineCan = 79, kItemAmmoMax = 81, kItemBase = 100, @@ -302,7 +320,7 @@ enum { kMissilePukeGreen = 309, kMissileUnused = 310, kMissileArcGargoyle = 311, - kMissileFireballNapam = 312, + kMissileFireballNapalm = 312, kMissileFireballCerberus = 313, kMissileFireballTchernobog = 314, kMissileLifeLeechRegular = 315, diff --git a/source/games/blood/src/gameutil.cpp b/source/games/blood/src/gameutil.cpp index c51e73e3b..2840c85f8 100644 --- a/source/games/blood/src/gameutil.cpp +++ b/source/games/blood/src/gameutil.cpp @@ -886,23 +886,20 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect int x2 = wall[nWallB].x, y2 = wall[nWallB].y; int nLength = approxDist(x1-x2, y1-y2); const int nDist2 = (nDist+(nDist>>1))<<4; - if (nLength > nDist2) // if span is greater than range * 1.5, test midsection + nLength = ClipRange(nLength / nDist2, 1, 4); // never split more than 4 times + for (int k = 0; true; k++) // subdivide span into smaller chunks towards direction { - nLength = ClipRange(nLength / nDist2, 1, 4); // never split more than 4 times - for (int k = 0; k < nLength; k++) // subdivide span into smaller chunks towards direction - { - const int xcenter = (x1+x2)>>1, ycenter = (y1+y2)>>1; - withinRange = CheckProximityPoint(xcenter, ycenter, 0, x, y, 0, nDist); - if (withinRange) - break; - if ((k+1) == nLength) // reached end, no point in calculating direction/center again - break; - const bool bDir = approxDist(x-x1, y-y1) < approxDist(x-x2, y-y2); - if (bDir) // step closer and check again - x2 = xcenter, y2 = ycenter; - else - x1 = xcenter, y1 = ycenter; - } + const int xcenter = (x1+x2)>>1, ycenter = (y1+y2)>>1; + withinRange = CheckProximityPoint(xcenter, ycenter, 0, x, y, 0, nDist); + if (withinRange) + break; + if (k == (nLength-1)) // reached end + break; + const bool bDir = approxDist(x-x1, y-y1) < approxDist(x-x2, y-y2); + if (bDir) // step closer and check again + x2 = xcenter, y2 = ycenter; + else + x1 = xcenter, y1 = ycenter; } } if (withinRange) // if new sector is within range, set to current sector and test walls diff --git a/source/games/blood/src/loadsave.cpp b/source/games/blood/src/loadsave.cpp index 08ee82125..7589b0e0e 100644 --- a/source/games/blood/src/loadsave.cpp +++ b/source/games/blood/src/loadsave.cpp @@ -318,7 +318,7 @@ static AISTATE* allAIStates[] = &spidSearch, &spidBite, &spidJump, - &spid13A92C, + &spidBirth, &tchernobogIdle, &tchernobogSearch, &tchernobogChase, diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index c4a3a4c28..b97ffbfb6 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -491,7 +491,7 @@ void nnExtInitModernStuff(bool bSaveLoad) { nnExtResetGlobals(); // use true random only for single player mode, otherwise use Blood's default one. - if (gGameOptions.nGameType == 0 && !VanillaMode() && !DemoRecordStatus()) { + if (gGameOptions.nGameType == 0 && !VanillaMode()) { gStdRandom.seed(std::random_device()()); diff --git a/source/games/blood/src/seq.cpp b/source/games/blood/src/seq.cpp index 9977fd10e..0bf150b03 100644 --- a/source/games/blood/src/seq.cpp +++ b/source/games/blood/src/seq.cpp @@ -75,7 +75,7 @@ static void (*seqClientCallback[])(int, DBloodActor*) = { ratBiteSeqCallback, SpidBiteSeqCallback, SpidJumpSeqCallback, - sub_71370, + SpidBirthSeqCallback, sub_71BD4, sub_720AC, sub_71A90, diff --git a/source/games/blood/src/seqcb.h b/source/games/blood/src/seqcb.h index 62e5c9987..5f7f70ad1 100644 --- a/source/games/blood/src/seqcb.h +++ b/source/games/blood/src/seqcb.h @@ -43,7 +43,7 @@ void sub_70284(int, DBloodActor*); void ratBiteSeqCallback(int, DBloodActor*); void SpidBiteSeqCallback(int, DBloodActor*); void SpidJumpSeqCallback(int, DBloodActor*); -void sub_71370(int, DBloodActor*); +void SpidBirthSeqCallback(int, DBloodActor*); void sub_71A90(int, DBloodActor*); void sub_71BD4(int, DBloodActor*); void sub_720AC(int, DBloodActor*); @@ -104,7 +104,7 @@ enum nRatBiteClient, nSpidBiteClient, nSpidJumpClient, - dword_279B50, + nSpidBirthClient, dword_279B54, dword_279B58, dword_279B5C, diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index ec15179de..e535f9552 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -1466,6 +1466,7 @@ void OperateTeleport(unsigned int nSector, XSECTOR *pXSector) { playerResetInertia(pPlayer); pPlayer->zViewVel = pPlayer->zWeaponVel = 0; + pPlayer->angle.settarget(pSprite->ang, true); } } } diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index a49e74fa4..424d69dde 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -151,7 +151,7 @@ static bool checkFired6or7(PLAYER *pPlayer) case 6: return 1; case 7: - if (VanillaMode() || DemoRecordStatus()) + if (VanillaMode()) return 0; return 1; } @@ -717,7 +717,7 @@ void WeaponLower(PLAYER *pPlayer) } break; case 7: // throwing ignited alt fire spray - if (VanillaMode() || DemoRecordStatus() || (pPlayer->newWeapon != 0)) + if (VanillaMode() || (pPlayer->newWeapon != 0)) break; pPlayer->weaponState = 1; StartQAV(pPlayer, 11, -1, 0); @@ -1465,7 +1465,7 @@ void AltFireVoodoo(int nTrigger, PLAYER *pPlayer) // by NoOne: trying to simulate v1.0x voodoo here. // dunno how exactly it works, but at least it not spend all the ammo on alt fire - if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus()) { + if (gGameOptions.weaponsV10x && !VanillaMode()) { int nCount = ClipHigh(pPlayer->ammoCount[9], pPlayer->aimTargetsCount); if (nCount > 0) { @@ -1622,7 +1622,7 @@ void FireNapalm(int nTrigger, PLAYER *pPlayer) offset = 50; break; } - playerFireMissile(pPlayer, offset, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapam); + playerFireMissile(pPlayer, offset, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapalm); sfxPlay3DSound(pSprite, 480, 2, 0); UseAmmo(pPlayer, 4, 1); pPlayer->flashEffect = 1; @@ -1631,8 +1631,8 @@ void FireNapalm(int nTrigger, PLAYER *pPlayer) void FireNapalm2(int , PLAYER *pPlayer) { spritetype *pSprite = pPlayer->pSprite; - playerFireMissile(pPlayer, -120, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapam); - playerFireMissile(pPlayer, 120, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapam); + playerFireMissile(pPlayer, -120, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapalm); + playerFireMissile(pPlayer, 120, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapalm); sfxPlay3DSound(pSprite, 480, 2, 0); UseAmmo(pPlayer, 4, 2); pPlayer->flashEffect = 1; @@ -2196,7 +2196,7 @@ void WeaponProcess(PLAYER *pPlayer) { } if (pPlayer->newWeapon) { - if (pPlayer->isUnderwater && BannedUnderwater(pPlayer->newWeapon) && !checkFired6or7(pPlayer) && !VanillaMode() && !DemoRecordStatus()) // skip banned weapons when underwater and using next/prev weapon key inputs + if (pPlayer->isUnderwater && BannedUnderwater(pPlayer->newWeapon) && !checkFired6or7(pPlayer) && !VanillaMode()) // skip banned weapons when underwater and using next/prev weapon key inputs { if (prevNewWeaponVal == WeaponSel_Next || prevNewWeaponVal == WeaponSel_Prev) // if player switched weapons { @@ -2247,7 +2247,7 @@ void WeaponProcess(PLAYER *pPlayer) { pPlayer->newWeapon = kWeapRemote; } } - else if ((pPlayer->newWeapon == kWeapSpraycan) && !VanillaMode() && !DemoRecordStatus()) + else if ((pPlayer->newWeapon == kWeapSpraycan) && !VanillaMode()) { if ((pPlayer->curWeapon == kWeapSpraycan) && (pPlayer->weaponState == 2)) // fix spray can state glitch when switching from spray to tnt and back quickly { @@ -2570,10 +2570,10 @@ void WeaponProcess(PLAYER *pPlayer) { case kWeapNapalm: if (powerupCheck(pPlayer, kPwUpTwoGuns)) // by NoOne: allow napalm launcher alt fire act like in v1.0x versions - if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus()) StartQAV(pPlayer, kQAV2NAPFIR2, nClientFireNapalm2); - else StartQAV(pPlayer, kQAV2NAPFIRE, nClientAltFireNapalm, 0); + if (gGameOptions.weaponsV10x && !VanillaMode()) StartQAV(pPlayer, kQAV2NAPFIR2, nClientFireNapalm2); + else StartQAV(pPlayer, kQAV2NAPFIRE, nClientAltFireNapalm); else - StartQAV(pPlayer, kQAVNAPFIRE, (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus()) ? nClientFireNapalm : nClientAltFireNapalm); + StartQAV(pPlayer, kQAVNAPFIRE, (gGameOptions.weaponsV10x && !VanillaMode()) ? nClientFireNapalm : nClientAltFireNapalm); return; case kWeapFlareGun: if (CheckAmmo(pPlayer, 1, 8)) @@ -2618,7 +2618,7 @@ void teslaHit(spritetype *pMissile, int a2) int nDist = 300; int nSector = pMissile->sectnum; int nOwner = pMissile->owner; - const bool newSectCheckMethod = !VanillaMode() && !DemoRecordStatus(); // use new sector checking logic + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(nSector, x, y, nDist, sectmap, nullptr, newSectCheckMethod); bool v4 = true; DBloodActor* actor = nullptr; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index ae74c085e..56b1c91f3 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -962,6 +962,12 @@ OptionValue "ExplosBehavior" 1, "$OPTVAL_OLD" } +OptionValue "EnemyBehavior" +{ + 0, "$OPTVAL_DEFAULT" + 1, "$OPTVAL_OLD" +} + OptionMenu GameplayOptions protected { @@ -984,6 +990,7 @@ OptionMenu GameplayOptions protected { Option "$PLRMNU_EQUIP", "cl_weaponswitch", "WeapSwitch" Option "$EXPLOS_BEHAVIOR", "cl_bloodvanillaexplosions", "ExplosBehavior" + Option "$ENEMY_BEHAVIOR", "cl_bloodvanillaenemies", "EnemyBehavior" } ifgame(Exhumed) {