Merge branch 'master' into powerslave

This commit is contained in:
Christoph Oelckers 2019-11-28 17:07:11 +01:00
commit 115675417a
57 changed files with 1488 additions and 1443 deletions

View file

@ -110,6 +110,7 @@ static FORCE_INLINE int FX_Pan3D(int handle, int angle, int distance)
return FX_CheckMVErr(MV_Pan3D(handle, angle, distance)); return FX_CheckMVErr(MV_Pan3D(handle, angle, distance));
} }
static FORCE_INLINE int FX_SoundActive(int handle) { return MV_VoicePlaying(handle); } static FORCE_INLINE int FX_SoundActive(int handle) { return MV_VoicePlaying(handle); }
static FORCE_INLINE int FX_SoundValidAndActive(int handle) { return handle > 0 && MV_VoicePlaying(handle); }
static FORCE_INLINE int FX_SoundsPlaying(void) { return MV_VoicesPlaying(); } static FORCE_INLINE int FX_SoundsPlaying(void) { return MV_VoicesPlaying(); }
static FORCE_INLINE int FX_StopSound(int handle) { return FX_CheckMVErr(MV_Kill(handle)); } static FORCE_INLINE int FX_StopSound(int handle) { return FX_CheckMVErr(MV_Kill(handle)); }
static FORCE_INLINE int FX_StopAllSounds(void) { return FX_CheckMVErr(MV_KillAllVoices()); } static FORCE_INLINE int FX_StopAllSounds(void) { return FX_CheckMVErr(MV_KillAllVoices()); }

View file

@ -2737,7 +2737,7 @@ void actInit(bool bSaveLoad) {
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
pSprite->cstat |= 4096 + CSTAT_SPRITE_BLOCK_HITSCAN + CSTAT_SPRITE_BLOCK; pSprite->cstat |= 4096 + CSTAT_SPRITE_BLOCK_HITSCAN + CSTAT_SPRITE_BLOCK;
seqStartId = getSeqStartId(pXSprite); // by NoOne: Custom Dude stores it's SEQ in data2 seqStartId = genDudeSeqStartId(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->sysData1 = pXSprite->data3; // by NoOne move sndStartId to sysData1, because data3 used by the game;
pXSprite->data3 = 0; pXSprite->data3 = 0;
break; break;
@ -3127,10 +3127,10 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
if ((gSysRes.Lookup(pXSprite->data2 + 15, "SEQ") || gSysRes.Lookup(pXSprite->data2 + 16, "SEQ")) && pXSprite->medium == kMediumNormal) { if ((gSysRes.Lookup(pXSprite->data2 + 15, "SEQ") || gSysRes.Lookup(pXSprite->data2 + 16, "SEQ")) && pXSprite->medium == kMediumNormal) {
if (gSysRes.Lookup(pXSprite->data2 + 3, "SEQ")) { if (gSysRes.Lookup(pXSprite->data2 + 3, "SEQ")) {
pSprite->type = kDudeModernCustomBurning; pSprite->type = kDudeModernCustomBurning;
if (pXSprite->data2 == kDefaultAnimationBase) // don't inherit palette for burning if using default animation if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation
pSprite->pal = 0; pSprite->pal = 0;
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnGoto); aiGenDudeNewState(pSprite, &genDudeBurnGoto);
actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth); actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
if (pXSprite->burnTime <= 0) pXSprite->burnTime = 1200; if (pXSprite->burnTime <= 0) pXSprite->burnTime = 1200;
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360; gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
@ -3147,7 +3147,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
} else { } else {
pXSprite->locked = 1; // lock while transforming pXSprite->locked = 1; // lock while transforming
aiSetGenIdleState(pSprite, pXSprite); // set idle state aiSetGenIdleState(pSprite, pXSprite); // set idle state
if (pXSprite->key > 0) // drop keys if (pXSprite->key > 0) // drop keys
@ -3156,13 +3156,13 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
if (pXSprite->dropMsg > 0) // drop items if (pXSprite->dropMsg > 0) // drop items
actDropObject(pSprite, pXSprite->dropMsg); actDropObject(pSprite, pXSprite->dropMsg);
pSprite->flags &= ~kPhysMove; xvel[pSprite->index] = yvel[pSprite->index] = 0; pSprite->flags &= ~kPhysMove; xvel[pSprite->index] = yvel[pSprite->index] = 0;
int seqId = pXSprite->data2 + 18; int seqId = pXSprite->data2 + 18;
if (!gSysRes.Lookup(seqId, "SEQ")) { if (!gSysRes.Lookup(seqId, "SEQ")) {
seqKill(3, nXSprite); seqKill(3, nXSprite);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTransforming); playGenDudeSound(pSprite, kGenDudeSndTransforming);
spritetype* pEffect = gFX.fxSpawn((FX_ID)52, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, pSprite->ang); spritetype* pEffect = gFX.fxSpawn((FX_ID)52, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, pSprite->ang);
if (pEffect != NULL) { if (pEffect != NULL) {
pEffect->cstat = CSTAT_SPRITE_ALIGNMENT_FACING; pEffect->cstat = CSTAT_SPRITE_ALIGNMENT_FACING;
@ -3187,7 +3187,10 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
return; return;
} }
seqSpawn(seqId, 3, nXSprite, -1); seqSpawn(seqId, 3, nXSprite, -1);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTransforming); playGenDudeSound(pSprite, kGenDudeSndTransforming);
pXSprite->sysData1 = kGenDudeTransformStatus; // in transform
return; return;
} }
break; break;
@ -3287,7 +3290,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
switch (pSprite->type) { switch (pSprite->type) {
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathExplode); playGenDudeSound(pSprite, kGenDudeSndDeathExplode);
break; break;
case kDudeCultistTommy: case kDudeCultistTommy:
case kDudeCultistShotgun: case kDudeCultistShotgun:
@ -3406,26 +3409,25 @@ 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;
case kDudeModernCustom: case kDudeModernCustom:
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathNormal); playGenDudeSound(pSprite, kGenDudeSndDeathNormal);
if (nSeq == 3) { if (nSeq == 3) {
bool seq15 = gSysRes.Lookup(pXSprite->data2 + 15, "SEQ"); bool seq16 = gSysRes.Lookup(pXSprite->data2 + 16, "SEQ"); GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
if (seq15 && seq16) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, nDudeToGibClient2); if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
else if (seq16) seqSpawn(16 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2); else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
else if (seq15) seqSpawn(15 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2); else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
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, nDudeToGibClient2);
else seqKill(3, nXSprite); else seqSpawn(1 + pXSprite->data2, 3, nXSprite, nDudeToGibClient2);
} else { } else {
seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, nDudeToGibClient1); seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
} }
pXSprite->txID = 0; // to avoid second trigger. pXSprite->txID = 0; // to avoid second trigger.
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning: {
{ playGenDudeSound(pSprite, kGenDudeSndDeathExplode);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathExplode);
damageType = DAMAGE_TYPE_3; damageType = DAMAGE_TYPE_3;
if (Chance(0x4000)) { if (Chance(0x4000)) {
@ -3436,14 +3438,11 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
GibSprite(pSprite, GIBTYPE_7, &gibPos, &gibVel); GibSprite(pSprite, GIBTYPE_7, &gibPos, &gibVel);
} }
int seqId = pXSprite->data2; GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
bool seq15 = gSysRes.Lookup(pXSprite->data2 + 15, "SEQ"); bool seq16 = gSysRes.Lookup(pXSprite->data2 + 16, "SEQ"); if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
if (seq15 && seq16) seqId += (15 + Random(2)); else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
else if (seq16) seqId += 16; else seqSpawn(1 + pXSprite->data2, 3, nXSprite, nDudeToGibClient1);
else seqId += 15;
seqSpawn(seqId, 3, nXSprite, nDudeToGibClient1);
break; break;
} }
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
@ -3571,29 +3570,37 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1);
break; break;
case kDudePodGreen: case kDudePodGreen:
if (Chance(0x4000) && nSeq == 3)
sfxPlay3DSound(pSprite, 2205, -1, 0);
else
sfxPlay3DSound(pSprite, 2203+Random(2), -1, 0);
seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1);
break;
case kDudeTentacleGreen: case kDudeTentacleGreen:
if (damage == 5)
sfxPlay3DSound(pSprite, 2471, -1, 0);
else
sfxPlay3DSound(pSprite, 2472, -1, 0);
seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1);
break;
case kDudePodFire: case kDudePodFire:
if (damage == 5)
sfxPlay3DSound(pSprite, 2451, -1, 0);
else
sfxPlay3DSound(pSprite, 2452, -1, 0);
seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1);
break;
case kDudeTentacleFire: case kDudeTentacleFire:
sfxPlay3DSound(pSprite, 2501, -1, 0); if ((pSprite->cstat & CSTAT_SPRITE_YFLIP)) pSprite->cstat &= ~CSTAT_SPRITE_YFLIP;
seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); switch (pSprite->type) {
case kDudePodGreen:
if (Chance(0x4000) && nSeq == 3)
sfxPlay3DSound(pSprite, 2205, -1, 0);
else
sfxPlay3DSound(pSprite, 2203 + Random(2), -1, 0);
seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1);
break;
case kDudeTentacleGreen:
if (damage == 5)
sfxPlay3DSound(pSprite, 2471, -1, 0);
else
sfxPlay3DSound(pSprite, 2472, -1, 0);
seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1);
break;
case kDudePodFire:
if (damage == 5)
sfxPlay3DSound(pSprite, 2451, -1, 0);
else
sfxPlay3DSound(pSprite, 2452, -1, 0);
seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1);
break;
case kDudeTentacleFire:
sfxPlay3DSound(pSprite, 2501, -1, 0);
seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1);
break;
}
break; break;
case kDudePodMother: case kDudePodMother:
if (Chance(0x4000) && nSeq == 3) if (Chance(0x4000) && nSeq == 3)
@ -4717,7 +4724,10 @@ void MoveDude(spritetype *pSprite)
PLAYER *pPlayer = NULL; PLAYER *pPlayer = NULL;
if (IsPlayerSprite(pSprite)) if (IsPlayerSprite(pSprite))
pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; pPlayer = &gPlayer[pSprite->type-kDudePlayer1];
dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
consoleSysMsg("pSprite->type >= kDudeBase && pSprite->type < kDudeMax");
return;
}
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase]; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase];
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite, &top, &bottom); GetSpriteExtents(pSprite, &top, &bottom);
@ -6141,9 +6151,10 @@ void actProcessSprites(void)
} }
// By NoOne: handle incarnations of custom dude // By NoOne: handle incarnations of custom dude
if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->health <= 0 && seqGetStatus(3, nXSprite) < 0) { if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->health <= 0 && pXSprite->sysData1 == kGenDudeTransformStatus) {
xvel[pSprite->index] = ClipLow(xvel[pSprite->index] >> 4, 0); yvel[pSprite->index] = ClipLow(yvel[pSprite->index] >> 4, 0);
XSPRITE* pXIncarnation = getNextIncarnation(pXSprite); XSPRITE* pXIncarnation = getNextIncarnation(pXSprite);
if (pXIncarnation != NULL) { if (seqGetStatus(3, nXSprite) < 0 && pXIncarnation != NULL) {
spritetype* pIncarnation = &sprite[pXIncarnation->reference]; spritetype* pIncarnation = &sprite[pXIncarnation->reference];
pXSprite->key = pXSprite->dropMsg = pXSprite->locked = 0; pXSprite->key = pXSprite->dropMsg = pXSprite->locked = 0;
@ -6158,7 +6169,6 @@ void actProcessSprites(void)
// trigger dude death before transform // trigger dude death before transform
trTriggerSprite(nSprite, pXSprite, kCmdOff, pSprite->owner); trTriggerSprite(nSprite, pXSprite, kCmdOff, pSprite->owner);
pSprite->type = pIncarnation->type; pSprite->type = pIncarnation->type;
pSprite->flags = pIncarnation->flags; pSprite->flags = pIncarnation->flags;
pSprite->pal = pIncarnation->pal; pSprite->pal = pIncarnation->pal;
@ -6211,8 +6221,8 @@ void actProcessSprites(void)
break; break;
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
seqId = getSeqStartId(pXSprite); seqId = genDudeSeqStartId(pXSprite);
getSpriteMassBySize(pSprite); // create or refresh mass cache genDudePrepare(pSprite, kGenDudePropertyMass);
fallthrough__; // go below fallthrough__; // go below
default: default:
seqSpawn(seqId, 3, nXSprite, -1); seqSpawn(seqId, 3, nXSprite, -1);
@ -7510,7 +7520,7 @@ spritetype* actSpawnCustomDude(spritetype* pSprite, int nDist) {
pXDude->data3 = 0; pXDude->data3 = 0;
// spawn seq // spawn seq
seqSpawn(getSeqStartId(pXDude), 3, pDude->extra, -1); seqSpawn(genDudeSeqStartId(pXDude), 3, pDude->extra, -1);
// inherit movement speed. // inherit movement speed.
pXDude->busyTime = pXSource->busyTime; pXDude->busyTime = pXSource->busyTime;
@ -7550,6 +7560,12 @@ spritetype* actSpawnCustomDude(spritetype* pSprite, int nDist) {
} }
} }
// inherit sprite size (useful for seqs with zero repeats)
if (pSource->flags & kModernTypeFlag2) {
pDude->xrepeat = pSource->xrepeat;
pDude->yrepeat = pSource->yrepeat;
}
aiInitSprite(pDude); aiInitSprite(pDude);
return pDude; return pDude;
} }
@ -7650,7 +7666,7 @@ int getSpriteMassBySize(spritetype* pSprite) {
cached->picnum = pSprite->picnum; cached->seqId = seqId; cached->picnum = pSprite->picnum; cached->seqId = seqId;
cached->clipdist = pSprite->clipdist; cached->clipdist = pSprite->clipdist;
viewSetSystemMessage("MASS: %d", cached->mass); //viewSetSystemMessage("MASS: %d", cached->mass);
return cached->mass; return cached->mass;
} }

View file

