mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 17:01:51 +00:00
- Fixed getPlayeById() function in multiplayer.
- Fixed debris physics flags was not properly reset on level restart. - Added new modern type "kModernSlopeChanger" that can manipulate sector and sprite slopes. - Allow to drop items and keys for players in multiplayer (gModernMap only). - Added event commands to manipulate dude flags. - Patrol enemies (xsprite.dudeFlag4, gModernMap only): - Added path markers following. - Added stealth mechanics. - Added spot target progress bar. - Added alarm dude flag. - Added blind dude flag. - Added deaf dude flag. - Added conditions for kModernCondition related to patrol enemies. - kModernDamager can work like generator and damage anyone in sectors or in map. - kSectorDamage is not does the damage if in Off state (gModernMap only). - Additional options kModernSeqSpawner. - Effects that created with kModernEffectSpawner now inherits offset of the sprite. - Added kCmdSectorMotionPause and kCmdSectorMotionContinue event commands that allows to pause or continue sector motion (gModernMap only, WIP). - Various minor fixes. # Conflicts: # source/blood/src/ai.cpp # source/blood/src/common_game.h # source/blood/src/eventq.cpp # source/blood/src/nnexts.cpp # source/blood/src/nnexts.h # source/blood/src/triggers.cpp # source/blood/src/triggers.h # source/blood/src/view.cpp # Conflicts: # source/games/blood/src/ai.cpp # source/games/blood/src/nnexts.h # Conflicts: # source/games/blood/src/actor.cpp # source/games/blood/src/ai.cpp
This commit is contained in:
parent
c4fa99c891
commit
3a59243ea0
13 changed files with 1508 additions and 234 deletions
|
@ -4193,8 +4193,14 @@ static void actTouchFloor(DBloodActor* actor, int nSector)
|
|||
XSECTOR* pXSector = nullptr;
|
||||
if (pSector->extra > 0) pXSector = &xsector[pSector->extra];
|
||||
|
||||
if (pXSector && (pSector->type == kSectorDamage || pXSector->damageType > 0))
|
||||
{
|
||||
bool doDamage = (pXSector && (pSector->type == kSectorDamage || pXSector->damageType > 0));
|
||||
// don't allow damage for damage sectors if they are not enabled
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap && doDamage && pSector->type == kSectorDamage && !pXSector->state)
|
||||
doDamage = false;
|
||||
#endif
|
||||
|
||||
if (doDamage) {
|
||||
DAMAGE_TYPE nDamageType;
|
||||
if (pSector->type == kSectorDamage) nDamageType = (DAMAGE_TYPE)ClipRange(pXSector->damageType, DAMAGE_TYPE_0, DAMAGE_TYPE_6);
|
||||
else nDamageType = (DAMAGE_TYPE)ClipRange(pXSector->damageType - 1, DAMAGE_TYPE_0, DAMAGE_TYPE_6);
|
||||
|
|
|
@ -893,13 +893,126 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
|
|||
{
|
||||
spritetype *pSource = &source->s();
|
||||
int nSource = pSource->index;
|
||||
if (pSprite == pSource)
|
||||
return 0;
|
||||
if (pXSprite->target == -1 || (nSource != pXSprite->target && Chance(pSprite->type == pSource->type ? nDamage*pDudeInfo->changeTargetKin : nDamage*pDudeInfo->changeTarget)))
|
||||
if (pSprite == pSource) return 0;
|
||||
else if (pXSprite->target == -1 || (nSource != pXSprite->target && Chance(pSprite->type == pSource->type ? nDamage*pDudeInfo->changeTargetKin : nDamage*pDudeInfo->changeTarget)))
|
||||
{
|
||||
aiSetTarget(pXSprite, nSource);
|
||||
aiActivateDude(&bloodActors[pXSprite->reference]);
|
||||
}
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap) {
|
||||
|
||||
// for enemies in patrol mode
|
||||
if (aiInPatrolState(pXSprite->aiState)) {
|
||||
|
||||
aiPatrolStop(pSprite, pSource->index, pXSprite->dudeAmbush);
|
||||
|
||||
PLAYER* pPlayer = getPlayerById(pSource->type);
|
||||
if (!pPlayer) return nDamage;
|
||||
if (powerupCheck(pPlayer, kPwUpShadowCloak)) pPlayer->pwUpTime[kPwUpShadowCloak] = 0;
|
||||
if (readyForCrit(pSource, pSprite)) {
|
||||
nDamage += aiDamageSprite(pSprite, pXSprite, pSource->index, nDmgType, nDamage * (10 - gGameOptions.nDifficulty));
|
||||
if (pXSprite->health > 0) {
|
||||
int fullHp = (pXSprite->sysData2 > 0) ? ClipRange(pXSprite->sysData2 << 4, 1, 65535) : getDudeInfo(pSprite->type)->startHealth << 4;
|
||||
if (((100 * pXSprite->health) / fullHp) <= 75) {
|
||||
cumulDamage[pSprite->extra] += nDamage << 4; // to be sure any enemy will play the recoil animation
|
||||
RecoilDude(pSprite, pXSprite);
|
||||
}
|
||||
}
|
||||
|
||||
consoleSysMsg("Player #%d does the critical damage to patrol dude #%d!", pPlayer->nPlayer + 1, pSprite->index);
|
||||
}
|
||||
|
||||
return nDamage;
|
||||
}
|
||||
|
||||
if (pSprite->type == kDudeModernCustomBurning) {
|
||||
|
||||
if (Chance(0x2000) && gDudeExtra[pSprite->extra].at0 < (int)gFrameClock) {
|
||||
playGenDudeSound(pSprite, kGenDudeSndBurning);
|
||||
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
|
||||
}
|
||||
|
||||
if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400;
|
||||
if (spriteIsUnderwater(pSprite, false)) {
|
||||
pSprite->type = kDudeModernCustom;
|
||||
pXSprite->burnTime = 0;
|
||||
pXSprite->health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before.
|
||||
aiGenDudeNewState(pSprite, &genDudeGotoW);
|
||||
}
|
||||
|
||||
return nDamage;
|
||||
|
||||
}
|
||||
|
||||
if (pSprite->type == kDudeModernCustom) {
|
||||
|
||||
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
|
||||
if (nDmgType == DAMAGE_TYPE_1) {
|
||||
|
||||
if (pXSprite->health > pDudeInfo->fleeHealth) return nDamage;
|
||||
else if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) {
|
||||
removeDudeStuff(pSprite);
|
||||
|
||||
if (pExtra->weaponType == kGenDudeWeaponKamikaze)
|
||||
doExplosion(pSprite, pXSprite->data1 - kTrapExploder);
|
||||
|
||||
if (spriteIsUnderwater(pSprite)) {
|
||||
pXSprite->health = 0;
|
||||
return nDamage;
|
||||
}
|
||||
|
||||
if (pXSprite->burnTime <= 0)
|
||||
pXSprite->burnTime = 1200;
|
||||
|
||||
if (pExtra->canBurn && pExtra->availDeaths[DAMAGE_TYPE_1] > 0) {
|
||||
|
||||
aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1);
|
||||
playGenDudeSound(pSprite, kGenDudeSndBurning);
|
||||
pSprite->type = kDudeModernCustomBurning;
|
||||
|
||||
if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation
|
||||
pSprite->pal = 0;
|
||||
|
||||
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
|
||||
actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
|
||||
gDudeExtra[pSprite->extra].at0 = (int)gFrameClock + 360;
|
||||
evKill(nSprite, 3, kCallbackFXFlameLick);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
actKillDude(nSource, pSprite, DAMAGE_TYPE_0, 65535);
|
||||
}
|
||||
|
||||
} else if (canWalk(pSprite) && !inDodge(pXSprite->aiState) && !inRecoil(pXSprite->aiState)) {
|
||||
|
||||
if (!dudeIsMelee(pXSprite)) {
|
||||
if (inIdle(pXSprite->aiState) || Chance(getDodgeChance(pSprite))) {
|
||||
if (!spriteIsUnderwater(pSprite)) {
|
||||
if (!canDuck(pSprite) || !sub_5BDA8(pSprite, 14)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL);
|
||||
else aiGenDudeNewState(pSprite, &genDudeDodgeShortD);
|
||||
|
||||
if (Chance(0x0200))
|
||||
playGenDudeSound(pSprite, kGenDudeSndGotHit);
|
||||
|
||||
} else if (sub_5BDA8(pSprite, 13)) {
|
||||
aiGenDudeNewState(pSprite, &genDudeDodgeShortW);
|
||||
}
|
||||
}
|
||||
} else if (Chance(0x0200)) {
|
||||
playGenDudeSound(pSprite, kGenDudeSndGotHit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nDamage;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nDmgType == DAMAGE_TYPE_6)
|
||||
{
|
||||
DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra];
|
||||
|
@ -985,79 +1098,6 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
|
|||
evKill(nSprite, 3, kCallbackFXFlameLick);
|
||||
}
|
||||
break;
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustomBurning:
|
||||
if (Chance(0x2000) && gDudeExtra[pSprite->extra].time < PlayClock) {
|
||||
playGenDudeSound(pSprite, kGenDudeSndBurning);
|
||||
gDudeExtra[pSprite->extra].time = PlayClock + 360;
|
||||
}
|
||||
if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400;
|
||||
if (spriteIsUnderwater(pSprite, false)) {
|
||||
pSprite->type = kDudeModernCustom;
|
||||
pXSprite->burnTime = 0;
|
||||
pXSprite->health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before.
|
||||
aiGenDudeNewState(pSprite, &genDudeGotoW);
|
||||
}
|
||||
break;
|
||||
case kDudeModernCustom: {
|
||||
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
|
||||
|
||||
if (nDmgType == DAMAGE_TYPE_1) {
|
||||
if (pXSprite->health > (unsigned)pDudeInfo->fleeHealth) break;
|
||||
else if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) {
|
||||
removeDudeStuff(pSprite);
|
||||
|
||||
if (pExtra->weaponType == kGenDudeWeaponKamikaze)
|
||||
doExplosion(pSprite, pXSprite->data1 - kTrapExploder);
|
||||
|
||||
if (spriteIsUnderwater(pSprite, false)) {
|
||||
pXSprite->health = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pXSprite->burnTime <= 0)
|
||||
pXSprite->burnTime = 1200;
|
||||
|
||||
if (pExtra->canBurn && pExtra->availDeaths[DAMAGE_TYPE_1] > 0) {
|
||||
|
||||
aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1);
|
||||
playGenDudeSound(pSprite, kGenDudeSndBurning);
|
||||
pSprite->type = kDudeModernCustomBurning;
|
||||
|
||||
if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation
|
||||
pSprite->pal = 0;
|
||||
|
||||
aiGenDudeNewState(pSprite, &genDudeBurnGoto);
|
||||
actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
|
||||
gDudeExtra[pSprite->extra].time = PlayClock + 360;
|
||||
evKill(nSprite, 3, kCallbackFXFlameLick);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
actKillDude(nSource, pSprite, DAMAGE_TYPE_0, 65535);
|
||||
}
|
||||
} else if (canWalk(pSprite) && !inDodge(pXSprite->aiState) && !inRecoil(pXSprite->aiState)) {
|
||||
if (!dudeIsMelee(pXSprite)) {
|
||||
if (inIdle(pXSprite->aiState) || Chance(getDodgeChance(pSprite))) {
|
||||
if (!spriteIsUnderwater(pSprite, false)) {
|
||||
if (!canDuck(pSprite) || !dudeIsPlayingSeq(pSprite, 14)) aiGenDudeNewState(pSprite, &genDudeDodgeShortL);
|
||||
else aiGenDudeNewState(pSprite, &genDudeDodgeShortD);
|
||||
|
||||
if (Chance(0x0200))
|
||||
playGenDudeSound(pSprite, kGenDudeSndGotHit);
|
||||
|
||||
} else if (dudeIsPlayingSeq(pSprite, 13)) {
|
||||
aiGenDudeNewState(pSprite, &genDudeDodgeShortW);
|
||||
}
|
||||
}
|
||||
} else if (Chance(0x0200)) {
|
||||
playGenDudeSound(pSprite, kGenDudeSndGotHit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case kDudeCultistBeast:
|
||||
if (pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth)
|
||||
{
|
||||
|
@ -1515,17 +1555,25 @@ void aiInitSprite(spritetype *pSprite)
|
|||
DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra];
|
||||
pDudeExtra->recoil = 0;
|
||||
pDudeExtra->time = 0;
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
int stateTimer = -1, targetMarker = -1;
|
||||
int targetX = 0, targetY = 0, targetZ = 0;
|
||||
|
||||
// dude patrol init
|
||||
if (gModernMap) {
|
||||
|
||||
// must keep it in case of loading save
|
||||
if (pXSprite->dudeFlag4 && spriRangeIsFine(pXSprite->target) && sprite[pXSprite->target].type == kMarkerPath) {
|
||||
stateTimer = pXSprite->stateTimer; targetMarker = pXSprite->target;
|
||||
targetX = pXSprite->targetX; targetY = pXSprite->targetY;
|
||||
targetZ = pXSprite->targetZ;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (pSprite->type) {
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
case kDudeModernCustom:
|
||||
aiGenDudeInitSprite(pSprite, pXSprite);
|
||||
genDudePrepare(pSprite, kGenDudePropertyAll);
|
||||
return;
|
||||
case kDudeModernCustomBurning:
|
||||
aiGenDudeInitSprite(pSprite, pXSprite);
|
||||
return;
|
||||
#endif
|
||||
case kDudeCultistTommy:
|
||||
case kDudeCultistShotgun:
|
||||
case kDudeCultistTesla:
|
||||
|
@ -1739,6 +1787,45 @@ void aiInitSprite(spritetype *pSprite)
|
|||
pSprite->flags = 15;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap) {
|
||||
|
||||
if (pSprite->type == kDudeModernCustom) {
|
||||
aiGenDudeInitSprite(pSprite, pXSprite);
|
||||
genDudePrepare(pSprite, kGenDudePropertyAll);
|
||||
}
|
||||
|
||||
if (pXSprite->dudeFlag4) {
|
||||
|
||||
// restore dude's path
|
||||
if (spriRangeIsFine(targetMarker)) {
|
||||
pXSprite->target = targetMarker;
|
||||
pXSprite->targetX = targetX;
|
||||
pXSprite->targetY = targetY;
|
||||
pXSprite->targetZ = targetZ;
|
||||
}
|
||||
|
||||
// reset target spot progress
|
||||
pXSprite->data3 = 0;
|
||||
|
||||
// make dude follow the markers
|
||||
bool uwater = spriteIsUnderwater(pSprite);
|
||||
if (stateTimer > 0) {
|
||||
if (uwater) aiPatrolState(pSprite, kAiStatePatrolWaitW);
|
||||
else if (pXSprite->unused2) aiPatrolState(pSprite, kAiStatePatrolWaitC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolWaitL);
|
||||
pXSprite->stateTimer = stateTimer; // restore state timer
|
||||
}
|
||||
else if (uwater) aiPatrolState(pSprite, kAiStatePatrolMoveW);
|
||||
else if (pXSprite->unused2) aiPatrolState(pSprite, kAiStatePatrolMoveC);
|
||||
else aiPatrolState(pSprite, kAiStatePatrolMoveL);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -251,6 +251,7 @@ void Respawn(int nSprite) // 9
|
|||
#ifdef NOONE_EXTENSIONS
|
||||
if (!gModernMap || pXSprite->sysData2 <= 0) pXSprite->health = dudeInfo[pSprite->type - kDudeBase].startHealth << 4;
|
||||
else pXSprite->health = ClipRange(pXSprite->sysData2 << 4, 1, 65535);
|
||||
|
||||
switch (pSprite->type) {
|
||||
default:
|
||||
pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist;
|
||||
|
@ -261,6 +262,12 @@ void Respawn(int nSprite) // 9
|
|||
seqSpawn(genDudeSeqStartId(pXSprite), 3, pSprite->extra, -1);
|
||||
break;
|
||||
}
|
||||
|
||||
// return dude to the patrol state
|
||||
if (gModernMap && pXSprite->dudeFlag4) {
|
||||
pXSprite->data3 = 0;
|
||||
pXSprite->target = -1;
|
||||
}
|
||||
#else
|
||||
pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist;
|
||||
pXSprite->health = getDudeInfo(nType + kDudeBase)->startHealth << 4;
|
||||
|
|
|
@ -51,7 +51,7 @@ enum
|
|||
kExplodeMax = 8,
|
||||
|
||||
kLensSize = 80,
|
||||
kViewEffectMax = 19,
|
||||
kViewEffectMax = 20,
|
||||
|
||||
kNoTile = -1,
|
||||
|
||||
|
@ -401,6 +401,14 @@ kAiStateSearch = 3,
|
|||
kAiStateChase = 4,
|
||||
kAiStateRecoil = 5,
|
||||
kAiStateAttack = 6,
|
||||
kAiStatePatrolBase = 7,
|
||||
kAiStatePatrolWaitL = kAiStatePatrolBase,
|
||||
kAiStatePatrolWaitC,
|
||||
kAiStatePatrolWaitW,
|
||||
kAiStatePatrolMoveL,
|
||||
kAiStatePatrolMoveC,
|
||||
kAiStatePatrolMoveW,
|
||||
kAiStatePatrolMax,
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -1553,7 +1553,7 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
|
|||
20,
|
||||
10240, // hear distance
|
||||
51200, // seeing distance
|
||||
kAng120, // vision periphery
|
||||
kAng90, // vision periphery
|
||||
// 0,
|
||||
618, // melee distance
|
||||
5, // flee health
|
||||
|
@ -1561,7 +1561,7 @@ DUDEINFO dudeInfo[kDudeMax-kDudeBase] =
|
|||
0x0000, // change target chance
|
||||
0x0000, // change target to kin chance
|
||||
0x8000, // alertChance
|
||||
0, // lockout
|
||||
1, // lockout
|
||||
46603, // frontSpeed
|
||||
34952, // sideSpeed
|
||||
13981, // backSpeed
|
||||
|
|
|
@ -458,7 +458,7 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
|
|||
PLAYER* pPlayer = NULL;
|
||||
if (playerRXRngIsFine(rxId))
|
||||
{
|
||||
if ((pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != nullptr)
|
||||
if ((pPlayer = getPlayerById((rxId - kChannelPlayer7) + kMaxPlayers)) != nullptr)
|
||||
trMessageSprite(pPlayer->nSprite, event);
|
||||
}
|
||||
else if (rxId == kChannelAllPlayers)
|
||||
|
@ -468,6 +468,7 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
|
|||
if ((pPlayer = getPlayerById(i)) != nullptr)
|
||||
trMessageSprite(pPlayer->nSprite, event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ kCmdCounterSector = 12,
|
|||
kCmdCallback = 20,
|
||||
kCmdRepeat = 21,
|
||||
|
||||
|
||||
kCmdSpritePush = 30,
|
||||
kCmdSpriteImpact = 31,
|
||||
kCmdSpritePickup = 32,
|
||||
|
@ -113,8 +114,20 @@ kCmdSectorExit = 43,
|
|||
kCmdWallPush = 50,
|
||||
kCmdWallImpact = 51,
|
||||
kCmdWallTouch = 52,
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
kCmdSectorMotionPause = 13, // stops motion of the sector
|
||||
kCmdSectorMotionContinue = 14, // continues motion of the sector
|
||||
kCmdModernUse = 53, // used by most of modern types
|
||||
kCmdModernPatrolOff = 54, // to manipulate dudeFlags
|
||||
kCmdModernPatrolOn = 55, // to manipulate dudeFlags
|
||||
kCmdModernDeafOff = 56, // to manipulate dudeFlags
|
||||
kCmdModernDeafOn = 57, // to manipulate dudeFlags
|
||||
kCmdModernBlindOff = 58, // to manipulate dudeFlags
|
||||
kCmdModernBlindOn = 59, // to manipulate dudeFlags
|
||||
kCmdModernAlarmOff = 60, // to manipulate dudeFlags
|
||||
kCmdModernAlarmOn = 61, // to manipulate dudeFlags
|
||||
#endif
|
||||
|
||||
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 kChannelMapModernize RX / TX
|
||||
kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapModernize RX / TX
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "actor.h"
|
||||
#include "dude.h"
|
||||
#include "player.h"
|
||||
#include "triggers.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
@ -66,6 +67,11 @@ enum
|
|||
kCondRange = 100,
|
||||
};
|
||||
|
||||
#define kPatrolStateSize 27
|
||||
#define kMaxPatrolVelocity 500000
|
||||
#define kMaxPatrolCrouchVelocity (kMaxPatrolVelocity >> 1)
|
||||
#define kMaxPatrolSpotValue 500
|
||||
|
||||
|
||||
|
||||
// modern statnums
|
||||
|
@ -83,6 +89,7 @@ kStatModernMax = 40,
|
|||
|
||||
// modern sprite types
|
||||
enum {
|
||||
kModernSlopeChanger = 16,
|
||||
kModernCustomDudeSpawn = 24,
|
||||
kModernRandomTX = 25,
|
||||
kModernSequentialTX = 26,
|
||||
|
@ -185,7 +192,12 @@ struct MISSILEINFO_EXTRA {
|
|||
struct DUDEINFO_EXTRA {
|
||||
bool flying; // used by kModernDudeTargetChanger (ai fight)
|
||||
bool melee; // used by kModernDudeTargetChanger (ai fight)
|
||||
bool annoying; // used by kModernDudeTargetChanger (ai fight)
|
||||
int idlgseqofs : 6; // used for patrol
|
||||
int mvegseqofs : 6; // used for patrol
|
||||
int idlwseqofs : 6; // used for patrol
|
||||
int mvewseqofs : 6; // used for patrol
|
||||
int idlcseqofs : 6; // used for patrol
|
||||
int mvecseqofs : 6; // used for patrol
|
||||
};
|
||||
|
||||
struct TRPLAYERCTRL { // this one for controlling the player using triggers (movement speed, jumps and other stuff)
|
||||
|
@ -228,6 +240,7 @@ extern short gSightSpritesCount;
|
|||
extern short gPhysSpritesCount;
|
||||
extern short gImpactSpritesCount;
|
||||
extern short gTrackingCondsCount;
|
||||
extern AISTATE genPatrolStates[kPatrolStateSize];
|
||||
|
||||
// - FUNCTIONS ------------------------------------------------------------------
|
||||
bool nnExtEraseModernStuff(spritetype* pSprite, XSPRITE* pXSprite);
|
||||
|
@ -271,15 +284,16 @@ spritetype* aiFightGetTargetInRange(spritetype* pSprite, int minDist, int maxDis
|
|||
spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite);
|
||||
spritetype* aiFightGetMateTargets(XSPRITE* pXSprite);
|
||||
// ------------------------------------------------------------------------- //
|
||||
void useSlopeChanger(XSPRITE* pXSource, int objType, int objIndex);
|
||||
void useSectorWindGen(XSPRITE* pXSource, sectortype* pSector);
|
||||
void useEffectGen(XSPRITE* pXSource, spritetype* pSprite);
|
||||
void useSeqSpawnerGen(XSPRITE* pXSource, int objType, int index);
|
||||
void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite);
|
||||
void damageSprites(XSPRITE* pXSource, spritetype* pSprite);
|
||||
void useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite);
|
||||
void useObjResizer(XSPRITE* pXSource, short objType, int objIndex);
|
||||
void useRandomItemGen(spritetype* pSource, XSPRITE* pXSource);
|
||||
void useUniMissileGen(int, int nXSprite);
|
||||
void useSoundGen(spritetype* pSource, XSPRITE* pXSource);
|
||||
void useSoundGen(XSPRITE* pXSource, spritetype* pSprite);
|
||||
void useIncDecGen(XSPRITE* pXSource, short objType, int objIndex);
|
||||
void useDataChanger(XSPRITE* pXSource, int objType, int objIndex);
|
||||
void useSectorLigthChanger(XSPRITE* pXSource, XSECTOR* pXSector);
|
||||
|
@ -305,6 +319,7 @@ void trPlayerCtrlUsePackItem(XSPRITE* pXSource, PLAYER* pPlayer, int evCmd);
|
|||
// ------------------------------------------------------------------------- //
|
||||
void modernTypeTrigger(int type, int nDest, EVENT event);
|
||||
char modernTypeSetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
|
||||
bool modernTypeOperateSector(int nSector, sectortype* pSector, XSECTOR* pXSector, EVENT event);
|
||||
bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite, EVENT event);
|
||||
bool modernTypeOperateWall(int nWall, walltype* pWall, XWALL* pXWall, EVENT event);
|
||||
void modernTypeSendCommand(int nSprite, int channel, COMMAND_ID command);
|
||||
|
@ -355,6 +370,20 @@ XSPRITE* evrListRedirectors(int objType, int objXIndex, XSPRITE* pXRedir, int* t
|
|||
XSPRITE* evrIsRedirector(int nSprite);
|
||||
int listTx(XSPRITE* pXRedir, int tx);
|
||||
void seqSpawnerOffSameTx(XSPRITE* pXSource);
|
||||
// ------------------------------------------------------------------------- //
|
||||
void aiPatrolSetMarker(spritetype* pSprite, XSPRITE* pXSprite);
|
||||
void aiPatrolThink(spritetype* pSprite, XSPRITE* pXSprite);
|
||||
void aiPatrolStop(spritetype* pSprite, int target, bool alarm = false);
|
||||
void aiPatrolAlarm(spritetype* pSprite, bool chain);
|
||||
void aiPatrolState(spritetype* pSprite, int state);
|
||||
void aiPatrolMove(spritetype* pSprite, XSPRITE* pXSprite);
|
||||
int aiPatrolMarkerBusy(int nExcept, int nMarker);
|
||||
bool aiPatrolMarkerReached(spritetype* pSprite, XSPRITE* pXSprite);
|
||||
AISTATE* aiInPatrolState(AISTATE* pAiState);
|
||||
// ------------------------------------------------------------------------- //
|
||||
bool readyForCrit(spritetype* pHunter, spritetype* pVictim);
|
||||
int sectorInMotion(int nSector);
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// This file provides modern features for mappers.
|
||||
|
|
|
@ -2017,6 +2017,32 @@ int playerDamageSprite(DBloodActor* source, PLAYER *pPlayer, DAMAGE_TYPE nDamage
|
|||
}
|
||||
FragPlayer(pPlayer, nSource);
|
||||
trTriggerSprite(nSprite, pXSprite, kCmdOff);
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
// allow drop items and keys in multiplayer
|
||||
if (gModernMap && gGameOptions.nGameType != 0 && pPlayer->pXSprite->health <= 0) {
|
||||
|
||||
spritetype* pItem = NULL;
|
||||
if (pPlayer->pXSprite->dropMsg && (pItem = actDropItem(pPlayer->pSprite, pPlayer->pXSprite->dropMsg)) != NULL)
|
||||
evPost(pItem->index, OBJ_SPRITE, 500, kCallbackRemove);
|
||||
|
||||
if (pPlayer->pXSprite->key) {
|
||||
|
||||
int i; // if all players have this key, don't drop it
|
||||
for (i = connecthead; i >= 0; i = connectpoint2[i]) {
|
||||
if (!gPlayer[i].hasKey[pPlayer->pXSprite->key])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0 && (pItem = actDropKey(pPlayer->pSprite, (pPlayer->pXSprite->key + kItemKeyBase) - 1)) != NULL)
|
||||
evPost(pItem->index, OBJ_SPRITE, 500, kCallbackRemove);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
assert(getSequence(pDudeInfo->seqStartID + nDeathSeqID) != NULL);
|
||||
seqSpawn(pDudeInfo->seqStartID+nDeathSeqID, 3, nXSprite, nKneelingPlayer);
|
||||
|
|
|
@ -132,26 +132,7 @@ char SetSectorState(int nSector, XSECTOR *pXSector, int nState)
|
|||
}
|
||||
|
||||
int gBusyCount = 0;
|
||||
|
||||
enum BUSYID {
|
||||
BUSYID_0 = 0,
|
||||
BUSYID_1,
|
||||
BUSYID_2,
|
||||
BUSYID_3,
|
||||
BUSYID_4,
|
||||
BUSYID_5,
|
||||
BUSYID_6,
|
||||
BUSYID_7,
|
||||
};
|
||||
|
||||
struct BUSY {
|
||||
int index;
|
||||
int delta;
|
||||
int busy;
|
||||
int type;
|
||||
};
|
||||
|
||||
BUSY gBusy[128];
|
||||
BUSY gBusy[];
|
||||
|
||||
void AddBusy(int a1, BUSYID a2, int nDelta)
|
||||
{
|
||||
|
@ -164,7 +145,7 @@ void AddBusy(int a1, BUSYID a2, int nDelta)
|
|||
}
|
||||
if (i == gBusyCount)
|
||||
{
|
||||
if (gBusyCount == 128)
|
||||
if (gBusyCount == kMaxBusyCount)
|
||||
return;
|
||||
gBusy[i].index = a1;
|
||||
gBusy[i].type = a2;
|
||||
|
@ -1544,22 +1525,10 @@ void OperateSector(unsigned int nSector, XSECTOR *pXSector, EVENT event)
|
|||
sectortype *pSector = §or[nSector];
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap) {
|
||||
switch (pSector->type) {
|
||||
// reset counter sector state and make it work again after unlock, so it can be used again.
|
||||
case kSectorCounter:
|
||||
switch (event.cmd) {
|
||||
case kCmdUnlock:
|
||||
case kCmdToggleLock:
|
||||
if (pXSector->locked != 1) break;
|
||||
SetSectorState(nSector, pXSector, 0);
|
||||
evPost(nSector, 6, 0, kCallbackCounterCheck);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gModernMap && modernTypeOperateSector(nSector, pSector, pXSector, event))
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch (event.cmd) {
|
||||
case kCmdLock:
|
||||
pXSector->locked = 1;
|
||||
|
@ -1583,6 +1552,9 @@ void OperateSector(unsigned int nSector, XSECTOR *pXSector, EVENT event)
|
|||
pXSector->stopOff = 1;
|
||||
break;
|
||||
default:
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap && pXSector->unused1) break;
|
||||
#endif
|
||||
switch (pSector->type) {
|
||||
case kSectorZMotionSprite:
|
||||
OperateDoor(nSector, pXSector, event, BUSYID_1);
|
||||
|
@ -1992,9 +1964,15 @@ void trProcessBusy(void)
|
|||
memset(velCeil, 0, sizeof(velCeil));
|
||||
for (int i = gBusyCount-1; i >= 0; i--)
|
||||
{
|
||||
int oldBusy = gBusy[i].busy;
|
||||
gBusy[i].busy = ClipRange(oldBusy+gBusy[i].delta*4, 0, 65536);
|
||||
int nStatus = gBusyProc[gBusy[i].type](gBusy[i].index, gBusy[i].busy);
|
||||
int nStatus;
|
||||
int oldBusy = gBusy[i].at8;
|
||||
gBusy[i].at8 = ClipRange(oldBusy+gBusy[i].at4*4, 0, 65536);
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (!gModernMap || !xsector[sector[gBusy[i].at0].extra].unused1) nStatus = gBusyProc[gBusy[i].atc](gBusy[i].at0, gBusy[i].at8);
|
||||
else nStatus = 3; // allow to pause/continue motion for sectors any time by sending special command
|
||||
#else
|
||||
nStatus = gBusyProc[gBusy[i].atc](gBusy[i].at0, gBusy[i].at8);
|
||||
#endif
|
||||
switch (nStatus) {
|
||||
case 1:
|
||||
gBusy[i].busy = oldBusy;
|
||||
|
|
|
@ -29,7 +29,31 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "dude.h"
|
||||
#include "player.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
enum BUSYID {
|
||||
BUSYID_0 = 0,
|
||||
BUSYID_1,
|
||||
BUSYID_2,
|
||||
BUSYID_3,
|
||||
BUSYID_4,
|
||||
BUSYID_5,
|
||||
BUSYID_6,
|
||||
BUSYID_7,
|
||||
};
|
||||
|
||||
#define kMaxBusyCount 128
|
||||
struct BUSY {
|
||||
int index;
|
||||
int delta;
|
||||
int busy;
|
||||
/* int at0;
|
||||
int at4;
|
||||
int at8;*/
|
||||
BUSYID atc;
|
||||
};
|
||||
|
||||
extern BUSY gBusy[kMaxBusyCount];
|
||||
extern int gBusyCount;
|
||||
|
||||
void trTriggerSector(unsigned int nSector, XSECTOR *pXSector, int command);
|
||||
void trMessageSector(unsigned int nSector, EVENT event);
|
||||
void trTriggerWall(unsigned int nWall, XWALL *pXWall, int command);
|
||||
|
@ -42,6 +66,9 @@ void trInit(void);
|
|||
void trTextOver(int nId);
|
||||
char SetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
|
||||
char SetWallState(int nWall, XWALL* pXWall, int nState);
|
||||
char SetSectorState(int nSector, XSECTOR* pXSector, int nState);
|
||||
void TeleFrag(int nKiller, int nSector);
|
||||
void SectorStartSound(int nSector, int nState);
|
||||
void SectorEndSound(int nSector, int nState);
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -95,6 +95,7 @@ enum VIEW_EFFECT {
|
|||
VIEW_EFFECT_16,
|
||||
VIEW_EFFECT_17,
|
||||
VIEW_EFFECT_18,
|
||||
kViewEffectSpotProgress,
|
||||
};
|
||||
|
||||
enum VIEWPOS {
|
||||
|
|
Loading…
Reference in a new issue