- condCheckSprite

This commit is contained in:
Christoph Oelckers 2021-10-14 01:06:50 +02:00
parent 0ff9afde61
commit 9965245449
2 changed files with 67 additions and 72 deletions

View file

@ -4514,23 +4514,23 @@ bool condCheckDude(DBloodActor* aCond, int cmpOp, bool PUSH)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) { bool condCheckSprite(DBloodActor* aCond, int cmpOp, bool PUSH)
{
auto pXCond = &aCond->x();
auto aCond = &bloodActors[pXCond->reference];
int var = -1, var2 = -1, var3 = -1; PLAYER* pPlayer = NULL; bool retn = false; int var = -1, var2 = -1, var3 = -1; PLAYER* pPlayer = NULL; bool retn = false;
int cond = pXCond->data1 - kCondSpriteBase; int arg1 = pXCond->data2; int cond = pXCond->data1 - kCondSpriteBase; 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, objIndex = -1;
DBloodActor* objActor = nullptr; DBloodActor* objActor = nullptr;
condUnserialize(aCond, &objType, &objIndex, &objActor); condUnserialize(aCond, &objType, &objIndex, &objActor);
if (objType != OBJ_SPRITE || !spriRangeIsFine(objIndex)) if (objType != OBJ_SPRITE || !objActor)
condError(aCond, "Object #%d (objType: %d) is not a sprite!", cond, objIndex, objType); condError(aCond, "Object #%d (objType: %d) is not a sprite!", cond, objActor->GetIndex(), objType);
spritetype* pSpr = &sprite[objIndex]; spritetype* pSpr = &objActor->s();
XSPRITE* pXSpr = (xspriRangeIsFine(pSpr->extra)) ? &xsprite[pSpr->extra] : NULL; XSPRITE* pXSpr = objActor->hasX()? &objActor->x() : nullptr;
DBloodActor* spractor = &bloodActors[pXSpr->reference];
if (cond < (kCondRange >> 1)) if (cond < (kCondRange >> 1))
{ {
@ -4544,36 +4544,36 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) {
case 10: return condCmp(pSpr->clipdist, arg1, arg2, cmpOp); case 10: return condCmp(pSpr->clipdist, arg1, arg2, cmpOp);
case 15: case 15:
if (!spriRangeIsFine(pSpr->owner)) return false; if (!spriRangeIsFine(pSpr->owner)) return false;
else if (PUSH) condPush(pXCond, OBJ_SPRITE, pSpr->owner); else if (PUSH) condPush(aCond, OBJ_SPRITE, 0, objActor->GetOwner());
return true; return true;
case 20: // stays in a sector? case 20: // stays in a sector?
if (!sectRangeIsFine(pSpr->sectnum)) return false; if (!sectRangeIsFine(pSpr->sectnum)) return false;
else if (PUSH) condPush(pXCond, OBJ_SECTOR, pSpr->sectnum); else if (PUSH) condPush(aCond, OBJ_SECTOR, pSpr->sectnum, nullptr);
return true; return true;
case 25: case 25:
switch (arg1) switch (arg1)
{ {
case 0: return (xvel[pSpr->index] || yvel[pSpr->index] || zvel[pSpr->index]); case 0: return (objActor->xvel() || objActor->yvel() || objActor->zvel());
case 1: return (xvel[pSpr->index]); case 1: return (objActor->xvel());
case 2: return (yvel[pSpr->index]); case 2: return (objActor->yvel());
case 3: return (zvel[pSpr->index]); case 3: return (objActor->zvel());
} }
break; break;
case 30: case 30:
if (!spriteIsUnderwater(spractor) && !spriteIsUnderwater(spractor, true)) return false; if (!spriteIsUnderwater(objActor) && !spriteIsUnderwater(objActor, true)) return false;
else if (PUSH) condPush(pXCond, OBJ_SECTOR, pSpr->sectnum); else if (PUSH) condPush(aCond, OBJ_SECTOR, pSpr->sectnum, nullptr);
return true; return true;
case 31: case 31:
if (arg1 == -1) if (arg1 == -1)
{ {
for (var = 0; var < kDmgMax; var++) for (var = 0; var < kDmgMax; var++)
{ {
if (!nnExtIsImmune(spractor, arg1, 0)) if (!nnExtIsImmune(objActor, arg1, 0))
return false; return false;
} }
return true; return true;
} }
return nnExtIsImmune(spractor, arg1, 0); return nnExtIsImmune(objActor, arg1, 0);
case 35: // hitscan: ceil? case 35: // hitscan: ceil?
case 36: // hitscan: floor? case 36: // hitscan: floor?
@ -4588,8 +4588,8 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) {
if ((pPlayer = getPlayerById(pSpr->type)) != NULL) if ((pPlayer = getPlayerById(pSpr->type)) != NULL)
var = HitScan(pSpr, pPlayer->zWeapon, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, arg1, arg3 << 1); var = HitScan(pSpr, pPlayer->zWeapon, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, arg1, arg3 << 1);
else if (IsDudeSprite(pSpr)) else if (objActor->IsDudeActor())
var = HitScan(pSpr, pSpr->z, bcos(pSpr->ang), bsin(pSpr->ang), (!spractor->hasX()) ? 0 : spractor->dudeSlope, arg1, arg3 << 1); var = HitScan(pSpr, pSpr->z, bcos(pSpr->ang), bsin(pSpr->ang), (!objActor->hasX()) ? 0 : objActor->dudeSlope, arg1, arg3 << 1);
else if ((var2 & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_FLOOR) { else if ((var2 & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_FLOOR) {
var3 = (var2 & 0x0008) ? 0x10000 << 1 : -(0x10000 << 1); var3 = (var2 & 0x0008) ? 0x10000 << 1 : -(0x10000 << 1);
@ -4613,25 +4613,25 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) {
if (!PUSH) return retn; if (!PUSH) return retn;
switch (var) switch (var)
{ {
case 0: case 4: condPush(pXCond, OBJ_WALL, gHitInfo.hitwall); break; case 0: case 4: condPush(aCond, OBJ_WALL, gHitInfo.hitwall, nullptr); break;
case 1: case 2: condPush(pXCond, OBJ_SECTOR, gHitInfo.hitsect); break; case 1: case 2: condPush(aCond, OBJ_SECTOR, gHitInfo.hitsect, nullptr); break;
case 3: condPush(pXCond, OBJ_SPRITE, gHitInfo.hitactor? gHitInfo.hitactor->s().index : -1); break; case 3: condPush(aCond, OBJ_SPRITE, 0, gHitInfo.hitactor); break;
} }
} }
return retn; return retn;
case 45: // this sprite is a target of some dude?
int nSprite;
StatIterator it(kStatDude);
while ((nSprite = it.NextIndex()) >= 0)
{
if (pSpr->index == nSprite) continue;
spritetype* pDude = &sprite[nSprite]; case 45: // this sprite is a target of some dude?
if (IsDudeSprite(pDude) && xspriRangeIsFine(pDude->extra)) { BloodStatIterator it(kStatDude);
XSPRITE* pXDude = &xsprite[pDude->extra]; while (auto iactor = it.Next())
if (pXDude->health <= 0 || pXDude->target_i != pSpr->index) continue; {
else if (PUSH) condPush(pXCond, OBJ_SPRITE, nSprite); if (objActor == iactor) continue;
if (iactor->IsDudeActor() && iactor->hasX())
{
XSPRITE* pXDude = &iactor->x();
if (pXDude->health <= 0 || iactor->GetTarget() != objActor) continue;
else if (PUSH) condPush(aCond, OBJ_SPRITE, 0, iactor);
return true; return true;
} }
} }
@ -4644,21 +4644,21 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) {
{ {
default: break; default: break;
case 50: // compare hp (in %) case 50: // compare hp (in %)
if (IsDudeSprite(pSpr)) var = (pXSpr->sysData2 > 0) ? ClipRange(pXSpr->sysData2 << 4, 1, 65535) : getDudeInfo(pSpr->type)->startHealth << 4; if (objActor->IsDudeActor()) var = (pXSpr->sysData2 > 0) ? ClipRange(pXSpr->sysData2 << 4, 1, 65535) : getDudeInfo(pSpr->type)->startHealth << 4;
else if (pSpr->type == kThingBloodChunks) return condCmp(0, arg1, arg2, cmpOp); else if (pSpr->type == kThingBloodChunks) return condCmp(0, 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((kPercFull * 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.type != kHitSector) return false; if (objActor->hit().ceilhit.type != kHitSector) return false;
else if (PUSH) condPush(pXCond, OBJ_SECTOR, gSpriteHit[pSpr->extra].ceilhit.index); else if (PUSH) condPush(aCond, OBJ_SECTOR, objActor->hit().ceilhit.index, nullptr);
return true; return true;
case 56: // touching floor of sector? case 56: // touching floor of sector?
if (gSpriteHit[pSpr->extra].florhit.type != kHitSector) return false; if (objActor->hit().florhit.type != kHitSector) return false;
else if (PUSH) condPush(pXCond, OBJ_SECTOR, gSpriteHit[pSpr->extra].florhit.index); else if (PUSH) condPush(aCond, OBJ_SECTOR, objActor->hit().florhit.index, nullptr);
return true; return true;
case 57: // touching walls of sector? case 57: // touching walls of sector?
if (gSpriteHit[pSpr->extra].hit.type != kHitWall) return false; if (objActor->hit().hit.type != kHitWall) return false;
else if (PUSH) condPush(pXCond, OBJ_WALL, gSpriteHit[pSpr->extra].hit.index); else if (PUSH) condPush(aCond, OBJ_WALL, objActor->hit().hit.index, nullptr);
return true; return true;
case 58: // touching another sprite? case 58: // touching another sprite?
{ {
@ -4667,70 +4667,71 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) {
{ {
case 0: case 0:
case 1: case 1:
if (gSpriteHit[pSpr->extra].florhit.type == kHitSprite) actorvar = gSpriteHit[pSpr->extra].florhit.actor; if (objActor->hit().florhit.type == kHitSprite) actorvar = objActor->hit().florhit.actor;
if (arg3 || var >= 0) break; if (arg3 || var >= 0) break;
[[fallthrough]]; [[fallthrough]];
case 2: case 2:
if (gSpriteHit[pSpr->extra].hit.type == kHitSprite) actorvar = gSpriteHit[pSpr->extra].hit.actor; if (objActor->hit().hit.type == kHitSprite) actorvar = objActor->hit().hit.actor;
if (arg3 || var >= 0) break; if (arg3 || var >= 0) break;
[[fallthrough]]; [[fallthrough]];
case 3: case 3:
if (gSpriteHit[pSpr->extra].ceilhit.type == kHitSprite) actorvar = gSpriteHit[pSpr->extra].ceilhit.actor; if (objActor->hit().ceilhit.type == kHitSprite) actorvar = objActor->hit().ceilhit.actor;
break; break;
} }
if (actorvar == nullptr) if (actorvar == nullptr)
{ {
// check if something touching this sprite // check if something is touching this sprite
for (int i = kMaxXSprites - 1, idx = i; i > 0; idx = xsprite[--i].reference) for (int i = kMaxXSprites - 1, idx = i; i > 0; idx = xsprite[--i].reference)
{ {
if (idx < 0 || (sprite[idx].flags & kHitagRespawn)) continue; if (idx < 0) continue;
auto iactor = &bloodActors[idx]; auto iactor = &bloodActors[idx];
auto objactor = &bloodActors[objIndex];
auto& hit = gSpriteHit[i]; if (iactor->s().flags & kHitagRespawn) continue;
switch (arg3) { auto& hit = iactor->hit();
switch (arg3)
{
case 0: case 0:
case 1: case 1:
if (hit.ceilhit.type == kHitSprite && hit.ceilhit.actor == objactor) actorvar = iactor; if (hit.ceilhit.type == kHitSprite && hit.ceilhit.actor == objActor) actorvar = iactor;
if (arg3 || actorvar) break; if (arg3 || actorvar) break;
[[fallthrough]]; [[fallthrough]];
case 2: case 2:
if (hit.hit.type == kHitSprite && hit.hit.actor == objactor) actorvar = iactor; if (hit.hit.type == kHitSprite && hit.hit.actor == objActor) actorvar = iactor;
if (arg3 || actorvar) break; if (arg3 || actorvar) break;
[[fallthrough]]; [[fallthrough]];
case 3: case 3:
if (hit.florhit.type == kHitSprite && hit.florhit.actor == objactor) actorvar = iactor; if (hit.florhit.type == kHitSprite && hit.florhit.actor == objActor) actorvar = iactor;
break; break;
} }
} }
} }
if (actorvar == nullptr) return false; if (actorvar == nullptr) return false;
else if (PUSH) condPush(pXCond, OBJ_SPRITE, actorvar->s().index); else if (PUSH) condPush(aCond, OBJ_SPRITE, 0, actorvar);
return true; return true;
} }
case 65: // compare burn time (in %) case 65: // compare burn time (in %)
var = (IsDudeSprite(pSpr)) ? 2400 : 1200; var = (objActor->IsDudeActor()) ? 2400 : 1200;
if (!condCmp((kPercFull * pXSpr->burnTime) / var, arg1, arg2, cmpOp)) return false; if (!condCmp((kPercFull * pXSpr->burnTime) / var, arg1, arg2, cmpOp)) return false;
else if (PUSH && spriRangeIsFine(pXSpr->burnSource)) condPush(pXCond, OBJ_SPRITE, pXSpr->burnSource); else if (PUSH && spriRangeIsFine(pXSpr->burnSource)) condPush(aCond, OBJ_SPRITE, 0, objActor->GetBurnSource());
return true; return true;
case 66: // any flares stuck in this sprite? case 66: // any flares stuck in this sprite?
{ {
int nSprite; BloodStatIterator it(kStatFlare);
StatIterator it(kStatFlare); while (auto flareactor = it.Next())
while ((nSprite = it.NextIndex()) >= 0)
{ {
spritetype* pFlare = &sprite[nSprite]; if (!flareactor->hasX() || (flareactor->s().flags & kHitagFree))
if (!xspriRangeIsFine(pFlare->extra) || (pFlare->flags & kHitagFree))
continue; continue;
XSPRITE* pXFlare = &xsprite[pFlare->extra]; if (flareactor->GetTarget() != objActor) continue;
if (!spriRangeIsFine(pXFlare->target_i) || pXFlare->target_i != objIndex) continue; else if (PUSH) condPush(aCond, OBJ_SPRITE, 0, flareactor);
else if (PUSH) condPush(pXCond, OBJ_SPRITE, nSprite);
return true; return true;
} }
return false; return false;
} }
case 70: case 70:
return condCmp(getSpriteMassBySize(spractor), arg1, arg2, cmpOp); // mass of the sprite in a range? return condCmp(getSpriteMassBySize(objActor), arg1, arg2, cmpOp); // mass of the sprite in a range?
} }
} }
else else
@ -6321,8 +6322,8 @@ int useCondition(DBloodActor* sourceactor, const EVENT& event)
else if (cond >= kCondSectorBase && cond < kCondSectorMax) ok = condCheckSector(sourceactor, comOp, PUSH); else if (cond >= kCondSectorBase && cond < kCondSectorMax) ok = condCheckSector(sourceactor, comOp, PUSH);
else if (cond >= kCondPlayerBase && cond < kCondPlayerMax) ok = condCheckPlayer(sourceactor, comOp, PUSH); else if (cond >= kCondPlayerBase && cond < kCondPlayerMax) ok = condCheckPlayer(sourceactor, comOp, PUSH);
else if (cond >= kCondDudeBase && cond < kCondDudeMax) ok = condCheckDude(sourceactor, comOp, PUSH); else if (cond >= kCondDudeBase && cond < kCondDudeMax) ok = condCheckDude(sourceactor, comOp, PUSH);
else if (cond >= kCondSpriteBase && cond < kCondSpriteMax) ok = condCheckSprite(pXSource, comOp, PUSH); else if (cond >= kCondSpriteBase && cond < kCondSpriteMax) ok = condCheckSprite(sourceactor, comOp, PUSH);
else condError(sourceactor, "Unexpected condition id %d!", cond); else condError(sourceactor,"Unexpected condition id %d!", cond);
pXSource->state = (ok ^ RVRS); pXSource->state = (ok ^ RVRS);

View file

@ -374,12 +374,6 @@ int useCondition(DBloodActor*, const EVENT& event);
bool condCmp(int val, int arg1, int arg2, int comOp); bool condCmp(int val, int arg1, int arg2, int comOp);
bool condCmpne(int arg1, int arg2, int comOp); bool condCmpne(int arg1, int arg2, int comOp);
void condError(DBloodActor* pXCond, const char* pzFormat, ...); void condError(DBloodActor* pXCond, const char* pzFormat, ...);
bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH);
bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH);
bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH);
bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH);
bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH);
bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH);
void condUpdateObjectIndex(int objType, int oldIndex, int newIndex); void condUpdateObjectIndex(int objType, int oldIndex, int newIndex);
DBloodActor* evrListRedirectors(int objType, int objXIndex, DBloodActor* objActor, DBloodActor* pXRedir, int* tx); DBloodActor* evrListRedirectors(int objType, int objXIndex, DBloodActor* objActor, DBloodActor* pXRedir, int* tx);
void seqSpawnerOffSameTx(DBloodActor* actor); void seqSpawnerOffSameTx(DBloodActor* actor);