@ -110,25 +110,20 @@ void aiPlay3DSound(spritetype *pSprite, int a2, AI_SFX_PRIORITY a3, int a4)
void aiNewState(spritetype *pSprite, XSPRITE *pXSprite, AISTATE *pAIState) void aiNewState(spritetype *pSprite, XSPRITE *pXSprite, AISTATE *pAIState)
{ {
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase]; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase];
pXSprite->stateTimer = pAIState->at8; pXSprite->stateTimer = pAIState->stateTicks;
pXSprite->aiState = pAIState; pXSprite->aiState = pAIState;
int seqStartId = pDudeInfo->seqStartID; int seqStartId = pDudeInfo->seqStartID;
if (pAIState->at0 >= 0) { if (pAIState->seqId >= 0) {
// By NoOne: Custom dude uses data2 to keep it's seqStartId seqStartId += pAIState->seqId;
switch (pSprite->type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
seqStartId = pXSprite->data2;
break;
}
seqStartId += pAIState->at0;
if (gSysRes.Lookup(seqStartId, "SEQ")) if (gSysRes.Lookup(seqStartId, "SEQ"))
seqSpawn(seqStartId, 3, pSprite->extra, pAIState->at4); seqSpawn(seqStartId, 3, pSprite->extra, pAIState->funcId);
} }
if (pAIState->atc) pAIState->atc(pSprite, pXSprite); // entry function if (pAIState->enterFunc)
pAIState->enterFunc(pSprite, pXSprite);
} }
bool dudeIsImmune(spritetype* pSprite, int dmgType) { bool dudeIsImmune(spritetype* pSprite, int dmgType) {
if (dmgType < 0 || dmgType > 6) return true; if (dmgType < 0 || dmgType > 6) return true;
else if (dudeInfo[pSprite->type - kDudeBase].startDamage[dmgType] == 0) return true; else if (dudeInfo[pSprite->type - kDudeBase].startDamage[dmgType] == 0) return true;
@ -417,31 +412,18 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
pDudeExtraE->at8 = 1; pDudeExtraE->at8 = 1;
pDudeExtraE->at0 = 0; pDudeExtraE->at0 = 0;
if (pXSprite->target == -1) { if (pXSprite->target == -1) {
if (spriteIsUnderwater(pSprite, false)) if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeSearchW);
aiNewState(pSprite, pXSprite, &GDXGenDudeSearchW); else aiGenDudeNewState(pSprite, &genDudeSearchL);
else { } else {
aiNewState(pSprite, pXSprite, &GDXGenDudeSearchL); if (Chance(0x4000)) playGenDudeSound(pSprite, kGenDudeSndTargetSpot);
if (Chance(0x4000)) if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeChaseW);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTargetSpot); else aiGenDudeNewState(pSprite, &genDudeChaseL);
}
}
else {
if (Chance(0x4000))
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTargetSpot);
if (spriteIsUnderwater(pSprite, false))
aiNewState(pSprite, pXSprite, &GDXGenDudeChaseW);
else
aiNewState(pSprite, pXSprite, &GDXGenDudeChaseL);
} }
break; break;
} }
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
if (pXSprite->target == -1) if (pXSprite->target == -1) aiGenDudeNewState(pSprite, &genDudeBurnSearch);
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnSearch); else aiGenDudeNewState(pSprite, &genDudeBurnChase);
else
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnChase);
break; break;
case kDudeCultistTommyProne: { case kDudeCultistTommyProne: {
DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1;
@ -1026,7 +1008,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
if (Chance(0x2000) && gDudeExtra[pSprite->extra].at0 < (int)gFrameClock) { if (Chance(0x2000) && gDudeExtra[pSprite->extra].at0 < (int)gFrameClock) {
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndBurning); playGenDudeSound(pSprite, kGenDudeSndBurning);
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360; gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
} }
if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400; if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400;
@ -1034,63 +1016,61 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
pSprite->type = kDudeModernCustom; pSprite->type = kDudeModernCustom;
pXSprite->burnTime = 0; pXSprite->burnTime = 0;
pXSprite->health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before. pXSprite->health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before.
aiNewState(pSprite, pXSprite, &GDXGenDudeGotoW); aiGenDudeNewState(pSprite, &genDudeGotoW);
} }
break; break;
case kDudeModernCustom: case kDudeModernCustom: {
{ GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
if (nDmgType == DAMAGE_TYPE_1) { if (nDmgType == DAMAGE_TYPE_1) {
if (pXSprite->health <= pDudeInfo->fleeHealth) { if (pXSprite->health > pDudeInfo->fleeHealth) break;
if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) { else if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) {
removeDudeStuff(pSprite); removeDudeStuff(pSprite);
if (pExtra->curWeapon >= kTrapExploder && pExtra->curWeapon < (kTrapExploder + kExplodeMax) - 1)
doExplosion(pSprite, pXSprite->data1 - kTrapExploder);
if (pXSprite->data1 >= kTrapExploder && pXSprite->data1 < (kTrapExploder + kExplodeMax) - 1) if (spriteIsUnderwater(pSprite, false)) {
doExplosion(pSprite, pXSprite->data1 - kTrapExploder); pXSprite->health = 0;
break;
if (spriteIsUnderwater(pSprite, false)) {
pXSprite->health = 0;
break;
}
if (pXSprite->burnTime <= 0)
pXSprite->burnTime = 1200;
if ((gSysRes.Lookup(pXSprite->data2 + 15, "SEQ") || gSysRes.Lookup(pXSprite->data2 + 16, "SEQ"))
&& gSysRes.Lookup(pXSprite->data2 + 3, "SEQ")) {
aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndBurning);
pSprite->type = kDudeModernCustomBurning;
if (pXSprite->data2 == kDefaultAnimationBase) // don't inherit palette for burning if using default animation
pSprite->pal = 0;
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnGoto);
actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
evKill(nSprite, 3, kCallbackFXFlameLick);
}
} else {
actKillDude(nSource, pSprite, DAMAGE_TYPE_0, 65535);
} }
if (pXSprite->burnTime <= 0)
pXSprite->burnTime = 1200;
if (pExtra->canBurn && pExtra->availDeaths[DAMAGE_TYPE_1] > 0) {
aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1);
playGenDudeSound(pSprite, kGenDudeSndBurning);
pSprite->type = kDudeModernCustomBurning;
if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation
pSprite->pal = 0;
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
evKill(nSprite, 3, kCallbackFXFlameLick);
}
} else {
actKillDude(nSource, pSprite, DAMAGE_TYPE_0, 65535);
} }
} else if (!inDodge(pXSprite->aiState)) { } else if (canWalk(pSprite) && !inDodge(pXSprite->aiState) && !inRecoil(pXSprite->aiState)) {
if (inIdle(pXSprite->aiState) || inSearch(pXSprite->aiState) || Chance(getDodgeChance(pSprite))) {
if (Chance(getDodgeChance(pSprite)) || inIdle(pXSprite->aiState)) {
if (!spriteIsUnderwater(pSprite, false)) { if (!spriteIsUnderwater(pSprite, false)) {
if (!canDuck(pSprite) || !sub_5BDA8(pSprite, 14)) aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgL); if (!canDuck(pSprite) || !sub_5BDA8(pSprite, 14)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL);
else aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgD); else aiGenDudeNewState(pSprite, &genDudeDodgeShortD);
if (Chance(0x0200)) if (Chance(0x0200))
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit); playGenDudeSound(pSprite, kGenDudeSndGotHit);
} else if (sub_5BDA8(pSprite, 13)) {
aiGenDudeNewState(pSprite, &genDudeDodgeShortW);
} }
else if (sub_5BDA8(pSprite, 13))
aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgW);
} }
} }
break; break;
} }
case kDudeCultistBeast: case kDudeCultistBeast:
@ -1123,43 +1103,53 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
{ {
char v4 = Chance(0x8000); char v4 = Chance(0x8000);
DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra]; DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra];
if (pSprite->statnum == kStatDude && (pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) if (pSprite->statnum == kStatDude && (pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) {
{
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase]; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase];
switch (pSprite->type) switch (pSprite->type) {
{ case kDudeModernCustom: {
case kDudeModernCustom: GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); int rChance = getRecoilChance(pSprite);
{ if (pExtra->canElectrocute && pDudeExtra->at4 && !spriteIsUnderwater(pSprite, false)) {
int mass = getSpriteMassBySize(pSprite); int chance4 = getRecoilChance(pSprite); bool chance3 = Chance(chance4);
if (pDudeExtra->at4 && (inIdle(pXSprite->aiState) || mass < 155 || (mass >= 155 && chance3)) && !spriteIsUnderwater(pSprite, false))
{
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit);
if (gSysRes.Lookup(pXSprite->data2 + 4, "SEQ")) { if (Chance(rChance << 3) || (dudeIsMelee(pXSprite) && Chance(rChance << 4))) aiGenDudeNewState(pSprite, &genDudeRecoilTesla);
GDXGenDudeRTesla.at18 = (Chance(chance4 * 2) ? &GDXGenDudeDodgeL : &GDXGenDudeDodgeDmgL); else if (pExtra->canRecoil && Chance(rChance)) aiGenDudeNewState(pSprite, &genDudeRecoilL);
aiNewState(pSprite, pXSprite, &GDXGenDudeRTesla); else if (canWalk(pSprite)) {
if (Chance(rChance >> 2)) aiGenDudeNewState(pSprite, &genDudeDodgeL);
else if (Chance(rChance >> 1)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL);
} }
else if (canDuck(pSprite) && (Chance(chance4) || gGameOptions.nDifficulty == 0)) aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilD);
else if (canSwim(pSprite) && spriteIsUnderwater(pSprite, false)) aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilW); } else if (pExtra->canRecoil && Chance(rChance)) {
else aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilL);
break; if (inDuck(pXSprite->aiState) && Chance(rChance >> 2)) aiGenDudeNewState(pSprite, &genDudeRecoilD);
else if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeRecoilW);
else aiGenDudeNewState(pSprite, &genDudeRecoilL);
} }
short rState = inRecoil(pXSprite->aiState);
if (rState > 0) {
if (!canWalk(pSprite)) {
if (rState == 1) pXSprite->aiState->nextState = &genDudeChaseNoWalkL;
else if (rState == 2) pXSprite->aiState->nextState = &genDudeChaseNoWalkD;
else pXSprite->aiState->nextState = &genDudeChaseNoWalkW;
if (inDodge(pXSprite->aiState)) { } else if (!dudeIsMelee(pXSprite) || Chance(rChance >> 2)) {
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit); if (rState == 1) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeL : &genDudeDodgeShortL);
break; else if (rState == 2) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeD : &genDudeDodgeShortD);
} else if (rState == 1) pXSprite->aiState->nextState = (Chance(rChance) ? &genDudeDodgeW : &genDudeDodgeShortW);
if (inIdle(pXSprite->aiState) || chance3 || Chance(getRecoilChance(pSprite)) || (!dudeIsMelee(pXSprite) && mass < 155)) { }
else if (rState == 1) pXSprite->aiState->nextState = &genDudeChaseL;
else if (rState == 2) pXSprite->aiState->nextState = &genDudeChaseD;
else pXSprite->aiState->nextState = &genDudeChaseW;
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit); playGenDudeSound(pSprite, kGenDudeSndGotHit);
if (canDuck(pSprite) && (Chance(chance4) || gGameOptions.nDifficulty == 0)) aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilD);
else if (canSwim(pSprite) && spriteIsUnderwater(pSprite, false)) aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilW);
else aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilL);
} }
pDudeExtra->at4 = 0;
break; break;
} }
case kDudeCultistTommy: case kDudeCultistTommy:
@ -1193,7 +1183,7 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
aiNewState(pSprite, pXSprite, &cultistBurnGoto); aiNewState(pSprite, pXSprite, &cultistBurnGoto);
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnGoto); aiGenDudeNewState(pSprite, &genDudeBurnGoto);
break; break;
case kDudeZombieButcher: case kDudeZombieButcher:
aiPlay3DSound(pSprite, 1202, AI_SFX_PRIORITY_2, -1); aiPlay3DSound(pSprite, 1202, AI_SFX_PRIORITY_2, -1);
@ -1453,45 +1443,39 @@ void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite)
} }
} }
void aiProcessDudes(void) void aiProcessDudes(void) {
{
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) { for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
spritetype *pSprite = &sprite[nSprite]; spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags & 32) continue; if (pSprite->flags & 32) continue;
int nXSprite = pSprite->extra; int nXSprite = pSprite->extra;
XSPRITE *pXSprite = &xsprite[nXSprite]; XSPRITE *pXSprite = &xsprite[nXSprite]; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue; if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue;
pXSprite->stateTimer = ClipLow(pXSprite->stateTimer-4, 0); pXSprite->stateTimer = ClipLow(pXSprite->stateTimer-4, 0);
if (pXSprite->aiState->at10) if (pSprite->type >= kDudeVanillaMax && pSprite->type < kDudeMax)
pXSprite->aiState->at10(pSprite, pXSprite); genDudeProcess(pSprite, pXSprite);
if (pXSprite->aiState->at14 && (gFrame&3) == (nSprite&3))
pXSprite->aiState->at14(pSprite, pXSprite);
if (pXSprite->stateTimer == 0 && pXSprite->aiState->at18) {
if (pXSprite->aiState->at8 > 0)
aiNewState(pSprite, pXSprite, pXSprite->aiState->at18);
else if (seqGetStatus(3, nXSprite) < 0)
aiNewState(pSprite, pXSprite, pXSprite->aiState->at18);
}
if (pXSprite->health > 0 && ((pDudeInfo->hinderDamage << 4) <= cumulDamage[nXSprite])) { else {
pXSprite->data3 = cumulDamage[nXSprite];
RecoilDude(pSprite, pXSprite); if (pXSprite->aiState->moveFunc)
} pXSprite->aiState->moveFunc(pSprite, pXSprite);
if (pSprite->type >= kDudeVanillaMax) { if (pXSprite->aiState->thinkFunc && (gFrame & 3) == (nSprite & 3))
switch (pSprite->type) { pXSprite->aiState->thinkFunc(pSprite, pXSprite);
case kDudeModernCustom:
case kDudeModernCustomBurning: if (pXSprite->stateTimer == 0 && pXSprite->aiState->nextState) {
GENDUDEEXTRA* pExtra = &gGenDudeExtra[pSprite->index]; if (pXSprite->aiState->stateTicks > 0)
if (pExtra->slaveCount > 0) updateTargetOfSlaves(pSprite); aiNewState(pSprite, pXSprite, pXSprite->aiState->nextState);
if (pExtra->nLifeLeech >= 0) updateTargetOfLeech(pSprite); else if (seqGetStatus(3, nXSprite) < 0)
break; aiNewState(pSprite, pXSprite, pXSprite->aiState->nextState);
} }
if (pXSprite->health > 0 && ((pDudeInfo->hinderDamage << 4) <= cumulDamage[nXSprite])) {
pXSprite->data3 = cumulDamage[nXSprite];
RecoilDude(pSprite, pXSprite);
}
} }
} }
memset(cumulDamage, 0, sizeof(cumulDamage)); memset(cumulDamage, 0, sizeof(cumulDamage));
} }
@ -1520,12 +1504,12 @@ void aiInitSprite(spritetype *pSprite)
case kDudeModernCustom: { case kDudeModernCustom: {
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1;
pDudeExtraE->at8 = pDudeExtraE->at0 = 0; pDudeExtraE->at8 = pDudeExtraE->at0 = 0;
aiNewState(pSprite, pXSprite, &GDXGenDudeIdleL); aiGenDudeNewState(pSprite, &genDudeIdleL);
genDudePrepare(pSprite); genDudePrepare(pSprite);
break; break;
} }
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnGoto); aiGenDudeNewState(pSprite, &genDudeBurnGoto);
pXSprite->burnTime = 1200; pXSprite->burnTime = 1200;
break; break;
case kDudeCultistTommy: case kDudeCultistTommy:

View file

@ -32,13 +32,13 @@ BEGIN_BLD_NS
struct AISTATE { struct AISTATE {
int stateType; // By NoOne: current type of state. Basically required for kModernDudeTargetChanger, but can be used for something else. int stateType; // By NoOne: current type of state. Basically required for kModernDudeTargetChanger, but can be used for something else.
int at0; // seq int seqId;
int at4; // seq callback int funcId; // seq callback
int at8; int stateTicks;
void(*atc)(spritetype *, XSPRITE *); void(*enterFunc)(spritetype *, XSPRITE *);
void(*at10)(spritetype *, XSPRITE *); void(*moveFunc)(spritetype *, XSPRITE *);
void(*at14)(spritetype *, XSPRITE *); void(*thinkFunc)(spritetype *, XSPRITE *);
AISTATE *at18; // next state ? AISTATE *nextState;
}; };
extern AISTATE aiState[]; extern AISTATE aiState[];
@ -86,6 +86,7 @@ struct TARGETTRACK {
extern int dword_138BB0[5]; extern int dword_138BB0[5];
extern DUDEEXTRA gDudeExtra[]; extern DUDEEXTRA gDudeExtra[];
extern int gDudeSlope[]; extern int gDudeSlope[];
extern int cumulDamage[];
bool sub_5BDA8(spritetype *pSprite, int nSeq); bool sub_5BDA8(spritetype *pSprite, int nSeq);
void aiPlay3DSound(spritetype *pSprite, int a2, AI_SFX_PRIORITY a3, int a4); void aiPlay3DSound(spritetype *pSprite, int a2, AI_SFX_PRIORITY a3, int a4);
@ -104,6 +105,7 @@ void aiProcessDudes(void);
void aiInit(void); void aiInit(void);
void aiInitSprite(spritetype *pSprite); void aiInitSprite(spritetype *pSprite);
bool CanMove(spritetype* pSprite, int a2, int nAngle, int nRange); bool CanMove(spritetype* pSprite, int a2, int nAngle, int nRange);
void RecoilDude(spritetype* pSprite, XSPRITE* pXSprite);
// By NoOne: this function required for kModernDudeTargetChanger // By NoOne: this function required for kModernDudeTargetChanger
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite); void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite);

View file

@ -81,11 +81,11 @@ AISTATE tinycalebBurnGoto = { kAiStateMove, 3, -1, 3600, NULL, aiMoveForward, th
AISTATE tinycalebBurnSearch = { kAiStateSearch, 3, -1, 3600, NULL, aiMoveForward, thinkSearch, &tinycalebBurnSearch }; AISTATE tinycalebBurnSearch = { kAiStateSearch, 3, -1, 3600, NULL, aiMoveForward, thinkSearch, &tinycalebBurnSearch };
AISTATE tinycalebBurnAttack = { kAiStateChase, 3, nBurnClient, 120, NULL, NULL, NULL, &tinycalebBurnChase }; AISTATE tinycalebBurnAttack = { kAiStateChase, 3, nBurnClient, 120, NULL, NULL, NULL, &tinycalebBurnChase };
AISTATE GDXGenDudeBurnIdle = { kAiStateIdle, 3, -1, 0, NULL, NULL, aiThinkTarget, NULL }; AISTATE genDudeBurnIdle = { kAiStateIdle, 3, -1, 0, NULL, NULL, aiThinkTarget, NULL };
AISTATE GDXGenDudeBurnChase = { kAiStateChase, 3, -1, 0, NULL, aiMoveForward, thinkChase, NULL }; AISTATE genDudeBurnChase = { kAiStateChase, 3, -1, 0, NULL, aiMoveForward, thinkChase, NULL };
AISTATE GDXGenDudeBurnGoto = { kAiStateMove, 3, -1, 3600, NULL, aiMoveForward, thinkGoto, &GDXGenDudeBurnSearch }; AISTATE genDudeBurnGoto = { kAiStateMove, 3, -1, 3600, NULL, aiMoveForward, thinkGoto, &genDudeBurnSearch };
AISTATE GDXGenDudeBurnSearch = { kAiStateSearch, 3, -1, 3600, NULL, aiMoveForward, thinkSearch, &GDXGenDudeBurnSearch }; AISTATE genDudeBurnSearch = { kAiStateSearch, 3, -1, 3600, NULL, aiMoveForward, thinkSearch, &genDudeBurnSearch };
AISTATE GDXGenDudeBurnAttack = { kAiStateChase, 3, nBurnClient, 120, NULL, NULL, NULL, &GDXGenDudeBurnChase }; AISTATE genDudeBurnAttack = { kAiStateChase, 3, nBurnClient, 120, NULL, NULL, NULL, &genDudeBurnChase };
static void BurnSeqCallback(int, int) static void BurnSeqCallback(int, int)
{ {
@ -129,7 +129,7 @@ static void thinkGoto(spritetype *pSprite, XSPRITE *pXSprite)
aiNewState(pSprite, pXSprite, &tinycalebBurnSearch); aiNewState(pSprite, pXSprite, &tinycalebBurnSearch);
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnSearch); aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break; break;
} }
} }
@ -161,7 +161,7 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
aiNewState(pSprite, pXSprite, &tinycalebBurnGoto); aiNewState(pSprite, pXSprite, &tinycalebBurnGoto);
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnGoto); aiNewState(pSprite, pXSprite, &genDudeBurnGoto);
break; break;
} }
return; return;
@ -197,7 +197,7 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
aiNewState(pSprite, pXSprite, &tinycalebBurnSearch); aiNewState(pSprite, pXSprite, &tinycalebBurnSearch);
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnSearch); aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break; break;
} }
return; return;
@ -235,7 +235,7 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
aiNewState(pSprite, pXSprite, &tinycalebBurnAttack); aiNewState(pSprite, pXSprite, &tinycalebBurnAttack);
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnSearch); aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break; break;
} }
} }
@ -265,7 +265,7 @@ static void thinkChase(spritetype *pSprite, XSPRITE *pXSprite)
aiNewState(pSprite, pXSprite, &tinycalebBurnGoto); aiNewState(pSprite, pXSprite, &tinycalebBurnGoto);
break; break;
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
aiNewState(pSprite, pXSprite, &GDXGenDudeBurnSearch); aiNewState(pSprite, pXSprite, &genDudeBurnSearch);
break; break;
} }
pXSprite->target = -1; pXSprite->target = -1;

View file

@ -50,10 +50,10 @@ extern AISTATE tinycalebBurnChase;
extern AISTATE tinycalebBurnGoto; extern AISTATE tinycalebBurnGoto;
extern AISTATE tinycalebBurnSearch; extern AISTATE tinycalebBurnSearch;
extern AISTATE tinycalebBurnAttack; extern AISTATE tinycalebBurnAttack;
extern AISTATE GDXGenDudeBurnIdle; extern AISTATE genDudeBurnIdle;
extern AISTATE GDXGenDudeBurnChase; extern AISTATE genDudeBurnChase;
extern AISTATE GDXGenDudeBurnGoto; extern AISTATE genDudeBurnGoto;
extern AISTATE GDXGenDudeBurnSearch; extern AISTATE genDudeBurnSearch;
extern AISTATE GDXGenDudeBurnAttack; extern AISTATE genDudeBurnAttack;
END_BLD_NS END_BLD_NS

File diff suppressed because it is too large Load diff

View file

