- Added event initiator for sectors and walls

- Added dynamic dispersion for custom dude
- Added dynamic attack distance for custom dude
- Added dynamic damage resistance scale for custom dude
- There was some refactor actions performed
- Added player RX channels for triggering the players
- Updates for modern types
- There was added player control modern type which can do a lot things. It's
still WIP
- Other updates and fixes mainly related to gModernMap

Note that your save games will be no longer compatible

# Conflicts:
#	source/blood/src/actor.h
#	source/blood/src/aiunicult.h
#	source/blood/src/db.h
#	source/blood/src/player.h
#	source/blood/src/triggers.h
#	source/blood/src/weapon.cpp
This commit is contained in:
Grind Core 2019-11-08 22:57:01 +03:00 committed by Christoph Oelckers
parent d79c45584a
commit 0d82280b87
26 changed files with 1949 additions and 1106 deletions

View file

@ -3092,6 +3092,25 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
int nXSprite = pSprite->extra;
dassert(nXSprite > 0);
XSPRITE *pXSprite = &xsprite[pSprite->extra];
// kMaxSprites - 1 = custom dude had once life leech
if (pSprite->owner >= 0 && pSprite->owner != (kMaxSprites - 1)) {
switch (sprite[pSprite->owner].type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
for (int i = 0; i <= gGameOptions.nDifficulty; i++) {
if (!IsDudeSprite(pSprite) || gGenDudeExtra[pSprite->owner].slave[i] == pSprite->index || pXSprite->health <= 0) {
gGenDudeExtra[pSprite->owner].slave[i] = -1;
gGenDudeExtra[pSprite->owner].slaveCount = ClipRange(gGenDudeExtra[pSprite->owner].slaveCount - 1, 0, gGameOptions.nDifficulty + 1);
//viewSetSystemMessage("REMOVING %d FROM %d, COUNT: %d", pSprite->index, sprite[pSprite->owner].type, gGenDudeExtra[pSprite->owner].slaveCount);
break;
}
}
break;
}
}
switch (pSprite->type) {
case kDudeModernCustom: {
removeDudeStuff(pSprite);
@ -3143,7 +3162,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
int seqId = pXSprite->data2 + 18;
if (!gSysRes.Lookup(seqId, "SEQ")) {
seqKill(3, nXSprite);
sfxPlayGDXGenDudeSound(pSprite, 10);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTransforming);
spritetype* pEffect = gFX.fxSpawn((FX_ID)52, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, pSprite->ang);
if (pEffect != NULL) {
pEffect->cstat = CSTAT_SPRITE_ALIGNMENT_FACING;
@ -3168,7 +3187,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
return;
}
seqSpawn(seqId, 3, nXSprite, -1);
sfxPlayGDXGenDudeSound(pSprite, 10);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTransforming);
return;
}
break;
@ -3268,7 +3287,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
switch (pSprite->type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
sfxPlayGDXGenDudeSound(pSprite, 4);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathExplode);
break;
case kDudeCultistTommy:
case kDudeCultistShotgun:
@ -3387,7 +3406,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
seqSpawn(dudeInfo[nType].seqStartID+15, 3, nXSprite, nDudeToGibClient2);
break;
case kDudeModernCustom:
sfxPlayGDXGenDudeSound(pSprite, 2);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathNormal);
if (nSeq == 3) {
bool seq15 = gSysRes.Lookup(pXSprite->data2 + 15, "SEQ"); bool seq16 = gSysRes.Lookup(pXSprite->data2 + 16, "SEQ");
@ -3406,7 +3425,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
case kDudeModernCustomBurning:
{
sfxPlayGDXGenDudeSound(pSprite, 4);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathExplode);
damageType = DAMAGE_TYPE_3;
if (Chance(0x4000)) {
@ -3628,21 +3647,6 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
break;
}
// kMaxSprites - 1 = custom dude had once life leech
if (pSprite->owner != -1 && pSprite->owner != (kMaxSprites - 1)) {
//int owner = actSpriteIdToOwnerId(pSprite->xvel);
int owner = pSprite->owner;
switch (sprite[owner].type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
if (owner != -1) gDudeExtra[sprite[owner].extra].at6.u1.at4--;
break;
default:
break;
}
}
if (damageType == DAMAGE_TYPE_3)
{
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase];
@ -3672,7 +3676,7 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, in
nSource = pSprite->index;
PLAYER *pSourcePlayer = NULL;
if (IsPlayerSprite(&sprite[nSource])) pSourcePlayer = &gPlayer[sprite[nSource].type - kDudePlayer1];
if (IsPlayerSprite(&sprite[nSource])) pSourcePlayer = &gPlayer[sprite[nSource].type - kDudePlayer1];
if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0;
switch (pSprite->statnum) {
@ -3684,6 +3688,8 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, in
}
int nType = pSprite->type - kDudeBase; int nDamageFactor = dudeInfo[nType].at70[damageType];
if (pSprite->type == kDudeModernCustom)
nDamageFactor = gGenDudeExtra[pSprite->index].dmgControl[damageType];
if (!nDamageFactor) return 0;
else if (nDamageFactor != 256)
@ -4493,7 +4499,7 @@ void ProcessTouchObjects(spritetype *pSprite, int nXSprite)
if ((nHWall = gSpriteHit[nXSprite].hit & 0x3fff) >= 0 && wall[nHWall].extra >= 0) {
XWALL* pXHWall = &xwall[wall[nHWall].extra];
if (pXHWall->triggerTouch && !pXHWall->isTriggered && (!pXHWall->dudeLockout || IsPlayerSprite(pSprite)))
trTriggerWall(nHWall, pXHWall, kCmdWallTouch);
trTriggerWall(nHWall, pXHWall, kCmdWallTouch, nSprite);
}
}
}
@ -4794,7 +4800,7 @@ void MoveDude(spritetype *pSprite)
if (pHitWall->extra > 0)
pHitXWall = &xwall[pHitWall->extra];
if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer)
trTriggerWall(nHitWall, pHitXWall, kCmdWallPush);
trTriggerWall(nHitWall, pHitXWall, kCmdWallPush, nSprite);
if (pHitWall->nextsector != -1)
{
sectortype *pHitSector = &sector[pHitWall->nextsector];
@ -4802,7 +4808,7 @@ void MoveDude(spritetype *pSprite)
if (pHitSector->extra > 0)
pHitXSector = &xsector[pHitSector->extra];
if (pDudeInfo->lockOut && pHitXSector && pHitXSector->Wallpush && !pHitXSector->Key && !pHitXSector->dudeLockout && !pHitXSector->state && !pHitXSector->busy && !pPlayer)
trTriggerSector(pHitWall->nextsector, pHitXSector, kCmdSectorPush);
trTriggerSector(pHitWall->nextsector, pHitXSector, kCmdSectorPush, nSprite);
if (top < pHitSector->ceilingz || bottom > pHitSector->floorz)
{
// ???
@ -4828,7 +4834,7 @@ void MoveDude(spritetype *pSprite)
else
pXSector = NULL;
if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout))
trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit);
trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit, nSprite);
ChangeSpriteSect(nSprite, nSector);
nXSector = sector[nSector].extra;
@ -4837,7 +4843,7 @@ void MoveDude(spritetype *pSprite)
if (sector[nSector].type == kSectorTeleport)
pXSector->data = pPlayer ? nSprite : -1;
trTriggerSector(nSector, pXSector, kCmdSectorEnter);
trTriggerSector(nSector, pXSector, kCmdSectorEnter, nSprite);
}
nSector = pSprite->sectnum;
@ -5340,7 +5346,7 @@ int MoveMissile(spritetype *pSprite)
XWALL *pXWall = &xwall[pWall->extra];
if (pXWall->triggerVector)
{
trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact);
trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact, nSprite);
if (!(pWall->cstat&64))
{
vdi = -1;
@ -5514,7 +5520,7 @@ void actExplodeSprite(spritetype *pSprite)
sfxPlay3DSound(pSprite, nSnd, -1, 0);
}
break;
case kThingPodGreenBall:
case kThingPodFireBall:
nType = 3;
seqSpawn(9, 3, nXSprite, -1);
sfxPlay3DSound(pSprite, 307, -1, 0);
@ -5890,7 +5896,7 @@ void actProcessSprites(void)
actDamageSprite(actSpriteOwnerToSpriteId(pSprite), pObject, DAMAGE_TYPE_0, 12);
}
break;
case kThingPodFireBall:
case kThingPodGreenBall:
if ((hit&0xc000) == 0x4000)
{
sub_2A620(actSpriteOwnerToSpriteId(pSprite), pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, DAMAGE_TYPE_3, 6, 0, 0, 0);
@ -5907,7 +5913,7 @@ void actProcessSprites(void)
evPost(pSprite->index, 3, 0, kCallbackFXPodBloodSplat);
}
break;
case kThingPodGreenBall:
case kThingPodFireBall:
{
int nObject = hit & 0x3fff;
if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096))
@ -5969,7 +5975,7 @@ void actProcessSprites(void)
if (nWall == -1)
break;
XWALL *pXWall = &xwall[wall[nWall].extra];
trTriggerWall(nWall, pXWall, kCmdWallImpact);
trTriggerWall(nWall, pXWall, kCmdWallImpact, nSprite);
}
for (int nSprite2 = headspritestat[kStatDude]; nSprite2 >= 0; nSprite2 = nextspritestat[nSprite2])
@ -6172,7 +6178,7 @@ void actProcessSprites(void)
pXSprite->burnSource = -1;
pXSprite->data1 = pXIncarnation->data1;
short oldData2 = pXSprite->data2; pXSprite->data2 = pXIncarnation->data2; // seq new seqId and save old one.
pXSprite->data2 = pXIncarnation->data2;
// if incarnation is active dude, it's sndStartId will be stored in sysData1, otherwise it will be data3
if (pIncarnation->statnum == kStatDude && pIncarnation->type == kDudeModernCustom) pXSprite->sysData1 = pXIncarnation->sysData1;
@ -6206,8 +6212,7 @@ void actProcessSprites(void)
case kDudeModernCustom:
case kDudeModernCustomBurning:
seqId = getSeqStartId(pXSprite);
if (seqId != oldData2)
getSpriteMassBySize(pSprite); // create or refresh mass cache
getSpriteMassBySize(pSprite); // create or refresh mass cache
fallthrough__; // go below
default:
seqSpawn(seqId, 3, nXSprite, -1);
@ -6946,7 +6951,7 @@ void actFireVector(spritetype *pShooter, int a2, int a3, int a4, int a5, int a6,
{
XWALL *pXWall = &xwall[nXWall];
if (pXWall->triggerVector)
trTriggerWall(nWall, pXWall, kCmdWallImpact);
trTriggerWall(nWall, pXWall, kCmdWallImpact, nShooter);
}
break;
}
@ -7553,7 +7558,6 @@ int getSpriteMassBySize(spritetype* pSprite) {
int mass = 0; int seqId = -1; Seq* pSeq = NULL;
if (IsDudeSprite(pSprite)) {
switch (pSprite->type) {
case kDudePodMother: // fake dude, no seq
break;
@ -7562,7 +7566,6 @@ int getSpriteMassBySize(spritetype* pSprite) {
seqId = xsprite[pSprite->extra].data2;
break;
default:
seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID;
break;
}
@ -7647,6 +7650,7 @@ int getSpriteMassBySize(spritetype* pSprite) {
cached->picnum = pSprite->picnum; cached->seqId = seqId;
cached->clipdist = pSprite->clipdist;
viewSetSystemMessage("MASS: %d", cached->mass);
return cached->mass;
}

View file

@ -288,6 +288,6 @@ extern short gPhysSpritesList[kMaxSuperXSprites];
extern short gProxySpritesCount;
extern short gSightSpritesCount;
extern short gPhysSpritesCount;
//extern short gQavPlayerIndex;
extern int DudeDifficulty[];
END_BLD_NS

View file

@ -65,6 +65,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "sfx.h"
#include "trig.h"
#include "triggers.h"
#include "view.h"
BEGIN_BLD_NS
@ -421,12 +422,12 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
else {
aiNewState(pSprite, pXSprite, &GDXGenDudeSearchL);
if (Chance(0x4000))
sfxPlayGDXGenDudeSound(pSprite, 0);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTargetSpot);
}
}
else {
if (Chance(0x4000))
sfxPlayGDXGenDudeSound(pSprite, 0);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTargetSpot);
if (spriteIsUnderwater(pSprite, false))
aiNewState(pSprite, pXSprite, &GDXGenDudeChaseW);
@ -1025,7 +1026,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
break;
case kDudeModernCustomBurning:
if (Chance(0x2000) && gDudeExtra[pSprite->extra].at0 < (int)gFrameClock) {
sfxPlayGDXGenDudeSound(pSprite, 3);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndBurning);
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
}
if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400;
@ -1058,7 +1059,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
&& gSysRes.Lookup(pXSprite->data2 + 3, "SEQ")) {
aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1);
sfxPlayGDXGenDudeSound(pSprite, 3);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndBurning);
pSprite->type = kDudeModernCustomBurning;
if (pXSprite->data2 == kDefaultAnimationBase) // don't inherit palette for burning if using default animation
@ -1083,7 +1084,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
else aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgD);
if (Chance(0x0200))
sfxPlayGDXGenDudeSound(pSprite, 1);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit);
}
else if (sub_5BDA8(pSprite, 13))
aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgW);
@ -1132,7 +1133,7 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
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, 1);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit);
if (gSysRes.Lookup(pXSprite->data2 + 4, "SEQ")) {
GDXGenDudeRTesla.at18 = (Chance(chance4 * 2) ? &GDXGenDudeDodgeL : &GDXGenDudeDodgeDmgL);
@ -1145,13 +1146,13 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
}
if (inDodge(pXSprite->aiState)) {
sfxPlayGDXGenDudeSound(pSprite, 1);
sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit);
break;
}
if (inIdle(pXSprite->aiState) || chance3 || Chance(getRecoilChance(pSprite)) || (!dudeIsMelee(pXSprite) && mass < 155)) {
sfxPlayGDXGenDudeSound(pSprite, 1);
sfxPlayGDXGenDudeSound(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);
@ -1454,32 +1455,43 @@ void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite)
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];
if (pSprite->flags&32)
continue;
if (pSprite->flags & 32) continue;
int nXSprite = pSprite->extra;
XSPRITE *pXSprite = &xsprite[nXSprite];
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue;
pXSprite->stateTimer = ClipLow(pXSprite->stateTimer-4, 0);
if (pXSprite->aiState->at10)
pXSprite->aiState->at10(pSprite, pXSprite);
if (pXSprite->aiState->at14 && (gFrame&3) == (nSprite&3))
pXSprite->aiState->at14(pSprite, pXSprite);
if (pXSprite->stateTimer == 0 && pXSprite->aiState->at18)
{
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]))
{
if (pXSprite->health > 0 && ((pDudeInfo->hinderDamage << 4) <= cumulDamage[nXSprite])) {
pXSprite->data3 = cumulDamage[nXSprite];
RecoilDude(pSprite, pXSprite);
}
if (pSprite->type >= kDudeVanillaMax) {
switch (pSprite->type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
GENDUDEEXTRA* pExtra = &gGenDudeExtra[pSprite->index];
if (pExtra->slaveCount > 0) updateTargetOfSlaves(pSprite);
if (pExtra->nLifeLeech >= 0) updateTargetOfLeech(pSprite);
break;
}
}
}
memset(cumulDamage, 0, sizeof(cumulDamage));
}
@ -1505,13 +1517,11 @@ void aiInitSprite(spritetype *pSprite)
pDudeExtra->at4 = 0;
pDudeExtra->at0 = 0;
switch (pSprite->type) {
case kDudeModernCustom:
{
case kDudeModernCustom: {
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1;
pDudeExtraE->at8 = 0;
pDudeExtraE->at0 = 0;
pDudeExtraE->at4 = 0;
pDudeExtraE->at8 = pDudeExtraE->at0 = 0;
aiNewState(pSprite, pXSprite, &GDXGenDudeIdleL);
genDudePrepare(pSprite);
break;
}
case kDudeModernCustomBurning:

View file

@ -103,6 +103,7 @@ void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite);
void aiProcessDudes(void);
void aiInit(void);
void aiInitSprite(spritetype *pSprite);
bool CanMove(spritetype* pSprite, int a2, int nAngle, int nRange);
// By NoOne: this function required for kModernDudeTargetChanger
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite);

