From 6a0785bbd47b7a7ba19b99ccf796d31ce9d5f840 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 22 May 2020 18:28:03 +0200 Subject: [PATCH] - manual update of some missed content. --- source/blood/src/actor.cpp | 11 +- source/blood/src/aiunicult.cpp | 51 +- source/blood/src/db.cpp | 1 + source/blood/src/nnexts.cpp | 698 +++++++++++++----------- source/blood/src/nnexts.h | 3 +- source/blood/src/triggers.cpp | 20 +- source/blood/src/view.cpp | 4 +- source/core/gamecontrol.h | 1 + source/libsmackerdec/src/FileStream.cpp | 2 +- source/rr/src/playmve.h | 4 - 10 files changed, 429 insertions(+), 366 deletions(-) diff --git a/source/blood/src/actor.cpp b/source/blood/src/actor.cpp index 0a068b5ca..71247e7fc 100644 --- a/source/blood/src/actor.cpp +++ b/source/blood/src/actor.cpp @@ -2262,9 +2262,9 @@ const THINGINFO thingInfo[] = { 800, (char)-128, 0, - 48, - 48, - 64, 64, 112, 64, 0, 96, 96, + 44, + 44, + 0, 1024, 512, 1024, 0, 64, 512, }, }; @@ -2359,7 +2359,7 @@ const EXPLOSION explodeInfo[] = { }, }; - +int gDudeDrag = 0x2a00; short gAffectedSectors[kMaxSectors]; short gAffectedXWalls[kMaxXWalls]; @@ -5260,7 +5260,8 @@ void actExplodeSprite(spritetype *pSprite) return; sfxKill3DSound(pSprite, -1, -1); evKill(pSprite->index, 3); - int nType; + int nType = kExplosionStandard; + switch (pSprite->type) { case kMissileFireballNapam: diff --git a/source/blood/src/aiunicult.cpp b/source/blood/src/aiunicult.cpp index e737e6d39..5d0804478 100644 --- a/source/blood/src/aiunicult.cpp +++ b/source/blood/src/aiunicult.cpp @@ -365,14 +365,14 @@ static void ThrowThing(int nXIndex, bool impact) { case kModernThingEnemyLifeLeech: XSPRITE* pXThing = &xsprite[pThing->extra]; if (pLeech != NULL) pXThing->health = pXLeech->health; - else pXThing->health = 300 * gGameOptions.nDifficulty; + else pXThing->health = ((pThinkInfo->startHealth << 4) * gGameOptions.nDifficulty) >> 1; sfxPlay3DSound(pSprite, 490, -1, 0); - if (gGameOptions.nDifficulty <= 2) pXThing->data3 = 32700; - else pXThing->data3 = Random(10); + pXThing->data3 = 512 / (gGameOptions.nDifficulty + 1); pThing->cstat &= ~CSTAT_SPRITE_BLOCK; - pThing->pal = 6; + pThing->pal = 6; + pThing->clipdist = 0; pXThing->target = pTarget->index; pXThing->Proximity = true; pXThing->stateTimer = 1; @@ -438,17 +438,19 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) { if (pXTarget == NULL) { // target lost if(spriteIsUnderwater(pSprite,false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW); else aiGenDudeNewState(pSprite, &genDudeSearchShortL); + pXSprite->target = -1; return; } else if (pXTarget->health <= 0) { // target is dead PLAYER* pPlayer = NULL; if ((!IsPlayerSprite(pTarget)) || ((pPlayer = getPlayerById(pTarget->type)) != NULL && pPlayer->fraggerId == pSprite->index)) { - playGenDudeSound(pSprite, kGenDudeSndTargetDead); - if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW); - else aiGenDudeNewState(pSprite, &genDudeSearchShortL); + playGenDudeSound(pSprite, kGenDudeSndTargetDead); + if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW); + else aiGenDudeNewState(pSprite, &genDudeSearchShortL); } else if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeGotoW); else aiGenDudeNewState(pSprite, &genDudeGotoL); + pXSprite->target = -1; return; } @@ -477,6 +479,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) { if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) { if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW); else aiGenDudeNewState(pSprite, &genDudeSearchShortL); + pXSprite->target = -1; return; } } @@ -1388,57 +1391,57 @@ void scaleDamage(XSPRITE* pXSprite) { switch (surfType) { case 1: // stone curScale[kDmgFall] = 0; - curScale[kDmgBullet] -= 128; - curScale[kDmgBurn] -= 50; - curScale[kDmgExplode] -= 40; + curScale[kDmgBullet] -= 200; + curScale[kDmgBurn] -= 100; + curScale[kDmgExplode] -= 80; curScale[kDmgChoke] += 30; curScale[kDmgElectric] += 20; break; case 2: // metal curScale[kDmgFall] = 16; - curScale[kDmgBullet] -= 64; - curScale[kDmgBurn] -= 45; - curScale[kDmgExplode] -= 35; + curScale[kDmgBullet] -= 128; + curScale[kDmgBurn] -= 90; + curScale[kDmgExplode] -= 55; curScale[kDmgChoke] += 20; curScale[kDmgElectric] += 30; break; case 3: // wood - curScale[kDmgBullet] -= 5; + curScale[kDmgBullet] -= 10; curScale[kDmgBurn] += 50; curScale[kDmgExplode] += 40; curScale[kDmgChoke] += 10; - curScale[kDmgElectric] -= 30; + curScale[kDmgElectric] -= 60; break; case 5: // water case 6: // dirt case 7: // clay case 13: // goo curScale[kDmgFall] = 8; - curScale[kDmgBullet] -= 10; - curScale[kDmgBurn] -= 128; - curScale[kDmgExplode] -= 30; + curScale[kDmgBullet] -= 20; + curScale[kDmgBurn] -= 200; + curScale[kDmgExplode] -= 60; curScale[kDmgChoke] = 0; curScale[kDmgElectric] += 40; break; case 8: // snow case 9: // ice curScale[kDmgFall] = 8; - curScale[kDmgBullet] -= 10; - curScale[kDmgBurn] -= 60; - curScale[kDmgExplode] -= 40; + curScale[kDmgBullet] -= 20; + curScale[kDmgBurn] -= 100; + curScale[kDmgExplode] -= 50; curScale[kDmgChoke] = 0; curScale[kDmgElectric] += 40; break; case 10: // leaves case 12: // plant curScale[kDmgFall] = 0; - curScale[kDmgBullet] -= 5; + curScale[kDmgBullet] -= 10; curScale[kDmgBurn] += 70; curScale[kDmgExplode] += 50; break; case 11: // cloth curScale[kDmgFall] = 8; - curScale[kDmgBullet] -= 5; + curScale[kDmgBullet] -= 10; curScale[kDmgBurn] += 30; curScale[kDmgExplode] += 20; break; @@ -2116,7 +2119,7 @@ bool genDudePrepare(spritetype* pSprite, int propId) { pExtra->nLifeLeech = -1; if (pSprite->owner != kMaxSprites - 1) { for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { - if (sprite[nSprite].owner == pSprite->index && pSprite->type == kModernThingEnemyLifeLeech) { + if (sprite[nSprite].owner == pSprite->index && sprite[nSprite].type == kModernThingEnemyLifeLeech) { pExtra->nLifeLeech = nSprite; break; } diff --git a/source/blood/src/db.cpp b/source/blood/src/db.cpp index 570d12ac1..6d4117021 100644 --- a/source/blood/src/db.cpp +++ b/source/blood/src/db.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS +bool gModernMap = false; unsigned short gStatCount[kMaxStatus + 1]; XSPRITE xsprite[kMaxXSprites]; diff --git a/source/blood/src/nnexts.cpp b/source/blood/src/nnexts.cpp index 1b8f6752a..84862761f 100644 --- a/source/blood/src/nnexts.cpp +++ b/source/blood/src/nnexts.cpp @@ -49,7 +49,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -bool gModernMap = false; bool gAllowTrueRandom = false; bool gEventRedirectsUsed = false; SPRITEMASS gSpriteMass[]; // cache for getSpriteMassBySize(); @@ -113,20 +112,20 @@ THINGINFO_EXTRA gThingInfoExtra[] = { }; DUDEINFO_EXTRA gDudeInfoExtra[] = { - false, false, false, false, false, false, false, false, false, false, true, false, - false, false, false, false, true, false, true, true, false, true, false, false, - true, false, false, false, false, false, false, true, true, false, true, true, - false, true, true, false, true, true, false, true, true, false, true, false, - false, true, true, true, true, true, false, true, true, false, false, true, - false, true, true, false, false, true, false, true, true, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, true, false, false, true, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, true, false, false, true, false, false, false, false, false, false, false, - false, false, false, false, false, false, + false, false, false, false, false, false, false, true, + false, false, false, true, true, true, true, false, + true, false, false, false, false, true, false, true, + false, true, false, true, false, true, false, true, + false, true, true, true, false, true, false, false, + false, true, false, false, false, true, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, true, + false, false, false, false, false, false, false, false, + false, true, false, true, false, false, false, false, + false, false, false, false, }; // for actor.cpp @@ -294,78 +293,11 @@ void nnExtInitModernStuff(bool bSaveLoad) { break; case kModernCondition: case kModernConditionFalse: - if (!bSaveLoad) { - - pSprite->yvel = pSprite->type; // store it here, because inittype gets cleared later. - pSprite->type = kModernCondition; - - if (!pXSprite->rxID) { - ThrowError("\nThe condition must have RX ID!\nSPRITE #%d", pSprite->index); - } else if (!pXSprite->txID && !pSprite->hitag) { - consoleSysMsg("Inactive condition: RX ID %d, SPRITE #%d", pXSprite->rxID, pSprite->index); - break; - } - + if (bSaveLoad) break; + else if (!pXSprite->rxID) condError(pXSprite,"\nThe condition must have RX ID!\nSPRITE #%d", pSprite->index); + else if (!pXSprite->txID && !pSprite->hitag) { + consoleSysMsg("The condition must have TX ID or hitag to be set: RX ID %d, SPRITE #%d", pXSprite->rxID, pSprite->index); } - - // collect objects for tracking conditions - if (pXSprite->busyTime <= 0) break; - else if (gTrackingCondsCount >= kMaxTrackingConditions) - ThrowError("\nMax (%d) tracking conditions reached!", kMaxTrackingConditions); - - int tracedObjects = 0; TRCONDITION* pCond = &gCondition[gTrackingCondsCount]; - for (int i = 0; i < kMaxXSprites; i++) { - if (!spriRangeIsFine(xsprite[i].reference) || xsprite[i].txID != pXSprite->rxID || xsprite[i].reference == pSprite->index) - continue; - - XSPRITE* pXSpr = &xsprite[i]; spritetype* pSpr = &sprite[pXSpr->reference]; - int index = pXSpr->reference; int cmd = pXSpr->command; - if (pSpr->statnum == kStatModernPlayerLinker && pXSpr->isTriggered && bSaveLoad) { - - // assign player sprite after savegame loading - index = pXSpr->sysData1; - cmd = xsprite[sprite[index].extra].command; - - } - - if (pSpr->type == kModernCondition) - ThrowError("\nTracking condition always must be first in condition sequence!\nRX ID: %d, SPRITE #%d", pXSpr->rxID, pXSpr->reference); - - if (tracedObjects >= kMaxTracedObjects) - ThrowError("\nMax (%d) objects to track reached for condition #%d, rx id: %d!", pSprite->index, pXSprite->rxID); - - pCond->obj[tracedObjects].type = OBJ_SPRITE; - pCond->obj[tracedObjects].index = index; - pCond->obj[tracedObjects++].cmd = cmd; - } - - for (int i = 0; i < kMaxXSectors; i++) { - if (!sectRangeIsFine(xsector[i].reference) || xsector[i].txID != pXSprite->rxID) continue; - else if (tracedObjects < kMaxTracedObjects) { - pCond->obj[tracedObjects].type = OBJ_SECTOR; - pCond->obj[tracedObjects].index = xsector[i].reference; - pCond->obj[tracedObjects++].cmd = xsector[i].command; - } else { - ThrowError("\nMax (%d) objects to track reached for condition #%d, rx id: %d!", pSprite->index, pXSprite->rxID); - } - } - - for (int i = 0; i < kMaxXWalls; i++) { - if (!sectRangeIsFine(xwall[i].reference) || xwall[i].txID != pXSprite->rxID) continue; - else if (tracedObjects < kMaxTracedObjects) { - pCond->obj[tracedObjects].type = OBJ_WALL; - pCond->obj[tracedObjects].index = xwall[i].reference; - pCond->obj[tracedObjects++].cmd = xwall[i].command; - } else { - ThrowError("\nMax (%d) objects to track reached for condition #%d, rx id: %d!", pSprite->index, pXSprite->rxID); - } - } - - pCond->length = tracedObjects; - if (tracedObjects == 0) - consoleSysMsg("No objects to track found for condition #%d, rx id: %d!", pSprite->index, pXSprite->rxID); - - pXSprite->sysData1 = gTrackingCondsCount++; break; } @@ -395,6 +327,10 @@ void nnExtInitModernStuff(bool bSaveLoad) { } else { + // auto set going On and going Off if both are empty + if (pXSprite->txID && !pXSprite->triggerOn && !pXSprite->triggerOff) + pXSprite->triggerOn = pXSprite->triggerOff = true; + // copy custom start health to avoid overwrite by kThingBloodChunks if (IsDudeSprite(pSprite)) pXSprite->sysData2 = pXSprite->data4; @@ -404,20 +340,17 @@ void nnExtInitModernStuff(bool bSaveLoad) { bool sysStat = true; switch (pSprite->statnum) { case kStatModernDudeTargetChanger: - sysStat = (pSprite->type == kModernDudeTargetChanger); + sysStat = (pSprite->type != kModernDudeTargetChanger); break; case kStatModernCondition: - sysStat = (pSprite->type == kModernCondition || pSprite->type == kModernConditionFalse); + sysStat = (pSprite->type != kModernCondition && pSprite->type != kModernConditionFalse); break; case kStatModernEventRedirector: - sysStat = (pSprite->type == kModernRandomTX || pSprite->type == kModernSequentialTX); - break; - case kStatModernSeqSpawner: - sysStat = (pSprite->type == kModernSeqSpawner); + sysStat = (pSprite->type != kModernRandomTX && pSprite->type != kModernSequentialTX); break; case kStatModernPlayerLinker: case kStatModernQavScene: - sysStat = (pSprite->type == kModernPlayerControl); + sysStat = (pSprite->type != kModernPlayerControl); break; } @@ -455,9 +388,6 @@ void nnExtInitModernStuff(bool bSaveLoad) { break; } break; - case kModernSeqSpawner: - changespritestat(pSprite->index, kStatModernSeqSpawner); - break; case kModernThingTNTProx: pXSprite->Proximity = true; break; @@ -472,31 +402,35 @@ void nnExtInitModernStuff(bool bSaveLoad) { found++; } break; + case kDudePodMother: + case kDudeTentacleMother: + pXSprite->state = 1; + break; case kModernPlayerControl: switch (pXSprite->command) { case kCmdLink: if (pXSprite->data1 < 1 || pXSprite->data1 >= kMaxPlayers) - ThrowError("\nPlayer Control (SPRITE #%d):\nPlayer out of a range (data1 = %d)", pSprite->index, pXSprite->data1); + ThrowError("\nPlayer Control (SPRITE #%d):\nPlayer out of a range (data1 = %d)", pSprite->index, pXSprite->data1); //if (numplayers < pXSprite->data1) //ThrowError("\nPlayer Control (SPRITE #%d):\n There is no player #%d", pSprite->index, pXSprite->data1); - if (pXSprite->rxID && pXSprite->rxID != kChannelLevelStart) - ThrowError("\nPlayer Control (SPRITE #%d) with Link command should have no RX ID!", pSprite->index, pXSprite->data1); + if (pXSprite->rxID && pXSprite->rxID != kChannelLevelStart) + ThrowError("\nPlayer Control (SPRITE #%d) with Link command should have no RX ID!", pSprite->index, pXSprite->data1); - if (pXSprite->txID && pXSprite->txID < kChannelUser) - ThrowError("\nPlayer Control (SPRITE #%d):\nTX ID should be in range of %d and %d!", pSprite->index, kChannelUser, kChannelMax); + if (pXSprite->txID && pXSprite->txID < kChannelUser) + ThrowError("\nPlayer Control (SPRITE #%d):\nTX ID should be in range of %d and %d!", pSprite->index, kChannelUser, kChannelMax); - // only one linker per player allowed - for (int nSprite = headspritestat[kStatModernPlayerLinker]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { - XSPRITE* pXCtrl = &xsprite[sprite[nSprite].extra]; - if (pXSprite->data1 == pXCtrl->data1) - ThrowError("\nPlayer Control (SPRITE #%d):\nPlayer %d already linked with different player control sprite #%d!", pSprite->index, pXSprite->data1, nSprite); - } + // only one linker per player allowed + for (int nSprite = headspritestat[kStatModernPlayerLinker]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { + XSPRITE* pXCtrl = &xsprite[sprite[nSprite].extra]; + if (pXSprite->data1 == pXCtrl->data1) + ThrowError("\nPlayer Control (SPRITE #%d):\nPlayer %d already linked with different player control sprite #%d!", pSprite->index, pXSprite->data1, nSprite); + } pXSprite->sysData1 = -1; pSprite->cstat &= ~CSTAT_SPRITE_BLOCK; - changespritestat(pSprite->index, kStatModernPlayerLinker); - break; + changespritestat(pSprite->index, kStatModernPlayerLinker); + break; case 67: // play qav animation if (pXSprite->txID && !pXSprite->waitTime) pXSprite->waitTime = 1; changespritestat(pSprite->index, kStatModernQavScene); @@ -504,18 +438,35 @@ void nnExtInitModernStuff(bool bSaveLoad) { } break; case kModernCondition: - if (pXSprite->waitTime > 0 && pXSprite->busyTime > 0) { - pXSprite->busyTime += ClipHigh(((pXSprite->waitTime * 120) / 10), 4095); pXSprite->waitTime = 0; - consoleSysMsg("Summing busyTime and waitTime for tracking condition #%d, RX ID %d. Result = %d ticks", pSprite->index, pXSprite->rxID, pXSprite->busyTime); + case kModernConditionFalse: + if (pXSprite->busyTime > 0) { + + if (pXSprite->waitTime > 0) { + pXSprite->busyTime += ClipHigh(((pXSprite->waitTime * 120) / 10), 4095); pXSprite->waitTime = 0; + consoleSysMsg("Summing busyTime and waitTime for tracking condition #%d, RX ID %d. Result = %d ticks", pSprite->index, pXSprite->rxID, pXSprite->busyTime); + } + + pXSprite->busy = pXSprite->busyTime; } + + if (pXSprite->waitTime && pXSprite->command >= kCmdNumberic) + condError(pXSprite, "Delay is not available when using numberic commands (%d - %d)", kCmdNumberic, 255); pXSprite->Decoupled = false; // must go through operateSprite always pXSprite->Sight = pXSprite->Impact = pXSprite->Touch = pXSprite->triggerOff = false; pXSprite->Proximity = pXSprite->Push = pXSprite->Vector = pXSprite->triggerOn = false; pXSprite->state = pXSprite->restState = 0; - pXSprite->targetX = pXSprite->targetY = pXSprite->targetZ = pXSprite->target = -1; + pXSprite->targetX = pXSprite->targetY = pXSprite->targetZ = pXSprite->target = pXSprite->sysData2 = -1; changespritestat(pSprite->index, kStatModernCondition); + int oldStat = pSprite->cstat; pSprite->cstat = 0x30; + + if (oldStat & CSTAT_SPRITE_BLOCK) + pSprite->cstat |= CSTAT_SPRITE_BLOCK; + + if (oldStat & 0x2000) pSprite->cstat |= 0x2000; + else if (oldStat & 0x4000) pSprite->cstat |= 0x4000; + pSprite->cstat |= CSTAT_SPRITE_INVISIBLE; break; } @@ -705,13 +656,13 @@ int nnExtRandom(int a, int b) { } int GetDataVal(spritetype* pSprite, int data) { - if (pSprite->extra >= 0) { - switch (data) { - case 0: return xsprite[pSprite->extra].data1; - case 1: return xsprite[pSprite->extra].data2; - case 2: return xsprite[pSprite->extra].data3; - case 3: return xsprite[pSprite->extra].data4; - } + dassert(xspriRangeIsFine(pSprite->extra)); + + switch (data) { + case 0: return xsprite[pSprite->extra].data1; + case 1: return xsprite[pSprite->extra].data2; + case 2: return xsprite[pSprite->extra].data3; + case 3: return xsprite[pSprite->extra].data4; } return -1; @@ -807,6 +758,27 @@ spritetype* randomSpawnDude(spritetype* pSource) { void nnExtProcessSuperSprites() { + // process tracking conditions + if (gTrackingCondsCount > 0) { + for (int i = 0; i < gTrackingCondsCount; i++) { + + TRCONDITION* pCond = &gCondition[i]; XSPRITE* pXCond = &xsprite[pCond->xindex]; + if (pCond->length > 0 && !pXCond->locked && !pXCond->isTriggered && ++pXCond->busy >= pXCond->busyTime) { + + pXCond->busy = 0; + for (int k = 0; k < pCond->length; k++) { + + EVENT evn; + evn.index = pCond->obj[k].index; evn.cmd = pCond->obj[k].cmd; + evn.type = pCond->obj[k].type; evn.funcID = kCallbackMax; + useCondition(&sprite[pXCond->reference], pXCond, evn); + + } + + } + } + } + // process additional proximity sprites if (gProxySpritesCount > 0) { for (int i = 0; i < gProxySpritesCount; i++) { @@ -1326,25 +1298,13 @@ void windGenStopWindOnSectors(XSPRITE* pXSource) { } } -/*XSPRITE* trPlayerCtrlFindNextScene(XSPRITE* pXScene) { + +void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, bool force) { + + int nSource = pXSource->reference; TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer]; + + if (pCtrl->qavScene.index >= 0 && !force) return; - int curIndex = pXScene->reference; bool oldFound = false; - for (int i = bucketHead[pXScene->txID]; i < bucketHead[pXScene->txID + 1]; i++) { - if (sprite[rxBucket[i].index].type != kModernPlayerControl) continue; - else if (rxBucket[i].index == curIndex) { - oldFound = true; - continue; - } - - XSPRITE* pXSpr = &xsprite[sprite[rxBucket[i].index].extra]; - if (oldFound && pXSpr->command == 67 && pXSpr->data1 == pXScene->data1 && !pXSpr->locked) - return pXSpr; - } -}*/ - -void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer) { - - int nSource = sprite[pXSource->reference].index; TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer]; QAV* pQav = playerQavSceneLoad(pXSource->data2); if (pQav != NULL) { @@ -1385,16 +1345,16 @@ void trPlayerCtrlStopScene(PLAYER* pPlayer) { } if (pCtrl->qavScene.index >= 0) { - pCtrl->qavScene.index = -1; - pCtrl->qavScene.qavResrc = NULL; - pPlayer->sceneQav = -1; + pCtrl->qavScene.index = -1; + pCtrl->qavScene.qavResrc = NULL; + pPlayer->sceneQav = -1; - // restore weapon - if (pPlayer->pXSprite->health > 0) { + // restore weapon + if (pPlayer->pXSprite->health > 0) { int oldWeapon = (pXSource && pXSource->dropMsg != 0) ? pXSource->dropMsg : 1; - pPlayer->input.newWeapon = pPlayer->curWeapon = oldWeapon; - WeaponRaise(pPlayer); - } + pPlayer->input.newWeapon = pPlayer->curWeapon = oldWeapon; + WeaponRaise(pPlayer); + } } } @@ -1433,13 +1393,12 @@ void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition) { // let's check if there is tracking condition expecting objects with this TX id if (checkCondition && pXSource->txID >= kChannelUser) { - for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++) { - if (sprite[rxBucket[i].index].type != kModernCondition) continue; + for (int i = 0; i < gTrackingCondsCount; i++) { - XSPRITE* pXCond = &xsprite[sprite[rxBucket[i].index].extra]; - if (pXCond->busyTime <= 0) continue; - - TRCONDITION* pCond = &gCondition[pXCond->sysData1]; + TRCONDITION* pCond = &gCondition[i]; + if (xsprite[pCond->xindex].rxID != pXSource->txID) + continue; + // search for player control sprite and replace it with actual player sprite for (int k = 0; k < pCond->length; k++) { if (pCond->obj[k].type != OBJ_SPRITE || pCond->obj[k].index != pXSource->reference) continue; @@ -1447,6 +1406,7 @@ void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition) { pCond->obj[k].cmd = pPlayer->pXSprite->command; break; } + } } } @@ -1473,11 +1433,11 @@ void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer) { for (int i = 0; i < kModeMax; i++) { for (int a = 0; a < kPostureMax; a++) { POSTURE* curPosture = &pPlayer->pPosture[i][a]; POSTURE* defPosture = &gPostureDefaults[i][a]; - curPosture->frontAccel = (defPosture->frontAccel * speed) / kPercentFull; - curPosture->sideAccel = (defPosture->sideAccel * speed) / kPercentFull; - curPosture->backAccel = (defPosture->backAccel * speed) / kPercentFull; - } + curPosture->frontAccel = (defPosture->frontAccel * speed) / kPercFull; + curPosture->sideAccel = (defPosture->sideAccel * speed) / kPercFull; + curPosture->backAccel = (defPosture->backAccel * speed) / kPercFull; } + } } void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer) { @@ -1485,9 +1445,9 @@ void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer) { int jump = ClipRange(pXSource->data3, 0, 500); for (int i = 0; i < kModeMax; i++) { POSTURE* curPosture = &pPlayer->pPosture[i][kPostureStand]; POSTURE* defPosture = &gPostureDefaults[i][kPostureStand]; - curPosture->normalJumpZ = (defPosture->normalJumpZ * jump) / kPercentFull; - curPosture->pwupJumpZ = (defPosture->pwupJumpZ * jump) / kPercentFull; - } + curPosture->normalJumpZ = (defPosture->normalJumpZ * jump) / kPercFull; + curPosture->pwupJumpZ = (defPosture->pwupJumpZ * jump) / kPercFull; + } } void trPlayerCtrlSetScreenEffect(XSPRITE* pXSource, PLAYER* pPlayer) { @@ -1528,13 +1488,13 @@ void trPlayerCtrlSetScreenEffect(XSPRITE* pXSource, PLAYER* pPlayer) { void trPlayerCtrlSetLookAngle(XSPRITE* pXSource, PLAYER* pPlayer) { - int upAngle = 289; int downAngle = -347; - double lookStepUp = 4.0 * upAngle / 60.0; - double lookStepDown = -4.0 * downAngle / 60.0; + CONSTEXPR int upAngle = 289; CONSTEXPR int downAngle = -347; + CONSTEXPR double lookStepUp = 4.0 * upAngle / 60.0; + CONSTEXPR double lookStepDown = -4.0 * downAngle / 60.0; int look = pXSource->data2 << 5; - if (look > 0) pPlayer->q16look = fix16_min(mulscale8(fix16_from_dbl(lookStepUp), look), fix16_from_int(upAngle)); - else if (look < 0) pPlayer->q16look = -fix16_max(mulscale8(fix16_from_dbl(lookStepDown), abs(look)), fix16_from_int(downAngle)); + if (look > 0) pPlayer->q16look = fix16_min(mulscale8(F16(lookStepUp), look), F16(upAngle)); + else if (look < 0) pPlayer->q16look = -fix16_max(mulscale8(F16(lookStepDown), abs(look)), F16(downAngle)); else pPlayer->q16look = 0; } @@ -1569,12 +1529,17 @@ void trPlayerCtrlEraseStuff(XSPRITE* pXSource, PLAYER* pPlayer) { pPlayer->packSlots[i].isActive = false; pPlayer->packSlots[i].curAmount = 0; } - pPlayer->packItemId = -1; + pPlayer->packItemId = -1; if (pXSource->data2) break; fallthrough__; case 4: // erase all keys for (int i = 0; i < 8; i++) pPlayer->hasKey[i] = false; if (pXSource->data2) break; + fallthrough__; + case 5: // erase powerups + for (int i = 0; i < kMaxPowerUps; i++) pPlayer->pwUpTime[i] = 0; + if (pXSource->data2) break; + fallthrough__; } } @@ -1604,34 +1569,34 @@ void trPlayerCtrlGiveStuff(XSPRITE* pXSource, PLAYER* pPlayer, TRPLAYERCTRL* pCt for (int i = 0; i < 11; i++) { if (gWeaponItemData[i].type != weapon) continue; - const WEAPONITEMDATA* pWeaponData = &gWeaponItemData[i]; int nAmmoType = pWeaponData->ammoType; + WEAPONITEMDATA* pWeaponData = &gWeaponItemData[i]; int nAmmoType = pWeaponData->ammoType; switch (pXSource->data2) { case 1: pPlayer->hasWeapon[weapon] = true; if (pPlayer->ammoCount[nAmmoType] >= pWeaponData->count) break; - pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pWeaponData->count, gAmmoInfo[nAmmoType].max); + pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pWeaponData->count, gAmmoInfo[nAmmoType].max); break; case 2: - pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pXSource->data4, gAmmoInfo[nAmmoType].max); - break; - } + pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pXSource->data4, gAmmoInfo[nAmmoType].max); + break; + } break; } break; } if (pPlayer->hasWeapon[weapon] && pXSource->data4 == 0) { // switch on it - pPlayer->nextWeapon = 0; + pPlayer->nextWeapon = 0; - if (pPlayer->sceneQav >= 0 && spriRangeIsFine(pCtrl->qavScene.index)) { - XSPRITE* pXScene = &xsprite[sprite[pCtrl->qavScene.index].extra]; + if (pPlayer->sceneQav >= 0 && spriRangeIsFine(pCtrl->qavScene.index)) { + XSPRITE* pXScene = &xsprite[sprite[pCtrl->qavScene.index].extra]; pXScene->dropMsg = weapon; } else if (pPlayer->curWeapon != weapon) { pPlayer->input.newWeapon = weapon; - WeaponRaise(pPlayer); - } + WeaponRaise(pPlayer); } - break; } + break; + } } void trPlayerCtrlUsePackItem(XSPRITE* pXSource, PLAYER* pPlayer, int evCmd) { @@ -1644,7 +1609,7 @@ void trPlayerCtrlUsePackItem(XSPRITE* pXSource, PLAYER* pPlayer, int evCmd) { if (pPlayer->packSlots[invItem].isActive) packUseItem(pPlayer, invItem); break; default: - packUseItem(pPlayer, invItem); + packUseItem(pPlayer, invItem); break; } @@ -1655,8 +1620,8 @@ void trPlayerCtrlUsePackItem(XSPRITE* pXSource, PLAYER* pPlayer, int evCmd) { if (!pXSource->data4) break; fallthrough__; case 1: // force remove after use - pPlayer->packSlots[invItem].isActive = false; - pPlayer->packSlots[invItem].curAmount = 0; + pPlayer->packSlots[invItem].isActive = false; + pPlayer->packSlots[invItem].curAmount = 0; break; } } @@ -2313,6 +2278,7 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) { if (!IsDudeSprite(pSprite) || !xspriRangeIsFine(pSprite->extra) || xsprite[pSprite->extra].health <= 0 || pXSource->data3 < 0) return; + XSPRITE* pXSprite = &xsprite[pSprite->extra]; PLAYER* pPlayer = getPlayerById(pSprite->type); int dmgType = (pXSource->data2 >= kDmgFall) ? ClipHigh(pXSource->data2, kDmgElectric) : -1; int dmg = pXSprite->health << 4; int armor[3]; @@ -2323,9 +2289,9 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) { if (godMode || pXSprite->locked) return; else if (pXSource->data3) { if (pSource->flags & kModernTypeFlag1) dmg = ClipHigh(pXSource->data3 << 1, 65535); - else if (pXSprite->sysData2 > 0) dmg = (ClipHigh(pXSprite->sysData2 << 4, 65535) * pXSource->data3) / kPercentFull; - else dmg = ((getDudeInfo(pSprite->type)->startHealth << 4) * pXSource->data3) / kPercentFull; - } + else if (pXSprite->sysData2 > 0) dmg = (ClipHigh(pXSprite->sysData2 << 4, 65535) * pXSource->data3) / kPercFull; + else dmg = ((getDudeInfo(pSprite->type)->startHealth << 4) * pXSource->data3) / kPercFull; + } if (dmgType >= kDmgFall) { if (dmg < pXSprite->health << 4) { @@ -2345,9 +2311,9 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) { actDamageSprite(pSource->index, pSprite, (DAMAGE_TYPE)dmgType, dmg); - } + } - } + } else if (!pPlayer) actKillDude(pSource->index, pSprite, (DAMAGE_TYPE)dmgType, dmg); else playerDamageSprite(pSource->index, pPlayer, (DAMAGE_TYPE)dmgType, dmg); } @@ -2498,7 +2464,11 @@ bool condRestore(XSPRITE* pXSprite) { bool condCmp(int val, int arg1, int arg2, int comOp) { if (comOp & 0x2000) return (comOp & CSTAT_SPRITE_BLOCK) ? (val > arg1) : (val >= arg1); // blue sprite else if (comOp & 0x4000) return (comOp & CSTAT_SPRITE_BLOCK) ? (val < arg1) : (val <= arg1); // green sprite - else return (comOp & CSTAT_SPRITE_BLOCK) ? (val >= arg1 && val <= arg2) : (val == arg1); + else if (comOp & CSTAT_SPRITE_BLOCK) { + if (arg1 > arg2) ThrowError("Value of argument #1 (%d) must be less than value of argument #2 (%d)", arg1, arg2); + return (val >= arg1 && val <= arg2); + } + else return (val == arg1); } // no extra comparison (val always = 0)? @@ -2506,7 +2476,11 @@ bool condCmpne(int arg1, int arg2, int comOp) { if (comOp & 0x2000) return (comOp & CSTAT_SPRITE_BLOCK) ? (0 > arg1) : (0 >= arg1); // blue sprite else if (comOp & 0x4000) return (comOp & CSTAT_SPRITE_BLOCK) ? (0 < arg1) : (0 <= arg1); // green sprite - else return (comOp & CSTAT_SPRITE_BLOCK) ? (0 >= arg1 && 0 <= arg2) : (0 == arg1); + else if (comOp & CSTAT_SPRITE_BLOCK) { + if (arg1 > arg2) ThrowError("Value of argument #1 (%d) must be less than value of argument #2 (%d)", arg1, arg2); + return (0 >= arg1 && 0 <= arg2); + } + else return (0 == arg1); } @@ -2516,20 +2490,25 @@ bool condCmpb(int val, int arg1, int arg2, int comOp) { arg1 = ClipRange(arg1, 0, 1); arg2 = ClipRange(arg2, 0, 1); if (comOp & 0x2000) return (comOp & CSTAT_SPRITE_BLOCK) ? (val > 0) : (val >= 0); // blue sprite else if (comOp & 0x4000) return (comOp & CSTAT_SPRITE_BLOCK) ? (val < arg1) : (val <= arg1); // green sprite - else return (comOp & CSTAT_SPRITE_BLOCK) ? (val >= arg1 && val <= arg2) : (val == arg1); + else if (comOp & CSTAT_SPRITE_BLOCK) { + if (arg1 > arg2) ThrowError("Value of argument #1 (%d) must be less than value of argument #2 (%d)", arg1, arg2); + return (val >= arg1 && val <= arg2); + } + else return (val == arg1); } void condError(XSPRITE* pXCond, const char* pzFormat, ...) { - + char buffer[256]; char buffer2[512]; - Bsprintf(buffer, "\nCONDITION RX: %d, TX: %d, SPRITE: #%d RETURNS:\n", pXCond->rxID, pXCond->txID, pXCond->reference); + Bsprintf(buffer, "\nCONDITION RX: %d, TX: %d, SPRITE: #%d RETURNS:\n----------\n\n", pXCond->rxID, pXCond->txID, pXCond->reference); va_list args; va_start(args, pzFormat); vsprintf(buffer2, pzFormat, args); ThrowError(Bstrcat(buffer, buffer2)); } + bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { UNREFERENCED_PARAMETER(PUSH); @@ -2542,8 +2521,8 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { condUnserialize(pXCond->targetX, &objType, &objIndex); switch (cond) { - case 0: return (objType == OBJ_SECTOR && sectRangeIsFine(objIndex)); // is a sector? - case 5: return (objType == OBJ_WALL && wallRangeIsFine(objIndex)); // is a wall? + case 0: return (objType == OBJ_SECTOR && sectRangeIsFine(objIndex)); // is a sector? + case 5: return (objType == OBJ_WALL && wallRangeIsFine(objIndex)); // is a wall? case 10: return (objType == OBJ_SPRITE && spriRangeIsFine(objIndex)); // is a sprite? case 15: // x-index is fine? switch (objType) { @@ -2657,9 +2636,8 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { case 54: return condCmpb(pXObj->triggerOff, arg1, arg2, cmpOp); case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp); case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp); - case 57: - return condCmpb(pXObj->state, arg1, arg2, cmpOp); - case 58: return condCmp((kPercentFull * pXObj->busy) / 65536, arg1, arg2, cmpOp); + case 57: return condCmpb(pXObj->state, arg1, arg2, cmpOp); + case 58: return condCmp((kPercFull * pXObj->busy) / 65536, arg1, arg2, cmpOp); case 59: return condCmpb(pXObj->dudeLockout, arg1, arg2, cmpOp); case 70: switch (arg3) { @@ -2667,13 +2645,13 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { case 1: return condCmp(seqGetID(0, wall[objIndex].extra), arg1, arg2, cmpOp); case 2: return condCmp(seqGetID(4, wall[objIndex].extra), arg1, arg2, cmpOp); } - break; + break; case 71: switch (arg3) { default: return (condCmp(seqGetStatus(0, wall[objIndex].extra), arg1, arg2, cmpOp) || condCmp(seqGetStatus(4, wall[objIndex].extra), arg1, arg2, cmpOp)); case 1: return condCmp(seqGetStatus(0, wall[objIndex].extra), arg1, arg2, cmpOp); case 2: return condCmp(seqGetStatus(4, wall[objIndex].extra), arg1, arg2, cmpOp); - } + } break; } break; @@ -2693,7 +2671,7 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp); case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp); case 57: return condCmpb(pXObj->state, arg1, arg2, cmpOp); - case 58: return condCmp((kPercentFull * pXObj->busy) / 65536, arg1, arg2, cmpOp); + case 58: return condCmp((kPercFull * pXObj->busy) / 65536, arg1, arg2, cmpOp); case 59: return condCmpb(pXObj->DudeLockout, arg1, arg2, cmpOp); case 70: return condCmp(seqGetID(3, sprite[objIndex].extra), arg1, arg2, cmpOp); case 71: return condCmp(seqGetStatus(3, sprite[objIndex].extra), arg1, arg2, cmpOp); @@ -2713,7 +2691,7 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp); case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp); case 57: return condCmpb(pXObj->state, arg1, arg2, cmpOp); - case 58: return condCmp((kPercentFull * pXObj->busy) / 65536, arg1, arg2, cmpOp); + case 58: return condCmp((kPercFull * pXObj->busy) / 65536, arg1, arg2, cmpOp); case 59: return condCmpb(pXObj->dudeLockout, arg1, arg2, cmpOp); case 70: switch (arg3) { @@ -2721,16 +2699,16 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { case 1: return condCmp(seqGetID(1, wall[objIndex].extra), arg1, arg2, cmpOp); case 2: return condCmp(seqGetID(2, wall[objIndex].extra), arg1, arg2, cmpOp); } - break; + break; case 71: switch (arg3) { default: return (condCmp(seqGetStatus(1, wall[objIndex].extra), arg1, arg2, cmpOp) || condCmp(seqGetStatus(2, wall[objIndex].extra), arg1, arg2, cmpOp)); case 1: return condCmp(seqGetStatus(1, wall[objIndex].extra), arg1, arg2, cmpOp); case 2: return condCmp(seqGetStatus(2, wall[objIndex].extra), arg1, arg2, cmpOp); - } + } break; - } - break; + } + break; } } break; @@ -2788,7 +2766,7 @@ bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH) { h = ClipLow(abs(pXSect->onCeilZ - pXSect->offCeilZ), 1); curH = abs(pSect->ceilingz - pXSect->offCeilZ); } - return condCmp((kPercentFull * curH) / h, arg1, arg2, cmpOp); + return condCmp((kPercFull * curH) / h, arg1, arg2, cmpOp); default: condError(pXCond, "Sector conditions:\nUsupported sector type %d", pSect->type); return false; @@ -2855,8 +2833,8 @@ bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH) { else if (PUSH) { condPush(pXCond, OBJ_SPRITE, i); return true; - } - } + } + } return false;*/ } } @@ -2886,7 +2864,7 @@ bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH) { condError(pXCond, "\nPlayer conditions:\nObject #%d (objType: %d) is not a player!", objIndex, objType); spritetype* pSpr = pPlayer->pSprite; //XSPRITE* pXSpr = pPlayer->pXSprite; - switch (cond) { + switch (cond) { case 0: // check if this player is connected if (!condCmp(pPlayer->nPlayer + 1, arg1, arg2, cmpOp) || !spriRangeIsFine(pPlayer->nSprite)) return false; else if (PUSH) condPush(pXCond, OBJ_SPRITE, pPlayer->nSprite); @@ -2894,20 +2872,20 @@ bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH) { case 1: return condCmp((gGameOptions.nGameType != 3) ? 0 : pPlayer->teamId + 1, arg1, arg2, cmpOp); // compare team case 2: return (arg1 > 0 && arg1 < 8 && pPlayer->hasKey[arg1 - 1]); case 3: return (arg1 > 0 && arg1 < 15 && pPlayer->hasWeapon[arg1 - 1]); - case 4: return condCmp(pPlayer->curWeapon, arg1, arg2, cmpOp); + case 4: return condCmp(pPlayer->curWeapon, arg1, arg2, cmpOp); case 5: return (arg1 > 0 && arg1 < 6 && condCmp(pPlayer->packSlots[arg1 - 1].curAmount, arg2, arg3, cmpOp)); case 6: return (arg1 > 0 && arg1 < 6 && pPlayer->packSlots[arg1 - 1].isActive); case 7: return condCmp(pPlayer->packItemId + 1, arg1, arg2, cmpOp); - case 8: // check for powerup amount in % + case 8: // check for powerup amount in % if (arg3 > 0 && arg3 < 30) var = (12 + arg3) - 1; // allowable powerups else condError(pXCond, "Unexpected powerup #%d", arg3); - return condCmp((kPercentFull * pPlayer->pwUpTime[var]) / gPowerUpInfo[var].bonusTime, arg1, arg2, cmpOp); + return condCmp((kPercFull * pPlayer->pwUpTime[var]) / gPowerUpInfo[var].bonusTime, arg1, arg2, cmpOp); case 9: if (!spriRangeIsFine(pPlayer->fraggerId)) return false; else if (PUSH) condPush(pXCond, OBJ_SPRITE, pPlayer->fraggerId); return true; - case 10: // check keys pressed - switch (arg1) { + case 10: // check keys pressed + switch (arg1) { case 1: return (pPlayer->input.forward > 0); // forward case 2: return (pPlayer->input.forward < 0); // backward case 3: return (pPlayer->input.strafe > 0); // left @@ -2916,19 +2894,19 @@ bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH) { case 6: return (pPlayer->input.buttonFlags.crouch); // crouch case 7: return (pPlayer->input.buttonFlags.shoot); // normal fire weapon case 8: return (pPlayer->input.buttonFlags.shoot2); // alt fire weapon - default: + default: condError(pXCond, "Player conditions:\nSpecify a correct key!"); - break; - } - return false; - case 11: return (pPlayer->isRunning); - case 12: return (pPlayer->fallScream); // falling in abyss? + break; + } + return false; + case 11: return (pPlayer->isRunning); + case 12: return (pPlayer->fallScream); // falling in abyss? case 13: return condCmp(pPlayer->lifeMode + 1, arg1, arg2, cmpOp); case 14: return condCmp(pPlayer->posture + 1, arg1, arg2, cmpOp); - case 46: return condCmp(pPlayer->sceneQav, arg1, arg2, cmpOp); + case 46: return condCmp(pPlayer->sceneQav, arg1, arg2, cmpOp); case 47: return (pPlayer->godMode || powerupCheck(pPlayer, kPwUpDeathMask)); - case 48: return isShrinked(pSpr); - case 49: return isGrown(pSpr); + case 48: return isShrinked(pSpr); + case 49: return isGrown(pSpr); } condError(pXCond, "Player conditions:\nUnexpected condition #%d!", cond); @@ -2939,9 +2917,9 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) { UNREFERENCED_PARAMETER(cmpOp); - //int var = -1; PLAYER* pPlayer = NULL; - int cond = pXCond->data1 - kCondDudeBase; //int arg1 = pXCond->data2; - //int arg2 = pXCond->data3; int arg3 = pXCond->data4; + int var = -1; //PLAYER* pPlayer = NULL; + int cond = pXCond->data1 - kCondDudeBase; int arg1 = pXCond->data2; + int arg2 = pXCond->data3; //int arg3 = pXCond->data4; int objType = -1; int objIndex = -1; condUnserialize(pXCond->targetX, &objType, &objIndex); @@ -2962,15 +2940,68 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) { XSPRITE* pXSpr = &xsprite[pSpr->extra]; if (pSpr->flags & kHitagRespawn || pSpr->statnum == kStatRespawn) return false; - else if (IsPlayerSprite(pSpr)) condError(pXCond, "Dude conditions:\nObject #%d (objType: %d) is not an enemy!", objIndex, objType); + else if (IsPlayerSprite(pSpr))condError(pXCond, "Dude conditions:\nObject #%d (objType: %d) is not an enemy!", objIndex, objType); switch (cond) { default: break; case 0: // dude have any targets? - if (!spriRangeIsFine(pXSpr->target)) return false; + if (!spriRangeIsFine(pXSpr->target) || !IsDudeSprite(&sprite[pXSpr->target])) return false; else if (PUSH) condPush(pXCond, OBJ_SPRITE, pXSpr->target); return true; case 1: return aiFightDudeIsAffected(pXSpr); // dude affected by ai fight? + case 2: // distance to the target in a range? + case 3: // is the target visible? + case 4: // is the target visible with periphery? + { + DUDEINFO* pInfo = getDudeInfo(pSpr->type); + int eyeAboveZ = pInfo->eyeHeight * pSpr->yrepeat << 2; + if (!spriRangeIsFine(pXSpr->target)) + condError(pXCond, "Dude #%d have no target!", objIndex); + + spritetype* pTrgt = &sprite[pXSpr->target]; + int dx = pTrgt->x - pSpr->x; int dy = pTrgt->y - pSpr->y; + + switch (cond) { + case 2: + var = condCmp(approxDist(dx, dy), arg1 * 512, arg2 * 512, cmpOp); + break; + case 3: + case 4: + var = cansee(pSpr->x, pSpr->y, pSpr->z, pSpr->sectnum, pTrgt->x, pTrgt->y, pTrgt->z - eyeAboveZ, pTrgt->sectnum); + if (cond == 4 && var > 0) { + var = ((1024 + getangle(dx, dy) - pSpr->ang) & 2047) - 1024; + var = (klabs(var) < ((arg1 <= 0) ? pInfo->periphery : ClipHigh(arg1, 2048))); + } + break; + } + + if (var <= 0) return false; + else if (PUSH) condPush(pXCond, OBJ_SPRITE, pXSpr->target); + return true; + + } + case 20: // kDudeModernCustom conditions + case 21: + switch (pSpr->type) { + case kDudeModernCustom: + case kDudeModernCustomBurning: + switch (cond) { + case 20: // life leech is thrown? + var = genDudeExtra(pSpr)->nLifeLeech; + if (!spriRangeIsFine(var)) return false; + else if (PUSH) condPush(pXCond, OBJ_SPRITE, var); + return true; + case 21: // life leech is destroyed? + var = genDudeExtra(pSpr)->nLifeLeech; + if (!spriRangeIsFine(var) && pSpr->owner == kMaxSprites - 1) return true; + else if (PUSH) condPush(pXCond, OBJ_SPRITE, var); + return false; + } + fallthrough__; + default: + condError(pXCond, "Dude #%d is not a Custom Dude!", objIndex); + return false; + } } } @@ -3084,7 +3115,7 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) { if (IsDudeSprite(pSpr)) var = (pXSpr->sysData2 > 0) ? ClipRange(pXSpr->sysData2 << 4, 1, 65535) : getDudeInfo(pSpr->type)->startHealth << 4; else if (pSpr->type == kThingBloodChunks) return condCmpne(arg1, arg2, cmpOp); else if (pSpr->type >= kThingBase && pSpr->type < kThingMax) var = thingInfo[pSpr->type - kThingBase].startHealth << 4; - return condCmp((kPercentFull * pXSpr->health) / ClipLow(var, 1), arg1, arg2, cmpOp); + return condCmp((kPercFull * pXSpr->health) / ClipLow(var, 1), arg1, arg2, cmpOp); case 55: // touching ceil of sector? if ((gSpriteHit[pSpr->extra].ceilhit & 0xc000) != 0x4000) return false; else if (PUSH) condPush(pXCond, OBJ_SECTOR, gSpriteHit[pSpr->extra].ceilhit & 0x3fff); @@ -3117,9 +3148,21 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) { return true; case 65: // compare burn time (in %) var = (IsDudeSprite(pSpr)) ? 2400 : 1200; - if (!condCmp((kPercentFull * pXSpr->burnTime) / var, arg1, arg2, cmpOp)) return false; - else if (PUSH) condPush(pXCond, OBJ_SPRITE, pXSpr->burnSource); + if (!condCmp((kPercFull * pXSpr->burnTime) / var, arg1, arg2, cmpOp)) return false; + else if (PUSH && spriRangeIsFine(pXSpr->burnSource)) condPush(pXCond, OBJ_SPRITE, pXSpr->burnSource); return true; + case 66: // any flares stuck in this sprite? + for (int nSprite = headspritestat[kStatFlare]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { + spritetype* pFlare = &sprite[nSprite]; + if (!xspriRangeIsFine(pFlare->extra) || (pFlare->flags & kHitagFree)) + continue; + + XSPRITE* pXFlare = &xsprite[pFlare->extra]; + if (!spriRangeIsFine(pXFlare->target) || pXFlare->target != objIndex) continue; + else if (PUSH) condPush(pXCond, OBJ_SPRITE, nSprite); + return true; + } + return false; case 70: return condCmp(getSpriteMassBySize(pSpr), arg1, arg2, cmpOp); // mass of the sprite in a range? } @@ -3139,16 +3182,11 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) { // this updates index of object in all conditions void condUpdateObjectIndex(int objType, int oldIndex, int newIndex) { - - int oldSerial = condSerialize(objType, oldIndex); - int newSerial = condSerialize(objType, newIndex); - - for (int nSpr = headspritestat[kStatModernCondition]; nSpr >= 0; nSpr = nextspritestat[nSpr]) { - - XSPRITE* pXCond = &xsprite[sprite[nSpr].extra]; - if (pXCond->busyTime > 0) { - - TRCONDITION* pCond = &gCondition[pXCond->sysData1]; + + // update index in tracking conditions first + for (int i = 0; i < gTrackingCondsCount; i++) { + + TRCONDITION* pCond = &gCondition[i]; for (int k = 0; k < pCond->length; k++) { if (pCond->obj[k].type != objType || pCond->obj[k].index != oldIndex) continue; pCond->obj[k].index = newIndex; @@ -3156,7 +3194,14 @@ void condUpdateObjectIndex(int objType, int oldIndex, int newIndex) { } } + + int oldSerial = condSerialize(objType, oldIndex); + int newSerial = condSerialize(objType, newIndex); + + // then update serials + for (int nSpr = headspritestat[kStatModernCondition]; nSpr >= 0; nSpr = nextspritestat[nSpr]) { + XSPRITE* pXCond = &xsprite[sprite[nSpr].extra]; if (pXCond->targetX == oldSerial) pXCond->targetX = newSerial; if (pXCond->targetY == oldSerial) pXCond->targetY = newSerial; @@ -3527,10 +3572,6 @@ void aiFightAlarmDudesInSight(spritetype* pSprite, int max) { } } -bool aiFightIsAnnoyingUnit(spritetype* pDude) { - return (IsDudeSprite(pDude) && gDudeInfoExtra[pDude->type - kDudeBase].annoying); -} - bool aiFightUnitCanFly(spritetype* pDude) { return (IsDudeSprite(pDude) && gDudeInfoExtra[pDude->type - kDudeBase].flying); } @@ -3573,26 +3614,23 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite if (event.cmd >= kCmdLock && event.cmd <= kCmdToggleLock) { switch (event.cmd) { - case kCmdLock: - pXSprite->locked = 1; - break; - case kCmdUnlock: - pXSprite->locked = 0; - break; - case kCmdToggleLock: - pXSprite->locked = pXSprite->locked ^ 1; - break; + case kCmdLock: + pXSprite->locked = 1; + break; + case kCmdUnlock: + pXSprite->locked = 0; + break; + case kCmdToggleLock: + pXSprite->locked = pXSprite->locked ^ 1; + break; } switch (pSprite->type) { - case kModernCondition: - if (!pXSprite->locked) { - if (pXSprite->busyTime > 0) - evPost(pSprite->index, OBJ_SPRITE, 0, kCallbackCondition); - } else { - pXSprite->state = 0; - evKill(pSprite->index, OBJ_SPRITE); - } + case kModernCondition: + case kModernConditionFalse: + pXSprite->restState = 0; + if (pXSprite->busyTime <= 0) break; + else if (!pXSprite->locked) pXSprite->busy = 0; break; } @@ -3627,7 +3665,8 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite switch (pSprite->type) { default: return false; // no modern type found to work with, go normal OperateSprite(); - case kModernCondition: // WIP + case kModernCondition: + case kModernConditionFalse: if (!pXSprite->isTriggered) useCondition(pSprite, pXSprite, event); return true; // add spawn random dude feature - works only if at least 2 data fields are not empty. @@ -3663,11 +3702,11 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite if (pXSprite->command == kCmdLink) return true; // work as event redirector switch (pSprite->type) { case kModernRandomTX: - useRandomTx(pXSprite, (COMMAND_ID)event.cmd, true); + useRandomTx(pXSprite, (COMMAND_ID)pXSprite->command, true); break; case kModernSequentialTX: - if (!(pSprite->flags & kModernTypeFlag1)) useSequentialTx(pXSprite, (COMMAND_ID)event.cmd, true); - else seqTxSendCmdAll(pXSprite, pSprite->index, (COMMAND_ID)event.cmd, false); + if (!(pSprite->flags & kModernTypeFlag1)) useSequentialTx(pXSprite, (COMMAND_ID)pXSprite->command, true); + else seqTxSendCmdAll(pXSprite, pSprite->index, (COMMAND_ID)pXSprite->command, false); break; } return true; @@ -3856,7 +3895,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite case kModernPlayerControl: { // WIP PLAYER* pPlayer = NULL; int cmd = (event.cmd >= kCmdNumberic) ? event.cmd : pXSprite->command; if ((pPlayer = getPlayerById(pXSprite->data1)) == NULL - || ((cmd < 3 || cmd > 4) && !modernTypeSetSpriteState(nSprite, pXSprite, pXSprite->state ^ 1))) + || ((cmd < 67 || cmd > 68) && !modernTypeSetSpriteState(nSprite, pXSprite, pXSprite->state ^ 1))) return true; TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer]; @@ -3870,11 +3909,11 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite actHealDude(pPlayer->pXSprite, ((pXSprite->data2 > 0) ? ClipHigh(pXSprite->data2, 200) : getDudeInfo(pPlayer->pSprite->type)->startHealth), 200); pPlayer->curWeapon = 1; break; - } + } - return true; + return true; - } + } switch (cmd) { case 0: // 64 (player life form) @@ -3895,11 +3934,11 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite else trPlayerCtrlSetScreenEffect(pXSprite, pPlayer); break; case 3: // 67 (start playing qav scene) - if (pCtrl->qavScene.index == nSprite && !pXSprite->Interrutable) break; - else trPlayerCtrlStartScene(pXSprite, pPlayer); + trPlayerCtrlStartScene(pXSprite, pPlayer, (pXSprite->data4 == 1) ? true : false); break; case 4: // 68 (stop playing qav scene) - trPlayerCtrlStopScene(pPlayer); + if (pXSprite->data2 > 0 && pXSprite->data2 != pPlayer->sceneQav) break; + else trPlayerCtrlStopScene(pPlayer); break; case 5: // 69 (set player look angle, TO-DO: if tx > 0, take a look on TX ID sprite) //data4 is reserved @@ -3955,7 +3994,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite else evPost(nSprite, 3, 0, kCmdOff); break; } - return true; + return true; } } @@ -3998,14 +4037,14 @@ void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernS bool ranged = txIsRanged(pXSource); if (ranged) { for (pXSource->txID = pXSource->data1; pXSource->txID <= pXSource->data4; pXSource->txID++) { - if (pXSource->txID < 0 || pXSource->txID >= kChannelUserMax) continue; + if (pXSource->txID <= 0 || pXSource->txID >= kChannelUserMax) continue; else if (!modernSend) evSend(nIndex, 3, pXSource->txID, cmd); else modernTypeSendCommand(nIndex, pXSource->txID, cmd); } } else { for (int i = 0; i <= 3; i++) { pXSource->txID = GetDataVal(&sprite[pXSource->reference], i); - if (pXSource->txID < 0 || pXSource->txID >= kChannelUserMax) continue; + if (pXSource->txID <= 0 || pXSource->txID >= kChannelUserMax) continue; else if (!modernSend) evSend(nIndex, 3, pXSource->txID, cmd); else modernTypeSendCommand(nIndex, pXSource->txID, cmd); } @@ -4099,29 +4138,29 @@ void useSequentialTx(XSPRITE* pXSource, COMMAND_ID cmd, bool setState) { int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) { int objType = event.type; int objIndex = event.index; - bool srcIsCondition = (objType == OBJ_SPRITE && sprite[objIndex].type == kModernCondition && objIndex != pSource->index); + bool srcIsCondition = false; + if (objType == OBJ_SPRITE && objIndex != pSource->index) + srcIsCondition = (sprite[objIndex].type == kModernCondition || sprite[objIndex].type == kModernConditionFalse); - // if it's a tracking condition, it must ignore all the commands sent from objects - if (pXSource->busyTime > 0 && event.funcID != kCallbackCondition) return -1; + // if it's a tracking condition, it must ignore all the commands sent from objects + if (pXSource->busyTime > 0 && event.funcID != kCallbackMax) return -1; else if (!srcIsCondition) { // save object serials in the stack and make copy of initial object - pXSource->targetX = pXSource->targetY = condSerialize(objType, objIndex); + pXSource->targetX = pXSource->targetY = condSerialize(objType, objIndex); } else { // or grab serials of objects from previous conditions pXSource->targetX = xsprite[sprite[objIndex].extra].targetX; pXSource->targetY = xsprite[sprite[objIndex].extra].targetY; - } + } + + int cond = pXSource->data1; bool ok = false; bool RVRS = (pSource->type == kModernConditionFalse); + bool RSET = (pXSource->command == kCmdNumberic + 36); bool PUSH = (pXSource->command == kCmdNumberic); + int comOp = pSource->cstat; // comparison operator - int cond = pXSource->data1; bool ok = false; bool RVRS = (pSource->yvel == kModernConditionFalse); - bool RSET = (pXSource->command == kCmdNumberic + 36); - if (pXSource->restState == 0) { - - bool PUSH = (pXSource->command == kCmdNumberic); - int comOp = pSource->cstat; // comparison operator - + if (cond == 0) ok = true; // dummy else if (cond >= kCondMixedBase && cond < kCondMixedMax) ok = condCheckMixed(pXSource, event, comOp, PUSH); else if (cond >= kCondWallBase && cond < kCondWallMax) ok = condCheckWall(pXSource, comOp, PUSH); @@ -4140,7 +4179,7 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) { evPost(pSource->index, OBJ_SPRITE, (pXSource->waitTime * 120) / 10, kCmdRepeat); return -1; - } + } } else if (event.cmd == kCmdRepeat) { @@ -4152,21 +4191,24 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) { } + // IF if (pXSource->state) { pXSource->isTriggered = (pXSource->triggerOnce) ? true : false; if (RSET) condRestore(pXSource); // reset focus to the initial object - + // send command to rx bucket if (pXSource->txID) evSend(pSource->index, OBJ_SPRITE, pXSource->txID, (COMMAND_ID)pXSource->command); if (pSource->hitag) { - + // send it for object currently in the focus - if (pSource->hitag & kModernTypeFlag1) + if (pSource->hitag & kModernTypeFlag1) { + condUnserialize(pXSource->targetX, &objType, &objIndex); nnExtTriggerObject(objType, objIndex, pXSource->command); + } // send it for initial object if ((pSource->hitag & kModernTypeFlag2) && (pXSource->targetX != pXSource->targetY || !(pSource->hitag & kModernTypeFlag1))) { @@ -4174,7 +4216,15 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) { nnExtTriggerObject(objType, objIndex, pXSource->command); } - } + } + + // ELSE + } else if (pXSource->sysData2 >= 0) { + + pSource = &sprite[pXSource->sysData2]; pXSource = &xsprite[pSource->extra]; + useCondition(pSource, pXSource, event); + + if (pXSource->isTriggered) pXSource->sysData2 = -1; } @@ -4386,7 +4436,7 @@ void useSectorLigthChanger(XSPRITE* pXSource, XSECTOR* pXSector) { } else { - pXSector->shadeAlways = true; + pXSector->shadeAlways = true; } } @@ -4422,7 +4472,9 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) { } - spritetype* pSource = &sprite[pXSource->reference]; XSPRITE* pXSprite = &xsprite[pSprite->extra]; + //spritetype* pSource = &sprite[pXSource->reference]; + + XSPRITE* pXSprite = &xsprite[pSprite->extra]; spritetype* pTarget = NULL; XSPRITE* pXTarget = NULL; int receiveHp = 33 + Random(33); DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); int matesPerEnemy = 1; @@ -4493,14 +4545,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) { } } - // instantly kill annoying spiders, rats, hands etc if dude is big enough - else if (aiFightIsAnnoyingUnit(pTarget) && !aiFightIsAnnoyingUnit(pSprite) && tilesiz[pSprite->picnum].y >= 60 && - aiFightGetTargetDist(pSprite, pDudeInfo, pTarget) < 2) { - - actKillDude(pSource->index, pTarget, DAMAGE_TYPE_0, 65535); - aiSetTarget(pXSprite, pSprite->x, pSprite->y, pSprite->z); - - } else if (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, pXTarget)) { + else if (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, pXTarget)) { spritetype* pMate = pTarget; XSPRITE* pXMate = pXTarget; // heal dude @@ -4568,11 +4613,12 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) { if (!isActive(pTarget->index)) aiActivateDude(pTarget, pXTarget); } + return; } } } - + if ((pXSprite->target < 0 || pPlayer != NULL) && ((int)gFrameClock & 32) != 0) { // try find first target that dude can see for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { @@ -4604,7 +4650,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) { // ...and change target of target to dude to force it fight if (pXSource->data3 > 0 && pXTarget->target != pSprite->index) { aiSetTarget(pXTarget, pSprite->index); - if (!isActive(pTarget->index)) + if (pPlayer == NULL && !isActive(pTarget->index)) aiActivateDude(pTarget, pXTarget); if (pXSource->data3 == 2) @@ -4688,7 +4734,7 @@ void usePictureChanger(XSPRITE* pXSource, int objType, int objIndex) { if (valueIsBetween(pXSource->data3, -1, 32767)) wall[objIndex].pal = pXSource->data3; break; - } + } } //--------------------------------------- @@ -4706,13 +4752,42 @@ QAV* playerQavSceneLoad(int qavId) { void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene) { int nIndex = pQavScene->index; if (xspriRangeIsFine(sprite[nIndex].extra)) { + XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra]; if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) { - if (pXSprite->txID > 0) evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID)pXSprite->command); - else trPlayerCtrlStopScene(pPlayer); + if (pXSprite->txID >= kChannelUser) { + + XSPRITE* pXSpr = NULL; + for (int i = bucketHead[pXSprite->txID]; i < bucketHead[pXSprite->txID + 1]; i++) { + if (rxBucket[i].type == OBJ_SPRITE) { + + spritetype* pSpr = &sprite[rxBucket[i].index]; + if (pSpr->index == nIndex || !xspriRangeIsFine(pSpr->extra)) + continue; + + pXSpr = &xsprite[pSpr->extra]; + if (pSpr->type == kModernPlayerControl && pXSpr->command == 67) { + if (pXSpr->data2 == pXSprite->data2 || pXSpr->locked) continue; + else trPlayerCtrlStartScene(pXSpr, pPlayer, true); + return; + } + + } + + nnExtTriggerObject(rxBucket[i].type, rxBucket[i].index, pXSprite->command); + + } + } //else { + + trPlayerCtrlStopScene(pPlayer); + + //} + } else { + playerQavScenePlay(pPlayer); pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0); + } } else { @@ -5088,11 +5163,14 @@ bool incDecGoalValueIsReached(XSPRITE* pXSprite) { } void seqSpawnerOffSameTx(XSPRITE* pXSource) { - for (int nSprite = headspritestat[kStatModernSeqSpawner]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { - if (nSprite != pXSource->reference) { - XSPRITE* pXSprite = &xsprite[sprite[nSprite].extra]; - if (pXSprite->txID == pXSource->txID && pXSprite->state == 1) { - evKill(nSprite, OBJ_SPRITE); + + for (int i = 0; i < kMaxXSprites; i++) { + + XSPRITE* pXSprite = &xsprite[i]; + if (pXSprite->reference != pXSource->reference && spriRangeIsFine(pXSprite->reference)) { + if (sprite[pXSprite->reference].type != kModernSeqSpawner) continue; + else if (pXSprite->txID == pXSource->txID && pXSprite->state == 1) { + evKill(pXSprite->reference, OBJ_SPRITE); pXSprite->state = 0; } } diff --git a/source/blood/src/nnexts.h b/source/blood/src/nnexts.h index 31899b17c..a1b685b61 100644 --- a/source/blood/src/nnexts.h +++ b/source/blood/src/nnexts.h @@ -195,6 +195,7 @@ struct OBJECTS_TO_TRACK { }; struct TRCONDITION { + signed int xindex: 16; unsigned int length: 8; OBJECTS_TO_TRACK obj[kMaxTracedObjects]; }; @@ -289,7 +290,7 @@ void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernS // ------------------------------------------------------------------------- // void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition); void trPlayerCtrlSetRace(XSPRITE* pXSource, PLAYER* pPlayer); -void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer); +void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, bool force); void trPlayerCtrlStopScene(PLAYER* pPlayer); void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer); void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer); diff --git a/source/blood/src/triggers.cpp b/source/blood/src/triggers.cpp index 880ede1bc..df548b118 100644 --- a/source/blood/src/triggers.cpp +++ b/source/blood/src/triggers.cpp @@ -568,21 +568,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event) evPost(nSprite, 3, 18, kCmdOff); } } - break; - - /*if (pSprite->statnum != kStatRespawn) { - switch (event.cmd) { - case kCmdOn: - actExplodeSprite(pSprite); - break; - default: - sfxPlay3DSound(pSprite, 454, 0, 0); - evPost(nSprite, 3, 18, kCmdOff); - break; - } - }*/ - break; - + break; case kThingArmedProxBomb: if (pSprite->statnum != kStatRespawn) { switch (event.cmd) { @@ -2157,10 +2143,6 @@ void trInit(void) if (pXSprite->waitTime > 0) evPost(i, 3, (pXSprite->waitTime * 120) / 10, pXSprite->restState ? kCmdOn : kCmdOff); break; - case kModernCondition: - if (pXSprite->busyTime <= 0 || pXSprite->locked) break; - evPost(i, 3, ClipLow(pXSprite->busyTime, 5), kCallbackCondition); - break; #endif case kGenTrigger: case kGenDripWater: diff --git a/source/blood/src/view.cpp b/source/blood/src/view.cpp index 6de24bad7..f255b87e4 100644 --- a/source/blood/src/view.cpp +++ b/source/blood/src/view.cpp @@ -2419,12 +2419,12 @@ void viewProcessSprites(int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t pTSprite->ang = (pTSprite->ang+((int)totalclock<<3))&2047; } - if ((pTSprite->cstat&48) != 48 && usemodels && !(spriteext[nSprite].flags&SPREXT_NOTMD)) + if ((pTSprite->cstat&48) != 48 && hw_models && !(spriteext[nSprite].flags&SPREXT_NOTMD)) { int const nRootTile = pTSprite->picnum; int nAnimTile = pTSprite->picnum + animateoffs_replace(pTSprite->picnum, 32768+pTSprite->owner); - if (usemodels && tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].modelid >= 0 && + if (tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].modelid >= 0 && tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].framenum >= 0) { pTSprite->yoffset += picanm[nAnimTile].yofs; diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 627c5a044..2c0ae6a11 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -1,5 +1,6 @@ #pragma once +#include #include "c_cvars.h" #include "zstring.h" #include "inputstate.h" diff --git a/source/libsmackerdec/src/FileStream.cpp b/source/libsmackerdec/src/FileStream.cpp index 772b8bcb2..09303b993 100644 --- a/source/libsmackerdec/src/FileStream.cpp +++ b/source/libsmackerdec/src/FileStream.cpp @@ -95,7 +95,7 @@ int32_t FileStream::Seek(int32_t offset, SeekDirection direction) nStatus = file.Seek(offset, FileReader::SeekCur); } else if (kSeekEnd == direction) { - nStatus = klseek(file, offset, SEEK_END); + nStatus = file.Seek(offset, FileReader::SeekEnd); } return nStatus; diff --git a/source/rr/src/playmve.h b/source/rr/src/playmve.h index 7834ed1d8..ce2ecbe05 100644 --- a/source/rr/src/playmve.h +++ b/source/rr/src/playmve.h @@ -47,13 +47,9 @@ #ifndef playmve_h_ #define playmve_h_ -#include "a.h" #include "baselayer.h" #include "build.h" -#include "cache1d.h" #include "compat.h" -#include "fx_man.h" -#include "keyboard.h" #include "pragmas.h" bool playmve(const char* filename);