@ -26,9 +26,40 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "eventq.h" #include "eventq.h"
BEGIN_BLD_NS BEGIN_BLD_NS
#define kGenDudeDefaultSeq 11520
#define kDefaultAnimationBase 11520
#define kGenDudeMaxSlaves 7 #define kGenDudeMaxSlaves 7
#define kGenDudeTransformStatus -222
#define kGenDudeUpdTimeRate 10
#define kGenDudeMaxMeleeDist 2048
enum {
kGenDudeSeqIdleL = 0,
kGenDudeSeqDeathDefault = 1,
kGenDudeSeqDeathExplode = 2,
kGenDudeSeqBurning = 3,
kGenDudeSeqElectocuted = 4,
kGenDudeSeqRecoil = 5,
kGenDudeSeqAttackNormalL = 6,
kGenDudeSeqAttackThrow = 7,
kGenDudeSeqAttackNormalDW = 8,
kGenDudeSeqMoveL = 9,
kGenDudeSeqAttackPunch = 10,
kGenDudeSeqReserved1 = 11,
kGenDudeSeqReserved2 = 12,
kGenDudeSeqMoveW = 13,
kGenDudeSeqMoveD = 14,
kGenDudeSeqDeathBurn1 = 15,
kGenDudeSeqDeathBurn2 = 16,
kGenDudeSeqIdleW = 17,
kGenDudeSeqTransform = 18,
kGenDudeSeqReserved3 = 19,
kGenDudeSeqReserved4 = 20,
kGenDudeSeqReserved5 = 21,
kGenDudeSeqReserved6 = 22,
kGenDudeSeqReserved7 = 23,
kGenDudeSeqReserved8 = 24,
kGenDudeSeqMax ,
};
enum { enum {
kGenDudeSndTargetSpot = 0, kGenDudeSndTargetSpot = 0,
@ -48,44 +79,47 @@ kGenDudeSndMax ,
enum { enum {
kGenDudePropertyAll = 0, kGenDudePropertyAll = 0,
kGenDudePropertyWeapon = 1, kGenDudePropertyWeapon = 1,
kGenDudePropertyDamage = 2, kGenDudePropertyDmgScale = 2,
kGenDudePropertyMass = 3, kGenDudePropertyMass = 3,
kGenDudePropertyAttack = 4, kGenDudePropertyAttack = 4,
kGenDudePropertyStates = 5, kGenDudePropertyStates = 5,
kGenDudePropertyLeech = 6, kGenDudePropertyLeech = 6,
kGenDudePropertySlaves = 7, kGenDudePropertySlaves = 7,
kGenDudePropertyMelee = 8, kGenDudePropertySpriteSize = 8,
kGenDudePropertyClipdist = 9, kGenDudePropertyInitVals = 9,
kGenDudePropertyMax , kGenDudePropertyMax ,
}; };
extern AISTATE genDudeIdleL;
extern AISTATE GDXGenDudeIdleL; extern AISTATE genDudeIdleW;
extern AISTATE GDXGenDudeIdleW; extern AISTATE genDudeSearchL;
extern AISTATE GDXGenDudeSearchL; extern AISTATE genDudeSearchW;
extern AISTATE GDXGenDudeSearchW; extern AISTATE genDudeGotoL;
extern AISTATE GDXGenDudeGotoL; extern AISTATE genDudeGotoW;
extern AISTATE GDXGenDudeGotoW; extern AISTATE genDudeDodgeL;
extern AISTATE GDXGenDudeDodgeL; extern AISTATE genDudeDodgeD;
extern AISTATE GDXGenDudeDodgeD; extern AISTATE genDudeDodgeW;
extern AISTATE GDXGenDudeDodgeW; extern AISTATE genDudeDodgeShortL;
extern AISTATE GDXGenDudeDodgeDmgL; extern AISTATE genDudeDodgeShortD;
extern AISTATE GDXGenDudeDodgeDmgD; extern AISTATE genDudeDodgeShortW;
extern AISTATE GDXGenDudeDodgeDmgW; extern AISTATE genDudeChaseL;
extern AISTATE GDXGenDudeChaseL; extern AISTATE genDudeChaseD;
extern AISTATE GDXGenDudeChaseD; extern AISTATE genDudeChaseW;
extern AISTATE GDXGenDudeChaseW; extern AISTATE genDudeFireL;
extern AISTATE GDXGenDudeFireL; extern AISTATE genDudeFireD;
extern AISTATE GDXGenDudeFireD; extern AISTATE genDudeFireW;
extern AISTATE GDXGenDudeFireW; extern AISTATE genDudeRecoilL;
extern AISTATE GDXGenDudeRecoilL; extern AISTATE genDudeRecoilD;
extern AISTATE GDXGenDudeRecoilD; extern AISTATE genDudeRecoilW;
extern AISTATE GDXGenDudeRecoilW; extern AISTATE genDudeThrow;
extern AISTATE GDXGenDudeThrow; extern AISTATE genDudeThrow2;
extern AISTATE GDXGenDudeThrow2; extern AISTATE genDudePunch;
extern AISTATE GDXGenDudePunch; extern AISTATE genDudeRecoilTesla;
extern AISTATE GDXGenDudeRTesla; extern AISTATE genDudeSearchNoWalkL;
extern AISTATE GDXGenDudeTransform; extern AISTATE genDudeSearchNoWalkW;
extern AISTATE genDudeChaseNoWalkL;
extern AISTATE genDudeChaseNoWalkD;
extern AISTATE genDudeChaseNoWalkW;
struct GENDUDESND struct GENDUDESND
{ {
@ -93,6 +127,7 @@ struct GENDUDESND
int randomRange; int randomRange;
int sndIdOffset; // relative to data3 int sndIdOffset; // relative to data3
bool aiPlaySound; // false = sfxStart3DSound(); bool aiPlaySound; // false = sfxStart3DSound();
bool interruptable;
}; };
extern GENDUDESND gCustomDudeSnd[]; extern GENDUDESND gCustomDudeSnd[];
@ -105,29 +140,41 @@ struct GENDUDEEXTRA {
unsigned short curWeapon; // data1 duplicate to avoid potential problems when changing data dynamically unsigned short curWeapon; // data1 duplicate to avoid potential problems when changing data dynamically
unsigned short baseDispersion; unsigned short baseDispersion;
signed short nLifeLeech; // spritenum of dropped dude's leech signed short nLifeLeech; // spritenum of dropped dude's leech
short dmgControl[kDamageMax]; // depends of current weapon, drop armor item and sprite yrepeat
short slave[kGenDudeMaxSlaves]; // index of the ones dude is summon
short slaveCount; short slaveCount;
short slave[kGenDudeMaxSlaves]; // index of the ones dude is summon
short dmgControl[kDamageMax]; // depends of current weapon, drop armor item, sprite yrepeat and surface type
short availDeaths[kDamageMax]; // list of seqs with deaths for each damage type
short initVals[3]; // xrepeat, yrepeat, clipdist
bool forcePunch; // indicate if there is no fire trigger in punch state seq
bool updReq[kGenDudePropertyMax]; // update requests bool updReq[kGenDudePropertyMax]; // update requests
bool sndPlaying; // indicate if sound of AISTATE currently playing
bool isMelee; bool isMelee;
bool canBurn; // can turn in Burning dude or not
bool canElectrocute;
bool canAttack;
bool canRecoil;
bool canWalk; bool canWalk;
bool canDuck; bool canDuck;
bool canSwim; bool canSwim;
bool canFly; bool canFly;
}; };
extern GENDUDEEXTRA gGenDudeExtra[]; extern GENDUDEEXTRA gGenDudeExtra[];
inline GENDUDEEXTRA* genDudeExtra(spritetype* pSprite) {
return &gGenDudeExtra[pSprite->index];
}
XSPRITE* getNextIncarnation(XSPRITE* pXSprite); XSPRITE* getNextIncarnation(XSPRITE* pXSprite);
void killDudeLeech(spritetype* pLeech); void killDudeLeech(spritetype* pLeech);
void removeLeech(spritetype* pLeech, bool delSprite = true); void removeLeech(spritetype* pLeech, bool delSprite = true);
void removeDudeStuff(spritetype* pSprite); void removeDudeStuff(spritetype* pSprite);
spritetype* leechIsDropped(spritetype* pSprite); spritetype* leechIsDropped(spritetype* pSprite);
bool spriteIsUnderwater(spritetype* pSprite, bool oldWay); bool spriteIsUnderwater(spritetype* pSprite, bool oldWay = false);
bool sfxPlayGDXGenDudeSound(spritetype* pSprite, int mode); bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt = false);
void aiGenDudeMoveForward(spritetype* pSprite, XSPRITE* pXSprite); void aiGenDudeMoveForward(spritetype* pSprite, XSPRITE* pXSprite);
void aiGenDudeChooseDirection(spritetype* pSprite, XSPRITE* pXSprite, int a3, int aXvel = -1, int aYvel = -1); void aiGenDudeChooseDirection(spritetype* pSprite, XSPRITE* pXSprite, int a3, int aXvel = -1, int aYvel = -1);
void aiGenDudeNewState(spritetype* pSprite, AISTATE* pAIState);
int getGenDudeMoveSpeed(spritetype* pSprite, int which, bool mul, bool shift); int getGenDudeMoveSpeed(spritetype* pSprite, int which, bool mul, bool shift);
bool TargetNearThing(spritetype* pSprite, int thingType); bool TargetNearThing(spritetype* pSprite, int thingType);
int checkAttackState(spritetype* pSprite, XSPRITE* pXSprite); int checkAttackState(spritetype* pSprite, XSPRITE* pXSprite);
@ -143,12 +190,16 @@ bool canDuck(spritetype* pSprite);
bool canWalk(spritetype* pSprite); bool canWalk(spritetype* pSprite);
bool inDodge(AISTATE* aiState); bool inDodge(AISTATE* aiState);
bool inIdle(AISTATE* aiState); bool inIdle(AISTATE* aiState);
int getSeqStartId(XSPRITE* pXSprite); bool inAttack(AISTATE* aiState);
int getSeeDist(spritetype* pSprite, int startDist, int minDist, int maxDist); short inRecoil(AISTATE* aiState);
short inSearch(AISTATE* aiState);
short inDuck(AISTATE* aiState);
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);
void genDudePrepare(spritetype* pSprite, int propId = kGenDudePropertyAll); bool genDudePrepare(spritetype* pSprite, int propId = kGenDudePropertyAll);
void genDudeUpdate(spritetype* pSprite); void genDudeUpdate(spritetype* pSprite);
void genDudeProcess(spritetype* pSprite, XSPRITE* pXSprite);
END_BLD_NS END_BLD_NS

View file

@ -608,6 +608,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
case kModernObjDataAccumulator: case kModernObjDataAccumulator:
case kModernEffectSpawner: case kModernEffectSpawner:
case kModernWindGenerator: case kModernWindGenerator:
case kModernPlayerControl:
pSprite->type = kSpriteDecoration; pSprite->type = kSpriteDecoration;
break; break;
case kItemModernMapLevel: case kItemModernMapLevel:

View file

@ -45,6 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "trig.h" #include "trig.h"
#include "triggers.h" #include "triggers.h"
#include "view.h" #include "view.h"
#include "aiunicult.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -763,6 +764,12 @@ void makeMissileBlocking(int nSprite) // 23
sprite[nSprite].cstat |= CSTAT_SPRITE_BLOCK; sprite[nSprite].cstat |= CSTAT_SPRITE_BLOCK;
} }
void genDudeUpdateCallback(int nSprite) // 24
{
if (spriRangeIsFine(nSprite))
genDudeUpdate(&sprite[nSprite]);
}
void(*gCallback[kCallbackMax])(int) = void(*gCallback[kCallbackMax])(int) =
{ {
fxFlameLick, fxFlameLick,
@ -789,6 +796,7 @@ void(*gCallback[kCallbackMax])(int) =
DropVoodoo, // unused DropVoodoo, // unused
UniMissileBurst, UniMissileBurst,
makeMissileBlocking, makeMissileBlocking,
genDudeUpdateCallback,
}; };
END_BLD_NS END_BLD_NS

View file

@ -51,6 +51,7 @@ enum CALLBACK_ID {
kCallbackDropVoodoo = 21, // unused kCallbackDropVoodoo = 21, // unused
kCallbackMissileBurst = 22, // by NoOne kCallbackMissileBurst = 22, // by NoOne
kCallbackMissileSpriteBlock = 23, // by NoOne kCallbackMissileSpriteBlock = 23, // by NoOne
kCallbackGenDudeUpdate = 24, // by NoOne
kCallbackMax, kCallbackMax,
}; };

View file

@ -436,6 +436,17 @@ enum {
kSectorMax = 620, kSectorMax = 620,
}; };
// ai state types
enum {
kAiStateOther = -1,
kAiStateIdle = 0,
kAiStateGenIdle = 1,
kAiStateMove = 2,
kAiStateSearch = 3,
kAiStateChase = 4,
kAiStateRecoil = 5,
kAiStateAttack = 6,
};
// sprite attributes // sprite attributes
#define kHitagAutoAim 0x0008 #define kHitagAutoAim 0x0008
@ -472,16 +483,6 @@ enum {
#define kSecCFloorShade 0x8000 #define kSecCFloorShade 0x8000
// ai state types
#define kAiStateOther -1
#define kAiStateIdle 0
#define kAiStateGenIdle 1
#define kAiStateMove 2
#define kAiStateSearch 3
#define kAiStateChase 4
#define kAiStateRecoil 5
#define kAng5 28 #define kAng5 28
#define kAng15 85 #define kAng15 85
#define kAng30 170 #define kAng30 170

View file

@ -32,7 +32,7 @@ BEGIN_BLD_NS
#define kMaxSuperXSprites 128 #define kMaxSuperXSprites 128
// by NoOne: functions to quckly check range of specifical arrays // by NoOne: functions to quckly check range of specifical arrays
inline bool xsprRangeIsFine(int nXindex) { inline bool xspriRangeIsFine(int nXindex) {
return (nXindex >= 0 && nXindex < kMaxXSprites); return (nXindex >= 0 && nXindex < kMaxXSprites);
} }
@ -44,6 +44,10 @@ inline bool xwallRangeIsFine(int nXindex) {
return (nXindex >= 0 && nXindex < kMaxXWalls); return (nXindex >= 0 && nXindex < kMaxXWalls);
} }
inline bool xspriIsFine(int nIndex) {
return (nIndex >= 0 && nIndex < kMaxSprites && !(sprite[nIndex].flags & 32) && sprite[nIndex].statnum != kStatFree);
}
extern bool gModernMap; extern bool gModernMap;
#pragma pack(push, 1) #pragma pack(push, 1)

View file

@ -1544,7 +1544,7 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
0, 0,
0 0
}, },
//254 - kGDXUniversalCultist //254 - kDudeModernCustom
{ {
11520, // start sequence ID 11520, // start sequence ID
85, // start health 85, // start health
@ -1570,12 +1570,12 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
256, // angSpeed 256, // angSpeed
// 0, // 0,
7, -1, 18, // nGibType 7, -1, 18, // nGibType
128, 128, 128, 128, 128, 128, 128, 128, 150, 128, 256, 128, 128, 128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
0 0
}, },
//255 - kGDXGenDudeBurning //255 - kDudeModernCustomBurning
{ {
4096, // start sequence ID 4096, // start sequence ID
25, // start health 25, // start health

View file

@ -158,45 +158,6 @@ void CKillMgr::sub_2641C(void)
} }
} }
/*
void CKillMgr::AddKill(spritetype *pSprite) {
if (pSprite->statnum == kStatDude) {
switch (pSprite->type) {
case kDudeBat:
case kDudeRat:
case kDudeBurningInnocent:
case kDudeInnocent:
return;
}
at4++;
}
}
void CKillMgr::sub_2641C(void)
{
at0 = 0;
for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
spritetype *pSprite = &sprite[nSprite];
if (IsDudeSprite(pSprite)) {
if (pSprite->statnum == kStatDude) {
switch (pSprite->type) {
case kDudeBat:
case kDudeRat:
case kDudeBurningInnocent:
case kDudeInnocent:
return;
}
at0++;
}
}
}
}
*/
void CKillMgr::Draw(void) void CKillMgr::Draw(void)
{ {
char pBuffer[40]; char pBuffer[40];

View file

@ -427,11 +427,12 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command, short causedBy)
break; break;
} }
//by NoOne: allow to send commands on player sprites
if (gModernMap) { if (gModernMap) {
// allow to send commands on player sprites
PLAYER* pPlayer = NULL; PLAYER* pPlayer = NULL;
if (rxId >= kChannelPlayer0 && rxId <= kChannelPlayer7) { if (playerRXRngIsFine(rxId)) {
if ((pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != NULL) if ((pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != NULL)
trMessageSprite(pPlayer->nSprite, event); trMessageSprite(pPlayer->nSprite, event);
} else if (rxId == kChannelAllPlayers) { } else if (rxId == kChannelAllPlayers) {
@ -439,6 +440,9 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command, short causedBy)
if ((pPlayer = getPlayerById(i)) != NULL) if ((pPlayer = getPlayerById(i)) != NULL)
trMessageSprite(pPlayer->nSprite, event); trMessageSprite(pPlayer->nSprite, event);
} }
// send command on sprite which create the event sequence
} else if (rxId == kChannelEventCauser && spriRangeIsFine(event.causedBy)) {
trMessageSprite(event.causedBy, event);
} }
} }

View file

@ -40,9 +40,8 @@ kChannelLevelStartCoop,
kChannelLevelStartTeamsOnly, kChannelLevelStartTeamsOnly,
kChannelPlayerDeathTeamA = 15, kChannelPlayerDeathTeamA = 15,
kChannelPlayerDeathTeamB, kChannelPlayerDeathTeamB,
// by NoOne: RX channels of players to send commands on
///////////////////////////// /////////////////////////////
// channels of players to send commands on
kChannelPlayer0 = 30, kChannelPlayer0 = 30,
kChannelPlayer1, kChannelPlayer1,
kChannelPlayer2, kChannelPlayer2,
@ -52,10 +51,11 @@ kChannelPlayer5,
kChannelPlayer6, kChannelPlayer6,
kChannelPlayer7, kChannelPlayer7,
kChannelAllPlayers = kChannelPlayer0 + kMaxPlayers, kChannelAllPlayers = kChannelPlayer0 + kMaxPlayers,
// channel of event causer
kChannelEventCauser = 50,
// map requires modern features to work properly
kChannelMapModernize = 60,
///////////////////////////// /////////////////////////////
kChannelMapModernize = 60, // map requires modern features to work properly
kChannelTeamAFlagCaptured = 80, kChannelTeamAFlagCaptured = 80,
kChannelTeamBFlagCaptured, kChannelTeamBFlagCaptured,
kChannelRemoteBomb0 = 90, kChannelRemoteBomb0 = 90,
@ -79,44 +79,44 @@ extern RXBUCKET rxBucket[];
extern unsigned short bucketHead[]; extern unsigned short bucketHead[];
enum COMMAND_ID { enum COMMAND_ID {
kCmdOff = 0, kCmdOff = 0,
kCmdOn = 1, kCmdOn = 1,
kCmdState = 2, kCmdState = 2,
kCmdToggle = 3, kCmdToggle = 3,
kCmdNotState = 4, kCmdNotState = 4,
kCmdLink = 5, kCmdLink = 5,
kCmdLock = 6, kCmdLock = 6,
kCmdUnlock = 7, kCmdUnlock = 7,
kCmdToggleLock = 8, kCmdToggleLock = 8,
kCmdStopOff = 9, kCmdStopOff = 9,
kCmdStopOn = 10, kCmdStopOn = 10,
kCmdStopNext = 11, kCmdStopNext = 11,
kCmdCounterSector = 12, kCmdCounterSector = 12,
kCmdCallback = 20, kCmdCallback = 20,
kCmdRepeat = 21, kCmdRepeat = 21,
kCmdSpritePush = 30, kCmdSpritePush = 30,
kCmdSpriteImpact = 31, kCmdSpriteImpact = 31,
kCmdSpritePickup = 32, kCmdSpritePickup = 32,
kCmdSpriteTouch = 33, kCmdSpriteTouch = 33,
kCmdSpriteSight = 34, kCmdSpriteSight = 34,
kCmdSpriteProximity = 35, kCmdSpriteProximity = 35,
kCmdSpriteExplode = 36, kCmdSpriteExplode = 36,
kCmdSectorPush = 40, kCmdSectorPush = 40,
kCmdSectorImpact = 41, kCmdSectorImpact = 41,
kCmdSectorEnter = 42, kCmdSectorEnter = 42,
kCmdSectorExit = 43, kCmdSectorExit = 43,
kCmdWallPush = 50, kCmdWallPush = 50,
kCmdWallImpact = 51, kCmdWallImpact = 51,
kCmdWallTouch = 52, kCmdWallTouch = 52,
kCmdModernUse = 53, // used by most of modern types kCmdModernUse = 53, // used by most of modern types
kCmdNumberic = 64, // 64: 0, 65: 1 and so on up to 255 kCmdNumberic = 64, // 64: 0, 65: 1 and so on up to 255
kCmdModernFeaturesEnable = 100, // must be in object with kChannelMapModernize RX / TX kCmdModernFeaturesEnable = 100, // must be in object with kChannelMapModernize RX / TX
kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapModernize RX / TX kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapModernize RX / TX
kCmdNumbericMax = 255, kCmdNumbericMax = 255,
}; };
inline bool playerRXRngIsFine(int rx) { inline bool playerRXRngIsFine(int rx) {

View file

@ -357,7 +357,7 @@ void levelEndLevel(int arg)
} }
} }
// By NoOne: this function can be called via sending numbered command to TX kGDXChannelEndLevel // By NoOne: this function can be called via sending numbered command to TX kChannelModernEndLevelCustom
// This allows to set custom next level instead of taking it from INI file. // This allows to set custom next level instead of taking it from INI file.
void levelEndLevelCustom(int nLevel) { void levelEndLevelCustom(int nLevel) {

View file

@ -483,23 +483,45 @@ QAV* qavSceneLoad(int qavId) {
return pQav; return pQav;
} }
void qavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5) { void qavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5) {
if (pPlayer == NULL || pPlayer->sceneQav == -1) return; if (pPlayer == NULL || pPlayer->sceneQav == -1) return;
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene; QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
spritetype* pSprite = &sprite[pQavScene->index];
if (pQavScene->qavResrc != NULL) { if (pQavScene->qavResrc != NULL) {
QAV* pQAV = pQavScene->qavResrc; QAV* pQAV = pQavScene->qavResrc;
int v4 = (pPlayer->weaponTimer == 0) ? (int)totalclock % pQAV->at10 : pQAV->at10 - pPlayer->weaponTimer; int v4 = (pPlayer->weaponTimer == 0) ? (int)totalclock % pQAV->at10 : pQAV->at10 - pPlayer->weaponTimer;
pQAV->x = a3; pQAV->y = a4; int flags = 2; int flags = 2; int nInv = powerupCheck(pPlayer, kPwUpShadowCloak);
int nInv = powerupCheck(pPlayer, kPwUpShadowCloak);
if (nInv >= 120 * 8 || (nInv != 0 && ((int)totalclock & 32))) { if (nInv >= 120 * 8 || (nInv != 0 && ((int)totalclock & 32))) {
a2 = -128; a2 = -128; flags |= 1;
flags |= 1; }
// draw as weapon
if (!(pSprite->flags & kModernTypeFlag1)) {
pQAV->x = a3; pQAV->y = a4;
pQAV->Draw(v4, flags, a2, a5);
// draw fullscreen (currently 4:3 only)
} else {
int wx1 = windowxy1.x, wy1 = windowxy1.y, wx2 = windowxy2.x, wy2 = windowxy2.y;
windowxy2.x = xdim - 1; windowxy2.y = ydim - 1;
windowxy1.x = windowxy1.y = 0;
pQAV->Draw(v4, flags, a2, a5);
windowxy1.x = wx1; windowxy1.y = wy1;
windowxy2.x = wx2; windowxy2.y = wy2;
} }
pQAV->Draw(v4, flags, a2, a5);
} }
} }

