- Fixes for refactor

- Some ThrowError() calls was replaced my viewSetSystemMessage()
- New modern type playQAV (WIP)

# Conflicts:
#	source/blood/src/actor.cpp
#	source/blood/src/weapon.h
This commit is contained in:
Grind Core 2019-10-12 23:45:46 +03:00 committed by Christoph Oelckers
parent 08dfee073c
commit 16d4aebbb4
16 changed files with 389 additions and 360 deletions

View file

@ -2645,41 +2645,37 @@ void actInit(bool bSaveLoad) {
}
}
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite->type == kItemWeaponVoodooDoll)
pSprite->type = kAmmoItemVoodooDoll;
}
for (int nSprite = headspritestat[kStatTraps]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
spritetype *pSprite = &sprite[nSprite];
int nXSprite = pSprite->extra;
XSPRITE *pXSprite = NULL;
if (nXSprite > 0 && nXSprite < kMaxXSprites)
pXSprite = &xsprite[nXSprite];
if (pSprite->type == kTrapExploder) {
pXSprite->state = 0;
pXSprite->waitTime = ClipLow(pXSprite->waitTime, 1);
pSprite->cstat &= ~1;
pSprite->cstat |= 32768;
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
switch (sprite[nSprite].type) {
case kItemWeaponVoodooDoll:
sprite[nSprite].type = kAmmoItemVoodooDoll;
break;
}
}
for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
for (int nSprite = headspritestat[kStatTraps]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
spritetype *pSprite = &sprite[nSprite];
int nXSprite = pSprite->extra;
if (nXSprite <= 0 || nXSprite >= kMaxXSprites)
ThrowError("WARNING: Sprite %d is on the wrong status list!\n", nSprite);
XSPRITE *pXSprite = &xsprite[nXSprite];
switch (pSprite->type) {
case kTrapExploder:
pSprite->cstat &= ~1; pSprite->cstat |= CSTAT_SPRITE_INVISIBLE;
if (pSprite->extra <= 0 || pSprite->extra >= kMaxXSprites) continue;
xsprite[pSprite->extra].waitTime = ClipLow(xsprite[pSprite->extra].waitTime, 1);
xsprite[pSprite->extra].state = 0;
break;
}
}
for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (sprite[nSprite].extra <= 0 || sprite[nSprite].extra >= kMaxXSprites) continue;
spritetype* pSprite = &sprite[nSprite]; XSPRITE *pXSprite = &xsprite[pSprite->extra];
int nType = pSprite->type - kThingBase;
pSprite->clipdist = thingInfo[nType].at4;
pSprite->flags = thingInfo[nType].at5;
if (pSprite->flags&2)
pSprite->flags |= 4;
pXSprite->health = thingInfo[nType].health << 4;
pSprite->clipdist = thingInfo[nType].clipdist;
pSprite->flags = thingInfo[nType].flags;
if (pSprite->flags & kPhysGravity) pSprite->flags |= kPhysFalling;
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
pXSprite->health = thingInfo[nType].at0<<4;
switch (pSprite->type) {
case kThingArmedProxBomb:
case kTrapMachinegun:
@ -2687,11 +2683,11 @@ void actInit(bool bSaveLoad) {
pXSprite->state = 0;
break;
case kThingBloodChunks: {
SEQINST *pInst = GetInstance(3, nXSprite);
SEQINST *pInst = GetInstance(3, pSprite->extra);
if (pInst && pInst->at13) {
DICTNODE *hSeq = gSysRes.Lookup(pInst->at8, "SEQ");
if (!hSeq) break;
seqSpawn(pInst->at8, 3, nXSprite);
seqSpawn(pInst->at8, 3, pSprite->extra);
}
break;
}
@ -2700,55 +2696,44 @@ void actInit(bool bSaveLoad) {
break;
}
}
if (gGameOptions.nMonsterSettings == 0)
{
if (gGameOptions.nMonsterSettings == 0) {
gKillMgr.SetCount(0);
while (headspritestat[kStatDude] >= 0)
{
while (headspritestat[kStatDude] >= 0) {
spritetype *pSprite = &sprite[headspritestat[kStatDude]];
int nXSprite = pSprite->extra;
dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
XSPRITE *pXSprite = &xsprite[nXSprite];
// Drop Key
if (pXSprite->key > 0)
actDropObject(pSprite, 99 + pXSprite->key);
if (pSprite->extra > 0 && pSprite->extra < kMaxXSprites && xsprite[pSprite->extra].key > 0) // Drop Key
actDropObject(pSprite, kItemKeyBase + (xsprite[pSprite->extra].key - 1));
DeleteSprite(headspritestat[kStatDude]);
}
}
else
{
} else {
// by NoOne: WTF is this?
///////////////
char unk[kDudeMax-kDudeBase];
memset(unk, 0, sizeof(unk));
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
spritetype *pSprite = &sprite[nSprite];
if (pSprite->type < kDudeBase || pSprite->type >= kDudeMax)
ThrowError("Non-enemy sprite (%d) in the enemy sprite list.\n", nSprite);
unk[pSprite->type-kDudeBase] = 1;
unk[pSprite->type - kDudeBase] = 1;
}
gKillMgr.sub_2641C();
///////////////
for (int i = 0; i < kDudeMax-kDudeBase; i++)
for (int i = 0; i < kDudeMax - kDudeBase; i++)
for (int j = 0; j < 7; j++)
dudeInfo[i].at70[j] = mulscale8(DudeDifficulty[gGameOptions.nDifficulty], dudeInfo[i].startDamage[j]);
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
spritetype *pSprite = &sprite[nSprite];
int nXSprite = pSprite->extra;
dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
XSPRITE *pXSprite = &xsprite[nXSprite];
int nType = pSprite->type-kDudeBase;
int seqStartId = dudeInfo[nType].seqStartID;
if (sprite[nSprite].extra <= 0 || sprite[nSprite].extra >= kMaxXSprites) continue;
spritetype *pSprite = &sprite[nSprite]; XSPRITE *pXSprite = &xsprite[pSprite->extra];
int nType = pSprite->type - kDudeBase; int seqStartId = dudeInfo[nType].seqStartID;
if (!IsPlayerSprite(pSprite)) {
switch (pSprite->type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
pSprite->cstat |= 4096 + 256 + 1;
pSprite->cstat |= 4096 + CSTAT_SPRITE_BLOCK_HITSCAN + CSTAT_SPRITE_BLOCK;
seqStartId = getSeqStartId(pXSprite); // by NoOne: Custom Dude stores it's SEQ in data2
pXSprite->sysData1 = pXSprite->data3; // by NoOne move sndStartId to sysData1, because data3 used by the game;
pXSprite->data3 = 0;
@ -2758,7 +2743,7 @@ void actInit(bool bSaveLoad) {
fallthrough__;
default:
pSprite->clipdist = dudeInfo[nType].clipdist;
pSprite->cstat |= 4096 + 256 + 1;
pSprite->cstat |= 4096 + CSTAT_SPRITE_BLOCK_HITSCAN + CSTAT_SPRITE_BLOCK;
break;
}
@ -2767,10 +2752,9 @@ void actInit(bool bSaveLoad) {
// By NoOne: 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);
}
if (gSysRes.Lookup(seqStartId, "SEQ")) seqSpawn(seqStartId, 3, nXSprite);
if (gSysRes.Lookup(seqStartId, "SEQ")) seqSpawn(seqStartId, 3, pSprite->extra);
}
aiInit();
}
@ -2785,8 +2769,7 @@ void ConcussSprite(int a1, spritetype *pSprite, int x, int y, int z, int a6)
int dist2 = 0x40000+dx*dx+dy*dy+dz*dz;
dassert(dist2 > 0);
a6 = scale(0x40000, a6, dist2);
if (pSprite->flags & 1)
{
if (pSprite->flags & kPhysMove) {
int mass = 0;
if (IsDudeSprite(pSprite)) {
mass = dudeInfo[pSprite->type - kDudeBase].mass;
@ -2798,9 +2781,11 @@ void ConcussSprite(int a1, spritetype *pSprite, int x, int y, int z, int a6)
}
}
else if (pSprite->type >= kThingBase && pSprite->type < kThingMax)
mass = thingInfo[pSprite->type - kThingBase].at2;
mass = thingInfo[pSprite->type - kThingBase].mass;
else
ThrowError("Unexpected type in ConcussSprite(): Sprite: %d Type: %d Stat: %d", (int)pSprite->index, (int)pSprite->type, (int)pSprite->statnum);
return;
//else
//ThrowError("Unexpected type in ConcussSprite(): Sprite: %d Type: %d Stat: %d", (int)pSprite->index, (int)pSprite->type, (int)pSprite->statnum);
int size = (tilesiz[pSprite->picnum].x*pSprite->xrepeat*tilesiz[pSprite->picnum].y*pSprite->yrepeat)>>1;
dassert(mass > 0);
@ -2814,6 +2799,7 @@ void ConcussSprite(int a1, spritetype *pSprite, int x, int y, int z, int a6)
yvel[nSprite] += dy;
zvel[nSprite] += dz;
}
actDamageSprite(a1, pSprite, DAMAGE_TYPE_3, a6);
}
@ -3248,15 +3234,18 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
if (pXSprite->dropMsg > 0)
actDropObject(pSprite, pXSprite->dropMsg);
int nRand = Random(100);
switch (pSprite->type) {
case kDudeCultistTommy:
case kDudeCultistTommy: {
int nRand = Random(100);
if (nRand < 10) actDropObject(pSprite, kItemWeaponTommygun);
else if (nRand < 50) actDropObject(pSprite, kItemAmmoTommygunFew);
}
break;
case kDudeCultistShotgun:
case kDudeCultistShotgun: {
int nRand = Random(100);
if (nRand <= 10) actDropObject(pSprite, kItemWeaponSawedoff);
else if (nRand <= 50) actDropObject(pSprite, kItemAmmoSawedoffFew);
}
break;
}
@ -3657,91 +3646,76 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
actPostSprite(pSprite->index, kStatThing);
}
int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, int damage)
{
int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, int damage) {
dassert(nSource < kMaxSprites);
if (pSprite->flags&32)
if (pSprite->flags&32 || pSprite->extra <= 0 || pSprite->extra >= kMaxXSprites || xsprite[pSprite->extra].reference != pSprite->index)
return 0;
int nXSprite = pSprite->extra;
if (nXSprite <= 0)
return 0;
dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
XSPRITE *pXSprite = &xsprite[nXSprite];
dassert(pXSprite->reference == pSprite->index);
XSPRITE *pXSprite = &xsprite[pSprite->extra];
if ((pXSprite->health == 0 && pSprite->statnum != kStatDude) || pXSprite->locked)
return 0;
if (nSource == -1)
if (nSource == -1)
nSource = pSprite->index;
PLAYER *pSourcePlayer = NULL;
if (IsPlayerSprite(&sprite[nSource]))
pSourcePlayer = &gPlayer[sprite[nSource].type-kDudePlayer1];
if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite))
return 0;
switch (pSprite->statnum)
{
case kStatDude:
{
if (pSprite->type < kDudeBase || pSprite->type >= kDudeMax)
{
sprintf(buffer, "Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags&16) ? "RESPAWN" : "NORMAL");
ThrowError(buffer);
}
dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
int nType = pSprite->type-kDudeBase;
int nDamageFactor = dudeInfo[nType].at70[damageType];
if (!nDamageFactor)
return 0;
if (nDamageFactor != 256)
if (IsPlayerSprite(&sprite[nSource])) pSourcePlayer = &gPlayer[sprite[nSource].type - kDudePlayer1];
if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0;
switch (pSprite->statnum) {
case kStatDude: {
if (!IsDudeSprite(pSprite))
ThrowError("Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags & 16) ? "RESPAWN" : "NORMAL");
int nType = pSprite->type - kDudeBase; int nDamageFactor = dudeInfo[nType].at70[damageType];
if (!nDamageFactor) return 0;
else if (nDamageFactor != 256)
damage = mulscale8(damage, nDamageFactor);
if (!IsPlayerSprite(pSprite))
{
if (!pXSprite->health)
return 0;
if (!IsPlayerSprite(pSprite)) {
if (pXSprite->health <= 0) return 0;
damage = aiDamageSprite(pSprite, pXSprite, nSource, damageType, damage);
if (!pXSprite->health)
{
if (damageType == DAMAGE_TYPE_3 && damage < 160)
damageType = DAMAGE_TYPE_0;
actKillDude(nSource, pSprite, damageType, damage);
}
}
else
{
PLAYER *pPlayer = &gPlayer[pSprite->type-kDudePlayer1];
if (pXSprite->health <= 0)
actKillDude(nSource, pSprite, ((damageType == DAMAGE_TYPE_3 && damage < 160) ? DAMAGE_TYPE_0 : damageType), damage);
} else {
PLAYER *pPlayer = &gPlayer[pSprite->type - kDudePlayer1];
if (pXSprite->health > 0 || playerSeqPlaying(pPlayer, 16))
damage = playerDamageSprite(nSource, pPlayer, damageType, damage);
}
}
break;
}
case kStatThing:
dassert(pSprite->type >= kThingBase && pSprite->type < kThingMax);
int nType = pSprite->type-kThingBase;
int nDamageFactor = thingInfo[nType].at17[damageType];
if (!nDamageFactor)
return 0;
if (nDamageFactor != 256)
int nType = pSprite->type - kThingBase; int nDamageFactor = thingInfo[nType].at17[damageType];
if (!nDamageFactor) return 0;
else if (nDamageFactor != 256)
damage = mulscale8(damage, nDamageFactor);
pXSprite->health = ClipLow(pXSprite->health-damage, 0);
if (!pXSprite->health)
{
if (pSprite->type == kThingDroppedLifeLeech || pSprite->type == kModernThingEnemyLifeLeech)
{
pXSprite->health = ClipLow(pXSprite->health - damage, 0);
if (pXSprite->health <= 0) {
switch (pSprite->type) {
case kThingDroppedLifeLeech:
case kModernThingEnemyLifeLeech:
GibSprite(pSprite, GIBTYPE_14, NULL, NULL);
pXSprite->data1 = 0;
pXSprite->data2 = 0;
pXSprite->data3 = 0;
pXSprite->stateTimer = 0;
pXSprite->data4 = 0;
pXSprite->isTriggered = 0;
pXSprite->DudeLockout = 0;
pXSprite->data1 = pXSprite->data2 = pXSprite->data3 = pXSprite->DudeLockout = 0;
pXSprite->stateTimer = pXSprite->data4 = pXSprite->isTriggered = 0;
if (pSprite->owner >= 0 && sprite[pSprite->owner].type == kDudeModernCustom)
sprite[pSprite->owner].owner = kMaxSprites -1; // By NoOne: indicates if custom dude had life leech.
sprite[pSprite->owner].owner = kMaxSprites - 1; // By NoOne: indicates if custom dude had life leech.
break;
default:
if (!(pSprite->flags & 16))
actPropagateSpriteOwner(pSprite, &sprite[nSource]);
break;
}
else if (!(pSprite->flags&16))
actPropagateSpriteOwner(pSprite, &sprite[nSource]);
trTriggerSprite(pSprite->index, pXSprite, kCmdOff);
switch (pSprite->type) {
case kThingObjectGib:
case kThingObjectExplode:
@ -3788,7 +3762,8 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, in
}
break;
}
return damage>>4;
return damage >> 4;
}
void actHitcodeToData(int a1, HITINFO *pHitInfo, int *a3, spritetype **a4, XSPRITE **a5, int *a6, walltype **a7, XWALL **a8, int *a9, sectortype **a10, XSECTOR **a11)
@ -3910,10 +3885,12 @@ void actImpactMissile(spritetype *pMissile, int hitCode)
switch (hitCode) {
case 0:
case 4:
if (!pWallHit) break;
if (pWallHit) {
spritetype* pFX = gFX.fxSpawn(FX_52, pMissile->sectnum, pMissile->x, pMissile->y, pMissile->z, 0);
if (pFX) pFX->ang = (GetWallAngle(nWallHit) + 512) & 2047;
}
}
break;
}
GibSprite(pMissile, GIBTYPE_24, NULL, NULL);
actPostSprite(pMissile->index, kStatFree);
break;
@ -4202,9 +4179,9 @@ void ProcessTouchObjects(spritetype *pSprite, int nXSprite)
{
int nType = pSprite2->type-kThingBase;
THINGINFO *pThingInfo = &thingInfo[nType];
if (pThingInfo->at5&1)
if (pThingInfo->flags&1)
pSprite2->flags |= 1;
if (pThingInfo->at5&2)
if (pThingInfo->flags&2)
pSprite2->flags |= 4;
// Inlined ?
xvel[pSprite2->index] += mulscale(4, pSprite2->x-sprite[nSprite].x, 2);
@ -5454,7 +5431,7 @@ void actExplodeSprite(spritetype *pSprite)
{
XSPRITE *pXSprite = &xsprite[nXSprite];
pXSprite->state = 1;
pXSprite->health = thingInfo[0].at0<<4;
pXSprite->health = thingInfo[0].health<<4;
}
else
actPostSprite(pSprite->index, kStatFree);
@ -5793,9 +5770,9 @@ void actProcessSprites(void)
{
int nType = pSprite->type - kThingBase;
THINGINFO *pThingInfo = &thingInfo[nType];
if (pThingInfo->at5 & 1)
if (pThingInfo->flags & 1)
pSprite->flags |= 1;
if (pThingInfo->at5 & 2)
if (pThingInfo->flags & 2)
pSprite->flags |= 4;
}
if (pSprite->flags&3)
@ -6492,9 +6469,9 @@ spritetype * actSpawnThing(int nSector, int x, int y, int z, int nThingType)
dassert(nXThing > 0 && nXThing < kMaxXSprites);
XSPRITE *pXThing = &xsprite[nXThing];
THINGINFO *pThingInfo = &thingInfo[nType];
pXThing->health = pThingInfo->at0<<4;
pSprite->clipdist = pThingInfo->at4;
pSprite->flags = pThingInfo->at5;
pXThing->health = pThingInfo->health<<4;
pSprite->clipdist = pThingInfo->clipdist;
pSprite->flags = pThingInfo->flags;
if (pSprite->flags & 2)
pSprite->flags |= 4;
pSprite->cstat |= pThingInfo->atf;
@ -6942,7 +6919,7 @@ void actFireVector(spritetype *pShooter, int a2, int a3, int a4, int a5, int a6,
}
if (pSprite->statnum == kStatThing)
{
int t = thingInfo[pSprite->type-kThingBase].at2;
int t = thingInfo[pSprite->type-kThingBase].mass;
if (t > 0 && pVectorData->at5)
{
int t2 = divscale(pVectorData->at5, t, 8);
@ -7129,7 +7106,7 @@ void TreeToGibCallback(int, int nXSprite)
pXSprite->data1 = 15;
pXSprite->data2 = 0;
pXSprite->data3 = 0;
pXSprite->health = thingInfo[17].at0;
pXSprite->health = thingInfo[17].health;
pXSprite->data4 = 312;
pSprite->cstat |= 257;
}
@ -7143,7 +7120,7 @@ void DudeToGibCallback1(int, int nXSprite)
pXSprite->data1 = 8;
pXSprite->data2 = 0;
pXSprite->data3 = 0;
pXSprite->health = thingInfo[26].at0;
pXSprite->health = thingInfo[26].health;
pXSprite->data4 = 319;
pXSprite->triggerOnce = 0;
pXSprite->isTriggered = 0;
@ -7161,7 +7138,7 @@ void DudeToGibCallback2(int, int nXSprite)
pXSprite->data1 = 3;
pXSprite->data2 = 0;
pXSprite->data3 = 0;
pXSprite->health = thingInfo[26].at0;
pXSprite->health = thingInfo[26].health;
pXSprite->data4 = 319;
pXSprite->triggerOnce = 0;
pXSprite->isTriggered = 0;

View file

@ -69,10 +69,10 @@ enum VECTOR_TYPE {
struct THINGINFO
{
short at0; // health
short at2; // mass
unsigned char at4; // clipdist
short at5; // flags
short health; // health
short mass; // mass
unsigned char clipdist; // clipdist
short flags; // flags
int at7; // elasticity
int atb; // damage resistance
short atf; // cstat
@ -191,7 +191,6 @@ extern int gDudeDrag;
extern short gAffectedSectors[kMaxSectors];
extern short gAffectedXWalls[kMaxXWalls];
inline bool IsPlayerSprite(spritetype *pSprite)
{
if (pSprite->type >= kDudePlayer1 && pSprite->type <= kDudePlayer8)

View file

@ -121,10 +121,15 @@ static void SpidBiteSeqCallback(int, int nXSprite)
actFireVector(pSprite, 0, 0, dx, dy, dz, VECTOR_TYPE_17);
sub_70D30(pXTarget, 8, 16);
break;
case kDudeSpiderMother:
case kDudeSpiderMother: {
actFireVector(pSprite, 0, 0, dx, dy, dz, VECTOR_TYPE_17);
dx += Random2(2000);
dy += Random2(2000);
dz += Random2(2000);
actFireVector(pSprite, 0, 0, dx, dy, dz, VECTOR_TYPE_17);
actFireVector(pSprite, 0, 0, dx + Random2(2000), dy + Random2(2000), dz + Random2(2000), VECTOR_TYPE_17);
sub_70D30(pXTarget, 8, 16);
}
break;
}
}

View file

@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "fx_man.h"
#include "common_game.h"
//#include "blood.h"
#include "view.h"
#include "config.h"
#include "db.h"
#include "player.h"
@ -116,49 +117,52 @@ void ambInit(void)
{
ambKillAll();
memset(ambChannels, 0, sizeof(ambChannels));
for (int nSprite = headspritestat[kStatAmbience]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
spritetype *pSprite = &sprite[nSprite];
int nXSprite = pSprite->extra;
if (nXSprite > 0 && nXSprite < kMaxXSprites)
{
XSPRITE *pXSprite = &xsprite[nXSprite];
if (pXSprite->data1 < pXSprite->data2)
{
int i;
AMB_CHANNEL *pChannel = ambChannels;
for (i = 0; i < nAmbChannels; i++, pChannel++)
if (pXSprite->data3 == pChannel->at8)
break;
if (i == nAmbChannels)
{
if (i >= kMaxAmbChannel)
{
pSprite->owner = -1;
continue;
}
int nSFX = pXSprite->data3;
DICTNODE *pSFXNode = gSoundRes.Lookup(nSFX, "SFX");
if (!pSFXNode)
ThrowError("Missing sound #%d used in ambient sound generator %d\n", nSFX);
SFX *pSFX = (SFX*)gSoundRes.Load(pSFXNode);
DICTNODE *pRAWNode = gSoundRes.Lookup(pSFX->rawName, "RAW");
if (!pRAWNode)
ThrowError("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX);
if (pRAWNode->size > 0)
{
pChannel->at14 = pRAWNode->size;
pChannel->at8 = nSFX;
pChannel->atc = pRAWNode;
pChannel->at14 = pRAWNode->size;
pChannel->at10 = (char*)gSoundRes.Lock(pRAWNode);
pChannel->at18 = pSFX->format;
nAmbChannels++;
}
}
pSprite->owner = i;
for (int nSprite = headspritestat[kStatAmbience]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (sprite[nSprite].extra <= 0 || sprite[nSprite].extra >= kMaxXSprites) continue;
XSPRITE *pXSprite = &xsprite[sprite[nSprite].extra];
if (pXSprite->data1 >= pXSprite->data2) continue;
int i; AMB_CHANNEL *pChannel = ambChannels;
for (i = 0; i < nAmbChannels; i++, pChannel++)
if (pXSprite->data3 == pChannel->at8) break;
if (i == nAmbChannels) {
if (i >= kMaxAmbChannel) {
sprite[nSprite].owner = -1;
continue;
}
int nSFX = pXSprite->data3;
DICTNODE *pSFXNode = gSoundRes.Lookup(nSFX, "SFX");
if (!pSFXNode) {
//ThrowError("Missing sound #%d used in ambient sound generator %d\n", nSFX);
viewSetSystemMessage("Missing sound #%d used in ambient sound generator #%d\n", nSFX);
continue;
}
SFX *pSFX = (SFX*)gSoundRes.Load(pSFXNode);
DICTNODE *pRAWNode = gSoundRes.Lookup(pSFX->rawName, "RAW");
if (!pRAWNode) {
//ThrowError("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX);
viewSetSystemMessage("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX);
continue;
}
if (pRAWNode->size > 0) {
pChannel->at14 = pRAWNode->size;
pChannel->at8 = nSFX;
pChannel->atc = pRAWNode;
pChannel->at14 = pRAWNode->size;
pChannel->at10 = (char*)gSoundRes.Lock(pRAWNode);
pChannel->at18 = pSFX->format;
nAmbChannels++;
}
}
sprite[nSprite].owner = i;
}
}

View file

@ -629,6 +629,10 @@ void StartLevel(GAMEOPTIONS *gameOptions)
case kModernDudeTargetChanger:
changespritestat(i, kStatModernDudeTargetChanger);
break;
// add statnum for faster searching of already enabled qav players
case kModernPlayQAV:
changespritestat(i, kStatModernPlayQAV);
break;
// remove kStatItem status from random item generators
case kModernRandom:
case kModernRandom2:

View file

@ -227,67 +227,66 @@ void fxDynPuff(int nSprite) // 8
void Respawn(int nSprite) // 9
{
spritetype *pSprite = &sprite[nSprite];
int nXSprite = pSprite->extra;
dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
XSPRITE *pXSprite = &xsprite[nXSprite];
if (pSprite->statnum != kStatRespawn && pSprite->statnum != kStatThing)
ThrowError("Sprite %d is not on Respawn or Thing list\n", nSprite);
if (!(pSprite->flags&16))
ThrowError("Sprite %d does not have the respawn attribute\n", nSprite);
switch (pXSprite->respawnPending)
{
case 1:
{
int nTime = mulscale16(actGetRespawnTime(pSprite), 0x4000);
pXSprite->respawnPending = 2;
evPost(nSprite, 3, nTime, kCallbackRespawn);
break;
dassert(pSprite->extra > 0 && pSprite->extra < kMaxXSprites);
XSPRITE *pXSprite = &xsprite[pSprite->extra];
if (pSprite->statnum != kStatRespawn && pSprite->statnum != kStatThing) {
viewSetSystemMessage("Sprite #%d is not on Respawn or Thing list\n", nSprite);
return;
} else if (!(pSprite->flags & kHitagRespawn)) {
viewSetSystemMessage("Sprite #%d does not have the respawn attribute\n", nSprite);
return;
}
case 2:
{
int nTime = mulscale16(actGetRespawnTime(pSprite), 0x2000);
pXSprite->respawnPending = 3;
evPost(nSprite, 3, nTime, kCallbackRespawn);
break;
}
case 3:
{
dassert(pSprite->owner != kStatRespawn);
dassert(pSprite->owner >= 0 && pSprite->owner < kMaxStatus);
ChangeSpriteStat(nSprite, pSprite->owner);
pSprite->type = pSprite->inittype;
pSprite->owner = -1;
pSprite->flags &= ~16;
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
pXSprite->respawnPending = 0;
pXSprite->burnTime = 0;
pXSprite->isTriggered = 0;
if (pSprite->type >= kDudeBase && pSprite->type < kDudeMax)
{
int nType = pSprite->type-kDudeBase;
pSprite->x = baseSprite[nSprite].x;
pSprite->y = baseSprite[nSprite].y;
pSprite->z = baseSprite[nSprite].z;
pSprite->cstat |= 0x1101;
pSprite->clipdist = dudeInfo[nType].clipdist;
pXSprite->health = dudeInfo[nType].startHealth<<4;
if (gSysRes.Lookup(dudeInfo[nType].seqStartID, "SEQ"))
seqSpawn(dudeInfo[nType].seqStartID, 3, pSprite->extra, -1);
aiInitSprite(pSprite);
pXSprite->key = 0;
switch (pXSprite->respawnPending) {
case 1: {
int nTime = mulscale16(actGetRespawnTime(pSprite), 0x4000);
pXSprite->respawnPending = 2;
evPost(nSprite, 3, nTime, kCallbackRespawn);
break;
}
if (pSprite->type == kThingTNTBarrel)
{
pSprite->cstat |= CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN;
pSprite->cstat &= (unsigned short)~CSTAT_SPRITE_INVISIBLE;
case 2: {
int nTime = mulscale16(actGetRespawnTime(pSprite), 0x2000);
pXSprite->respawnPending = 3;
evPost(nSprite, 3, nTime, kCallbackRespawn);
break;
}
case 3: {
dassert(pSprite->owner != kStatRespawn);
dassert(pSprite->owner >= 0 && pSprite->owner < kMaxStatus);
ChangeSpriteStat(nSprite, pSprite->owner);
pSprite->type = pSprite->inittype;
pSprite->owner = -1;
pSprite->flags &= ~16;
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
pXSprite->respawnPending = 0;
pXSprite->burnTime = 0;
pXSprite->isTriggered = 0;
if (IsDudeSprite(pSprite)) {
int nType = pSprite->type-kDudeBase;
pSprite->x = baseSprite[nSprite].x;
pSprite->y = baseSprite[nSprite].y;
pSprite->z = baseSprite[nSprite].z;
pSprite->cstat |= 0x1101;
pSprite->clipdist = dudeInfo[nType].clipdist;
pXSprite->health = dudeInfo[nType].startHealth<<4;
if (gSysRes.Lookup(dudeInfo[nType].seqStartID, "SEQ"))
seqSpawn(dudeInfo[nType].seqStartID, 3, pSprite->extra, -1);
aiInitSprite(pSprite);
pXSprite->key = 0;
} else if (pSprite->type == kThingTNTBarrel) {
pSprite->cstat |= CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN;
pSprite->cstat &= (unsigned short)~CSTAT_SPRITE_INVISIBLE;
}
gFX.fxSpawn(FX_29, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0);
sfxPlay3DSound(pSprite, 350, -1, 0);
break;
}
gFX.fxSpawn(FX_29, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0);
sfxPlay3DSound(pSprite, 350, -1, 0);
break;
}
default:
ThrowError("Unexpected respawnPending value = %d", pXSprite->respawnPending);
break;
}
}

View file

@ -51,7 +51,7 @@ enum CALLBACK_ID {
kCallbackDropVoodoo = 21, // unused
kCallbackMissileBurst = 22, // by NoOne
kCallbackMissileSpriteBlock = 23, // by NoOne
kCallbackMax = 24
kCallbackMax = 24,
};
extern void (*gCallback[kCallbackMax])(int);

View file

@ -99,7 +99,8 @@ void QuitGame(void);
#define kStatFlare 14
#define kStatDebris 15
#define kStatPathMarker 16
#define kStatModernDudeTargetChanger 20
#define kStatModernDudeTargetChanger 20 // gModernMap only
#define kStatModernPlayQAV 21 // gModernMap only
#define kStatFree 1024
#define kLensSize 80
@ -159,7 +160,8 @@ enum {
kModernObjDataAccumulator = 37,
kModernEffectSpawner = 38,
kModernWindGenerator = 39,
kModernConcussSprite = 712,
kModernConcussSprite = 712, /// WIP
kModernPlayQAV = 713, /// WIP
// decorations
kDecorationTorch = 30,

View file

@ -158,19 +158,18 @@ void CKillMgr::sub_2641C(void)
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
spritetype *pSprite = &sprite[nSprite];
if (pSprite->type < kDudeBase || pSprite->type >= kDudeMax)
ThrowError("Non-enemy sprite (%d) in the enemy sprite list.", nSprite);
if (pSprite->statnum == kStatDude) {
switch (pSprite->type) {
case kDudeBat:
case kDudeRat:
case kDudeBurningInnocent:
case kDudeInnocent:
return;
}
if (IsDudeSprite(pSprite)) {
if (pSprite->statnum == kStatDude) {
switch (pSprite->type) {
case kDudeBat:
case kDudeRat:
case kDudeBurningInnocent:
case kDudeInnocent:
return;
}
at0++;
at0++;
}
}
}
@ -229,22 +228,20 @@ void CSecretMgr::SetCount(int nCount)
void CSecretMgr::Found(int nType)
{
if (nType < 0)
ThrowError("Invalid secret type %d triggered.", nType);
if (nType == 0)
at4++;
else
at8++;
if (gGameOptions.nGameType == 0)
{
switch (Random(2))
{
case 0:
viewSetMessage("A secret is revealed.", 0, MESSAGE_PRIORITY_SECRET);
break;
case 1:
viewSetMessage("You found a secret.", 0, MESSAGE_PRIORITY_SECRET);
break;
if (nType == 0) at4++;
else if (nType < 0) {
viewSetSystemMessage("Invalid secret type %d triggered.", nType);
return;
} else at8++;
if (gGameOptions.nGameType == 0) {
switch (Random(2)) {
case 0:
viewSetMessage("A secret is revealed.", 0, MESSAGE_PRIORITY_SECRET);
break;
case 1:
viewSetMessage("You found a secret.", 0, MESSAGE_PRIORITY_SECRET);
break;
}
}
}

View file

@ -82,32 +82,25 @@ RXBUCKET rxBucket[kMaxChannels+1];
int GetBucketChannel(const RXBUCKET *pRX)
{
switch (pRX->type)
{
case 6:
{
int nIndex = pRX->index;
int nXIndex = sector[nIndex].extra;
dassert(nXIndex > 0);
return xsector[nXIndex].rxID;
}
case 0:
{
int nIndex = pRX->index;
int nXIndex = wall[nIndex].extra;
dassert(nXIndex > 0);
return xwall[nXIndex].rxID;
}
case 3:
{
int nIndex = pRX->index;
int nXIndex = sprite[nIndex].extra;
dassert(nXIndex > 0);
return xsprite[nXIndex].rxID;
}
default:
ThrowError("Unexpected rxBucket type %d, index %d", pRX->type, pRX->index);
break;
switch (pRX->type) {
case 6: {
int nIndex = pRX->index;
int nXIndex = sector[nIndex].extra;
dassert(nXIndex > 0);
return xsector[nXIndex].rxID;
}
case 0: {
int nIndex = pRX->index;
int nXIndex = wall[nIndex].extra;
dassert(nXIndex > 0);
return xwall[nXIndex].rxID;
}
case 3: {
int nIndex = pRX->index;
int nXIndex = sprite[nIndex].extra;
dassert(nXIndex > 0);
return xsprite[nXIndex].rxID;
}
}
return 0;
}

View file

@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gameutil.h"
#include "actor.h"
#include "tile.h"
#include "view.h"
BEGIN_BLD_NS
@ -378,11 +379,14 @@ void UnlockInstance(SEQINST *pInst)
void seqSpawn(int a1, int a2, int a3, int a4)
{
SEQINST *pInst = GetInstance(a2, a3);
if (!pInst)
return;
if (!pInst) return;
DICTNODE *hSeq = gSysRes.Lookup(a1, "SEQ");
if (!hSeq)
ThrowError("Missing sequence #%d", a1);
if (!hSeq) {
viewSetSystemMessage("Missing sequence #%d", a1);
return;
}
int i = activeCount;
if (pInst->at13)
{
@ -577,8 +581,10 @@ void SeqLoadSave::Load(void)
{
int nSeq = pInst->at8;
DICTNODE *hSeq = gSysRes.Lookup(nSeq, "SEQ");
if (!hSeq)
ThrowError("Missing sequence #%d", nSeq);
if (!hSeq) {
viewSetSystemMessage("Missing sequence #%d", nSeq);
continue;
}
Seq *pSeq = (Seq*)gSysRes.Lock(hSeq);
if (memcmp(pSeq->signature, "SEQ\x1a", 4) != 0)
ThrowError("Invalid sequence %d", nSeq);

View file

@ -119,18 +119,15 @@ void Calc3DValues(BONKLE *pBonkle)
void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector)
{
if (!SoundToggle)
return;
if (soundId < 0)
ThrowError("Invalid sound ID");
if (!SoundToggle || soundId < 0) return;
DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX");
if (!hRes)
return;
if (!hRes)return;
SFX *pEffect = (SFX*)gSoundRes.Load(hRes);
hRes = gSoundRes.Lookup(pEffect->rawName, "RAW");
if (!hRes)
return;
if (!hRes) return;
int v1c, v18;
v1c = v18 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format));
if (nBonkles >= 256)

View file

@ -35,16 +35,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "globals.h"
#include "resource.h"
#include "tile.h"
#include "view.h"
BEGIN_BLD_NS
void qloadvoxel(int32_t nVoxel)
{
static int nLastVoxel = 0;
dassert(nVoxel >= 0 && nVoxel < kMaxVoxels);
DICTNODE *hVox = gSysRes.Lookup(nVoxel, "KVX");
if (!hVox)
ThrowError("Missing voxel #%d", nVoxel);
if (!hVox) {
viewSetSystemMessage("Missing voxel #%d (max voxels: %d)", nVoxel, kMaxVoxels);
return;
}
if (!hVox->lockCount)
voxoff[nLastVoxel][0] = 0;
nLastVoxel = nVoxel;

View file

@ -52,6 +52,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "view.h"
#include "sectorfx.h"
#include "messages.h"
#include "weapon.h"
BEGIN_BLD_NS
@ -406,10 +407,10 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
case kMarkerLowStack:
case kMarkerPath:
switch (pXSprite->command) {
case kCmdLink:
if (pXSprite->txID <= 0) return;
evSend(nSprite, 3, pXSprite->txID, (COMMAND_ID)pXSprite->command);
return;
case kCmdLink:
if (pXSprite->txID <= 0) return;
evSend(nSprite, 3, pXSprite->txID, (COMMAND_ID)pXSprite->command);
return;
}
break; // go normal operate switch
@ -816,6 +817,36 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
break;
}
return;
case kModernPlayQAV: // WIP
PLAYER* pPlayer = &gPlayer[pXSprite->data1];
switch (event.cmd) {
case kCmdOff:
pPlayer->atbd = pXSprite->sysData1;
if (pXSprite->state == 1) SetSpriteState(nSprite, pXSprite, 0);
if (pPlayer->atbd != 0)
WeaponRaise(pPlayer);
break;
case kCmdOn:
evKill(nSprite, 3); // queue overflow protect
disableQAVPlayers(pSprite);
if (pXSprite->state == 0) SetSpriteState(nSprite, pXSprite, 1);
if (pPlayer->atbd != 0) {
pXSprite->sysData1 = pPlayer->atbd; // save current weapon
WeaponLower(pPlayer);
}
fallthrough__;
case kCmdRepeat:
if (pPlayer->at26 != pXSprite->data2)
StartQAV(&gPlayer[pXSprite->data1], pXSprite->data2);
if (pXSprite->busyTime > 0) evPost(nSprite, 3, pXSprite->busyTime, kCmdRepeat);
break;
default:
if (pXSprite->state == 0) evPost(nSprite, 3, 0, kCmdOn);
else evPost(nSprite, 3, 0, kCmdOff);
break;
}
return;
}
}
@ -1711,6 +1742,7 @@ void SetupGibWallState(walltype *pWall, XWALL *pXWall)
void OperateWall(int nWall, XWALL *pXWall, EVENT event) {
walltype *pWall = &wall[nWall];
switch (event.cmd) {
case kCmdLock:
pXWall->locked = 1;
@ -1723,28 +1755,30 @@ void OperateWall(int nWall, XWALL *pXWall, EVENT event) {
return;
}
// by NoOne: make 1-Way switch type for walls to work...
if (gModernMap) {
// by NoOne: make 1-Way switch type for walls to work...
switch (pWall->type) {
case kSwitchOneWay:
switch (event.cmd) {
case kCmdOff:
SetWallState(nWall, pXWall, 0);
break;
case kCmdOn:
SetWallState(nWall, pXWall, 1);
break;
default:
SetWallState(nWall, pXWall, pXWall->restState ^ 1);
break;
}
return;
case kSwitchOneWay:
switch (event.cmd) {
case kCmdOff:
SetWallState(nWall, pXWall, 0);
break;
case kCmdOn:
SetWallState(nWall, pXWall, 1);
break;
default:
SetWallState(nWall, pXWall, pXWall->restState ^ 1);
break;
}
return;
default:
break;
}
} else {
}
switch (pWall->type) {
switch (pWall->type) {
case kWallGib:
if (GetWallType(nWall) != pWall->type) break;
char bStatus;
@ -1771,22 +1805,22 @@ void OperateWall(int nWall, XWALL *pXWall, EVENT event) {
}
}
return;
}
}
switch (event.cmd) {
case kCmdOff:
SetWallState(nWall, pXWall, 0);
break;
case kCmdOn:
SetWallState(nWall, pXWall, 1);
break;
default:
SetWallState(nWall, pXWall, pXWall->state ^ 1);
break;
switch (event.cmd) {
case kCmdOff:
SetWallState(nWall, pXWall, 0);
break;
case kCmdOn:
SetWallState(nWall, pXWall, 1);
break;
default:
SetWallState(nWall, pXWall, pXWall->state ^ 1);
break;
}
return;
}
}
void SectorStartSound(int nSector, int nState)
@ -3758,6 +3792,14 @@ bool dudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget)
}
void disableQAVPlayers(spritetype* pException) {
for (int nSprite = headspritestat[kStatModernPlayQAV]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (nSprite == pException->index || sprite[nSprite].extra < 0) continue;
else if (xsprite[sprite[nSprite].extra].state == 1)
evPost(nSprite, 3, 0, kCmdOff);
}
}
// by NoOne: this function required if monsters in genIdle ai state. It wakes up monsters
// when kModernDudeTargetChanger goes to off state, so they won't ignore the world.
void activateDudes(int rx) {

View file

@ -77,6 +77,7 @@ void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite);
void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex);
void TeleFrag(int nKiller, int nSector);
bool valueIsBetween(int val, int min, int max);
void disableQAVPlayers(spritetype* pException);
// -------------------------------------------------------

View file

@ -35,5 +35,5 @@ void WeaponLower(PLAYER *pPlayer);
char WeaponUpgrade(PLAYER *pPlayer, char newWeapon);
void WeaponProcess(PLAYER *pPlayer);
void sub_51340(spritetype *pMissile, int a2);
void StartQAV(PLAYER* pPlayer, int nWeaponQAV, int a3 = -1, char a4 = 0);
END_BLD_NS