mirror of
https://github.com/DrBeef/Raze.git
synced 2025-01-18 15:11:51 +00:00
- More compact code for event redirection
- Fix demo desync - Fix MINGW compile warnings - Move custom start health from data4 to sysData2 in gModern maps - Proper respawn for custom dude # Conflicts: # source/blood/src/dude.cpp # source/blood/src/dude.h
This commit is contained in:
parent
64de30209b
commit
e3e805b24c
8 changed files with 172 additions and 162 deletions
|
@ -2469,7 +2469,7 @@ void actInit(bool bSaveLoad) {
|
|||
nnExtInitModernStuff(bSaveLoad);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
||||
switch (sprite[nSprite].type) {
|
||||
case kItemWeaponVoodooDoll:
|
||||
|
@ -2587,7 +2587,15 @@ void actInit(bool bSaveLoad) {
|
|||
#endif
|
||||
|
||||
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
|
||||
pXSprite->health = dudeGetStartHp(pSprite);
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
// add a way to set custom hp for every enemy - should work only if map just started and not loaded.
|
||||
if (!gModernMap || pXSprite->sysData2 <= 0) pXSprite->health = dudeInfo[nType].startHealth << 4;
|
||||
else pXSprite->health = ClipRange(pXSprite->sysData2 << 4, 1, 65535);
|
||||
#else
|
||||
pXSprite->health = dudeInfo[nType].startHealth << 4;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (gSysRes.Lookup(seqStartId, "SEQ")) seqSpawn(seqStartId, 3, pSprite->extra);
|
||||
|
|
|
@ -1647,7 +1647,9 @@ spritetype* genDudeSpawn(spritetype* pSprite, int nDist) {
|
|||
if (pSource->clipdist > 0) pDude->clipdist = pSource->clipdist;
|
||||
|
||||
// inherit custom hp settings
|
||||
pXDude->health = dudeGetStartHp(pDude);
|
||||
if (pXSource->data4 <= 0) pXDude->health = dudeInfo[nType - kDudeBase].startHealth << 4;
|
||||
else pXDude->health = ClipRange(pXSource->data4 << 4, 1, 65535);
|
||||
|
||||
|
||||
if (pSource->flags & kModernTypeFlag1) {
|
||||
switch (pSource->type) {
|
||||
|
@ -1740,8 +1742,8 @@ void genDudeTransform(spritetype* pSprite) {
|
|||
pXSprite->data1 = pXIncarnation->data1;
|
||||
pXSprite->data2 = pXIncarnation->data2;
|
||||
|
||||
pXSprite->sysData1 = pXIncarnation->data3;
|
||||
pXSprite->sysData2 = pXIncarnation->data4;
|
||||
pXSprite->sysData1 = pXIncarnation->data3; // soundBase id
|
||||
pXSprite->sysData2 = pXIncarnation->data4; // start hp
|
||||
|
||||
pXSprite->dudeGuard = pXIncarnation->dudeGuard;
|
||||
pXSprite->dudeDeaf = pXIncarnation->dudeDeaf;
|
||||
|
@ -1758,7 +1760,8 @@ void genDudeTransform(spritetype* pSprite) {
|
|||
pXIncarnation->key = pXIncarnation->dropMsg = 0;
|
||||
|
||||
// set hp
|
||||
pXSprite->health = dudeGetStartHp(pSprite);
|
||||
if (pXSprite->sysData2 <= 0) pXSprite->health = dudeInfo[pSprite->type - kDudeBase].startHealth << 4;
|
||||
else pXSprite->health = ClipRange(pXSprite->sysData2 << 4, 1, 65535);
|
||||
|
||||
int seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID;
|
||||
switch (pSprite->type) {
|
||||
|
|
|
@ -270,7 +270,9 @@ void Respawn(int nSprite) // 9
|
|||
pSprite->y = baseSprite[nSprite].y;
|
||||
pSprite->z = baseSprite[nSprite].z;
|
||||
pSprite->cstat |= 0x1101;
|
||||
pXSprite->health = dudeGetStartHp(pSprite);
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (!gModernMap || pXSprite->sysData2 <= 0) pXSprite->health = dudeInfo[pSprite->type - kDudeBase].startHealth << 4;
|
||||
else pXSprite->health = ClipRange(pXSprite->sysData2 << 4, 1, 65535);
|
||||
switch (pSprite->type) {
|
||||
default:
|
||||
pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist;
|
||||
|
@ -281,6 +283,12 @@ void Respawn(int nSprite) // 9
|
|||
seqSpawn(genDudeSeqStartId(pXSprite), 3, pSprite->extra, -1);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist;
|
||||
pXSprite->health = getDudeInfo(nType + kDudeBase)->startHealth << 4;
|
||||
if (gSysRes.Lookup(getDudeInfo(nType + kDudeBase)->seqStartID, "SEQ"))
|
||||
seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, 3, pSprite->extra, -1);
|
||||
#endif
|
||||
aiInitSprite(pSprite);
|
||||
pXSprite->key = 0;
|
||||
} else if (pSprite->type == kThingTNTBarrel) {
|
||||
|
|
|
@ -1570,7 +1570,7 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
|
|||
256, // angSpeed
|
||||
// 0,
|
||||
7, -1, 18, // nGibType
|
||||
64, 256, 256, 256, 256, 256, 256,
|
||||
128, 150, 128, 256, 128, 128, 128,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0
|
||||
|
@ -1732,20 +1732,4 @@ DUDEINFO gPlayerTemplate[4] =
|
|||
};
|
||||
|
||||
DUDEINFO fakeDudeInfo = {};
|
||||
|
||||
int dudeGetStartHp(spritetype* pDude) {
|
||||
|
||||
int hp = getDudeInfo(pDude->type)->startHealth << 4;
|
||||
if (!hp) {
|
||||
consoleSysMsg("Sprite #%d (type %d) is not a dude!", pDude->index, pDude->type);
|
||||
return hp;
|
||||
}
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
// add a way to set custom hp for every enemy (data4 moved to sysData2)
|
||||
else if (gModernMap && xsprite[pDude->extra].sysData2 > 0)
|
||||
hp = ClipRange(xsprite[pDude->extra].sysData2 << 4, 1, 65535);
|
||||
#endif
|
||||
return hp;
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -66,6 +66,4 @@ inline DUDEINFO *getDudeInfo(int const nType)
|
|||
return &fakeDudeInfo;
|
||||
}
|
||||
|
||||
int dudeGetStartHp(spritetype* pDude);
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -407,6 +407,7 @@ void nnExtInitModernStuff(bool bSaveLoad) {
|
|||
if (sysStat)
|
||||
ThrowError("Sprite #%d: System status list number %d detected!", pSprite->index, pSprite->statnum);
|
||||
*/
|
||||
|
||||
switch (pSprite->type) {
|
||||
case kModernRandomTX:
|
||||
case kModernSequentialTX:
|
||||
|
@ -729,7 +730,6 @@ void nnExtProcessSuperSprites() {
|
|||
|
||||
// process Debris sprites for movement
|
||||
if (gPhysSpritesCount > 0) {
|
||||
//viewSetSystemMessage("PHYS COUNT: %d", gPhysSpritesCount);
|
||||
for (int i = 0; i < gPhysSpritesCount; i++) {
|
||||
if (gPhysSpritesList[i] == -1) continue;
|
||||
else if (sprite[gPhysSpritesList[i]].statnum == kStatFree || (sprite[gPhysSpritesList[i]].flags & kHitagFree) != 0) {
|
||||
|
@ -1174,30 +1174,15 @@ void windGenStopWindOnSectors(XSPRITE* pXSource) {
|
|||
pXSector->windVel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (gEventRedirectsUsed) {
|
||||
int rx = 0; XSPRITE* pXRedir = eventRedirected(OBJ_SPRITE, pSource->extra, false);
|
||||
if (pXRedir == NULL) return;
|
||||
else if (txIsRanged(pXRedir)) {
|
||||
if (!channelRangeIsFine(pXRedir->data4 - pXRedir->data1)) return;
|
||||
for (rx = pXRedir->data1; rx <= pXRedir->data4; rx++) {
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SECTOR) continue;
|
||||
XSECTOR* pXSector = &xsector[sector[rxBucket[i].index].extra];
|
||||
if ((pXSector->state == 1 && !pXSector->windAlways) || (pSource->flags & kModernTypeFlag2))
|
||||
pXSector->windVel = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
if (!channelRangeIsFine((rx = GetDataVal(&sprite[pXRedir->reference], i)))) continue;
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SECTOR) continue;
|
||||
XSECTOR* pXSector = &xsector[sector[rxBucket[i].index].extra];
|
||||
if ((pXSector->state == 1 && !pXSector->windAlways) || (pSource->flags & kModernTypeFlag2))
|
||||
pXSector->windVel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// check redirected TX buckets
|
||||
int rx = -1; XSPRITE* pXRedir = NULL;
|
||||
while ((pXRedir = evrListRedirectors(OBJ_SPRITE, sprite[pXSource->reference].extra, pXRedir, &rx)) != NULL) {
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SECTOR) continue;
|
||||
XSECTOR* pXSector = &xsector[sector[rxBucket[i].index].extra];
|
||||
if ((pXSector->state == 1 && !pXSector->windAlways) || (pSource->flags & kModernTypeFlag2))
|
||||
pXSector->windVel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1238,7 +1223,6 @@ void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer) {
|
|||
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer) {
|
||||
|
||||
TRPLAYERCTRL* pCtrl = &gPlayerCtrl[pPlayer->nPlayer];
|
||||
//viewSetSystemMessage("OFF %d", pCtrl->qavScene.index);
|
||||
|
||||
pXSource->sysData1 = 0;
|
||||
pCtrl->qavScene.index = -1;
|
||||
|
@ -2204,6 +2188,9 @@ bool condCmp(int val, int arg1, int arg2, int comOp) {
|
|||
|
||||
// no extra comparison (val always = 0)?
|
||||
bool condCmpne(int arg1, int arg2, int comOp) {
|
||||
|
||||
UNREFERENCED_PARAMETER(arg2);
|
||||
|
||||
if (comOp & 0x2000) return (comOp & CSTAT_SPRITE_BLOCK) ? false : (!arg1); // blue sprite
|
||||
else if (comOp & 0x4000) return (comOp & CSTAT_SPRITE_BLOCK) ? false : (!arg1); // green sprite
|
||||
else return (!arg1);
|
||||
|
@ -2299,6 +2286,7 @@ bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH, bool RVR
|
|||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
|
@ -2376,7 +2364,7 @@ bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
|
||||
int var = -1;
|
||||
int cond = pXCond->data1 - kCondSectorBase; 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;
|
||||
condUnserialize(pXCond->targetX, &objType, &objIndex);
|
||||
|
@ -2445,7 +2433,7 @@ bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
|
||||
int var = -1;
|
||||
int cond = pXCond->data1 - kCondWallBase; 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;
|
||||
condUnserialize(pXCond->targetX, &objType, &objIndex);
|
||||
|
@ -2454,7 +2442,7 @@ bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
ThrowError("\nWall conditions:\nObject #%d (objType: %d) is not a wall!", objIndex, objType);
|
||||
|
||||
walltype* pWall = &wall[objIndex];
|
||||
XWALL* pXWall = (xwallRangeIsFine(pWall->extra)) ? &xwall[pWall->extra] : NULL;
|
||||
//XWALL* pXWall = (xwallRangeIsFine(pWall->extra)) ? &xwall[pWall->extra] : NULL;
|
||||
|
||||
if (cond < (kCondRange >> 1)) {
|
||||
switch (cond) {
|
||||
|
@ -2488,6 +2476,8 @@ bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
|
||||
bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
||||
|
||||
UNREFERENCED_PARAMETER(RVRS);
|
||||
|
||||
int var = -1; PLAYER* pPlayer = NULL;
|
||||
int cond = pXCond->data1 - kCondDudeBase; int arg1 = pXCond->data2;
|
||||
int arg2 = pXCond->data3; int arg3 = pXCond->data4;
|
||||
|
@ -2569,6 +2559,8 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
|
||||
bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
||||
|
||||
UNREFERENCED_PARAMETER(RVRS);
|
||||
|
||||
int var = -1; PLAYER* pPlayer = NULL; bool retn = false;
|
||||
int cond = pXCond->data1 - kCondSpriteBase; int arg1 = pXCond->data2;
|
||||
int arg2 = pXCond->data3; int arg3 = pXCond->data4;
|
||||
|
@ -2666,7 +2658,7 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
switch (cond) {
|
||||
default: break;
|
||||
case 50: // compare hp (in %)
|
||||
if (IsDudeSprite(pSpr)) var = dudeGetStartHp(pSpr);
|
||||
if (IsDudeSprite(pSpr)) var = (pXSpr->sysData2 > 0) ? ClipRange(pXSpr->sysData2 << 4, 1, 65535) : getDudeInfo(pSpr->type)->startHealth << 4;
|
||||
else if (condCmpne(arg1, arg2, cmpOp) && pSpr->type == kThingBloodChunks) return true;
|
||||
else if (pSpr->type >= kThingBase && pSpr->type < kThingMax)
|
||||
var = thingInfo[pSpr->type - kThingBase].startHealth << 4;
|
||||
|
@ -2711,7 +2703,6 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
|||
return condCmp(getSpriteMassBySize(pSpr), arg1, arg2, cmpOp); // mass of the sprite in a range?
|
||||
}
|
||||
} else {
|
||||
viewSetSystemMessage("!!!!!!!! %d", pSpr->type);
|
||||
switch (cond) {
|
||||
default: return false;
|
||||
case 50:
|
||||
|
@ -2832,6 +2823,7 @@ void modernTypeTrigger(int destObjType, int destObjIndex, EVENT event) {
|
|||
modernTypeSendCommand(pSource->index, pXSpr->txID, (COMMAND_ID)pXSource->command);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -2896,55 +2888,6 @@ void modernTypeTrigger(int destObjType, int destObjIndex, EVENT event) {
|
|||
}
|
||||
}
|
||||
|
||||
XSPRITE* eventRedirected(int objType, int objXIndex, bool byRx) {
|
||||
unsigned short id = 0;
|
||||
switch (objType) {
|
||||
case OBJ_SECTOR:
|
||||
if (!xsectRangeIsFine(objXIndex)) return NULL;
|
||||
id = (byRx) ? xsector[objXIndex].rxID : xsector[objXIndex].txID;
|
||||
break;
|
||||
case OBJ_SPRITE:
|
||||
if (!xspriRangeIsFine(objXIndex)) return NULL;
|
||||
id = (byRx) ? xsprite[objXIndex].rxID : xsprite[objXIndex].txID;
|
||||
break;
|
||||
case OBJ_WALL:
|
||||
if (!xwallRangeIsFine(objXIndex)) return NULL;
|
||||
id = (byRx) ? xwall[objXIndex].rxID : xwall[objXIndex].txID;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!byRx) {
|
||||
for (int i = bucketHead[id]; i < bucketHead[id + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SPRITE) continue;
|
||||
spritetype* pSpr = &sprite[rxBucket[i].index];
|
||||
if (!xspriRangeIsFine(pSpr->extra)) continue;
|
||||
switch (pSpr->type) {
|
||||
case kModernRandomTX:
|
||||
case kModernSequentialTX:
|
||||
XSPRITE* pXSpr = &xsprite[pSpr->extra];
|
||||
if (!(pSpr->flags & kModernTypeFlag2) || pXSpr->locked) continue;
|
||||
return pXSpr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int nSprite = headspritestat[kStatModernEventRedirector]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
||||
if (xspriRangeIsFine(sprite[nSprite].extra)) {
|
||||
XSPRITE* pXRedir = &xsprite[sprite[nSprite].extra];
|
||||
if (txIsRanged(pXRedir)) {
|
||||
if (id >= pXRedir->data1 && id <= pXRedir->data4) return pXRedir;
|
||||
} else {
|
||||
for (int i = 0; i <= 3; i++)
|
||||
if (id == GetDataVal(&sprite[pXRedir->reference], i)) return pXRedir;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// the following functions required for kModernDudeTargetChanger
|
||||
//---------------------------------------
|
||||
spritetype* aiFightGetTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode) {
|
||||
|
@ -3031,7 +2974,6 @@ bool aiFightDudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* p
|
|||
spritetype* pDude = &sprite[pXDude->reference];
|
||||
int dx = pTarget->x - pDude->x; int dy = pTarget->y - pDude->y;
|
||||
|
||||
//viewSetSystemMessage("zzzz");
|
||||
// check target
|
||||
if (approxDist(dx, dy) < pDudeInfo->seeDist) {
|
||||
int eyeAboveZ = pDudeInfo->eyeHeight * pDude->yrepeat << 2;
|
||||
|
@ -3116,27 +3058,13 @@ bool aiFightGetDudesForBattle(XSPRITE* pXSprite) {
|
|||
xsprite[sprite[rxBucket[i].index].extra].health > 0) return true;
|
||||
}
|
||||
|
||||
if (gEventRedirectsUsed) {
|
||||
int rx = 0; XSPRITE* pXRedir = eventRedirected(OBJ_SPRITE, sprite[pXSprite->reference].extra, false);
|
||||
if (pXRedir == NULL) return false;
|
||||
else if (txIsRanged(pXRedir)) {
|
||||
if (!channelRangeIsFine(pXRedir->data4 - pXRedir->data1)) return false;
|
||||
for (rx = pXRedir->data1; rx <= pXRedir->data4; rx++) {
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SPRITE) continue;
|
||||
else if (IsDudeSprite(&sprite[rxBucket[i].index]) &&
|
||||
xsprite[sprite[rxBucket[i].index].extra].health > 0) return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
if (!channelRangeIsFine((rx = GetDataVal(&sprite[pXRedir->reference], i)))) continue;
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SPRITE) continue;
|
||||
else if (IsDudeSprite(&sprite[rxBucket[i].index]) &&
|
||||
xsprite[sprite[rxBucket[i].index].extra].health > 0) return true;
|
||||
}
|
||||
}
|
||||
// check redirected TX buckets
|
||||
int rx = -1; XSPRITE* pXRedir = NULL;
|
||||
while ((pXRedir = evrListRedirectors(OBJ_SPRITE, sprite[pXSprite->reference].extra, pXRedir, &rx)) != NULL) {
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SPRITE) continue;
|
||||
else if (IsDudeSprite(&sprite[rxBucket[i].index]) &&
|
||||
xsprite[sprite[rxBucket[i].index].extra].health > 0) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -3442,11 +3370,9 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
|
|||
evPost(nSprite, 3, 0, kCmdOff);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pXSprite->txID > 0 /*&& pXSprite->data1 > 0 && pXSprite->data1 <= 4*/) {
|
||||
modernTypeSendCommand(nSprite, pXSprite->txID, (COMMAND_ID)pXSprite->command);
|
||||
if (pXSprite->busyTime > 0) evPost(nSprite, 3, pXSprite->busyTime, kCmdRepeat);
|
||||
}
|
||||
|
||||
modernTypeSendCommand(nSprite, pXSprite->txID, (COMMAND_ID)pXSprite->command);
|
||||
if (pXSprite->busyTime > 0) evPost(nSprite, 3, pXSprite->busyTime, kCmdRepeat);
|
||||
break;
|
||||
default:
|
||||
if (pXSprite->state == 0) evPost(nSprite, 3, 0, kCmdOn);
|
||||
|
@ -4099,6 +4025,7 @@ void useIncDecGen(XSPRITE* pXSource, short objType, int objIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
pXSource->sysData1 = data;
|
||||
setDataValueOfObject(objType, objIndex, dataIndex, data);
|
||||
}
|
||||
|
||||
|
@ -4196,11 +4123,10 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
|
|||
if (pBurnSource->extra >= 0) {
|
||||
if (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, &xsprite[pBurnSource->extra])) {
|
||||
pXSprite->burnTime = 0;
|
||||
|
||||
|
||||
// heal dude a bit in case of friendly fire
|
||||
int startHp = dudeGetStartHp(pSprite);
|
||||
int startHp = (pXSprite->sysData2 > 0) ? ClipRange(pXSprite->sysData2 << 4, 1, 65535) : pDudeInfo->startHealth << 4;
|
||||
if (pXSprite->health < startHp) actHealDude(pXSprite, receiveHp, startHp);
|
||||
|
||||
} else if (xsprite[pBurnSource->extra].health <= 0) {
|
||||
pXSprite->burnTime = 0;
|
||||
}
|
||||
|
@ -4266,11 +4192,11 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
|
|||
spritetype* pMate = pTarget; XSPRITE* pXMate = pXTarget;
|
||||
|
||||
// heal dude
|
||||
int startHp = dudeGetStartHp(pSprite);
|
||||
int startHp = (pXSprite->sysData2 > 0) ? ClipRange(pXSprite->sysData2 << 4, 1, 65535) : pDudeInfo->startHealth << 4;
|
||||
if (pXSprite->health < startHp) actHealDude(pXSprite, receiveHp, startHp);
|
||||
|
||||
// heal mate
|
||||
startHp = dudeGetStartHp(pMate);
|
||||
startHp = (pXMate->sysData2 > 0) ? ClipRange(pXMate->sysData2 << 4, 1, 65535) : getDudeInfo(pMate->type)->startHealth << 4;
|
||||
if (pXMate->health < startHp) actHealDude(pXMate, receiveHp, startHp);
|
||||
|
||||
if (pXMate->target > -1 && sprite[pXMate->target].extra >= 0) {
|
||||
|
@ -4750,44 +4676,114 @@ bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value) {
|
|||
}
|
||||
}
|
||||
|
||||
int listTx(XSPRITE* pXRedir, int tx) {
|
||||
if (txIsRanged(pXRedir)) {
|
||||
if (tx == -1) tx = pXRedir->data1;
|
||||
else if (tx < pXRedir->data4) tx++;
|
||||
else tx = -1;
|
||||
} else {
|
||||
if (tx == -1) {
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
if ((tx = GetDataVal(&sprite[pXRedir->reference], i)) <= 0) continue;
|
||||
else return tx;
|
||||
}
|
||||
} else {
|
||||
int saved = tx; bool savedFound = false;
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
tx = GetDataVal(&sprite[pXRedir->reference], i);
|
||||
if (savedFound && tx > 0) return tx;
|
||||
else if (tx != saved) continue;
|
||||
else savedFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
tx = -1;
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
XSPRITE* evrIsRedirector(int nSprite) {
|
||||
if (spriRangeIsFine(nSprite)) {
|
||||
switch (sprite[nSprite].type) {
|
||||
case kModernRandomTX:
|
||||
case kModernSequentialTX:
|
||||
if ((sprite[nSprite].flags & kModernTypeFlag2)
|
||||
&& xspriRangeIsFine(sprite[nSprite].extra) && !xsprite[sprite[nSprite].extra].locked) {
|
||||
return &xsprite[sprite[nSprite].extra];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XSPRITE* evrListRedirectors(int objType, int objXIndex, XSPRITE* pXRedir, int* tx) {
|
||||
if (!gEventRedirectsUsed) return NULL;
|
||||
else if (pXRedir && (*tx = listTx(pXRedir, *tx)) != -1)
|
||||
return pXRedir;
|
||||
|
||||
int id = 0;
|
||||
switch (objType) {
|
||||
case OBJ_SECTOR:
|
||||
if (!xsectRangeIsFine(objXIndex)) return NULL;
|
||||
id = xsector[objXIndex].txID;
|
||||
break;
|
||||
case OBJ_SPRITE:
|
||||
if (!xspriRangeIsFine(objXIndex)) return NULL;
|
||||
id = xsprite[objXIndex].txID;
|
||||
break;
|
||||
case OBJ_WALL:
|
||||
if (!xwallRangeIsFine(objXIndex)) return NULL;
|
||||
id = xwall[objXIndex].txID;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nIndex = (pXRedir) ? pXRedir->reference : -1; bool prevFound = false;
|
||||
for (int i = bucketHead[id]; i < bucketHead[id + 1]; i++) {
|
||||
if (rxBucket[i].type != OBJ_SPRITE) continue;
|
||||
XSPRITE* pXSpr = evrIsRedirector(rxBucket[i].index);
|
||||
if (!pXSpr) continue;
|
||||
else if (prevFound || nIndex == -1) { *tx = listTx(pXSpr, *tx); return pXSpr; }
|
||||
else if (nIndex != pXSpr->reference) continue;
|
||||
else prevFound = true;
|
||||
}
|
||||
|
||||
*tx = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this function checks if all TX objects have the same value
|
||||
bool incDecGoalValueIsReached(XSPRITE* pXSprite) {
|
||||
|
||||
char buffer[5]; sprintf(buffer, "%d", abs(pXSprite->data1)); int len = strlen(buffer); int rx = 0;
|
||||
XSPRITE* pXRedir = (gEventRedirectsUsed) ? eventRedirected(OBJ_SPRITE, sprite[pXSprite->reference].extra, false) : NULL;
|
||||
if (pXSprite->data3 != pXSprite->sysData1) return false;
|
||||
char buffer[5]; sprintf(buffer, "%d", abs(pXSprite->data1)); int len = strlen(buffer); int rx = -1;
|
||||
for (int i = bucketHead[pXSprite->txID]; i < bucketHead[pXSprite->txID + 1]; i++) {
|
||||
if (pXRedir && sprite[pXRedir->reference].index == (int) rxBucket[i].index) continue;
|
||||
if (rxBucket[i].type == OBJ_SPRITE && evrIsRedirector(rxBucket[i].index)) continue;
|
||||
for (int a = 0; a < len; a++) {
|
||||
if (getDataFieldOfObject(rxBucket[i].type, rxBucket[i].index, (buffer[a] - 52) + 4) != pXSprite->data3)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pXRedir == NULL) return true;
|
||||
else if (txIsRanged(pXRedir)) {
|
||||
if (!channelRangeIsFine(pXRedir->data4 - pXRedir->data1)) return false;
|
||||
for (rx = pXRedir->data1; rx <= pXRedir->data4; rx++) {
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
for (int a = 0; a < len; i++) {
|
||||
if (getDataFieldOfObject(rxBucket[i].type, rxBucket[i].index, (buffer[a] - 52) + 4) != pXSprite->data3)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
if (!channelRangeIsFine((rx = GetDataVal(&sprite[pXRedir->reference], i)))) continue;
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
for (int a = 0; a < len; a++) {
|
||||
if (getDataFieldOfObject(rxBucket[i].type, rxBucket[i].index, (buffer[a] - 52) + 4) != pXSprite->data3)
|
||||
return false;
|
||||
}
|
||||
XSPRITE* pXRedir = NULL; // check redirected TX buckets
|
||||
while ((pXRedir = evrListRedirectors(OBJ_SPRITE, sprite[pXSprite->reference].extra, pXRedir, &rx)) != NULL) {
|
||||
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) {
|
||||
for (int a = 0; a < len; a++) {
|
||||
if (getDataFieldOfObject(rxBucket[i].type, rxBucket[i].index, (buffer[a] - 52) + 4) != pXSprite->data3)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// this function can be called via sending numbered command to TX kChannelModernEndLevelCustom
|
||||
// it allows to set custom next level instead of taking it from INI file.
|
||||
void levelEndLevelCustom(int nLevel) {
|
||||
|
|
|
@ -328,7 +328,6 @@ void windGenStopWindOnSectors(XSPRITE* pXSource);
|
|||
int getSpriteMassBySize(spritetype* pSprite);
|
||||
bool ceilIsTooLow(spritetype* pSprite);
|
||||
void levelEndLevelCustom(int nLevel);
|
||||
XSPRITE* eventRedirected(int objType, int objXIndex, bool byRx);
|
||||
bool useCondition(XSPRITE* pXSource, EVENT event);
|
||||
bool condPush(XSPRITE* pXSprite, int objType, int objIndex);
|
||||
bool condRestore(XSPRITE* pXSprite);
|
||||
|
@ -339,6 +338,9 @@ bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS);
|
|||
bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS);
|
||||
bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS);
|
||||
void condUpdateObjectIndex(int objType, int oldIndex, int newIndex);
|
||||
XSPRITE* evrListRedirectors(int objType, int objXIndex, XSPRITE* pXRedir, int* tx);
|
||||
XSPRITE* evrIsRedirector(int nSprite);
|
||||
int listTx(XSPRITE* pXRedir, int tx);
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -332,8 +332,19 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
|
|||
spritetype *pSprite = &sprite[nSprite];
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap && modernTypeOperateSprite(nSprite, pSprite, pXSprite, event))
|
||||
if (gModernMap && modernTypeOperateSprite(nSprite, pSprite, pXSprite, event))
|
||||
return;
|
||||
switch (event.cmd) {
|
||||
case kCmdLock:
|
||||
pXSprite->locked = 1;
|
||||
return;
|
||||
case kCmdUnlock:
|
||||
pXSprite->locked = 0;
|
||||
return;
|
||||
case kCmdToggleLock:
|
||||
pXSprite->locked = pXSprite->locked ^ 1;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
switch (event.cmd) {
|
||||
case kCmdLock:
|
||||
|
|
Loading…
Reference in a new issue