View file

@ -64,7 +64,7 @@ struct PLAYER {
DUDEINFO *pDudeInfo; DUDEINFO *pDudeInfo;
GINPUT input; GINPUT input;
//short input; // INPUT //short input; // INPUT
//char at10; // forward //char moveFunc; // forward
//short at11; // turn //short at11; // turn
//char hearDist; // strafe //char hearDist; // strafe
//int bobV; // buttonFlags //int bobV; // buttonFlags
@ -216,11 +216,15 @@ struct POWERUPINFO {
int maxTime; int maxTime;
}; };
#define kQavSceneStackSize 16
// by NoOne: this one stores qavs anims that can be played by trigger // by NoOne: this one stores qavs anims that can be played by trigger
struct QAVSCENE { struct QAVSCENE {
short index = -1; // index of sprite which triggered qav scene short index = -1; // index of sprite which triggered qav scene
QAV* qavResrc = NULL; QAV* qavResrc = NULL;
short causedBy = -1; short causedBy = -1;
// TO-DO: Stack of animations which allows to pop and push (restoring previous animation instead of weapon once current animation is played)
}; };
// by NoOne: this one for controlling the player using triggers (movement speed, jumps and other stuff) // by NoOne: this one for controlling the player using triggers (movement speed, jumps and other stuff)

View file

@ -56,7 +56,7 @@ struct Seq {
short at8; short at8;
short ata; short ata;
int atc; int atc;
SEQFRAME frames[1]; // at10 SEQFRAME frames[1];
void Preload(void); void Preload(void);
void Precache(void); void Precache(void);
}; };

View file

@ -42,28 +42,6 @@ POINT2D earL, earR, earL0, earR0; // Ear position
VECTOR2D earVL, earVR; // Ear velocity ? VECTOR2D earVL, earVR; // Ear velocity ?
int lPhase, rPhase, lVol, rVol, lPitch, rPitch; int lPhase, rPhase, lVol, rVol, lPitch, rPitch;
struct BONKLE
{
int at0;
int at4;
DICTNODE *at8;
int atc;
spritetype *at10;
int at14;
int at18;
int at1c;
POINT3D at20;
POINT3D at2c;
//int at20;
//int at24;
//int at28;
//int at2c;
//int at30;
//int at34;
int at38;
int at3c;
};
BONKLE Bonkle[256]; BONKLE Bonkle[256];
BONKLE *BonkleCache[256]; BONKLE *BonkleCache[256];

View file

@ -25,6 +25,31 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
struct BONKLE
{
int at0;
int at4;
DICTNODE* at8;
int atc;
spritetype* at10;
int at14;
int at18;
int at1c;
POINT3D at20;
POINT3D at2c;
//int at20;
//int at24;
//int at28;
//int at2c;
//int at30;
//int at34;
int at38;
int at3c;
};
extern BONKLE Bonkle[256];
extern BONKLE* BonkleCache[256];
void sfxInit(void); void sfxInit(void);
void sfxTerm(void); void sfxTerm(void);
void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector); void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector);

View file

@ -863,29 +863,30 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
} }
return; return;
case kModernPlayerControl: // WIP case kModernPlayerControl: // WIP
PLAYER* pPlayer = NULL; int nPlayer = pXSprite->data1; PLAYER* pPlayer = NULL; int nPlayer = pXSprite->data1; int oldCmd = -1;
if (pXSprite->data1 == 0 && spriRangeIsFine(event.causedBy)) if (pXSprite->data1 == 0 && spriRangeIsFine(event.causedBy))
nPlayer = sprite[event.causedBy].type; nPlayer = sprite[event.causedBy].type;
if ((pPlayer = getPlayerById(nPlayer)) == NULL || pPlayer->pXSprite->health <= 0) if ((pPlayer = getPlayerById(nPlayer)) == NULL || pPlayer->pXSprite->health <= 0) return;
return; else if (pXSprite->command < kCmdNumberic + 3 && pXSprite->command > kCmdNumberic + 4
&& !modernTypeSetSpriteState(nSprite, pXSprite, pXSprite->state ^ 1, event.causedBy)) return;
TRPLAYERCTRL* pCtrl = pCtrl = &gPlayerCtrl[pPlayer->nPlayer]; TRPLAYERCTRL* pCtrl = pCtrl = &gPlayerCtrl[pPlayer->nPlayer];
if (event.cmd >= kCmdNumberic) { if (event.cmd >= kCmdNumberic) {
switch (event.cmd) { switch (event.cmd) {
case kCmdNumberic + 3:// start playing qav scene case kCmdNumberic + 3:// start playing qav scene
viewSetSystemMessage("START QAV %d, %d", pXSprite->rxID, pXSprite->txID);
if (pCtrl->qavScene.index != nSprite || pXSprite->Interrutable) if (pCtrl->qavScene.index != nSprite || pXSprite->Interrutable)
trPlayerCtrlStartScene(pXSprite, pPlayer, event.causedBy); trPlayerCtrlStartScene(pXSprite, pPlayer, event.causedBy);
break; return;
case kCmdNumberic + 4: // stop playing qav scene case kCmdNumberic + 4: // stop playing qav scene
viewSetSystemMessage("STOP QAV", gPlayerCtrl[pPlayer->nPlayer].qavScene.index); if (pCtrl->qavScene.index == nSprite || event.type != 3 || sprite[event.index].type != kModernPlayerControl)
if (pCtrl->qavScene.index == nSprite)
trPlayerCtrlStopScene(pXSprite, pPlayer); trPlayerCtrlStopScene(pXSprite, pPlayer);
return;
default:
oldCmd = pXSprite->command;
pXSprite->command = event.cmd; // convert event command to current sprite command
break; break;
} }
return;
} }
/// !!! COMMANDS OF THE CURRENT SPRITE, NOT OF THE EVENT !!! /// /// !!! COMMANDS OF THE CURRENT SPRITE, NOT OF THE EVENT !!! ///
@ -923,7 +924,8 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
gPosture[i][a].frontAccel = gPosture[i][a].sideAccel = gPosture[i][a].backAccel = ClipRange(mulscale8(defSpeed, speed), 0, 65535); gPosture[i][a].frontAccel = gPosture[i][a].sideAccel = gPosture[i][a].backAccel = ClipRange(mulscale8(defSpeed, speed), 0, 65535);
} }
} }
viewSetSystemMessage("MOVEMENT: %d %d %d", pXSprite->rxID,pSprite->index, gPosture[0][0].frontAccel);
//viewSetSystemMessage("MOVEMENT: %d %d %d", pXSprite->rxID,pSprite->index, gPosture[0][0].frontAccel);
} }
// player jump height (for all players ATM) // player jump height (for all players ATM)
@ -941,7 +943,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
} }
} }
} }
viewSetSystemMessage("JUMPING: %d", gPosture[0][0].normalJumpZ); //viewSetSystemMessage("JUMPING: %d", gPosture[0][0].normalJumpZ);
} }
break; break;
@ -950,7 +952,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
if (pXSprite->data3 < 0) break; if (pXSprite->data3 < 0) break;
switch (pXSprite->data2) { switch (pXSprite->data2) {
case 1: // tilting case 1: // tilting
pPlayer->tiltEffect = pXSprite->data3; pPlayer->tiltEffect = ClipRange(pXSprite->data3, 0, 220);
break; break;
case 2: // pain case 2: // pain
pPlayer->painEffect = pXSprite->data3; pPlayer->painEffect = pXSprite->data3;
@ -987,27 +989,25 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
case kCmdNumberic + 5: // 69 case kCmdNumberic + 5: // 69
// set player sprite and look angles // set player sprite and look angles
if (pXSprite->data2 == 0) { if (pXSprite->data4 == 0) {
// look angle // look angle
if (valueIsBetween(pXSprite->data3, -128, 128)) { if (valueIsBetween(pXSprite->data2, -128, 128)) {
CONSTEXPR int upAngle = 289; CONSTEXPR int downAngle = -347; CONSTEXPR int upAngle = 289; CONSTEXPR int downAngle = -347;
CONSTEXPR double lookStepUp = 4.0 * upAngle / 60.0; CONSTEXPR double lookStepUp = 4.0 * upAngle / 60.0;
CONSTEXPR double lookStepDown = -4.0 * downAngle / 60.0; CONSTEXPR double lookStepDown = -4.0 * downAngle / 60.0;
int look = pXSprite->data3 << 5; int look = pXSprite->data2 << 5;
if (look > 0) pPlayer->q16look = fix16_min(mulscale8(F16(lookStepUp), look), F16(upAngle)); if (look > 0) pPlayer->q16look = fix16_min(mulscale8(F16(lookStepUp), look), F16(upAngle));
else if (look < 0) pPlayer->q16look = -fix16_max(mulscale8(F16(lookStepDown), abs(look)), F16(downAngle)); else if (look < 0) pPlayer->q16look = -fix16_max(mulscale8(F16(lookStepDown), abs(look)), F16(downAngle));
else pPlayer->q16look = 0; else pPlayer->q16look = 0;
} }
// angle // angle
if ((pSprite->flags & kModernTypeFlag1) && valueIsBetween(pXSprite->data4, 0, kAng180)) // TO-DO: if tx > 0, take a look on TX ID sprite
pPlayer->pSprite->ang = pXSprite->data4; if (pXSprite->data3 == 1) pPlayer->pSprite->ang = pXSprite->data3;
else if (pXSprite->data4 == 1) else if (valueIsBetween(pXSprite->data3, 0, kAng180))
pPlayer->pSprite->ang = pSprite->ang; pPlayer->pSprite->ang = pXSprite->data3;
} }
//viewSetSystemMessage("ANGLE: %d, SLOPE: %d", pPlayer->pSprite->ang, pPlayer->q16look); //viewSetSystemMessage("ANGLE: %d, SLOPE: %d", pPlayer->pSprite->ang, pPlayer->q16look);
break; break;
@ -1017,22 +1017,28 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
switch (pXSprite->data2) { switch (pXSprite->data2) {
// erase all // erase all
case 0: case 0:
// erase all weapons except pitchfork // erase weapons
case 1: case 1:
WeaponLower(pPlayer); // erase all
if (pXSprite->data3 <= 0) {
for (int i = 0; i < 14; i++) { WeaponLower(pPlayer);
pPlayer->hasWeapon[i] = false;
// also erase ammo
if (i < 12 && pXSprite->data3 == 1)
pPlayer->ammoCount[i] = 0;
}
pPlayer->hasWeapon[1] = true; for (int i = 0; i < 14; i++) {
pPlayer->curWeapon = 0; pPlayer->hasWeapon[i] = false;
pPlayer->nextWeapon = 1; // also erase ammo
if (i < 12) pPlayer->ammoCount[i] = 0;
WeaponRaise(pPlayer); }
pPlayer->hasWeapon[1] = true;
pPlayer->curWeapon = 0;
pPlayer->nextWeapon = 1;
WeaponRaise(pPlayer);
// erase just specified
} else {
}
if (pXSprite->data2) break; if (pXSprite->data2) break;
// erase all armor // erase all armor
case 2: case 2:
@ -1065,11 +1071,11 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
if (pXSprite->data2 == 1) { if (pXSprite->data2 == 1) {
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pWeaponData->count, gAmmoInfo[nAmmoType].max); pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pWeaponData->count, gAmmoInfo[nAmmoType].max);
} else { } else {
pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pXSprite->data3, gAmmoInfo[nAmmoType].max); pPlayer->ammoCount[nAmmoType] = ClipHigh(pPlayer->ammoCount[nAmmoType] + pXSprite->data4, gAmmoInfo[nAmmoType].max);
break; break;
} }
pPlayer->hasWeapon[pXSprite->data2] = true; pPlayer->hasWeapon[pXSprite->data3] = true;
if (pXSprite->data4 == 0) { // switch on it if (pXSprite->data4 == 0) { // switch on it
if (pPlayer->sceneQav >= 0) { if (pPlayer->sceneQav >= 0) {
@ -1085,7 +1091,19 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
break; break;
} }
break; break;
case kCmdNumberic + 8: // 72
// use inventory item
if (pXSprite->data2 > 0 && pXSprite->data2 <= 5) {
packUseItem(pPlayer, pXSprite->data2 - 1);
// force remove after use
if (pXSprite->data4 == 1)
pPlayer->packSlots[0].curAmount = pPlayer->packSlots[0].curAmount = 0;
}
break;
} }
if (oldCmd > -1) pXSprite->command = oldCmd;
return; return;
} }
} }
@ -1548,11 +1566,7 @@ void useObjResizer(XSPRITE* pXSource, short objType, int objIndex) {
break; break;
// for sprites // for sprites
case 3: case 3:
/*PLAYER* pPlayer = NULL;
if (playerRXRngIsFine(pXSource->txID) && (pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != NULL)
objIndex = pPlayer->nSprite;*/
// resize by seq scaling // resize by seq scaling
if (sprite[pXSource->reference].flags & kModernTypeFlag1) { if (sprite[pXSource->reference].flags & kModernTypeFlag1) {
if (valueIsBetween(pXSource->data1, -255, 32767)) { if (valueIsBetween(pXSource->data1, -255, 32767)) {
@ -1563,27 +1577,28 @@ void useObjResizer(XSPRITE* pXSource, short objType, int objIndex) {
// request properties update for custom dude // request properties update for custom dude
switch (sprite[objIndex].type) { switch (sprite[objIndex].type) {
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
gGenDudeExtra[objIndex].updReq[kGenDudePropertyAttack] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertySpriteSize] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyMass] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyAttack] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyDamage] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyMass] = true;
break; gGenDudeExtra[objIndex].updReq[kGenDudePropertyDmgScale] = true;
evPost(objIndex, 3, kGenDudeUpdTimeRate, kCallbackGenDudeUpdate, -1);
break;
} }
} }
// resize by repeats // resize by repeats
} else { } else {
if (valueIsBetween(pXSource->data1, -1, 32767)) if (valueIsBetween(pXSource->data1, -1, 32767))
sprite[objIndex].xrepeat = ClipRange(pXSource->data1, 0, 255); sprite[objIndex].xrepeat = ClipRange(pXSource->data1, 0, 255);
if (valueIsBetween(pXSource->data2, -1, 32767)) if (valueIsBetween(pXSource->data2, -1, 32767))
sprite[objIndex].yrepeat = ClipRange(pXSource->data2, 0, 255); sprite[objIndex].yrepeat = ClipRange(pXSource->data2, 0, 255);
} }
if (valueIsBetween(pXSource->data3, -1, 32767)) if (valueIsBetween(pXSource->data3, -1, 32767))
sprite[objIndex].xoffset = ClipRange(pXSource->data3, 0, 255); sprite[objIndex].xoffset = ClipRange(pXSource->data3, 0, 255);
@ -1876,7 +1891,12 @@ void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite) {
if (pXSector != NULL && pXSector->Underwater) xsprite[pSprite->extra].medium = kMediumWater; if (pXSector != NULL && pXSector->Underwater) xsprite[pSprite->extra].medium = kMediumWater;
else xsprite[pSprite->extra].medium = kMediumNormal; else xsprite[pSprite->extra].medium = kMediumNormal;
if (pXSource->data2 == 1) pSprite->ang = pSource->ang; if (pXSource->data2 == 1) {
pSprite->ang = pSource->ang;
if (IsDudeSprite(pSprite) && xspriRangeIsFine(pSprite->index))
xsprite[pSprite->extra].goalAng = pSprite->ang;
}
if (pXSource->data3 == 1) if (pXSource->data3 == 1)
xvel[pSprite->xvel] = yvel[pSprite->xvel] = zvel[pSprite->xvel] = 0; xvel[pSprite->xvel] = yvel[pSprite->xvel] = zvel[pSprite->xvel] = 0;
@ -2006,11 +2026,21 @@ void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector) {
} }
} }
void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) { void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) {
if (pSprite != NULL) {
int dmgType = (pXSource->data2 == 7) ? Random(6) : ClipRange(pXSource->data2, 0, 6); spritetype* pSource = &sprite[pXSource->reference];
if (pSprite != NULL && xspriIsFine(pSprite->index)) {
int dmg = (pXSource->data3 == 0) ? 65535 : ClipRange(pXSource->data3, 1, 65535); int dmg = (pXSource->data3 == 0) ? 65535 : ClipRange(pXSource->data3, 1, 65535);
actDamageSprite(pSprite->index, pSprite, (DAMAGE_TYPE)dmgType, dmg); int dmgType = ClipRange(pXSource->data2, 0, 6);
if (pXSource->data2 == -1 && IsDudeSprite(pSprite)) {
xsprite[pSprite->extra].health = ClipLow(xsprite[pSprite->extra].health - dmg, 0);
if (xsprite[pSprite->extra].health == 0)
actKillDude(pSource->index, pSprite, (DAMAGE_TYPE)0, 65535);
}
else actDamageSprite(pSource->index, pSprite, (DAMAGE_TYPE)dmgType, dmg);
} }
} }
@ -4206,42 +4236,59 @@ int getDataFieldOfObject(int objType, int objIndex, int dataIndex) {
bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value, int causedBy) { bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value, int causedBy) {
switch (objType) { switch (objType) {
case 3: case 3: {
XSPRITE* pXSprite = &xsprite[sprite[objIndex].extra];
// exceptions
if (IsDudeSprite(&sprite[objIndex]) && pXSprite->health <= 0) return true;
/*switch (sprite[objIndex].type) {
case kThingBloodBits:
case kThingBloodChunks:
case kThingZombieHead:
case kThingObjectGib:
case kThingObjectExplode:
if (pXSprite->data1 > 0 || pXSprite->data2 > 0 || pXSprite->data3 > 0 || pXSprite->data4 > 0) return true;
break;
}*/
switch (dataIndex) { switch (dataIndex) {
case 1: case 1:
xsprite[sprite[objIndex].extra].data1 = value; xsprite[sprite[objIndex].extra].data1 = value;
switch (sprite[objIndex].type) { switch (sprite[objIndex].type) {
case kSwitchCombo: case kSwitchCombo:
if (value == xsprite[sprite[objIndex].extra].data2) SetSpriteState(objIndex, &xsprite[sprite[objIndex].extra], 1, causedBy); if (value == xsprite[sprite[objIndex].extra].data2) SetSpriteState(objIndex, &xsprite[sprite[objIndex].extra], 1, causedBy);
else SetSpriteState(objIndex, &xsprite[sprite[objIndex].extra], 0, causedBy); else SetSpriteState(objIndex, &xsprite[sprite[objIndex].extra], 0, causedBy);
break; break;
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
gGenDudeExtra[objIndex].updReq[kGenDudePropertyWeapon] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyWeapon] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyMelee] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyDmgScale] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyDamage] = true; evPost(objIndex, 3, kGenDudeUpdTimeRate, kCallbackGenDudeUpdate, causedBy);
break; break;
} }
return true; return true;
case 2: case 2:
xsprite[sprite[objIndex].extra].data2 = value; xsprite[sprite[objIndex].extra].data2 = value;
switch (sprite[objIndex].type) { switch (sprite[objIndex].type) {
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
gGenDudeExtra[objIndex].updReq[kGenDudePropertyMass] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertySpriteSize] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyDamage] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyMass] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyStates] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyDmgScale] = true;
gGenDudeExtra[objIndex].updReq[kGenDudePropertyAttack] = true; gGenDudeExtra[objIndex].updReq[kGenDudePropertyStates] = true;
break; gGenDudeExtra[objIndex].updReq[kGenDudePropertyAttack] = true;
evPost(objIndex, 3, kGenDudeUpdTimeRate, kCallbackGenDudeUpdate, causedBy);
break;
} }
return true; return true;
case 3: case 3:
xsprite[sprite[objIndex].extra].data3 = value; xsprite[sprite[objIndex].extra].data3 = value;
switch (sprite[objIndex].type) { switch (sprite[objIndex].type) {
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
xsprite[sprite[objIndex].extra].sysData1 = value; xsprite[sprite[objIndex].extra].sysData1 = value;
break; break;
} }
return true; return true;
case 4: case 4:
@ -4250,6 +4297,7 @@ bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value, i
default: default:
return false; return false;
} }
}
case 0: case 0:
xsector[sector[objIndex].extra].data = value; xsector[sector[objIndex].extra].data = value;
return true; return true;

