- 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

@ -2547,7 +2547,7 @@ void actInit(bool bSaveLoad) {
// by NoOne: init code for all my stuff // by NoOne: init code for all my stuff
if (gModernMap) { if (gModernMap) {
// reset counters // reset counters
gProxySpritesCount = gSightSpritesCount = gPhysSpritesCount = 0; gProxySpritesCount = gSightSpritesCount = gPhysSpritesCount = 0;
@ -3092,6 +3092,25 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
int nXSprite = pSprite->extra; int nXSprite = pSprite->extra;
dassert(nXSprite > 0); dassert(nXSprite > 0);
XSPRITE *pXSprite = &xsprite[pSprite->extra]; 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) { switch (pSprite->type) {
case kDudeModernCustom: { case kDudeModernCustom: {
removeDudeStuff(pSprite); removeDudeStuff(pSprite);
@ -3143,7 +3162,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
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, 10); sfxPlayGDXGenDudeSound(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;
@ -3168,7 +3187,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
return; return;
} }
seqSpawn(seqId, 3, nXSprite, -1); seqSpawn(seqId, 3, nXSprite, -1);
sfxPlayGDXGenDudeSound(pSprite, 10); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTransforming);
return; return;
} }
break; break;
@ -3268,7 +3287,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, 4); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathExplode);
break; break;
case kDudeCultistTommy: case kDudeCultistTommy:
case kDudeCultistShotgun: case kDudeCultistShotgun:
@ -3387,7 +3406,7 @@ 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, 2); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathNormal);
if (nSeq == 3) { if (nSeq == 3) {
bool seq15 = gSysRes.Lookup(pXSprite->data2 + 15, "SEQ"); bool seq16 = gSysRes.Lookup(pXSprite->data2 + 16, "SEQ"); 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: case kDudeModernCustomBurning:
{ {
sfxPlayGDXGenDudeSound(pSprite, 4); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndDeathExplode);
damageType = DAMAGE_TYPE_3; damageType = DAMAGE_TYPE_3;
if (Chance(0x4000)) { if (Chance(0x4000)) {
@ -3628,21 +3647,6 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType,
break; 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) if (damageType == DAMAGE_TYPE_3)
{ {
DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase]; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase];
@ -3672,7 +3676,7 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, in
nSource = pSprite->index; nSource = pSprite->index;
PLAYER *pSourcePlayer = NULL; 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; if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0;
switch (pSprite->statnum) { switch (pSprite->statnum) {
@ -3684,7 +3688,9 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, in
} }
int nType = pSprite->type - kDudeBase; int nDamageFactor = dudeInfo[nType].at70[damageType]; 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; if (!nDamageFactor) return 0;
else if (nDamageFactor != 256) else if (nDamageFactor != 256)
damage = mulscale8(damage, nDamageFactor); damage = mulscale8(damage, nDamageFactor);
@ -4493,7 +4499,7 @@ void ProcessTouchObjects(spritetype *pSprite, int nXSprite)
if ((nHWall = gSpriteHit[nXSprite].hit & 0x3fff) >= 0 && wall[nHWall].extra >= 0) { if ((nHWall = gSpriteHit[nXSprite].hit & 0x3fff) >= 0 && wall[nHWall].extra >= 0) {
XWALL* pXHWall = &xwall[wall[nHWall].extra]; XWALL* pXHWall = &xwall[wall[nHWall].extra];
if (pXHWall->triggerTouch && !pXHWall->isTriggered && (!pXHWall->dudeLockout || IsPlayerSprite(pSprite))) 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) if (pHitWall->extra > 0)
pHitXWall = &xwall[pHitWall->extra]; pHitXWall = &xwall[pHitWall->extra];
if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer) 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) if (pHitWall->nextsector != -1)
{ {
sectortype *pHitSector = &sector[pHitWall->nextsector]; sectortype *pHitSector = &sector[pHitWall->nextsector];
@ -4802,7 +4808,7 @@ void MoveDude(spritetype *pSprite)
if (pHitSector->extra > 0) if (pHitSector->extra > 0)
pHitXSector = &xsector[pHitSector->extra]; pHitXSector = &xsector[pHitSector->extra];
if (pDudeInfo->lockOut && pHitXSector && pHitXSector->Wallpush && !pHitXSector->Key && !pHitXSector->dudeLockout && !pHitXSector->state && !pHitXSector->busy && !pPlayer) 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) if (top < pHitSector->ceilingz || bottom > pHitSector->floorz)
{ {
// ??? // ???
@ -4828,7 +4834,7 @@ void MoveDude(spritetype *pSprite)
else else
pXSector = NULL; pXSector = NULL;
if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout)) if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout))
trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit); trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit, nSprite);
ChangeSpriteSect(nSprite, nSector); ChangeSpriteSect(nSprite, nSector);
nXSector = sector[nSector].extra; nXSector = sector[nSector].extra;
@ -4837,7 +4843,7 @@ void MoveDude(spritetype *pSprite)
if (sector[nSector].type == kSectorTeleport) if (sector[nSector].type == kSectorTeleport)
pXSector->data = pPlayer ? nSprite : -1; pXSector->data = pPlayer ? nSprite : -1;
trTriggerSector(nSector, pXSector, kCmdSectorEnter); trTriggerSector(nSector, pXSector, kCmdSectorEnter, nSprite);
} }
nSector = pSprite->sectnum; nSector = pSprite->sectnum;
@ -5340,7 +5346,7 @@ int MoveMissile(spritetype *pSprite)
XWALL *pXWall = &xwall[pWall->extra]; XWALL *pXWall = &xwall[pWall->extra];
if (pXWall->triggerVector) if (pXWall->triggerVector)
{ {
trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact); trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact, nSprite);
if (!(pWall->cstat&64)) if (!(pWall->cstat&64))
{ {
vdi = -1; vdi = -1;
@ -5514,7 +5520,7 @@ void actExplodeSprite(spritetype *pSprite)
sfxPlay3DSound(pSprite, nSnd, -1, 0); sfxPlay3DSound(pSprite, nSnd, -1, 0);
} }
break; break;
case kThingPodGreenBall: case kThingPodFireBall:
nType = 3; nType = 3;
seqSpawn(9, 3, nXSprite, -1); seqSpawn(9, 3, nXSprite, -1);
sfxPlay3DSound(pSprite, 307, -1, 0); sfxPlay3DSound(pSprite, 307, -1, 0);
@ -5890,7 +5896,7 @@ void actProcessSprites(void)
actDamageSprite(actSpriteOwnerToSpriteId(pSprite), pObject, DAMAGE_TYPE_0, 12); actDamageSprite(actSpriteOwnerToSpriteId(pSprite), pObject, DAMAGE_TYPE_0, 12);
} }
break; break;
case kThingPodFireBall: case kThingPodGreenBall:
if ((hit&0xc000) == 0x4000) 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); 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); evPost(pSprite->index, 3, 0, kCallbackFXPodBloodSplat);
} }
break; break;
case kThingPodGreenBall: case kThingPodFireBall:
{ {
int nObject = hit & 0x3fff; int nObject = hit & 0x3fff;
if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096)) if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096))
@ -5969,7 +5975,7 @@ void actProcessSprites(void)
if (nWall == -1) if (nWall == -1)
break; break;
XWALL *pXWall = &xwall[wall[nWall].extra]; 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]) for (int nSprite2 = headspritestat[kStatDude]; nSprite2 >= 0; nSprite2 = nextspritestat[nSprite2])
@ -6172,7 +6178,7 @@ void actProcessSprites(void)
pXSprite->burnSource = -1; pXSprite->burnSource = -1;
pXSprite->data1 = pXIncarnation->data1; 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 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; if (pIncarnation->statnum == kStatDude && pIncarnation->type == kDudeModernCustom) pXSprite->sysData1 = pXIncarnation->sysData1;
@ -6206,8 +6212,7 @@ void actProcessSprites(void)
case kDudeModernCustom: case kDudeModernCustom:
case kDudeModernCustomBurning: case kDudeModernCustomBurning:
seqId = getSeqStartId(pXSprite); seqId = getSeqStartId(pXSprite);
if (seqId != oldData2) getSpriteMassBySize(pSprite); // create or refresh mass cache
getSpriteMassBySize(pSprite); // create or refresh mass cache
fallthrough__; // go below fallthrough__; // go below
default: default:
seqSpawn(seqId, 3, nXSprite, -1); 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]; XWALL *pXWall = &xwall[nXWall];
if (pXWall->triggerVector) if (pXWall->triggerVector)
trTriggerWall(nWall, pXWall, kCmdWallImpact); trTriggerWall(nWall, pXWall, kCmdWallImpact, nShooter);
} }
break; break;
} }
@ -7553,7 +7558,6 @@ int getSpriteMassBySize(spritetype* pSprite) {
int mass = 0; int seqId = -1; Seq* pSeq = NULL; int mass = 0; int seqId = -1; Seq* pSeq = NULL;
if (IsDudeSprite(pSprite)) { if (IsDudeSprite(pSprite)) {
switch (pSprite->type) { switch (pSprite->type) {
case kDudePodMother: // fake dude, no seq case kDudePodMother: // fake dude, no seq
break; break;
@ -7562,7 +7566,6 @@ int getSpriteMassBySize(spritetype* pSprite) {
seqId = xsprite[pSprite->extra].data2; seqId = xsprite[pSprite->extra].data2;
break; break;
default: default:
seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID; seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID;
break; break;
} }
@ -7647,6 +7650,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);
return cached->mass; return cached->mass;
} }

View file

@ -288,6 +288,6 @@ extern short gPhysSpritesList[kMaxSuperXSprites];
extern short gProxySpritesCount; extern short gProxySpritesCount;
extern short gSightSpritesCount; extern short gSightSpritesCount;
extern short gPhysSpritesCount; extern short gPhysSpritesCount;
//extern short gQavPlayerIndex; extern int DudeDifficulty[];
END_BLD_NS 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 "sfx.h"
#include "trig.h" #include "trig.h"
#include "triggers.h" #include "triggers.h"
#include "view.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -421,12 +422,12 @@ void aiActivateDude(spritetype *pSprite, XSPRITE *pXSprite)
else { else {
aiNewState(pSprite, pXSprite, &GDXGenDudeSearchL); aiNewState(pSprite, pXSprite, &GDXGenDudeSearchL);
if (Chance(0x4000)) if (Chance(0x4000))
sfxPlayGDXGenDudeSound(pSprite, 0); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTargetSpot);
} }
} }
else { else {
if (Chance(0x4000)) if (Chance(0x4000))
sfxPlayGDXGenDudeSound(pSprite, 0); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndTargetSpot);
if (spriteIsUnderwater(pSprite, false)) if (spriteIsUnderwater(pSprite, false))
aiNewState(pSprite, pXSprite, &GDXGenDudeChaseW); aiNewState(pSprite, pXSprite, &GDXGenDudeChaseW);
@ -1025,7 +1026,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, 3); sfxPlayGDXGenDudeSound(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;
@ -1058,7 +1059,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T
&& gSysRes.Lookup(pXSprite->data2 + 3, "SEQ")) { && gSysRes.Lookup(pXSprite->data2 + 3, "SEQ")) {
aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1); aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1);
sfxPlayGDXGenDudeSound(pSprite, 3); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndBurning);
pSprite->type = kDudeModernCustomBurning; pSprite->type = kDudeModernCustomBurning;
if (pXSprite->data2 == kDefaultAnimationBase) // don't inherit palette for burning if using default animation 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); else aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgD);
if (Chance(0x0200)) if (Chance(0x0200))
sfxPlayGDXGenDudeSound(pSprite, 1); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit);
} }
else if (sub_5BDA8(pSprite, 13)) else if (sub_5BDA8(pSprite, 13))
aiNewState(pSprite, pXSprite, &GDXGenDudeDodgeDmgW); 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); 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)) 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")) { if (gSysRes.Lookup(pXSprite->data2 + 4, "SEQ")) {
GDXGenDudeRTesla.at18 = (Chance(chance4 * 2) ? &GDXGenDudeDodgeL : &GDXGenDudeDodgeDmgL); GDXGenDudeRTesla.at18 = (Chance(chance4 * 2) ? &GDXGenDudeDodgeL : &GDXGenDudeDodgeDmgL);
@ -1145,13 +1146,13 @@ void RecoilDude(spritetype *pSprite, XSPRITE *pXSprite)
} }
if (inDodge(pXSprite->aiState)) { if (inDodge(pXSprite->aiState)) {
sfxPlayGDXGenDudeSound(pSprite, 1); sfxPlayGDXGenDudeSound(pSprite, kGenDudeSndGotHit);
break; break;
} }
if (inIdle(pXSprite->aiState) || chance3 || Chance(getRecoilChance(pSprite)) || (!dudeIsMelee(pXSprite) && mass < 155)) { 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); 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 (canSwim(pSprite) && spriteIsUnderwater(pSprite, false)) aiNewState(pSprite, pXSprite, &GDXGenDudeRecoilW);
@ -1454,32 +1455,43 @@ 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) if (pSprite->flags & 32) continue;
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 (pXSprite->aiState->at10)
pXSprite->aiState->at10(pSprite, pXSprite); pXSprite->aiState->at10(pSprite, pXSprite);
if (pXSprite->aiState->at14 && (gFrame&3) == (nSprite&3)) if (pXSprite->aiState->at14 && (gFrame&3) == (nSprite&3))
pXSprite->aiState->at14(pSprite, pXSprite); pXSprite->aiState->at14(pSprite, pXSprite);
if (pXSprite->stateTimer == 0 && pXSprite->aiState->at18) if (pXSprite->stateTimer == 0 && pXSprite->aiState->at18) {
{
if (pXSprite->aiState->at8 > 0) if (pXSprite->aiState->at8 > 0)
aiNewState(pSprite, pXSprite, pXSprite->aiState->at18); aiNewState(pSprite, pXSprite, pXSprite->aiState->at18);
else if (seqGetStatus(3, nXSprite) < 0) else if (seqGetStatus(3, nXSprite) < 0)
aiNewState(pSprite, pXSprite, pXSprite->aiState->at18); 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]; pXSprite->data3 = cumulDamage[nXSprite];
RecoilDude(pSprite, pXSprite); 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)); memset(cumulDamage, 0, sizeof(cumulDamage));
} }
@ -1505,13 +1517,11 @@ void aiInitSprite(spritetype *pSprite)
pDudeExtra->at4 = 0; pDudeExtra->at4 = 0;
pDudeExtra->at0 = 0; pDudeExtra->at0 = 0;
switch (pSprite->type) { switch (pSprite->type) {
case kDudeModernCustom: case kDudeModernCustom: {
{
DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[nXSprite].at6.u1;
pDudeExtraE->at8 = 0; pDudeExtraE->at8 = pDudeExtraE->at0 = 0;
pDudeExtraE->at0 = 0;
pDudeExtraE->at4 = 0;
aiNewState(pSprite, pXSprite, &GDXGenDudeIdleL); aiNewState(pSprite, pXSprite, &GDXGenDudeIdleL);
genDudePrepare(pSprite);
break; break;
} }
case kDudeModernCustomBurning: case kDudeModernCustomBurning:

View file

@ -103,6 +103,7 @@ void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite);
void aiProcessDudes(void); 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);
// 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

