- fixed cherry picked commit.

# Conflicts:
#	source/core/gamecontrol.h
This commit is contained in:
Christoph Oelckers 2021-05-04 00:03:01 +02:00
parent 3a59243ea0
commit 7fa690082e
9 changed files with 81 additions and 51 deletions

View file

@ -197,6 +197,7 @@ enum
CSTAT_SPRITE_ALIGNMENT_WALL = 1u<<4u,
CSTAT_SPRITE_ALIGNMENT_FLOOR = 1u<<5u,
CSTAT_SPRITE_ALIGNMENT_SLAB = 1u<<4u | 1u<<5u,
CSTAT_SPRITE_ALIGNMENT_SLOPE = 1u << 4u | 1u << 5u,
CSTAT_SPRITE_ALIGNMENT_MASK = 1u<<4u | 1u<<5u,
};

View file

@ -11,6 +11,7 @@
#include "stats.h"
#include "i_time.h"
#include "palentry.h"
#include "build.h"
EXTERN_CVAR(Bool, hud_textfont)
@ -249,3 +250,21 @@ enum gameaction_t : int
ga_fullconsole,
};
extern gameaction_t gameaction;
inline void spriteSetSlope(int spritenum, int heinum)
{
auto spr = &sprite[spritenum];
int cstat = spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK;
if (spr->cstat & CSTAT_SPRITE_ALIGNMENT_FLOOR)
{
spr->xoffset = heinum & 255;
spr->yoffset = (heinum >> 8) & 255;
spr->cstat = (spr->cstat & ~CSTAT_SPRITE_ALIGNMENT_MASK) | (heinum != 0 ? CSTAT_SPRITE_ALIGNMENT_SLOPE : CSTAT_SPRITE_ALIGNMENT_FLOOR);
}
}
inline int spriteGetSlope(int spritenum)
{
auto spr = &sprite[spritenum];
return ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLOPE)? 0 : uint8_t(spr->xoffset) + (uint8_t(spr->yoffset) << 8);
}

View file