View file

@ -1067,6 +1067,13 @@ FORCE_INLINE CONSTEXPR DivResult<T> divrhs(T lhs)
{ {
return divide(lhs, (T)base); return divide(lhs, (T)base);
} }
template <typename T, typename T2>
static FORCE_INLINE CONSTEXPR_CXX14 enable_if_t<is_signed<T>::value, T> NEGATE_ON_CONDITION(T value, T2 condition)
{
T const invert = !!condition;
return (value ^ -invert) + invert;
}
#endif #endif
template <size_t base, typename T> template <size_t base, typename T>
@ -1081,11 +1088,11 @@ CONSTEXPR size_t logbasenegative(T n)
return n > static_cast<T>(-(native_t)base) ? 1 : 1 + logbase<base>(n / static_cast<T>(-(native_t)base)); return n > static_cast<T>(-(native_t)base) ? 1 : 1 + logbase<base>(n / static_cast<T>(-(native_t)base));
} }
#endif
#define isPow2OrZero(v) (((v) & ((v) - 1)) == 0) #define isPow2OrZero(v) (((v) & ((v) - 1)) == 0)
#define isPow2(v) (isPow2OrZero(v) && (v)) #define isPow2(v) (isPow2OrZero(v) && (v))
#endif
////////// Bitfield manipulation ////////// ////////// Bitfield manipulation //////////
#if 0 #if 0

View file

@ -650,7 +650,8 @@ static int32_t defsparser(scriptfile *script)
int32_t havexoffset = 0, haveyoffset = 0, haveextra = 0; int32_t havexoffset = 0, haveyoffset = 0, haveextra = 0;
int32_t xoffset = 0, yoffset = 0; int32_t xoffset = 0, yoffset = 0;
int32_t istexture = 0; int32_t istexture = 0;
int32_t tilecrc = 0, origcrc = 0; int32_t tilecrc = 0;
uint8_t have_ifcrc = 0;
int32_t extra = 0; int32_t extra = 0;
static const tokenlist tilefromtexturetokens[] = static const tokenlist tilefromtexturetokens[] =
@ -695,6 +696,7 @@ static int32_t defsparser(scriptfile *script)
break; break;
case T_IFCRC: case T_IFCRC:
scriptfile_getsymbol(script, &tilecrc); scriptfile_getsymbol(script, &tilecrc);
have_ifcrc = 1;
break; break;
case T_TEXHITSCAN: case T_TEXHITSCAN:
flags |= PICANM_TEXHITSCAN_BIT; flags |= PICANM_TEXHITSCAN_BIT;
@ -721,9 +723,9 @@ static int32_t defsparser(scriptfile *script)
break; break;
} }
if (tilecrc) if (have_ifcrc)
{ {
origcrc = tileCRC(tile); int32_t origcrc = tileCRC(tile);
if (origcrc != tilecrc) if (origcrc != tilecrc)
{ {
//initprintf("CRC of tile %d doesn't match! CRC: %d, Expected: %d\n", tile, origcrc, tilecrc); //initprintf("CRC of tile %d doesn't match! CRC: %d, Expected: %d\n", tile, origcrc, tilecrc);

View file

@ -745,7 +745,7 @@ void videoSetPalette(char dabrightness, uint8_t dapalid, uint8_t flags)
int32_t palsumdidchange; int32_t palsumdidchange;
// uint32_t lastbright = curbrightness; // uint32_t lastbright = curbrightness;
Bassert((flags & 4) == 0); // Bassert((flags&4)==0); // What is so bad about this flag?
if (/*(unsigned)dapalid >= MAXBASEPALS ||*/ basepaltable[dapalid] == NULL) if (/*(unsigned)dapalid >= MAXBASEPALS ||*/ basepaltable[dapalid] == NULL)
dapalid = 0; dapalid = 0;

View file

@ -760,7 +760,6 @@ static FORCE_INLINE int __fastcall getvar__(int const gameVar, int const spriteN
int returnValue = 0; int returnValue = 0;
int const varFlags = var.flags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK); int const varFlags = var.flags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK);
int const invertResult = !!(gameVar & GV_FLAG_NEGATIVE);
if (!varFlags) returnValue = var.global; if (!varFlags) returnValue = var.global;
else if (varFlags == GAMEVAR_PERACTOR) else if (varFlags == GAMEVAR_PERACTOR)
@ -775,7 +774,7 @@ static FORCE_INLINE int __fastcall getvar__(int const gameVar, int const spriteN
case GAMEVAR_Q16PTR: returnValue = fix16_to_int(*(fix16_t *)var.global); break; case GAMEVAR_Q16PTR: returnValue = fix16_to_int(*(fix16_t *)var.global); break;
} }
return (returnValue ^ -invertResult) + invertResult; return NEGATE_ON_CONDITION(returnValue, gameVar & GV_FLAG_NEGATIVE);
} }
} }

View file

@ -698,7 +698,7 @@ static MenuEntry_t *MEL_DISPLAYSETUP_GL[] = {
static char const *MenuKeyNone = " -"; static char const MenuKeyNone[] = " -";
static char const *MEOSN_Keys[NUMKEYS]; static char const *MEOSN_Keys[NUMKEYS];
static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS_TEMPLATE = { 0, &MF_Minifont, NUMKEYS, 54<<16, 0 }; static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS_TEMPLATE = { 0, &MF_Minifont, NUMKEYS, 54<<16, 0 };
@ -1565,8 +1565,9 @@ void Menu_Init(void)
} }
MEOS_Gamefuncs.numOptions = k; MEOS_Gamefuncs.numOptions = k;
for (i = 0; i < NUMKEYS; ++i) for (i = 1; i < NUMKEYS-1; ++i)
MEOSN_Keys[i] = KB_ScanCodeToString(i); MEOSN_Keys[i] = KB_ScanCodeToString(i);
MEOSN_Keys[0] = MenuKeyNone;
MEOSN_Keys[NUMKEYS-1] = MenuKeyNone; MEOSN_Keys[NUMKEYS-1] = MenuKeyNone;

View file

@ -5731,7 +5731,6 @@ int portableBackupSave(const char * path, const char * name, int volume, int lev
} }
fil->Write(encoded, strlen(encoded)); fil->Write(encoded, strlen(encoded));
delete fil;
sjson_free_string(ctx, encoded); sjson_free_string(ctx, encoded);
sjson_destroy_context(ctx); sjson_destroy_context(ctx);

View file

@ -466,7 +466,7 @@ int32_t G_LoadPlayer(savebrief_t & sv)
if (currentboardfilename[0]) if (currentboardfilename[0])
{ {
// only setup art if map differs from previous // only setup art if map differs from previous
if (!previousboardfilename[0] || previousboardfilename != currentboardfilename) if (!previousboardfilename[0] || Bstrcmp(previousboardfilename, currentboardfilename))
artSetupMapArt(currentboardfilename); artSetupMapArt(currentboardfilename);
Bstrcpy(previousboardfilename, currentboardfilename); Bstrcpy(previousboardfilename, currentboardfilename);
append_ext_UNSAFE(currentboardfilename, ".mhk"); append_ext_UNSAFE(currentboardfilename, ".mhk");

View file

@ -427,7 +427,7 @@ void GLInstance::SetBlendFunc(int src, int dst)
glBlendFunc(blendstyles[src], blendstyles[dst]); glBlendFunc(blendstyles[src], blendstyles[dst]);
} }
static int renderops[] = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT }; static int renderops[] = { GL_FUNC_ADD, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT };
void GLInstance::SetBlendOp(int op) void GLInstance::SetBlendOp(int op)
{ {

View file

@ -264,7 +264,7 @@ void fullscreen_tint_gl_blood(int tint_blood_r, int tint_blood_g, int tint_blood
vt[2].Set(.0f, -2.5f); vt[2].Set(.0f, -2.5f);
GLInterface.Draw(DT_TRIANGLES, data.first, 3); GLInterface.Draw(DT_TRIANGLES, data.first, 3);
GLInterface.SetBlendOp(STYLEOP_Add); GLInterface.SetBlendOp(STYLEOP_Add);
GLInterface.SetColorub(0, 0, 0, 0); GLInterface.SetColorub(255, 255, 255, 255);
GLInterface.SetBlendFunc(STYLEALPHA_Src, STYLEALPHA_InvSrc); GLInterface.SetBlendFunc(STYLEALPHA_Src, STYLEALPHA_InvSrc);
GLInterface.UseColorOnly(false); GLInterface.UseColorOnly(false);

View file

@ -753,7 +753,6 @@ FString GameInterface::statFPS()
GameStats GameInterface::getStats() GameStats GameInterface::getStats()
{ {
GameStats stats;
DukePlayer_t* p = g_player[myconnectindex].ps; DukePlayer_t* p = g_player[myconnectindex].ps;
return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC }; return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC };
} }

View file

@ -24,9 +24,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#include "ns.h" #include "ns.h"
// Added improved crosshair accuracy
// Added UsingMenus for fragbar
//
#include "build.h" #include "build.h"

View file

@ -63,20 +63,23 @@ void CopySectorWalls(short dest_sectnum, short src_sectnum)
wall[dest_wall_num].lotag = wall[src_wall_num].lotag; wall[dest_wall_num].lotag = wall[src_wall_num].lotag;
wall[dest_wall_num].extra = wall[src_wall_num].extra; wall[dest_wall_num].extra = wall[src_wall_num].extra;
if (wall[dest_wall_num].nextwall >= 0 && wall[src_wall_num].nextwall >= 0) uint16_t const dest_nextwall = wall[dest_wall_num].nextwall;
uint16_t const src_nextwall = wall[src_wall_num].nextwall;
if (dest_nextwall < MAXWALLS && src_nextwall < MAXWALLS)
{ {
wall[wall[dest_wall_num].nextwall].picnum = wall[wall[src_wall_num].nextwall].picnum; wall[dest_nextwall].picnum = wall[src_nextwall].picnum;
wall[wall[dest_wall_num].nextwall].xrepeat = wall[wall[src_wall_num].nextwall].xrepeat; wall[dest_nextwall].xrepeat = wall[src_nextwall].xrepeat;
wall[wall[dest_wall_num].nextwall].yrepeat = wall[wall[src_wall_num].nextwall].yrepeat; wall[dest_nextwall].yrepeat = wall[src_nextwall].yrepeat;
wall[wall[dest_wall_num].nextwall].overpicnum = wall[wall[src_wall_num].nextwall].overpicnum; wall[dest_nextwall].overpicnum = wall[src_nextwall].overpicnum;
wall[wall[dest_wall_num].nextwall].pal = wall[wall[src_wall_num].nextwall].pal; wall[dest_nextwall].pal = wall[src_nextwall].pal;
wall[wall[dest_wall_num].nextwall].cstat = wall[wall[src_wall_num].nextwall].cstat; wall[dest_nextwall].cstat = wall[src_nextwall].cstat;
wall[wall[dest_wall_num].nextwall].shade = wall[wall[src_wall_num].nextwall].shade; wall[dest_nextwall].shade = wall[src_nextwall].shade;
wall[wall[dest_wall_num].nextwall].xpanning = wall[wall[src_wall_num].nextwall].xpanning; wall[dest_nextwall].xpanning = wall[src_nextwall].xpanning;
wall[wall[dest_wall_num].nextwall].ypanning = wall[wall[src_wall_num].nextwall].ypanning; wall[dest_nextwall].ypanning = wall[src_nextwall].ypanning;
wall[wall[dest_wall_num].nextwall].hitag = wall[wall[src_wall_num].nextwall].hitag; wall[dest_nextwall].hitag = wall[src_nextwall].hitag;
wall[wall[dest_wall_num].nextwall].lotag = wall[wall[src_wall_num].nextwall].lotag; wall[dest_nextwall].lotag = wall[src_nextwall].lotag;
wall[wall[dest_wall_num].nextwall].extra = wall[wall[src_wall_num].nextwall].extra; wall[dest_nextwall].extra = wall[src_nextwall].extra;
} }
dest_wall_num = wall[dest_wall_num].point2; dest_wall_num = wall[dest_wall_num].point2;

View file

@ -2413,7 +2413,8 @@ drawscreen(PLAYERp pp)
i = wal->nextsector; i = wal->nextsector;
if (i < 0) continue; if (i < 0) continue;
if (wal->cstat&0x0071) continue; if (wal->cstat&0x0071) continue;
if (wall[wal->nextwall].cstat&0x0071) continue; uint16_t const nextwall = wal->nextwall;
if (nextwall < MAXWALLS && wall[nextwall].cstat&0x0071) continue;
if (sector[i].lotag == 32767) continue; if (sector[i].lotag == 32767) continue;
if (sector[i].ceilingz >= sector[i].floorz) continue; if (sector[i].ceilingz >= sector[i].floorz) continue;
show2dsector[i>>3] |= (1<<(i&7)); show2dsector[i>>3] |= (1<<(i&7));

View file

@ -105,9 +105,6 @@ signed char MNU_InputString(char*, short);
SWBOOL IsCommand(const char* str); SWBOOL IsCommand(const char* str);
SWBOOL MNU_StartNetGame(void); SWBOOL MNU_StartNetGame(void);
const char* AppProperName = "VoidSW";
const char* AppTechnicalName = "voidsw";
#if DEBUG #if DEBUG
#define BETA 0 #define BETA 0
@ -2304,6 +2301,9 @@ void BonusScreen(PLAYERp pp)
} }
gStateControl(&State, &Tics); gStateControl(&State, &Tics);
videoClearViewableArea(0L);
rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1);
if (UserMapName[0]) if (UserMapName[0])
@ -3911,7 +3911,6 @@ void GetHelpInput(PLAYERp pp)
} }
short MirrorDelay; short MirrorDelay;
int MouseYAxisMode = -1;
void getinput(SW_PACKET *loc) void getinput(SW_PACKET *loc)
{ {
@ -3930,16 +3929,11 @@ void getinput(SW_PACKET *loc)
#define MAXVEL ((NORMALKEYMOVE*2)+10) #define MAXVEL ((NORMALKEYMOVE*2)+10)
#define MAXSVEL ((NORMALKEYMOVE*2)+10) #define MAXSVEL ((NORMALKEYMOVE*2)+10)
#define MAXANGVEL 100 #define MAXANGVEL 100
#define MAXAIMVEL 128
#define SET_LOC_KEY(loc, sync_num, key_test) SET(loc, ((!!(key_test)) << (sync_num))) #define SET_LOC_KEY(loc, sync_num, key_test) SET(loc, ((!!(key_test)) << (sync_num)))
ControlInfo info;
int32_t running;
int32_t turnamount;
static int32_t turnheldtime; static int32_t turnheldtime;
int32_t keymove;
int32_t momx, momy; int32_t momx, momy;
int aimvel;
int mouseaxis;
extern SWBOOL MenuButtonAutoRun; extern SWBOOL MenuButtonAutoRun;
extern SWBOOL MenuButtonAutoAim; extern SWBOOL MenuButtonAutoAim;
@ -3951,7 +3945,6 @@ void getinput(SW_PACKET *loc)
// reset all syncbits // reset all syncbits
loc->bits = 0; loc->bits = 0;
svel = vel = angvel = aimvel = 0;
// MAKE SURE THIS WILL GET SET // MAKE SURE THIS WILL GET SET
SET_LOC_KEY(loc->bits, SK_QUIT_GAME, MultiPlayQuitFlag); SET_LOC_KEY(loc->bits, SK_QUIT_GAME, MultiPlayQuitFlag);
@ -3978,7 +3971,9 @@ void getinput(SW_PACKET *loc)
} }
} }
int const aimMode = TEST(pp->Flags, PF_MOUSE_AIMING_ON);
ControlInfo info;
CONTROL_GetInput(&info); CONTROL_GetInput(&info);
if (in_mousedeadzone) if (in_mousedeadzone)
@ -4065,39 +4060,10 @@ void getinput(SW_PACKET *loc)
SET_LOC_KEY(loc->bits, SK_SPACE_BAR, ((!!inputState.GetKeyStatus(KEYSC_SPACE)) | buttonMap.ButtonDown(gamefunc_Open))); SET_LOC_KEY(loc->bits, SK_SPACE_BAR, ((!!inputState.GetKeyStatus(KEYSC_SPACE)) | buttonMap.ButtonDown(gamefunc_Open)));
running = false;// G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); int const running = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run));
int32_t turnamount;
int const keyMove = running ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; int32_t keymove;
constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp
constexpr int const analogTurnAmount = (NORMALTURN << 1);
if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop)
{
static int strafeyaw;
svel = -(info.mousex + strafeyaw) >> 3;
strafeyaw = (info.mousex + strafeyaw) % 8;
svel -= info.dyaw * keyMove / analogExtent;
}
else
{
angvel = fix16_div(fix16_from_int(info.mousex), F16(32));
angvel += fix16_from_int(info.dyaw) / analogExtent * (analogTurnAmount << 1);
angvel >>= 15;
}
aimvel = fix16_div(fix16_from_int(info.mousey), F16(64));
if (!in_mouseflip) // SW's mouse is inverted by default.
aimvel = -aimvel;
aimvel -= fix16_from_int(info.dpitch) / analogExtent * analogTurnAmount;
aimvel >>= 15;
svel -= info.dx * keyMove / analogExtent;
vel -= info.dz * keyMove / analogExtent;
if (running) if (running)
{ {
@ -4118,6 +4084,34 @@ void getinput(SW_PACKET *loc)
keymove = NORMALKEYMOVE; keymove = NORMALKEYMOVE;
} }
info.dz = (info.dz * move_scale)>>8;
info.dyaw = (info.dyaw * turn_scale)>>8;
int32_t svel = 0, vel = 0, angvel = 0, aimvel = 0;
if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop)
{
svel = -info.mousex;
svel -= info.dyaw * keymove / analogExtent;
}
else
{
angvel = info.mousex / 32;
angvel += info.dyaw * (turnamount << 1) / analogExtent;
}
if (true)//aimMode)
aimvel = -info.mousey / 64;
else
vel = -(info.mousey >> 6);
if (in_mouseflip)
aimvel = -aimvel;
aimvel -= info.dpitch * turnamount / analogExtent;
svel -= info.dx * keymove / analogExtent;
vel -= info.dz * keymove / analogExtent;
if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop) if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop)
{ {
if (buttonMap.ButtonDown(gamefunc_Turn_Left)) if (buttonMap.ButtonDown(gamefunc_Turn_Left))
@ -4170,19 +4164,11 @@ void getinput(SW_PACKET *loc)
if (buttonMap.ButtonDown(gamefunc_Move_Backward)) if (buttonMap.ButtonDown(gamefunc_Move_Backward))
vel += -keymove; vel += -keymove;
vel = clamp(vel, -MAXVEL, MAXVEL);
svel = clamp(svel, -MAXSVEL, MAXSVEL);
if (vel < -MAXVEL) angvel = clamp(angvel, -MAXANGVEL, MAXANGVEL);
vel = -MAXVEL; aimvel = clamp(aimvel, -MAXAIMVEL, MAXAIMVEL);
if (vel > MAXVEL)
vel = MAXVEL;
if (svel < -MAXSVEL)
svel = -MAXSVEL;
if (svel > MAXSVEL)
svel = MAXSVEL;
if (angvel < -MAXANGVEL)
angvel = -MAXANGVEL;
if (angvel > MAXANGVEL)
angvel = MAXANGVEL;
momx = mulscale9(vel, sintable[NORM_ANGLE(newpp->pang + 512)]); momx = mulscale9(vel, sintable[NORM_ANGLE(newpp->pang + 512)]);
momy = mulscale9(vel, sintable[NORM_ANGLE(newpp->pang)]); momy = mulscale9(vel, sintable[NORM_ANGLE(newpp->pang)]);
@ -4456,7 +4442,7 @@ void drawoverheadmap(int cposx, int cposy, int czoom, short cang)
for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++) for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++)
{ {
k = wal->nextwall; k = wal->nextwall;
if (k < 0) if ((unsigned)k >= MAXWALLS)
continue; continue;
if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0) if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0)
@ -4709,7 +4695,7 @@ SHOWSPRITE:
for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++) for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++)
{ {
if (wal->nextwall >= 0) if ((uint16_t)wal->nextwall < MAXWALLS)
continue; continue;
if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0) if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0)

