Refactor of NOONE_EXTESNIONS:

All functions and definitions was moved to nnexts.h and nnexts.cpp files
to minimize ifdefs and generally make code more clear

# Conflicts:
#	GNUmakefile
#	platform/Windows/nblood.vcxproj
#	platform/Windows/nblood.vcxproj.filters
#	platform/Windows/props/build_common.props
#	source/blood/src/actor.cpp
#	source/blood/src/ai.h
#	source/blood/src/aiunicult.cpp
#	source/blood/src/blood.cpp
#	source/blood/src/db.cpp
#	source/blood/src/eventq.cpp
#	source/blood/src/gameutil.cpp
#	source/blood/src/gameutil.h
#	source/blood/src/loadsave.cpp
#	source/blood/src/player.cpp
#	source/blood/src/player.h
#	source/blood/src/triggers.h
#	source/blood/src/view.cpp
This commit is contained in:
NoOneBlood 2020-02-07 22:47:43 +03:00 committed by Christoph Oelckers
parent 8ee516086b
commit e79a693313
33 changed files with 4457 additions and 4476 deletions

File diff suppressed because it is too large Load Diff

View File

@ -266,65 +266,6 @@ void actPostProcess(void);
void MakeSplash(spritetype *pSprite, XSPRITE *pXSprite);
void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite);
#ifdef NOONE_EXTENSIONS
spritetype* DropRandomPickupObject(spritetype* pSprite, short prevItem);
spritetype* spawnRandomDude(spritetype* pSprite);
int GetDataVal(spritetype* pSprite, int data);
int GetRandDataVal(XSPRITE* pXSprite, int randType);
bool sfxPlayMissileSound(spritetype* pSprite, int missileId);
bool sfxPlayVectorSound(spritetype* pSprite, int vectorId);
spritetype* actSpawnCustomDude(spritetype* pSprite, int nDist);
int getSpriteMassBySize(spritetype* pSprite);
bool ceilIsTooLow(spritetype* pSprite);
int isDebris(int nSprite);
int debrisGetFreeIndex(void);
void debrisMove(int listIndex);
void debrisConcuss(int nOwner, int listIndex, int x, int y, int z, int dmg);
bool isImmune(spritetype* pSprite, int dmgType, int minScale = 16);
enum {
kRandomizeItem = 0,
kRandomizeDude = 1,
kRandomizeTX = 2,
};
// sprite mass info for getSpriteMassBySize();
struct SPRITEMASS {
int seqId;
short picnum; // mainly needs for moving debris
short xrepeat;
short yrepeat;
short clipdist; // mass multiplier
int mass;
short airVel; // mainly needs for moving debris
int fraction; // mainly needs for moving debris
};
struct THINGINFO_EXTRA {
bool allowThrow; // indicates if kDudeModernCustom can throw it
};
struct VECTORINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
};
struct MISSILEINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
bool dmgType[kDamageMax]; // list of damages types missile can use
};
extern THINGINFO_EXTRA gThingInfoExtra[kThingMax];
extern VECTORINFO_EXTRA gVectorInfoExtra[kVectorMax];
extern MISSILEINFO_EXTRA gMissileInfoExtra[kMissileMax];
extern SPRITEMASS gSpriteMass[kMaxXSprites];
extern short gProxySpritesList[kMaxSuperXSprites];
extern short gSightSpritesList[kMaxSuperXSprites];
extern short gPhysSpritesList[kMaxSuperXSprites];
extern short gProxySpritesCount;
extern short gSightSpritesCount;
extern short gPhysSpritesCount;
#endif
extern int DudeDifficulty[];
END_BLD_NS

View File

@ -66,6 +66,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "trig.h"
#include "triggers.h"
#include "view.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -77,19 +78,6 @@ AISTATE genIdle = {kAiStateGenIdle, 0, -1, 0, NULL, NULL, NULL, NULL };
AISTATE genRecoil = {kAiStateRecoil, 5, -1, 20, NULL, NULL, NULL, &genIdle };
int dword_138BB0[5] = {0x2000, 0x4000, 0x8000, 0xa000, 0xe000};
#ifdef NOONE_EXTENSIONS
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite) {
switch (pSprite->type) {
case kDudeModernCustom:
case kDudeModernCustomBurning:
aiGenDudeNewState(pSprite, &genIdle);
break;
default:
aiNewState(pSprite, pXSprite, &genIdle);
break;
}
}
#endif
bool sub_5BDA8(spritetype *pSprite, int nSeq)
{
@ -133,6 +121,20 @@ void aiNewState(spritetype *pSprite, XSPRITE *pXSprite, AISTATE *pAIState)
pAIState->enterFunc(pSprite, pXSprite);
}
bool isUmmune(spritetype* pSprite, int dmgType, int minScale) {
if (dmgType >= kDmgFall && dmgType < kDmgMax && pSprite->extra >= 0 && xsprite[pSprite->extra].locked != 1) {
if (pSprite->type >= kThingBase && pSprite->type < kThingMax)
return (thingInfo[pSprite->type - kThingBase].dmgControl[dmgType] <= minScale);
else if (IsDudeSprite(pSprite)) {
if (IsPlayerSprite(pSprite)) return (gPlayer[pSprite->type - kDudePlayer1].damageControl[dmgType] <= minScale);
else return (dudeInfo[pSprite->type - kDudeBase].at70[dmgType] <= minScale);
}
}
return true;
}
bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
{
int top, bottom;
@ -166,26 +168,8 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
Underwater = 1;
if (pXSector->Depth)
Depth = 1;
if (sector[nSector].type == kSectorDamage || pXSector->damageType > 0) {
// a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used.
// It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like
// in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as
// i don't think it will broke something in game.
switch (pSprite->type) {
case kDudeCerberusTwoHead: // Cerberus
case kDudeCerberusOneHead: // 1 Head Cerberus
if (VanillaMode()
#ifdef NOONE_EXTENSIONS
|| !isImmune(pSprite, pXSector->damageType)
#endif
)
Crusher = 1;
break;
default:
Crusher = 1;
break;
}
}
if (sector[nSector].type == kSectorDamage || pXSector->damageType > 0)
Crusher = 1;
}
int nUpper = gUpperLink[nSector];
int nLower = gLowerLink[nSector];
@ -222,6 +206,14 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
if (Underwater)
return true;
break;
case kDudeCerberusTwoHead:
case kDudeCerberusOneHead:
// by NoOne: a quick fix for Cerberus spinning in E3M7-like maps, where damage sectors is used.
// It makes ignore danger if enemy immune to N damageType. As result Cerberus start acting like
// in Blood 1.0 so it can move normally to player. It's up to you for adding rest of enemies here as
// i don't think it will broke something in game.
if (!VanillaMode() && Crusher && isUmmune(pSprite, pXSector->damageType, 16)) return true;
fallthrough__;
case kDudeZombieButcher:
case kDudeSpiderBrown:
case kDudeSpiderRed:
@ -229,7 +221,6 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
case kDudeSpiderMother:
case kDudeHellHound:
case kDudeRat:
case kDudeCerberusTwoHead:
case kDudeInnocent:
if (Crusher)
return false;
@ -241,7 +232,7 @@ bool CanMove(spritetype *pSprite, int a2, int nAngle, int nRange)
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
case kDudeModernCustomBurning:
if ((Crusher && !isImmune(pSprite, pXSector->damageType)) || ((Water || Underwater) && !canSwim(pSprite))) return false;
if ((Crusher && !nnExtIsUmmune(pSprite, pXSector->damageType)) || ((Water || Underwater) && !canSwim(pSprite))) return false;
return true;
fallthrough__;
#endif
@ -285,8 +276,8 @@ void aiChooseDirection(spritetype *pSprite, XSPRITE *pXSprite, int a3)
pXSprite->goalAng = pSprite->ang;
else if (CanMove(pSprite, pXSprite->target, pSprite->ang-v8, vsi))
pXSprite->goalAng = pSprite->ang-v8;
else if (pSprite->flags&2)
pXSprite->goalAng = pSprite->ang+341;
//else if (pSprite->flags&2)
//pXSprite->goalAng = pSprite->ang+341;
else // Weird..
pXSprite->goalAng = pSprite->ang+341;
if (Chance(0x8000))
@ -1478,20 +1469,32 @@ void aiProcessDudes(void) {
XSPRITE *pXSprite = &xsprite[nXSprite]; DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type);
if (IsPlayerSprite(pSprite) || pXSprite->health == 0) continue;
pXSprite->stateTimer = ClipLow(pXSprite->stateTimer-4, 0);
switch (pSprite->type){
if (pXSprite->aiState->moveFunc)
pXSprite->aiState->moveFunc(pSprite, pXSprite);
if (pXSprite->aiState->thinkFunc && (gFrame & 3) == (nSprite & 3))
pXSprite->aiState->thinkFunc(pSprite, pXSprite);
switch (pSprite->type) {
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
case kDudeModernCustomBurning:
genDudeProcess(pSprite, pXSprite);
case kDudeModernCustomBurning: {
GENDUDEEXTRA* pExtra = &gGenDudeExtra[pSprite->index];
if (pExtra->slaveCount > 0) updateTargetOfSlaves(pSprite);
if (pExtra->nLifeLeech >= 0) updateTargetOfLeech(pSprite);
if (pXSprite->stateTimer == 0 && pXSprite->aiState->nextState
&& (pXSprite->aiState->stateTicks > 0 || seqGetStatus(3, pSprite->extra) < 0)) {
aiGenDudeNewState(pSprite, pXSprite->aiState->nextState);
}
int hinder = ((pExtra->isMelee) ? 25 : 5) << 4;
if (pXSprite->health <= 0 || hinder > cumulDamage[pSprite->extra]) break;
pXSprite->data3 = cumulDamage[pSprite->extra];
RecoilDude(pSprite, pXSprite);
break;
}
#endif
default:
if (pXSprite->aiState->moveFunc)
pXSprite->aiState->moveFunc(pSprite, pXSprite);
if (pXSprite->aiState->thinkFunc && (gFrame & 3) == (nSprite & 3))
pXSprite->aiState->thinkFunc(pSprite, pXSprite);
if (pXSprite->stateTimer == 0 && pXSprite->aiState->nextState) {
if (pXSprite->aiState->stateTicks > 0)
aiNewState(pSprite, pXSprite, pXSprite->aiState->nextState);

View File

@ -41,6 +41,8 @@ struct AISTATE {
AISTATE *nextState;
};
extern AISTATE aiState[];
extern AISTATE genIdle;
extern AISTATE genRecoil;
enum AI_SFX_PRIORITY {
AI_SFX_PRIORITY_0 = 0,
@ -106,9 +108,4 @@ void aiInit(void);
void aiInitSprite(spritetype *pSprite);
bool CanMove(spritetype* pSprite, int a2, int nAngle, int nRange);
void RecoilDude(spritetype* pSprite, XSPRITE* pXSprite);
#ifdef NOONE_EXTENSIONS
// this function required for kModernDudeTargetChanger
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite);
#endif
END_BLD_NS

View File

@ -40,6 +40,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "seq.h"
#include "sfx.h"
#include "trig.h"
#include "nnexts.h"
BEGIN_BLD_NS

View File

@ -42,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "seq.h"
#include "sfx.h"
#include "trig.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -209,11 +210,19 @@ static void BlastSSeqCallback(int, int nXSprite)
}
}
}
if (IsPlayerSprite(pTarget) || !VanillaMode()) // By NoOne: allow to fire missile in non-player targets
{
actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
}
#ifdef NOONE_EXTENSIONS
// allow to fire missile in non-player targets
if (IsPlayerSprite(pTarget) || gModernMap) {
actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
}
#else
if (IsPlayerSprite(pTarget)) {
actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
}
#endif
}
static void ThrowSSeqCallback(int, int nXSprite)