View file

@ -181,7 +181,7 @@ static void ThrowSeqCallback(int, int nXSprite)
if (v4)
xsprite[pMissile->extra].Impact = 1;
else
evPost(pMissile->index, 3, 120*(1+Random(2)), kCmdOn);
evPost(pMissile->index, 3, 120*(1+Random(2)), kCmdOn, nSprite);
}
static void sub_68170(int, int nXSprite)
@ -194,7 +194,7 @@ static void sub_68170(int, int nXSprite)
nMissile = kThingArmedTNTBundle;
sfxPlay3DSound(pSprite, 455, -1, 0);
spritetype *pMissile = actFireThing(pSprite, 0, 0, gDudeSlope[nXSprite]-9460, nMissile, 0x133333);
evPost(pMissile->index, 3, 120*(2+Random(2)), kCmdOn);
evPost(pMissile->index, 3, 120*(2+Random(2)), kCmdOn, nSprite);
}
static void sub_68230(int, int nXSprite)

View file

@ -126,7 +126,7 @@ static void sub_6FFA0(int, int nXSprite)
sfxPlay3DSound(pSprite, 2474, -1, 0);
else
sfxPlay3DSound(pSprite, 2475, -1, 0);
pMissile = actFireThing(pSprite, 0, -8000, dz/128-14500, kThingPodFireBall, (nDist2<<23)/120);
pMissile = actFireThing(pSprite, 0, -8000, dz/128-14500, kThingPodGreenBall, (nDist2<<23)/120);
}
if (pMissile)
seqSpawn(68, 3, pMissile->extra, -1);
@ -136,7 +136,7 @@ static void sub_6FFA0(int, int nXSprite)
if (pDudeInfo->seeDist*0.1 < nDist)
{
sfxPlay3DSound(pSprite, 2454, -1, 0);
pMissile = actFireThing(pSprite, 0, -8000, dz/128-14500, kThingPodGreenBall, (nDist2<<23)/120);
pMissile = actFireThing(pSprite, 0, -8000, dz/128-14500, kThingPodFireBall, (nDist2<<23)/120);
}
if (pMissile)
seqSpawn(22, 3, pMissile->extra, -1);