View file

@ -360,9 +360,6 @@ extern char MessageOutputString[256];
#define SET_SPRITE_TAG13(sp,val) (*((short*)&sprite[sp].xoffset)) = B_LITTLE16(val) #define SET_SPRITE_TAG13(sp,val) (*((short*)&sprite[sp].xoffset)) = B_LITTLE16(val)
#define SET_SPRITE_TAG14(sp,val) (*((short*)&sprite[sp].xrepeat)) = B_LITTLE16(val) #define SET_SPRITE_TAG14(sp,val) (*((short*)&sprite[sp].xrepeat)) = B_LITTLE16(val)
// this will get you the other wall moved by dragpoint
#define DRAG_WALL(w) (wall[wall[(w)].nextwall].point2)
// OVER and UNDER water macros // OVER and UNDER water macros
#define SpriteInDiveArea(sp) (TEST(sector[(sp)->sectnum].extra, SECTFX_DIVE_AREA) ? TRUE : FALSE) #define SpriteInDiveArea(sp) (TEST(sector[(sp)->sectnum].extra, SECTFX_DIVE_AREA) ? TRUE : FALSE)
#define SpriteInUnderwaterArea(sp) (TEST(sector[(sp)->sectnum].extra, SECTFX_UNDERWATER|SECTFX_UNDERWATER2) ? TRUE : FALSE) #define SpriteInUnderwaterArea(sp) (TEST(sector[(sp)->sectnum].extra, SECTFX_UNDERWATER|SECTFX_UNDERWATER2) ? TRUE : FALSE)
@ -2251,7 +2248,6 @@ extern char keys[];
extern short screenpeek; extern short screenpeek;
extern int dimensionmode, zoom; extern int dimensionmode, zoom;
extern int vel,svel,angvel;
#define STAT_DAMAGE_LIST_SIZE 20 #define STAT_DAMAGE_LIST_SIZE 20
extern int16_t StatDamageList[STAT_DAMAGE_LIST_SIZE]; extern int16_t StatDamageList[STAT_DAMAGE_LIST_SIZE];

View file

@ -578,7 +578,7 @@ JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
{ {
for (cnt = MAXMIRRORS - 1; cnt >= 0; cnt--) for (cnt = MAXMIRRORS - 1; cnt >= 0; cnt--)
//if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(cnt + CAMSPRITE)) //if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(cnt + CAMSPRITE))
if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(mirror[cnt].campic)) if (TEST_GOTPIC(cnt + MIRRORLABEL) || ((unsigned)mirror[cnt].campic < MAXTILES && TEST_GOTPIC(mirror[cnt].campic)))
{ {
bIsWallMirror = FALSE; bIsWallMirror = FALSE;
if (TEST_GOTPIC(cnt + MIRRORLABEL)) if (TEST_GOTPIC(cnt + MIRRORLABEL))
@ -587,7 +587,7 @@ JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
RESET_GOTPIC(cnt + MIRRORLABEL); RESET_GOTPIC(cnt + MIRRORLABEL);
} }
//else if (TEST_GOTPIC(cnt + CAMSPRITE)) //else if (TEST_GOTPIC(cnt + CAMSPRITE))
else if (TEST_GOTPIC(mirror[cnt].campic)) else if ((unsigned)mirror[cnt].campic < MAXTILES && TEST_GOTPIC(mirror[cnt].campic))
{ {
//RESET_GOTPIC(cnt + CAMSPRITE); //RESET_GOTPIC(cnt + CAMSPRITE);
RESET_GOTPIC(mirror[cnt].campic); RESET_GOTPIC(mirror[cnt].campic);

View file

@ -93,13 +93,17 @@ void SectorLightShade(SPRITEp sp, short intensity)
wall[w].pal = sp->pal; wall[w].pal = sp->pal;
wallcount++; wallcount++;
if (TEST(sp->extra, SPRX_BOOL5) && wall[w].nextwall >= 0) if (TEST(sp->extra, SPRX_BOOL5))
{ {
base_shade = wall_shade[wallcount]; uint16_t const nextwall = wall[w].nextwall;
wall[wall[w].nextwall].shade = base_shade + intensity; if (nextwall < MAXWALLS)
if (!TEST_BOOL6(sp)) {
wall[wall[w].nextwall].pal = sp->pal; base_shade = wall_shade[wallcount];
wallcount++; wall[nextwall].shade = base_shade + intensity;
if (!TEST_BOOL6(sp))
wall[nextwall].pal = sp->pal;
wallcount++;
}
} }
} }
} }

View file

@ -683,12 +683,6 @@ SWBOOL MNU_KeySetupCustom(UserCall call, MenuItem *item)
{ {
inputState.ClearKeyStatus(inputState.GetLastScanCode()); inputState.ClearKeyStatus(inputState.GetLastScanCode());
//KeyboardKeys[currentkey][currentcol] = KB_GetLastScanCode();
#if 0 // [JM] Re-do this shit !CHECKME!
CONTROL_MapKey(currentkey,
KeyboardKeys[currentkey][0],
KeyboardKeys[currentkey][1]);
#endif
currentmode = 0; currentmode = 0;
} }
@ -811,12 +805,12 @@ SWBOOL MNU_KeySetupCustom(UserCall call, MenuItem *item)
MNU_DrawSmallString(OPT_XS, j, ds, (i==currentkey) ? 0 : 12, 16); MNU_DrawSmallString(OPT_XS, j, ds, (i==currentkey) ? 0 : 12, 16);
p = keyGetName(KeyboardKeys[i][0]); p = keyGetName(KeyboardKeys[i][0]);
if (!p || KeyboardKeys[i][0]==0xff) p = " -"; if (!p || !KeyboardKeys[i][0] || KeyboardKeys[i][0]==0xff) p = " -";
MNU_DrawSmallString(OPT_XSIDE, j, p, (i==currentkey) ? -5 : 12, MNU_DrawSmallString(OPT_XSIDE, j, p, (i==currentkey) ? -5 : 12,
(i==currentkey && currentcol==0) ? 14 : 16); (i==currentkey && currentcol==0) ? 14 : 16);
p = keyGetName(KeyboardKeys[i][1]); p = keyGetName(KeyboardKeys[i][1]);
if (!p || KeyboardKeys[i][1]==0xff) p = " -"; if (!p || !KeyboardKeys[i][1] || KeyboardKeys[i][1]==0xff) p = " -";
MNU_DrawSmallString(OPT_XSIDE + 4*14, j, p, (i==currentkey) ? -5 : 12, MNU_DrawSmallString(OPT_XSIDE + 4*14, j, p, (i==currentkey) ? -5 : 12,
(i==currentkey && currentcol==1) ? 14 : 16); (i==currentkey && currentcol==1) ? 14 : 16);
#endif #endif
@ -1276,7 +1270,7 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
//5261, //5261,
//5262 //5262
5114 // JBF: for my credits 5120 // 5114 // JBF: for my credits
}; };
static short SWOrderScreen[] = static short SWOrderScreen[] =
{ {
@ -1288,7 +1282,7 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
5118, 5118,
4979, 4979,
5114 // JBF: for my credits 5120 // 5114 // JBF: for my credits
}; };
short *OrderScreen, OrderScreenSiz; short *OrderScreen, OrderScreenSiz;
@ -1317,9 +1311,9 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
{ {
DidOrderSound = TRUE; DidOrderSound = TRUE;
choose_snd = STD_RANDOM_RANGE(1000); choose_snd = STD_RANDOM_RANGE(1000);
if (choose_snd > 500 && !FX_SoundActive(wanghandle)) if (choose_snd > 500 && !FX_SoundValidAndActive(wanghandle))
wanghandle = PlaySound(DIGI_WANGORDER1, &zero, &zero, &zero, v3df_dontpan); wanghandle = PlaySound(DIGI_WANGORDER1, &zero, &zero, &zero, v3df_dontpan);
else if (!FX_SoundActive(wanghandle)) else if (!FX_SoundValidAndActive(wanghandle))
wanghandle = PlaySound(DIGI_WANGORDER2, &zero, &zero, &zero, v3df_dontpan); wanghandle = PlaySound(DIGI_WANGORDER2, &zero, &zero, &zero, v3df_dontpan);
} }
@ -1416,7 +1410,8 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
on_screen = 0; on_screen = 0;
// CTW MODIFICATION END // CTW MODIFICATION END
rotatesprite(0,0,RS_SCALE,0,OrderScreen[on_screen],0,0, int const shade = on_screen == OrderScreenSiz-1 ? 8 : 0;
rotatesprite(0,0,RS_SCALE,0,OrderScreen[on_screen], shade, 0,
(ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST), (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST),
0, 0, xdim-1, ydim-1); 0, 0, xdim-1, ydim-1);
@ -1427,38 +1422,31 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
static const char *jtitle = "^Port Credits"; static const char *jtitle = "^Port Credits";
static const char *jtext[] = static const char *jtext[] =
{ {
"*GAME AND ENGINE PORT", "*Developers",
" Richard \"TerminX\" Gobeille",
" Evan \"Hendricks266\" Ramos",
" Alex \"pogokeen\" Dawson",
"*Retired developers",
" Pierre-Loup \"Plagman\" Griffais",
" Philipp \"Helixhorned\" Kutin",
"*Special thanks to",
" Jonathon \"JonoF\" Fowler", " Jonathon \"JonoF\" Fowler",
"-", "*Uses BUILD Engine technology by",
"*\"POLYMOST\" 3D RENDERER",
"*NETWORKING, OTHER CODE",
" Ken \"Awesoken\" Silverman", " Ken \"Awesoken\" Silverman",
"*Additional thanks to",
" Alexey \"Nuke.YKT\" Skrybykin",
" Jordon \"Striker\" Moss",
" Par \"Parkar\" Karlsson", // "Pär \"Parkar\" Karlsson",
" Ben \"ProAsm\" Smit",
" NY00123",
"-", "-",
" Visit http://www.jonof.id.au/jfsw for the", " Visit eduke32.com for news and updates"
" source code, latest news, and updates of this port."
}; };
#if 0
static const char *scroller[] = static const char *scroller[] =
{ {
"This program is free software; you can redistribute it",
"and/or modify it under the terms of the GNU General",
"Public License as published by the Free Software",
"Foundation; either version 2 of the License, or (at your",
"option) any later version.",
"",
"This program is distributed in the hope that it will be",
"useful but WITHOUT ANY WARRANTY; without even the implied",
"warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR",
"PURPOSE. See the GNU General Public License (GPL.TXT) for",
"more details.",
"",
"",
"",
"",
"Thanks to these people for their input and contributions:", "Thanks to these people for their input and contributions:",
"", "",
"Richard \"TerminX\" Gobeille,",
"Par \"Parkar\" Karlsson", // "Pär \"Parkar\" Karlsson",
"Ben \"ProAsm\" Smit",
"", "",
"and all those who submitted bug reports and ", "and all those who submitted bug reports and ",
"supported the project financially!", "supported the project financially!",
@ -1470,9 +1458,9 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
"", "",
"" ""
}; };
const int numscrollerlines = SIZ(scroller); #endif
short dimx, dimy; short dimx, dimy;
int ycur = 54; int ycur = 20;
unsigned ji; unsigned ji;
dimy = 0; MNU_MeasureString(jtitle, &dimx, &dimy); dimy = 0; MNU_MeasureString(jtitle, &dimx, &dimy);
@ -1502,6 +1490,8 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
} }
} }
#if 0
const int numscrollerlines = SIZ(scroller);
int m,i; int m,i;
for (m=0, i=((int32_t) totalclock/104)%numscrollerlines; m<4; m++,i++) for (m=0, i=((int32_t) totalclock/104)%numscrollerlines; m<4; m++,i++)
{ {
@ -1511,6 +1501,7 @@ MNU_OrderCustom(UserCall call, MenuItem *item)
MNU_MeasureSmallString(scroller[i], &dimx, &dimy); MNU_MeasureSmallString(scroller[i], &dimx, &dimy);
MNU_DrawSmallString(160-(dimx>>1), 154+(m*7), scroller[i], 0, 8); MNU_DrawSmallString(160-(dimx>>1), 154+(m*7), scroller[i], 0, 8);
} }
#endif
} }
//inputState.ClearKeysDown(); //inputState.ClearKeysDown();
@ -2893,11 +2884,8 @@ MNU_JoystickCheck(MenuItem *item)
static SWBOOL static SWBOOL
MNU_TryMusicInit(void) MNU_TryMusicInit(void)
{ {
if (PlaySong(0, RedBookSong[Level], TRUE, FALSE))
{
if (currentmenu->cursor == 0) if (currentmenu->cursor == 0)
MNU_MusicCheck(&currentmenu->items[currentmenu->cursor+1]); MNU_MusicCheck(&currentmenu->items[currentmenu->cursor+1]);
}
return TRUE; return TRUE;
} }
@ -3773,11 +3761,11 @@ static void MNU_DownLevel(MenuGroup * group)
static void MNU_UpLevel(void) static void MNU_UpLevel(void)
{ {
int zero = 0; int zero = 0;
static int handle1=0; static int handle1;
// if run out of menus then EXIT // if run out of menus then EXIT
if (!menuarrayptr) if (!menuarrayptr)
{ {
if(!FX_SoundActive(handle1)) if (!FX_SoundValidAndActive(handle1))
handle1 = PlaySound(DIGI_STARCLINK,&zero,&zero,&zero,v3df_dontpan); handle1 = PlaySound(DIGI_STARCLINK,&zero,&zero,&zero,v3df_dontpan);
ExitMenus(); ExitMenus();
return; return;
@ -4118,7 +4106,7 @@ void MNU_DoMenu( CTLType type, PLAYERp pp )
SWBOOL resetitem; SWBOOL resetitem;
unsigned char key; unsigned char key;
int zero = 0; int zero = 0;
static int handle2 = 0; static int handle2;
static int limitmove=0; static int limitmove=0;
static SWBOOL select_held=FALSE; static SWBOOL select_held=FALSE;
@ -4152,7 +4140,7 @@ void MNU_DoMenu( CTLType type, PLAYERp pp )
{ {
static int handle5=0; static int handle5=0;
I_GeneralTriggerClear(); I_GeneralTriggerClear();
if (!FX_SoundActive(handle5)) if (!FX_SoundValidAndActive(handle5))
handle5 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan); handle5 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan);
inputState.ClearKeysDown(); inputState.ClearKeysDown();
MNU_DoItem(); MNU_DoItem();
@ -4175,16 +4163,16 @@ void MNU_DoMenu( CTLType type, PLAYERp pp )
else if (I_ReturnTrigger()) else if (I_ReturnTrigger())
{ {
I_ReturnTriggerClear(); I_ReturnTriggerClear();
static int handle3=0; static int handle3;
if (!FX_SoundActive(handle3)) if (!FX_SoundValidAndActive(handle3))
handle3 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan); handle3 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan);
MNU_UpLevel(); MNU_UpLevel();
resetitem = TRUE; resetitem = TRUE;
} }
else if (MNU_DoHotkey()) else if (MNU_DoHotkey())
{ {
static int handle4=0; static int handle4;
if (!FX_SoundActive(handle4)) if (!FX_SoundValidAndActive(handle4))
handle4 = PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan); handle4 = PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan);
resetitem = TRUE; resetitem = TRUE;
} }

View file

