- manual update of some missed content.

This commit is contained in:
Christoph Oelckers 2020-05-22 18:28:03 +02:00
parent f60fa44efb
commit 6a0785bbd4
10 changed files with 429 additions and 366 deletions

View file

@ -2262,9 +2262,9 @@ const THINGINFO thingInfo[] = {
800, 800,
(char)-128, (char)-128,
0, 0,
48, 44,
48, 44,
64, 64, 112, 64, 0, 96, 96, 0, 1024, 512, 1024, 0, 64, 512,
}, },
}; };
@ -2359,7 +2359,7 @@ const EXPLOSION explodeInfo[] = {
}, },
}; };
int gDudeDrag = 0x2a00;
short gAffectedSectors[kMaxSectors]; short gAffectedSectors[kMaxSectors];
short gAffectedXWalls[kMaxXWalls]; short gAffectedXWalls[kMaxXWalls];
@ -5260,7 +5260,8 @@ void actExplodeSprite(spritetype *pSprite)
return; return;
sfxKill3DSound(pSprite, -1, -1); sfxKill3DSound(pSprite, -1, -1);
evKill(pSprite->index, 3); evKill(pSprite->index, 3);
int nType; int nType = kExplosionStandard;
switch (pSprite->type) switch (pSprite->type)
{ {
case kMissileFireballNapam: case kMissileFireballNapam:

View file

@ -365,14 +365,14 @@ static void ThrowThing(int nXIndex, bool impact) {
case kModernThingEnemyLifeLeech: case kModernThingEnemyLifeLeech:
XSPRITE* pXThing = &xsprite[pThing->extra]; XSPRITE* pXThing = &xsprite[pThing->extra];
if (pLeech != NULL) pXThing->health = pXLeech->health; 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); sfxPlay3DSound(pSprite, 490, -1, 0);
if (gGameOptions.nDifficulty <= 2) pXThing->data3 = 32700; pXThing->data3 = 512 / (gGameOptions.nDifficulty + 1);
else pXThing->data3 = Random(10);
pThing->cstat &= ~CSTAT_SPRITE_BLOCK; pThing->cstat &= ~CSTAT_SPRITE_BLOCK;
pThing->pal = 6; pThing->pal = 6;
pThing->clipdist = 0;
pXThing->target = pTarget->index; pXThing->target = pTarget->index;
pXThing->Proximity = true; pXThing->Proximity = true;
pXThing->stateTimer = 1; pXThing->stateTimer = 1;
@ -438,6 +438,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
if (pXTarget == NULL) { // target lost if (pXTarget == NULL) { // target lost
if(spriteIsUnderwater(pSprite,false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW); if(spriteIsUnderwater(pSprite,false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW);
else aiGenDudeNewState(pSprite, &genDudeSearchShortL); else aiGenDudeNewState(pSprite, &genDudeSearchShortL);
pXSprite->target = -1;
return; return;
} else if (pXTarget->health <= 0) { // target is dead } else if (pXTarget->health <= 0) { // target is dead
@ -449,6 +450,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
} }
else if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeGotoW); else if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeGotoW);
else aiGenDudeNewState(pSprite, &genDudeGotoL); else aiGenDudeNewState(pSprite, &genDudeGotoL);
pXSprite->target = -1;
return; return;
} }
@ -477,6 +479,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) { if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) {
if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW); if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchShortW);
else aiGenDudeNewState(pSprite, &genDudeSearchShortL); else aiGenDudeNewState(pSprite, &genDudeSearchShortL);
pXSprite->target = -1;
return; return;
} }
} }
@ -1388,57 +1391,57 @@ void scaleDamage(XSPRITE* pXSprite) {
switch (surfType) { switch (surfType) {
case 1: // stone case 1: // stone
curScale[kDmgFall] = 0; curScale[kDmgFall] = 0;
curScale[kDmgBullet] -= 128; curScale[kDmgBullet] -= 200;
curScale[kDmgBurn] -= 50; curScale[kDmgBurn] -= 100;
curScale[kDmgExplode] -= 40; curScale[kDmgExplode] -= 80;
curScale[kDmgChoke] += 30; curScale[kDmgChoke] += 30;
curScale[kDmgElectric] += 20; curScale[kDmgElectric] += 20;
break; break;
case 2: // metal case 2: // metal
curScale[kDmgFall] = 16; curScale[kDmgFall] = 16;
curScale[kDmgBullet] -= 64; curScale[kDmgBullet] -= 128;
curScale[kDmgBurn] -= 45; curScale[kDmgBurn] -= 90;
curScale[kDmgExplode] -= 35; curScale[kDmgExplode] -= 55;
curScale[kDmgChoke] += 20; curScale[kDmgChoke] += 20;
curScale[kDmgElectric] += 30; curScale[kDmgElectric] += 30;
break; break;
case 3: // wood case 3: // wood
curScale[kDmgBullet] -= 5; curScale[kDmgBullet] -= 10;
curScale[kDmgBurn] += 50; curScale[kDmgBurn] += 50;
curScale[kDmgExplode] += 40; curScale[kDmgExplode] += 40;
curScale[kDmgChoke] += 10; curScale[kDmgChoke] += 10;
curScale[kDmgElectric] -= 30; curScale[kDmgElectric] -= 60;
break; break;
case 5: // water case 5: // water
case 6: // dirt case 6: // dirt
case 7: // clay case 7: // clay
case 13: // goo case 13: // goo
curScale[kDmgFall] = 8; curScale[kDmgFall] = 8;
curScale[kDmgBullet] -= 10; curScale[kDmgBullet] -= 20;
curScale[kDmgBurn] -= 128; curScale[kDmgBurn] -= 200;
curScale[kDmgExplode] -= 30; curScale[kDmgExplode] -= 60;
curScale[kDmgChoke] = 0; curScale[kDmgChoke] = 0;
curScale[kDmgElectric] += 40; curScale[kDmgElectric] += 40;
break; break;
case 8: // snow case 8: // snow
case 9: // ice case 9: // ice
curScale[kDmgFall] = 8; curScale[kDmgFall] = 8;
curScale[kDmgBullet] -= 10; curScale[kDmgBullet] -= 20;
curScale[kDmgBurn] -= 60; curScale[kDmgBurn] -= 100;
curScale[kDmgExplode] -= 40; curScale[kDmgExplode] -= 50;
curScale[kDmgChoke] = 0; curScale[kDmgChoke] = 0;
curScale[kDmgElectric] += 40; curScale[kDmgElectric] += 40;
break; break;
case 10: // leaves case 10: // leaves
case 12: // plant case 12: // plant
curScale[kDmgFall] = 0; curScale[kDmgFall] = 0;
curScale[kDmgBullet] -= 5; curScale[kDmgBullet] -= 10;
curScale[kDmgBurn] += 70; curScale[kDmgBurn] += 70;
curScale[kDmgExplode] += 50; curScale[kDmgExplode] += 50;
break; break;
case 11: // cloth case 11: // cloth
curScale[kDmgFall] = 8; curScale[kDmgFall] = 8;
curScale[kDmgBullet] -= 5; curScale[kDmgBullet] -= 10;
curScale[kDmgBurn] += 30; curScale[kDmgBurn] += 30;
curScale[kDmgExplode] += 20; curScale[kDmgExplode] += 20;
break; break;
@ -2116,7 +2119,7 @@ bool genDudePrepare(spritetype* pSprite, int propId) {
pExtra->nLifeLeech = -1; pExtra->nLifeLeech = -1;
if (pSprite->owner != kMaxSprites - 1) { if (pSprite->owner != kMaxSprites - 1) {
for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { 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; pExtra->nLifeLeech = nSprite;
break; break;
} }

View file

@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
bool gModernMap = false;
unsigned short gStatCount[kMaxStatus + 1]; unsigned short gStatCount[kMaxStatus + 1];
XSPRITE xsprite[kMaxXSprites]; XSPRITE xsprite[kMaxXSprites];

View file

@ -49,7 +49,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
bool gModernMap = false;
bool gAllowTrueRandom = false; bool gAllowTrueRandom = false;
bool gEventRedirectsUsed = false; bool gEventRedirectsUsed = false;
SPRITEMASS gSpriteMass[]; // cache for getSpriteMassBySize(); SPRITEMASS gSpriteMass[]; // cache for getSpriteMassBySize();
@ -113,20 +112,20 @@ THINGINFO_EXTRA gThingInfoExtra[] = {
}; };
DUDEINFO_EXTRA gDudeInfoExtra[] = { DUDEINFO_EXTRA gDudeInfoExtra[] = {
false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, true,
false, false, false, false, true, false, true, true, false, true, false, false, false, false, false, true, true, true, true, false,
true, false, false, false, false, false, false, true, true, false, true, true, true, false, false, false, false, true, false, true,
false, true, true, false, true, true, false, true, true, false, true, false, false, true, false, true, false, true, false, true,
false, true, true, true, true, true, false, true, true, false, false, true, false, true, true, true, false, true, false, false,
false, true, true, false, false, true, false, true, true, false, 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, 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, true, false, true,
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, true, false, true, false, false, false, false,
false, false, false, false, false, false, false, false, false, false,
}; };
// for actor.cpp // for actor.cpp
@ -294,78 +293,11 @@ void nnExtInitModernStuff(bool bSaveLoad) {
break; break;
case kModernCondition: case kModernCondition:
case kModernConditionFalse: case kModernConditionFalse:
if (!bSaveLoad) { if (bSaveLoad) break;
else if (!pXSprite->rxID) condError(pXSprite,"\nThe condition must have RX ID!\nSPRITE #%d", pSprite->index);
pSprite->yvel = pSprite->type; // store it here, because inittype gets cleared later. else if (!pXSprite->txID && !pSprite->hitag) {
pSprite->type = kModernCondition; consoleSysMsg("The condition must have TX ID or hitag to be set: RX ID %d, SPRITE #%d", pXSprite->rxID, pSprite->index);
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;
} }
}
// 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; break;
} }
@ -395,6 +327,10 @@ void nnExtInitModernStuff(bool bSaveLoad) {
} else { } 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 // copy custom start health to avoid overwrite by kThingBloodChunks
if (IsDudeSprite(pSprite)) if (IsDudeSprite(pSprite))
pXSprite->sysData2 = pXSprite->data4; pXSprite->sysData2 = pXSprite->data4;
@ -404,20 +340,17 @@ void nnExtInitModernStuff(bool bSaveLoad) {
bool sysStat = true; bool sysStat = true;
switch (pSprite->statnum) { switch (pSprite->statnum) {
case kStatModernDudeTargetChanger: case kStatModernDudeTargetChanger:
sysStat = (pSprite->type == kModernDudeTargetChanger); sysStat = (pSprite->type != kModernDudeTargetChanger);
break; break;
case kStatModernCondition: case kStatModernCondition:
sysStat = (pSprite->type == kModernCondition || pSprite->type == kModernConditionFalse); sysStat = (pSprite->type != kModernCondition && pSprite->type != kModernConditionFalse);
break; break;
case kStatModernEventRedirector: case kStatModernEventRedirector:
sysStat = (pSprite->type == kModernRandomTX || pSprite->type == kModernSequentialTX); sysStat = (pSprite->type != kModernRandomTX && pSprite->type != kModernSequentialTX);
break;
case kStatModernSeqSpawner:
sysStat = (pSprite->type == kModernSeqSpawner);
break; break;
case kStatModernPlayerLinker: case kStatModernPlayerLinker:
case kStatModernQavScene: case kStatModernQavScene:
sysStat = (pSprite->type == kModernPlayerControl); sysStat = (pSprite->type != kModernPlayerControl);
break; break;
} }
@ -455,9 +388,6 @@ void nnExtInitModernStuff(bool bSaveLoad) {
break; break;
} }
break; break;
case kModernSeqSpawner:
changespritestat(pSprite->index, kStatModernSeqSpawner);
break;
case kModernThingTNTProx: case kModernThingTNTProx:
pXSprite->Proximity = true; pXSprite->Proximity = true;
break; break;
@ -472,6 +402,10 @@ void nnExtInitModernStuff(bool bSaveLoad) {
found++; found++;
} }
break; break;
case kDudePodMother:
case kDudeTentacleMother:
pXSprite->state = 1;
break;
case kModernPlayerControl: case kModernPlayerControl:
switch (pXSprite->command) { switch (pXSprite->command) {
case kCmdLink: case kCmdLink:
@ -504,18 +438,35 @@ void nnExtInitModernStuff(bool bSaveLoad) {
} }
break; break;
case kModernCondition: case kModernCondition:
if (pXSprite->waitTime > 0 && pXSprite->busyTime > 0) { case kModernConditionFalse:
if (pXSprite->busyTime > 0) {
if (pXSprite->waitTime > 0) {
pXSprite->busyTime += ClipHigh(((pXSprite->waitTime * 120) / 10), 4095); 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); 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->Decoupled = false; // must go through operateSprite always
pXSprite->Sight = pXSprite->Impact = pXSprite->Touch = pXSprite->triggerOff = false; pXSprite->Sight = pXSprite->Impact = pXSprite->Touch = pXSprite->triggerOff = false;
pXSprite->Proximity = pXSprite->Push = pXSprite->Vector = pXSprite->triggerOn = false; pXSprite->Proximity = pXSprite->Push = pXSprite->Vector = pXSprite->triggerOn = false;
pXSprite->state = pXSprite->restState = 0; 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); 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; pSprite->cstat |= CSTAT_SPRITE_INVISIBLE;
break; break;
} }
@ -705,14 +656,14 @@ int nnExtRandom(int a, int b) {
} }
int GetDataVal(spritetype* pSprite, int data) { int GetDataVal(spritetype* pSprite, int data) {
if (pSprite->extra >= 0) { dassert(xspriRangeIsFine(pSprite->extra));
switch (data) { switch (data) {
case 0: return xsprite[pSprite->extra].data1; case 0: return xsprite[pSprite->extra].data1;
case 1: return xsprite[pSprite->extra].data2; case 1: return xsprite[pSprite->extra].data2;
case 2: return xsprite[pSprite->extra].data3; case 2: return xsprite[pSprite->extra].data3;
case 3: return xsprite[pSprite->extra].data4; case 3: return xsprite[pSprite->extra].data4;
} }
}
return -1; return -1;
} }
@ -807,6 +758,27 @@ spritetype* randomSpawnDude(spritetype* pSource) {
void nnExtProcessSuperSprites() { 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 // process additional proximity sprites
if (gProxySpritesCount > 0) { if (gProxySpritesCount > 0) {
for (int i = 0; i < gProxySpritesCount; i++) { for (int i = 0; i < gProxySpritesCount; i++) {
@ -1326,25 +1298,13 @@ void windGenStopWindOnSectors(XSPRITE* pXSource) {
} }
} }
/*XSPRITE* trPlayerCtrlFindNextScene(XSPRITE* pXScene) {
int curIndex = pXScene->reference; bool oldFound = false; void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, bool force) {
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]; int nSource = pXSource->reference; TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer];
if (oldFound && pXSpr->command == 67 && pXSpr->data1 == pXScene->data1 && !pXSpr->locked)
return pXSpr;
}
}*/
void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer) { if (pCtrl->qavScene.index >= 0 && !force) return;
int nSource = sprite[pXSource->reference].index; TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer];
QAV* pQav = playerQavSceneLoad(pXSource->data2); QAV* pQav = playerQavSceneLoad(pXSource->data2);
if (pQav != NULL) { if (pQav != NULL) {
@ -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 // let's check if there is tracking condition expecting objects with this TX id
if (checkCondition && pXSource->txID >= kChannelUser) { if (checkCondition && pXSource->txID >= kChannelUser) {
for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++) { for (int i = 0; i < gTrackingCondsCount; i++) {
if (sprite[rxBucket[i].index].type != kModernCondition) continue;
XSPRITE* pXCond = &xsprite[sprite[rxBucket[i].index].extra]; TRCONDITION* pCond = &gCondition[i];
if (pXCond->busyTime <= 0) continue; if (xsprite[pCond->xindex].rxID != pXSource->txID)
continue;
TRCONDITION* pCond = &gCondition[pXCond->sysData1];
// search for player control sprite and replace it with actual player sprite // search for player control sprite and replace it with actual player sprite
for (int k = 0; k < pCond->length; k++) { for (int k = 0; k < pCond->length; k++) {
if (pCond->obj[k].type != OBJ_SPRITE || pCond->obj[k].index != pXSource->reference) continue; 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; pCond->obj[k].cmd = pPlayer->pXSprite->command;
break; break;
} }
} }
} }
} }
@ -1473,9 +1433,9 @@ void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer) {
for (int i = 0; i < kModeMax; i++) { for (int i = 0; i < kModeMax; i++) {
for (int a = 0; a < kPostureMax; a++) { for (int a = 0; a < kPostureMax; a++) {
POSTURE* curPosture = &pPlayer->pPosture[i][a]; POSTURE* defPosture = &gPostureDefaults[i][a]; POSTURE* curPosture = &pPlayer->pPosture[i][a]; POSTURE* defPosture = &gPostureDefaults[i][a];
curPosture->frontAccel = (defPosture->frontAccel * speed) / kPercentFull; curPosture->frontAccel = (defPosture->frontAccel * speed) / kPercFull;
curPosture->sideAccel = (defPosture->sideAccel * speed) / kPercentFull; curPosture->sideAccel = (defPosture->sideAccel * speed) / kPercFull;
curPosture->backAccel = (defPosture->backAccel * speed) / kPercentFull; curPosture->backAccel = (defPosture->backAccel * speed) / kPercFull;
} }
} }
} }
@ -1485,8 +1445,8 @@ void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer) {
int jump = ClipRange(pXSource->data3, 0, 500); int jump = ClipRange(pXSource->data3, 0, 500);
for (int i = 0; i < kModeMax; i++) { for (int i = 0; i < kModeMax; i++) {
POSTURE* curPosture = &pPlayer->pPosture[i][kPostureStand]; POSTURE* defPosture = &gPostureDefaults[i][kPostureStand]; POSTURE* curPosture = &pPlayer->pPosture[i][kPostureStand]; POSTURE* defPosture = &gPostureDefaults[i][kPostureStand];
curPosture->normalJumpZ = (defPosture->normalJumpZ * jump) / kPercentFull; curPosture->normalJumpZ = (defPosture->normalJumpZ * jump) / kPercFull;
curPosture->pwupJumpZ = (defPosture->pwupJumpZ * jump) / kPercentFull; curPosture->pwupJumpZ = (defPosture->pwupJumpZ * jump) / kPercFull;
} }
} }
@ -1528,13 +1488,13 @@ void trPlayerCtrlSetScreenEffect(XSPRITE* pXSource, PLAYER* pPlayer) {
void trPlayerCtrlSetLookAngle(XSPRITE* pXSource, PLAYER* pPlayer) { void trPlayerCtrlSetLookAngle(XSPRITE* pXSource, PLAYER* pPlayer) {
int upAngle = 289; int downAngle = -347; CONSTEXPR int upAngle = 289; CONSTEXPR int downAngle = -347;
double lookStepUp = 4.0 * upAngle / 60.0; CONSTEXPR double lookStepUp = 4.0 * upAngle / 60.0;
double lookStepDown = -4.0 * downAngle / 60.0; CONSTEXPR double lookStepDown = -4.0 * downAngle / 60.0;
int look = pXSource->data2 << 5; int look = pXSource->data2 << 5;
if (look > 0) pPlayer->q16look = fix16_min(mulscale8(fix16_from_dbl(lookStepUp), look), fix16_from_int(upAngle)); if (look > 0) pPlayer->q16look = fix16_min(mulscale8(F16(lookStepUp), look), F16(upAngle));
else if (look < 0) pPlayer->q16look = -fix16_max(mulscale8(fix16_from_dbl(lookStepDown), abs(look)), fix16_from_int(downAngle)); else if (look < 0) pPlayer->q16look = -fix16_max(mulscale8(F16(lookStepDown), abs(look)), F16(downAngle));
else pPlayer->q16look = 0; else pPlayer->q16look = 0;
} }
@ -1575,6 +1535,11 @@ void trPlayerCtrlEraseStuff(XSPRITE* pXSource, PLAYER* pPlayer) {
case 4: // erase all keys case 4: // erase all keys
for (int i = 0; i < 8; i++) pPlayer->hasKey[i] = false; for (int i = 0; i < 8; i++) pPlayer->hasKey[i] = false;
if (pXSource->data2) break; 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,7 +1569,7 @@ void trPlayerCtrlGiveStuff(XSPRITE* pXSource, PLAYER* pPlayer, TRPLAYERCTRL* pCt
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
if (gWeaponItemData[i].type != weapon) continue; 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) { switch (pXSource->data2) {
case 1: case 1:
pPlayer->hasWeapon[weapon] = true; pPlayer->hasWeapon[weapon] = true;
@ -2313,6 +2278,7 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) {
if (!IsDudeSprite(pSprite) || !xspriRangeIsFine(pSprite->extra) || xsprite[pSprite->extra].health <= 0 || pXSource->data3 < 0) if (!IsDudeSprite(pSprite) || !xspriRangeIsFine(pSprite->extra) || xsprite[pSprite->extra].health <= 0 || pXSource->data3 < 0)
return; return;
XSPRITE* pXSprite = &xsprite[pSprite->extra]; PLAYER* pPlayer = getPlayerById(pSprite->type); XSPRITE* pXSprite = &xsprite[pSprite->extra]; PLAYER* pPlayer = getPlayerById(pSprite->type);
int dmgType = (pXSource->data2 >= kDmgFall) ? ClipHigh(pXSource->data2, kDmgElectric) : -1; int dmgType = (pXSource->data2 >= kDmgFall) ? ClipHigh(pXSource->data2, kDmgElectric) : -1;
int dmg = pXSprite->health << 4; int armor[3]; int dmg = pXSprite->health << 4; int armor[3];
@ -2323,8 +2289,8 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) {
if (godMode || pXSprite->locked) return; if (godMode || pXSprite->locked) return;
else if (pXSource->data3) { else if (pXSource->data3) {
if (pSource->flags & kModernTypeFlag1) dmg = ClipHigh(pXSource->data3 << 1, 65535); 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 if (pXSprite->sysData2 > 0) dmg = (ClipHigh(pXSprite->sysData2 << 4, 65535) * pXSource->data3) / kPercFull;
else dmg = ((getDudeInfo(pSprite->type)->startHealth << 4) * pXSource->data3) / kPercentFull; else dmg = ((getDudeInfo(pSprite->type)->startHealth << 4) * pXSource->data3) / kPercFull;
} }
if (dmgType >= kDmgFall) { if (dmgType >= kDmgFall) {
@ -2498,7 +2464,11 @@ bool condRestore(XSPRITE* pXSprite) {
bool condCmp(int val, int arg1, int arg2, int comOp) { bool condCmp(int val, int arg1, int arg2, int comOp) {
if (comOp & 0x2000) return (comOp & CSTAT_SPRITE_BLOCK) ? (val > arg1) : (val >= arg1); // blue sprite 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 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)? // 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 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 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); arg1 = ClipRange(arg1, 0, 1); arg2 = ClipRange(arg2, 0, 1);
if (comOp & 0x2000) return (comOp & CSTAT_SPRITE_BLOCK) ? (val > 0) : (val >= 0); // blue sprite 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 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, ...) { void condError(XSPRITE* pXCond, const char* pzFormat, ...) {
char buffer[256]; char buffer2[512]; 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_list args;
va_start(args, pzFormat); va_start(args, pzFormat);
vsprintf(buffer2, pzFormat, args); vsprintf(buffer2, pzFormat, args);
ThrowError(Bstrcat(buffer, buffer2)); ThrowError(Bstrcat(buffer, buffer2));
} }
bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) {
UNREFERENCED_PARAMETER(PUSH); UNREFERENCED_PARAMETER(PUSH);
@ -2657,9 +2636,8 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) {
case 54: return condCmpb(pXObj->triggerOff, arg1, arg2, cmpOp); case 54: return condCmpb(pXObj->triggerOff, arg1, arg2, cmpOp);
case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp); case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp);
case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp); case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp);
case 57: case 57: return condCmpb(pXObj->state, arg1, arg2, cmpOp);
return condCmpb(pXObj->state, arg1, arg2, cmpOp); case 58: return condCmp((kPercFull * pXObj->busy) / 65536, arg1, arg2, cmpOp);
case 58: return condCmp((kPercentFull * pXObj->busy) / 65536, arg1, arg2, cmpOp);
case 59: return condCmpb(pXObj->dudeLockout, arg1, arg2, cmpOp); case 59: return condCmpb(pXObj->dudeLockout, arg1, arg2, cmpOp);
case 70: case 70:
switch (arg3) { switch (arg3) {
@ -2693,7 +2671,7 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) {
case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp); case 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp);
case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp); case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp);
case 57: return condCmpb(pXObj->state, 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 59: return condCmpb(pXObj->DudeLockout, arg1, arg2, cmpOp);
case 70: return condCmp(seqGetID(3, sprite[objIndex].extra), 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); 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 55: return condCmpb(pXObj->triggerOnce, arg1, arg2, cmpOp);
case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp); case 56: return condCmpb(pXObj->isTriggered, arg1, arg2, cmpOp);
case 57: return condCmpb(pXObj->state, 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 59: return condCmpb(pXObj->dudeLockout, arg1, arg2, cmpOp);
case 70: case 70:
switch (arg3) { switch (arg3) {
@ -2788,7 +2766,7 @@ bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH) {
h = ClipLow(abs(pXSect->onCeilZ - pXSect->offCeilZ), 1); h = ClipLow(abs(pXSect->onCeilZ - pXSect->offCeilZ), 1);
curH = abs(pSect->ceilingz - pXSect->offCeilZ); curH = abs(pSect->ceilingz - pXSect->offCeilZ);
} }
return condCmp((kPercentFull * curH) / h, arg1, arg2, cmpOp); return condCmp((kPercFull * curH) / h, arg1, arg2, cmpOp);
default: default:
condError(pXCond, "Sector conditions:\nUsupported sector type %d", pSect->type); condError(pXCond, "Sector conditions:\nUsupported sector type %d", pSect->type);
return false; return false;
@ -2901,7 +2879,7 @@ bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH) {
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 if (arg3 > 0 && arg3 < 30) var = (12 + arg3) - 1; // allowable powerups
else condError(pXCond, "Unexpected powerup #%d", arg3); 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: case 9:
if (!spriRangeIsFine(pPlayer->fraggerId)) return false; if (!spriRangeIsFine(pPlayer->fraggerId)) return false;
else if (PUSH) condPush(pXCond, OBJ_SPRITE, pPlayer->fraggerId); else if (PUSH) condPush(pXCond, OBJ_SPRITE, pPlayer->fraggerId);
@ -2939,9 +2917,9 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) {
UNREFERENCED_PARAMETER(cmpOp); UNREFERENCED_PARAMETER(cmpOp);
//int var = -1; PLAYER* pPlayer = NULL; int var = -1; //PLAYER* pPlayer = NULL;
int cond = pXCond->data1 - kCondDudeBase; //int arg1 = pXCond->data2; int cond = pXCond->data1 - kCondDudeBase; int arg1 = pXCond->data2;
//int arg2 = pXCond->data3; int arg3 = pXCond->data4; int arg2 = pXCond->data3; //int arg3 = pXCond->data4;
int objType = -1; int objIndex = -1; int objType = -1; int objIndex = -1;
condUnserialize(pXCond->targetX, &objType, &objIndex); condUnserialize(pXCond->targetX, &objType, &objIndex);
@ -2967,10 +2945,63 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) {
switch (cond) { switch (cond) {
default: break; default: break;
case 0: // dude have any targets? 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); else if (PUSH) condPush(pXCond, OBJ_SPRITE, pXSpr->target);
return true; return true;
case 1: return aiFightDudeIsAffected(pXSpr); // dude affected by ai fight? 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; 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 == kThingBloodChunks) return condCmpne(arg1, arg2, cmpOp);
else if (pSpr->type >= kThingBase && pSpr->type < kThingMax) var = thingInfo[pSpr->type - kThingBase].startHealth << 4; 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? case 55: // touching ceil of sector?
if ((gSpriteHit[pSpr->extra].ceilhit & 0xc000) != 0x4000) return false; if ((gSpriteHit[pSpr->extra].ceilhit & 0xc000) != 0x4000) return false;
else if (PUSH) condPush(pXCond, OBJ_SECTOR, gSpriteHit[pSpr->extra].ceilhit & 0x3fff); 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; return true;
case 65: // compare burn time (in %) case 65: // compare burn time (in %)
var = (IsDudeSprite(pSpr)) ? 2400 : 1200; var = (IsDudeSprite(pSpr)) ? 2400 : 1200;
if (!condCmp((kPercentFull * pXSpr->burnTime) / var, arg1, arg2, cmpOp)) return false; if (!condCmp((kPercFull * pXSpr->burnTime) / var, arg1, arg2, cmpOp)) return false;
else if (PUSH) condPush(pXCond, OBJ_SPRITE, pXSpr->burnSource); else if (PUSH && spriRangeIsFine(pXSpr->burnSource)) condPush(pXCond, OBJ_SPRITE, pXSpr->burnSource);
return true; 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: case 70:
return condCmp(getSpriteMassBySize(pSpr), arg1, arg2, cmpOp); // mass of the sprite in a range? return condCmp(getSpriteMassBySize(pSpr), arg1, arg2, cmpOp); // mass of the sprite in a range?
} }
@ -3140,15 +3183,10 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) {
// this updates index of object in all conditions // this updates index of object in all conditions
void condUpdateObjectIndex(int objType, int oldIndex, int newIndex) { void condUpdateObjectIndex(int objType, int oldIndex, int newIndex) {
int oldSerial = condSerialize(objType, oldIndex); // update index in tracking conditions first
int newSerial = condSerialize(objType, newIndex); for (int i = 0; i < gTrackingCondsCount; i++) {
for (int nSpr = headspritestat[kStatModernCondition]; nSpr >= 0; nSpr = nextspritestat[nSpr]) { TRCONDITION* pCond = &gCondition[i];
XSPRITE* pXCond = &xsprite[sprite[nSpr].extra];
if (pXCond->busyTime > 0) {
TRCONDITION* pCond = &gCondition[pXCond->sysData1];
for (int k = 0; k < pCond->length; k++) { for (int k = 0; k < pCond->length; k++) {
if (pCond->obj[k].type != objType || pCond->obj[k].index != oldIndex) continue; if (pCond->obj[k].type != objType || pCond->obj[k].index != oldIndex) continue;
pCond->obj[k].index = newIndex; pCond->obj[k].index = newIndex;
@ -3157,6 +3195,13 @@ 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->targetX == oldSerial) pXCond->targetX = newSerial;
if (pXCond->targetY == oldSerial) pXCond->targetY = 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) { bool aiFightUnitCanFly(spritetype* pDude) {
return (IsDudeSprite(pDude) && gDudeInfoExtra[pDude->type - kDudeBase].flying); return (IsDudeSprite(pDude) && gDudeInfoExtra[pDude->type - kDudeBase].flying);
} }
@ -3586,13 +3627,10 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
switch (pSprite->type) { switch (pSprite->type) {
case kModernCondition: case kModernCondition:
if (!pXSprite->locked) { case kModernConditionFalse:
if (pXSprite->busyTime > 0) pXSprite->restState = 0;
evPost(pSprite->index, OBJ_SPRITE, 0, kCallbackCondition); if (pXSprite->busyTime <= 0) break;
} else { else if (!pXSprite->locked) pXSprite->busy = 0;
pXSprite->state = 0;
evKill(pSprite->index, OBJ_SPRITE);
}
break; break;
} }
@ -3627,7 +3665,8 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
switch (pSprite->type) { switch (pSprite->type) {
default: default:
return false; // no modern type found to work with, go normal OperateSprite(); 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); if (!pXSprite->isTriggered) useCondition(pSprite, pXSprite, event);
return true; return true;
// add spawn random dude feature - works only if at least 2 data fields are not empty. // 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 if (pXSprite->command == kCmdLink) return true; // work as event redirector
switch (pSprite->type) { switch (pSprite->type) {
case kModernRandomTX: case kModernRandomTX:
useRandomTx(pXSprite, (COMMAND_ID)event.cmd, true); useRandomTx(pXSprite, (COMMAND_ID)pXSprite->command, true);
break; break;
case kModernSequentialTX: case kModernSequentialTX:
if (!(pSprite->flags & kModernTypeFlag1)) useSequentialTx(pXSprite, (COMMAND_ID)event.cmd, true); if (!(pSprite->flags & kModernTypeFlag1)) useSequentialTx(pXSprite, (COMMAND_ID)pXSprite->command, true);
else seqTxSendCmdAll(pXSprite, pSprite->index, (COMMAND_ID)event.cmd, false); else seqTxSendCmdAll(pXSprite, pSprite->index, (COMMAND_ID)pXSprite->command, false);
break; break;
} }
return true; return true;
@ -3856,7 +3895,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
case kModernPlayerControl: { // WIP case kModernPlayerControl: { // WIP
PLAYER* pPlayer = NULL; int cmd = (event.cmd >= kCmdNumberic) ? event.cmd : pXSprite->command; PLAYER* pPlayer = NULL; int cmd = (event.cmd >= kCmdNumberic) ? event.cmd : pXSprite->command;
if ((pPlayer = getPlayerById(pXSprite->data1)) == NULL 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; return true;
TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer]; TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer];
@ -3895,11 +3934,11 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
else trPlayerCtrlSetScreenEffect(pXSprite, pPlayer); else trPlayerCtrlSetScreenEffect(pXSprite, pPlayer);
break; break;
case 3: // 67 (start playing qav scene) case 3: // 67 (start playing qav scene)
if (pCtrl->qavScene.index == nSprite && !pXSprite->Interrutable) break; trPlayerCtrlStartScene(pXSprite, pPlayer, (pXSprite->data4 == 1) ? true : false);
else trPlayerCtrlStartScene(pXSprite, pPlayer);
break; break;
case 4: // 68 (stop playing qav scene) case 4: // 68 (stop playing qav scene)
trPlayerCtrlStopScene(pPlayer); if (pXSprite->data2 > 0 && pXSprite->data2 != pPlayer->sceneQav) break;
else trPlayerCtrlStopScene(pPlayer);
break; break;
case 5: // 69 (set player look angle, TO-DO: if tx > 0, take a look on TX ID sprite) case 5: // 69 (set player look angle, TO-DO: if tx > 0, take a look on TX ID sprite)
//data4 is reserved //data4 is reserved
@ -3998,14 +4037,14 @@ void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernS
bool ranged = txIsRanged(pXSource); bool ranged = txIsRanged(pXSource);
if (ranged) { if (ranged) {
for (pXSource->txID = pXSource->data1; pXSource->txID <= pXSource->data4; pXSource->txID++) { 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 if (!modernSend) evSend(nIndex, 3, pXSource->txID, cmd);
else modernTypeSendCommand(nIndex, pXSource->txID, cmd); else modernTypeSendCommand(nIndex, pXSource->txID, cmd);
} }
} else { } else {
for (int i = 0; i <= 3; i++) { for (int i = 0; i <= 3; i++) {
pXSource->txID = GetDataVal(&sprite[pXSource->reference], 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 if (!modernSend) evSend(nIndex, 3, pXSource->txID, cmd);
else modernTypeSendCommand(nIndex, pXSource->txID, cmd); else modernTypeSendCommand(nIndex, pXSource->txID, cmd);
} }
@ -4099,10 +4138,12 @@ void useSequentialTx(XSPRITE* pXSource, COMMAND_ID cmd, bool setState) {
int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) { int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) {
int objType = event.type; int objIndex = event.index; 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 it's a tracking condition, it must ignore all the commands sent from objects
if (pXSource->busyTime > 0 && event.funcID != kCallbackCondition) return -1; if (pXSource->busyTime > 0 && event.funcID != kCallbackMax) return -1;
else if (!srcIsCondition) { // save object serials in the stack and make copy of initial object 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);
@ -4114,14 +4155,12 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) {
} }
int cond = pXSource->data1; bool ok = false; bool RVRS = (pSource->yvel == kModernConditionFalse); int cond = pXSource->data1; bool ok = false; bool RVRS = (pSource->type == kModernConditionFalse);
bool RSET = (pXSource->command == kCmdNumberic + 36); bool RSET = (pXSource->command == kCmdNumberic + 36); bool PUSH = (pXSource->command == kCmdNumberic);
int comOp = pSource->cstat; // comparison operator
if (pXSource->restState == 0) { if (pXSource->restState == 0) {
bool PUSH = (pXSource->command == kCmdNumberic);
int comOp = pSource->cstat; // comparison operator
if (cond == 0) ok = true; // dummy if (cond == 0) ok = true; // dummy
else if (cond >= kCondMixedBase && cond < kCondMixedMax) ok = condCheckMixed(pXSource, event, comOp, PUSH); else if (cond >= kCondMixedBase && cond < kCondMixedMax) ok = condCheckMixed(pXSource, event, comOp, PUSH);
else if (cond >= kCondWallBase && cond < kCondWallMax) ok = condCheckWall(pXSource, comOp, PUSH); else if (cond >= kCondWallBase && cond < kCondWallMax) ok = condCheckWall(pXSource, comOp, PUSH);
@ -4152,6 +4191,7 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) {
} }
// IF
if (pXSource->state) { if (pXSource->state) {
pXSource->isTriggered = (pXSource->triggerOnce) ? true : false; pXSource->isTriggered = (pXSource->triggerOnce) ? true : false;
@ -4165,8 +4205,10 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) {
if (pSource->hitag) { if (pSource->hitag) {
// send it for object currently in the focus // 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); nnExtTriggerObject(objType, objIndex, pXSource->command);
}
// send it for initial object // send it for initial object
if ((pSource->hitag & kModernTypeFlag2) && (pXSource->targetX != pXSource->targetY || !(pSource->hitag & kModernTypeFlag1))) { if ((pSource->hitag & kModernTypeFlag2) && (pXSource->targetX != pXSource->targetY || !(pSource->hitag & kModernTypeFlag1))) {
@ -4176,6 +4218,14 @@ int useCondition(spritetype* pSource, XSPRITE* pXSource, EVENT event) {
} }
// ELSE
} else if (pXSource->sysData2 >= 0) {
pSource = &sprite[pXSource->sysData2]; pXSource = &xsprite[pSource->extra];
useCondition(pSource, pXSource, event);
if (pXSource->isTriggered) pXSource->sysData2 = -1;
} }
return pXSource->state; return pXSource->state;
@ -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); spritetype* pTarget = NULL; XSPRITE* pXTarget = NULL; int receiveHp = 33 + Random(33);
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); int matesPerEnemy = 1; 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 (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, pXTarget)) {
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)) {
spritetype* pMate = pTarget; XSPRITE* pXMate = pXTarget; spritetype* pMate = pTarget; XSPRITE* pXMate = pXTarget;
// heal dude // heal dude
@ -4568,6 +4613,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
if (!isActive(pTarget->index)) if (!isActive(pTarget->index))
aiActivateDude(pTarget, pXTarget); aiActivateDude(pTarget, pXTarget);
} }
return; return;
} }
} }
@ -4604,7 +4650,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
// ...and change target of target to dude to force it fight // ...and change target of target to dude to force it fight
if (pXSource->data3 > 0 && pXTarget->target != pSprite->index) { if (pXSource->data3 > 0 && pXTarget->target != pSprite->index) {
aiSetTarget(pXTarget, pSprite->index); aiSetTarget(pXTarget, pSprite->index);
if (!isActive(pTarget->index)) if (pPlayer == NULL && !isActive(pTarget->index))
aiActivateDude(pTarget, pXTarget); aiActivateDude(pTarget, pXTarget);
if (pXSource->data3 == 2) if (pXSource->data3 == 2)
@ -4706,13 +4752,42 @@ QAV* playerQavSceneLoad(int qavId) {
void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene) { void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene) {
int nIndex = pQavScene->index; int nIndex = pQavScene->index;
if (xspriRangeIsFine(sprite[nIndex].extra)) { if (xspriRangeIsFine(sprite[nIndex].extra)) {
XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra]; XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra];
if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) { if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) {
if (pXSprite->txID > 0) evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID)pXSprite->command); if (pXSprite->txID >= kChannelUser) {
else trPlayerCtrlStopScene(pPlayer);
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 { } else {
playerQavScenePlay(pPlayer); playerQavScenePlay(pPlayer);
pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0); pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0);
} }
} else { } else {
@ -5088,11 +5163,14 @@ bool incDecGoalValueIsReached(XSPRITE* pXSprite) {
} }
void seqSpawnerOffSameTx(XSPRITE* pXSource) { void seqSpawnerOffSameTx(XSPRITE* pXSource) {
for (int nSprite = headspritestat[kStatModernSeqSpawner]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (nSprite != pXSource->reference) { for (int i = 0; i < kMaxXSprites; i++) {
XSPRITE* pXSprite = &xsprite[sprite[nSprite].extra];
if (pXSprite->txID == pXSource->txID && pXSprite->state == 1) { XSPRITE* pXSprite = &xsprite[i];
evKill(nSprite, OBJ_SPRITE); 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; pXSprite->state = 0;
} }
} }

View file

@ -195,6 +195,7 @@ struct OBJECTS_TO_TRACK {
}; };
struct TRCONDITION { struct TRCONDITION {
signed int xindex: 16;
unsigned int length: 8; unsigned int length: 8;
OBJECTS_TO_TRACK obj[kMaxTracedObjects]; 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 trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition);
void trPlayerCtrlSetRace(XSPRITE* pXSource, PLAYER* pPlayer); 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 trPlayerCtrlStopScene(PLAYER* pPlayer);
void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer); void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer); void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer);

View file

@ -569,20 +569,6 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
} }
} }
break; 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;
case kThingArmedProxBomb: case kThingArmedProxBomb:
if (pSprite->statnum != kStatRespawn) { if (pSprite->statnum != kStatRespawn) {
switch (event.cmd) { switch (event.cmd) {
@ -2157,10 +2143,6 @@ void trInit(void)
if (pXSprite->waitTime > 0) if (pXSprite->waitTime > 0)
evPost(i, 3, (pXSprite->waitTime * 120) / 10, pXSprite->restState ? kCmdOn : kCmdOff); evPost(i, 3, (pXSprite->waitTime * 120) / 10, pXSprite->restState ? kCmdOn : kCmdOff);
break; break;
case kModernCondition:
if (pXSprite->busyTime <= 0 || pXSprite->locked) break;
evPost(i, 3, ClipLow(pXSprite->busyTime, 5), kCallbackCondition);
break;
#endif #endif
case kGenTrigger: case kGenTrigger:
case kGenDripWater: case kGenDripWater:

View file

@ -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; 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 const nRootTile = pTSprite->picnum;
int nAnimTile = pTSprite->picnum + animateoffs_replace(pTSprite->picnum, 32768+pTSprite->owner); 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) tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].framenum >= 0)
{ {
pTSprite->yoffset += picanm[nAnimTile].yofs; pTSprite->yoffset += picanm[nAnimTile].yofs;

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <memory>
#include "c_cvars.h" #include "c_cvars.h"
#include "zstring.h" #include "zstring.h"
#include "inputstate.h" #include "inputstate.h"

View file

@ -95,7 +95,7 @@ int32_t FileStream::Seek(int32_t offset, SeekDirection direction)
nStatus = file.Seek(offset, FileReader::SeekCur); nStatus = file.Seek(offset, FileReader::SeekCur);
} }
else if (kSeekEnd == direction) { else if (kSeekEnd == direction) {
nStatus = klseek(file, offset, SEEK_END); nStatus = file.Seek(offset, FileReader::SeekEnd);
} }
return nStatus; return nStatus;

View file

@ -47,13 +47,9 @@
#ifndef playmve_h_ #ifndef playmve_h_
#define playmve_h_ #define playmve_h_
#include "a.h"
#include "baselayer.h" #include "baselayer.h"
#include "build.h" #include "build.h"
#include "cache1d.h"
#include "compat.h" #include "compat.h"
#include "fx_man.h"
#include "keyboard.h"
#include "pragmas.h" #include "pragmas.h"
bool playmve(const char* filename); bool playmve(const char* filename);