@ -181,7 +181,7 @@ static void ThrowSeqCallback(int, int nXSprite)
if (v4) if (v4)
xsprite[pMissile->extra].Impact = 1; xsprite[pMissile->extra].Impact = 1;
else 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) static void sub_68170(int, int nXSprite)
@ -194,7 +194,7 @@ static void sub_68170(int, int nXSprite)
nMissile = kThingArmedTNTBundle; nMissile = kThingArmedTNTBundle;
sfxPlay3DSound(pSprite, 455, -1, 0); sfxPlay3DSound(pSprite, 455, -1, 0);
spritetype *pMissile = actFireThing(pSprite, 0, 0, gDudeSlope[nXSprite]-9460, nMissile, 0x133333); 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) 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); sfxPlay3DSound(pSprite, 2474, -1, 0);
else else
sfxPlay3DSound(pSprite, 2475, -1, 0); 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) if (pMissile)
seqSpawn(68, 3, pMissile->extra, -1); seqSpawn(68, 3, pMissile->extra, -1);
@ -136,7 +136,7 @@ static void sub_6FFA0(int, int nXSprite)
if (pDudeInfo->seeDist*0.1 < nDist) if (pDudeInfo->seeDist*0.1 < nDist)
{ {
sfxPlay3DSound(pSprite, 2454, -1, 0); 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) if (pMissile)
seqSpawn(22, 3, pMissile->extra, -1); 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 BEGIN_BLD_NS
#define kMaxGenDudeSndMode 11
#define kDefaultAnimationBase 11520 #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; extern AISTATE GDXGenDudeIdleL;
@ -68,6 +97,28 @@ struct GENDUDESND
extern GENDUDESND gCustomDudeSnd[]; 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); 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);
@ -76,6 +127,7 @@ spritetype* leechIsDropped(spritetype* pSprite);
bool spriteIsUnderwater(spritetype* pSprite, bool oldWay); bool spriteIsUnderwater(spritetype* pSprite, bool oldWay);
bool sfxPlayGDXGenDudeSound(spritetype* pSprite, int mode); bool sfxPlayGDXGenDudeSound(spritetype* pSprite, int mode);
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);
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);
@ -85,11 +137,18 @@ int getDodgeChance(spritetype* pSprite);
int getRecoilChance(spritetype* pSprite); int getRecoilChance(spritetype* pSprite);
bool dudeIsMelee(XSPRITE* pXSprite); bool dudeIsMelee(XSPRITE* pXSprite);
void updateTargetOfSlaves(spritetype* pSprite); void updateTargetOfSlaves(spritetype* pSprite);
void updateTargetOfLeech(spritetype* pSprite);
bool canSwim(spritetype* pSprite); bool canSwim(spritetype* pSprite);
bool canDuck(spritetype* pSprite); bool canDuck(spritetype* pSprite);
bool CDCanMove(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); 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 END_BLD_NS