@ -173,7 +173,7 @@ int DoToiletGirl(short SpriteNum)
choose_snd = RANDOM_P2(1024<<4)>>4; choose_snd = RANDOM_P2(1024<<4)>>4;
if (!FX_SoundActive(handle)) if (!FX_SoundValidAndActive(handle))
{ {
if (choose_snd > 750) if (choose_snd > 750)
handle = PlaySound(DIGI_TOILETGIRLFART1,&sp->x,&sp->y,&sp->z,v3df_dontpan); handle = PlaySound(DIGI_TOILETGIRLFART1,&sp->x,&sp->y,&sp->z,v3df_dontpan);
@ -188,7 +188,7 @@ int DoToiletGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
if (RANDOM_RANGE(1000<<8)>>8 > 500) if (RANDOM_RANGE(1000<<8)>>8 > 500)
madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan);
@ -235,7 +235,7 @@ int NullToiletGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
if (RANDOM_RANGE(1000<<8)>>8 > 500) if (RANDOM_RANGE(1000<<8)>>8 > 500)
madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan);
@ -416,7 +416,7 @@ int DoWashGirl(short SpriteNum)
{ {
static int handle; static int handle;
if (!FX_SoundActive(handle)) if (!FX_SoundValidAndActive(handle))
{ {
if (RANDOM_P2(1024<<4)>>4 > 500) if (RANDOM_P2(1024<<4)>>4 > 500)
handle = PlaySound(DIGI_ANIMESING1,&sp->x,&sp->y,&sp->z,v3df_dontpan); handle = PlaySound(DIGI_ANIMESING1,&sp->x,&sp->y,&sp->z,v3df_dontpan);
@ -446,7 +446,7 @@ int DoWashGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
if (RANDOM_RANGE(1000<<8)>>8 > 500) if (RANDOM_RANGE(1000<<8)>>8 > 500)
madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan);
@ -490,7 +490,7 @@ int NullWashGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
if (RANDOM_RANGE(1000<<8)>>8 > 500) if (RANDOM_RANGE(1000<<8)>>8 > 500)
madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan);
@ -1305,7 +1305,7 @@ int DoCarGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);
@ -1360,7 +1360,7 @@ int NullCarGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);
@ -1532,7 +1532,7 @@ int DoMechanicGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);
@ -1587,7 +1587,7 @@ int NullMechanicGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);
@ -1760,7 +1760,7 @@ int DoSailorGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);
@ -1820,7 +1820,7 @@ int NullSailorGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);
@ -1968,7 +1968,7 @@ int DoPruneGirl(short SpriteNum)
USERp u = User[SpriteNum]; USERp u = User[SpriteNum];
SPRITEp sp = User[SpriteNum]->SpriteP; SPRITEp sp = User[SpriteNum]->SpriteP;
short rnd_range = 0; short rnd_range = 0;
static int madhandle=0,coyhandle=0; static int madhandle, coyhandle;
SWBOOL ICanSee = FALSE; SWBOOL ICanSee = FALSE;
DoActorPickClosePlayer(SpriteNum); DoActorPickClosePlayer(SpriteNum);
@ -1978,7 +1978,7 @@ int DoPruneGirl(short SpriteNum)
{ {
if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee)
{ {
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = STD_RANDOM_RANGE(1000); choose = STD_RANDOM_RANGE(1000);
@ -1998,7 +1998,7 @@ int DoPruneGirl(short SpriteNum)
} }
else else
{ {
if (!FX_SoundActive(coyhandle)) if (!FX_SoundValidAndActive(coyhandle))
{ {
short choose; short choose;
choose = STD_RANDOM_RANGE(1000); choose = STD_RANDOM_RANGE(1000);
@ -2049,7 +2049,7 @@ int NullPruneGirl(short SpriteNum)
{ {
static int madhandle; static int madhandle;
if (!FX_SoundActive(madhandle)) if (!FX_SoundValidAndActive(madhandle))
{ {
short choose; short choose;
choose = RANDOM_RANGE(1000); choose = RANDOM_RANGE(1000);

View file

@ -997,7 +997,11 @@ int WeaponOperate(PLAYERp pp)
if (pp->WpnRocketType != 2 || pp->CurWpn != pp->Wpn[WPN_MICRO]) if (pp->WpnRocketType != 2 || pp->CurWpn != pp->Wpn[WPN_MICRO])
{ {
pp->InitingNuke = FALSE; pp->InitingNuke = FALSE;
FX_StopSound(pp->nukevochandle); if (pp->nukevochandle > 0)
{
FX_StopSound(pp->nukevochandle);
pp->nukevochandle = 0;
}
} }
return 0; return 0;

View file

@ -134,7 +134,6 @@ extern SWBOOL FinishedLevel;
char PlayerGravity = PLAYER_JUMP_GRAV; char PlayerGravity = PLAYER_JUMP_GRAV;
#endif #endif
int vel, svel, angvel;
extern SWBOOL DebugOperate; extern SWBOOL DebugOperate;
//unsigned char synctics, lastsynctics; //unsigned char synctics, lastsynctics;
@ -2405,7 +2404,6 @@ MoveScrollMode2D(PLAYERp pp)
#define MAXANGVEL 100 #define MAXANGVEL 100
ControlInfo scrl_input; ControlInfo scrl_input;
int32_t running;
int32_t keymove; int32_t keymove;
int32_t momx, momy; int32_t momx, momy;
static int mfvel=0, mfsvel=0; static int mfvel=0, mfsvel=0;
@ -2436,19 +2434,19 @@ MoveScrollMode2D(PLAYERp pp)
Follow_posy = pp->posy; Follow_posy = pp->posy;
} }
running = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run));
if (buttonMap.ButtonDown(gamefunc_Strafe)) if (buttonMap.ButtonDown(gamefunc_Strafe))
mfsvel -= scrl_input.dyaw>>2; mfsvel -= scrl_input.dyaw>>2;
mfsvel -= scrl_input.dx>>2; mfsvel -= scrl_input.dx>>2;
mfvel = -scrl_input.dz>>2; mfvel = -scrl_input.dz>>2;
#if 0
int const running = !!BUTTON(gamefunc_Run) ^ !!TEST(pp->Flags, PF_LOCK_RUN);
if (running) if (running)
{ {
//keymove = NORMALKEYMOVE << 1; keymove = NORMALKEYMOVE << 1;
keymove = NORMALKEYMOVE;
} }
else else
#endif
{ {
keymove = NORMALKEYMOVE; keymove = NORMALKEYMOVE;
} }
@ -3116,7 +3114,7 @@ DriveCrush(PLAYERp pp, int *x, int *y)
if (sp->z < sop->crush_z) if (sp->z < sop->crush_z)
continue; continue;
vel = FindDistance2D(pp->xvect>>8, pp->yvect>>8); int32_t const vel = FindDistance2D(pp->xvect>>8, pp->yvect>>8);
if (vel < 9000) if (vel < 9000)
{ {
DoActorBeginSlide(i, getangle(pp->xvect, pp->yvect), vel/8, 5); DoActorBeginSlide(i, getangle(pp->xvect, pp->yvect), vel/8, 5);
@ -3738,7 +3736,7 @@ DoPlayerFall(PLAYERp pp)
PlaySound(DIGI_HITGROUND, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); PlaySound(DIGI_HITGROUND, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan);
} }
if (handle && FX_SoundActive(handle)) if (FX_SoundValidAndActive(handle))
{ {
// My sound code will detect the sound has stopped and clean up // My sound code will detect the sound has stopped and clean up
// for you. // for you.
@ -5168,9 +5166,10 @@ DoPlayerStopDiveNoWarp(PLAYERp pp)
if (!NoMeters) SetRedrawScreen(pp); if (!NoMeters) SetRedrawScreen(pp);
if (pp->TalkVocHandle && FX_SoundActive(pp->TalkVocHandle)) if (FX_SoundValidAndActive(pp->TalkVocHandle))
{ {
FX_StopSound(pp->TalkVocHandle); FX_StopSound(pp->TalkVocHandle);
pp->TalkVocHandle = 0;
pp->PlayerTalking = FALSE; pp->PlayerTalking = FALSE;
} }
@ -5203,9 +5202,10 @@ DoPlayerStopDive(PLAYERp pp)
if (!NoMeters) SetRedrawScreen(pp); if (!NoMeters) SetRedrawScreen(pp);
if (pp->TalkVocHandle && FX_SoundActive(pp->TalkVocHandle)) if (FX_SoundValidAndActive(pp->TalkVocHandle))
{ {
FX_StopSound(pp->TalkVocHandle); FX_StopSound(pp->TalkVocHandle);
pp->TalkVocHandle = 0;
pp->PlayerTalking = FALSE; pp->PlayerTalking = FALSE;
} }
@ -6505,7 +6505,7 @@ DoPlayerBeginDie(PLAYERp pp)
// Override any previous talking, death scream has precedance // Override any previous talking, death scream has precedance
if (pp->PlayerTalking) if (pp->PlayerTalking)
{ {
if (FX_SoundActive(pp->TalkVocHandle)) if (FX_SoundValidAndActive(pp->TalkVocHandle))
FX_StopSound(pp->TalkVocHandle); FX_StopSound(pp->TalkVocHandle);
pp->PlayerTalking = FALSE; pp->PlayerTalking = FALSE;
pp->TalkVocnum = -1; pp->TalkVocnum = -1;

View file

@ -1246,11 +1246,11 @@ int DoRipper2StandHeart(short SpriteNum)
{ {
SPRITEp sp = &sprite[SpriteNum]; SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum]; USERp u = User[SpriteNum];
static int riphearthandle=0; static int riphearthandle;
NullRipper2(SpriteNum); NullRipper2(SpriteNum);
if (!FX_SoundActive(riphearthandle)) if (!FX_SoundValidAndActive(riphearthandle))
riphearthandle = PlaySound(DIGI_RIPPER2HEARTOUT,&sp->x,&sp->y,&sp->z,v3df_none); riphearthandle = PlaySound(DIGI_RIPPER2HEARTOUT,&sp->x,&sp->y,&sp->z,v3df_none);
if ((u->WaitTics -= ACTORMOVETICS) <= 0) if ((u->WaitTics -= ACTORMOVETICS) <= 0)

View file

@ -126,7 +126,7 @@ void SetWallWarpHitscan(short sectnum)
// Travel all the way around loop setting wall bits // Travel all the way around loop setting wall bits
do do
{ {
if (wall[wall_num].nextwall >= 0) if ((uint16_t)wall[wall_num].nextwall < MAXWALLS)
SET(wall[wall_num].cstat, CSTAT_WALL_WARP_HITSCAN); SET(wall[wall_num].cstat, CSTAT_WALL_WARP_HITSCAN);
wall_num = wall[wall_num].point2; wall_num = wall[wall_num].point2;
} }
@ -830,9 +830,10 @@ GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
if (!found) if (!found)
continue; continue;
sectorlist[sln] = i;
if (sln < (int)SIZ(GlobStackSect)) if (sln < (int)SIZ(GlobStackSect))
GlobStackSect[sln] = i; GlobStackSect[sln] = i;
if (sln < (int)SIZ(sectorlist))
sectorlist[sln] = i;
sln++; sln++;
} }
} }
@ -845,10 +846,17 @@ GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
*lower = -1; *lower = -1;
return; return;
} }
else // Map rooms have NOT been dragged on top of each other
else if (sln == 1)
{
*lower = sectorlist[0];
*upper = sectorlist[0];
return;
}
// Map rooms HAVE been dragged on top of each other
// inside will somtimes find that you are in two different sectors if the x,y // inside will somtimes find that you are in two different sectors if the x,y
// is exactly on a sector line. // is exactly on a sector line.
if (sln > 2) else if (sln > 2)
{ {
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]); //DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
MONO_PRINT(ds); MONO_PRINT(ds);

View file

@ -280,8 +280,12 @@ void DoRotatorSetInterp(short SpriteNum)
setinterpolation(&wall[w].x); setinterpolation(&wall[w].x);
setinterpolation(&wall[w].y); setinterpolation(&wall[w].y);
setinterpolation(&wall[DRAG_WALL(w)].x); uint16_t const nextwall = wall[w].nextwall;
setinterpolation(&wall[DRAG_WALL(w)].y); if (nextwall < MAXWALLS)
{
setinterpolation(&wall[wall[nextwall].point2].x);
setinterpolation(&wall[wall[nextwall].point2].y);
}
} }
} }
@ -299,8 +303,12 @@ void DoRotatorStopInterp(short SpriteNum)
stopinterpolation(&wall[w].x); stopinterpolation(&wall[w].x);
stopinterpolation(&wall[w].y); stopinterpolation(&wall[w].y);
stopinterpolation(&wall[DRAG_WALL(w)].x); uint16_t const nextwall = wall[w].nextwall;
stopinterpolation(&wall[DRAG_WALL(w)].y); if (nextwall < MAXWALLS)
{
stopinterpolation(&wall[wall[nextwall].point2].x);
stopinterpolation(&wall[wall[nextwall].point2].y);
}
} }
} }

View file

@ -493,6 +493,7 @@ int SaveGame(short save_num)
MWRITE(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil); MWRITE(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil);
} }
int32_t svel = 0, vel = 0, angvel = 0;
MWRITE(&vel,sizeof(vel),1,fil); MWRITE(&vel,sizeof(vel),1,fil);
MWRITE(&svel,sizeof(svel),1,fil); MWRITE(&svel,sizeof(svel),1,fil);
MWRITE(&angvel,sizeof(angvel),1,fil); MWRITE(&angvel,sizeof(angvel),1,fil);
@ -1013,6 +1014,7 @@ int LoadGame(short save_num)
} }
} }
int32_t svel, vel, angvel;
MREAD(&vel,sizeof(vel),1,fil); MREAD(&vel,sizeof(vel),1,fil);
MREAD(&svel,sizeof(svel),1,fil); MREAD(&svel,sizeof(svel),1,fil);
MREAD(&angvel,sizeof(angvel),1,fil); MREAD(&angvel,sizeof(angvel),1,fil);

View file

@ -107,8 +107,12 @@ void SetSectorWallBits(short sectnum, int bit_mask, SWBOOL set_sectwall, SWBOOL
if (set_sectwall) if (set_sectwall)
SET(wall[wall_num].extra, bit_mask); SET(wall[wall_num].extra, bit_mask);
if (set_nextwall && wall[wall_num].nextwall >= 0) if (set_nextwall)
SET(wall[wall[wall_num].nextwall].extra, bit_mask); {
uint16_t const nextwall = wall[wall_num].nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, bit_mask);
}
wall_num = wall[wall_num].point2; wall_num = wall[wall_num].point2;
} }
@ -143,6 +147,28 @@ void WallSetupDontMove(void)
} }
} }
static void WallSetupLoop(WALLp wp, int16_t lotag, int16_t extra)
{
// set first wall
{
SET(wp->extra, extra);
uint16_t const nextwall = wp->nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, extra);
}
// Travel all the way around loop setting wall bits
for (uint16_t wall_num = wp->point2;
wall[wall_num].lotag != lotag;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, extra);
uint16_t const nextwall = wall[wall_num].nextwall;
if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, extra);
}
}
void void
WallSetup(void) WallSetup(void)
{ {
@ -181,111 +207,33 @@ WallSetup(void)
{ {
case TAG_WALL_LOOP_DONT_SPIN: case TAG_WALL_LOOP_DONT_SPIN:
{ {
short wall_num, start_wall; WallSetupLoop(wp, TAG_WALL_LOOP_DONT_SPIN, WALLFX_LOOP_DONT_SPIN);
// set first wall
SET(wp->extra, WALLFX_LOOP_DONT_SPIN);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_DONT_SPIN);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_DONT_SPIN;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_DONT_SPIN);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_DONT_SPIN);
}
break; break;
} }
case TAG_WALL_LOOP_DONT_SCALE: case TAG_WALL_LOOP_DONT_SCALE:
{ {
short wall_num, start_wall; WallSetupLoop(wp, TAG_WALL_LOOP_DONT_SCALE, WALLFX_DONT_SCALE);
// set first wall
SET(wp->extra, WALLFX_DONT_SCALE);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_DONT_SCALE);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_DONT_SCALE;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_DONT_SCALE);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_DONT_SCALE);
}
wp->lotag = 0; wp->lotag = 0;
break; break;
} }
case TAG_WALL_LOOP_OUTER_SECONDARY: case TAG_WALL_LOOP_OUTER_SECONDARY:
{ {
short wall_num, start_wall; // make sure it's a red wall
ASSERT((uint16_t)wp->nextwall < MAXWALLS);
// make sure its a red wall
ASSERT(wp->nextwall >= 0);
// set first wall
SET(wp->extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_OUTER_SECONDARY;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
}
WallSetupLoop(wp, TAG_WALL_LOOP_OUTER_SECONDARY, WALLFX_LOOP_OUTER|WALLFX_LOOP_OUTER_SECONDARY);
break; break;
} }
case TAG_WALL_LOOP_OUTER: case TAG_WALL_LOOP_OUTER:
{ {
short wall_num, start_wall; // make sure it's a red wall
ASSERT((uint16_t)wp->nextwall < MAXWALLS);
// make sure its a red wall
ASSERT(wp->nextwall >= 0);
// set first wall
SET(wp->extra, WALLFX_LOOP_OUTER);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_OUTER);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_OUTER;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_OUTER);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_OUTER);
}
WallSetupLoop(wp, TAG_WALL_LOOP_OUTER, WALLFX_LOOP_OUTER);
wp->lotag = 0; wp->lotag = 0;
break; break;
} }
@ -298,76 +246,19 @@ WallSetup(void)
case TAG_WALL_LOOP_SPIN_2X: case TAG_WALL_LOOP_SPIN_2X:
{ {
short wall_num, start_wall; WallSetupLoop(wp, TAG_WALL_LOOP_SPIN_2X, WALLFX_LOOP_SPIN_2X);
// set first wall
SET(wp->extra, WALLFX_LOOP_SPIN_2X);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_SPIN_2X);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_SPIN_2X;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_SPIN_2X);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_SPIN_2X);
}
break; break;
} }
case TAG_WALL_LOOP_SPIN_4X: case TAG_WALL_LOOP_SPIN_4X:
{ {
short wall_num, start_wall; WallSetupLoop(wp, TAG_WALL_LOOP_SPIN_4X, WALLFX_LOOP_SPIN_4X);
// set first wall
SET(wp->extra, WALLFX_LOOP_SPIN_4X);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_SPIN_4X);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_SPIN_4X;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_SPIN_4X);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_SPIN_4X);
}
break; break;
} }
case TAG_WALL_LOOP_REVERSE_SPIN: case TAG_WALL_LOOP_REVERSE_SPIN:
{ {
short wall_num, start_wall; WallSetupLoop(wp, TAG_WALL_LOOP_REVERSE_SPIN, WALLFX_LOOP_REVERSE_SPIN);
// set first wall
SET(wp->extra, WALLFX_LOOP_REVERSE_SPIN);
if (wp->nextwall >= 0)
SET(wall[wp->nextwall].extra, WALLFX_LOOP_REVERSE_SPIN);
// move the the next wall
start_wall = wp->point2;
// Travel all the way around loop setting wall bits
for (wall_num = start_wall;
wall[wall_num].lotag != TAG_WALL_LOOP_REVERSE_SPIN;
wall_num = wall[wall_num].point2)
{
SET(wall[wall_num].extra, WALLFX_LOOP_REVERSE_SPIN);
if (wall[wall_num].nextwall >= 0)
SET(wall[wall[wall_num].nextwall].extra, WALLFX_LOOP_REVERSE_SPIN);
}
break; break;
} }

View file