View File

@ -42,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "seq.h"
#include "sfx.h"
#include "trig.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -192,11 +193,18 @@ static void BlastSeqCallback(int, int nXSprite)
}
}
}
if (IsPlayerSprite(pTarget) || !VanillaMode()) // By NoOne: allow fire missile in non-player targets if not a demo
{
sfxPlay3DSound(pSprite, 489, 0, 0);
actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
}
#ifdef NOONE_EXTENSIONS
// allow fire missile in non-player targets if not a demo
if (IsPlayerSprite(pTarget) || gModernMap) {
sfxPlay3DSound(pSprite, 489, 0, 0);
actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
}
#else
if (IsPlayerSprite(pTarget)) {
sfxPlay3DSound(pSprite, 489, 0, 0);
actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
}
#endif
}
static void thinkTarget(spritetype *pSprite, XSPRITE *pXSprite)

View File

@ -42,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "seq.h"
#include "sfx.h"
#include "trig.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -82,8 +83,13 @@ static void BiteSeqCallback(int, int nXSprite)
return;
}
spritetype *pTarget = &sprite[pXSprite->target];
if (IsPlayerSprite(pTarget) || !VanillaMode()) // allow to hit non-player targets if not a demo
actFireVector(pSprite, 0, 0, dx, dy, pTarget->z-pSprite->z, VECTOR_TYPE_15);
#ifdef NOONE_EXTENSIONS
if (IsPlayerSprite(pTarget) || gModernMap) // allow to hit non-player targets
actFireVector(pSprite, 0, 0, dx, dy, pTarget->z - pSprite->z, VECTOR_TYPE_15);
#else
if (IsPlayerSprite(pTarget))
actFireVector(pSprite, 0, 0, dx, dy, pTarget->z - pSprite->z, VECTOR_TYPE_15);
#endif
}
static void BurnSeqCallback(int, int nXSprite)