File diff suppressed because it is too large Load diff

View file

@ -27,8 +27,37 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
#define kMaxGenDudeSndMode 11
#define kDefaultAnimationBase 11520
#define kGenDudeMaxSlaves 7
enum {
kGenDudeSndTargetSpot = 0,
kGenDudeSndGotHit = 1,
kGenDudeSndDeathNormal = 2,
kGenDudeSndBurning = 3,
kGenDudeSndDeathExplode = 4,
kGenDudeSndTargetDead = 5,
kGenDudeSndChasing = 6,
kGenDudeSndAttackNormal = 7,
kGenDudeSndAttackThrow = 8,
kGenDudeSndAttackMelee = 9,
kGenDudeSndTransforming = 10,
kGenDudeSndMax ,
};
enum {
kGenDudePropertyAll = 0,
kGenDudePropertyWeapon = 1,
kGenDudePropertyDamage = 2,
kGenDudePropertyMass = 3,
kGenDudePropertyAttack = 4,
kGenDudePropertyStates = 5,
kGenDudePropertyLeech = 6,
kGenDudePropertySlaves = 7,
kGenDudePropertyMelee = 8,
kGenDudePropertyClipdist = 9,
kGenDudePropertyMax ,
};
extern AISTATE GDXGenDudeIdleL;
@ -68,6 +97,28 @@ struct GENDUDESND
extern GENDUDESND gCustomDudeSnd[];
// temporary, until normal DUDEEXTRA gets refactored
struct GENDUDEEXTRA {
unsigned int fireDist; // counts from sprite size
unsigned int throwDist; // counts from sprite size
unsigned int frontSpeed;
unsigned short curWeapon; // data1 duplicate to avoid potential problems when changing data dynamically
unsigned short baseDispersion;
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;
bool updReq[kGenDudePropertyMax]; // update requests
bool isMelee;
bool canWalk;
bool canDuck;
bool canSwim;
bool canFly;
};
extern GENDUDEEXTRA gGenDudeExtra[];
XSPRITE* getNextIncarnation(XSPRITE* pXSprite);
void killDudeLeech(spritetype* pLeech);
void removeLeech(spritetype* pLeech, bool delSprite = true);
@ -76,6 +127,7 @@ spritetype* leechIsDropped(spritetype* pSprite);
bool spriteIsUnderwater(spritetype* pSprite, bool oldWay);
bool sfxPlayGDXGenDudeSound(spritetype* pSprite, int mode);
void aiGenDudeMoveForward(spritetype* pSprite, XSPRITE* pXSprite);
void aiGenDudeChooseDirection(spritetype* pSprite, XSPRITE* pXSprite, int a3, int aXvel = -1, int aYvel = -1);
int getGenDudeMoveSpeed(spritetype* pSprite, int which, bool mul, bool shift);
bool TargetNearThing(spritetype* pSprite, int thingType);
int checkAttackState(spritetype* pSprite, XSPRITE* pXSprite);
@ -85,11 +137,18 @@ int getDodgeChance(spritetype* pSprite);
int getRecoilChance(spritetype* pSprite);
bool dudeIsMelee(XSPRITE* pXSprite);
void updateTargetOfSlaves(spritetype* pSprite);
void updateTargetOfLeech(spritetype* pSprite);
bool canSwim(spritetype* pSprite);
bool canDuck(spritetype* pSprite);
bool CDCanMove(spritetype* pSprite);
bool canWalk(spritetype* pSprite);
bool inDodge(AISTATE* aiState);
bool inIdle(AISTATE* aiState);
int getSeqStartId(XSPRITE* pXSprite);
int getSeeDist(spritetype* pSprite, int startDist, int minDist, int maxDist);
int getRangeAttackDist(spritetype* pSprite, int minDist = 1200, int maxDist = 80000);
int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp);
void scaleDamage(XSPRITE* pXSprite);
void genDudePrepare(spritetype* pSprite, int propId = kGenDudePropertyAll);
void genDudeUpdate(spritetype* pSprite);
END_BLD_NS

View file

@ -358,7 +358,7 @@ void CounterCheck(int nSector) // 12
return;
} else {
//pXSector->waitTimeA = 0; //do not reset necessary objects counter to zero
trTriggerSector(nSector, pXSector, kCmdOn);
trTriggerSector(nSector, pXSector, kCmdOn, -1);
pXSector->locked = 1; //lock sector, so it can be opened again later
}
}
@ -539,9 +539,9 @@ void fxPodBloodSplat(int nSprite) // 19
sfxPlay3DSound(pSprite, 385, nChannel, 1);
}
spritetype *pFX = NULL;
if (pSprite->type == 53 || pSprite->type == kThingPodFireBall)
if (pSprite->type == 53 || pSprite->type == kThingPodGreenBall)
{
if (Chance(0x500) || pSprite->type == kThingPodFireBall)
if (Chance(0x500) || pSprite->type == kThingPodGreenBall)
pFX = gFX.fxSpawn(FX_55, pSprite->sectnum, x, y, floorZ-64, 0);
if (pFX)
pFX->ang = nAngle;

View file

@ -88,6 +88,15 @@ void _consoleSysMsg(const char* pMessage, ...);
#define kMaxPAL 5
#define kFreeQAVEntry 108
#define kDmgFall 0
#define kDmgBurn 1
#define kDmgBullet 2
#define kDmgExplode 3
#define kDmgChoke 4
#define kDmgSpirit 5
#define kDmgElectric 6
#define kDmgMax 7
// MEDIUM /////////////////////////////////////////////////////
enum {
kMediumNormal = 0,
@ -368,8 +377,8 @@ enum {
kThingBloodChunks = 426,
kThingZombieHead = 427,
kThingNapalmBall = 428,
kThingPodGreenBall = 429,
kThingPodFireBall = 430,
kThingPodFireBall = 429,
kThingPodGreenBall = 430,
kThingDroppedLifeLeech = 431,
kThingVoodooHead = 432, // unused
kModernThingTNTProx = 433, // gModernMap only - detects only players

View file

@ -696,13 +696,14 @@ const int nXSectorSize = 60;
const int nXSpriteSize = 56;
const int nXWallSize = 24;
int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC)
{
char name2[BMAX_PATH];
int16_t tpskyoff[256];
int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC) {
char name2[BMAX_PATH]; int16_t tpskyoff[256];
memset(show2dsector, 0, sizeof(show2dsector));
memset(show2dwall, 0, sizeof(show2dwall));
memset(show2dsprite, 0, sizeof(show2dsprite));
gModernMap = false;
#ifdef USE_OPENGL
Polymost_prepare_loadboard();
#endif
@ -747,7 +748,6 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
// for maps wich created in PMAPEDIT BETA13 or higher versions. Since only minor version changed,
// the map is still can be loaded with vanilla BLOOD / MAPEDIT and should work in other ports too.
if ((header.version & 0x00ff) == 0x001) gModernMap = true;
else gModernMap = false;
} else {
initprintf("Map file is wrong version");
@ -963,10 +963,6 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
xsector[sector[i].extra].reference = i;
xsector[sector[i].extra].busy = xsector[sector[i].extra].state<<16;
// by NoOne: indicate if the map requires modern features to work properly
// for maps wich created in different editors (include vanilla MAPEDIT) or in PMAPEDIT version below than BETA13
if (pXSector->rxID == kChannelMapExtended && pXSector->rxID == pXSector->txID && pXSector->command == kCmdModernFeaturesEnable)
gModernMap = true;
}
}
for (int i = 0; i < numwalls; i++)
@ -1042,10 +1038,6 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
xwall[wall[i].extra].reference = i;
xwall[wall[i].extra].busy = xwall[wall[i].extra].state << 16;
// by NoOne: indicate if the map requires modern features to work properly
// for maps wich created in different editors (include vanilla MAPEDIT) or in PMAPEDIT version below than BETA13
if (pXWall->rxID == kChannelMapExtended && pXWall->rxID == pXWall->txID && pXWall->command == kCmdModernFeaturesEnable)
gModernMap = true;
}
}
initspritelists();
@ -1168,7 +1160,7 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
// by NoOne: indicate if the map requires modern features to work properly
// for maps wich created in different editors (include vanilla MAPEDIT) or in PMAPEDIT version below than BETA13
if (pXSprite->rxID == kChannelMapExtended && pXSprite->rxID == pXSprite->txID && pXSprite->command == kCmdModernFeaturesEnable)
if (!gModernMap && pXSprite->rxID == kChannelMapModernize && pXSprite->rxID == pXSprite->txID && pXSprite->command == kCmdModernFeaturesEnable)
gModernMap = true;
}
if ((sprite[i].cstat & 0x30) == 0x30)

