diff --git a/source/blood/src/actor.cpp b/source/blood/src/actor.cpp index 5382ec633..e450853e4 100644 --- a/source/blood/src/actor.cpp +++ b/source/blood/src/actor.cpp @@ -7125,8 +7125,9 @@ void actFireVector(spritetype *pShooter, int a2, int a3, int a4, int a5, int a6, actBurnSprite(actSpriteIdToOwnerId(nShooter), &xsprite[nXSprite], pVectorData->at11); } - if (pSprite->index >= kThingBase && pSprite->index < kThingMax) - actPostSprite(pSprite->index, 4); // if it was a thing, return it's statnum back + if (pSprite->type >= kThingBase && pSprite->type < kThingMax) + changespritestat(pSprite->index, 4); + //actPostSprite(pSprite->index, 4); // if it was a thing, return it's statnum back } } @@ -7739,10 +7740,13 @@ void debrisConcuss(int nOwner, int listIndex, int x, int y, int z, int dmg) { yvel[pSprite->xvel] += mulscale16(t, dy); zvel[pSprite->xvel] += mulscale16(t, dz); } + + + if (pSprite->type >= kThingBase && pSprite->type < kThingMax) + //actPostSprite(pSprite->index, 4); // !!! (does not working here) if it was a thing, return it's statnum back + changespritestat(pSprite->index, 4); } - if (pSprite->index >= kThingBase && pSprite->index < kThingMax) - actPostSprite(pSprite->index, 4); // if it was a thing, return it's statnum back actDamageSprite(nOwner, pSprite, DAMAGE_TYPE_3, dmg); return; diff --git a/source/blood/src/common_game.h b/source/blood/src/common_game.h index 1ee49a5f3..a72234eed 100644 --- a/source/blood/src/common_game.h +++ b/source/blood/src/common_game.h @@ -137,6 +137,7 @@ void QuitGame(void); #define kPhysFalling 0x0004 // currently in z-motion // additional physics attributes for debris sprites #define kPhysDebrisFly 0x0008 // *debris* affected by negative gravity (fly instead of falling, DO NOT mess with kHitagAutoAim) +#define kPhysDebrisSwim 0x0016 // *debris* can swim underwater (instead of drowning) #define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons #define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions diff --git a/source/blood/src/triggers.cpp b/source/blood/src/triggers.cpp index cfbf55503..c96f30cf0 100644 --- a/source/blood/src/triggers.cpp +++ b/source/blood/src/triggers.cpp @@ -979,6 +979,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT a3) fallthrough__; case COMMAND_ID_21: if (pXSprite->txID <= 0 || !getDudesForTargetChg(pXSprite)) { + freeAllTargets(pXSprite); evPost(nSprite, 3, 0, COMMAND_ID_0); break; } else { @@ -3039,15 +3040,28 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) { /* 3: go to idle state if no targets in sight and ignore player(s) always - */ /* 4: follow player(s) when no targets in sight, attack targets if any in sight - */ - if (type != 3 || !IsDudeSprite(&sprite[nDest]) || sprite[nDest].statnum != 6) return; + if (type != 3) return; + else if (!IsDudeSprite(&sprite[nDest]) && sprite[nDest].statnum != 6 && xsprite[sprite[nDest].extra].data3 != 0) { + switch (sprite[nDest].type) { // can be dead dude turned in gib + // make current target and all other dudes not attack this dude anymore + case 425: + case 426: + xsprite[sprite[nDest].extra].data3 = 0; + freeTargets(nDest); + return; + default: + return; + } + } + spritetype* pSprite = &sprite[nDest]; XSPRITE* pXSprite = &xsprite[pSprite->extra]; spritetype* pTarget = NULL; XSPRITE* pXTarget = NULL; int receiveHp = 33 + Random(33); DUDEINFO* pDudeInfo = &dudeInfo[pSprite->type - kDudeBase]; int matesPerEnemy = 1; // dude is burning? if (pXSprite->burnTime > 0 && pXSprite->burnSource >= 0 && pXSprite->burnSource < kMaxSprites) { - if (!IsBurningDude(pSprite)) - { + if (IsBurningDude(pSprite)) actKillDude(pSource->xvel, pSprite, DAMAGE_TYPE_0, 65535); + else { spritetype* pBurnSource = &sprite[pXSprite->burnSource]; if (pBurnSource->extra >= 0) { if (pXSource->data2 == 1 && isMateOf(pXSprite, &xsprite[pBurnSource->extra])) { @@ -3064,10 +3078,12 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) { } } } - else { - actKillDude(pSource->xvel, pSprite, DAMAGE_TYPE_0, 65535); - return; - } + } + + // dude is dead? + if (pXSprite->health <= 0) { + pSprite->type = 426; actPostSprite(pSprite->xvel, 4); // turn it in gib + return; } spritetype* pPlayer = targetIsPlayer(pXSprite); @@ -3411,9 +3427,9 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) { /* - data4 = sector floor / sprite / wall cstat - */ int old = -1; switch (type) { + // for sectors - case 6: - { + case 6: { XSECTOR* pXSector = &xsector[sector[nDest].extra]; if (pXSource->data1 == 0) pXSector->Underwater = false; @@ -3431,8 +3447,9 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) { if (valueIsBetween(pXSource->data4, -1, 65535)) sector[nDest].floorstat = pXSource->data4; - break; } + break; + // for sprites case 3: { @@ -3580,10 +3597,10 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) { } } - break; + break; + // for walls case 0: { - walltype* pWall = &wall[nDest]; if (valueIsBetween(pXSource->data3, -1, 32767)) pWall->hitag = pXSource->data3; @@ -3609,9 +3626,9 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) { } } - } - break; + break; + } } } @@ -3755,6 +3772,29 @@ void activateDudes(int rx) { } } + +// by NoOne: this function sets target to -1 for all dudes that hunting for nSprite +void freeTargets(int nSprite) { + for (int nTarget = headspritestat[6]; nTarget >= 0; nTarget = nextspritestat[nTarget]) { + if (!IsDudeSprite(&sprite[nTarget]) || sprite[nTarget].extra < 0) continue; + else if (xsprite[sprite[nTarget].extra].target == nSprite) + aiSetTarget(&xsprite[sprite[nTarget].extra], sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z); + } + + return; +} + +// by NoOne: this function sets target to -1 for all targets that hunting for dudes affected by selected kModernDudeTargetChanger +void freeAllTargets(XSPRITE* pXSource) { + if (pXSource->txID <= 0) return; + for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++) { + if (rxBucket[i].type == 3 && sprite[rxBucket[i].index].extra >= 0) + freeTargets(rxBucket[i].index); + } + + return; +} + bool affectedByTargetChg(XSPRITE* pXDude) { if (pXDude->rxID <= 0 || pXDude->locked == 1) return false; for (int nSprite = headspritestat[kStatGDXDudeTargetChanger]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { diff --git a/source/blood/src/triggers.h b/source/blood/src/triggers.h index 0b26f46a3..7c7329b41 100644 --- a/source/blood/src/triggers.h +++ b/source/blood/src/triggers.h @@ -62,6 +62,8 @@ bool isAnnoyingUnit(spritetype* pDude); bool unitCanFly(spritetype* pDude); bool isMeleeUnit(spritetype* pDude); void activateDudes(int rx); +void freeTargets(int nSprite); +void freeAllTargets(XSPRITE* pXSource); bool affectedByTargetChg(XSPRITE* pXDude); int getDataFieldOfObject(int objType, int objIndex, int dataIndex); bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value);