@ -30,6 +30,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
void RecoilDude(DBloodActor* actor);
int cumulDamage[kMaxXSprites];
DUDEEXTRA gDudeExtra[kMaxXSprites];
@ -917,11 +919,11 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
int fullHp = (pXSprite->sysData2 > 0) ? ClipRange(pXSprite->sysData2 << 4, 1, 65535) : getDudeInfo(pSprite->type)->startHealth << 4;
if (((100 * pXSprite->health) / fullHp) <= 75) {
cumulDamage[pSprite->extra] += nDamage << 4; // to be sure any enemy will play the recoil animation
RecoilDude(pSprite, pXSprite);
RecoilDude(&bloodActors[pXSprite->reference]);
}
}
consoleSysMsg("Player #%d does the critical damage to patrol dude #%d!", pPlayer->nPlayer + 1, pSprite->index);
DPrintf(DMSG_SPAMMY, "Player #%d does the critical damage to patrol dude #%d!", pPlayer->nPlayer + 1, pSprite->index);
}
return nDamage;
@ -929,9 +931,9 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
if (pSprite->type == kDudeModernCustomBurning) {
if (Chance(0x2000) && gDudeExtra[pSprite->extra].at0 < (int)gFrameClock) {
if (Chance(0x2000) && gDudeExtra[pSprite->extra].time < (int)gFrameClock) {
playGenDudeSound(pSprite, kGenDudeSndBurning);
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
gDudeExtra[pSprite->extra].time = (int)gFrameClock + 360;
}
if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400;
@ -977,7 +979,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
gDudeExtra[pSprite->extra].time = (int)gFrameClock + 360;
evKill(nSprite, 3, kCallbackFXFlameLick);
}
@ -991,13 +993,13 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
if (!dudeIsMelee(pXSprite)) {
if (inIdle(pXSprite->aiState) || Chance(getDodgeChance(pSprite))) {
if (!spriteIsUnderwater(pSprite)) {
if (!canDuck(pSprite) || !sub_5BDA8(pSprite, 14)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL);
if (!canDuck(pSprite) || !dudeIsPlayingSeq(pSprite, 14)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL);
else aiGenDudeNewState(pSprite, &genDudeDodgeShortD);
if (Chance(0x0200))
playGenDudeSound(pSprite, kGenDudeSndGotHit);
} else if (sub_5BDA8(pSprite, 13)) {
} else if (dudeIsPlayingSeq(pSprite, 13)) {
aiGenDudeNewState(pSprite, &genDudeDodgeShortW);
}
}

View file

@ -718,7 +718,7 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor
pXSector->Depth = bitReader.readUnsigned(3);
pXSector->panVel = bitReader.readUnsigned(8);
pXSector->panAngle = bitReader.readUnsigned(11);
bitReader.readUnsigned(1);
pXSector->unused1 = bitReader.readUnsigned(1);
pXSector->decoupled = bitReader.readUnsigned(1);
pXSector->triggerOnce = bitReader.readUnsigned(1);
pXSector->isTriggered = bitReader.readUnsigned(1);
@ -730,7 +730,7 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor
pXSector->Exit = bitReader.readUnsigned(1);
pXSector->Wallpush = bitReader.readUnsigned(1);
pXSector->color = bitReader.readUnsigned(1);
bitReader.readUnsigned(1);
/*pXSector->unused2 =*/ bitReader.readUnsigned(1);
pXSector->busyTimeB = bitReader.readUnsigned(12);
pXSector->waitTimeB = bitReader.readUnsigned(12);
pXSector->stopOn = bitReader.readUnsigned(1);
@ -921,7 +921,7 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor
pXSprite->Interrutable = bitReader.readUnsigned(1);
bitReader.readUnsigned(2);
pXSprite->respawnPending = bitReader.readUnsigned(2);
bitReader.readUnsigned(1);
pXSprite->unused2 = bitReader.readUnsigned(1);
pXSprite->lT = bitReader.readUnsigned(1);
pXSprite->dropMsg = bitReader.readUnsigned(8);
pXSprite->Decoupled = bitReader.readUnsigned(1);

View file

@ -95,6 +95,7 @@ struct XSPRITE {
unsigned int wave : 2; // Wave
unsigned int medium : 2; // medium
unsigned int respawn : 2; // Respawn option
unsigned int unused2 : 1; // (new) patrol state
};
};
int32_t targetX; // target x
@ -175,6 +176,7 @@ struct XSECTOR {
unsigned int bobFloor : 1; // Motion bob floor
unsigned int bobCeiling : 1; // Motion bob ceiling
unsigned int bobRotate : 1; // Motion rotate
unsigned int unused1 : 1; // (new) pause motion
};
};

View file