View file

@ -31,6 +31,19 @@ BEGIN_BLD_NS
// by NoOne additional non-thing proximity, sight and physics sprites
#define kMaxSuperXSprites 128
// by NoOne: functions to quckly check range of specifical arrays
inline bool xsprRangeIsFine(int nXindex) {
return (nXindex >= 0 && nXindex < kMaxXSprites);
}
inline bool xsectRangeIsFine(int nXindex) {
return (nXindex >= 0 && nXindex < kMaxXSectors);
}
inline bool xwallRangeIsFine(int nXindex) {
return (nXindex >= 0 && nXindex < kMaxXWalls);
}
extern bool gModernMap;
#pragma pack(push, 1)
@ -58,7 +71,7 @@ struct XSPRITE {
unsigned int respawnPending : 2; // respawnPending
signed int dropMsg : 8; // Drop Item
unsigned int dropMsg : 8; // Drop Item
unsigned int Decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1; // works in case if triggerOnce selected

View file

@ -1570,7 +1570,7 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
256, // angSpeed
// 0,
7, -1, 18, // nGibType
256, 256, 128, 256, 256, 256, 192,
128, 128, 128, 128, 128, 128, 128,
0, 0, 0, 0, 0, 0, 0,
0,
0

View file

@ -351,78 +351,94 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command, short causedBy)
EVENT event; event.index = nIndex; event.type = nType; event.cmd = command; event.causedBy = causedBy;
switch (command) {
case kCmdState:
command = evGetSourceState(nType, nIndex) ? kCmdOn : kCmdOff;
break;
case kCmdNotState:
command = evGetSourceState(nType, nIndex) ? kCmdOff : kCmdOn;
break;
case kCmdState:
command = evGetSourceState(nType, nIndex) ? kCmdOn : kCmdOff;
break;
case kCmdNotState:
command = evGetSourceState(nType, nIndex) ? kCmdOff : kCmdOn;
break;
}
switch (rxId) {
case kChannelTextOver:
if (command >= kCmdNumberic) trTextOver(command - kCmdNumberic);
else viewSetSystemMessage("Invalid TextOver command by xobject #%d (object type %d)", nIndex, nType);
return;
case kChannelLevelExitNormal:
levelEndLevel(0);
return;
case kChannelLevelExitSecret:
levelEndLevel(1);
return;
case kChannelTextOver:
if (command >= kCmdNumberic) trTextOver(command - kCmdNumberic);
else viewSetSystemMessage("Invalid TextOver command by xobject #%d (object type %d)", nIndex, nType);
return;
case kChannelLevelExitNormal:
levelEndLevel(0);
return;
case kChannelLevelExitSecret:
levelEndLevel(1);
return;
// By NoOne: finished level and load custom level ¹ via numbered command.
case kChannelModernEndLevelCustom:
if (command >= kCmdNumberic) levelEndLevelCustom(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Level-Exit# command by xobject #%d (object type %d)", nIndex, nType);
return;
case kChannelSetTotalSecrets:
if (command >= kCmdNumberic) levelSetupSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Total-Secrets command by xobject #%d (object type %d)", nIndex, nType);
break;
case kChannelSecretFound:
if (command >= kCmdNumberic) levelTriggerSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Trigger-Secret command by xobject #%d (object type %d)", nIndex, nType);
break;
case kChannelRemoteBomb0:
case kChannelRemoteBomb1:
case kChannelRemoteBomb2:
case kChannelRemoteBomb3:
case kChannelRemoteBomb4:
case kChannelRemoteBomb5:
case kChannelRemoteBomb6:
case kChannelRemoteBomb7:
for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite])
case kChannelModernEndLevelCustom:
if (command >= kCmdNumberic) levelEndLevelCustom(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Level-Exit# command by xobject #%d (object type %d)", nIndex, nType);
return;
case kChannelSetTotalSecrets:
if (command >= kCmdNumberic) levelSetupSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Total-Secrets command by xobject #%d (object type %d)", nIndex, nType);
break;
case kChannelSecretFound:
if (command >= kCmdNumberic) levelTriggerSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Trigger-Secret command by xobject #%d (object type %d)", nIndex, nType);
break;
case kChannelRemoteBomb0:
case kChannelRemoteBomb1:
case kChannelRemoteBomb2:
case kChannelRemoteBomb3:
case kChannelRemoteBomb4:
case kChannelRemoteBomb5:
case kChannelRemoteBomb6:
case kChannelRemoteBomb7:
for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
spritetype* pSprite = &sprite[nSprite];
if (pSprite->flags & 32)
continue;
int nXSprite = pSprite->extra;
if (nXSprite > 0)
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags&32)
continue;
int nXSprite = pSprite->extra;
if (nXSprite > 0)
{
XSPRITE *pXSprite = &xsprite[nXSprite];
if (pXSprite->rxID == rxId)
trMessageSprite(nSprite, event);
}
XSPRITE* pXSprite = &xsprite[nXSprite];
if (pXSprite->rxID == rxId)
trMessageSprite(nSprite, event);
}
return;
case kChannelTeamAFlagCaptured:
case kChannelTeamBFlagCaptured:
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite])
}
return;
case kChannelTeamAFlagCaptured:
case kChannelTeamBFlagCaptured:
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite])
{
spritetype* pSprite = &sprite[nSprite];
if (pSprite->flags & 32)
continue;
int nXSprite = pSprite->extra;
if (nXSprite > 0)
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags&32)
continue;
int nXSprite = pSprite->extra;
if (nXSprite > 0)
{
XSPRITE *pXSprite = &xsprite[nXSprite];
if (pXSprite->rxID == rxId)
trMessageSprite(nSprite, event);
}
XSPRITE* pXSprite = &xsprite[nXSprite];
if (pXSprite->rxID == rxId)
trMessageSprite(nSprite, event);
}
return;
default:
break;
}
return;
default:
break;
}
//by NoOne: allow to send commands on player sprites
if (gModernMap) {
PLAYER* pPlayer = NULL;
if (rxId >= kChannelPlayer0 && rxId <= kChannelPlayer7) {
if ((pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != NULL)
trMessageSprite(pPlayer->nSprite, event);
} else if (rxId == kChannelAllPlayers) {
for (int i = 0; i < kMaxPlayers; i++) {
if ((pPlayer = getPlayerById(i)) != NULL)
trMessageSprite(pPlayer->nSprite, event);
}
}
}
for (int i = bucketHead[rxId]; i < bucketHead[rxId+1]; i++) {

View file

@ -27,32 +27,47 @@ BEGIN_BLD_NS
enum {
kChannelZero = 0,
kChannelSetTotalSecrets,
kChannelSecretFound,
kChannelTextOver,
kChannelLevelExitNormal,
kChannelLevelExitSecret,
kChannelModernEndLevelCustom, // // custom level end
kChannelLevelStart,
kChannelLevelStartMatch, // DM and TEAMS
kChannelLevelStartCoop,
kChannelLevelStartTeamsOnly,
kChannelPlayerDeathTeamA = 15,
kChannelPlayerDeathTeamB,
kChannelMapExtended = 60, // map requires modern features to work properly
kChannelTeamAFlagCaptured = 80,
kChannelTeamBFlagCaptured,
kChannelRemoteBomb0 = 90,
kChannelRemoteBomb1,
kChannelRemoteBomb2,
kChannelRemoteBomb3,
kChannelRemoteBomb4,
kChannelRemoteBomb5,
kChannelRemoteBomb6,
kChannelRemoteBomb7,
kChannelUser = 100,
kChannelMax = 4096,
kChannelZero = 0,
kChannelSetTotalSecrets,
kChannelSecretFound,
kChannelTextOver,
kChannelLevelExitNormal,
kChannelLevelExitSecret,
kChannelModernEndLevelCustom, // custom level end
kChannelLevelStart,
kChannelLevelStartMatch, // DM and TEAMS
kChannelLevelStartCoop,
kChannelLevelStartTeamsOnly,
kChannelPlayerDeathTeamA = 15,
kChannelPlayerDeathTeamB,
// by NoOne: RX channels of players to send commands on
/////////////////////////////
kChannelPlayer0 = 30,
kChannelPlayer1,
kChannelPlayer2,
kChannelPlayer3,
kChannelPlayer4,
kChannelPlayer5,
kChannelPlayer6,
kChannelPlayer7,
kChannelAllPlayers = kChannelPlayer0 + kMaxPlayers,
/////////////////////////////
kChannelMapModernize = 60, // map requires modern features to work properly
kChannelTeamAFlagCaptured = 80,
kChannelTeamBFlagCaptured,
kChannelRemoteBomb0 = 90,
kChannelRemoteBomb1,
kChannelRemoteBomb2,
kChannelRemoteBomb3,
kChannelRemoteBomb4,
kChannelRemoteBomb5,
kChannelRemoteBomb6,
kChannelRemoteBomb7,
kChannelUser = 100,
kChannelMax = 4096,
};
struct RXBUCKET
@ -99,11 +114,15 @@ enum COMMAND_ID {
kCmdModernUse = 53, // used by most of modern types
kCmdNumberic = 64, // 64: 0, 65: 1 and so on up to 255
kCmdModernFeaturesEnable = 100, // must be in object with kChannelMapExtended RX / TX
kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapExtended RX / TX
kCmdModernFeaturesEnable = 100, // must be in object with kChannelMapModernize RX / TX
kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapModernize RX / TX
kCmdNumbericMax = 255,
};
inline bool playerRXRngIsFine(int rx) {
return (rx >= kChannelPlayer0 && rx < kChannelPlayer7);
}
struct EVENT {
unsigned int index: 14; // index
unsigned int type: 3; // type
@ -114,8 +133,8 @@ struct EVENT {
void evInit(void);
char evGetSourceState(int nType, int nIndex);
void evSend(int nIndex, int nType, int rxId, COMMAND_ID command, short causedBy = -1);
void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command, short causedBy = -1);
void evSend(int nIndex, int nType, int rxId, COMMAND_ID command, short causedBy);
void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command, short causedBy);
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback, short causedBy = -1);
void evProcess(unsigned int nTime);
void evKill(int a1, int a2);

View file

@ -50,6 +50,21 @@ enum {
PARALLAXCLIP_FLOOR = 2,
};
// by NoOne: functions to quckly check range of specifical arrays
inline bool spriRangeIsFine(int nIndex) {
return (nIndex >= 0 && nIndex < kMaxSprites);
}
inline bool sectRangeIsFine(int nIndex) {
return (nIndex >= 0 && nIndex < kMaxSectors);
}
inline bool wallRangeIsFine(int nIndex) {
return (nIndex >= 0 && nIndex < kMaxWalls);
}
///
bool AreSectorsNeighbors(int sect1, int sect2);
bool FindSector(int nX, int nY, int nZ, int *nSector);
bool FindSector(int nX, int nY, int *nSector);

View file

@ -315,6 +315,7 @@ void MyLoadSave::Load(void)
Read(&gMapRev, sizeof(gMapRev));
Read(&gSongId, sizeof(gSkyCount));
Read(&gFogMode, sizeof(gFogMode));
Read(&gModernMap, sizeof(gModernMap));
#ifdef YAX_ENABLE
Read(&numyaxbunches, sizeof(numyaxbunches));
#endif
@ -420,6 +421,7 @@ void MyLoadSave::Save(void)
Write(&gMapRev, sizeof(gMapRev));
Write(&gSongId, sizeof(gSkyCount));
Write(&gFogMode, sizeof(gFogMode));
Write(&gModernMap, sizeof(gModernMap));
#ifdef YAX_ENABLE
Write(&numyaxbunches, sizeof(numyaxbunches));
#endif

View file

@ -126,13 +126,26 @@ int Handicap[] = {
int gDefaultAccel[] = {
// normal human
0x4000, 0x1200, 0x2000, // stand (front, side, back) / crouch (front, side, back) / swim (front, side, back)
0x4000, 0x1200, 0x2000, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// normal beast
0x4000, 0x1200, 0x2000, // stand (front, side, back) / crouch (front, side, back) / swim (front, side, back)
0x4000, 0x1200, 0x2000, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// shrink human
10384, 2108, 2192, // stand (front, side, back) / crouch (front, side, back) / swim (front, side, back)
10384, 2108, 2192, // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
// grown human
19384, 5608, 11192 // stand (front, side, back) / crouch (front, side, back) / swim (front, side, back)
19384, 5608, 11192 // stand (front, side, back) / swim (front, side, back) / crouch (front, side, back)
};
int gDefaultJumpZ[] = {
// normal human
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// normal beast
-0xbaaaa, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// shrink human
-200000, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
// grown human
-250000, -0x175555, 0x5b05, 0, 0, 0 // stand (normal jump, pwup jump) / swim (normal jump, pwup jump) / crouch (normal jump, pwup jump)
};
@ -154,7 +167,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
0x1600,
0x1200,
0xc00,
0x90
0x90,
gDefaultJumpZ[0],
gDefaultJumpZ[1],
},
{
gDefaultAccel[1],
@ -169,7 +184,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
0x1400,
0x1000,
-0x600,
0xb0
0xb0,
gDefaultJumpZ[2],
gDefaultJumpZ[3],
},
{
gDefaultAccel[2],
@ -184,7 +201,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
0x800,
0x600,
-0x600,
0xb0
0xb0,
gDefaultJumpZ[4],
gDefaultJumpZ[5],
},
},
@ -203,7 +222,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
0x1600,
0x1200,
0xc00,
0x90
0x90,
gDefaultJumpZ[6],
gDefaultJumpZ[7],
},
{
gDefaultAccel[4],
@ -218,7 +239,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
0x1400,
0x1000,
-0x600,
0xb0
0xb0,
gDefaultJumpZ[8],
gDefaultJumpZ[9],
},
{
gDefaultAccel[5],
@ -233,7 +256,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
0x800,
0x600,
-0x600,
0xb0
0xb0,
gDefaultJumpZ[10],
gDefaultJumpZ[11],
},
},
@ -252,7 +277,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
5632,
4608,
3072,
144
144,
gDefaultJumpZ[12],
gDefaultJumpZ[13],
},
{
gDefaultAccel[7],
@ -267,7 +294,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
5120,
4096,
-1536,
176
176,
gDefaultJumpZ[14],
gDefaultJumpZ[15],
},
{
gDefaultAccel[8],
@ -282,7 +311,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
2048,
1536,
-1536,
176
176,
gDefaultJumpZ[16],
gDefaultJumpZ[17],
},
},
@ -301,7 +332,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
5632,
4608,
3072,
144
144,
gDefaultJumpZ[18],
gDefaultJumpZ[19],
},
{
gDefaultAccel[10],
@ -316,7 +349,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
5120,
4096,
-1536,
176
176,
gDefaultJumpZ[20],
gDefaultJumpZ[21],
},
{
gDefaultAccel[11],
@ -331,7 +366,9 @@ POSTURE gPosture[kModeMax][kPostureMax] = {
2048,
1536,
-1536,
176
176,
gDefaultJumpZ[22],
gDefaultJumpZ[23],
},
},
};
@ -435,27 +472,48 @@ DAMAGEINFO damageInfo[7] = {
{ 0, 0, 0, 0, 0, 0, 0 }
};
TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
QAVSCENE gQavScene[kMaxPlayers];
QAV* qavSceneLoad(int qavId) {
QAV* pQav = NULL; DICTNODE* hQav = gSysRes.Lookup(qavId, "QAV");
void playQavScene(PLAYER* pPlayer) {
dassert(pPlayer != NULL);
if (pPlayer->weaponQav == -1)
return;
QAV * pQAV = gQavScene[pPlayer->nPlayer].qavId;
pQAV->nSprite = pPlayer->pSprite->index;
int nTicks = pQAV->at10 - pPlayer->weaponTimer;
pQAV->Play(nTicks - 4, nTicks, pPlayer->qavCallback, pPlayer);
if (hQav) pQav = (QAV*)gSysRes.Lock(hQav);
else viewSetSystemMessage("Failed to load QAV animation #%d", qavId);
return pQav;
}
void startQavScene(PLAYER * pPlayer, int qavId, int a3, char a4) {
pPlayer->weaponQav = qavId;
pPlayer->weaponTimer = gQavScene[pPlayer->nPlayer].qavId->at10;
pPlayer->qavCallback = a3;
pPlayer->qavLoop = a4;
gQavScene[pPlayer->nPlayer].qavId->Preload();
playQavScene(pPlayer);
pPlayer->weaponTimer -= 4;
void qavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5) {
if (pPlayer == NULL || pPlayer->sceneQav == -1) return;
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
if (pQavScene->qavResrc != NULL) {
QAV* pQAV = pQavScene->qavResrc;
int v4 = (pPlayer->weaponTimer == 0) ? (int)totalclock % pQAV->at10 : pQAV->at10 - pPlayer->weaponTimer;
pQAV->x = a3; pQAV->y = a4; int flags = 2;
int nInv = powerupCheck(pPlayer, kPwUpShadowCloak);
if (nInv >= 120 * 8 || (nInv != 0 && ((int)totalclock & 32))) {
a2 = -128;
flags |= 1;
}
pQAV->Draw(v4, flags, a2, a5);
}
}
void qavScenePlay(PLAYER* pPlayer) {
if (pPlayer == NULL || pPlayer->sceneQav == -1) return;
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
if (pQavScene->qavResrc != NULL) {
QAV* pQAV = pQavScene->qavResrc;
pQAV->nSprite = pPlayer->pSprite->index;
int nTicks = pQAV->at10 - pPlayer->weaponTimer;
pQAV->Play(nTicks - 4, nTicks, pPlayer->qavCallback, pPlayer);
}
}
int powerupCheck(PLAYER *pPlayer, int nPowerUp)
@ -489,7 +547,6 @@ bool shrinkPlayerSize(PLAYER* pPlayer, int divider) {
bool growPlayerSize(PLAYER* pPlayer, int multiplier) {
pPlayer->pXSprite->scale = 256*multiplier;
playerSetRace(pPlayer, kModeHumanGrown);
viewSetSystemMessage("%d", pPlayer->pXSprite->scale);
return true;
}
@ -514,9 +571,10 @@ PLAYER* getPlayerById(short id) {
if (id < kMaxPlayers && id == i + 1) return &gPlayer[i]; // relative to connected players
else if (id >= kDudePlayer1 && id <= kDudePlayer8 && id == gPlayer[i].pSprite->type) // absolute type
return &gPlayer[i];
}
if (id >= kDudePlayer1 && id <= kDudePlayer8) viewSetSystemMessage("There is no player #%d", (kDudePlayer8 - id) + kMaxPlayers);
else viewSetSystemMessage("There is no player #%d", id);
}
return NULL;
}
@ -899,19 +957,13 @@ void playerStart(int nPlayer)
GINPUT* pInput = &pPlayer->input;
ZONE* pStartZone = NULL;
// reset qav player index
if (gModernMap) {
gQavScene[pPlayer->nPlayer].index = -1;
gQavScene[pPlayer->nPlayer].qavId = NULL;
}
// normal start position
if (gGameOptions.nGameType <= 1)
pStartZone = &gStartZone[nPlayer];
// By NoOne: let's check if there is positions of teams is specified
// if no, pick position randomly, just like it works in vanilla.
else if (gGameOptions.nGameType == 3 && gTeamsSpawnUsed == true) {
else if (gModernMap && gGameOptions.nGameType == 3 && gTeamsSpawnUsed == true) {
int maxRetries = 5;
while (maxRetries-- > 0) {
if (pPlayer->teamId == 0) pStartZone = &gStartZoneTeam1[Random(3)];
@ -1077,15 +1129,39 @@ void playerReset(PLAYER *pPlayer)
pPlayer->weaponQav = -1;
pPlayer->qavLoop = 0;
pPlayer->packItemId = -1;
for (int i = 0; i < 5; i++)
{
for (int i = 0; i < 5; i++) {
pPlayer->packSlots[i].isActive = 0;
pPlayer->packSlots[i].curAmount = 0;
}
for (int i = 0; i < 4; i++) {
for (int a = 0; a < 3; a++)
gPosture[i][a].frontAccel = gPosture[i][a].sideAccel = gPosture[i][a].backAccel = gDefaultAccel[a];
/////////////////
// reset qav scene
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
pQavScene->index = pQavScene->causedBy = pPlayer->sceneQav = -1;
pQavScene->qavResrc = NULL;
// restore default movement speed
playerResetMoveSpeed(pPlayer);
// restore default jump height
playerResetJumpHeight(pPlayer);
/////////////////
}
void playerResetMoveSpeed(PLAYER* pPlayer) {
for (int i = 0, k = 0; i < 4; i++) {
for (int a = 0; a < 3; a++, k++)
gPosture[i][a].frontAccel = gPosture[i][a].sideAccel = gPosture[i][a].backAccel = gDefaultAccel[k];
}
}
void playerResetJumpHeight(PLAYER* pPlayer) {
for (int i = 0, k = 0; i < 4; i++) {
for (int a = 0; a < 3; a++) {
gPosture[i][a].normalJumpZ = gDefaultJumpZ[k++];
gPosture[i][a].pwupJumpZ = gDefaultJumpZ[k++];
}
}
}
@ -1178,7 +1254,7 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) {
pPlayer->used2[1] = -1;
dword_21EFB0[pPlayer->teamId] += 10;
dword_21EFD0[pPlayer->teamId] += 240;
evSend(0, 0, 81, kCmdOn);
evSend(0, 0, 81, kCmdOn, pPlayer->nSprite);
sprintf(buffer, "%s captured Red Flag!", gProfile[pPlayer->nPlayer].name);
sndStartSample(8001, 255, 2, 0);
viewSetMessage(buffer);
@ -1222,7 +1298,7 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) {
pPlayer->used2[0] = -1;
dword_21EFB0[pPlayer->teamId] += 10;
dword_21EFD0[pPlayer->teamId] += 240;
evSend(0, 0, 80, kCmdOn);
evSend(0, 0, 80, kCmdOn, pPlayer->nSprite);
sprintf(buffer, "%s captured Blue Flag!", gProfile[pPlayer->nPlayer].name);
sndStartSample(8000, 255, 2, 0);
viewSetMessage(buffer);
@ -1383,7 +1459,7 @@ void PickUp(PLAYER *pPlayer, spritetype *pSprite)
if (nType >= kItemBase && nType <= kItemMax) {
pickedUp = PickupItem(pPlayer, pSprite);
if (pickedUp && customMsg == -1) sprintf(buffer, "Picked up %s", gItemText[nType - 100]);
if (pickedUp && customMsg == -1) sprintf(buffer, "Picked up %s", gItemText[nType - kItemBase]);
} else if (nType >= kItemAmmoBase && nType < kItemAmmoMax) {
pickedUp = PickupAmmo(pPlayer, pSprite);
@ -1658,30 +1734,26 @@ void ProcessInput(PLAYER *pPlayer)
if (!pInput->buttonFlags.jump)
pPlayer->cantJump = 0;
switch (pPlayer->posture)
{
switch (pPlayer->posture) {
case 1:
if (pInput->buttonFlags.jump)
zvel[nSprite] -= 0x5b05;
zvel[nSprite] -= pPosture->normalJumpZ;//0x5b05;
if (pInput->buttonFlags.crouch)
zvel[nSprite] += 0x5b05;
zvel[nSprite] += pPosture->normalJumpZ;//0x5b05;
break;
case 2:
if (!pInput->buttonFlags.crouch)
pPlayer->posture = 0;
break;
default:
if (!pPlayer->cantJump && pInput->buttonFlags.jump && pXSprite->height == 0)
{
if (!pPlayer->cantJump && pInput->buttonFlags.jump && pXSprite->height == 0) {
sfxPlay3DSound(pSprite, 700, 0, 0);
if (packItemActive(pPlayer, 4))
zvel[nSprite] = -0x175555;
else
zvel[nSprite] = -0xbaaaa;
if (packItemActive(pPlayer, 4)) zvel[nSprite] = pPosture->pwupJumpZ;// -0x175555;
else zvel[nSprite] = pPosture->normalJumpZ;//-0xbaaaa;
if (isShrinked(pPlayer->pSprite)) zvel[nSprite] -= -200000;
else if (isGrown(pPlayer->pSprite)) zvel[nSprite] += -250000;
if (isShrinked(pPlayer->pSprite)) zvel[nSprite] -= gPosture[kModeHumanShrink][pPlayer->posture].normalJumpZ;//-200000;
else if (isGrown(pPlayer->pSprite)) zvel[nSprite] += gPosture[kModeHumanGrown][pPlayer->posture].normalJumpZ; //-250000;
pPlayer->cantJump = 1;
}
@ -1708,7 +1780,7 @@ void ProcessInput(PLAYER *pPlayer)
sndStartSample(3062, 255, 2, 0);
}
if (!key || pPlayer->hasKey[key])
trTriggerSector(a2, pXSector, kCmdSpritePush);
trTriggerSector(a2, pXSector, kCmdSpritePush, nSprite);
else if (pPlayer == gMe)
{
viewSetMessage("That requires a key.");
@ -1726,7 +1798,7 @@ void ProcessInput(PLAYER *pPlayer)
sndStartSample(3062, 255, 2, 0);
}
if (!key || pPlayer->hasKey[key])
trTriggerWall(a2, pXWall, kCmdWallPush);
trTriggerWall(a2, pXWall, kCmdWallPush, pPlayer->nSprite);
else if (pPlayer == gMe)
{
viewSetMessage("That requires a key.");
@ -2106,23 +2178,23 @@ void FragPlayer(PLAYER *pPlayer, int nSprite)
pSprite = &sprite[nSprite];
if (pSprite && IsPlayerSprite(pSprite))
{
PLAYER *pKiller = &gPlayer[pSprite->type-kDudePlayer1];
PLAYER *pKiller = &gPlayer[pSprite->type - kDudePlayer1];
playerFrag(pKiller, pPlayer);
int nTeam1 = pKiller->teamId&1;
int nTeam2 = pPlayer->teamId&1;
if (nTeam1 == 0)
{
if (nTeam1 != nTeam2)
evSend(0, 0, 15, kCmdToggle);
evSend(0, 0, 15, kCmdToggle, pKiller->nSprite);
else
evSend(0, 0, 16, kCmdToggle);
evSend(0, 0, 16, kCmdToggle, pKiller->nSprite);
}
else
{
if (nTeam1 == nTeam2)
evSend(0, 0, 16, kCmdToggle);
evSend(0, 0, 16, kCmdToggle, pKiller->nSprite);
else
evSend(0, 0, 15, kCmdToggle);
evSend(0, 0, 15, kCmdToggle, pKiller->nSprite);
}
}
}
@ -2304,7 +2376,7 @@ int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, in
{
powerupClear(pPlayer);
if (nXSector > 0 && xsector[nXSector].Exit)
trTriggerSector(pSprite->sectnum, &xsector[nXSector], kCmdSectorExit);
trTriggerSector(pSprite->sectnum, &xsector[nXSector], kCmdSectorExit, nSprite);
pSprite->flags |= 7;
for (int p = connecthead; p >= 0; p = connectpoint2[p])
{
@ -2427,15 +2499,43 @@ public:
void PlayerLoadSave::Load(void)
{
const char buffer[2048] = "";
Read(dword_21EFB0, sizeof(dword_21EFB0));
Read(&gNetPlayers, sizeof(gNetPlayers));
Read(&gProfile, sizeof(gProfile));
Read(&gPlayer, sizeof(gPlayer));
for (int i = 0; i < gNetPlayers; i++)
{
Read((void*)&buffer, sizeof(kPlayerCtrlSigStart));
Read(&gPlayerCtrl, sizeof(gPlayerCtrl));
Read((void*)&buffer, sizeof(kPlayerCtrlSigEnd));
for (int i = 0; i < gNetPlayers; i++) {
gPlayer[i].pSprite = &sprite[gPlayer[i].nSprite];
gPlayer[i].pXSprite = &xsprite[gPlayer[i].pSprite->extra];
gPlayer[i].pDudeInfo = &dudeInfo[gPlayer[i].pSprite->type-kDudeBase];
// by NoOne: load qav scene
if (gPlayer[i].sceneQav != -1) {
if (gPlayerCtrl[i].qavScene.qavResrc == NULL)
gPlayer[i].sceneQav = -1;
else {
QAV* pQav = qavSceneLoad(gPlayer[i].sceneQav);
if (pQav) {
gPlayerCtrl[i].qavScene.qavResrc = pQav;
gPlayerCtrl[i].qavScene.qavResrc->Preload();
} else {
gPlayer[i].sceneQav = -1;
}
}
}
// by NoOne: load posture info
/*for (int a = 0; a < kModeMax; a++) {
for (int b = 0; b < kPostureMax; b++) {
gPosture[a][b] = gPlayerCtrl[i].posture[a][b];
}
}*/
}
}
@ -2445,6 +2545,20 @@ void PlayerLoadSave::Save(void)
Write(&gNetPlayers, sizeof(gNetPlayers));
Write(&gProfile, sizeof(gProfile));
Write(&gPlayer, sizeof(gPlayer));
////// by NoOne: copy posture to TRPLAYERCTRL before saving the game
/*for (int i = 0; i < gNetPlayers; i++) {
for (int a = 0; a < kModeMax; a++) {
for (int b = 0; b < kPostureMax; b++) {
gPlayerCtrl[i].posture[a][b] = gPosture[a][b];
}
}
}*/
Write((void*)kPlayerCtrlSigStart, sizeof(kPlayerCtrlSigStart));
Write(&gPlayerCtrl, sizeof(gPlayerCtrl));
Write((void*)kPlayerCtrlSigEnd, sizeof(kPlayerCtrlSigEnd));
//////
}
static PlayerLoadSave *myLoadSave;

View file

@ -77,7 +77,7 @@ struct PLAYER {
int qavCallback;
bool isRunning;
int posture; // stand, crouch, swim
int unused1; // --> useless
int sceneQav; // by NoOne: used to keep qav id
int bobPhase;
int bobAmp;
int bobHeight;
@ -174,6 +174,10 @@ struct PLAYER {
// by NoOne: defaut player movement speeds of all move states for gPosture
extern int gDefaultAccel[12];
// by NoOne: defaut player jump heights of all move states for gPosture
extern int gDefaultJumpZ[24];
struct POSTURE {
int frontAccel;
int sideAccel;
@ -187,6 +191,8 @@ struct POSTURE {
int weaponAboveZ;
int xOffset;
int zOffset;
int normalJumpZ;
int pwupJumpZ;
};
extern POSTURE gPosture[kModeMax][kPostureMax];
@ -210,12 +216,19 @@ struct POWERUPINFO {
int maxTime;
};
// by NoOne: this one stores qavs anims that can be played by trigger
struct QAVSCENE {
short index = -1;
QAV* qavId = NULL;
short index = -1; // index of sprite which triggered qav scene
QAV* qavResrc = NULL;
short causedBy = -1;
};
extern QAVSCENE gQavScene[kMaxPlayers];
// by NoOne: this one for controlling the player using triggers (movement speed, jumps and other stuff)
struct TRPLAYERCTRL {
QAVSCENE qavScene;
};
extern TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
extern PLAYER gPlayer[kMaxPlayers];
extern PLAYER *gMe, *gView;
@ -310,7 +323,10 @@ bool growPlayerSize(PLAYER* pPlayer, int multiplier);
bool resetPlayerSize(PLAYER* pPlayer);
void deactivateSizeShrooms(PLAYER* pPlayer);
PLAYER* getPlayerById(short id);
void startQavScene(PLAYER* pPlayer, int qavId, int a3, char a4);
void playQavScene(PLAYER* pPlayer);
QAV* qavSceneLoad(int qavId);
void qavScenePlay(PLAYER* pPlayer);
void qavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5);
void playerResetMoveSpeed(PLAYER* pPlayer);
void playerResetJumpHeight(PLAYER* pPlayer);
END_BLD_NS

View file

@ -113,12 +113,12 @@ void UpdateSprite(int nXSprite, SEQFRAME *pFrame)
int scale = xsprite[nXSprite].scale; // SEQ size scaling
if (pFrame->at2_0) {
if (scale) pSprite->xrepeat = mulscale8(pFrame->at2_0, scale);
if (scale) pSprite->xrepeat = ClipRange(mulscale8(pFrame->at2_0, scale), 0, 255);
else pSprite->xrepeat = pFrame->at2_0;
}
if (pFrame->at3_0) {
if (scale) pSprite->yrepeat = mulscale8(pFrame->at3_0, scale);
if (scale) pSprite->yrepeat = ClipRange(mulscale8(pFrame->at3_0, scale), 0, 255);
else pSprite->yrepeat = pFrame->at3_0;
}

View file

@ -70,11 +70,11 @@ struct ACTIVE
struct SEQINST
{
DICTNODE *hSeq;
Seq *pSequence; // mass
Seq *pSequence;
int at8;
int atc;
short at10;
unsigned char frameIndex; // at12
unsigned char frameIndex;
char at13;
void Update(ACTIVE *pActive);
};

File diff suppressed because it is too large Load diff

View file

@ -29,13 +29,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "db.h"
#include "eventq.h"
#include "dude.h"
#include "player.h"
BEGIN_BLD_NS
void trTriggerSector(unsigned int nSector, XSECTOR *pXSector, int command);
#define kPlayerCtrlSigStart "<<<<TRPLAYERCTRL{" // save game TRPLAYERCTRL block start
#define kPlayerCtrlSigEnd "}TRPLAYERCTRL>>>>" // save game TRPLAYERCTRL block end
void trTriggerSector(unsigned int nSector, XSECTOR *pXSector, int command, short causedBy);
void trMessageSector(unsigned int nSector, EVENT event);
void trTriggerWall(unsigned int nWall, XWALL *pXWall, int command);
void trTriggerWall(unsigned int nWall, XWALL *pXWall, int command, short causedBy);
void trMessageWall(unsigned int nWall, EVENT event);
void trTriggerSprite(unsigned int nSprite, XSPRITE *pXSprite, int command, int causedBy);
void trTriggerSprite(unsigned int nSprite, XSPRITE *pXSprite, int command, short causedBy);
void trMessageSprite(unsigned int nSprite, EVENT event);
void trProcessBusy(void);
void trInit(void);
@ -65,7 +69,7 @@ void freeTargets(int nSprite);
void freeAllTargets(XSPRITE* pXSource);
bool affectedByTargetChg(XSPRITE* pXDude);
int getDataFieldOfObject(int objType, int objIndex, int dataIndex);
bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value);
bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value, int causedBy);
bool goalValueIsReached(XSPRITE* pXSprite);
bool getDudesForTargetChg(XSPRITE* pXSprite);
void stopWindOnSectors(XSPRITE* pXSource);
@ -75,8 +79,13 @@ void useSeqSpawnerGen(XSPRITE* pXSource, int objType, int index);
void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite);
void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite);
void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex);
void useObjResizer(XSPRITE* pXSource, short objType, int objIndex);
void TeleFrag(int nKiller, int nSector);
bool valueIsBetween(int val, int min, int max);
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, int causedBy);
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer);
// -------------------------------------------------------
END_BLD_NS

View file

@ -387,21 +387,22 @@ void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput)
{
case 1:
if (predict.at71)
predict.at64 -= 0x5b05;
predict.at64 -= pPosture->normalJumpZ;//0x5b05;
if (pInput->buttonFlags.crouch)
predict.at64 += 0x5b05;
predict.at64 += pPosture->normalJumpZ;//0x5b05;
break;
case 2:
if (!pInput->buttonFlags.crouch)
predict.at48 = 0;
break;
default:
if (!predict.at6f && predict.at71 && predict.at6a == 0)
{
if (packItemActive(pPlayer, 4))
predict.at64 = -0x175555;
else
predict.at64 = -0xbaaaa;
if (!predict.at6f && predict.at71 && predict.at6a == 0) {
if (packItemActive(pPlayer, 4)) predict.at64 = pPosture->pwupJumpZ;//-0x175555;
else predict.at64 = pPosture->normalJumpZ;//-0xbaaaa;
if (isShrinked(pPlayer->pSprite)) zvel[pPlayer->nSprite] -= gPosture[kModeHumanShrink][pPlayer->posture].normalJumpZ;//-200000;
else if (isGrown(pPlayer->pSprite)) zvel[pPlayer->nSprite] += gPosture[kModeHumanGrown][pPlayer->posture].normalJumpZ; //-250000;
predict.at6f = 1;
}
if (pInput->buttonFlags.crouch)
@ -3458,18 +3459,22 @@ RORHACK:
}
cX = (v4c>>8)+160;
cY = (v48>>8)+220+(zDelta>>7);
int nShade = sector[nSectnum].floorshade;
int nPalette = 0;
if (sector[gView->pSprite->sectnum].extra > 0)
{
int nShade = sector[nSectnum].floorshade; int nPalette = 0;
if (sector[gView->pSprite->sectnum].extra > 0) {
sectortype *pSector = &sector[gView->pSprite->sectnum];
XSECTOR *pXSector = &xsector[pSector->extra];
if (pXSector->color)
{
nPalette = pSector->floorpal;
}
}
WeaponDraw(gView, nShade, cX, cY, nPalette);
if (gView->sceneQav < 0) WeaponDraw(gView, nShade, cX, cY, nPalette);
else if (gView->pXSprite->health > 0) qavSceneDraw(gView, nShade, cX, cY, nPalette);
else {
gView->sceneQav = gView->weaponQav = -1;
gView->weaponTimer = gView->curWeapon = 0;
}
}
if (gViewPos == 0 && gView->pXSprite->burnTime > 60)
{

View file

@ -48,7 +48,7 @@ void warpInit(void)
gUpperLink[i] = -1;
gLowerLink[i] = -1;
}
int team1 = 0; int team2 = 0; // increment if team start positions specified.
int team1 = 0; int team2 = 0; gTeamsSpawnUsed = false; // increment if team start positions specified.
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
{
if (sprite[nSprite].statnum < kMaxStatus) {
@ -134,11 +134,14 @@ void warpInit(void)
}
}
}
// check if there is enough start positions for teams, if any used
if (team1 > 0 || team2 > 0) {
gTeamsSpawnUsed = true;
//if (team1 < kMaxPlayers / 2 || team2 < kMaxPlayers / 2)
//_ShowMessageWindow("At least 4 spawn positions for each team is recommended.");
if (team1 < kMaxPlayers / 2 || team2 < kMaxPlayers / 2) {
viewSetSystemMessage("At least 4 spawn positions for each team is recommended.");
viewSetSystemMessage("Team A positions: %d, Team B positions: %d.", team1, team2);
}
}
for (int i = 0; i < kMaxSectors; i++)

View file

@ -233,17 +233,17 @@ void WeaponDraw(PLAYER *pPlayer, int a2, int a3, int a4, int a5)
dassert(pPlayer != NULL);
if (pPlayer->weaponQav == -1)
return;
QAV *pQAV = weaponQAV[pPlayer->weaponQav];
QAV * pQAV = weaponQAV[pPlayer->weaponQav];
int v4;
if (pPlayer->weaponTimer == 0)
v4 = (int)totalclock%pQAV->at10;
v4 = (int)totalclock % pQAV->at10;
else
v4 = pQAV->at10-pPlayer->weaponTimer;
v4 = pQAV->at10 - pPlayer->weaponTimer;
pQAV->x = a3;
pQAV->y = a4;
int flags = 2;
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;
flags |= 1;
@ -996,7 +996,7 @@ void ThrowCan(int, PLAYER *pPlayer)
if (pSprite)
{
sfxPlay3DSound(pSprite, 441, 0, 0);
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn);
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn, pPlayer->nSprite);
int nXSprite = pSprite->extra;
XSPRITE *pXSprite = &xsprite[nXSprite];
pXSprite->Impact = 1;
@ -1011,7 +1011,7 @@ void DropCan(int, PLAYER *pPlayer)
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0);
if (pSprite)
{
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn);
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
}
}
@ -1020,7 +1020,7 @@ void ExplodeCan(int, PLAYER *pPlayer)
{
sfxKill3DSound(pPlayer->pSprite, -1, 441);
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0);
evPost(pSprite->index, 3, 0, kCmdOn);
evPost(pSprite->index, 3, 0, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
StartQAV(pPlayer, 15, -1);
pPlayer->curWeapon = 0;
@ -1038,7 +1038,7 @@ void ThrowBundle(int, PLAYER *pPlayer)
if (pPlayer->fuseTime < 0)
pXSprite->Impact = 1;
else
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn);
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 5, 1);
pPlayer->throwPower = 0;
}
@ -1047,7 +1047,7 @@ void DropBundle(int, PLAYER *pPlayer)
{
sfxKill3DSound(pPlayer->pSprite, 16, -1);
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedTNTBundle, 0);
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn);
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 5, 1);
}
@ -1055,7 +1055,7 @@ void ExplodeBundle(int, PLAYER *pPlayer)
{
sfxKill3DSound(pPlayer->pSprite, 16, -1);
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedTNTBundle, 0);
evPost(pSprite->index, 3, 0, kCmdOn);
evPost(pSprite->index, 3, 0, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 5, 1);
StartQAV(pPlayer, 24, -1, 0);
pPlayer->curWeapon = 0;
@ -1067,7 +1067,7 @@ void ThrowProx(int, PLAYER *pPlayer)
int nSpeed = mulscale16(pPlayer->throwPower, 0x177777)+0x66666;
sfxPlay3DSound(pPlayer->pSprite, 455, 1, 0);
spritetype *pSprite = playerFireThing(pPlayer, 0, -9460, kThingArmedProxBomb, nSpeed);
evPost(pSprite->index, 3, 240, kCmdOn);
evPost(pSprite->index, 3, 240, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 10, 1);
pPlayer->throwPower = 0;
}
@ -1075,7 +1075,7 @@ void ThrowProx(int, PLAYER *pPlayer)
void DropProx(int, PLAYER *pPlayer)
{
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedProxBomb, 0);
evPost(pSprite->index, 3, 240, kCmdOn);
evPost(pSprite->index, 3, 240, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 10, 1);
}
@ -1102,7 +1102,7 @@ void DropRemote(int, PLAYER *pPlayer)
void FireRemote(int, PLAYER *pPlayer)
{
evSend(0, 0, 90+(pPlayer->pSprite->type-kDudePlayer1), kCmdOn);
evSend(0, 0, 90+(pPlayer->pSprite->type-kDudePlayer1), kCmdOn, pPlayer->nSprite);
}
#define kMaxShotgunBarrels 4
@ -1928,22 +1928,24 @@ void WeaponProcess(PLAYER *pPlayer) {
pPlayer->flashEffect = ClipLow(pPlayer->flashEffect - 1, 0);
if (gModernMap && gQavScene[pPlayer->nPlayer].index >= 0) {
if (gPlayerCtrl[pPlayer->nPlayer].qavScene.index >= 0 && pPlayer->pXSprite->health > 0) {
int nIndex = gQavScene[pPlayer->nPlayer].index;
if (sprite[nIndex].extra >= 0 && pPlayer->pXSprite->health > 0) {
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
int nIndex = pQavScene->index;
if (sprite[nIndex].extra >= 0) {
XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra];
//viewSetSystemMessage("%d", pXSprite->sysData1);
if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) {
evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID)pXSprite->command, pPlayer->nSprite);
evPost(nIndex, 3, 0, kCmdOff, pPlayer->nSprite);
if (pXSprite->txID > 0)
evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID) pXSprite->command, pQavScene->causedBy);
evPost(nIndex, 3, 0, (COMMAND_ID) (kCmdNumberic + 4), pQavScene->causedBy);
} else {
playQavScene(pPlayer);
qavScenePlay(pPlayer);
pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0);
}
} else {
gQavScene[pPlayer->nPlayer].index = -1;
gQavScene[pPlayer->nPlayer].qavId = NULL;
pQavScene->index = pPlayer->sceneQav = -1;
pQavScene->qavResrc = NULL;
}
return;