View File

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "ns.h" // Must come before everything else!
#include "common_game.h"
#include "nnexts.h"
#ifdef NOONE_EXTENSIONS
#include "compat.h"
#include "build.h"
@ -134,7 +135,7 @@ GENDUDESND gCustomDudeSnd[] = {
GENDUDEEXTRA gGenDudeExtra[kMaxSprites];
static void forcePunch(spritetype* pSprite, XSPRITE* pXSprite) {
static void forcePunch(spritetype* pSprite, XSPRITE*) {
if (gGenDudeExtra[pSprite->index].forcePunch && seqGetStatus(3, pSprite->extra) == -1)
punchCallback(0,pSprite->extra);
}
@ -172,29 +173,9 @@ bool genDudeAdjustSlope(spritetype* pSprite, XSPRITE* pXSprite, int dist, int we
}
void genDudeProcess(spritetype* pSprite, XSPRITE* pXSprite) {
GENDUDEEXTRA* pExtra = &gGenDudeExtra[pSprite->index];
if (pExtra->slaveCount > 0)
updateTargetOfSlaves(pSprite);
if (pExtra->nLifeLeech >= 0)
updateTargetOfLeech(pSprite);
if (pXSprite->aiState->moveFunc)
pXSprite->aiState->moveFunc(pSprite, pXSprite);
if (pXSprite->aiState->thinkFunc && (gFrame & 3) == (pSprite->index & 3))
pXSprite->aiState->thinkFunc(pSprite, pXSprite);
if (pXSprite->stateTimer == 0 && pXSprite->aiState->nextState && (pXSprite->aiState->stateTicks > 0 || seqGetStatus(3, pSprite->extra) < 0))
aiGenDudeNewState(pSprite, pXSprite->aiState->nextState);
int hinder = ((pExtra->isMelee) ? 25 : 5) << 4;
if (pXSprite->health > 0 && hinder <= cumulDamage[pSprite->extra]) {
pXSprite->data3 = cumulDamage[pSprite->extra];
RecoilDude(pSprite, pXSprite);
}
GENDUDEEXTRA* genDudeExtra(spritetype* pGenDude) {
dassert(spriRangeIsFine(pGenDude->index));
return &gGenDudeExtra[pGenDude->index];
}
void genDudeUpdate(spritetype* pSprite) {
@ -343,7 +324,7 @@ static void ThrowThing(int nXIndex, bool impact) {
if ((pThing = actFireThing(pSprite, 0, 0, (dz / 128) - zThrow, curWeapon, divscale(dist / 540, 120, 23))) == NULL) return;
else if (pThinkInfo->picnum < 0 && pThing->type != kModernThingThrowableRock) pThing->picnum = 0;
pThing->owner = pSprite->xvel;
pThing->owner = pSprite->index;
switch (curWeapon) {
case kThingNapalmBall:
@ -390,19 +371,19 @@ static void ThrowThing(int nXIndex, bool impact) {
else pXThing->data3 = Random(10);
pThing->cstat &= ~CSTAT_SPRITE_BLOCK;
pThing->pal = 6;
pXThing->target = pTarget->xvel;
pXThing->target = pTarget->index;
pXThing->Proximity = true;
pXThing->stateTimer = 1;
gGenDudeExtra[pSprite->index].nLifeLeech = pThing->index;
evPost(pThing->xvel, 3, 80, kCallbackLeechStateTimer);
evPost(pThing->index, 3, 80, kCallbackLeechStateTimer);
return;
}
if (impact == true && dist <= 7680) xsprite[pThing->extra].Impact = true;
else {
xsprite[pThing->extra].Impact = false;
evPost(pThing->xvel, 3, 120 * Random(2) + 120, kCmdOn);
evPost(pThing->index, 3, 120 * Random(2) + 120, kCmdOn);
}
}
@ -549,7 +530,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
}
XSPRITE* pXLeech = &xsprite[pLeech->extra];
int ldist = getTargetDist(pTarget, pDudeInfo, pLeech);
int ldist = aiFightGetTargetDist(pTarget, pDudeInfo, pLeech);
if (ldist > 3 || !cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum,
pLeech->x, pLeech->y, pLeech->z, pLeech->sectnum) || pXLeech->target == -1) {
@ -672,9 +653,9 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
} else if (weaponType == kGenDudeWeaponKamikaze) {
int nType = curWeapon - kTrapExploder; EXPLOSION* pExpl = &explodeInfo[nType];
if (CheckProximity(pSprite, pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum, pExpl->radius >> 1)) {
xvel[pSprite->xvel] = zvel[pSprite->xvel] = yvel[pSprite->xvel] = 0;
xvel[pSprite->index] = zvel[pSprite->index] = yvel[pSprite->index] = 0;
if (doExplosion(pSprite, nType) && pXSprite->health > 0)
actDamageSprite(pSprite->xvel, pSprite, DAMAGE_TYPE_3, 65535);
actDamageSprite(pSprite->index, pSprite, DAMAGE_TYPE_3, 65535);
}
return;
}
@ -786,7 +767,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
VectorScan(pSprite, 0, 0, Cos(pSprite->ang) >> 16, Sin(pSprite->ang) >> 16, gDudeSlope[pSprite->extra], dist, 1);
if (pXSprite->target == gHitInfo.hitsprite) break;
bool immune = isImmune(pHSprite, gVectorData[curWeapon].dmgType);
bool immune = nnExtIsUmmune(pHSprite, gVectorData[curWeapon].dmgType);
if (!(pXHSprite != NULL && (!immune || (immune && pHSprite->statnum == kStatThing && pXHSprite->Vector)) && !pXHSprite->locked)) {
if ((approxDist(gHitInfo.hitx - pSprite->x, gHitInfo.hity - pSprite->y) <= 1500 && !blck)
@ -872,7 +853,7 @@ static void thinkChase( spritetype* pSprite, XSPRITE* pXSprite ) {
else if (hit == 3 && (failed = (pHSprite->statnum != kStatThing || pXHSprite == NULL || pXHSprite->locked)) == false) {
// check also for damage resistance (all possible damages missile can use)
for (int i = 0; i < kDmgMax; i++) {
if (gMissileInfoExtra[curWeapon - kMissileBase].dmgType[i] && (failed = isImmune(pHSprite, i)) == false)
if (gMissileInfoExtra[curWeapon - kMissileBase].dmgType[i] && (failed = nnExtIsUmmune(pHSprite, i)) == false)
break;
}
}
@ -1036,8 +1017,8 @@ void aiGenDudeMoveForward(spritetype* pSprite, XSPRITE* pXSprite ) {
int cos = Cos(pSprite->ang);
int frontSpeed = gGenDudeExtra[pSprite->index].moveSpeed;
xvel[pSprite->xvel] += mulscale(cos, frontSpeed, 30);
yvel[pSprite->xvel] += mulscale(sin, frontSpeed, 30);
xvel[pSprite->index] += mulscale(cos, frontSpeed, 30);
yvel[pSprite->index] += mulscale(sin, frontSpeed, 30);
}
}
@ -1181,7 +1162,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode) {
// If no success in getting random snd, get first existing one
if (gotSnd == false) {
int maxSndId = sndId + rand;
while (sndId++ <= maxSndId) {
while (sndId++ < maxSndId) {
if (!soundEngine->FindSoundByResID(sndId)) continue;
gotSnd = true;
break;
@ -1213,13 +1194,13 @@ spritetype* leechIsDropped(spritetype* pSprite) {
void removeDudeStuff(spritetype* pSprite) {
for (short nSprite = headspritestat[kStatThing]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (sprite[nSprite].owner != pSprite->xvel) continue;
if (sprite[nSprite].owner != pSprite->index) continue;
switch (sprite[nSprite].type) {
case kThingArmedProxBomb:
case kThingArmedRemoteBomb:
case kModernThingTNTProx:
sprite[nSprite].type = kSpriteDecoration;
actPostSprite(sprite[nSprite].xvel, kStatFree);
actPostSprite(sprite[nSprite].index, kStatFree);
break;
case kModernThingEnemyLifeLeech:
killDudeLeech(&sprite[nSprite]);
@ -1228,7 +1209,7 @@ void removeDudeStuff(spritetype* pSprite) {
}
for (short nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite]) {
if (sprite[nSprite].owner != pSprite->xvel) continue;
if (sprite[nSprite].owner != pSprite->index) continue;
actDamageSprite(sprite[nSprite].owner, &sprite[nSprite], (DAMAGE_TYPE) 0, 65535);
}
}
@ -1558,7 +1539,7 @@ int getDodgeChance(spritetype* pSprite) {
void dudeLeechOperate(spritetype* pSprite, XSPRITE* pXSprite, EVENT event)
{
if (event.cmd == kCmdOff) {
actPostSprite(pSprite->xvel, kStatFree);
actPostSprite(pSprite->index, kStatFree);
return;
}
@ -1641,6 +1622,198 @@ bool doExplosion(spritetype* pSprite, int nType) {
return true;
}
// this function allows to spawn new custom dude and inherit spawner settings,
// so custom dude can have different weapons, hp and so on...
spritetype* genDudeSpawn(spritetype* pSprite, int nDist) {
spritetype* pSource = pSprite; XSPRITE* pXSource = &xsprite[pSource->extra];
spritetype* pDude = actSpawnSprite(pSprite, 6); XSPRITE* pXDude = &xsprite[pDude->extra];
int x, y, z = pSprite->z, nAngle = pSprite->ang, nType = kDudeModernCustom;
if (nDist > 0) {
x = pSprite->x + mulscale30r(Cos(nAngle), nDist);
y = pSprite->y + mulscale30r(Sin(nAngle), nDist);
} else {
x = pSprite->x;
y = pSprite->y;
}
pDude->type = nType; pDude->ang = nAngle;
vec3_t pos = { x, y, z }; setsprite(pDude->index, &pos);
pDude->cstat |= 0x1101; pDude->clipdist = dudeInfo[nType - kDudeBase].clipdist;
// inherit weapon, seq and sound settings.
pXDude->data1 = pXSource->data1;
pXDude->data2 = pXSource->data2;
pXDude->sysData1 = pXSource->data3; // move sndStartId from data3 to sysData1
pXDude->data3 = 0;
// spawn seq
seqSpawn(genDudeSeqStartId(pXDude), 3, pDude->extra, -1);
// inherit movement speed.
pXDude->busyTime = pXSource->busyTime;
// inherit clipdist?
if (pSource->clipdist > 0) pDude->clipdist = pSource->clipdist;
// inherit custom hp settings
if (pXSource->data4 <= 0) pXDude->health = dudeInfo[nType - kDudeBase].startHealth << 4;
else pXDude->health = ClipRange(pXSource->data4 << 4, 1, 65535);
if (pSource->flags & kModernTypeFlag1) {
switch (pSource->type) {
case kModernCustomDudeSpawn:
//inherit pal?
if (pDude->pal <= 0) pDude->pal = pSource->pal;
// inherit spawn sprite trigger settings, so designer can count monsters.
pXDude->txID = pXSource->txID;
pXDude->command = pXSource->command;
pXDude->triggerOn = pXSource->triggerOn;
pXDude->triggerOff = pXSource->triggerOff;
// inherit drop items
pXDude->dropMsg = pXSource->dropMsg;
// inherit required key so it can be dropped
pXDude->key = pXSource->key;
// inherit dude flags
pXDude->dudeDeaf = pXSource->dudeDeaf;
pXDude->dudeGuard = pXSource->dudeGuard;
pXDude->dudeAmbush = pXSource->dudeAmbush;
pXDude->dudeFlag4 = pXSource->dudeFlag4;
break;
}
}
// inherit sprite size (useful for seqs with zero repeats)
if (pSource->flags & kModernTypeFlag2) {
pDude->xrepeat = pSource->xrepeat;
pDude->yrepeat = pSource->yrepeat;
}
aiInitSprite(pDude);
return pDude;
}
void genDudeTransform(spritetype* pSprite) {
if (!(pSprite->extra >= 0 && pSprite->extra < kMaxXSprites)) {
consoleSysMsg("pSprite->extra >= 0 && pSprite->extra < kMaxXSprites");
return;
}
XSPRITE* pXSprite = &xsprite[pSprite->extra];
XSPRITE* pXIncarnation = getNextIncarnation(pXSprite);
if (pXIncarnation == NULL) {
if (pXSprite->sysData1 == kGenDudeTransformStatus) pXSprite->sysData1 = 0;
trTriggerSprite(pSprite->index, pXSprite, kCmdOff);
return;
}
spritetype* pIncarnation = &sprite[pXIncarnation->reference];
pXSprite->key = pXSprite->dropMsg = pXSprite->locked = 0;
// save incarnation's going on and off options
bool triggerOn = pXIncarnation->triggerOn;
bool triggerOff = pXIncarnation->triggerOff;
// then remove it from incarnation so it will not send the commands
pXIncarnation->triggerOn = false;
pXIncarnation->triggerOff = false;
// trigger dude death before transform
trTriggerSprite(pSprite->index, pXSprite, kCmdOff);
pSprite->type = pIncarnation->type;
pSprite->flags = pIncarnation->flags;
pSprite->pal = pIncarnation->pal;
pSprite->shade = pIncarnation->shade;
pSprite->clipdist = pIncarnation->clipdist;
pSprite->xrepeat = pIncarnation->xrepeat;
pSprite->yrepeat = pIncarnation->yrepeat;
pXSprite->txID = pXIncarnation->txID;
pXSprite->command = pXIncarnation->command;
pXSprite->triggerOn = triggerOn;
pXSprite->triggerOff = triggerOff;
pXSprite->busyTime = pXIncarnation->busyTime;
pXSprite->waitTime = pXIncarnation->waitTime;
pXSprite->burnTime = 0;
pXSprite->burnSource = -1;
pXSprite->data1 = pXIncarnation->data1;
pXSprite->data2 = pXIncarnation->data2;
// if incarnation is active dude, it's sndStartId will be stored in sysData1, otherwise it will be data3
if (pIncarnation->statnum == kStatDude && pIncarnation->type == kDudeModernCustom) pXSprite->sysData1 = pXIncarnation->sysData1;
else pXSprite->sysData1 = pXIncarnation->data3;
pXSprite->data4 = pXIncarnation->data4;
pXSprite->dudeGuard = pXIncarnation->dudeGuard;
pXSprite->dudeDeaf = pXIncarnation->dudeDeaf;
pXSprite->dudeAmbush = pXIncarnation->dudeAmbush;
pXSprite->dudeFlag4 = pXIncarnation->dudeFlag4;
pXSprite->dropMsg = pXIncarnation->dropMsg;
pXSprite->key = pXIncarnation->key;
pXSprite->locked = pXIncarnation->locked;
pXSprite->Decoupled = pXIncarnation->Decoupled;
// clear drop items of the incarnation
pXIncarnation->key = pXIncarnation->dropMsg = 0;
// set hp
if (pXSprite->data4 <= 0) pXSprite->health = dudeInfo[pSprite->type - kDudeBase].startHealth << 4;
else pXSprite->health = ClipRange(pXSprite->data4 << 4, 1, 65535);
int seqId = dudeInfo[pSprite->type - kDudeBase].seqStartID;
switch (pSprite->type) {
case kDudePodMother: // fake dude
case kDudeTentacleMother: // fake dude
break;
case kDudeModernCustom:
case kDudeModernCustomBurning:
seqId = genDudeSeqStartId(pXSprite);
genDudePrepare(pSprite, kGenDudePropertyMass);
fallthrough__; // go below
default:
seqSpawn(seqId, 3, pSprite->extra, -1);
// save target
int target = pXSprite->target;
// re-init sprite
aiInitSprite(pSprite);
// try to restore target
if (target == -1) aiSetTarget(pXSprite, pSprite->x, pSprite->y, pSprite->z);
else aiSetTarget(pXSprite, target);
// finally activate it
aiActivateDude(pSprite, pXSprite);
break;
}
// remove the incarnation in case if non-locked
if (pXIncarnation->locked == 0) {
pXIncarnation->txID = pIncarnation->type = 0;
actPostSprite(pIncarnation->index, kStatFree);
// or restore triggerOn and off options
} else {
pXIncarnation->triggerOn = triggerOn;
pXIncarnation->triggerOff = triggerOff;
}
}
void updateTargetOfLeech(spritetype* pSprite) {
if (!(pSprite->extra >= 0 && pSprite->extra < kMaxXSprites)) {

View File

@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#pragma once
#include "nnexts.h"
#ifdef NOONE_EXTENSIONS
#include "ai.h"
#include "eventq.h"
@ -177,13 +178,9 @@ struct GENDUDEEXTRA {
bool canFly;
};
extern GENDUDEEXTRA gGenDudeExtra[];
inline GENDUDEEXTRA* genDudeExtra(spritetype* pGenDude) {
dassert(spriRangeIsFine(pGenDude->index));
return &gGenDudeExtra[pGenDude->index];
}
extern GENDUDEEXTRA gGenDudeExtra[kMaxSprites];
GENDUDEEXTRA* genDudeExtra(spritetype* pGenDude);
XSPRITE* getNextIncarnation(XSPRITE* pXSprite);
void killDudeLeech(spritetype* pLeech);
void removeLeech(spritetype* pLeech, bool delSprite = true);
@ -197,6 +194,8 @@ void aiGenDudeNewState(spritetype* pSprite, AISTATE* pAIState);
int getGenDudeMoveSpeed(spritetype* pSprite, int which, bool mul, bool shift);
int checkAttackState(spritetype* pSprite, XSPRITE* pXSprite);
bool doExplosion(spritetype* pSprite, int nType);
spritetype* genDudeSpawn(spritetype* pSprite, int nDist);
void genDudeTransform(spritetype* pSprite);
void dudeLeechOperate(spritetype* pSprite, XSPRITE* pXSprite, EVENT a3);
int getDodgeChance(spritetype* pSprite);
int getRecoilChance(spritetype* pSprite);
@ -219,7 +218,6 @@ int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp);
void scaleDamage(XSPRITE* pXSprite);
bool genDudePrepare(spritetype* pSprite, int propId = kGenDudePropertyAll);
void genDudeUpdate(spritetype* pSprite);
void genDudeProcess(spritetype* pSprite, XSPRITE* pXSprite);
bool genDudeAdjustSlope(spritetype* pSprite, XSPRITE* pXSprite, int dist, int weaponType, int by = 64);
#endif
END_BLD_NS

View File

@ -72,6 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "statistics.h"
#include "menu/menu.h"
#include "sound/s_soundinternal.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -569,6 +570,7 @@ void StartLevel(GAMEOPTIONS *gameOptions)
gLevelTime = 0;
automapping = 1;
int modernTypesErased = 0;
for (int i = 0; i < kMaxSprites; i++)
{
spritetype *pSprite = &sprite[i];
@ -585,80 +587,17 @@ void StartLevel(GAMEOPTIONS *gameOptions)
#ifdef NOONE_EXTENSIONS
if (gModernMap) {
switch (pSprite->type) {
// add statnum for faster dude searching
case kModernDudeTargetChanger:
changespritestat(i, kStatModernDudeTargetChanger);
break;
// remove kStatItem status from random item generators
case kModernRandom:
case kModernRandom2:
changespritestat(i, kStatDecoration);
break;
}
// very quick fix for floor sprites with Touch trigger flag if their Z is equals sector floorz / ceilgz
if ((pSprite->cstat & CSTAT_SPRITE_ALIGNMENT_FLOOR) && pSprite->sectnum >= 0 && pSprite->extra >= 0 && xsprite[pSprite->extra].Touch) {
if (pSprite->z == sector[pSprite->sectnum].floorz) pSprite->z--;
else if (pSprite->z == sector[pSprite->sectnum].ceilingz) pSprite->z++;
}
} else {
switch (pSprite->type) {
// erase all modern types if the map is not extended
case kModernCustomDudeSpawn:
case kModernRandomTX:
case kModernSequentialTX:
case kModernSeqSpawner:
case kModernObjPropertiesChanger:
case kModernObjPicnumChanger:
case kModernObjSizeChanger:
case kModernDudeTargetChanger:
case kModernSectorFXChanger:
case kModernObjDataChanger:
case kModernSpriteDamager:
case kModernObjDataAccumulator:
case kModernEffectSpawner:
case kModernWindGenerator:
case kModernPlayerControl:
pSprite->type = kSpriteDecoration;
break;
case kItemModernMapLevel:
case kDudeModernCustom:
case kDudeModernCustomBurning:
case kModernThingTNTProx:
case kModernThingEnemyLifeLeech:
pSprite->type = kSpriteDecoration;
changespritestat(pSprite->index, kStatDecoration);
break;
// also erase some modernized vanilla types which was not active
case kMarkerWarpDest:
if (pSprite->statnum != kStatMarker) pSprite->type = kSpriteDecoration;
break;
}
if (pXSprite->Sight)
pXSprite->Sight = false; // it does not work in vanilla at all
if (pXSprite->Proximity) {
// proximity works only for things and dudes in vanilla
switch (pSprite->statnum) {
case kStatThing:
case kStatDude:
break;
default:
pXSprite->Proximity = false;
break;
}
}
}
if (!gModernMap && nnExtEraseModernStuff(pSprite, pXSprite))
modernTypesErased++;
#endif
}
}
}
}
#ifdef NOONE_EXTENSIONS
if (!gModernMap)
OSD_Printf("> Modern types erased: %d.\n", modernTypesErased);
#endif
scrLoadPLUs();
startpos.z = getflorzofslope(startsectnum,startpos.x,startpos.y);
for (int i = 0; i < kMaxPlayers; i++) {

View File

@ -45,7 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "trig.h"
#include "triggers.h"
#include "view.h"
#include "aiunicult.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -712,72 +712,6 @@ void DropVoodoo(int nSprite) // unused
}
}
#ifdef NOONE_EXTENSIONS
void UniMissileBurst(int nSprite) // 22
{
dassert(nSprite >= 0 && nSprite < kMaxSprites);
if (sprite[nSprite].statnum != kStatProjectile) return;
spritetype * pSprite = &sprite[nSprite];
int nAngle = getangle(xvel[nSprite], yvel[nSprite]);
int nRadius = 0x55555;
for (int i = 0; i < 8; i++)
{
spritetype* pBurst = actSpawnSprite(pSprite, 5);
pBurst->type = pSprite->type;
pBurst->shade = pSprite->shade;
pBurst->picnum = pSprite->picnum;
pBurst->cstat = pSprite->cstat;
if ((pBurst->cstat & CSTAT_SPRITE_BLOCK)) {
pBurst->cstat &= ~CSTAT_SPRITE_BLOCK; // we don't want missiles impact each other
evPost(pBurst->xvel, 3, 100, kCallbackMissileSpriteBlock); // so set blocking flag a bit later
}
pBurst->pal = pSprite->pal;
pBurst->clipdist = pSprite->clipdist / 4;
pBurst->flags = pSprite->flags;
pBurst->xrepeat = pSprite->xrepeat / 2;
pBurst->yrepeat = pSprite->yrepeat / 2;
pBurst->ang = ((pSprite->ang + missileInfo[pSprite->type - kMissileBase].angleOfs) & 2047);
pBurst->owner = pSprite->owner;
actBuildMissile(pBurst, pBurst->extra, pSprite->xvel);
int nAngle2 = (i << 11) / 8;
int dx = 0;
int dy = mulscale30r(nRadius, Sin(nAngle2));
int dz = mulscale30r(nRadius, -Cos(nAngle2));
if (i & 1)
{
dy >>= 1;
dz >>= 1;
}
RotateVector(&dx, &dy, nAngle);
xvel[pBurst->index] += dx;
yvel[pBurst->index] += dy;
zvel[pBurst->index] += dz;
evPost(pBurst->index, 3, 960, kCallbackRemove);
}
evPost(nSprite, 3, 0, kCallbackRemove);
}
void makeMissileBlocking(int nSprite) // 23
{
dassert(nSprite >= 0 && nSprite < kMaxSprites);
if (sprite[nSprite].statnum != kStatProjectile) return;
sprite[nSprite].cstat |= CSTAT_SPRITE_BLOCK;
}
void genDudeUpdateCallback(int nSprite) // 24
{
if (spriRangeIsFine(nSprite))
genDudeUpdate(&sprite[nSprite]);
}
#endif
void(*gCallback[kCallbackMax])(int) =
{
fxFlameLick,
@ -802,11 +736,11 @@ void(*gCallback[kCallbackMax])(int) =
fxPodBloodSplat,
LeechStateTimer,
DropVoodoo, // unused
#ifdef NOONE_EXTENSIONS
UniMissileBurst,
makeMissileBlocking,
genDudeUpdateCallback,
#endif
#ifdef NOONE_EXTENSIONS
callbackUniMissileBurst, // the code is in nnexts.cpp
callbackMakeMissileBlocking, // the code is in nnexts.cpp
callbackGenDudeUpdate, // the code is in nnexts.cpp
#endif
};
END_BLD_NS

View File

@ -50,9 +50,9 @@ enum CALLBACK_ID {
kCallbackLeechStateTimer = 20,
kCallbackDropVoodoo = 21, // unused
#ifdef NOONE_EXTENSIONS
kCallbackMissileBurst = 22, // by NoOne
kCallbackMissileSpriteBlock = 23, // by NoOne
kCallbackGenDudeUpdate = 24, // by NoOne
kCallbackMissileBurst = 22,
kCallbackMissileSpriteBlock = 23,
kCallbackGenDudeUpdate = 24,
#endif
kCallbackMax,
};

View File

@ -391,55 +391,6 @@ enum {
kSoundPlayer = 711,
};
#ifdef NOONE_EXTENSIONS
// modern types (gModernMap only)
enum {
kModernCustomDudeSpawn = 24,
kModernRandomTX = 25,
kModernSequentialTX = 26,
kModernSeqSpawner = 27,
kModernObjPropertiesChanger = 28,
kModernObjPicnumChanger = 29,
kModernObjSizeChanger = 31,
kModernDudeTargetChanger = 33,
kModernSectorFXChanger = 34,
kModernObjDataChanger = 35,
kModernSpriteDamager = 36,
kModernObjDataAccumulator = 37,
kModernEffectSpawner = 38,
kModernWindGenerator = 39,
kModernRandom = 40,
kModernRandom2 = 80,
kItemShroomGrow = 129,
kItemShroomShrink = 130,
kItemModernMapLevel = 150, // once picked up, draws whole minimap
kDudeModernCustom = kDudeVanillaMax,
kDudeModernCustomBurning = 255,
kModernThingTNTProx = 433, // detects only players
kModernThingThrowableRock = 434, // does small damage if hits target
kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only
kModernPlayerControl = 500, /// WIP
kGenModernMissileUniversal = 704,
};
// modern statnums (gModernMap only)
enum {
kStatModernDudeTargetChanger = 20,
};
// additional physics attributes for debris sprites
#define kPhysDebrisFly 0x0008 // *debris* affected by negative gravity (fly instead of falling, DO NOT mess with kHitagAutoAim)
#define kPhysDebrisSwim 0x0016 // *debris* can swim underwater (instead of drowning)
#define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons
#define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions
// *modern types only hitag*
#define kModernTypeFlag0 0x0
#define kModernTypeFlag1 0x1
#define kModernTypeFlag2 0x2
#define kModernTypeFlag3 0x3
#endif
// WALL TYPES /////////////////////////////////////////////////
enum {
kWallBase = 500,

View File

@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "db.h"
#include "iob.h"
#include "eventq.h"
#include "nnexts.h"
BEGIN_BLD_NS
@ -54,9 +55,6 @@ PolymerLight_t gPolymerLight[kMaxSprites];
char qsprite_filler[kMaxSprites], qsector_filler[kMaxSectors];
int gVisibility;
#ifdef NOONE_EXTENSIONS
bool gModernMap = false;
#endif
void dbCrypt(char *pPtr, int nLength, int nKey)
{

View File

@ -29,11 +29,6 @@ BEGIN_BLD_NS
#define kMaxXSectors 512
#ifdef NOONE_EXTENSIONS
// additional non-thing proximity, sight and physics sprites
#define kMaxSuperXSprites 128
extern bool gModernMap;
#endif
// by NoOne: functions to quckly check range of specifical arrays
inline bool xspriRangeIsFine(int nXindex) {

View File

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "pqueue.h"
#include "triggers.h"
#include "view.h"
#include "nnexts.h"
#include "secrets.h"
BEGIN_BLD_NS

View File

@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <random>
#include "build.h"
#include "common_game.h"
@ -917,14 +917,6 @@ int picHeight(short nPic, short repeat) {
return ClipLow((tilesiz[nPic].y * repeat) << 2, 0);
}
#ifdef NOONE_EXTENSIONS
// used for better randomness in single player
int STD_Random(int a, int b) {
std::default_random_engine stdRandom;
stdRandom.seed(std::random_device()());
std::uniform_int_distribution<int> dist_a_b(a, b);
return dist_a_b(stdRandom);
}
#endif
END_BLD_NS

View File

@ -85,6 +85,6 @@ int GetClosestSectors(int nSector, int x, int y, int nDist, short *pSectors, cha
int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, short *pSectors, char *pSectBit, short *a8);
int picWidth(short nPic, short repeat);
int picHeight(short nPic, short repeat);
int STD_Random(int a, int b);
END_BLD_NS

View File

@ -358,25 +358,6 @@ void levelEndLevel(int arg)
}
}
#ifdef NOONE_EXTENSIONS
// this function can be called via sending numbered command to TX kChannelModernEndLevelCustom
// This allows to set custom next level instead of taking it from INI file.
void levelEndLevelCustom(int nLevel) {
gGameOptions.uGameFlags |= 1;
if (nLevel >= 16 || nLevel < 0)
{
gGameOptions.uGameFlags |= 2;
gGameOptions.nLevel = 0;
return;
}
gNextLevel = nLevel;
}
#endif
void levelRestart(void)
{
levelSetupOptions(gGameOptions.nEpisode, gGameOptions.nLevel);

View File

@ -117,12 +117,6 @@ void levelAddUserMap(const char *pzMap);
void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB);
// arg: 0 is normal exit, 1 is secret level
void levelEndLevel(int arg);
#ifdef NOONE_EXTENSIONS
// custom level selection via numbered command which sent to TX ID 6.
void levelEndLevelCustom(int nLevel);
#endif
void levelRestart(void);
int levelGetMusicIdx(const char *str);
bool levelTryPlayMusic(int nEpisode, int nlevel, bool bSetLevelSong = false);

View File

@ -46,6 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "sound.h"
#include "i_specialpaths.h"
#include "view.h"
#include "nnexts.h"
#include "savegamehelp.h"
#include "z_music.h"
#include "mapinfo.h"

3709
source/blood/src/nnexts.cpp Normal file

File diff suppressed because it is too large Load Diff

274
source/blood/src/nnexts.h Normal file
View File

@ -0,0 +1,274 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
Copyright (C) NoOne
This file is part of NBlood.
NBlood is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////////
// This file provides modern features for mappers.
// For full documentation please visit http://cruo.bloodgame.ru/xxsystem
/////////////////////////////////////////////////////////////////////////
#pragma once
#include "common_game.h"
#ifdef NOONE_EXTENSIONS
#include "eventq.h"
#include "qav.h"
#include "actor.h"
#include "dude.h"
#include "player.h"
#include "warp.h"
BEGIN_BLD_NS
// CONSTANTS
// additional non-thing proximity, sight and physics sprites
#define kMaxSuperXSprites 128
// additional physics attributes for debris sprites
#define kPhysDebrisFly 0x0008 // *debris* affected by negative gravity (fly instead of falling, DO NOT mess with kHitagAutoAim)
#define kPhysDebrisSwim 0x0016 // *debris* can swim underwater (instead of drowning)
#define kPhysDebrisVector 0x0400 // *debris* can be affected by vector weapons
#define kPhysDebrisExplode 0x0800 // *debris* can be affected by explosions
// *modern types only hitag*
#define kModernTypeFlag0 0x0
#define kModernTypeFlag1 0x1
#define kModernTypeFlag2 0x2
#define kModernTypeFlag3 0x3
#define kMaxRandomizeRetries 16
// modern sprite types
enum {
kStatModernDudeTargetChanger = 20,
kModernCustomDudeSpawn = 24,
kModernRandomTX = 25,
kModernSequentialTX = 26,
kModernSeqSpawner = 27,
kModernObjPropertiesChanger = 28,
kModernObjPicnumChanger = 29,
kModernObjSizeChanger = 31,
kModernDudeTargetChanger = 33,
kModernSectorFXChanger = 34,
kModernObjDataChanger = 35,
kModernSpriteDamager = 36,
kModernObjDataAccumulator = 37,
kModernEffectSpawner = 38,
kModernWindGenerator = 39,
kModernRandom = 40,
kModernRandom2 = 80,
kItemShroomGrow = 129,
kItemShroomShrink = 130,
kItemModernMapLevel = 150, // once picked up, draws whole minimap
kDudeModernCustom = kDudeVanillaMax,
kDudeModernCustomBurning = 255,
kModernThingTNTProx = 433, // detects only players
kModernThingThrowableRock = 434, // does small damage if hits target
kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only
kModernPlayerControl = 500, /// WIP
kGenModernMissileUniversal = 704,
kGenModernSound = 708,
};
// type of random
enum {
kRandomizeItem = 0,
kRandomizeDude = 1,
kRandomizeTX = 2,
};
// type of object
enum {
OBJ_WALL = 0,
OBJ_SPRITE = 3,
OBJ_SECTOR = 6,
};
// - STRUCTS ------------------------------------------------------------------
struct SPRITEMASS { // sprite mass info for getSpriteMassBySize();
int seqId;
short picnum; // mainly needs for moving debris
short xrepeat;
short yrepeat;
short clipdist; // mass multiplier
int mass;
short airVel; // mainly needs for moving debris
int fraction; // mainly needs for moving debris
};
struct QAVSCENE { // this one stores qavs anims that can be played by trigger
short index = -1; // index of sprite which triggered qav scene
QAV* qavResrc = NULL;
short dummy = -1;
};
struct THINGINFO_EXTRA {
bool allowThrow; // indicates if kDudeModernCustom can throw it
};
struct VECTORINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
};
struct MISSILEINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
bool dmgType[kDamageMax]; // list of damages types missile can use
};
struct TRPLAYERCTRL { // this one for controlling the player using triggers (movement speed, jumps and other stuff)
QAVSCENE qavScene;
};
// - VARIABLES ------------------------------------------------------------------
extern bool gModernMap;
extern bool gTeamsSpawnUsed;
extern ZONE gStartZoneTeam1[kMaxPlayers];
extern ZONE gStartZoneTeam2[kMaxPlayers];
extern THINGINFO_EXTRA gThingInfoExtra[kThingMax];
extern VECTORINFO_EXTRA gVectorInfoExtra[kVectorMax];
extern MISSILEINFO_EXTRA gMissileInfoExtra[kMissileMax];
extern TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
extern SPRITEMASS gSpriteMass[kMaxXSprites];
extern short gProxySpritesList[kMaxSuperXSprites];
extern short gSightSpritesList[kMaxSuperXSprites];
extern short gPhysSpritesList[kMaxSuperXSprites];
extern short gProxySpritesCount;
extern short gSightSpritesCount;
extern short gPhysSpritesCount;
// - FUNCTIONS ------------------------------------------------------------------
bool nnExtEraseModernStuff(spritetype* pSprite, XSPRITE* pXSprite);
void nnExtInitModernStuff(bool bSaveLoad);
void nnExtProcessSuperSprites(void);
bool nnExtIsUmmune(spritetype* pSprite, int dmgType, int minScale = 16);
int nnExtRandom(int a, int b);
// ------------------------------------------------------------------------- //
spritetype* randomDropPickupObject(spritetype* pSprite, short prevItem);
spritetype* randomSpawnDude(spritetype* pSprite);
int GetDataVal(spritetype* pSprite, int data);
int randomGetDataValue(XSPRITE* pXSprite, int randType);
void sfxPlayMissileSound(spritetype* pSprite, int missileId);
void sfxPlayVectorSound(spritetype* pSprite, int vectorId);
// ------------------------------------------------------------------------- //
int debrisGetIndex(int nSprite);
int debrisGetFreeIndex(void);
void debrisMove(int listIndex);
void debrisConcuss(int nOwner, int listIndex, int x, int y, int z, int dmg);
// ------------------------------------------------------------------------- //
void aiSetGenIdleState(spritetype* pSprite, XSPRITE* pXSprite);
// triggers related
// ------------------------------------------------------------------------- //
int aiFightGetTargetDist(spritetype* pSprite, DUDEINFO* pDudeInfo, spritetype* pTarget);
int aiFightGetFineTargetDist(spritetype* pSprite, spritetype* pTarget);
bool aiFightDudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget);
bool aiFightIsAnnoyingUnit(spritetype* pDude);
bool aiFightUnitCanFly(spritetype* pDude);
bool aiFightIsMeleeUnit(spritetype* pDude);
bool aiFightDudeIsAffected(XSPRITE* pXDude);
bool aiFightMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allow);
bool aiFightGetDudesForBattle(XSPRITE* pXSprite);
inline bool aiFightIsMateOf(XSPRITE* pXDude, XSPRITE* pXSprite) {
return (pXDude->rxID == pXSprite->rxID);
}
void aiFightAlarmDudesInSight(spritetype* pSprite, int max);
void aiFightActivateDudes(int rx);
void aiFightFreeTargets(int nSprite);
void aiFightFreeAllTargets(XSPRITE* pXSource);
spritetype* aiFightGetTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode);
spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite);
spritetype* aiFightGetMateTargets(XSPRITE* pXSprite);
// ------------------------------------------------------------------------- //
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 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 useIncDecGen(XSPRITE* pXSource, short objType, int objIndex);
void useDataChanger(XSPRITE* pXSource, int objType, int objIndex);
void useSectorLigthChanger(XSPRITE* pXSource, XSECTOR* pXSector);
void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite);
void usePictureChanger(XSPRITE* pXSource, int objType, int objIndex);
void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex);
// ------------------------------------------------------------------------- //
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlSetRace(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlSetMoveSpeed(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlSetJumpHeight(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlSetScreenEffect(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlSetLookAngle(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlEraseStuff(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlGiveStuff(XSPRITE* pXSource, PLAYER* pPlayer, TRPLAYERCTRL* pCtrl);
void trPlayerCtrlUsePackItem(XSPRITE* pXSource, PLAYER* pPlayer);
// ------------------------------------------------------------------------- //
void modernTypeTrigger(int type, int nDest, EVENT event);
char modernTypeSetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite, EVENT event);
bool modernTypeLinkSprite(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);
// ------------------------------------------------------------------------- //
bool playerSizeShrink(PLAYER* pPlayer, int divider);
bool playerSizeGrow(PLAYER* pPlayer, int multiplier);
bool playerSizeReset(PLAYER* pPlayer);
void playerDeactivateShrooms(PLAYER* pPlayer);
// ------------------------------------------------------------------------- //
QAV* playerQavSceneLoad(int qavId);
void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene);
void playerQavScenePlay(PLAYER* pPlayer);
void playerQavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5);
void playerQavSceneReset(PLAYER* pPlayer);
// ------------------------------------------------------------------------- //
void callbackUniMissileBurst(int nSprite);
void callbackMakeMissileBlocking(int nSprite);
void callbackGenDudeUpdate(int nSprite);
// ------------------------------------------------------------------------- //
PLAYER* getPlayerById(short id);
bool isGrown(spritetype* pSprite);
bool isShrinked(spritetype* pSprite);
bool valueIsBetween(int val, int min, int max);
bool IsBurningDude(spritetype* pSprite);
bool IsKillableDude(spritetype* pSprite);
bool isActive(int nSprite);
int getDataFieldOfObject(int objType, int objIndex, int dataIndex);
bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value);
bool incDecGoalValueIsReached(XSPRITE* pXSprite);
void windGenStopWindOnSectors(XSPRITE* pXSource);
int getSpriteMassBySize(spritetype* pSprite);
bool ceilIsTooLow(spritetype* pSprite);
void levelEndLevelCustom(int nLevel);
#endif
////////////////////////////////////////////////////////////////////////
// This file provides modern features for mappers.
// For full documentation please visit http://cruo.bloodgame.ru/xxsystem
////////////////////////////////////////////////////////////////////////////////////
END_BLD_NS

View File

@ -53,6 +53,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "weapon.h"
#include "common_game.h"
#include "messages.h"
#include "nnexts.h"
#include "gstrings.h"
BEGIN_BLD_NS
@ -254,133 +255,6 @@ DAMAGEINFO damageInfo[7] = {
{ 0, 0, 0, 0, 0, 0, 0 }
};
#ifdef NOONE_EXTENSIONS
TRPLAYERCTRL gPlayerCtrl[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);
return pQav;
}
void qavSceneDraw(PLAYER* pPlayer, int a2, int a3, int a4, int a5) {
if (pPlayer == NULL || pPlayer->sceneQav == -1) return;
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
spritetype* pSprite = &sprite[pQavScene->index];
if (pQavScene->qavResrc != NULL) {
QAV* pQAV = pQavScene->qavResrc;
int v4 = (pPlayer->weaponTimer == 0) ? (int)totalclock % pQAV->at10 : pQAV->at10 - pPlayer->weaponTimer;
int flags = 2; int nInv = powerupCheck(pPlayer, kPwUpShadowCloak);
if (nInv >= 120 * 8 || (nInv != 0 && ((int)totalclock & 32))) {
a2 = -128; flags |= 1;
}
// draw as weapon
if (!(pSprite->flags & kModernTypeFlag1)) {
pQAV->x = a3; pQAV->y = a4;
pQAV->Draw(v4, flags, a2, a5);
// draw fullscreen (currently 4:3 only)
} else {
int wx1 = windowxy1.x, wy1 = windowxy1.y, wx2 = windowxy2.x, wy2 = windowxy2.y;
windowxy2.x = xdim - 1; windowxy2.y = ydim - 1;
windowxy1.x = windowxy1.y = 0;
pQAV->Draw(v4, flags, a2, a5);
windowxy1.x = wx1; windowxy1.y = wy1;
windowxy2.x = wx2; windowxy2.y = wy2;
}
}
}
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);
}
}
bool isGrown(spritetype* pSprite) {
if (powerupCheck(&gPlayer[pSprite->type - kDudePlayer1], kPwUpGrowShroom) > 0) return true;
else if (pSprite->extra >= 0 && xsprite[pSprite->extra].scale >= 512) return true;
else return false;
}
bool isShrinked(spritetype* pSprite) {
if (powerupCheck(&gPlayer[pSprite->type - kDudePlayer1], kPwUpShrinkShroom) > 0) return true;
else if (pSprite->extra >= 0 && xsprite[pSprite->extra].scale > 0 && xsprite[pSprite->extra].scale <= 128) return true;
else return false;
}
bool shrinkPlayerSize(PLAYER* pPlayer, int divider) {
pPlayer->pXSprite->scale = 256/divider;
playerSetRace(pPlayer, kModeHumanShrink);
return true;
}
bool growPlayerSize(PLAYER* pPlayer, int multiplier) {
pPlayer->pXSprite->scale = 256*multiplier;
playerSetRace(pPlayer, kModeHumanGrown);
return true;
}
bool resetPlayerSize(PLAYER* pPlayer) {
playerSetRace(pPlayer, kModeHuman);
pPlayer->pXSprite->scale = 0;
return true;
}
#endif
void deactivateSizeShrooms(PLAYER* pPlayer) {
powerupDeactivate(pPlayer, kPwUpGrowShroom);
pPlayer->pwUpTime[kPwUpGrowShroom] = 0;
powerupDeactivate(pPlayer, kPwUpShrinkShroom);
pPlayer->pwUpTime[kPwUpShrinkShroom] = 0;
}
PLAYER* getPlayerById(short id) {
// relative to connected players
if (id >= 1 && id <= kMaxPlayers) {
id = id - 1;
for (int i = connecthead; i >= 0; i = connectpoint2[i]) {
if (id == gPlayer[i].nPlayer)
return &gPlayer[i];
}
// absolute sprite type
} else if (id >= kDudePlayer1 && id <= kDudePlayer8) {
for (int i = connecthead; i >= 0; i = connectpoint2[i]) {
if (id == gPlayer[i].pSprite->type)
return &gPlayer[i];
}
}
viewSetSystemMessage("There is no player id #%d", id);
return NULL;
}
int powerupCheck(PLAYER *pPlayer, int nPowerUp)
{
dassert(pPlayer != NULL);
@ -409,21 +283,21 @@ char powerupActivate(PLAYER *pPlayer, int nPowerUp)
break;
case kItemShroomShrink:
if (!gModernMap) break;
else if (isGrown(pPlayer->pSprite)) deactivateSizeShrooms(pPlayer);
else shrinkPlayerSize(pPlayer, 2);
else if (isGrown(pPlayer->pSprite)) playerDeactivateShrooms(pPlayer);
else playerSizeShrink(pPlayer, 2);
break;
case kItemShroomGrow:
if (!gModernMap) break;
else if (isShrinked(pPlayer->pSprite)) deactivateSizeShrooms(pPlayer);
else if (isShrinked(pPlayer->pSprite)) playerDeactivateShrooms(pPlayer);
else {
growPlayerSize(pPlayer, 2);
playerSizeGrow(pPlayer, 2);
if (powerupCheck(&gPlayer[pPlayer->pSprite->type - kDudePlayer1], kPwUpShadowCloak) > 0) {
powerupDeactivate(pPlayer, kPwUpShadowCloak);
pPlayer->pwUpTime[kPwUpShadowCloak] = 0;
}
if (ceilIsTooLow(pPlayer->pSprite))
actDamageSprite(pPlayer->pSprite->xvel, pPlayer->pSprite, DAMAGE_TYPE_3, 65535);
actDamageSprite(pPlayer->pSprite->index, pPlayer->pSprite, DAMAGE_TYPE_3, 65535);
}
break;
#endif
@ -469,13 +343,13 @@ void powerupDeactivate(PLAYER *pPlayer, int nPowerUp)
#ifdef NOONE_EXTENSIONS
case kItemShroomShrink:
if (gModernMap) {
resetPlayerSize(pPlayer);
playerSizeReset(pPlayer);
if (ceilIsTooLow(pPlayer->pSprite))
actDamageSprite(pPlayer->pSprite->xvel, pPlayer->pSprite, DAMAGE_TYPE_3, 65535);
actDamageSprite(pPlayer->pSprite->index, pPlayer->pSprite, DAMAGE_TYPE_3, 65535);
}
break;
case kItemShroomGrow:
if (gModernMap) resetPlayerSize(pPlayer);
if (gModernMap) playerSizeReset(pPlayer);
break;
#endif
case kItemFeatherFall:
@ -767,6 +641,10 @@ void playerResetPowerUps(PLAYER* pPlayer)
}
}
void playerResetPosture(PLAYER* pPlayer) {
memcpy(pPlayer->pPosture, gPostureDefaults, sizeof(gPostureDefaults));
}
void playerStart(int nPlayer)
{
PLAYER* pPlayer = &gPlayer[nPlayer];
@ -896,7 +774,7 @@ void playerStart(int nPlayer)
pPlayer->weaponState = 0;
pPlayer->weaponQav = -1;
#ifdef NOONE_EXTENSIONS
playerResetQavScene(pPlayer); // reset qav scene
playerQavSceneReset(pPlayer); // reset qav scene
#endif
pPlayer->hand = 0;
pPlayer->nWaterPal = 0;
@ -958,30 +836,14 @@ void playerReset(PLAYER *pPlayer)
pPlayer->packSlots[i].isActive = 0;
pPlayer->packSlots[i].curAmount = 0;
}
#ifdef NOONE_EXTENSIONS
/////////////////
// reset qav scene
playerResetQavScene(pPlayer);
#endif
#ifdef NOONE_EXTENSIONS
playerQavSceneReset(pPlayer);
#endif
// reset posture (mainly required for resetting movement speed and jump height)
playerResetPosture(pPlayer);
/////////////////
}
void playerResetPosture(PLAYER* pPlayer) {
memcpy(pPlayer->pPosture, gPostureDefaults, sizeof(gPostureDefaults));
}
#ifdef NOONE_EXTENSIONS
void playerResetQavScene(PLAYER* pPlayer) {
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
pQavScene->index = pQavScene->dummy = pPlayer->sceneQav = -1;
pQavScene->qavResrc = NULL;
}
#endif
int dword_21EFB0[8];
ClockTicks dword_21EFD0[8];
@ -1200,8 +1062,8 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) {
int addPower = gPowerUpInfo[nType].bonusTime;
#ifdef NOONE_EXTENSIONS
// allow custom amount for item
if (gModernMap && sprite[pItem->xvel].extra >= 0 && xsprite[sprite[pItem->xvel].extra].data1 > 0)
addPower = xsprite[sprite[pItem->xvel].extra].data1;
if (gModernMap && sprite[pItem->index].extra >= 0 && xsprite[sprite[pItem->index].extra].data1 > 0)
addPower = xsprite[sprite[pItem->index].extra].data1;
#endif
if (!actHealDude(pXSprite, addPower, gPowerUpInfo[nType].maxTime)) return 0;
@ -2331,16 +2193,13 @@ public:
void PlayerLoadSave::Load(void)
{
const char buffer[2048] = "";
Read(dword_21EFB0, sizeof(dword_21EFB0));
Read(&gNetPlayers, sizeof(gNetPlayers));
Read(&gProfile, sizeof(gProfile));
Read(&gPlayer, sizeof(gPlayer));
#ifdef NOONE_EXTENSIONS
Read((void*)&buffer, sizeof(kPlayerCtrlSigStart));
Read(&gPlayerCtrl, sizeof(gPlayerCtrl));
Read((void*)&buffer, sizeof(kPlayerCtrlSigEnd));
#endif
for (int i = 0; i < gNetPlayers; i++) {
gPlayer[i].pSprite = &sprite[gPlayer[i].nSprite];
@ -2353,7 +2212,7 @@ void PlayerLoadSave::Load(void)
if (gPlayerCtrl[i].qavScene.qavResrc == NULL)
gPlayer[i].sceneQav = -1;
else {
QAV* pQav = qavSceneLoad(gPlayer[i].sceneQav);
QAV* pQav = playerQavSceneLoad(gPlayer[i].sceneQav);
if (pQav) {
gPlayerCtrl[i].qavScene.qavResrc = pQav;
gPlayerCtrl[i].qavScene.qavResrc->Preload();
@ -2375,9 +2234,7 @@ void PlayerLoadSave::Save(void)
Write(&gPlayer, sizeof(gPlayer));
#ifdef NOONE_EXTENSIONS
Write((void*)kPlayerCtrlSigStart, sizeof(kPlayerCtrlSigStart));
Write(&gPlayerCtrl, sizeof(gPlayerCtrl));
Write((void*)kPlayerCtrlSigEnd, sizeof(kPlayerCtrlSigEnd));
#endif
}

View File

@ -50,8 +50,8 @@ enum
enum
{
kPostureStand = 0,
kPostureCrouch = 1,
kPostureSwim = 2,
kPostureSwim = 1,
kPostureCrouch = 2,
kPostureMax = 3,
};
@ -219,33 +219,6 @@ struct POWERUPINFO
int maxTime;
};
#ifdef NOONE_EXTENSIONS
// this one stores qavs anims that can be played by trigger
struct QAVSCENE
{
short index = -1; // index of sprite which triggered qav scene
QAV * qavResrc = NULL;
short dummy = -1;
};
// this one for controlling the player using triggers (movement speed, jumps and other stuff)
struct TRPLAYERCTRL {
QAVSCENE qavScene;
};
extern TRPLAYERCTRL gPlayerCtrl[kMaxPlayers];
bool isGrown(spritetype *pSprite);
bool isShrinked(spritetype *pSprite);
bool shrinkPlayerSize(PLAYER *pPlayer, int divider);
bool growPlayerSize(PLAYER *pPlayer, int multiplier);
bool resetPlayerSize(PLAYER *pPlayer);
void deactivateSizeShrooms(PLAYER *pPlayer);
PLAYER * getPlayerById(short id);
QAV * qavSceneLoad(int qavId);
void qavScenePlay(PLAYER *pPlayer);
void qavSceneDraw(PLAYER *pPlayer, int a2, int a3, int a4, int a5);
void playerResetQavScene(PLAYER *pPlayer);
#endif
void playerResetPosture(PLAYER* pPlayer);
extern PLAYER gPlayer[kMaxPlayers];

View File

@ -305,7 +305,7 @@ void SEQINST::Update(ACTIVE *pActive)
// by NoOne: add surfaceSound trigger feature
spritetype* pSprite = &sprite[xsprite[pActive->xindex].reference];
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && zvel[pSprite->xvel] == 0 && xvel[pSprite->xvel] != 0) {
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && zvel[pSprite->index] == 0 && xvel[pSprite->index] != 0) {
if (gUpperLink[pSprite->sectnum] >= 0) break; // don't play surface sound for stacked sectors
int surf = tileGetSurfType(pSprite->sectnum + 0x4000); if (!surf) break;

File diff suppressed because it is too large Load Diff

View File

@ -41,54 +41,8 @@ void trMessageSprite(unsigned int nSprite, EVENT event);
void trProcessBusy(void);
void trInit(void);
void trTextOver(int nId);
#ifdef NOONE_EXTENSIONS
// functions required for new features
// -------------------------------------------------------
#define kPlayerCtrlSigStart "<<<<TRPLAYERCTRL{" // save game TRPLAYERCTRL block start
#define kPlayerCtrlSigEnd "}TRPLAYERCTRL>>>>" // save game TRPLAYERCTRL block end
void pastePropertiesInObj(int type, int nDest, EVENT event);
spritetype* getTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode);
bool isMateOf(XSPRITE* pXDude, XSPRITE* pXSprite);
spritetype* targetIsPlayer(XSPRITE* pXSprite);
bool isTargetAimsDude(XSPRITE* pXTarget, spritetype* pDude);
spritetype* getMateTargets(XSPRITE* pXSprite);
bool isMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allow);
bool isActive(int nSprite);
bool dudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget);
void disturbDudesInSight(spritetype* pSprite, int max);
int getTargetDist(spritetype* pSprite, DUDEINFO* pDudeInfo, spritetype* pTarget);
int getFineTargetDist(spritetype* pSprite, spritetype* pTarget);
bool IsBurningDude(spritetype* pSprite);
bool IsKillableDude(spritetype* pSprite);
bool isAnnoyingUnit(spritetype* pDude);
bool unitCanFly(spritetype* pDude);
bool isMeleeUnit(spritetype* pDude);
void activateDudes(int rx);
void freeTargets(int nSprite);
void freeAllTargets(XSPRITE* pXSource);
bool affectedByTargetChg(XSPRITE* pXDude);
int getDataFieldOfObject(int objType, int objIndex, int dataIndex);
bool setDataValueOfObject(int objType, int objIndex, int dataIndex, int value);
bool goalValueIsReached(XSPRITE* pXSprite);
bool getDudesForTargetChg(XSPRITE* pXSprite);
void stopWindOnSectors(XSPRITE* pXSource);
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 useTeleportTarget(XSPRITE* pXSource, spritetype* pSprite);
void usePropertiesChanger(XSPRITE* pXSource, short objType, int objIndex);
void useObjResizer(XSPRITE* pXSource, short objType, int objIndex);
char SetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
char SetWallState(int nWall, XWALL* pXWall, int nState);
void TeleFrag(int nKiller, int nSector);
bool valueIsBetween(int val, int min, int max);
void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer);
void trPlayerCtrlStopScene(XSPRITE* pXSource, PLAYER* pPlayer);
char modernTypeSetSpriteState(int nSprite, XSPRITE* pXSprite, int nState);
// -------------------------------------------------------
#endif// -------------------------------------------------------
END_BLD_NS

