- Rewrite true random once again

- Fix Custom Dude genIdle aistate
- Fix grown and shrink races
- Fix qav scene was not able to stop if sprite is locked
- Fix stupid error in gDefaultJump array

# Conflicts:
#	source/blood/src/actor.cpp
#	source/blood/src/view.cpp
This commit is contained in:
Grind Core 2019-12-11 22:48:42 +03:00 committed by Christoph Oelckers
parent 1eb50414ab
commit ec782a28de
12 changed files with 144 additions and 178 deletions

View file

@ -3109,24 +3109,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
int nXSprite = pSprite->extra;
dassert(nXSprite > 0);
XSPRITE *pXSprite = &xsprite[pSprite->extra];
// kMaxSprites - 1 = custom dude had once life leech
if (pSprite->owner >= 0 && pSprite->owner != (kMaxSprites - 1)) {
switch (sprite[pSprite->owner].type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
for (int i = 0; i <= gGameOptions.nDifficulty; i++) {
if (!IsDudeSprite(pSprite) || gGenDudeExtra[pSprite->owner].slave[i] == pSprite->index || pXSprite->health <= 0) {
gGenDudeExtra[pSprite->owner].slave[i] = -1;
gGenDudeExtra[pSprite->owner].slaveCount = ClipRange(gGenDudeExtra[pSprite->owner].slaveCount - 1, 0, gGameOptions.nDifficulty + 1);
break;
}
}
break;
}
}
switch (pSprite->type) {
case kDudeModernCustom: {
@ -7355,43 +7338,55 @@ int GetDataVal(spritetype* pSprite, int data) {
}
// tries to get random data field of sprite
int GetRandDataVal(int *rData) {
dassert(rData != NULL);
int random = 0, a = 0; int first = -1; int maxRetries = 10;
// randomize only in case if at least 2 data fields are not empty
for (int i = 0; i < 4; i++) {
if (rData[i] <= 0 && a++ > 1) return -1;
else if (first == -1) first = rData[i];
}
int GetRandDataVal(XSPRITE* pXSprite, int randType) {
if (pXSprite == NULL) return -1;
int random = 0; int bad = 0; int maxRetries = 10;
int rData[4];
rData[0] = pXSprite->data1; rData[2] = pXSprite->data3;
rData[1] = pXSprite->data2; rData[3] = pXSprite->data4;
// randomize only in case if at least 2 data fields fits.
for (int i = 0; i < 4; i++) {
switch (randType) {
case kRandomizeItem:
if (rData[i] >= kItemWeaponBase && rData[i] < kItemMax) break;
else bad++;
break;
case kRandomizeDude:
if (rData[i] >= kDudeBase && rData[i] < kDudeMax) break;
else bad++;
break;
case kRandomizeTX:
if (rData[i] > kChannelZero && rData[i] < kChannelUserMax) break;
else bad++;
break;
default:
bad++;
break;
}
}
if (bad < 3) {
// try randomize few times
while (maxRetries > 0) {
// use true random only for single player mode, otherwise use Blood's default one.
random = (gGameOptions.nGameType == 0 && !VanillaMode() && !DemoRecordStatus()) ? STD_Random(0, 3) : Random(3);
if (rData[random] > 0) return rData[random];
else maxRetries--;
if (rData[random] > 0) return rData[random];
maxRetries--;
}
}
// if nothing, get first found data value from top
return first;
return -1;
}
// this function drops random item using random pickup generator(s)
spritetype* DropRandomPickupObject(spritetype* pSprite, short prevItem) {
spritetype* pSprite2 = NULL; int rData[4]; int selected = -1;
if (xspriData2Array(pSprite->extra,rData)) {
// randomize only in case if at least 2 data fields fits.
for (int i = 0; i <= 3; i++)
if (rData[i] < kItemWeaponBase || rData[i] >= kItemMax)
rData[i] = 0;
int maxRetries = 9;
while ((selected = GetRandDataVal(rData)) == prevItem) if (maxRetries-- <= 0) break;
spritetype* DropRandomPickupObject(spritetype* pSource, short prevItem) {
spritetype* pSprite2 = NULL; int selected = -1; int maxRetries = 9;
if (xspriRangeIsFine(pSource->extra)) {
XSPRITE* pXSource = &xsprite[pSource->extra];
while ((selected = GetRandDataVal(pXSource, kRandomizeItem)) == prevItem) if (maxRetries-- <= 0) break;
if (selected > 0) {
spritetype* pSource = pSprite; XSPRITE* pXSource = &xsprite[pSource->extra];
pSprite2 = actDropObject(pSprite, selected);
pSprite2 = actDropObject(pSource, selected);
if (pSprite2 != NULL) {
pXSource->dropMsg = pSprite2->type; // store dropped item type in dropMsg
@ -7415,23 +7410,17 @@ spritetype* DropRandomPickupObject(spritetype* pSprite, short prevItem) {
}
}
}
}
return pSprite2;
}
// this function spawns random dude using dudeSpawn
spritetype* spawnRandomDude(spritetype* pSprite) {
spritetype* pSprite2 = NULL; int rData[4]; int selected = -1;
if (xspriData2Array(pSprite->extra, rData)) {
// randomize only in case if at least 2 data fields fits.
for (int i = 0; i <= 3; i++)
if (rData[i] < kDudeBase || rData[i] >= kDudeMax)
rData[i] = 0;
if ((selected = GetRandDataVal(rData)) > 0)
pSprite2 = actSpawnDude(pSprite, selected, -1, 0);
spritetype* spawnRandomDude(spritetype* pSource) {
spritetype* pSprite2 = NULL; int selected = -1;
if (xspriRangeIsFine(pSource->extra)) {
XSPRITE* pXSource = &xsprite[pSource->extra];
if ((selected = GetRandDataVal(pXSource, kRandomizeDude)) > 0)
pSprite2 = actSpawnDude(pSource, selected, -1, 0);
}
return pSprite2;
}

View file

@ -68,6 +68,12 @@ enum VECTOR_TYPE {
kVectorMax,
};
enum {
kRandomizeItem = 0,
kRandomizeDude = 1,
kRandomizeTX = 2,
};
struct THINGINFO
{
short startHealth;
@ -269,7 +275,7 @@ void MakeSplash(spritetype *pSprite, XSPRITE *pXSprite);
spritetype* DropRandomPickupObject(spritetype* pSprite, short prevItem);
spritetype* spawnRandomDude(spritetype* pSprite);
int GetDataVal(spritetype* pSprite, int data);
int GetRandDataVal(int *rData);
int GetRandDataVal(XSPRITE* pXSprite, int randType);
bool sfxPlayMissileSound(spritetype* pSprite, int missileId);
bool sfxPlayVectorSound(spritetype* pSprite, int vectorId);
spritetype* actSpawnCustomDude(spritetype* pSprite, int nDist);

View file

@ -79,7 +79,15 @@ AISTATE genRecoil = {kAiStateRecoil, 5, -1, 20, NULL, NULL, NULL, &genIdle };
int dword_138BB0[5] = {0x2000, 0x4000, 0x8000, 0xa000, 0xe000};
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite) {
aiNewState(pSprite, pXSprite, &genIdle);
switch (pSprite->type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
aiGenDudeNewState(pSprite, &genIdle);
break;
default:
aiNewState(pSprite, pXSprite, &genIdle);
break;
}
}
bool sub_5BDA8(spritetype *pSprite, int nSeq)

View file

@ -237,18 +237,16 @@ static void genDudeAttack1(int, int nXIndex) {
consoleSysMsg("nIndex >= 0 && nIndex < kMaxSprites");
return;
}
int dx, dy, dz; spritetype* pSprite = &sprite[nSprite];
xvel[pSprite->index] = yvel[pSprite->index] = 0;
short dispersion = gGenDudeExtra[nSprite].baseDispersion;
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
short dispersion = pExtra->baseDispersion;
if (inDuck(pXSprite->aiState))
dispersion = ClipLow(dispersion >> 1, kGenDudeMinDispesion);
//short dispersion = 1;
short curWeapon = gGenDudeExtra[nSprite].curWeapon; short weaponType = gGenDudeExtra[nSprite].weaponType;
if (weaponType == kGenDudeWeaponHitscan) {
if (pExtra->weaponType == kGenDudeWeaponHitscan) {
dx = Cos(pSprite->ang) >> 16; dy = Sin(pSprite->ang) >> 16; dz = gDudeSlope[nXIndex];
// dispersal modifiers here in case if non-melee enemy
@ -256,42 +254,40 @@ static void genDudeAttack1(int, int nXIndex) {
dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion);
}
actFireVector(pSprite, 0, 0, dx, dy, dz,(VECTOR_TYPE)curWeapon);
actFireVector(pSprite, 0, 0, dx, dy, dz,(VECTOR_TYPE)pExtra->curWeapon);
if (!playGenDudeSound(pSprite, kGenDudeSndAttackNormal))
sfxPlayVectorSound(pSprite, curWeapon);
sfxPlayVectorSound(pSprite, pExtra->curWeapon);
} else if (weaponType == kGenDudeWeaponSummon) {
} else if (pExtra->weaponType == kGenDudeWeaponSummon) {
spritetype* pSpawned = NULL; int dist = pSprite->clipdist << 4;
short slaveCnt = gGenDudeExtra[pSprite->index].slaveCount;
if (slaveCnt <= gGameOptions.nDifficulty && (pSpawned = actSpawnDude(pSprite, curWeapon, dist + Random(dist), 0)) != NULL) {
pSpawned->owner = nSprite;
if (pSpawned->extra > -1) {
xsprite[pSpawned->extra].target = pXSprite->target;
if (pXSprite->target > -1)
aiActivateDude(pSpawned, &xsprite[pSpawned->extra]);
}
gKillMgr.sub_263E0(1);
gGenDudeExtra[pSprite->index].slave[slaveCnt] = pSpawned->index;
gGenDudeExtra[pSprite->index].slaveCount++;
if (pExtra->slaveCount <= gGameOptions.nDifficulty) {
if ((pSpawned = actSpawnDude(pSprite, pExtra->curWeapon, dist + Random(dist), 0)) != NULL) {
pSpawned->owner = nSprite;
if (!playGenDudeSound(pSprite, kGenDudeSndAttackNormal))
sfxPlay3DSoundCP(pSprite, 379, 1, 0, 0x10000 - Random3(0x3000));
if (xspriRangeIsFine(pSpawned->extra)) {
xsprite[pSpawned->extra].target = pXSprite->target;
if (pXSprite->target > -1)
aiActivateDude(pSpawned, &xsprite[pSpawned->extra]);
}
gKillMgr.sub_263E0(1);
pExtra->slave[pExtra->slaveCount++] = pSpawned->index;
if (!playGenDudeSound(pSprite, kGenDudeSndAttackNormal))
sfxPlay3DSoundCP(pSprite, 379, 1, 0, 0x10000 - Random3(0x3000));
}
}
} else if (weaponType == kGenDudeWeaponMissile) {
} else if (pExtra->weaponType == kGenDudeWeaponMissile) {
dx = Cos(pSprite->ang) >> 16; dy = Sin(pSprite->ang) >> 16; dz = gDudeSlope[nXIndex];
// dispersal modifiers here
dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion >> 1);
actFireMissile(pSprite, 0, 0, dx, dy, dz, curWeapon);
actFireMissile(pSprite, 0, 0, dx, dy, dz, pExtra->curWeapon);
if (!playGenDudeSound(pSprite, kGenDudeSndAttackNormal))
sfxPlayMissileSound(pSprite, curWeapon);
sfxPlayMissileSound(pSprite, pExtra->curWeapon);
}
}
@ -1124,14 +1120,14 @@ void aiGenDudeNewState(spritetype* pSprite, AISTATE* pAIState) {
}
pXSprite->stateTimer = pAIState->stateTicks; pXSprite->aiState = pAIState;
int seqStartId = pXSprite->data2;
if (pAIState->seqId >= 0 && gSysRes.Lookup((seqStartId += pAIState->seqId), "SEQ"))
seqSpawn(seqStartId, 3, pSprite->extra, pAIState->funcId);
int stateSeq = pXSprite->data2 + pAIState->seqId;
if (pAIState->seqId >= 0 && gSysRes.Lookup(stateSeq, "SEQ")) {
seqSpawn(stateSeq, 3, pSprite->extra, pAIState->funcId);
}
if (pAIState->enterFunc)
pAIState->enterFunc(pSprite, pXSprite);
}
@ -1665,41 +1661,38 @@ void updateTargetOfLeech(spritetype* pSprite) {
}
void updateTargetOfSlaves(spritetype* pSprite) {
if (!(pSprite->extra >= 0 && pSprite->extra < kMaxXSprites)) {
consoleSysMsg("pSprite->extra >= 0 && pSprite->extra < kMaxXSprites");
if (!xspriRangeIsFine(pSprite->extra)) {
consoleSysMsg("!xspriRangeIsFine(pSprite->extra)");
return;
}
XSPRITE* pXSprite = &xsprite[pSprite->extra];
short* slave = gGenDudeExtra[pSprite->index].slave;
XSPRITE* pXSprite = &xsprite[pSprite->extra];
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); short* slave = pExtra->slave;
spritetype* pTarget = (pXSprite->target >= 0 && IsDudeSprite(&sprite[pXSprite->target])) ? &sprite[pXSprite->target] : NULL;
XSPRITE* pXTarget = (pTarget != NULL && pTarget->extra >= 0 && xsprite[pTarget->extra].health > 0) ? &xsprite[pTarget->extra] : NULL;
XSPRITE* pXTarget = (pTarget != NULL && xspriRangeIsFine(pTarget->extra) && xsprite[pTarget->extra].health > 0) ? &xsprite[pTarget->extra] : NULL;
int newCnt = pExtra->slaveCount;
for (int i = 0; i <= gGameOptions.nDifficulty; i++) {
if (slave[i] >= 0) {
if (spriRangeIsFine(slave[i])) {
spritetype* pSlave = &sprite[slave[i]];
if (!IsDudeSprite(pSlave) || pSlave->extra < 0 || xsprite[pSlave->extra].health < 0) {
slave[i] = -1;
if (!IsDudeSprite(pSlave) || !xspriRangeIsFine(pSlave->extra) || xsprite[pSlave->extra].health < 0) {
slave[i] = pSlave->owner = -1; newCnt--;
continue;
}
XSPRITE* pXSlave = &xsprite[pSlave->index];
if (pXTarget == NULL) aiSetTarget(pXSlave, pSprite->x, pSprite->y, pSprite->z); // try return to master
else if (pXSprite->target != pXSlave->target)
aiSetTarget(pXSlave, pXSprite->target);
// check if slave attacking another slave
if (pXSlave->target >= 0) {
if (sprite[pXSlave->target].owner == pSprite->index)
aiSetTarget(pXSlave, pSprite->x, pSprite->y, pSprite->z); // try return to master
if (pXTarget != NULL) {
if (pXSprite->target != pXSlave->target) aiSetTarget(pXSlave, pXSprite->target);
// check if slave have proper target
if (!spriRangeIsFine(pXSlave->target) || sprite[pXSlave->target].owner == pSprite->index)
aiSetTarget(pXSlave, pSprite->x, pSprite->y, pSprite->z);
} else {
// try return to master
aiSetTarget(pXSlave, pSprite->x, pSprite->y, pSprite->z);
aiSetTarget(pXSlave, pSprite->x, pSprite->y, pSprite->z); // try return to master
}
}
}
pExtra->slaveCount = newCnt;
}
short inDodge(AISTATE* aiState) {
@ -1933,7 +1926,7 @@ bool genDudePrepare(spritetype* pSprite, int propId) {
case kGenDudeSeqMoveD:
case kGenDudeSeqDeathBurn2:
case kGenDudeSeqIdleW:
continue;
break;
case kGenDudeSeqReserved3:
case kGenDudeSeqReserved4:
case kGenDudeSeqReserved5:
@ -1967,8 +1960,8 @@ bool genDudePrepare(spritetype* pSprite, int propId) {
case kGenDudePropertySlaves:
pExtra->slaveCount = 0; memset(pExtra->slave, -1, sizeof(pExtra->slave));
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (sprite[nSprite].owner != pSprite->xvel) continue;
else if (!IsDudeSprite(&sprite[nSprite]) || sprite[nSprite].extra < 0 || xsprite[sprite[nSprite].extra].health <= 0) {
if (sprite[nSprite].owner != pSprite->index) continue;
else if (!IsDudeSprite(&sprite[nSprite]) || !xspriRangeIsFine(sprite[nSprite].extra) || xsprite[sprite[nSprite].extra].health <= 0) {
sprite[nSprite].owner = -1;
continue;
}

View file

@ -178,8 +178,9 @@ struct GENDUDEEXTRA {
extern GENDUDEEXTRA gGenDudeExtra[];
inline GENDUDEEXTRA* genDudeExtra(spritetype* pSprite) {
return &gGenDudeExtra[pSprite->index];
inline GENDUDEEXTRA* genDudeExtra(spritetype* pGenDude) {
dassert(spriRangeIsFine(pGenDude->index));
return &gGenDudeExtra[pGenDude->index];
}
XSPRITE* getNextIncarnation(XSPRITE* pXSprite);

View file

@ -67,6 +67,7 @@ kChannelRemoteBomb5,
kChannelRemoteBomb6,
kChannelRemoteBomb7,
kChannelUser = 100,
kChannelUserMax = 1024,
kChannelMax = 4096,
};

View file

@ -917,23 +917,12 @@ int picHeight(short nPic, short repeat) {
return ClipLow((tilesiz[nPic].y * repeat) << 2, 0);
}
bool xspriData2Array(int nXSprite, int* rData) {
if (xspriRangeIsFine(nXSprite) && rData) {
rData[0] = xsprite[nXSprite].data1; rData[2] = xsprite[nXSprite].data3;
rData[1] = xsprite[nXSprite].data2; rData[3] = xsprite[nXSprite].data4;
return true;
}
return false;
}
// by NoOne: used for better randomness in single player
int STD_Random(int a, int b) {
std::default_random_engine rng;
rng.seed(std::random_device()());
std::default_random_engine stdRandom;
stdRandom.seed(std::random_device()());
std::uniform_int_distribution<int> dist_a_b(a, b);
return dist_a_b(rng);
return dist_a_b(stdRandom);
}
END_BLD_NS

View file

@ -85,7 +85,6 @@ int GetClosestSectors(int nSector, int x, int y, int nDist, short *pSectors, cha
int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, short *pSectors, char *pSectBit, short *a8);
int picWidth(short nPic, short repeat);
int picHeight(short nPic, short repeat);
bool xspriData2Array(int nXSprite, int* rData);
int STD_Random(int a, int b);
END_BLD_NS

View file

@ -133,20 +133,20 @@ int gDefaultAccel[] = {
// shrink human
10384, 2108, 2192, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// grown human
19384, 5608, 11192 // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
19384, 5608, 11192, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
};
int gDefaultJumpZ[] = {
// normal human
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// normal beast
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// shrink human
-200000, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
-564586, -1329173, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// grown human
-250000, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
-1014586, -1779173, 0x5b05, 0, 0, 0, // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
};
@ -1183,17 +1183,19 @@ void playerReset(PLAYER *pPlayer)
}
void playerResetMoveSpeed(PLAYER* pPlayer) {
for (int i = 0, k = 0; i < 4; i++) {
for (int a = 0; a < 3; a++, k++)
for (int i = kModeHuman, k = 0; i < kModeMax; i++) {
for (int a = kPostureStand; a < kPostureMax; a++, k++)
gPosture[i][a].frontAccel = gPosture[i][a].sideAccel = gPosture[i][a].backAccel = gDefaultAccel[k];
}
}
void playerResetJumpHeight(PLAYER* pPlayer) {
for (int i = 0, k = 0; i < 4; i++) {
for (int a = 0; a < 3; a++) {
for (int i = kModeHuman, k = 0; i < kModeMax; i++) {
for (int a = kPostureStand; a < kPostureMax; a++) {
gPosture[i][a].normalJumpZ = gDefaultJumpZ[k++];
gPosture[i][a].pwupJumpZ = gDefaultJumpZ[k++];
}
}
}
@ -1787,17 +1789,11 @@ void ProcessInput(PLAYER *pPlayer)
default:
if (!pPlayer->cantJump && pInput->buttonFlags.jump && pXSprite->height == 0) {
sfxPlay3DSound(pSprite, 700, 0, 0);
if (packItemActive(pPlayer, 4)) zvel[nSprite] = pPosture->pwupJumpZ;// -0x175555;
else zvel[nSprite] = pPosture->normalJumpZ;//-0xbaaaa;
if (isShrinked(pPlayer->pSprite)) zvel[nSprite] -= gPosture[kModeHumanShrink][pPlayer->posture].normalJumpZ;//-200000;
else if (isGrown(pPlayer->pSprite)) zvel[nSprite] += gPosture[kModeHumanGrown][pPlayer->posture].normalJumpZ; //-250000;
if (packItemActive(pPlayer, 4)) zvel[nSprite] = pPosture->pwupJumpZ; //-0x175555;
else zvel[nSprite] = pPosture->normalJumpZ; //-0xbaaaa;
pPlayer->cantJump = 1;
}
if (pInput->buttonFlags.crouch)
pPlayer->posture = 2;
break;

View file

@ -462,21 +462,14 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
}
} else {
int rData[4];
if (xspriData2Array(pSprite->extra, rData)) {
while (maxRetries > 0) {
if ((tx = GetRandDataVal(rData)) > 0 && tx != pXSprite->txID) break;
maxRetries--;
}
while (maxRetries > 0) {
if ((tx = GetRandDataVal(pXSprite, kRandomizeTX)) > 0 && tx != pXSprite->txID) break;
maxRetries--;
}
}
if (tx > 0) {
pXSprite->txID = tx;
SetSpriteState(nSprite, pXSprite, pXSprite->state ^ 1, event.causedBy);
}
pXSprite->txID = (tx > 0 && tx < kChannelUserMax) ? tx : 0;
SetSpriteState(nSprite, pXSprite, pXSprite->state ^ 1, event.causedBy);
}
return;
@ -569,7 +562,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
break;
}
pXSprite->txID = tx;
pXSprite->txID = (tx > 0 && tx < kChannelUserMax) ? tx : 0;
SetSpriteState(nSprite, pXSprite, pXSprite->state ^ 1, event.causedBy);
}
return;
@ -3695,12 +3688,11 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) {
/* 4: follow player(s) when no targets in sight, attack targets if any in sight - */
if (type != 3) return;
else if (!IsDudeSprite(&sprite[nDest]) && sprite[nDest].statnum != kStatDude && xsprite[sprite[nDest].extra].data3 != 0) {
else if (!IsDudeSprite(&sprite[nDest]) && sprite[nDest].statnum != kStatDude) {
switch (sprite[nDest].type) { // can be dead dude turned in gib
// make current target and all other dudes not attack this dude anymore
case kThingBloodBits:
case kThingBloodChunks:
xsprite[sprite[nDest].extra].data3 = 0;
freeTargets(nDest);
return;
default:
@ -3713,8 +3705,9 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) {
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)) actKillDude(pSource->xvel, pSprite, DAMAGE_TYPE_0, 65535);
if (pXSprite->burnTime > 0 && spriRangeIsFine(pXSprite->burnSource)) {
if (IsBurningDude(pSprite)) return;
else {
spritetype* pBurnSource = &sprite[pXSprite->burnSource];
if (pBurnSource->extra >= 0) {
@ -3734,12 +3727,6 @@ void pastePropertiesInObj(int type, int nDest, EVENT event) {
}
}
// dude is dead?
if (pXSprite->health <= 0) {
pSprite->type = kThingBloodChunks; actPostSprite(pSprite->xvel, kStatThing); // turn it in gib
return;
}
spritetype* pPlayer = targetIsPlayer(pXSprite);
// special handling for player(s) if target changer data4 > 2.
if (pPlayer != NULL) {

View file

@ -402,10 +402,6 @@ void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput)
if (!predict.at6f && predict.at71 && predict.at6a == 0) {
if (packItemActive(pPlayer, 4)) predict.at64 = pPosture->pwupJumpZ;//-0x175555;
else predict.at64 = pPosture->normalJumpZ;//-0xbaaaa;
if (isShrinked(pPlayer->pSprite)) zvel[pPlayer->nSprite] -= gPosture[kModeHumanShrink][pPlayer->posture].normalJumpZ;//-200000;
else if (isGrown(pPlayer->pSprite)) zvel[pPlayer->nSprite] += gPosture[kModeHumanGrown][pPlayer->posture].normalJumpZ; //-250000;
predict.at6f = 1;
}
if (pInput->buttonFlags.crouch)
@ -2769,7 +2765,7 @@ void viewSetSystemMessage(const char* pMessage, ...) {
vsprintf(buffer, pMessage, args);
Printf(PRINT_HIGH | PRINT_NOTIFY, "%s\n", buffer); // print it also in console
gGameMessageMgr.Add(buffer, 15, 7, MESSAGE_PRIORITY_SYSTEM);
gGameMessageMgr.Add(buffer, 15, 7, MESSAGE_PRIORITY_NORMAL);
}
void viewSetMessage(const char *pMessage, const int pal, const MESSAGE_PRIORITY priority)

View file

@ -1938,7 +1938,8 @@ void WeaponProcess(PLAYER *pPlayer) {
if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) {
if (pXSprite->txID > 0)
evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID) pXSprite->command, pQavScene->causedBy);
evPost(nIndex, 3, 0, (COMMAND_ID) (kCmdNumberic + 4), pQavScene->causedBy);
if (pXSprite->locked) trPlayerCtrlStopScene(pXSprite, pPlayer);
else evPost(nIndex, 3, 0, (COMMAND_ID) (kCmdNumberic + 4), pQavScene->causedBy);
} else {
qavScenePlay(pPlayer);
pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0);