mirror of
https://github.com/DrBeef/Raze.git
synced 2025-01-31 05:00:41 +00:00
- Player control: more strict rules for copying properties of xsprite
- Fix for custom health when respawning enemy - Fix for custom dude when respawning it - Conditions: added way to refresh sprite index in tracking conditions # Conflicts: # source/blood/src/actor.cpp # source/blood/src/aiunicult.cpp # source/blood/src/aiunicult.h # source/blood/src/dude.cpp # source/blood/src/dude.h
This commit is contained in:
parent
8b0da35cb8
commit
64de30209b
11 changed files with 241 additions and 122 deletions
|
@ -2469,7 +2469,7 @@ void actInit(bool bSaveLoad) {
|
||||||
nnExtInitModernStuff(bSaveLoad);
|
nnExtInitModernStuff(bSaveLoad);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
||||||
switch (sprite[nSprite].type) {
|
switch (sprite[nSprite].type) {
|
||||||
case kItemWeaponVoodooDoll:
|
case kItemWeaponVoodooDoll:
|
||||||
|
@ -2587,15 +2587,7 @@ void actInit(bool bSaveLoad) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
|
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->data4 <= 0) pXSprite->health = dudeInfo[nType].startHealth << 4;
|
|
||||||
else pXSprite->health = ClipRange(pXSprite->data4 << 4, 1, 65535);
|
|
||||||
#else
|
|
||||||
pXSprite->health = dudeInfo[nType].startHealth << 4;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gSysRes.Lookup(seqStartId, "SEQ")) seqSpawn(seqStartId, 3, pSprite->extra);
|
if (gSysRes.Lookup(seqStartId, "SEQ")) seqSpawn(seqStartId, 3, pSprite->extra);
|
||||||
|
@ -3239,26 +3231,28 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
|
||||||
seqSpawn(dudeInfo[nType].seqStartID+15, 3, nXSprite, nDudeToGibClient2);
|
seqSpawn(dudeInfo[nType].seqStartID+15, 3, nXSprite, nDudeToGibClient2);
|
||||||
break;
|
break;
|
||||||
#ifdef NOONE_EXTENSIONS
|
#ifdef NOONE_EXTENSIONS
|
||||||
case kDudeModernCustom:
|
case kDudeModernCustom: {
|
||||||
playGenDudeSound(pSprite, kGenDudeSndDeathNormal);
|
playGenDudeSound(pSprite, kGenDudeSndDeathNormal);
|
||||||
|
int dudeToGib = (actCheckRespawn(pSprite)) ? -1 : ((nSeq == 3) ? nDudeToGibClient2 : nDudeToGibClient1);
|
||||||
if (nSeq == 3) {
|
if (nSeq == 3) {
|
||||||
|
|
||||||
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
|
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
|
||||||
if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
|
if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
|
else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
|
else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else if (gSysRes.Lookup(pXSprite->data2 + nSeq, "SEQ"))seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
|
else if (gSysRes.Lookup(pXSprite->data2 + nSeq, "SEQ"))seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else seqSpawn(1 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
|
else seqSpawn(1 + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
|
seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
}
|
}
|
||||||
|
genDudePostDeath(pSprite, damageType, damage);
|
||||||
|
return;
|
||||||
|
|
||||||
pXSprite->txID = 0; // to avoid second trigger.
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case kDudeModernCustomBurning: {
|
case kDudeModernCustomBurning: {
|
||||||
playGenDudeSound(pSprite, kGenDudeSndDeathExplode);
|
playGenDudeSound(pSprite, kGenDudeSndDeathExplode);
|
||||||
|
int dudeToGib = (actCheckRespawn(pSprite)) ? -1 : nDudeToGibClient1;
|
||||||
damageType = DAMAGE_TYPE_3;
|
damageType = DAMAGE_TYPE_3;
|
||||||
|
|
||||||
if (Chance(0x4000)) {
|
if (Chance(0x4000)) {
|
||||||
|
@ -3270,11 +3264,12 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
|
||||||
}
|
}
|
||||||
|
|
||||||
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
|
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
|
||||||
if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
|
if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
|
else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
|
else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
else seqSpawn(1 + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
|
else seqSpawn(1 + pXSprite->data2, 3, nXSprite, dudeToGib);
|
||||||
break;
|
genDudePostDeath(pSprite, damageType, damage);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case kDudeBurningZombieAxe:
|
case kDudeBurningZombieAxe:
|
||||||
|
|
|
@ -1532,20 +1532,17 @@ void aiInitSprite(spritetype *pSprite)
|
||||||
DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra];
|
DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra];
|
||||||
pDudeExtra->at4 = 0;
|
pDudeExtra->at4 = 0;
|
||||||
pDudeExtra->at0 = 0;
|
pDudeExtra->at0 = 0;
|
||||||
|
|
||||||
switch (pSprite->type) {
|
switch (pSprite->type) {
|
||||||
#ifdef NOONE_EXTENSIONS
|
#ifdef NOONE_EXTENSIONS
|
||||||
case kDudeModernCustom: {
|
case kDudeModernCustom:
|
||||||
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1;
|
aiGenDudeInitSprite(pSprite, pXSprite);
|
||||||
pDudeExtraE->at8 = pDudeExtraE->at0 = 0;
|
genDudePrepare(pSprite, kGenDudePropertyAll);
|
||||||
aiGenDudeNewState(pSprite, &genDudeIdleL);
|
return;
|
||||||
genDudePrepare(pSprite);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kDudeModernCustomBurning:
|
case kDudeModernCustomBurning:
|
||||||
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
|
aiGenDudeInitSprite(pSprite, pXSprite);
|
||||||
pXSprite->burnTime = 1200;
|
return;
|
||||||
break;
|
#endif
|
||||||
#endif
|
|
||||||
case kDudeCultistTommy:
|
case kDudeCultistTommy:
|
||||||
case kDudeCultistShotgun:
|
case kDudeCultistShotgun:
|
||||||
case kDudeCultistTesla:
|
case kDudeCultistTesla:
|
||||||
|
|
|
@ -53,6 +53,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
|
|
||||||
|
#include "gib.h"
|
||||||
|
#include "aiburn.h"
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
static void genDudeAttack1(int, int);
|
static void genDudeAttack1(int, int);
|
||||||
static void punchCallback(int, int);
|
static void punchCallback(int, int);
|
||||||
|
@ -174,7 +177,6 @@ bool genDudeAdjustSlope(spritetype* pSprite, XSPRITE* pXSprite, int dist, int we
|
||||||
}
|
}
|
||||||
|
|
||||||
GENDUDEEXTRA* genDudeExtra(spritetype* pGenDude) {
|
GENDUDEEXTRA* genDudeExtra(spritetype* pGenDude) {
|
||||||
dassert(spriRangeIsFine(pGenDude->index));
|
|
||||||
return &gGenDudeExtra[pGenDude->index];
|
return &gGenDudeExtra[pGenDude->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1254,14 +1256,9 @@ XSPRITE* getNextIncarnation(XSPRITE* pXSprite) {
|
||||||
if (rxBucket[i].type != 3 || rxBucket[i].index == pXSprite->reference)
|
if (rxBucket[i].type != 3 || rxBucket[i].index == pXSprite->reference)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (sprite[rxBucket[i].index].statnum) {
|
if (sprite[rxBucket[i].index].statnum == kStatInactive)
|
||||||
case kStatDude:
|
|
||||||
case kStatInactive: // inactive (ambush) dudes
|
|
||||||
if (xsprite[sprite[rxBucket[i].index].extra].health > 0)
|
|
||||||
return &xsprite[sprite[rxBucket[i].index].extra];
|
return &xsprite[sprite[rxBucket[i].index].extra];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1650,9 +1647,7 @@ spritetype* genDudeSpawn(spritetype* pSprite, int nDist) {
|
||||||
if (pSource->clipdist > 0) pDude->clipdist = pSource->clipdist;
|
if (pSource->clipdist > 0) pDude->clipdist = pSource->clipdist;
|
||||||
|
|
||||||
// inherit custom hp settings
|
// inherit custom hp settings
|
||||||
if (pXSource->data4 <= 0) pXDude->health = dudeInfo[nType - kDudeBase].startHealth << 4;
|
pXDude->health = dudeGetStartHp(pDude);
|
||||||
else pXDude->health = ClipRange(pXSource->data4 << 4, 1, 65535);
|
|
||||||
|
|
||||||
|
|
||||||
if (pSource->flags & kModernTypeFlag1) {
|
if (pSource->flags & kModernTypeFlag1) {
|
||||||
switch (pSource->type) {
|
switch (pSource->type) {
|
||||||
|
@ -1720,7 +1715,7 @@ void genDudeTransform(spritetype* pSprite) {
|
||||||
// trigger dude death before transform
|
// trigger dude death before transform
|
||||||
trTriggerSprite(pSprite->index, pXSprite, kCmdOff);
|
trTriggerSprite(pSprite->index, pXSprite, kCmdOff);
|
||||||
|
|
||||||
pSprite->type = pIncarnation->type;
|
pSprite->type = pSprite->inittype = pIncarnation->type;
|
||||||
pSprite->flags = pIncarnation->flags;
|
pSprite->flags = pIncarnation->flags;
|
||||||
pSprite->pal = pIncarnation->pal;
|
pSprite->pal = pIncarnation->pal;
|
||||||
pSprite->shade = pIncarnation->shade;
|
pSprite->shade = pIncarnation->shade;
|
||||||
|
@ -1735,17 +1730,18 @@ void genDudeTransform(spritetype* pSprite) {
|
||||||
pXSprite->busyTime = pXIncarnation->busyTime;
|
pXSprite->busyTime = pXIncarnation->busyTime;
|
||||||
pXSprite->waitTime = pXIncarnation->waitTime;
|
pXSprite->waitTime = pXIncarnation->waitTime;
|
||||||
|
|
||||||
|
// inherit respawn properties
|
||||||
|
pXSprite->respawn = pXIncarnation->respawn;
|
||||||
|
pXSprite->respawnPending = pXIncarnation->respawnPending;
|
||||||
|
|
||||||
pXSprite->burnTime = 0;
|
pXSprite->burnTime = 0;
|
||||||
pXSprite->burnSource = -1;
|
pXSprite->burnSource = -1;
|
||||||
|
|
||||||
pXSprite->data1 = pXIncarnation->data1;
|
pXSprite->data1 = pXIncarnation->data1;
|
||||||
pXSprite->data2 = pXIncarnation->data2;
|
pXSprite->data2 = pXIncarnation->data2;
|
||||||
|
|
||||||
// if incarnation is active dude, it's sndStartId will be stored in sysData1, otherwise it will be data3
|
pXSprite->sysData1 = pXIncarnation->data3;
|
||||||
if (pIncarnation->statnum == kStatDude && pIncarnation->type == kDudeModernCustom) pXSprite->sysData1 = pXIncarnation->sysData1;
|
pXSprite->sysData2 = pXIncarnation->data4;
|
||||||
else pXSprite->sysData1 = pXIncarnation->data3;
|
|
||||||
|
|
||||||
pXSprite->data4 = pXIncarnation->data4;
|
|
||||||
|
|
||||||
pXSprite->dudeGuard = pXIncarnation->dudeGuard;
|
pXSprite->dudeGuard = pXIncarnation->dudeGuard;
|
||||||
pXSprite->dudeDeaf = pXIncarnation->dudeDeaf;
|
pXSprite->dudeDeaf = pXIncarnation->dudeDeaf;
|
||||||
|
@ -1762,8 +1758,7 @@ void genDudeTransform(spritetype* pSprite) {
|
||||||
pXIncarnation->key = pXIncarnation->dropMsg = 0;
|
pXIncarnation->key = pXIncarnation->dropMsg = 0;
|
||||||
|
|
||||||
// set hp
|
// set hp
|
||||||
if (pXSprite->data4 <= 0) pXSprite->health = dudeInfo[pSprite->type - kDudeBase].startHealth << 4;
|
pXSprite->health = dudeGetStartHp(pSprite);
|
||||||
else pXSprite->health = ClipRange(pXSprite->data4 << 4, 1, 65535);
|
|
||||||
|
|
||||||
int seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID;
|
int seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID;
|
||||||
switch (pSprite->type) {
|
switch (pSprite->type) {
|
||||||
|
@ -1793,8 +1788,10 @@ void genDudeTransform(spritetype* pSprite) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
pXIncarnation->triggerOn = triggerOn;
|
||||||
|
pXIncarnation->triggerOff = triggerOff;
|
||||||
|
|
||||||
// remove the incarnation in case if non-locked
|
/*// remove the incarnation in case if non-locked
|
||||||
if (pXIncarnation->locked == 0) {
|
if (pXIncarnation->locked == 0) {
|
||||||
pXIncarnation->txID = pIncarnation->type = 0;
|
pXIncarnation->txID = pIncarnation->type = 0;
|
||||||
actPostSprite(pIncarnation->index, kStatFree);
|
actPostSprite(pIncarnation->index, kStatFree);
|
||||||
|
@ -1802,7 +1799,7 @@ void genDudeTransform(spritetype* pSprite) {
|
||||||
} else {
|
} else {
|
||||||
pXIncarnation->triggerOn = triggerOn;
|
pXIncarnation->triggerOn = triggerOn;
|
||||||
pXIncarnation->triggerOff = triggerOff;
|
pXIncarnation->triggerOff = triggerOff;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2159,5 +2156,40 @@ bool genDudePrepare(spritetype* pSprite, int propId) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void genDudePostDeath(spritetype* pSprite, DAMAGE_TYPE damageType, int damage) {
|
||||||
|
if (damageType == DAMAGE_TYPE_3) {
|
||||||
|
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
if (pDudeInfo->nGibType[i] > -1)
|
||||||
|
GibSprite(pSprite, (GIBTYPE)pDudeInfo->nGibType[i], NULL, NULL);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
fxSpawnBlood(pSprite, damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
gKillMgr.AddKill(pSprite);
|
||||||
|
|
||||||
|
pSprite->type = kThingBloodChunks;
|
||||||
|
actPostSprite(pSprite->index, kStatThing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aiGenDudeInitSprite(spritetype* pSprite, XSPRITE* pXSprite) {
|
||||||
|
switch (pSprite->type) {
|
||||||
|
case kDudeModernCustom: {
|
||||||
|
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1;
|
||||||
|
pDudeExtraE->at8 = pDudeExtraE->at0 = 0;
|
||||||
|
aiGenDudeNewState(pSprite, &genDudeIdleL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kDudeModernCustomBurning:
|
||||||
|
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
|
||||||
|
pXSprite->burnTime = 1200;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSprite->flags = 15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
END_BLD_NS
|
END_BLD_NS
|
||||||
|
|
|
@ -163,6 +163,7 @@ struct GENDUDEEXTRA {
|
||||||
unsigned short weaponType;
|
unsigned short weaponType;
|
||||||
unsigned short baseDispersion;
|
unsigned short baseDispersion;
|
||||||
unsigned short slaveCount; // how many dudes is summoned
|
unsigned short slaveCount; // how many dudes is summoned
|
||||||
|
//unsigned short incarnationsCount;
|
||||||
signed short nLifeLeech; // spritenum of dropped dude's leech
|
signed short nLifeLeech; // spritenum of dropped dude's leech
|
||||||
signed short slave[kGenDudeMaxSlaves]; // index of the ones dude is summon
|
signed short slave[kGenDudeMaxSlaves]; // index of the ones dude is summon
|
||||||
signed short dmgControl[kDamageMax]; // depends of current weapon, drop armor item, sprite yrepeat and surface type
|
signed short dmgControl[kDamageMax]; // depends of current weapon, drop armor item, sprite yrepeat and surface type
|
||||||
|
@ -218,8 +219,10 @@ int genDudeSeqStartId(XSPRITE* pXSprite);
|
||||||
int getRangeAttackDist(spritetype* pSprite, int minDist = 1200, int maxDist = 80000);
|
int getRangeAttackDist(spritetype* pSprite, int minDist = 1200, int maxDist = 80000);
|
||||||
int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp);
|
int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp);
|
||||||
void scaleDamage(XSPRITE* pXSprite);
|
void scaleDamage(XSPRITE* pXSprite);
|
||||||
bool genDudePrepare(spritetype* pSprite, int propId = kGenDudePropertyAll);
|
bool genDudePrepare(spritetype* pSprite, int propId);
|
||||||
void genDudeUpdate(spritetype* pSprite);
|
void genDudeUpdate(spritetype* pSprite);
|
||||||
bool genDudeAdjustSlope(spritetype* pSprite, XSPRITE* pXSprite, int dist, int weaponType, int by = 64);
|
bool genDudeAdjustSlope(spritetype* pSprite, XSPRITE* pXSprite, int dist, int weaponType, int by = 64);
|
||||||
|
void genDudePostDeath(spritetype* pSprite, DAMAGE_TYPE damageType, int damage);
|
||||||
|
void aiGenDudeInitSprite(spritetype* pSprite, XSPRITE* pXSprite);
|
||||||
#endif
|
#endif
|
||||||
END_BLD_NS
|
END_BLD_NS
|
||||||
|
|
|
@ -46,6 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "triggers.h"
|
#include "triggers.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "nnexts.h"
|
#include "nnexts.h"
|
||||||
|
#include "aiunicult.h"
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
@ -269,10 +270,17 @@ void Respawn(int nSprite) // 9
|
||||||
pSprite->y = baseSprite[nSprite].y;
|
pSprite->y = baseSprite[nSprite].y;
|
||||||
pSprite->z = baseSprite[nSprite].z;
|
pSprite->z = baseSprite[nSprite].z;
|
||||||
pSprite->cstat |= 0x1101;
|
pSprite->cstat |= 0x1101;
|
||||||
pSprite->clipdist = getDudeInfo(nType+kDudeBase)->clipdist;
|
pXSprite->health = dudeGetStartHp(pSprite);
|
||||||
pXSprite->health = getDudeInfo(nType+kDudeBase)->startHealth<<4;
|
switch (pSprite->type) {
|
||||||
if (gSysRes.Lookup(getDudeInfo(nType+kDudeBase)->seqStartID, "SEQ"))
|
default:
|
||||||
seqSpawn(getDudeInfo(nType+kDudeBase)->seqStartID, 3, pSprite->extra, -1);
|
pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist;
|
||||||
|
if (gSysRes.Lookup(getDudeInfo(nType + kDudeBase)->seqStartID, "SEQ"))
|
||||||
|
seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, 3, pSprite->extra, -1);
|
||||||
|
break;
|
||||||
|
case kDudeModernCustom:
|
||||||
|
seqSpawn(genDudeSeqStartId(pXSprite), 3, pSprite->extra, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
aiInitSprite(pSprite);
|
aiInitSprite(pSprite);
|
||||||
pXSprite->key = 0;
|
pXSprite->key = 0;
|
||||||
} else if (pSprite->type == kThingTNTBarrel) {
|
} else if (pSprite->type == kThingTNTBarrel) {
|
||||||
|
@ -719,28 +727,6 @@ void callbackCondition(int nSprite) {
|
||||||
|
|
||||||
TRCONDITION* pCond = &gCondition[pXSprite->sysData1];
|
TRCONDITION* pCond = &gCondition[pXSprite->sysData1];
|
||||||
for (int i = 0; i < pCond->length; i++) {
|
for (int i = 0; i < pCond->length; i++) {
|
||||||
/*if (pCond->obj[i].type == OBJ_SPRITE) {
|
|
||||||
spritetype* pObj = &sprite[pCond->obj[i].index];
|
|
||||||
XSPRITE* pXObj = (xspriRangeIsFine(pObj->extra)) ? &xsprite[pObj->extra] : NULL;
|
|
||||||
if (gGameOptions.nGameType != 0) {
|
|
||||||
if (pObj->type != pObj->inittype && pObj->inittype >= kDudePlayer1 && pObj->inittype <= kDudePlayer8) {
|
|
||||||
PLAYER* pPlayer = getPlayerById(pObj->inittype);
|
|
||||||
if (pPlayer) {
|
|
||||||
pCond->obj[i].index = pPlayer->pSprite->index;
|
|
||||||
viewSetSystemMessage("RESET INDEX");
|
|
||||||
} else {
|
|
||||||
viewSetSystemMessage("FAILED %d", pCond->obj[i].index);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if (pObj->flags & kHitagRespawn)
|
|
||||||
//viewSetSystemMessage("TYPE: %d ON RESPAWN", pObj->type);
|
|
||||||
//if (pObj->flags & kHitagFree) {
|
|
||||||
// viewSetSystemMessage("TYPE: %d IS FREE", pObj->type);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}*/
|
|
||||||
EVENT evn; evn.index = pCond->obj[i].index; evn.type = pCond->obj[i].type;
|
EVENT evn; evn.index = pCond->obj[i].index; evn.type = pCond->obj[i].type;
|
||||||
evn.cmd = pCond->obj[i].cmd; evn.funcID = kCallbackCondition;
|
evn.cmd = pCond->obj[i].cmd; evn.funcID = kCallbackCondition;
|
||||||
useCondition(pXSprite, evn);
|
useCondition(pXSprite, evn);
|
||||||
|
|
|
@ -112,8 +112,9 @@ struct XSPRITE {
|
||||||
unsigned int stateTimer : 16; // ai timer
|
unsigned int stateTimer : 16; // ai timer
|
||||||
AISTATE* aiState; // ai
|
AISTATE* aiState; // ai
|
||||||
#ifdef NOONE_EXTENSIONS
|
#ifdef NOONE_EXTENSIONS
|
||||||
signed int sysData1 : 16; // used to keep here various system data, so user can't change it in map editor
|
signed int sysData1: 32; // used to keep here various system data, so user can't change it in map editor
|
||||||
unsigned int physAttr : 12; // currently used by additional physics sprites to keep it's attributes.
|
signed int sysData2: 32; //
|
||||||
|
unsigned int physAttr : 32; // currently used by additional physics sprites to keep it's attributes.
|
||||||
#endif
|
#endif
|
||||||
signed int scale; // used for scaling SEQ size on sprites
|
signed int scale; // used for scaling SEQ size on sprites
|
||||||
|
|
||||||
|
|
|
@ -1733,4 +1733,19 @@ DUDEINFO gPlayerTemplate[4] =
|
||||||
|
|
||||||
DUDEINFO fakeDudeInfo = {};
|
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
|
END_BLD_NS
|
||||||
|
|
|
@ -66,4 +66,6 @@ inline DUDEINFO *getDudeInfo(int const nType)
|
||||||
return &fakeDudeInfo;
|
return &fakeDudeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dudeGetStartHp(spritetype* pDude);
|
||||||
|
|
||||||
END_BLD_NS
|
END_BLD_NS
|
||||||
|
|
|
@ -380,6 +380,33 @@ void nnExtInitModernStuff(bool bSaveLoad) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
/*// copy custom start health to avoid overwrite by kThingBloodChunks
|
||||||
|
if (IsDudeSprite(pSprite))
|
||||||
|
pXSprite->sysData2 = pXSprite->data4;
|
||||||
|
|
||||||
|
bool sysStat = false;
|
||||||
|
switch (pSprite->statnum) {
|
||||||
|
case kStatModernDudeTargetChanger:
|
||||||
|
if (pSprite->type != kModernDudeTargetChanger) sysStat = true;
|
||||||
|
break;
|
||||||
|
case kStatModernCondition:
|
||||||
|
if (pSprite->type != kModernCondition && pSprite->type != kModernConditionFalse) sysStat = true;
|
||||||
|
break;
|
||||||
|
case kStatModernEventRedirector:
|
||||||
|
if (pSprite->type != kModernRandomTX && pSprite->type != kModernSequentialTX) sysStat = true;
|
||||||
|
break;
|
||||||
|
case kStatModernPlayerLinker:
|
||||||
|
if (pSprite->type != kModernPlayerControl) sysStat = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (pSprite->statnum < kStatModernBase || pSprite->statnum >= kStatModernMax) break;
|
||||||
|
ThrowError("Sprite status list number %d on sprite #%d is in a range of system reserved (%d - %d)!", pSprite->index, pSprite->statnum, kStatModernBase, kStatModernMax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysStat)
|
||||||
|
ThrowError("Sprite #%d: System status list number %d detected!", pSprite->index, pSprite->statnum);
|
||||||
|
*/
|
||||||
switch (pSprite->type) {
|
switch (pSprite->type) {
|
||||||
case kModernRandomTX:
|
case kModernRandomTX:
|
||||||
case kModernSequentialTX:
|
case kModernSequentialTX:
|
||||||
|
@ -412,10 +439,43 @@ void nnExtInitModernStuff(bool bSaveLoad) {
|
||||||
case kModernThingTNTProx:
|
case kModernThingTNTProx:
|
||||||
pXSprite->Proximity = true;
|
pXSprite->Proximity = true;
|
||||||
break;
|
break;
|
||||||
|
case kDudeModernCustom:
|
||||||
|
if (pXSprite->txID <= 0) break;
|
||||||
|
for (int nSprite = headspritestat[kStatDude], found = 0; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
||||||
|
XSPRITE* pXSpr = &xsprite[sprite[nSprite].extra];
|
||||||
|
if (pXSpr->rxID != pXSprite->txID) continue;
|
||||||
|
else if (found) ThrowError("\nCustom dude (TX ID %d):\nOnly one incarnation allowed per channel!", pXSprite->txID);
|
||||||
|
changespritestat(nSprite, kStatInactive);
|
||||||
|
nSprite = headspritestat[kStatDude];
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kModernPlayerControl:
|
||||||
|
if (pXSprite->command != kCmdLink) break;
|
||||||
|
else if (pXSprite->data1 < 1 || pXSprite->data1 >= kMaxPlayers)
|
||||||
|
ThrowError("\nPlayer Control (SPRITE #%d):\nPlayer out of a range (data1 = %d)", pSprite->index, pXSprite->data1);
|
||||||
|
if (pXSprite->rxID && pXSprite->rxID != kChannelLevelStart)
|
||||||
|
ThrowError("\nPlayer Control (SPRITE #%d) with Link command should have no RX ID!", pSprite->index, pXSprite->data1);
|
||||||
|
|
||||||
|
if (pXSprite->txID && pXSprite->txID < kChannelUser)
|
||||||
|
ThrowError("\nPlayer Control (SPRITE #%d):\nTX ID should be in range of %d and %d!", pSprite->index, kChannelUser, kChannelMax);
|
||||||
|
|
||||||
|
// only one linker per player allowed
|
||||||
|
for (int nSprite = headspritestat[kStatModernPlayerLinker]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
||||||
|
XSPRITE* pXCtrl = &xsprite[sprite[nSprite].extra];
|
||||||
|
if (pXSprite->data1 == pXCtrl->data1)
|
||||||
|
ThrowError("\nPlayer Control (SPRITE #%d):\nPlayer %d already linked with different player control sprite #%d!", pSprite->index, pXSprite->data1, nSprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
pXSprite->rxID = kChannelLevelStart;
|
||||||
|
pXSprite->triggerOnce = true;
|
||||||
|
pXSprite->state = pXSprite->restState = pXSprite->waitTime = 0;
|
||||||
|
changespritestat(pSprite->index, kStatModernPlayerLinker);
|
||||||
|
break;
|
||||||
case kModernCondition:
|
case kModernCondition:
|
||||||
if (pXSprite->waitTime > 0 && pXSprite->busyTime > 0) {
|
if (pXSprite->waitTime > 0 && pXSprite->busyTime > 0) {
|
||||||
pXSprite->busyTime += ((pXSprite->waitTime * 60) / 10); pXSprite->waitTime = 0;
|
pXSprite->busyTime += ((pXSprite->waitTime * 60) / 10); 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->Decoupled = false; // must go through operateSprite always
|
pXSprite->Decoupled = false; // must go through operateSprite always
|
||||||
|
@ -430,7 +490,7 @@ void nnExtInitModernStuff(bool bSaveLoad) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the following trigger flags are sensless to have together
|
// the following trigger flags are senseless to have together
|
||||||
if ((pXSprite->Touch && (pXSprite->Proximity || pXSprite->Sight) && pXSprite->DudeLockout)
|
if ((pXSprite->Touch && (pXSprite->Proximity || pXSprite->Sight) && pXSprite->DudeLockout)
|
||||||
|| (pXSprite->Touch && pXSprite->Proximity && !pXSprite->Sight)) pXSprite->Touch = false;
|
|| (pXSprite->Touch && pXSprite->Proximity && !pXSprite->Sight)) pXSprite->Touch = false;
|
||||||
|
|
||||||
|
@ -1194,8 +1254,11 @@ void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer) {
|
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition) {
|
||||||
|
|
||||||
|
// save player's sprite index to use it later with conditions
|
||||||
|
pXSource->sysData1 = pPlayer->nSprite;
|
||||||
|
|
||||||
pPlayer->pXSprite->txID = pXSource->txID;
|
pPlayer->pXSprite->txID = pXSource->txID;
|
||||||
pPlayer->pXSprite->command = kCmdToggle;
|
pPlayer->pXSprite->command = kCmdToggle;
|
||||||
pPlayer->pXSprite->triggerOn = pXSource->triggerOn;
|
pPlayer->pXSprite->triggerOn = pXSource->triggerOn;
|
||||||
|
@ -1224,17 +1287,19 @@ void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer) {
|
||||||
pPlayer->pXSprite->dropMsg = pXSource->dropMsg;
|
pPlayer->pXSprite->dropMsg = pXSource->dropMsg;
|
||||||
|
|
||||||
// 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
|
||||||
for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++) {
|
if (checkCondition && pXSource->txID >= kChannelUser) {
|
||||||
if (sprite[rxBucket[i].index].type == kModernCondition) {
|
for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++) {
|
||||||
|
if (sprite[rxBucket[i].index].type != kModernCondition) continue;
|
||||||
|
|
||||||
XSPRITE* pXCond = &xsprite[sprite[rxBucket[i].index].extra];
|
XSPRITE* pXCond = &xsprite[sprite[rxBucket[i].index].extra];
|
||||||
if (pXCond->busyTime <= 0) continue;
|
if (pXCond->busyTime <= 0) continue;
|
||||||
|
|
||||||
// search for player control sprite and replace it with actual player sprite
|
|
||||||
TRCONDITION* pCond = &gCondition[pXCond->sysData1];
|
TRCONDITION* pCond = &gCondition[pXCond->sysData1];
|
||||||
|
// 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].index != pXSource->reference) continue;
|
if (pCond->obj[k].type != OBJ_SPRITE || pCond->obj[k].index != pXSource->reference) continue;
|
||||||
pCond->obj[k].index = pPlayer->nSprite;
|
pCond->obj[k].index = pPlayer->nSprite;
|
||||||
pCond->obj[k].cmd = kCmdToggle;
|
pCond->obj[k].cmd = pPlayer->pXSprite->command;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2434,12 +2499,9 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
||||||
ThrowError("\nDude conditions:\nObject #%d (objType: %d) is not a dude!", objIndex, objType);
|
ThrowError("\nDude conditions:\nObject #%d (objType: %d) is not a dude!", objIndex, objType);
|
||||||
|
|
||||||
spritetype* pSpr = &sprite[objIndex];
|
spritetype* pSpr = &sprite[objIndex];
|
||||||
if (!xspriRangeIsFine(sprite[objIndex].extra)) {
|
if (!xspriRangeIsFine(sprite[objIndex].extra))
|
||||||
// TO-DO: must search for respawned player / enemy
|
|
||||||
// there is currently serials for old sprite
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
XSPRITE* pXSpr = &xsprite[pSpr->extra];
|
XSPRITE* pXSpr = &xsprite[pSpr->extra];
|
||||||
if (pXSpr->health <= 0 || pSpr->type == kThingBloodChunks) return false;
|
if (pXSpr->health <= 0 || pSpr->type == kThingBloodChunks) return false;
|
||||||
else if (cond < (kCondRange >> 1)) {
|
else if (cond < (kCondRange >> 1)) {
|
||||||
|
@ -2604,11 +2666,11 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
default: break;
|
default: break;
|
||||||
case 50: // compare hp (in %)
|
case 50: // compare hp (in %)
|
||||||
if (IsDudeSprite(pSpr)) var = ((pXSpr->data4 <= 0) ? getDudeInfo(pSpr->type)->startHealth : pXSpr->data4) << 4;
|
if (IsDudeSprite(pSpr)) var = dudeGetStartHp(pSpr);
|
||||||
else if (condCmpne(arg1, arg2, cmpOp) && pSpr->type == kThingBloodChunks) return true;
|
else if (condCmpne(arg1, arg2, cmpOp) && pSpr->type == kThingBloodChunks) return true;
|
||||||
else if (pSpr->type >= kThingBase && pSpr->type < kThingMax)
|
else if (pSpr->type >= kThingBase && pSpr->type < kThingMax)
|
||||||
var = thingInfo[pSpr->type - kThingBase].startHealth << 4;
|
var = thingInfo[pSpr->type - kThingBase].startHealth << 4;
|
||||||
|
|
||||||
return condCmp((100 * pXSpr->health) / ClipLow(var, 1), arg1, arg2, cmpOp);
|
return condCmp((100 * 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;
|
||||||
|
@ -2649,6 +2711,7 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
||||||
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?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
viewSetSystemMessage("!!!!!!!! %d", pSpr->type);
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
default: return false;
|
default: return false;
|
||||||
case 50:
|
case 50:
|
||||||
|
@ -2662,6 +2725,20 @@ bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this updates index of object in all tracking conditions
|
||||||
|
void condUpdateObjectIndex(int objType, int oldIndex, int newIndex) {
|
||||||
|
for (int i = 0; i <= gTrackingCondsCount; i++) {
|
||||||
|
TRCONDITION* pCond = &gCondition[i];
|
||||||
|
for (int k = 0; k < pCond->length; k++) {
|
||||||
|
if (pCond->obj[k].type != objType || pCond->obj[k].index != oldIndex) continue;
|
||||||
|
pCond->obj[k].index = newIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool valueIsBetween(int val, int min, int max) {
|
bool valueIsBetween(int val, int min, int max) {
|
||||||
return (val > min && val < max);
|
return (val > min && val < max);
|
||||||
}
|
}
|
||||||
|
@ -3451,7 +3528,9 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
|
||||||
/// !!! COMMANDS OF THE CURRENT SPRITE, NOT OF THE EVENT !!! ///
|
/// !!! COMMANDS OF THE CURRENT SPRITE, NOT OF THE EVENT !!! ///
|
||||||
switch (pXSprite->command) {
|
switch (pXSprite->command) {
|
||||||
case kCmdLink: // copy properties of sprite to player
|
case kCmdLink: // copy properties of sprite to player
|
||||||
trPlayerCtrlLink(pXSprite, pPlayer);
|
if (pXSprite->isTriggered) break;
|
||||||
|
trPlayerCtrlLink(pXSprite, pPlayer, true);
|
||||||
|
pXSprite->isTriggered = true;
|
||||||
break;
|
break;
|
||||||
case kCmdNumberic: // player life form
|
case kCmdNumberic: // player life form
|
||||||
if (pXSprite->data2 < kModeHuman || pXSprite->data2 > kModeHumanShrink) break;
|
if (pXSprite->data2 < kModeHuman || pXSprite->data2 > kModeHumanShrink) break;
|
||||||
|
@ -4119,10 +4198,9 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
|
||||||
pXSprite->burnTime = 0;
|
pXSprite->burnTime = 0;
|
||||||
|
|
||||||
// heal dude a bit in case of friendly fire
|
// heal dude a bit in case of friendly fire
|
||||||
if (pXSprite->data4 > 0 && pXSprite->health < pXSprite->data4)
|
int startHp = dudeGetStartHp(pSprite);
|
||||||
actHealDude(pXSprite, receiveHp, pXSprite->data4);
|
if (pXSprite->health < startHp) actHealDude(pXSprite, receiveHp, startHp);
|
||||||
else if (pXSprite->health < pDudeInfo->startHealth)
|
|
||||||
actHealDude(pXSprite, receiveHp, pDudeInfo->startHealth);
|
|
||||||
} else if (xsprite[pBurnSource->extra].health <= 0) {
|
} else if (xsprite[pBurnSource->extra].health <= 0) {
|
||||||
pXSprite->burnTime = 0;
|
pXSprite->burnTime = 0;
|
||||||
}
|
}
|
||||||
|
@ -4188,19 +4266,12 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
|
||||||
spritetype* pMate = pTarget; XSPRITE* pXMate = pXTarget;
|
spritetype* pMate = pTarget; XSPRITE* pXMate = pXTarget;
|
||||||
|
|
||||||
// heal dude
|
// heal dude
|
||||||
if (pXSprite->data4 > 0 && pXSprite->health < pXSprite->data4)
|
int startHp = dudeGetStartHp(pSprite);
|
||||||
actHealDude(pXSprite, receiveHp, pXSprite->data4);
|
if (pXSprite->health < startHp) actHealDude(pXSprite, receiveHp, startHp);
|
||||||
else if (pXSprite->health < pDudeInfo->startHealth)
|
|
||||||
actHealDude(pXSprite, receiveHp, pDudeInfo->startHealth);
|
|
||||||
|
|
||||||
// heal mate
|
// heal mate
|
||||||
if (pXMate->data4 > 0 && pXMate->health < pXMate->data4)
|
startHp = dudeGetStartHp(pMate);
|
||||||
actHealDude(pXMate, receiveHp, pXMate->data4);
|
if (pXMate->health < startHp) actHealDude(pXMate, receiveHp, startHp);
|
||||||
else {
|
|
||||||
DUDEINFO* pTDudeInfo = getDudeInfo(pMate->type);
|
|
||||||
if (pXMate->health < pTDudeInfo->startHealth)
|
|
||||||
actHealDude(pXMate, receiveHp, pTDudeInfo->startHealth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pXMate->target > -1 && sprite[pXMate->target].extra >= 0) {
|
if (pXMate->target > -1 && sprite[pXMate->target].extra >= 0) {
|
||||||
pTarget = &sprite[pXMate->target];
|
pTarget = &sprite[pXMate->target];
|
||||||
|
|
|
@ -64,9 +64,12 @@ BEGIN_BLD_NS
|
||||||
#define kCondRange 100
|
#define kCondRange 100
|
||||||
// modern statnums
|
// modern statnums
|
||||||
enum {
|
enum {
|
||||||
|
kStatModernBase = 20,
|
||||||
kStatModernDudeTargetChanger = 20,
|
kStatModernDudeTargetChanger = 20,
|
||||||
kStatModernCondition = 21,
|
kStatModernCondition = 21,
|
||||||
kStatModernEventRedirector = 22,
|
kStatModernEventRedirector = 22,
|
||||||
|
kStatModernPlayerLinker = 23,
|
||||||
|
kStatModernMax = 64,
|
||||||
};
|
};
|
||||||
|
|
||||||
// modern sprite types
|
// modern sprite types
|
||||||
|
@ -277,7 +280,7 @@ void useRandomTx(XSPRITE* pXSource, COMMAND_ID cmd, bool setState);
|
||||||
bool txIsRanged(XSPRITE* pXSource);
|
bool txIsRanged(XSPRITE* pXSource);
|
||||||
void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernSend);
|
void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernSend);
|
||||||
// ------------------------------------------------------------------------- //
|
// ------------------------------------------------------------------------- //
|
||||||
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer);
|
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);
|
||||||
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer);
|
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer);
|
||||||
|
@ -331,11 +334,11 @@ bool condPush(XSPRITE* pXSprite, int objType, int objIndex);
|
||||||
bool condRestore(XSPRITE* pXSprite);
|
bool condRestore(XSPRITE* pXSprite);
|
||||||
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);
|
||||||
/*bool condCmpr(int val, int min, int max, int cmpOp);*/
|
|
||||||
bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH, bool RVRS);
|
bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH, bool RVRS);
|
||||||
bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS);
|
bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS);
|
||||||
bool condCheckWall(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);
|
bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH, bool RVRS);
|
||||||
|
void condUpdateObjectIndex(int objType, int oldIndex, int newIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -650,7 +650,7 @@ void playerStart(int nPlayer, int bNewLevel)
|
||||||
PLAYER* pPlayer = &gPlayer[nPlayer];
|
PLAYER* pPlayer = &gPlayer[nPlayer];
|
||||||
GINPUT* pInput = &pPlayer->input;
|
GINPUT* pInput = &pPlayer->input;
|
||||||
ZONE* pStartZone = NULL;
|
ZONE* pStartZone = NULL;
|
||||||
|
|
||||||
// normal start position
|
// normal start position
|
||||||
if (gGameOptions.nGameType <= 1)
|
if (gGameOptions.nGameType <= 1)
|
||||||
pStartZone = &gStartZone[nPlayer];
|
pStartZone = &gStartZone[nPlayer];
|
||||||
|
@ -775,6 +775,20 @@ void playerStart(int nPlayer, int bNewLevel)
|
||||||
pPlayer->weaponQav = -1;
|
pPlayer->weaponQav = -1;
|
||||||
#ifdef NOONE_EXTENSIONS
|
#ifdef NOONE_EXTENSIONS
|
||||||
playerQavSceneReset(pPlayer); // reset qav scene
|
playerQavSceneReset(pPlayer); // reset qav scene
|
||||||
|
|
||||||
|
// we must check if properties of old pPlayer->pXSprite was
|
||||||
|
// changed with kModernPlayerControl and copy it to the new x-sprite
|
||||||
|
if (gModernMap && gGameOptions.nGameType != 0) {
|
||||||
|
|
||||||
|
for (int nSprite = headspritestat[kStatModernPlayerLinker]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
|
||||||
|
XSPRITE* pXCtrl = &xsprite[sprite[nSprite].extra];
|
||||||
|
if (pXCtrl->data1 != pPlayer->nPlayer + 1) continue;
|
||||||
|
int nSpriteOld = pXCtrl->sysData1;
|
||||||
|
trPlayerCtrlLink(pXCtrl, pPlayer, false);
|
||||||
|
if (pPlayer->pXSprite->txID >= kChannelUser && gTrackingCondsCount > 0)
|
||||||
|
condUpdateObjectIndex(OBJ_SPRITE, nSpriteOld, pXCtrl->sysData1);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
pPlayer->hand = 0;
|
pPlayer->hand = 0;
|
||||||
pPlayer->nWaterPal = 0;
|
pPlayer->nWaterPal = 0;
|
||||||
|
|
Loading…
Reference in a new issue