View file

@ -358,7 +358,7 @@ void CounterCheck(int nSector) // 12
return; return;
} else { } else {
//pXSector->waitTimeA = 0; //do not reset necessary objects counter to zero //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 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); sfxPlay3DSound(pSprite, 385, nChannel, 1);
} }
spritetype *pFX = NULL; 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); pFX = gFX.fxSpawn(FX_55, pSprite->sectnum, x, y, floorZ-64, 0);
if (pFX) if (pFX)
pFX->ang = nAngle; pFX->ang = nAngle;

View file

@ -88,6 +88,15 @@ void _consoleSysMsg(const char* pMessage, ...);
#define kMaxPAL 5 #define kMaxPAL 5
#define kFreeQAVEntry 108 #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 ///////////////////////////////////////////////////// // MEDIUM /////////////////////////////////////////////////////
enum { enum {
kMediumNormal = 0, kMediumNormal = 0,
@ -368,8 +377,8 @@ enum {
kThingBloodChunks = 426, kThingBloodChunks = 426,
kThingZombieHead = 427, kThingZombieHead = 427,
kThingNapalmBall = 428, kThingNapalmBall = 428,
kThingPodGreenBall = 429, kThingPodFireBall = 429,
kThingPodFireBall = 430, kThingPodGreenBall = 430,
kThingDroppedLifeLeech = 431, kThingDroppedLifeLeech = 431,
kThingVoodooHead = 432, // unused kThingVoodooHead = 432, // unused
kModernThingTNTProx = 433, // gModernMap only - detects only players kModernThingTNTProx = 433, // gModernMap only - detects only players

View file

@ -696,13 +696,14 @@ const int nXSectorSize = 60;
const int nXSpriteSize = 56; const int nXSpriteSize = 56;
const int nXWallSize = 24; const int nXWallSize = 24;
int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC) 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];
char name2[BMAX_PATH];
int16_t tpskyoff[256];
memset(show2dsector, 0, sizeof(show2dsector)); memset(show2dsector, 0, sizeof(show2dsector));
memset(show2dwall, 0, sizeof(show2dwall)); memset(show2dwall, 0, sizeof(show2dwall));
memset(show2dsprite, 0, sizeof(show2dsprite)); memset(show2dsprite, 0, sizeof(show2dsprite));
gModernMap = false;
#ifdef USE_OPENGL #ifdef USE_OPENGL
Polymost_prepare_loadboard(); Polymost_prepare_loadboard();
#endif #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, // 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. // 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; if ((header.version & 0x00ff) == 0x001) gModernMap = true;
else gModernMap = false;
} else { } else {
initprintf("Map file is wrong version"); 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].reference = i;
xsector[sector[i].extra].busy = xsector[sector[i].extra].state<<16; 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++) 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].reference = i;
xwall[wall[i].extra].busy = xwall[wall[i].extra].state << 16; 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(); 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 // 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 // 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; gModernMap = true;
} }
if ((sprite[i].cstat & 0x30) == 0x30) 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 // by NoOne additional non-thing proximity, sight and physics sprites
#define kMaxSuperXSprites 128 #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; extern bool gModernMap;
#pragma pack(push, 1) #pragma pack(push, 1)
@ -58,7 +71,7 @@ struct XSPRITE {
unsigned int respawnPending : 2; // respawnPending unsigned int respawnPending : 2; // respawnPending
signed int dropMsg : 8; // Drop Item unsigned int dropMsg : 8; // Drop Item
unsigned int Decoupled : 1; // Decoupled unsigned int Decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1; // works in case if triggerOnce selected unsigned int isTriggered : 1; // works in case if triggerOnce selected

View file

@ -1570,7 +1570,7 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
256, // angSpeed 256, // angSpeed
// 0, // 0,
7, -1, 18, // nGibType 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, 0, 0, 0, 0, 0,
0, 0,
0 0

View file

@ -349,80 +349,96 @@ char evGetSourceState(int nType, int nIndex)
void evSend(int nIndex, int nType, int rxId, COMMAND_ID command, short causedBy) 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; EVENT event; event.index = nIndex; event.type = nType; event.cmd = command; event.causedBy = causedBy;
switch (command) { switch (command) {
case kCmdState: case kCmdState:
command = evGetSourceState(nType, nIndex) ? kCmdOn : kCmdOff; command = evGetSourceState(nType, nIndex) ? kCmdOn : kCmdOff;
break; break;
case kCmdNotState: case kCmdNotState:
command = evGetSourceState(nType, nIndex) ? kCmdOff : kCmdOn; command = evGetSourceState(nType, nIndex) ? kCmdOff : kCmdOn;
break; break;
} }
switch (rxId) { switch (rxId) {
case kChannelTextOver: case kChannelTextOver:
if (command >= kCmdNumberic) trTextOver(command - kCmdNumberic); if (command >= kCmdNumberic) trTextOver(command - kCmdNumberic);
else viewSetSystemMessage("Invalid TextOver command by xobject #%d (object type %d)", nIndex, nType); else viewSetSystemMessage("Invalid TextOver command by xobject #%d (object type %d)", nIndex, nType);
return; return;
case kChannelLevelExitNormal: case kChannelLevelExitNormal:
levelEndLevel(0); levelEndLevel(0);
return; return;
case kChannelLevelExitSecret: case kChannelLevelExitSecret:
levelEndLevel(1); levelEndLevel(1);
return; return;
// By NoOne: finished level and load custom level ¹ via numbered command. // By NoOne: finished level and load custom level ¹ via numbered command.
case kChannelModernEndLevelCustom: case kChannelModernEndLevelCustom:
if (command >= kCmdNumberic) levelEndLevelCustom(command - kCmdNumberic); if (command >= kCmdNumberic) levelEndLevelCustom(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Level-Exit# command by xobject #%d (object type %d)", nIndex, nType); else viewSetSystemMessage("Invalid Level-Exit# command by xobject #%d (object type %d)", nIndex, nType);
return; return;
case kChannelSetTotalSecrets: case kChannelSetTotalSecrets:
if (command >= kCmdNumberic) levelSetupSecret(command - kCmdNumberic); if (command >= kCmdNumberic) levelSetupSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Total-Secrets command by xobject #%d (object type %d)", nIndex, nType); else viewSetSystemMessage("Invalid Total-Secrets command by xobject #%d (object type %d)", nIndex, nType);
break; break;
case kChannelSecretFound: case kChannelSecretFound:
if (command >= kCmdNumberic) levelTriggerSecret(command - kCmdNumberic); if (command >= kCmdNumberic) levelTriggerSecret(command - kCmdNumberic);
else viewSetSystemMessage("Invalid Trigger-Secret command by xobject #%d (object type %d)", nIndex, nType); else viewSetSystemMessage("Invalid Trigger-Secret command by xobject #%d (object type %d)", nIndex, nType);
break; break;
case kChannelRemoteBomb0: case kChannelRemoteBomb0:
case kChannelRemoteBomb1: case kChannelRemoteBomb1:
case kChannelRemoteBomb2: case kChannelRemoteBomb2:
case kChannelRemoteBomb3: case kChannelRemoteBomb3:
case kChannelRemoteBomb4: case kChannelRemoteBomb4:
case kChannelRemoteBomb5: case kChannelRemoteBomb5:
case kChannelRemoteBomb6: case kChannelRemoteBomb6:
case kChannelRemoteBomb7: case kChannelRemoteBomb7:
for (int nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite]) 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]; XSPRITE* pXSprite = &xsprite[nXSprite];
if (pSprite->flags&32) if (pXSprite->rxID == rxId)
continue; trMessageSprite(nSprite, event);
int nXSprite = pSprite->extra;
if (nXSprite > 0)
{
XSPRITE *pXSprite = &xsprite[nXSprite];
if (pXSprite->rxID == rxId)
trMessageSprite(nSprite, event);
}
} }
return; }
case kChannelTeamAFlagCaptured: return;
case kChannelTeamBFlagCaptured: case kChannelTeamAFlagCaptured:
for (int nSprite = headspritestat[kStatItem]; nSprite >= 0; nSprite = nextspritestat[nSprite]) 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]; XSPRITE* pXSprite = &xsprite[nXSprite];
if (pSprite->flags&32) if (pXSprite->rxID == rxId)
continue; trMessageSprite(nSprite, event);
int nXSprite = pSprite->extra;
if (nXSprite > 0)
{
XSPRITE *pXSprite = &xsprite[nXSprite];
if (pXSprite->rxID == rxId)
trMessageSprite(nSprite, event);
}
} }
return; }
default: return;
break; 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++) { for (int i = bucketHead[rxId]; i < bucketHead[rxId+1]; i++) {

View file

@ -27,32 +27,47 @@ BEGIN_BLD_NS
enum { enum {
kChannelZero = 0, kChannelZero = 0,
kChannelSetTotalSecrets, kChannelSetTotalSecrets,
kChannelSecretFound, kChannelSecretFound,
kChannelTextOver, kChannelTextOver,
kChannelLevelExitNormal, kChannelLevelExitNormal,
kChannelLevelExitSecret, kChannelLevelExitSecret,
kChannelModernEndLevelCustom, // // custom level end kChannelModernEndLevelCustom, // custom level end
kChannelLevelStart, kChannelLevelStart,
kChannelLevelStartMatch, // DM and TEAMS kChannelLevelStartMatch, // DM and TEAMS
kChannelLevelStartCoop, kChannelLevelStartCoop,
kChannelLevelStartTeamsOnly, kChannelLevelStartTeamsOnly,
kChannelPlayerDeathTeamA = 15, kChannelPlayerDeathTeamA = 15,
kChannelPlayerDeathTeamB, kChannelPlayerDeathTeamB,
kChannelMapExtended = 60, // map requires modern features to work properly
kChannelTeamAFlagCaptured = 80, // by NoOne: RX channels of players to send commands on
kChannelTeamBFlagCaptured, /////////////////////////////
kChannelRemoteBomb0 = 90, kChannelPlayer0 = 30,
kChannelRemoteBomb1, kChannelPlayer1,
kChannelRemoteBomb2, kChannelPlayer2,
kChannelRemoteBomb3, kChannelPlayer3,
kChannelRemoteBomb4, kChannelPlayer4,
kChannelRemoteBomb5, kChannelPlayer5,
kChannelRemoteBomb6, kChannelPlayer6,
kChannelRemoteBomb7, kChannelPlayer7,
kChannelUser = 100, kChannelAllPlayers = kChannelPlayer0 + kMaxPlayers,
kChannelMax = 4096, /////////////////////////////
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 struct RXBUCKET
@ -79,7 +94,7 @@ enum COMMAND_ID {
kCmdCounterSector = 12, kCmdCounterSector = 12,
kCmdCallback = 20, kCmdCallback = 20,
kCmdRepeat = 21, kCmdRepeat = 21,
kCmdSpritePush = 30, kCmdSpritePush = 30,
kCmdSpriteImpact = 31, kCmdSpriteImpact = 31,
kCmdSpritePickup = 32, kCmdSpritePickup = 32,
@ -87,7 +102,7 @@ enum COMMAND_ID {
kCmdSpriteSight = 34, kCmdSpriteSight = 34,
kCmdSpriteProximity = 35, kCmdSpriteProximity = 35,
kCmdSpriteExplode = 36, kCmdSpriteExplode = 36,
kCmdSectorPush = 40, kCmdSectorPush = 40,
kCmdSectorImpact = 41, kCmdSectorImpact = 41,
kCmdSectorEnter = 42, kCmdSectorEnter = 42,
@ -99,11 +114,15 @@ enum COMMAND_ID {
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 kChannelMapExtended RX / TX kCmdModernFeaturesEnable = 100, // must be in object with kChannelMapModernize RX / TX
kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapExtended RX / TX kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapModernize RX / TX
kCmdNumbericMax = 255, kCmdNumbericMax = 255,
}; };
inline bool playerRXRngIsFine(int rx) {
return (rx >= kChannelPlayer0 && rx < kChannelPlayer7);
}
struct EVENT { struct EVENT {
unsigned int index: 14; // index unsigned int index: 14; // index
unsigned int type: 3; // type unsigned int type: 3; // type
@ -114,8 +133,8 @@ struct EVENT {
void evInit(void); void evInit(void);
char evGetSourceState(int nType, int nIndex); char evGetSourceState(int nType, int nIndex);
void evSend(int nIndex, int nType, int rxId, 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 = -1); 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 evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback, short causedBy = -1);
void evProcess(unsigned int nTime); void evProcess(unsigned int nTime);
void evKill(int a1, int a2); void evKill(int a1, int a2);

View file

@ -50,6 +50,21 @@ enum {
PARALLAXCLIP_FLOOR = 2, 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 AreSectorsNeighbors(int sect1, int sect2);
bool FindSector(int nX, int nY, int nZ, int *nSector); bool FindSector(int nX, int nY, int nZ, int *nSector);
bool FindSector(int nX, int nY, 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(&gMapRev, sizeof(gMapRev));
Read(&gSongId, sizeof(gSkyCount)); Read(&gSongId, sizeof(gSkyCount));
Read(&gFogMode, sizeof(gFogMode)); Read(&gFogMode, sizeof(gFogMode));
Read(&gModernMap, sizeof(gModernMap));
#ifdef YAX_ENABLE #ifdef YAX_ENABLE
Read(&numyaxbunches, sizeof(numyaxbunches)); Read(&numyaxbunches, sizeof(numyaxbunches));
#endif #endif
@ -420,6 +421,7 @@ void MyLoadSave::Save(void)
Write(&gMapRev, sizeof(gMapRev)); Write(&gMapRev, sizeof(gMapRev));
Write(&gSongId, sizeof(gSkyCount)); Write(&gSongId, sizeof(gSkyCount));
Write(&gFogMode, sizeof(gFogMode)); Write(&gFogMode, sizeof(gFogMode));
Write(&gModernMap, sizeof(gModernMap));
#ifdef YAX_ENABLE #ifdef YAX_ENABLE
Write(&numyaxbunches, sizeof(numyaxbunches)); Write(&numyaxbunches, sizeof(numyaxbunches));
#endif #endif

View file

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

View file

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

View file

@ -113,12 +113,12 @@ void UpdateSprite(int nXSprite, SEQFRAME *pFrame)
int scale = xsprite[nXSprite].scale; // SEQ size scaling int scale = xsprite[nXSprite].scale; // SEQ size scaling
if (pFrame->at2_0) { 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; else pSprite->xrepeat = pFrame->at2_0;
} }
if (pFrame->at3_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; else pSprite->yrepeat = pFrame->at3_0;
} }

View file

@ -70,11 +70,11 @@ struct ACTIVE
struct SEQINST struct SEQINST
{ {
DICTNODE *hSeq; DICTNODE *hSeq;
Seq *pSequence; // mass Seq *pSequence;
int at8; int at8;
int atc; int atc;
short at10; short at10;
unsigned char frameIndex; // at12 unsigned char frameIndex;
char at13; char at13;
void Update(ACTIVE *pActive); 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 "db.h"
#include "eventq.h" #include "eventq.h"
#include "dude.h" #include "dude.h"
#include "player.h"
BEGIN_BLD_NS 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 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 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 trMessageSprite(unsigned int nSprite, EVENT event);
void trProcessBusy(void); void trProcessBusy(void);
void trInit(void); void trInit(void);
@ -65,7 +69,7 @@ void freeTargets(int nSprite);
void freeAllTargets(XSPRITE* pXSource); void freeAllTargets(XSPRITE* pXSource);
bool affectedByTargetChg(XSPRITE* pXDude); bool affectedByTargetChg(XSPRITE* pXDude);
int getDataFieldOfObject(int objType, int objIndex, int dataIndex); 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 goalValueIsReached(XSPRITE* pXSprite);
bool getDudesForTargetChg(XSPRITE* pXSprite); bool getDudesForTargetChg(XSPRITE* pXSprite);
void stopWindOnSectors(XSPRITE* pXSource); void stopWindOnSectors(XSPRITE* pXSource);
@ -75,8 +79,13 @@ void useSeqSpawnerGen(XSPRITE* pXSource, int objType, int index);
void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite); void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite);
void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite); void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite);
void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex); void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex);
void useObjResizer(XSPRITE* pXSource, short objType, int objIndex);
void TeleFrag(int nKiller, int nSector); void TeleFrag(int nKiller, int nSector);
bool valueIsBetween(int val, int min, int max); 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 END_BLD_NS

View file

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

View file

@ -48,7 +48,7 @@ void warpInit(void)
gUpperLink[i] = -1; gUpperLink[i] = -1;
gLowerLink[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++) for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
{ {
if (sprite[nSprite].statnum < kMaxStatus) { if (sprite[nSprite].statnum < kMaxStatus) {
@ -134,11 +134,14 @@ void warpInit(void)
} }
} }
} }
// check if there is enough start positions for teams, if any used // check if there is enough start positions for teams, if any used
if (team1 > 0 || team2 > 0) { if (team1 > 0 || team2 > 0) {
gTeamsSpawnUsed = true; gTeamsSpawnUsed = true;
//if (team1 < kMaxPlayers / 2 || team2 < kMaxPlayers / 2) if (team1 < kMaxPlayers / 2 || team2 < kMaxPlayers / 2) {
//_ShowMessageWindow("At least 4 spawn positions for each team is recommended."); 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++) 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); dassert(pPlayer != NULL);
if (pPlayer->weaponQav == -1) if (pPlayer->weaponQav == -1)
return; return;
QAV *pQAV = weaponQAV[pPlayer->weaponQav]; QAV * pQAV = weaponQAV[pPlayer->weaponQav];
int v4; int v4;
if (pPlayer->weaponTimer == 0) if (pPlayer->weaponTimer == 0)
v4 = (int)totalclock%pQAV->at10; v4 = (int)totalclock % pQAV->at10;
else else
v4 = pQAV->at10-pPlayer->weaponTimer; v4 = pQAV->at10 - pPlayer->weaponTimer;
pQAV->x = a3; pQAV->x = a3;
pQAV->y = a4; 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;
@ -996,7 +996,7 @@ void ThrowCan(int, PLAYER *pPlayer)
if (pSprite) if (pSprite)
{ {
sfxPlay3DSound(pSprite, 441, 0, 0); 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; int nXSprite = pSprite->extra;
XSPRITE *pXSprite = &xsprite[nXSprite]; XSPRITE *pXSprite = &xsprite[nXSprite];
pXSprite->Impact = 1; pXSprite->Impact = 1;
@ -1011,7 +1011,7 @@ void DropCan(int, PLAYER *pPlayer)
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0); spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0);
if (pSprite) if (pSprite)
{ {
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn); evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 6, gAmmoItemData[0].count); UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
} }
} }
@ -1020,7 +1020,7 @@ void ExplodeCan(int, PLAYER *pPlayer)
{ {
sfxKill3DSound(pPlayer->pSprite, -1, 441); sfxKill3DSound(pPlayer->pSprite, -1, 441);
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0); 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); UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
StartQAV(pPlayer, 15, -1); StartQAV(pPlayer, 15, -1);
pPlayer->curWeapon = 0; pPlayer->curWeapon = 0;
@ -1038,7 +1038,7 @@ void ThrowBundle(int, PLAYER *pPlayer)
if (pPlayer->fuseTime < 0) if (pPlayer->fuseTime < 0)
pXSprite->Impact = 1; pXSprite->Impact = 1;
else else
evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn); evPost(pSprite->index, 3, pPlayer->fuseTime, kCmdOn, pPlayer->nSprite);
UseAmmo(pPlayer, 5, 1); UseAmmo(pPlayer, 5, 1);
pPlayer->throwPower = 0; pPlayer->throwPower = 0;
} }
@ -1047,7 +1047,7 @@ void DropBundle(int, PLAYER *pPlayer)
{ {
sfxKill3DSound(pPlayer->pSprite, 16, -1); sfxKill3DSound(pPlayer->pSprite, 16, -1);
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedTNTBundle, 0); 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); UseAmmo(pPlayer, 5, 1);
} }
@ -1055,7 +1055,7 @@ void ExplodeBundle(int, PLAYER *pPlayer)
{ {
sfxKill3DSound(pPlayer->pSprite, 16, -1); sfxKill3DSound(pPlayer->pSprite, 16, -1);
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedTNTBundle, 0); 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); UseAmmo(pPlayer, 5, 1);
StartQAV(pPlayer, 24, -1, 0); StartQAV(pPlayer, 24, -1, 0);
pPlayer->curWeapon = 0; pPlayer->curWeapon = 0;
@ -1067,7 +1067,7 @@ void ThrowProx(int, PLAYER *pPlayer)
int nSpeed = mulscale16(pPlayer->throwPower, 0x177777)+0x66666; int nSpeed = mulscale16(pPlayer->throwPower, 0x177777)+0x66666;
sfxPlay3DSound(pPlayer->pSprite, 455, 1, 0); sfxPlay3DSound(pPlayer->pSprite, 455, 1, 0);
spritetype *pSprite = playerFireThing(pPlayer, 0, -9460, kThingArmedProxBomb, nSpeed); 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); UseAmmo(pPlayer, 10, 1);
pPlayer->throwPower = 0; pPlayer->throwPower = 0;
} }
@ -1075,7 +1075,7 @@ void ThrowProx(int, PLAYER *pPlayer)
void DropProx(int, PLAYER *pPlayer) void DropProx(int, PLAYER *pPlayer)
{ {
spritetype *pSprite = playerFireThing(pPlayer, 0, 0, kThingArmedProxBomb, 0); 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); UseAmmo(pPlayer, 10, 1);
} }
@ -1102,7 +1102,7 @@ void DropRemote(int, PLAYER *pPlayer)
void FireRemote(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 #define kMaxShotgunBarrels 4
@ -1927,23 +1927,25 @@ char sub_4F484(PLAYER *pPlayer)
void WeaponProcess(PLAYER *pPlayer) { void WeaponProcess(PLAYER *pPlayer) {
pPlayer->flashEffect = ClipLow(pPlayer->flashEffect - 1, 0); 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; QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
if (sprite[nIndex].extra >= 0 && pPlayer->pXSprite->health > 0) {
int nIndex = pQavScene->index;
if (sprite[nIndex].extra >= 0) {
XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra]; XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra];
//viewSetSystemMessage("%d", pXSprite->sysData1);
if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) { if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) {
evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID)pXSprite->command, pPlayer->nSprite); if (pXSprite->txID > 0)
evPost(nIndex, 3, 0, kCmdOff, pPlayer->nSprite); evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID) pXSprite->command, pQavScene->causedBy);
evPost(nIndex, 3, 0, (COMMAND_ID) (kCmdNumberic + 4), pQavScene->causedBy);
} else { } else {
playQavScene(pPlayer); qavScenePlay(pPlayer);
pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0); pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0);
} }
} else { } else {
gQavScene[pPlayer->nPlayer].index = -1; pQavScene->index = pPlayer->sceneQav = -1;
gQavScene[pPlayer->nPlayer].qavId = NULL; pQavScene->qavResrc = NULL;
} }
return; return;