- ProcessTouchObjects

This commit is contained in:
Christoph Oelckers 2020-12-03 20:30:30 +01:00
parent f7668fc074
commit c4fa99c891
4 changed files with 458 additions and 301 deletions

View file

@ -2408,13 +2408,14 @@ static void actInitThings()
#endif
pXSprite->state = 0;
break;
case kThingBloodChunks: {
case kThingBloodChunks:
{
SEQINST* pInst = GetInstance(3, pSprite->extra);
if (pInst)
{
auto seq = getSequence(pInst->nSeqID);
if (!seq) break;
seqSpawn(pInst->nSeqID, 3, pSprite->extra);
seqSpawn(pInst->nSeqID, act);
}
break;
}
@ -4217,93 +4218,87 @@ static void actTouchFloor(DBloodActor* actor, int nSector)
//
//---------------------------------------------------------------------------
static void ProcessTouchObjects(DBloodActor* actor)
static void checkCeilHit(DBloodActor* actor)
{
auto pSprite = &actor->s();
auto pXSprite = &actor->x();
SPRITEHIT* pSpriteHit = &actor->hit();
PLAYER *pPlayer = nullptr;
if (actor->IsPlayerActor()) pPlayer = &gPlayer[pSprite->type-kDudePlayer1];
auto pXSprite = actor->hasX() ? &actor->x() : nullptr;
int nHitSprite = pSpriteHit->ceilhit & 0x3fff;
switch (pSpriteHit->ceilhit&0xc000)
Collision coll(actor->hit().ceilhit);
switch (coll.type)
{
case 0x8000:
case kHitWall:
break;
case 0xc000:
if (sprite[nHitSprite].extra > 0)
case kHitSprite:
if (coll.actor->hasX())
{
spritetype *pSprite2 = &sprite[nHitSprite];
auto actor2 = &bloodActors[nHitSprite];
XSPRITE *pXSprite2 = &xsprite[pSprite2->extra];
auto actor2 = coll.actor;
spritetype* pSprite2 = &actor2->s();
XSPRITE* pXSprite2 = &actor2->x();
if ((pSprite2->statnum == kStatThing || pSprite2->statnum == kStatDude) && (actor->xvel() != 0 || actor->yvel() != 0 || actor->zvel() != 0))
{
if (pSprite2->statnum == kStatThing)
{
int nType = pSprite2->type-kThingBase;
const THINGINFO *pThingInfo = &thingInfo[nType];
if (pThingInfo->flags&1)
pSprite2->flags |= 1;
if (pThingInfo->flags&2)
pSprite2->flags |= 4;
int nType = pSprite2->type - kThingBase;
const THINGINFO* pThingInfo = &thingInfo[nType];
if (pThingInfo->flags & 1) pSprite2->flags |= 1;
if (pThingInfo->flags & 2) pSprite2->flags |= 4;
// Inlined ?
xvel[pSprite2->index] += MulScale(4, pSprite2->x-pSprite->x, 2);
yvel[pSprite2->index] += MulScale(4, pSprite2->y-pSprite->y, 2);
actor2->xvel() += MulScale(4, pSprite2->x - pSprite->x, 2);
actor2->yvel() += MulScale(4, pSprite2->y - pSprite->y, 2);
}
else
{
pSprite2->flags |= 5;
xvel[pSprite2->index] += MulScale(4, pSprite2->x-pSprite->x, 2);
yvel[pSprite2->index] += MulScale(4, pSprite2->y-pSprite->y, 2);
actor2->xvel() += MulScale(4, pSprite2->x - pSprite->x, 2);
actor2->yvel() += MulScale(4, pSprite2->y - pSprite->y, 2);
#ifdef NOONE_EXTENSIONS
#ifdef NOONE_EXTENSIONS
// add size shroom abilities
if ((IsPlayerSprite(pSprite) && isShrinked(pSprite)) || (IsPlayerSprite(pSprite2) && isGrown(pSprite2))) {
if ((actor->IsPlayerActor() && isShrinked(pSprite)) || (IsPlayerSprite(pSprite2) && isGrown(pSprite2))) {
int mass1 = getDudeInfo(pSprite2->type)->mass;
int mass2 = getDudeInfo(pSprite->type)->mass;
switch (pSprite->type) {
switch (pSprite->type)
{
case kDudeModernCustom:
case kDudeModernCustomBurning:
mass2 = getSpriteMassBySize(pSprite);
break;
}
if (mass1 > mass2) {
if (mass1 > mass2)
{
int dmg = abs((mass1 - mass2) * (pSprite2->clipdist - pSprite->clipdist));
if (IsDudeSprite(pSprite2)) {
if (dmg > 0)
actDamageSprite(pSprite2->index, pSprite, (Chance(0x2000)) ? DAMAGE_TYPE_0 : (Chance(0x4000)) ? DAMAGE_TYPE_3 : DAMAGE_TYPE_2, dmg);
if (Chance(0x0200))
actKickObject(actor2, actor);
if (actor2->IsDudeActor())
{
if (dmg > 0) actDamageSprite(pSprite2->index, pSprite, (Chance(0x2000)) ? DAMAGE_TYPE_0 : (Chance(0x4000)) ? DAMAGE_TYPE_3 : DAMAGE_TYPE_2, dmg);
if (Chance(0x0200)) actKickObject(actor2, actor);
}
}
}
#endif
if (!IsPlayerSprite(pSprite) || gPlayer[pSprite->type - kDudePlayer1].godMode == 0) {
switch (pSprite2->type) {
#endif
if (!actor->IsPlayerActor() || gPlayer[pSprite->type - kDudePlayer1].godMode == 0)
{
switch (pSprite2->type)
{
case kDudeTchernobog:
actDamageSprite(pSprite2->index, pSprite, DAMAGE_TYPE_3, pXSprite->health << 2);
actDamageSprite(actor2, actor, DAMAGE_TYPE_3, pXSprite->health << 2);
break;
#ifdef NOONE_EXTENSIONS
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
case kDudeModernCustomBurning:
int dmg = 0;
if (!IsDudeSprite(pSprite) || (dmg = ClipLow((getSpriteMassBySize(pSprite2) - getSpriteMassBySize(pSprite)) >> 1, 0)) == 0)
if (!actor->IsDudeActor() || (dmg = ClipLow((getSpriteMassBySize(pSprite2) - getSpriteMassBySize(pSprite)) >> 1, 0)) == 0)
break;
if (!IsPlayerSprite(pSprite)) {
actDamageSprite(pSprite2->index, pSprite, DAMAGE_TYPE_0, dmg);
if (xspriRangeIsFine(pSprite->extra) && !isActive(pSprite->index))
aiActivateDude(&bloodActors[pSprite->index]);
if (!actor->IsPlayerActor())
{
actDamageSprite(actor2, actor, DAMAGE_TYPE_0, dmg);
if (pXSprite && !actor->isActive()) aiActivateDude(actor);
}
else if (powerupCheck(&gPlayer[pSprite->type - kDudePlayer1], kPwUpJumpBoots) > 0) actDamageSprite(pSprite2->index, pSprite, DAMAGE_TYPE_3, dmg);
else actDamageSprite(pSprite2->index, pSprite, DAMAGE_TYPE_0, dmg);
else if (powerupCheck(&gPlayer[pSprite->type - kDudePlayer1], kPwUpJumpBoots) > 0) actDamageSprite(actor2, actor, DAMAGE_TYPE_3, dmg);
else actDamageSprite(actor2, actor, DAMAGE_TYPE_0, dmg);
break;
#endif
#endif
}
@ -4311,125 +4306,167 @@ static void ProcessTouchObjects(DBloodActor* actor)
}
}
if (pSprite2->type == kTrapSawCircular) {
if (pSprite2->type == kTrapSawCircular)
{
if (!pXSprite2->state) actDamageSprite(actor, actor, DAMAGE_TYPE_2, 1);
else {
pXSprite2->data1 = 1;
pXSprite2->data2 = ClipHigh(pXSprite2->data2+8, 600);
pXSprite2->data2 = ClipHigh(pXSprite2->data2 + 8, 600);
actDamageSprite(actor, actor, DAMAGE_TYPE_2, 16);
}
}
}
break;
}
}
}
break;
}
nHitSprite = pSpriteHit->hit & 0x3fff;
switch (pSpriteHit->hit&0xc000)
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void checkHit(DBloodActor* actor)
{
auto pSprite = &actor->s();
auto pXSprite = actor->hasX() ? &actor->x() : nullptr;
Collision coll(actor->hit().hit);
switch (coll.type)
{
case 0x8000:
case kHitWall:
break;
case 0xc000:
if (sprite[nHitSprite].extra > 0)
case kHitSprite:
if (coll.actor->hasX())
{
spritetype *pSprite2 = &sprite[nHitSprite];
auto actor2 = &bloodActors[nHitSprite];
auto actor2 = coll.actor;
spritetype* pSprite2 = &actor2->s();
//XSPRITE *pXSprite2 = &Xsprite[pSprite2->extra];
#ifdef NOONE_EXTENSIONS
#ifdef NOONE_EXTENSIONS
// add size shroom abilities
if ((IsPlayerSprite(pSprite2) && isShrinked(pSprite2)) || (IsPlayerSprite(pSprite) && isGrown(pSprite))) {
if (xvel[pSprite->xvel] != 0 && IsDudeSprite(pSprite2)) {
if ((actor2->IsPlayerActor() && isShrinked(pSprite2)) || (actor->IsPlayerActor() && isGrown(pSprite)))
{
if (actor->xvel() != 0 && actor2->IsDudeActor())
{
int mass1 = getDudeInfo(pSprite->type)->mass;
int mass2 = getDudeInfo(pSprite2->type)->mass;
switch (pSprite2->type) {
switch (pSprite2->type)
{
case kDudeModernCustom:
case kDudeModernCustomBurning:
mass2 = getSpriteMassBySize(pSprite2);
break;
}
if (mass1 > mass2) {
if (mass1 > mass2)
{
actKickObject(actor, actor2);
sfxPlay3DSound(pSprite, 357, -1, 1);
int dmg = (mass1 - mass2) + abs(FixedToInt(xvel[pSprite->index]));
if (dmg > 0)
actDamageSprite(actor, actor2, (Chance(0x2000)) ? DAMAGE_TYPE_0 : DAMAGE_TYPE_2, dmg);
int dmg = (mass1 - mass2) + abs(FixedToInt(actor->xvel()));
if (dmg > 0) actDamageSprite(actor, actor2, (Chance(0x2000)) ? DAMAGE_TYPE_0 : DAMAGE_TYPE_2, dmg);
}
}
}
#endif
#endif
switch (pSprite2->type) {
switch (pSprite2->type)
{
case kThingKickablePail:
actKickObject(actor, actor2);
break;
case kThingZombieHead:
sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 357, pSprite->sectnum);
actKickObject(actor, actor2);
actDamageSprite(nullptr, actor2, DAMAGE_TYPE_0, 80);
break;
case kDudeBurningInnocent:
case kDudeBurningCultist:
case kDudeBurningZombieAxe:
case kDudeBurningZombieButcher:
// This does not make sense
pXSprite->burnTime = ClipLow(pXSprite->burnTime-4, 0);
actDamageSprite(pXSprite->burnSource, pSprite, DAMAGE_TYPE_1, 8);
pXSprite->burnTime = ClipLow(pXSprite->burnTime - 4, 0);
actDamageSprite(actor->GetBurnSource(), actor, DAMAGE_TYPE_1, 8);
break;
}
}
break;
}
nHitSprite = pSpriteHit->florhit & 0x3fff;
switch (pSpriteHit->florhit & 0xc000) {
case 0x8000:
break;
case 0x4000:
actTouchFloor(actor,nHitSprite);
break;
case 0xc000:
if (sprite[nHitSprite].extra > 0)
{
spritetype *pSprite2 = &sprite[nHitSprite];
XSPRITE *pXSprite2 = &xsprite[pSprite2->extra];
auto actor2 = &bloodActors[nHitSprite];
}
#ifdef NOONE_EXTENSIONS
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void checkFloorHit(DBloodActor* actor)
{
auto pSprite = &actor->s();
auto pXSprite = actor->hasX() ? &actor->x() : nullptr;
Collision coll(actor->hit().florhit);
switch (coll.type)
{
case kHitWall:
break;
case kHitSector:
actTouchFloor(actor, coll.index);
break;
case kHitSprite:
if (coll.actor->hasX())
{
auto actor2 = coll.actor;
spritetype* pSprite2 = &actor2->s();
XSPRITE* pXSprite2 = &actor2->x();
#ifdef NOONE_EXTENSIONS
// add size shroom abilities
if ((IsPlayerSprite(pSprite2) && isShrinked(pSprite2)) || (IsPlayerSprite(pSprite) && isGrown(pSprite))) {
if ((actor2->IsPlayerActor() && isShrinked(pSprite2)) || (actor->IsPlayerActor() && isGrown(pSprite)))
{
int mass1 = getDudeInfo(pSprite->type)->mass;
int mass2 = getDudeInfo(pSprite2->type)->mass;
switch (pSprite2->type) {
switch (pSprite2->type)
{
case kDudeModernCustom:
case kDudeModernCustomBurning:
mass2 = getSpriteMassBySize(pSprite2);
break;
}
if (mass1 > mass2 && IsDudeSprite(pSprite2)) {
if (mass1 > mass2 && IsDudeSprite(pSprite2))
{
if ((IsPlayerSprite(pSprite2) && Chance(0x500)) || !IsPlayerSprite(pSprite2))
actKickObject(actor, actor2);
int dmg = (mass1 - mass2) + pSprite->clipdist;
if (dmg > 0)
actDamageSprite(actor, actor2, (Chance(0x2000)) ? DAMAGE_TYPE_0 : DAMAGE_TYPE_2, dmg);
if (dmg > 0) actDamageSprite(actor, actor2, (Chance(0x2000)) ? DAMAGE_TYPE_0 : DAMAGE_TYPE_2, dmg);
}
}
#endif
#endif
switch (pSprite2->type) {
PLAYER* pPlayer = nullptr;
if (actor->IsPlayerActor()) pPlayer = &gPlayer[pSprite->type - kDudePlayer1];
switch (pSprite2->type)
{
case kThingKickablePail:
if (pPlayer) {
if (pPlayer)
{
if (pPlayer->kickPower > PlayClock) return;
pPlayer->kickPower = PlayClock+60;
pPlayer->kickPower = PlayClock + 60;
}
actKickObject(actor, actor2);
sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 357, pSprite->sectnum);
sfxPlay3DSound(pSprite, 374, 0, 0);
break;
case kThingZombieHead:
if (pPlayer) {
if (pPlayer)
{
if (pPlayer->kickPower > PlayClock) return;
pPlayer->kickPower = PlayClock+60;
pPlayer->kickPower = PlayClock + 60;
}
actKickObject(actor, actor2);
sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 357, pSprite->sectnum);
@ -4437,9 +4474,10 @@ static void ProcessTouchObjects(DBloodActor* actor)
break;
case kTrapSawCircular:
if (!pXSprite2->state) actDamageSprite(actor, actor, DAMAGE_TYPE_2, 1);
else {
else
{
pXSprite2->data1 = 1;
pXSprite2->data2 = ClipHigh(pXSprite2->data2+8, 600);
pXSprite2->data2 = ClipHigh(pXSprite2->data2 + 8, 600);
actDamageSprite(actor, actor, DAMAGE_TYPE_2, 16);
}
break;
@ -4476,54 +4514,80 @@ static void ProcessTouchObjects(DBloodActor* actor)
case kDudePlayer6:
case kDudePlayer7:
case kDudePlayer8:
#ifdef NOONE_EXTENSIONS
#ifdef NOONE_EXTENSIONS
if (pPlayer && !isShrinked(pSprite))
#else
#else
if (pPlayer)
#endif
actDamageSprite(actor, actor2,DAMAGE_TYPE_2, 8);
#endif
actDamageSprite(actor, actor2, DAMAGE_TYPE_2, 8);
break;
}
}
break;
}
}
#ifdef NOONE_EXTENSIONS
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void ProcessTouchObjects(DBloodActor* actor)
{
checkCeilHit(actor);
checkHit(actor);
checkFloorHit(actor);
#ifdef NOONE_EXTENSIONS
// add more trigger statements for Touch flag
if (gModernMap && IsDudeSprite(pSprite)) {
if (gModernMap && actor->IsDudeActor())
{
DBloodActor* actor2 = nullptr;
for (int i : { actor->hit().hit, actor->hit().florhit, actor->hit().ceilhit})
{
Collision coll = i;
if (coll.type == kHitSprite)
{
actor2 = coll.actor;
break;
}
}
// Touch sprites
int nHSprite = -1;
if ((pSpriteHit->hit & 0xc000) == 0xc000) nHSprite = pSpriteHit->hit & 0x3fff;
else if ((pSpriteHit->florhit & 0xc000) == 0xc000) nHSprite = pSpriteHit->florhit & 0x3fff;
else if ((pSpriteHit->ceilhit & 0xc000) == 0xc000) nHSprite = pSpriteHit->ceilhit & 0x3fff;
if (spriRangeIsFine(nHSprite) && xspriRangeIsFine(sprite[nHSprite].extra)) {
XSPRITE* pXHSprite = &xsprite[sprite[nHSprite].extra];
if (pXHSprite->Touch && !pXHSprite->isTriggered && (!pXHSprite->DudeLockout || IsPlayerSprite(pSprite)))
trTriggerSprite(nHSprite, pXHSprite, kCmdSpriteTouch);
if (actor2->hasX())
{
XSPRITE* pXHSprite = &actor2->x();
if (pXHSprite->Touch && !pXHSprite->isTriggered && (!pXHSprite->DudeLockout || actor->IsPlayerActor()))
trTriggerSprite(actor2, kCmdSpriteTouch);
}
// Touch walls
Collision coll = actor->hit().hit;
int nHWall = -1;
if ((pSpriteHit->hit & 0xc000) == 0x8000)
if (coll.type == kHitWall)
{
nHWall = pSpriteHit->hit & 0x3fff;
nHWall = coll.index;
if (wallRangeIsFine(nHWall) && xwallRangeIsFine(wall[nHWall].extra))
{
XWALL* pXHWall = &xwall[wall[nHWall].extra];
if (pXHWall->triggerTouch && !pXHWall->isTriggered && (!pXHWall->dudeLockout || IsPlayerSprite(pSprite)))
if (pXHWall->triggerTouch && !pXHWall->isTriggered && (!pXHWall->dudeLockout || actor->IsPlayerActor()))
trTriggerWall(nHWall, pXHWall, kCmdWallTouch);
}
}
// enough to reset SpriteHit values
if (nHWall != -1 || nHSprite != -1) actor->xvel() += 5;
if (nHWall != -1 || actor2) actor->xvel() += 5;
}
#endif
#endif
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actAirDrag(spritetype *pSprite, int a2)
{
int vbp = 0;

View file

@ -61,6 +61,17 @@ public:
return base() + x().target;
}
void SetBurnSource(DBloodActor* own)
{
x().burnSource = own ? own->s().index : -1;
}
DBloodActor* GetBurnSource()
{
if (x().burnSource == -1 || x().burnSource == kMaxSprites - 1) return nullptr;
return base() + x().burnSource;
}
void SetSpecialOwner() // nnext hackery
{
s().owner = kMaxSprites - 1;
@ -96,6 +107,24 @@ public:
return s().type >= kItemAmmoBase && s().type < kItemAmmoMax;
}
bool isActive()
{
if (!hasX())
return false;
switch (x().aiState->stateType)
{
case kAiStateIdle:
case kAiStateGenIdle:
case kAiStateSearch:
case kAiStateMove:
case kAiStateOther:
return false;
default:
return true;
}
}
};
extern DBloodActor bloodActors[kMaxSprites];
@ -171,4 +200,62 @@ inline void PLAYER::setFragger(DBloodActor* actor)
fraggerId = actor == nullptr ? -1 : actor->s().index;
}
// Wrapper around the insane collision info mess from Build.
struct Collision
{
int type;
int index;
int legacyVal; // should be removed later, but needed for converting back for unadjusted code.
DBloodActor* actor;
Collision() = default;
Collision(int legacyval) { setFromEngine(legacyval); }
int setNone()
{
type = kHitNone;
index = -1;
legacyVal = 0;
actor = nullptr;
return kHitNone;
}
int setSector(int num)
{
type = kHitSector;
index = num;
legacyVal = type | index;
actor = nullptr;
return kHitSector;
}
int setWall(int num)
{
type = kHitWall;
index = num;
legacyVal = type | index;
actor = nullptr;
return kHitWall;
}
int setSprite(DBloodActor* num)
{
type = kHitSprite;
index = -1;
legacyVal = type | int(num - bloodActors);
actor = num;
return kHitSprite;
}
int setFromEngine(int value)
{
legacyVal = value;
type = value & kHitTypeMask;
if (type == 0) { index = -1; actor = nullptr; }
else if (type != kHitSprite) { index = value & kHitIndexMask; actor = nullptr; }
else { index = -1; actor = &bloodActors[value & kHitIndexMask]; }
return type;
}
};
END_BLD_NS

View file

@ -477,6 +477,11 @@ SEQINST* GetInstance(int type, int nXIndex)
return activeList.get(type, nXIndex);
}
SEQINST* GetInstance(DBloodActor* actor)
{
return activeList.get(3, actor->s().index);
}
void seqKill(int type, int nXIndex)
{
activeList.remove(type, nXIndex);
@ -650,7 +655,7 @@ void seqProcess(int nTicks)
short nSprite = (short)xsprite[index].reference;
assert(nSprite >= 0 && nSprite < kMaxSprites);
evKill(nSprite, SS_SPRITE);
if ((sprite[nSprite].hitag & kAttrRespawn) != 0 && (sprite[nSprite].zvel >= kDudeBase && sprite[nSprite].zvel < kDudeMax))
if ((sprite[nSprite].hitag & kAttrRespawn) != 0 && (sprite[nSprite].inittype >= kDudeBase && sprite[nSprite].inittype < kDudeMax))
evPost(nSprite, 3, gGameOptions.nMonsterRespawnTime, kCallbackRespawn);
else deletesprite(nSprite); // safe to not use actPostSprite here
}

View file

@ -98,6 +98,7 @@ inline int seqGetTile(SEQFRAME* pFrame)
int seqRegisterClient(void(*pClient)(int, int));
void seqPrecacheId(int id, int palette);
SEQINST* GetInstance(int a1, int a2);
SEQINST* GetInstance(DBloodActor* actor);
void UnlockInstance(SEQINST* pInst);
void seqSpawn(int a1, int a2, int a3, int a4 = -1);
void seqSpawn(int a1, DBloodActor* actor, int a4 = -1);