View File

@ -59,6 +59,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "view.h"
#include "warp.h"
#include "weapon.h"
#include "nnexts.h"
#include "zstring.h"
#include "menu/menu.h"
#include "gstrings.h"
@ -3499,7 +3500,7 @@ void viewDrawScreen(bool sceneonly)
#ifdef NOONE_EXTENSIONS
if (gView->sceneQav < 0) WeaponDraw(gView, nShade, cX, cY, nPalette);
else if (gView->pXSprite->health > 0) qavSceneDraw(gView, nShade, cX, cY, nPalette);
else if (gView->pXSprite->health > 0) playerQavSceneDraw(gView, nShade, cX, cY, nPalette);
else {
gView->sceneQav = gView->weaponQav = -1;
gView->weaponTimer = gView->curWeapon = 0;

View File

@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "loadsave.h"
#include "view.h"
#include "warp.h"
#include "nnexts.h"
BEGIN_BLD_NS

View File

@ -30,11 +30,6 @@ struct ZONE {
short sectnum, ang;
};
extern ZONE gStartZone[8];
#ifdef NOONE_EXTENSIONS
extern ZONE gStartZoneTeam1[8];
extern ZONE gStartZoneTeam2[8];
extern bool gTeamsSpawnUsed;
#endif
void warpInit(void);
int CheckLink(spritetype *pSprite);

View File

@ -47,7 +47,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "sfx.h"
#include "sound.h"
#include "trig.h"
#include "triggers.h"
#include "nnexts.h"
#include "view.h"
BEGIN_BLD_NS
@ -1583,8 +1583,8 @@ void FireNapalm2(int nTrigger, PLAYER *pPlayer)
void AltFireNapalm(int nTrigger, PLAYER *pPlayer)
{
//UNREFERENCED_PARAMETER(nTrigger);
//char UNUSED(bAkimbo) = powerupCheck(pPlayer, kPwUpTwoGuns);
UNREFERENCED_PARAMETER(nTrigger);
char UNUSED(bAkimbo) = powerupCheck(pPlayer, kPwUpTwoGuns);
int nSpeed = mulscale16(0x8000, 0x177777)+0x66666;
spritetype *pMissile = playerFireThing(pPlayer, 0, -4730, kThingNapalmBall, nSpeed);
if (pMissile)
@ -1936,28 +1936,10 @@ char sub_4F484(PLAYER *pPlayer)
void WeaponProcess(PLAYER *pPlayer) {
pPlayer->flashEffect = ClipLow(pPlayer->flashEffect - 1, 0);
#ifdef NOONE_EXTENSIONS
if (gPlayerCtrl[pPlayer->nPlayer].qavScene.index >= 0 && pPlayer->pXSprite->health > 0) {
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene;
int nIndex = pQavScene->index;
if (sprite[nIndex].extra >= 0) {
XSPRITE* pXSprite = &xsprite[sprite[nIndex].extra];
if (pXSprite->waitTime > 0 && --pXSprite->sysData1 <= 0) {
if (pXSprite->txID > 0)
evSend(nIndex, 3, pXSprite->txID, (COMMAND_ID) pXSprite->command);
if (pXSprite->locked) trPlayerCtrlStopScene(pXSprite, pPlayer);
else evPost(nIndex, 3, 0, (COMMAND_ID) (kCmdNumberic + 4));
} else {
qavScenePlay(pPlayer);
pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer -= 4, 0);
}
} else {
pQavScene->index = pPlayer->sceneQav = -1;
pQavScene->qavResrc = NULL;
}
playerQavSceneProcess(pPlayer, &gPlayerCtrl[pPlayer->nPlayer].qavScene);
return;
}
#endif