@ -36,6 +36,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
inline int mulscale8(int a, int b) { return MulScale(a, b, 8); }
bool gAllowTrueRandom = false;
bool gEventRedirectsUsed = false;
SPRITEMASS gSpriteMass[]; // cache for getSpriteMassBySize();
@ -2581,7 +2583,7 @@ void useSeqSpawnerGen(XSPRITE* pXSource, int objType, int index) {
sprite[nSprite].z = top;
break;
case 4:
sprite[nSprite].z = sprite[index].z + (tilesiz[sprite[index].picnum].y / 2 + picanm[sprite[index].picnum].yofs);
sprite[nSprite].z = sprite[index].z + tileHeight(sprite[index].picnum) / 2 + tileTopOffset(sprite[index].picnum);
break;
case 5:
case 6:
@ -3901,7 +3903,7 @@ int aiFightGetFineTargetDist(spritetype* pSprite, spritetype* pTarget) {
int sectorInMotion(int nSector) {
for (int i = 0; i < kMaxBusyCount; i++) {
if (gBusy->at0 == nSector) return i;
if (gBusy->index == nSector) return i;
}
return -1;
@ -3909,7 +3911,7 @@ int sectorInMotion(int nSector) {
void sectorPauseMotion(int nSector) {
dassert(xsectRangeIsFine(sector[nSector].extra));
assert(xsectRangeIsFine(sector[nSector].extra));
xsector[sector[nSector].extra].unused1 = 1;
SectorEndSound(nSector, xsector[sector[nSector].extra].state);
/*for (int nSprite = headspritesect[nSector]; nSprite >= 0; nSprite = nextspritesect[nSprite]) {
@ -3929,7 +3931,7 @@ void sectorContinueMotion(int nSector, EVENT event) {
if (gBusyCount >= kMaxBusyCount)
return;
dassert(xsectRangeIsFine(sector[nSector].extra));
assert(xsectRangeIsFine(sector[nSector].extra));
XSECTOR* pXSector = &xsector[sector[nSector].extra];
pXSector->unused1 = 0;
@ -3974,15 +3976,15 @@ void sectorContinueMotion(int nSector, EVENT event) {
busyFunc = BUSYID_7;
break;
default:
ThrowError("Unsupported sector type %d", sector[nSector].type);
I_Error("Unsupported sector type %d", sector[nSector].type);
break;
}
nDelta = (pXSector->state) ? -nDelta : nDelta;
gBusy[gBusyCount].at0 = nSector;
gBusy[gBusyCount].at4 = nDelta;
gBusy[gBusyCount].at8 = pXSector->busy;
gBusy[gBusyCount].atc = (BUSYID)busyFunc;
gBusy[gBusyCount].index = nSector;
gBusy[gBusyCount].delta = nDelta;
gBusy[gBusyCount].busy = pXSector->busy;
gBusy[gBusyCount].type = (BUSYID)busyFunc;
gBusyCount++;
SectorStartSound(nSector, pXSector->state);
@ -5620,7 +5622,7 @@ bool aiPatrolMoving(AISTATE* pAiState) {
void aiPatrolState(spritetype* pSprite, int state) {
dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
XSPRITE* pXSprite = &xsprite[pSprite->extra];
int seq = -1, i, start, end; bool crouch;
@ -5667,7 +5669,7 @@ void aiPatrolState(spritetype* pSprite, int state) {
if (curState->stateType != state || seq != curState->seqId) continue;
aiChooseDirection(pSprite, pXSprite, getangle(pXSprite->targetX - pSprite->x, pXSprite->targetY - pSprite->y));
if (pSprite->type == kDudeModernCustom) aiGenDudeNewState(pSprite, &genPatrolStates[i]);
else aiNewState(pSprite, pXSprite, &genPatrolStates[i]);
else aiNewState(&bloodActors[pXSprite->reference], &genPatrolStates[i]);
pXSprite->unused2 = crouch;
@ -5713,8 +5715,8 @@ bool aiPatrolMarkerReached(spritetype* pSprite, XSPRITE* pXSprite) {
// ignore z of marker for ground
spritetype* pMarker = &sprite[pXSprite->target];
int oX = klabs(pMarker->x - pSprite->x) >> 4;
int oY = klabs(pMarker->y - pSprite->y) >> 4;
int oX = abs(pMarker->x - pSprite->x) >> 4;
int oY = abs(pMarker->y - pSprite->y) >> 4;
return (approxDist(oX, oY) <= okDist);
}
@ -5802,7 +5804,7 @@ void aiPatrolStop(spritetype* pSprite, int target, bool alarm) {
if (spriRangeIsFine(target) && IsDudeSprite(&sprite[target]) && xspriRangeIsFine(sprite[target].extra)) {
aiSetTarget(pXSprite, target);
aiActivateDude(pSprite, pXSprite);
aiActivateDude(&bloodActors[pXSprite->reference]);
if (alarm)
aiPatrolAlarm(pSprite, Chance(0x0500));
@ -5830,7 +5832,7 @@ void aiPatrolMoveZ(spritetype* pSprite, XSPRITE* pXSprite) {
int nAng = ((pXSprite->goalAng + 1024 - pSprite->ang) & 2047) - 1024;
int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4;
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
if (klabs(nAng) > 341) {
if (abs(nAng) > 341) {
pSprite->ang = (pSprite->ang + 512) & 2047;
return;
}
@ -5840,7 +5842,10 @@ void aiPatrolMoveZ(spritetype* pSprite, XSPRITE* pXSprite) {
}
void aiPatrolMove(spritetype* pSprite, XSPRITE* pXSprite) {
void aiPatrolMove(DBloodActor* actor) {
auto pXSprite = &actor->x();
auto pSprite = &actor->s();
if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax))
return;
@ -5863,7 +5868,7 @@ void aiPatrolMove(spritetype* pSprite, XSPRITE* pXSprite) {
if (pSprite->type == kDudeModernCustom) {
aiGenDudeMoveForward(pSprite, pXSprite);
aiGenDudeMoveForward(&bloodActors[pXSprite->reference]);
} else {
@ -5873,9 +5878,9 @@ void aiPatrolMove(spritetype* pSprite, XSPRITE* pXSprite) {
int frontSpeed = pDudeInfo->frontSpeed;
pSprite->ang = (pSprite->ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047;
if (klabs(nAng) <= 341) {
xvel[pSprite->index] += mulscale30(frontSpeed, Cos(pSprite->ang));
yvel[pSprite->index] += mulscale30(frontSpeed, Sin(pSprite->ang));
if (abs(nAng) <= 341) {
xvel[pSprite->index] += MulScale(frontSpeed, Cos(pSprite->ang), 30);
yvel[pSprite->index] += MulScale(frontSpeed, Sin(pSprite->ang), 30);
}
}
@ -5908,13 +5913,13 @@ void aiPatrolAlarm(spritetype* pSprite, bool chain) {
if (spriRangeIsFine(target)) aiSetTarget(pXDude, target);
else aiSetTarget(pXDude, pXSprite->targetX, pXSprite->targetY, pXSprite->targetZ);
aiActivateDude(pDude, pXDude);
aiActivateDude(&bloodActors[pXDude->reference]);
if (chain) {
aiPatrolAlarm(pDude, Chance(chainChance));
chainChance -= 0x0100;
}
consoleSysMsg("Dude #%d alarms dude #%d", pSprite->index, pDude->index);
DPrintf(DMSG_SPAMMY, "Dude #%d alarms dude #%d", pSprite->index, pDude->index);
}
}
@ -5961,12 +5966,12 @@ bool readyForCrit(spritetype* pHunter, spritetype* pVictim) {
DUDEINFO* pDudeInfo = getDudeInfo(pVictim->type);
int nDeltaAngle = ((getangle(dx, dy) + 1024 - pVictim->ang) & 2047) - 1024;
return (klabs(nDeltaAngle) < (pDudeInfo->periphery >> 1));
return (abs(nDeltaAngle) < (pDudeInfo->periphery >> 1));
}
int aiPatrolSearchTargets(spritetype* pSprite, XSPRITE* pXSprite) {
dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type);
int i, x, y, z, dx, dy, nDist, eyeAboveZ;
PLAYER* pPlayer = NULL;
@ -6049,12 +6054,12 @@ int aiPatrolSearchTargets(spritetype* pSprite, XSPRITE* pXSprite) {
if (nDist < hearDist && hearChance > 0) {
consoleSysMsg("Patrol dude #%d hearing the Player #%d.", pSprite->index, pPlayer->nPlayer + 1);
DPrintf(DMSG_SPAMMY, "Patrol dude #%d hearing the Player #%d.", pSprite->index, pPlayer->nPlayer + 1);
pXSprite->data3 += hearChance;
}
if (nDist < seeDist && klabs(nDeltaAngle) < periphery && seeChance > 0) {
consoleSysMsg("Patrol dude #%d seeing the Player #%d.", pSprite->index, pPlayer->nPlayer + 1);
if (nDist < seeDist && abs(nDeltaAngle) < periphery && seeChance > 0) {
DPrintf(DMSG_SPAMMY, "Patrol dude #%d seeing the Player #%d.", pSprite->index, pPlayer->nPlayer + 1);
pXSprite->data3 += seeChance;
}
@ -6066,7 +6071,7 @@ int aiPatrolSearchTargets(spritetype* pSprite, XSPRITE* pXSprite) {
} else {
consoleSysMsg("Patrol dude #%d spot the Player #%d via touch.", pSprite->index, pPlayer->nPlayer + 1);
DPrintf(DMSG_SPAMMY, "Patrol dude #%d spot the Player #%d via touch.", pSprite->index, pPlayer->nPlayer + 1);
if (invisible) pPlayer->pwUpTime[kPwUpShadowCloak] = 0;
target = pSpr->index;
break;
@ -6083,9 +6088,12 @@ int aiPatrolSearchTargets(spritetype* pSprite, XSPRITE* pXSprite) {
return -1;
}
void aiPatrolThink(spritetype* pSprite, XSPRITE* pXSprite) {
void aiPatrolThink(DBloodActor*actor) {
auto pXSprite = &actor->x();
auto pSprite = &actor->s();
assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
int nTarget = -1;
if ((nTarget = aiPatrolSearchTargets(pSprite, pXSprite)) != -1) {

View file

@ -37,7 +37,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "actor.h"
#include "dude.h"
#include "player.h"
#include "triggers.h"
BEGIN_BLD_NS
@ -372,11 +371,11 @@ int listTx(XSPRITE* pXRedir, int tx);
void seqSpawnerOffSameTx(XSPRITE* pXSource);
// ------------------------------------------------------------------------- //
void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite);
void aiPatrolThink(spritetype* pSprite, XSPRITE* pXSprite);
void aiPatrolThink(DBloodActor* actor);
void aiPatrolStop(spritetype* pSprite, int target, bool alarm = false);
void aiPatrolAlarm(spritetype* pSprite, bool chain);
void aiPatrolState(spritetype* pSprite, int state);
void aiPatrolMove(spritetype* pSprite, XSPRITE* pXSprite);
void aiPatrolMove(DBloodActor* actor);
int aiPatrolMarkerBusy(int nExcept, int nMarker);
bool aiPatrolMarkerReached(spritetype* pSprite, XSPRITE* pXSprite);
AISTATE* aiInPatrolState(AISTATE* pAiState);

View file

@ -1965,13 +1965,13 @@ void trProcessBusy(void)
for (int i = gBusyCount-1; i >= 0; i--)
{
int nStatus;
int oldBusy = gBusy[i].at8;
gBusy[i].at8 = ClipRange(oldBusy+gBusy[i].at4*4, 0, 65536);
int oldBusy = gBusy[i].busy;
gBusy[i].busy = ClipRange(oldBusy+gBusy[i].delta*4, 0, 65536);
#ifdef NOONE_EXTENSIONS
if (!gModernMap || !xsector[sector[gBusy[i].at0].extra].unused1) nStatus = gBusyProc[gBusy[i].atc](gBusy[i].at0, gBusy[i].at8);
if (!gModernMap || !xsector[sector[gBusy[i].index].extra].unused1) nStatus = gBusyProc[gBusy[i].type](gBusy[i].index, gBusy[i].busy);
else nStatus = 3; // allow to pause/continue motion for sectors any time by sending special command
#else
nStatus = gBusyProc[gBusy[i].atc](gBusy[i].at0, gBusy[i].at8);
nStatus = gBusyProc[gBusy[i].type](gBusy[i].at0, gBusy[i].at8);
#endif
switch (nStatus) {
case 1:

View file

@ -29,6 +29,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "dude.h"
#include "player.h"
BEGIN_BLD_NS
enum BUSYID {
BUSYID_0 = 0,
BUSYID_1,
@ -45,10 +47,7 @@ struct BUSY {
int index;
int delta;
int busy;
/* int at0;
int at4;
int at8;*/
BUSYID atc;
int/*BUSYID*/ type;
};
extern BUSY gBusy[kMaxBusyCount];