@ -273,13 +273,14 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
switch (wall[w].lotag) switch (wall[w].lotag)
{ {
case TAG_WALL_SLIDOR_LEFT: case TAG_WALL_SLIDOR_LEFT:
{
// prev wall // prev wall
pw = w - 1; pw = w - 1;
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{ {
// white wall - move 4 points // white wall - move 4 points
interp_func(&wall[w].x); interp_func(&wall[w].x);
@ -291,21 +292,23 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
{ {
// red wall - move 2 points // red wall - move 2 points
interp_func(&wall[w].x); interp_func(&wall[w].x);
interp_func(&wall[DRAG_WALL(w)].x); interp_func(&wall[wall[nextwall].point2].x);
interp_func(&wall[wall[w].point2].x); interp_func(&wall[wall[w].point2].x);
interp_func(&wall[DRAG_WALL(wall[w].point2)].x); interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].x);
} }
break; break;
}
case TAG_WALL_SLIDOR_RIGHT: case TAG_WALL_SLIDOR_RIGHT:
{
// prev wall // prev wall
pw = w - 1; pw = w - 1;
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{ {
// white wall - move 4 points // white wall - move 4 points
interp_func(&wall[w].x); interp_func(&wall[w].x);
@ -317,21 +320,23 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
{ {
// red wall - move 2 points // red wall - move 2 points
interp_func(&wall[w].x); interp_func(&wall[w].x);
interp_func(&wall[DRAG_WALL(w)].x); interp_func(&wall[wall[nextwall].point2].x);
interp_func(&wall[wall[w].point2].x); interp_func(&wall[wall[w].point2].x);
interp_func(&wall[DRAG_WALL(wall[w].point2)].x); interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].x);
} }
break; break;
}
case TAG_WALL_SLIDOR_UP: case TAG_WALL_SLIDOR_UP:
{
// prev wall // prev wall
pw = w - 1; pw = w - 1;
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{ {
interp_func(&wall[w].y); interp_func(&wall[w].y);
interp_func(&wall[pw].y); interp_func(&wall[pw].y);
@ -341,21 +346,23 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
else else
{ {
interp_func(&wall[w].y); interp_func(&wall[w].y);
interp_func(&wall[DRAG_WALL(w)].y); interp_func(&wall[wall[nextwall].point2].y);
interp_func(&wall[wall[w].point2].y); interp_func(&wall[wall[w].point2].y);
interp_func(&wall[DRAG_WALL(wall[w].point2)].y); interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].y);
} }
break; break;
}
case TAG_WALL_SLIDOR_DOWN: case TAG_WALL_SLIDOR_DOWN:
{
// prev wall // prev wall
pw = w - 1; pw = w - 1;
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) uint16_t const nextwall = wall[w].nextwall;
if (nextwall >= MAXWALLS)
{ {
interp_func(&wall[w].y); interp_func(&wall[w].y);
interp_func(&wall[pw].y); interp_func(&wall[pw].y);
@ -365,14 +372,14 @@ void DoSlidorInterp(short SpriteNum, INTERP_FUNCp interp_func)
else else
{ {
interp_func(&wall[w].y); interp_func(&wall[w].y);
interp_func(&wall[DRAG_WALL(w)].y); interp_func(&wall[wall[nextwall].point2].y);
interp_func(&wall[wall[w].point2].y); interp_func(&wall[wall[w].point2].y);
interp_func(&wall[DRAG_WALL(wall[w].point2)].y); interp_func(&wall[wall[wall[wall[w].point2].nextwall].point2].y);
} }
break; break;
} }
}
w = wall[w].point2; w = wall[w].point2;
} }
@ -397,7 +404,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{ {
// white wall - move 4 points // white wall - move 4 points
wall[w].x -= amt; wall[w].x -= amt;
@ -421,7 +428,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{ {
// white wall - move 4 points // white wall - move 4 points
wall[w].x += amt; wall[w].x += amt;
@ -445,7 +452,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{ {
wall[w].y -= amt; wall[w].y -= amt;
wall[pw].y -= amt; wall[pw].y -= amt;
@ -467,7 +474,7 @@ int DoSlidorMoveWalls(short SpriteNum, int amt)
if (w < startwall) if (w < startwall)
pw = endwall; pw = endwall;
if (wall[w].nextwall < 0) if ((uint16_t)wall[w].nextwall >= MAXWALLS)
{ {
wall[w].y += amt; wall[w].y += amt;
wall[pw].y += amt; wall[pw].y += amt;

View file

@ -527,9 +527,10 @@ StopSong(void)
if (DemoMode) if (DemoMode)
return; return;
if (SongType == SongTypeWave && SongVoice >= 0) if (SongType == SongTypeWave && SongVoice > 0)
{ {
FX_StopSound(SongVoice); FX_StopSound(SongVoice);
SongVoice = 0;
} }
else if (SongType == SongTypeMIDI) else if (SongType == SongTypeMIDI)
{ {
@ -553,7 +554,7 @@ PauseSong(SWBOOL pauseon)
{ {
if (!MusicEnabled()) return; if (!MusicEnabled()) return;
if (SongType == SongTypeWave && SongVoice >= 0) if (SongType == SongTypeWave && SongVoice > 0)
{ {
FX_PauseVoice(SongVoice, pauseon); FX_PauseVoice(SongVoice, pauseon);
} }
@ -1313,9 +1314,10 @@ DeleteNoSoundOwner(short spritenum)
// Make sure to stop active // Make sure to stop active
// sounds // sounds
if (FX_SoundActive(vp->handle)) if (FX_SoundValidAndActive(vp->handle))
{ {
FX_StopSound(vp->handle); FX_StopSound(vp->handle);
vp->handle = 0;
} }
#if 0 #if 0
@ -1372,9 +1374,10 @@ void DeleteNoFollowSoundOwner(short spritenum)
// If the follow flag is set, compare the x and y addresses. // If the follow flag is set, compare the x and y addresses.
if ((vp->flags & v3df_follow) && vp->x == &sp->x && vp->y == &sp->y) if ((vp->flags & v3df_follow) && vp->x == &sp->x && vp->y == &sp->y)
{ {
if (FX_SoundActive(vp->handle)) if (FX_SoundValidAndActive(vp->handle))
{ {
FX_StopSound(vp->handle); FX_StopSound(vp->handle);
vp->handle = 0;
} }
#if 0 #if 0
@ -1529,7 +1532,7 @@ DoTimedSound(VOC3D_INFOp p)
if (p->tics >= p->maxtics) if (p->tics >= p->maxtics)
{ {
if (!FX_SoundActive(p->handle)) if (!FX_SoundValidAndActive(p->handle))
{ {
// Check for special case ambient sounds // Check for special case ambient sounds
p->num = RandomizeAmbientSpecials(p->num); p->num = RandomizeAmbientSpecials(p->num);
@ -1549,7 +1552,7 @@ DoTimedSound(VOC3D_INFOp p)
p->deleted = TRUE; // Mark old sound for deletion p->deleted = TRUE; // Mark old sound for deletion
} }
} }
} // !FX_SoundActive }
p->tics = 0; p->tics = 0;
//while (p->tics >= p->maxtics) // Really stupid thing to do! //while (p->tics >= p->maxtics) // Really stupid thing to do!
@ -1577,8 +1580,11 @@ StopAmbientSound(void)
if (p->flags & v3df_kill) if (p->flags & v3df_kill)
{ {
if (FX_SoundActive(p->handle)) if (FX_SoundValidAndActive(p->handle))
{
FX_StopSound(p->handle); // Make sure to stop active sounds FX_StopSound(p->handle); // Make sure to stop active sounds
p->handle = 0;
}
p->deleted = TRUE; p->deleted = TRUE;
} }
@ -1668,8 +1674,11 @@ DoUpdateSounds3D(void)
// Is the sound slated for death? Kill it, otherwise play it. // Is the sound slated for death? Kill it, otherwise play it.
if (p->flags & v3df_kill) if (p->flags & v3df_kill)
{ {
if (FX_SoundActive(p->handle)) if (FX_SoundValidAndActive(p->handle))
{
FX_StopSound(p->handle); // Make sure to stop active sounds FX_StopSound(p->handle); // Make sure to stop active sounds
p->handle = 0;
}
//DSPRINTF(ds,"%d had v3df_kill.\n",p->num); //DSPRINTF(ds,"%d had v3df_kill.\n",p->num);
//MONO_PRINT(ds); //MONO_PRINT(ds);
@ -1677,7 +1686,7 @@ DoUpdateSounds3D(void)
} }
else else
{ {
if (!FX_SoundActive(p->handle) && !looping) if (!FX_SoundValidAndActive(p->handle) && !looping)
{ {
if (p->flags & v3df_intermit) if (p->flags & v3df_intermit)
{ {
@ -1691,7 +1700,7 @@ DoUpdateSounds3D(void)
p->deleted = TRUE; p->deleted = TRUE;
} }
} }
else if (FX_SoundActive(p->handle)) else if (FX_SoundValidAndActive(p->handle))
{ {
if (p->flags & v3df_follow) if (p->flags & v3df_follow)
{ {
@ -1732,6 +1741,7 @@ DoUpdateSounds3D(void)
if (dist >= 255 && p->vp->voc_distance == DIST_NORMAL) if (dist >= 255 && p->vp->voc_distance == DIST_NORMAL)
{ {
FX_StopSound(p->handle); // Make sure to stop active FX_StopSound(p->handle); // Make sure to stop active
p->handle = 0;
// sounds // sounds
} }
else else
@ -1770,7 +1780,7 @@ DoUpdateSounds3D(void)
} }
} }
} }
else if (!FX_SoundActive(p->handle) && looping) else if (!FX_SoundValidAndActive(p->handle) && looping)
{ {
if (p->flags & v3df_follow) if (p->flags & v3df_follow)
{ {
@ -1898,7 +1908,9 @@ Terminate3DSounds(void)
while (vp) while (vp)
{ {
FX_StopSound(vp->handle); // Make sure to stop active sounds if (vp->handle > 0)
FX_StopSound(vp->handle); // Make sure to stop active sounds
vp->handle = 0;
vp->deleted = TRUE; vp->deleted = TRUE;
vp = vp->next; vp = vp->next;
} }

View file

@ -2616,7 +2616,8 @@ SpriteSetup(void)
wallcount++; wallcount++;
if (TEST_BOOL5(sp)) if (TEST_BOOL5(sp))
{ {
if (wall[w].nextwall >= 0) uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{ {
wall_shade[wallcount] = wall[wall[w].nextwall].shade; wall_shade[wallcount] = wall[wall[w].nextwall].shade;
wallcount++; wallcount++;
@ -2672,7 +2673,8 @@ SpriteSetup(void)
wallcount++; wallcount++;
if (TEST_BOOL5(sp)) if (TEST_BOOL5(sp))
{ {
if (wall[w].nextwall >= 0) uint16_t const nextwall = wall[w].nextwall;
if (nextwall < MAXWALLS)
{ {
wall_shade[wallcount] = wall[wall[w].nextwall].shade; wall_shade[wallcount] = wall[wall[w].nextwall].shade;
wallcount++; wallcount++;
@ -2955,7 +2957,7 @@ SpriteSetup(void)
do do
{ {
// DO NOT TAG WHITE WALLS! // DO NOT TAG WHITE WALLS!
if (wall[wall_num].nextwall >= 0) if ((uint16_t)wall[wall_num].nextwall < MAXWALLS)
{ {
SET(wall[wall_num].cstat, CSTAT_WALL_WARP_HITSCAN); SET(wall[wall_num].cstat, CSTAT_WALL_WARP_HITSCAN);
} }
@ -3070,8 +3072,9 @@ SpriteSetup(void)
do do
{ {
SET(wall[wall_num].cstat, CSTAT_WALL_BLOCK_ACTOR); SET(wall[wall_num].cstat, CSTAT_WALL_BLOCK_ACTOR);
if (wall[wall_num].nextwall >= 0) uint16_t const nextwall = wall[wall_num].nextwall;
SET(wall[wall[wall_num].nextwall].cstat, CSTAT_WALL_BLOCK_ACTOR); if (nextwall < MAXWALLS)
SET(wall[nextwall].cstat, CSTAT_WALL_BLOCK_ACTOR);
wall_num = wall[wall_num].point2; wall_num = wall[wall_num].point2;
} }
while (wall_num != start_wall); while (wall_num != start_wall);

View file

@ -872,8 +872,9 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop)
// each wall has this set - for collision detection // each wall has this set - for collision detection
SET(wall[k].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK); SET(wall[k].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
if (wall[k].nextwall >= 0) uint16_t const nextwall = wall[k].nextwall;
SET(wall[wall[k].nextwall].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK); if (nextwall < MAXWALLS)
SET(wall[nextwall].extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
} }
} }
@ -2117,7 +2118,8 @@ DetectSectorObjectByWall(WALLp wph)
// if outer wall check the NEXTWALL also // if outer wall check the NEXTWALL also
if (TEST(wp->extra, WALLFX_LOOP_OUTER)) if (TEST(wp->extra, WALLFX_LOOP_OUTER))
{ {
if (wph == &wall[wp->nextwall]) uint16_t const nextwall = wp->nextwall;
if (nextwall < MAXWALLS && wph == &wall[nextwall])
return sop; return sop;
} }

View file

@ -9251,7 +9251,7 @@ DoVulcanBoulder(int16_t Weapon)
u->ret = move_missile(Weapon, u->xchange, u->ychange, u->zchange, u->ret = move_missile(Weapon, u->xchange, u->ychange, u->zchange,
u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS); u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS);
vel = ksqrt(SQ(u->xchange) + SQ(u->ychange)); int32_t const vel = ksqrt(SQ(u->xchange) + SQ(u->ychange));
if (vel < 30) if (vel < 30)
{ {
@ -11268,7 +11268,7 @@ SpawnNuclearSecondaryExp(int16_t Weapon, short ang)
RESET(exp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN); RESET(exp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
//ang = RANDOM_P2(2048); //ang = RANDOM_P2(2048);
vel = (2048+128) + RANDOM_RANGE(2048); int32_t const vel = (2048+128) + RANDOM_RANGE(2048);
eu->xchange = MOVEx(vel, ang); eu->xchange = MOVEx(vel, ang);
eu->ychange = MOVEy(vel, ang); eu->ychange = MOVEy(vel, ang);
eu->Radius = 200; // was NUKE_RADIUS eu->Radius = 200; // was NUKE_RADIUS
@ -20654,7 +20654,7 @@ SWBOOL TestDontStick(short SpriteNum, short hit_sect, short hit_wall, int hit_z)
return TRUE; return TRUE;
// if blocking red wallo // if blocking red wallo
if (TEST(wp->cstat, CSTAT_WALL_BLOCK) && wp->nextwall >= 0) if (TEST(wp->cstat, CSTAT_WALL_BLOCK) && (uint16_t)wp->nextwall < MAXWALLS)
return TRUE; return TRUE;
return FALSE; return FALSE;

View file

@ -725,7 +725,7 @@ int DoZillaMove(short SpriteNum)
//DoActorSlide(SpriteNum); //DoActorSlide(SpriteNum);
// Random Zilla taunts // Random Zilla taunts
if (!FX_SoundActive(handle)) if (!FX_SoundValidAndActive(handle))
{ {
choose = STD_RANDOM_RANGE(1000); choose = STD_RANDOM_RANGE(1000);
if (choose > 990) if (choose > 990)

View file

@ -1,235 +0,0 @@
#version 330
const int RF_ColorOnly = 1;
const int RF_UsePalette = 2;
const int RF_DetailMapping = 4;
const int RF_GlowMapping = 8;
const int RF_Brightmapping = 16;
const int RF_NPOTEmulation = 32;
const int RF_ShadeInterpolate = 64;
const int RF_FogDisabled = 128;
const int RF_HICTINT_Grayscale = 0x10000;
const int RF_HICTINT_Invert = 0x20000;
const int RF_HICTINT_Colorize = 0x40000;
const int RF_HICTINT_BLEND_Screen = 0x80000;
const int RF_HICTINT_BLEND_Overlay = 0x100000;
const int RF_HICTINT_BLEND_Hardlight = 0x200000;
const int RF_HICTINT_BLENDMASK = RF_HICTINT_BLEND_Screen | RF_HICTINT_BLEND_Overlay | RF_HICTINT_BLEND_Hardlight;
//s_texture points to an indexed color texture
uniform sampler2D s_texture;
//s_palswap is the palette swap texture where u is the color index and v is the shade
uniform sampler2D s_palswap;
//s_palette is the base palette texture where u is the color index
uniform sampler2D s_palette;
uniform sampler2D s_detail;
uniform sampler2D s_glow;
uniform sampler2D s_brightmap;
uniform float u_shade;
uniform float u_numShades;
uniform float u_shadeDiv;
uniform float u_visFactor;
uniform int u_flags;
uniform float u_alphaThreshold;
uniform float u_npotEmulationFactor;
uniform float u_npotEmulationXOffset;
uniform float u_brightness;
uniform vec4 u_fogColor;
uniform vec3 u_tintcolor;
uniform vec3 u_tintmodulate;
in vec4 v_color;
in float v_distance;
in vec4 v_texCoord;
in vec4 v_detailCoord;
in float v_fogCoord;
const float c_basepalScale = 255.0/256.0;
const float c_basepalOffset = 0.5/256.0;
const float c_zero = 0.0;
const float c_one = 1.0;
const float c_two = 2.0;
const vec4 c_vec4_one = vec4(c_one);
const float c_wrapThreshold = 0.9;
layout(location=0) out vec4 fragColor;
//===========================================================================
//
// Color to grayscale
//
//===========================================================================
float grayscale(vec4 color)
{
return dot(color.rgb, vec3(0.3, 0.56, 0.14));
}
//===========================================================================
//
// Hightile tinting code. (hictinting[dapalnum]) This can be done inside the shader
// to avoid costly texture duplication (but needs a more modern GLSL than 1.10.)
//
//===========================================================================
vec4 convertColor(vec4 color, int effect, vec3 tint)
{
#if 0
if (effect & RF_HICTINT_Grayscale)
{
float g = grayscale(color);
color = vec4(g, g, g, color.a);
}
if (effect & RF_HICTINT_Invert)
{
color = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b);
}
vec3 tcol = color.rgb * 255.0; // * 255.0 to make it easier to reuse the integer math.
tint *= 255.0;
if (effect & RF_HICTINT_Colorize)
{
tcol.b = min(((tcol.b) * tint.r) / 64.0, 255.0);
tcol.g = min(((tcol.g) * tint.g) / 64.0, 255.0);
tcol.r = min(((tcol.r) * tint.b) / 64.0, 255.0);
}
switch (effect & RF_HICTINT_BLENDMASK)
{
case RF_HICTINT_BLEND_Screen:
tcol.b = 255.0 - (((255.0 - tcol.b) * (255.0 - tint.r)) / 256.0);
tcol.g = 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 256.0);
tcol.r = 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 256.0);
break;
case RF_HICTINT_BLEND_Overlay:
tcol.b = tcol.b < 128.0? (tcol.b * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - tint.r)) / 128.0);
tcol.g = tcol.g < 128.0? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 128.0);
tcol.r = tcol.r < 128.0? (tcol.r * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 128.0);
break;
case RF_HICTINT_BLEND_Hardlight:
tcol.b = tint.r < 128.0 ? (tcol.b * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - r)) / 128.0);
tcol.g = tint.g < 128.0 ? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - g)) / 128.0);
tcol.r = tint.b < 128.0 ? (tcol.r * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - b)) / 128.0);
break;
}
color.rgb = tcol / 255.0;
#endif
return color;
}
//===========================================================================
//
//
//
//===========================================================================
void main()
{
float fullbright = 0.0;
vec4 color;
if ((u_flags & RF_ColorOnly) == 0)
{
float coordX = v_texCoord.x;
float coordY = v_texCoord.y;
vec2 newCoord;
// Coordinate adjustment for NPOT textures (something must have gone very wrong to make this necessary...)
if ((u_flags & RF_NPOTEmulation) != 0)
{
float period = floor(coordY / u_npotEmulationFactor);
coordX += u_npotEmulationXOffset * floor(mod(coordY, u_npotEmulationFactor));
coordY = period + mod(coordY, u_npotEmulationFactor);
}
newCoord = vec2(coordX, coordY);
// Paletted textures are stored in column major order rather than row major so coordinates need to be swapped here.
color = texture2D(s_texture, newCoord);
// This was further down but it really should be done before applying any kind of depth fading, not afterward.
vec4 detailColor = vec4(1.0);
if ((u_flags & RF_DetailMapping) != 0)
{
detailColor = texture2D(s_detail, v_detailCoord.xy);
detailColor = mix(vec4(1.0), 2.0 * detailColor, detailColor.a);
// Application of this differs based on render mode because for paletted rendering with palettized shade tables it can only be done after processing the shade table. We only have a palette index before.
}
float visibility = max(u_visFactor * v_distance - ((u_flags & RF_ShadeInterpolate) != 0.0? 0.5 : 0.0), 0.0);
float shade = clamp((u_shade + visibility), 0.0, u_numShades - 1.0);
if ((u_flags & RF_UsePalette) != 0)
{
int palindex = int(color.r * 255.0 + 0.1); // The 0.1 is for roundoff error compensation.
int shadeindex = int(floor(shade));
float colorIndexF = texelFetch(s_palswap, ivec2(palindex, shadeindex), 0).r;
int colorIndex = int(colorIndexF * 255.0 + 0.1); // The 0.1 is for roundoff error compensation.
vec4 palettedColor = texelFetch(s_palette, ivec2(colorIndex, 0), 0);
if ((u_flags & RF_ShadeInterpolate) != 0)
{
// Get the next shaded palette index for interpolation
colorIndexF = texelFetch(s_palswap, ivec2(palindex, shadeindex+1), 0).r;
colorIndex = int(colorIndexF * 255.0 + 0.1); // The 0.1 is for roundoff error compensation.
vec4 palettedColorNext = texelFetch(s_palette, ivec2(colorIndex, 0), 0);
float shadeFrac = mod(shade, 1.0);
palettedColor.rgb = mix(palettedColor.rgb, palettedColorNext.rgb, shadeFrac);
}
fullbright = palettedColor.a; // This only gets set for paletted rendering.
palettedColor.a = c_one-floor(color.r);
color = palettedColor;
color.rgb *= detailColor.rgb; // with all this palettizing, this can only be applied afterward, even though it is wrong to do it this way.
if (fullbright == 0.0) color.rgb *= v_color.rgb; // Well, this is dead wrong but unavoidable. For colored fog it applies the light to the fog as well...
}
else
{
color.rgb *= detailColor.rgb;
shade = clamp(shade * u_shadeDiv, 0.0, 1.0); // u_shadeDiv is really 1/shadeDiv.
vec3 lightcolor = v_color.rgb;
if ((u_flags & RF_FogDisabled) == 0)
{
lightcolor *= shade;
}
if ((u_flags & RF_Brightmapping) != 0)
{
vec4 brightcolor = texture2D(s_brightmap, v_texCoord.xy);
lightcolor = clamp(brightcolor.rgb + lightcolor, 0.0, 1.0);
}
color.rgb *= lightcolor;
if ((u_flags & RF_FogDisabled) == 0 && u_fogColor.rgb != vec3(0))
{
// Apply the shade as a linear depth fade ramp.
color.rgb += u_fogColor.rgb * (1.0 - shade);
}
}
if (color.a < u_alphaThreshold) discard; // it's only here that we have the alpha value available to be able to perform the alpha test.
color.a *= v_color.a;
}
else
{
// untextured rendering
color = v_color;
}
if ((u_flags & (RF_ColorOnly|RF_GlowMapping)) == RF_GlowMapping)
{
vec4 glowColor = texture2D(s_glow, v_texCoord.xy);
color.rgb = mix(color.rgb, glowColor.rgb, glowColor.a);
}
color.rgb = pow(color.rgb, vec3(u_brightness));
fragColor = color;
}