ported SHA-1: 82e3f6af9367200853fe2af1b9665dd0c53b4f05 from NBlood

* - Change gBusyCount limit to a higher value since xsector limit raised.

gModernMap:
- The return of the event causer (kChannelEventCauser, TXID 50).
- Fix flags for kModernPropertiesChanger type.
- Add new modern type kModernVelocityChanger.
- New features for kMarkerWarpDest type.
- New features for kModernSectorFXChanger type.
- Fix sector condition 58.
- Fix sprite hitscan conditions (35 - 38).
- Add new command (kCmdEventKillFull).
- Misc changes.

# Conflicts:
#	source/games/blood/src/actor.cpp
#	source/games/blood/src/nnexts.cpp
This commit is contained in:
Christoph Oelckers 2022-08-10 23:45:29 +02:00
parent 0139ac5e4a
commit b196e67f40
12 changed files with 853 additions and 397 deletions

View file

@ -107,6 +107,16 @@ namespace GC
return obj = NULL;
}
// Handles a read barrier for a const pointer. This does not alter the source data, but only returns NULL if the object is destroyed.
template<class T> inline T* ReadBarrier(const T*& obj)
{
if (obj == NULL || !(obj->ObjectFlags & OF_EuthanizeMe))
{
return obj;
}
return NULL;
}
// Check if it's time to collect, and do a collection step if it is.
static inline void CheckGC()
{
@ -214,7 +224,13 @@ public:
return GC::ReadBarrier(pp);
}
constexpr T ForceGet() noexcept //for situations where the read barrier needs to be skipped.
constexpr T Get() const noexcept
{
auto ppp = pp;
return GC::ReadBarrier(ppp);
}
constexpr T ForceGet() const noexcept //for situations where the read barrier needs to be skipped.
{
return pp;
}

View file

@ -3410,7 +3410,7 @@ void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damag
gPlayer[p].fragger = nullptr;
}
if (actor->spr.type != kDudeCultistBeast)
trTriggerSprite(actor, kCmdOff);
trTriggerSprite(actor, kCmdOff, killerActor);
actor->spr.flags |= 7;
checkAddFrag(killerActor, actor);
@ -3690,7 +3690,7 @@ static int actDamageThing(DBloodActor* source, DBloodActor* actor, int damage, D
break;
}
trTriggerSprite(actor, kCmdOff);
trTriggerSprite(actor, kCmdOff, source);
switch (actor->spr.type)
{
@ -4087,7 +4087,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode)
#ifdef NOONE_EXTENSIONS
if (gModernMap && actorHit && actorHit->hasX() && actorHit->xspr.state != actorHit->xspr.restState && actorHit->xspr.Impact)
trTriggerSprite(actorHit, kCmdSpriteImpact);
trTriggerSprite(actorHit, kCmdSpriteImpact, missileActor);
#endif
missileActor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
}
@ -4470,8 +4470,7 @@ static void ProcessTouchObjects(DBloodActor* actor)
if (actor2 && actor2->hasX())
{
if (actor2->xspr.Touch && !actor2->xspr.isTriggered && (!actor2->xspr.DudeLockout || actor->IsPlayerActor()))
trTriggerSprite(actor2, kCmdSpriteTouch);
triggerTouchSprite(actor, actor2);
}
// Touch walls
@ -4482,14 +4481,9 @@ static void ProcessTouchObjects(DBloodActor* actor)
pHWall = coll.hitWall;
if (pHWall && pHWall->hasX())
{
if (pHWall->xw().triggerTouch && !pHWall->xw().isTriggered && (!pHWall->xw().dudeLockout || actor->IsPlayerActor()))
trTriggerWall(pHWall, kCmdWallTouch);
triggerTouchWall(actor, pHWall);
}
}
// enough to reset SpriteHit values
if (pHWall != nullptr || actor2) actor->vel.X += 5;
}
#endif
}
@ -4804,14 +4798,14 @@ void MoveDude(DBloodActor* actor)
}
#ifdef NOONE_EXTENSIONS
if (!gModernMap && hitActor->hasX() && hitActor->xspr.Touch && !hitActor->xspr.state && !hitActor->xspr.isTriggered)
trTriggerSprite(coll.actor(), kCmdSpriteTouch);
trTriggerSprite(coll.actor(), kCmdSpriteTouch, actor);
#else
if (hitActor->hasX() && hitActor->xspr.Touch && !hitActor->xspr.state && !hitActor->xspr.isTriggered)
trTriggerSprite(coll.actor, kCmdSpriteTouch);
#endif
if (pDudeInfo->lockOut && hitActor->hasX() && hitActor->xspr.Push && !hitActor->xspr.key && !hitActor->xspr.DudeLockout && !hitActor->xspr.state && !hitActor->xspr.busy && !pPlayer)
trTriggerSprite(coll.actor(), kCmdSpritePush);
trTriggerSprite(coll.actor(), kCmdSpritePush, actor);
break;
}
@ -4822,7 +4816,7 @@ void MoveDude(DBloodActor* actor)
if (pHitWall->hasX()) pHitXWall = &pHitWall->xw();
if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer)
trTriggerWall(pHitWall, kCmdWallPush);
trTriggerWall(pHitWall, kCmdWallPush, actor);
if (pHitWall->twoSided())
{
@ -4830,7 +4824,7 @@ void MoveDude(DBloodActor* actor)
XSECTOR* pHitXSector = pHitSector->hasX() ? &pHitSector->xs() : nullptr;
if (pDudeInfo->lockOut && pHitXSector && pHitXSector->Wallpush && !pHitXSector->Key && !pHitXSector->dudeLockout && !pHitXSector->state && !pHitXSector->busy && !pPlayer)
trTriggerSector(pHitSector, kCmdSectorPush);
trTriggerSector(pHitSector, kCmdSectorPush, actor);
if (top < pHitSector->ceilingz || bottom > pHitSector->floorz)
{
@ -4857,14 +4851,14 @@ void MoveDude(DBloodActor* actor)
XSECTOR* pXOldSector = pOldSector->hasX() ? &pOldSector->xs() : nullptr;
if (pXOldSector && pXOldSector->Exit && (pPlayer || !pXOldSector->dudeLockout))
trTriggerSector(pOldSector, kCmdSectorExit);
trTriggerSector(pOldSector, kCmdSectorExit, actor);
ChangeActorSect(actor, pSector);
if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout))
{
if (pSector->type == kSectorTeleport)
pXSector->actordata = actor;
trTriggerSector(pSector, kCmdSectorEnter);
trTriggerSector(pSector, kCmdSectorEnter, actor);
}
pSector = actor->sector();
@ -5306,7 +5300,7 @@ int MoveMissile(DBloodActor* actor)
XWALL* pXWall = &pWall->xw();
if (pXWall->triggerVector)
{
trTriggerWall(pWall, kCmdWallImpact);
trTriggerWall(pWall, kCmdWallImpact, Owner? Owner : actor);
if (!(pWall->cstat & CSTAT_WALL_BLOCK_HITSCAN))
{
cliptype = -1;
@ -5638,7 +5632,7 @@ static void actCheckProximity()
break;
}
if (actor->GetOwner() == nullptr) actor->SetOwner(dudeactor);
trTriggerSprite(actor, kCmdSpriteProximity);
trTriggerSprite(actor, kCmdSpriteProximity, dudeactor);
}
}
}
@ -5702,7 +5696,7 @@ static void actCheckThings()
Collision hit = MoveThing(actor);
if (hit.type)
{
if (actor->xspr.Impact) trTriggerSprite(actor, kCmdOff);
if (actor->xspr.Impact) trTriggerSprite(actor, kCmdOff, hit.type == kHitSprite? hit.safeActor() : nullptr);
switch (actor->spr.type)
{
@ -5814,7 +5808,7 @@ static void actCheckExplosion()
for (auto pWall : affectedXWalls)
{
trTriggerWall(pWall, kCmdWallImpact);
trTriggerWall(pWall, kCmdWallImpact, Owner);
}
BloodStatIterator it1(kStatDude);
@ -5906,7 +5900,7 @@ static void actCheckExplosion()
if (!CheckSector(sectorMap, impactactor) || !CheckProximity(impactactor, x, y, z, pSector, radius))
continue;
trTriggerSprite(impactactor, kCmdSpriteImpact);
trTriggerSprite(impactactor, kCmdSpriteImpact, Owner);
}
}
@ -6043,7 +6037,7 @@ static void actCheckDudes()
if (actor2->IsPlayerActor() && (unsigned int)actor2->xspr.health > 0)
{
if (CheckProximity(actor2, actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, actor->sector(), 128))
trTriggerSprite(actor, kCmdSpriteProximity);
trTriggerSprite(actor, kCmdSpriteProximity, actor2);
}
}
}
@ -6772,7 +6766,7 @@ void actFireVector(DBloodActor* shooter, int a2, int a3, int a4, int a5, int a6,
if (pWall->hasX())
{
if (pWall->xw().triggerVector)
trTriggerWall(pWall, kCmdWallImpact);
trTriggerWall(pWall, kCmdWallImpact, shooter);
}
break;
}
@ -6787,7 +6781,7 @@ void actFireVector(DBloodActor* shooter, int a2, int a3, int a4, int a5, int a6,
if (vectorType == kVectorTine && !actor->IsPlayerActor()) shift = 3;
actDamageSprite(shooter, actor, pVectorData->dmgType, pVectorData->dmg << shift);
if (actor->hasX() && actor->xspr.Vector) trTriggerSprite(actor, kCmdSpriteImpact);
if (actor->hasX() && actor->xspr.Vector) trTriggerSprite(actor, kCmdSpriteImpact, shooter);
if (actor->spr.statnum == kStatThing)
{

View file

@ -142,7 +142,7 @@ void cultThrowSeqCallback(int, DBloodActor* actor)
if (v4)
pMissile->xspr.Impact = 1;
else
evPostActor(pMissile, 120 * (1 + Random(2)), kCmdOn);
evPostActor(pMissile, 120 * (1 + Random(2)), kCmdOn, actor);
}
void sub_68170(int, DBloodActor* actor)
@ -152,7 +152,7 @@ void sub_68170(int, DBloodActor* actor)
nMissile = kThingArmedTNTBundle;
sfxPlay3DSound(actor, 455, -1, 0);
auto pMissile = actFireThing(actor, 0, 0, actor->dudeSlope - 9460, nMissile, 0x133333);
evPostActor(pMissile, 120 * (2 + Random(2)), kCmdOn);
evPostActor(pMissile, 120 * (2 + Random(2)), kCmdOn, actor);
}
void sub_68230(int, DBloodActor* actor)

View file

@ -387,7 +387,7 @@ static void ThrowThing(DBloodActor* actor, bool impact)
if (impact == true && dist <= 7680) spawned->xspr.Impact = true;
else {
spawned->xspr.Impact = false;
evPostActor(spawned, 120 * Random(2) + 120, kCmdOn);
evPostActor(spawned, 120 * Random(2) + 120, kCmdOn, actor);
}
}
@ -1973,7 +1973,7 @@ void genDudeTransform(DBloodActor* actor)
if (actIncarnation == NULL)
{
if (actor->xspr.sysData1 == kGenDudeTransformStatus) actor->xspr.sysData1 = 0;
trTriggerSprite(actor, kCmdOff);
trTriggerSprite(actor, kCmdOff, actor);
return;
}
@ -1988,7 +1988,7 @@ void genDudeTransform(DBloodActor* actor)
actIncarnation->xspr.triggerOff = false;
// trigger dude death before transform
trTriggerSprite(actor, kCmdOff);
trTriggerSprite(actor, kCmdOff, actor);
actor->spr.type = actor->spr.inittype = actIncarnation->spr.type;
actor->spr.flags = actIncarnation->spr.flags;

View file

@ -593,13 +593,13 @@ void returnFlagToBase(DBloodActor* actor, sectortype*) // 17
switch (actor->spr.type)
{
case kItemFlagA:
trTriggerSprite(aOwner, kCmdOn);
trTriggerSprite(aOwner, kCmdOn, aOwner);
sndStartSample(8003, 255, 2, 0);
gBlueFlagDropped = false;
viewSetMessage("Blue Flag returned to base.");
break;
case kItemFlagB:
trTriggerSprite(aOwner, kCmdOn);
trTriggerSprite(aOwner, kCmdOn, aOwner);
sndStartSample(8002, 255, 2, 0);
gRedFlagDropped = false;
viewSetMessage("Red Flag returned to base.");

View file

@ -349,7 +349,7 @@ static bool evGetSourceState(EventObject& eob)
//
//---------------------------------------------------------------------------
void evSend(EventObject& eob, int rxId, COMMAND_ID command)
void evSend(EventObject& eob, int rxId, COMMAND_ID command, DBloodActor* initiator)
{
switch (command) {
case kCmdState:
@ -365,6 +365,7 @@ void evSend(EventObject& eob, int rxId, COMMAND_ID command)
EVENT event;
event.target = eob;
event.cmd = command;
event.initiator = gModernMap? initiator : nullptr;
switch (rxId) {
case kChannelTextOver:
@ -459,17 +460,46 @@ void evSend(EventObject& eob, int rxId, COMMAND_ID command)
if (playerRXRngIsFine(rxId))
{
if ((pPlayer = getPlayerById((rxId - kChannelPlayer7) + kMaxPlayers)) != nullptr)
trMessageSprite(pPlayer->actor, event);
{
if (command == kCmdEventKillFull)
evKillActor(pPlayer->actor);
else
trMessageSprite(pPlayer->actor, event);
}
}
else if (rxId == kChannelAllPlayers)
{
for (int i = 0; i < kMaxPlayers; i++)
{
if ((pPlayer = getPlayerById(i)) != nullptr)
trMessageSprite(pPlayer->actor, event);
{
if (command == kCmdEventKillFull)
evKillActor(pPlayer->actor);
else
trMessageSprite(pPlayer->actor, event);
}
}
return;
}
// send command on sprite which created the event sequence
else if (rxId == kChannelEventCauser && event.initiator != nullptr)
{
DBloodActor* einitiator = event.initiator;
if (!(einitiator->spr.flags & kHitagFree) && !(einitiator->spr.flags & kHitagRespawn))
{
if (command == kCmdEventKillFull)
evKillActor(einitiator);
else
trMessageSprite(einitiator, event);
}
return;
}
else if (command == kCmdEventKillFull)
{
killEvents(rxId, command);
return;
}
}
#endif
@ -506,12 +536,12 @@ void evSend(EventObject& eob, int rxId, COMMAND_ID command)
//
//---------------------------------------------------------------------------
void evPost_(EventObject& eob, unsigned int nDelta, COMMAND_ID command)
void evPost_(EventObject& eob, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator)
{
assert(command != kCmdCallback);
if (command == kCmdState) command = evGetSourceState(eob) ? kCmdOn : kCmdOff;
else if (command == kCmdNotState) command = evGetSourceState(eob) ? kCmdOff : kCmdOn;
EVENT evn = { eob, (int8_t)command, 0, PlayClock + (int)nDelta };
EVENT evn = { eob, (int8_t)command, 0, PlayClock + (int)nDelta, MakeObjPtr(gModernMap ? initiator : nullptr) };
queue.insert(evn);
}
@ -522,10 +552,10 @@ void evPost_(const EventObject& eob, unsigned int nDelta, CALLBACK_ID callback)
}
void evPostActor(DBloodActor* actor, unsigned int nDelta, COMMAND_ID command)
void evPostActor(DBloodActor* actor, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator)
{
auto ev = EventObject(actor);
evPost_(ev, nDelta, command);
evPost_(ev, nDelta, command, initiator);
}
void evPostActor(DBloodActor* actor, unsigned int nDelta, CALLBACK_ID callback)
@ -533,10 +563,10 @@ void evPostActor(DBloodActor* actor, unsigned int nDelta, CALLBACK_ID callback)
evPost_(EventObject(actor), nDelta, callback);
}
void evPostSector(sectortype* sect, unsigned int nDelta, COMMAND_ID command)
void evPostSector(sectortype* sect, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator)
{
auto ev = EventObject(sect);
evPost_(ev, nDelta, command);
evPost_(ev, nDelta, command, initiator);
}
void evPostSector(sectortype* sect, unsigned int nDelta, CALLBACK_ID callback)
@ -544,10 +574,10 @@ void evPostSector(sectortype* sect, unsigned int nDelta, CALLBACK_ID callback)
evPost_(EventObject(sect), nDelta, callback);
}
void evPostWall(walltype* wal, unsigned int nDelta, COMMAND_ID command)
void evPostWall(walltype* wal, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator)
{
auto ev = EventObject(wal);
evPost_(ev, nDelta, command);
evPost_(ev, nDelta, command, initiator);
}
@ -566,6 +596,15 @@ void evKill_(const EventObject& eob)
}
}
void evKill_(const EventObject& eob, DBloodActor* initiator)
{
for (auto ev = queue.begin(); ev != queue.end();)
{
if (ev->event_isObject(eob) && ev->initiator.ForceGet() == initiator) ev = queue.erase(ev);
else ev++;
}
}
void evKill_(const EventObject& eob, CALLBACK_ID cb)
{
for (auto ev = queue.begin(); ev != queue.end();)
@ -580,6 +619,14 @@ void evKillActor(DBloodActor* actor)
evKill_(EventObject(actor));
}
void evKillActor(DBloodActor* actor, DBloodActor* initiator)
{
if (!gModernMap)
evKill_(EventObject(actor));
else
evKill_(EventObject(actor), initiator);
}
void evKillActor(DBloodActor* actor, CALLBACK_ID cb)
{
evKill_(EventObject(actor));
@ -595,29 +642,39 @@ void evKillSector(sectortype* sec)
evKill_(EventObject(sec));
}
void evKillWall(walltype* wal, DBloodActor* initiator)
{
evKill_(EventObject(wal), initiator);
}
void evKillSector(sectortype* sec, DBloodActor* initiator)
{
evKill_(EventObject(sec), initiator);
}
// these have no target.
void evSendGame(int rxId, COMMAND_ID command)
void evSendGame(int rxId, COMMAND_ID command, DBloodActor* initiator = nullptr)
{
auto ev = EventObject(nullptr);
evSend(ev, rxId, command);
evSend(ev, rxId, command, initiator);
}
void evSendActor(DBloodActor* actor, int rxId, COMMAND_ID command)
void evSendActor(DBloodActor* actor, int rxId, COMMAND_ID command, DBloodActor* initiator = nullptr)
{
auto ev = EventObject(actor);
evSend(ev, rxId, command);
evSend(ev, rxId, command, initiator);
}
void evSendSector(sectortype* sect, int rxId, COMMAND_ID command)
void evSendSector(sectortype* sect, int rxId, COMMAND_ID command, DBloodActor* initiator = nullptr)
{
auto ev = EventObject(sect);
evSend(ev, rxId, command);
evSend(ev, rxId, command, initiator);
}
void evSendWall(walltype* wal, int rxId, COMMAND_ID command)
void evSendWall(walltype* wal, int rxId, COMMAND_ID command, DBloodActor* initiator = nullptr)
{
auto ev = EventObject(wal);
evSend(ev, rxId, command);
evSend(ev, rxId, command, initiator);
}
//---------------------------------------------------------------------------
@ -703,6 +760,7 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, EVENT& w, EVENT* d
("command", w.cmd)
("func", w.funcID)
("prio", w.priority)
("initiator",w.initiator)
.EndObject();
}
return arc;

View file

@ -158,6 +158,7 @@ enum COMMAND_ID {
kCmdSectorMotionPause = 13, // stops motion of the sector
kCmdSectorMotionContinue = 14, // continues motion of the sector
kCmdDudeFlagsSet = 15, // copy dudeFlags from sprite to dude
kCmdEventKillFull = 16, // immediately kill the pending object events
kCmdModernUse = 53, // used by most of modern types
#endif
@ -192,6 +193,7 @@ struct EVENT
int8_t cmd;
int16_t funcID;
int priority;
TObjPtr<DBloodActor*> initiator;
bool operator<(const EVENT& other) const
{
@ -238,16 +240,17 @@ struct EVENT
};
void evInit(TArray<DBloodActor*>& actors);
void evPostActor(DBloodActor*, unsigned int nDelta, COMMAND_ID command);
void evPostActor(DBloodActor*, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator);
void evPostActor(DBloodActor*, unsigned int nDelta, CALLBACK_ID callback);
void evPostSector(sectortype* index, unsigned int nDelta, COMMAND_ID command);
void evPostSector(sectortype* index, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator);
void evPostSector(sectortype* index, unsigned int nDelta, CALLBACK_ID callback);
void evPostWall(walltype* index, unsigned int nDelta, COMMAND_ID command);
void evPostWall(walltype* index, unsigned int nDelta, COMMAND_ID command, DBloodActor* initiator);
void evProcess(unsigned int nTime);
void evKillActor(DBloodActor*);
void evKillActor(DBloodActor*, DBloodActor* initiator);
void evKillActor(DBloodActor*, CALLBACK_ID a3);
END_BLD_NS

File diff suppressed because it is too large Load diff

View file

@ -64,6 +64,7 @@ enum
kModernTypeFlag4 = 0x0004,
kModernTypeFlag8 = 0x0008,
kModernTypeFlag16 = 0x0010,
kModernTypeFlag64 = 0x0040,
kMaxRandomizeRetries = 16,
kPercFull = 100,
@ -139,6 +140,7 @@ enum {
kModernCondition = 501, /// WIP, sends command only if specified conditions == true
kModernConditionFalse = 502, /// WIP, sends command only if specified conditions != true
kModernSlopeChanger = 504,
kModernVelocityChanger = 506,
kGenModernMissileUniversal = 704,
kGenModernSound = 708,
};
@ -322,11 +324,12 @@ void useDataChanger(DBloodActor* sourceactor, int objType, sectortype* pSector,
void useSectorLightChanger(DBloodActor* pXSource, sectortype* pSector);
void useTargetChanger(DBloodActor* sourceactor, DBloodActor* actor);
void usePictureChanger(DBloodActor* sourceactor, int objType, sectortype*, walltype*, DBloodActor* objActor);
void useSequentialTx(DBloodActor* pXSource, COMMAND_ID cmd, bool setState);
void useRandomTx(DBloodActor* sourceactor, COMMAND_ID cmd, bool setState);
void useSequentialTx(DBloodActor* pXSource, COMMAND_ID cmd, bool setState, DBloodActor* initiator);
void useRandomTx(DBloodActor* sourceactor, COMMAND_ID cmd, bool setState, DBloodActor* initiator);
void useDudeSpawn(DBloodActor* pXSource, DBloodActor* pSprite);
void useCustomDudeSpawn(DBloodActor* pXSource, DBloodActor* pSprite);
void seqTxSendCmdAll(DBloodActor* pXSource, DBloodActor* nIndex, COMMAND_ID cmd, bool modernSend);
void useVelocityChanger(DBloodActor* pXSource, sectortype* sect, DBloodActor* causerID, DBloodActor* pSprite);
void seqTxSendCmdAll(DBloodActor* pXSource, DBloodActor* nIndex, COMMAND_ID cmd, bool modernSend, DBloodActor* initiator);
// ------------------------------------------------------------------------- //
void trPlayerCtrlLink(DBloodActor* pXSource, PLAYER* pPlayer, bool checkCondition);
void trPlayerCtrlStopScene(PLAYER* pPlayer);
@ -335,7 +338,7 @@ void modernTypeTrigger(int type, sectortype* sect, walltype* wal, DBloodActor* a
bool modernTypeOperateSector(sectortype* pSector, const EVENT& event);
bool modernTypeOperateSprite(DBloodActor*, EVENT& event);
bool modernTypeOperateWall(walltype* pWall, const EVENT& event);
void modernTypeSendCommand(DBloodActor* nSprite, int channel, COMMAND_ID command);
void modernTypeSendCommand(DBloodActor* nSprite, int channel, COMMAND_ID command, DBloodActor* initiator);
// ------------------------------------------------------------------------- //
bool playerSizeShrink(PLAYER* pPlayer, int divider);
bool playerSizeGrow(PLAYER* pPlayer, int multiplier);
@ -371,6 +374,11 @@ void condError(DBloodActor* pXCond, const char* pzFormat, ...);
void condUpdateObjectIndex(DBloodActor* oldplayer, DBloodActor* newplayer);
DBloodActor* evrListRedirectors(int objType, sectortype*, walltype*, DBloodActor* objActor, DBloodActor* pXRedir, int* tx);
void seqSpawnerOffSameTx(DBloodActor* actor);
void triggerTouchSprite(DBloodActor* pSprite, DBloodActor* nHSprite);
void triggerTouchWall(DBloodActor* pSprite, walltype* nHWall);
void killEvents(int nRx, int nCmd);
void changeSpriteAngle(DBloodActor* pSpr, int nAng);
int getVelocityAngle(DBloodActor* pSpr);
// ------------------------------------------------------------------------- //
void aiPatrolSetMarker(DBloodActor* actor);
void aiPatrolThink(DBloodActor* actor);

View file

@ -60,13 +60,13 @@ unsigned int GetWaveValue(unsigned int nPhase, int nType)
//
//---------------------------------------------------------------------------
bool SetSpriteState(DBloodActor* actor, int nState)
bool SetSpriteState(DBloodActor* actor, int nState, DBloodActor* initiator)
{
if ((actor->xspr.busy & 0xffff) == 0 && actor->xspr.state == nState)
return 0;
actor->xspr.busy = IntToFixed(nState);
actor->xspr.state = nState;
evKillActor(actor);
evKillActor(actor, initiator);
if ((actor->spr.flags & kHitagRespawn) != 0 && actor->spr.inittype >= kDudeBase && actor->spr.inittype < kDudeMax)
{
actor->xspr.respawnPending = 3;
@ -74,13 +74,13 @@ bool SetSpriteState(DBloodActor* actor, int nState)
return 1;
}
if (actor->xspr.restState != nState && actor->xspr.waitTime > 0)
evPostActor(actor, (actor->xspr.waitTime * 120) / 10, actor->xspr.restState ? kCmdOn : kCmdOff);
evPostActor(actor, (actor->xspr.waitTime * 120) / 10, actor->xspr.restState ? kCmdOn : kCmdOff, initiator);
if (actor->xspr.txID)
{
if (actor->xspr.command != kCmdLink && actor->xspr.triggerOn && actor->xspr.state)
evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command);
evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command, initiator);
if (actor->xspr.command != kCmdLink && actor->xspr.triggerOff && !actor->xspr.state)
evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command);
evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command, initiator);
}
return 1;
}
@ -91,22 +91,22 @@ bool SetSpriteState(DBloodActor* actor, int nState)
//
//---------------------------------------------------------------------------
bool SetWallState(walltype* pWall, int nState)
bool SetWallState(walltype* pWall, int nState, DBloodActor* initiator)
{
auto pXWall = &pWall->xw();
if ((pXWall->busy & 0xffff) == 0 && pXWall->state == nState)
return 0;
pXWall->busy = IntToFixed(nState);
pXWall->state = nState;
evKillWall(pWall);
evKillWall(pWall, initiator);
if (pXWall->restState != nState && pXWall->waitTime > 0)
evPostWall(pWall, (pXWall->waitTime * 120) / 10, pXWall->restState ? kCmdOn : kCmdOff);
evPostWall(pWall, (pXWall->waitTime * 120) / 10, pXWall->restState ? kCmdOn : kCmdOff, initiator);
if (pXWall->txID)
{
if (pXWall->command != kCmdLink && pXWall->triggerOn && pXWall->state)
evSendWall(pWall, pXWall->txID, (COMMAND_ID)pXWall->command);
evSendWall(pWall, pXWall->txID, (COMMAND_ID)pXWall->command, initiator);
if (pXWall->command != kCmdLink && pXWall->triggerOff && !pXWall->state)
evSendWall(pWall, pXWall->txID, (COMMAND_ID)pXWall->command);
evSendWall(pWall, pXWall->txID, (COMMAND_ID)pXWall->command, initiator);
}
return 1;
}
@ -117,7 +117,7 @@ bool SetWallState(walltype* pWall, int nState)
//
//---------------------------------------------------------------------------
bool SetSectorState(sectortype* pSector, int nState)
bool SetSectorState(sectortype* pSector, int nState, DBloodActor* initiator)
{
assert(pSector->hasX());
auto pXSector = &pSector->xs();
@ -125,30 +125,30 @@ bool SetSectorState(sectortype* pSector, int nState)
return 0;
pXSector->busy = IntToFixed(nState);
pXSector->state = nState;
evKillSector(pSector);
evKillSector(pSector, initiator);
if (nState == 1)
{
if (pXSector->command != kCmdLink && pXSector->triggerOn && pXSector->txID)
evSendSector(pSector, pXSector->txID, (COMMAND_ID)pXSector->command);
evSendSector(pSector, pXSector->txID, (COMMAND_ID)pXSector->command, initiator);
if (pXSector->stopOn)
{
pXSector->stopOn = 0;
pXSector->stopOff = 0;
}
else if (pXSector->reTriggerA)
evPostSector(pSector, (pXSector->waitTimeA * 120) / 10, kCmdOff);
evPostSector(pSector, (pXSector->waitTimeA * 120) / 10, kCmdOff, initiator);
}
else
{
if (pXSector->command != kCmdLink && pXSector->triggerOff && pXSector->txID)
evSendSector(pSector, pXSector->txID, (COMMAND_ID)pXSector->command);
evSendSector(pSector, pXSector->txID, (COMMAND_ID)pXSector->command, initiator);
if (pXSector->stopOff)
{
pXSector->stopOn = 0;
pXSector->stopOff = 0;
}
else if (pXSector->reTriggerB)
evPostSector(pSector, (pXSector->waitTimeB * 120) / 10, kCmdOn);
evPostSector(pSector, (pXSector->waitTimeB * 120) / 10, kCmdOn, initiator);
}
return 1;
}
@ -172,6 +172,7 @@ void AddBusy(sectortype* pSector, BUSYID a2, int nDelta)
return;
}
}
if (VanillaMode() && gBusy.Size() == 128) return;
BUSY b = { pSector, nDelta, nDelta > 0 ? 0 : 65536, a2 };
gBusy.Push(b);
}
@ -228,7 +229,8 @@ unsigned int GetSourceBusy(EVENT& a1)
void LifeLeechOperate(DBloodActor* actor, EVENT event)
{
switch (event.cmd) {
switch (event.cmd)
{
case kCmdSpritePush:
{
int nPlayer = actor->xspr.data4;
@ -317,6 +319,7 @@ void ActivateGenerator(DBloodActor*);
void OperateSprite(DBloodActor* actor, EVENT event)
{
DBloodActor* initiator = event.initiator;
#ifdef NOONE_EXTENSIONS
if (gModernMap && modernTypeOperateSprite(actor, event))
return;
@ -338,7 +341,7 @@ void OperateSprite(DBloodActor* actor, EVENT event)
switch (event.cmd) {
case kCmdOff:
SetSpriteState(actor, 0);
SetSpriteState(actor, 0, initiator);
break;
case kCmdSpriteProximity:
if (actor->xspr.state) break;
@ -346,7 +349,7 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kCmdOn:
case kCmdSpritePush:
case kCmdSpriteTouch:
if (!actor->xspr.state) SetSpriteState(actor, 1);
if (!actor->xspr.state) SetSpriteState(actor, 1, initiator);
aiActivateDude(actor);
break;
}
@ -360,11 +363,11 @@ void OperateSprite(DBloodActor* actor, EVENT event)
if (actor->xspr.health <= 0) break;
switch (event.cmd) {
case kCmdOff:
if (!SetSpriteState(actor, 0)) break;
if (!SetSpriteState(actor, 0, initiator)) break;
seqSpawn(40, actor, -1);
break;
case kCmdOn:
if (!SetSpriteState(actor, 1)) break;
if (!SetSpriteState(actor, 1, initiator)) break;
seqSpawn(38, actor, nMGunOpenClient);
if (actor->xspr.data1 > 0)
actor->xspr.data2 = actor->xspr.data1;
@ -372,15 +375,15 @@ void OperateSprite(DBloodActor* actor, EVENT event)
}
break;
case kThingFallingRock:
if (SetSpriteState(actor, 1))
if (SetSpriteState(actor, 1, initiator))
actor->spr.flags |= 7;
break;
case kThingWallCrack:
if (SetSpriteState(actor, 0))
if (SetSpriteState(actor, 0, initiator))
actPostSprite(actor, kStatFree);
break;
case kThingCrateFace:
if (SetSpriteState(actor, 0))
if (SetSpriteState(actor, 0, initiator))
actPostSprite(actor, kStatFree);
break;
case kTrapZapSwitchable:
@ -405,12 +408,12 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kTrapFlame:
switch (event.cmd) {
case kCmdOff:
if (!SetSpriteState(actor, 0)) break;
if (!SetSpriteState(actor, 0, initiator)) break;
seqSpawn(40, actor, -1);
sfxKill3DSound(actor, 0, -1);
break;
case kCmdOn:
if (!SetSpriteState(actor, 1)) break;
if (!SetSpriteState(actor, 1, initiator)) break;
seqSpawn(38, actor, -1);
sfxPlay3DSound(actor, 441, 0, 0);
break;
@ -419,14 +422,14 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kSwitchPadlock:
switch (event.cmd) {
case kCmdOff:
SetSpriteState(actor, 0);
SetSpriteState(actor, 0, initiator);
break;
case kCmdOn:
if (!SetSpriteState(actor, 1)) break;
if (!SetSpriteState(actor, 1, initiator)) break;
seqSpawn(37, actor, -1);
break;
default:
SetSpriteState(actor, actor->xspr.state ^ 1);
SetSpriteState(actor, actor->xspr.state ^ 1, initiator);
if (actor->xspr.state) seqSpawn(37, actor, -1);
break;
}
@ -434,15 +437,15 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kSwitchToggle:
switch (event.cmd) {
case kCmdOff:
if (!SetSpriteState(actor, 0)) break;
if (!SetSpriteState(actor, 0, initiator)) break;
sfxPlay3DSound(actor, actor->xspr.data2, 0, 0);
break;
case kCmdOn:
if (!SetSpriteState(actor, 1)) break;
if (!SetSpriteState(actor, 1, initiator)) break;
sfxPlay3DSound(actor, actor->xspr.data1, 0, 0);
break;
default:
if (!SetSpriteState(actor, actor->xspr.state ^ 1)) break;
if (!SetSpriteState(actor, actor->xspr.state ^ 1, initiator)) break;
if (actor->xspr.state) sfxPlay3DSound(actor, actor->xspr.data1, 0, 0);
else sfxPlay3DSound(actor, actor->xspr.data2, 0, 0);
break;
@ -451,15 +454,15 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kSwitchOneWay:
switch (event.cmd) {
case kCmdOff:
if (!SetSpriteState(actor, 0)) break;
if (!SetSpriteState(actor, 0, initiator)) break;
sfxPlay3DSound(actor, actor->xspr.data2, 0, 0);
break;
case kCmdOn:
if (!SetSpriteState(actor, 1)) break;
if (!SetSpriteState(actor, 1, initiator)) break;
sfxPlay3DSound(actor, actor->xspr.data1, 0, 0);
break;
default:
if (!SetSpriteState(actor, actor->xspr.restState ^ 1)) break;
if (!SetSpriteState(actor, actor->xspr.restState ^ 1, initiator)) break;
if (actor->xspr.state) sfxPlay3DSound(actor, actor->xspr.data1, 0, 0);
else sfxPlay3DSound(actor, actor->xspr.data2, 0, 0);
break;
@ -482,12 +485,12 @@ void OperateSprite(DBloodActor* actor, EVENT event)
sfxPlay3DSound(actor, actor->xspr.data4, -1, 0);
if (actor->xspr.command == kCmdLink && actor->xspr.txID > 0)
evSendActor(actor, actor->xspr.txID, kCmdLink);
evSendActor(actor, actor->xspr.txID, kCmdLink, initiator);
if (actor->xspr.data1 == actor->xspr.data2)
SetSpriteState(actor, 1);
SetSpriteState(actor, 1, initiator);
else
SetSpriteState(actor, 0);
SetSpriteState(actor, 0, initiator);
break;
case kMarkerDudeSpawn:
@ -518,7 +521,7 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kMarkerEarthQuake:
actor->xspr.triggerOn = 0;
actor->xspr.isTriggered = 1;
SetSpriteState(actor, 1);
SetSpriteState(actor, 1, initiator);
for (int p = connecthead; p >= 0; p = connectpoint2[p]) {
auto vec = actor->spr.pos - gPlayer[p].actor->spr.pos;
int dx = (vec.X) >> 4;
@ -539,7 +542,7 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kTrapExploder:
switch (event.cmd) {
case kCmdOn:
SetSpriteState(actor, 1);
SetSpriteState(actor, 1, initiator);
break;
default:
actor->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE;
@ -552,7 +555,7 @@ void OperateSprite(DBloodActor* actor, EVENT event)
if (event.cmd != kCmdOn) actExplodeSprite(actor);
else {
sfxPlay3DSound(actor, 454, 0, 0);
evPostActor(actor, 18, kCmdOff);
evPostActor(actor, 18, kCmdOff, initiator);
}
}
break;
@ -562,7 +565,7 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kCmdSpriteProximity:
if (actor->xspr.state) break;
sfxPlay3DSound(actor, 452, 0, 0);
evPostActor(actor, 30, kCmdOff);
evPostActor(actor, 30, kCmdOff, initiator);
actor->xspr.state = 1;
[[fallthrough]];
case kCmdOn:
@ -589,20 +592,20 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kGenSound:
switch (event.cmd) {
case kCmdOff:
SetSpriteState(actor, 0);
SetSpriteState(actor, 0, initiator);
break;
case kCmdRepeat:
if (actor->spr.type != kGenTrigger) ActivateGenerator(actor);
if (actor->xspr.txID) evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command);
if (actor->xspr.txID) evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command, initiator);
if (actor->xspr.busyTime > 0) {
int nRand = Random2(actor->xspr.data1);
evPostActor(actor, 120 * (nRand + actor->xspr.busyTime) / 10, kCmdRepeat);
evPostActor(actor, 120 * (nRand + actor->xspr.busyTime) / 10, kCmdRepeat, initiator);
}
break;
default:
if (!actor->xspr.state) {
SetSpriteState(actor, 1);
evPostActor(actor, 0, kCmdRepeat);
SetSpriteState(actor, 1, initiator);
evPostActor(actor, 0, kCmdRepeat, initiator);
}
break;
}
@ -623,15 +626,15 @@ void OperateSprite(DBloodActor* actor, EVENT event)
case kThingZombieHead:
switch (event.cmd) {
case kCmdOff:
if (!SetSpriteState(actor, 0)) break;
if (!SetSpriteState(actor, 0, initiator)) break;
actActivateGibObject(actor);
break;
case kCmdOn:
if (!SetSpriteState(actor, 1)) break;
if (!SetSpriteState(actor, 1, initiator)) break;
actActivateGibObject(actor);
break;
default:
if (!SetSpriteState(actor, actor->xspr.state ^ 1)) break;
if (!SetSpriteState(actor, actor->xspr.state ^ 1, initiator)) break;
actActivateGibObject(actor);
break;
}
@ -639,13 +642,13 @@ void OperateSprite(DBloodActor* actor, EVENT event)
default:
switch (event.cmd) {
case kCmdOff:
SetSpriteState(actor, 0);
SetSpriteState(actor, 0, initiator);
break;
case kCmdOn:
SetSpriteState(actor, 1);
SetSpriteState(actor, 1, initiator);
break;
default:
SetSpriteState(actor, actor->xspr.state ^ 1);
SetSpriteState(actor, actor->xspr.state ^ 1, initiator);
break;
}
break;
@ -694,7 +697,9 @@ void SetupGibWallState(walltype* pWall, XWALL* pXWall)
//
//---------------------------------------------------------------------------
void OperateWall(walltype* pWall, EVENT event) {
void OperateWall(walltype* pWall, EVENT event)
{
DBloodActor* initiator = event.initiator;
auto pXWall = &pWall->xw();
switch (event.cmd) {
@ -720,13 +725,13 @@ void OperateWall(walltype* pWall, EVENT event) {
switch (event.cmd) {
case kCmdOn:
case kCmdWallImpact:
bStatus = SetWallState(pWall, 1);
bStatus = SetWallState(pWall, 1, initiator);
break;
case kCmdOff:
bStatus = SetWallState(pWall, 0);
bStatus = SetWallState(pWall, 0, initiator);
break;
default:
bStatus = SetWallState(pWall, pXWall->state ^ 1);
bStatus = SetWallState(pWall, pXWall->state ^ 1, initiator);
break;
}
@ -743,13 +748,13 @@ void OperateWall(walltype* pWall, EVENT event) {
default:
switch (event.cmd) {
case kCmdOff:
SetWallState(pWall, 0);
SetWallState(pWall, 0, initiator);
break;
case kCmdOn:
SetWallState(pWall, 1);
SetWallState(pWall, 1, initiator);
break;
default:
SetWallState(pWall, pXWall->state ^ 1);
SetWallState(pWall, pXWall->state ^ 1, initiator);
break;
}
return;
@ -1175,7 +1180,7 @@ DBloodActor* GetCrushedSpriteExtents(sectortype* pSector, int* pzTop, int* pzBot
//
//---------------------------------------------------------------------------
int VCrushBusy(sectortype* pSector, unsigned int a2)
int VCrushBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1202,10 +1207,10 @@ int VCrushBusy(sectortype* pSector, unsigned int a2)
pSector->setfloorz(v10);
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
return 3;
}
@ -1218,7 +1223,7 @@ int VCrushBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int VSpriteBusy(sectortype* pSector, unsigned int a2)
int VSpriteBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1255,10 +1260,10 @@ int VSpriteBusy(sectortype* pSector, unsigned int a2)
}
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
return 3;
}
@ -1271,7 +1276,7 @@ int VSpriteBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int VDoorBusy(sectortype* pSector, unsigned int a2)
int VDoorBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1354,10 +1359,10 @@ int VDoorBusy(sectortype* pSector, unsigned int a2)
ZTranslateSector(pSector, pXSector, a2, nWave);
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
return 3;
}
@ -1370,7 +1375,7 @@ int VDoorBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int HDoorBusy(sectortype* pSector, unsigned int a2)
int HDoorBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1386,10 +1391,10 @@ int HDoorBusy(sectortype* pSector, unsigned int a2)
ZTranslateSector(pSector, pXSector, a2, nWave);
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
return 3;
}
@ -1402,7 +1407,7 @@ int HDoorBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int RDoorBusy(sectortype* pSector, unsigned int a2)
int RDoorBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1417,10 +1422,10 @@ int RDoorBusy(sectortype* pSector, unsigned int a2)
ZTranslateSector(pSector, pXSector, a2, nWave);
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
return 3;
}
@ -1433,7 +1438,7 @@ int RDoorBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int StepRotateBusy(sectortype* pSector, unsigned int a2)
int StepRotateBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1454,10 +1459,10 @@ int StepRotateBusy(sectortype* pSector, unsigned int a2)
}
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
pXSector->data = vbp & 2047;
return 3;
@ -1471,16 +1476,16 @@ int StepRotateBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int GenSectorBusy(sectortype* pSector, unsigned int a2)
int GenSectorBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
pXSector->busy = a2;
if (pXSector->command == kCmdLink && pXSector->txID)
evSendSector(pSector, pXSector->txID, kCmdLink);
evSendSector(pSector, pXSector->txID, kCmdLink, initiator);
if ((a2 & 0xffff) == 0)
{
SetSectorState(pSector, FixedToInt(a2));
SetSectorState(pSector, FixedToInt(a2), initiator);
SectorEndSound(pSector, FixedToInt(a2));
return 3;
}
@ -1493,7 +1498,7 @@ int GenSectorBusy(sectortype* pSector, unsigned int a2)
//
//---------------------------------------------------------------------------
int PathBusy(sectortype* pSector, unsigned int a2)
int PathBusy(sectortype* pSector, unsigned int a2, DBloodActor* initiator)
{
assert(pSector && pSector->hasX());
XSECTOR* pXSector = &pSector->xs();
@ -1509,7 +1514,7 @@ int PathBusy(sectortype* pSector, unsigned int a2)
pXSector->busy = a2;
if ((a2 & 0xffff) == 0)
{
evPostSector(pSector, (120 * marker1->xspr.waitTime) / 10, kCmdOn);
evPostSector(pSector, (120 * marker1->xspr.waitTime) / 10, kCmdOn, initiator);
pXSector->state = 0;
pXSector->busy = 0;
if (marker0->xspr.data4)
@ -1676,7 +1681,7 @@ void OperatePath(sectortype* pSector, EVENT event)
// trigger marker after it gets reached
#ifdef NOONE_EXTENSIONS
if (gModernMap && marker0->xspr.state != 1)
trTriggerSprite(pXSector->marker0, kCmdOn);
trTriggerSprite(pXSector->marker0, kCmdOn, event.initiator);
#endif
if (actor == nullptr) {
@ -1778,17 +1783,18 @@ void OperateSector(sectortype* pSector, EVENT event)
OperatePath(pSector, event);
break;
default:
if (!pXSector->busyTimeA && !pXSector->busyTimeB) {
if (!pXSector->busyTimeA && !pXSector->busyTimeB)
{
DBloodActor* initiator = event.initiator;
switch (event.cmd) {
case kCmdOff:
SetSectorState(pSector, 0);
SetSectorState(pSector, 0, initiator);
break;
case kCmdOn:
SetSectorState(pSector, 1);
SetSectorState(pSector, 1, initiator);
break;
default:
SetSectorState(pSector, pXSector->state ^ 1);
SetSectorState(pSector, pXSector->state ^ 1, initiator);
break;
}
@ -1835,7 +1841,7 @@ void InitPath(sectortype* pSector, XSECTOR* pXSector)
pXSector->basePath = pXSector->marker0 = actor;
if (pXSector->state)
evPostSector(pSector, 0, kCmdOn);
evPostSector(pSector, 0, kCmdOn, nullptr);
}
//---------------------------------------------------------------------------
@ -1846,27 +1852,28 @@ void InitPath(sectortype* pSector, XSECTOR* pXSector)
void LinkSector(sectortype* pSector, EVENT event)
{
DBloodActor* initiator = event.initiator;
auto pXSector = &pSector->xs();
int nBusy = GetSourceBusy(event);
switch (pSector->type) {
case kSectorZMotionSprite:
VSpriteBusy(pSector, nBusy);
VSpriteBusy(pSector, nBusy, initiator);
break;
case kSectorZMotion:
VDoorBusy(pSector, nBusy);
VDoorBusy(pSector, nBusy, initiator);
break;
case kSectorSlideMarked:
case kSectorSlide:
HDoorBusy(pSector, nBusy);
HDoorBusy(pSector, nBusy, initiator);
break;
case kSectorRotateMarked:
case kSectorRotate:
RDoorBusy(pSector, nBusy);
RDoorBusy(pSector, nBusy, initiator);
break;
default:
pXSector->busy = nBusy;
if ((pXSector->busy & 0xffff) == 0)
SetSectorState(pSector, FixedToInt(nBusy));
SetSectorState(pSector, FixedToInt(nBusy), initiator);
break;
}
}
@ -1879,6 +1886,7 @@ void LinkSector(sectortype* pSector, EVENT event)
void LinkSprite(DBloodActor* actor, EVENT event)
{
DBloodActor* initiator = event.initiator;
int nBusy = GetSourceBusy(event);
switch (actor->spr.type) {
@ -1890,9 +1898,9 @@ void LinkSprite(DBloodActor* actor, EVENT event)
actor->xspr.data1 = actor2 && actor2->hasX() ? actor2->xspr.data1 : 0;
if (actor->xspr.data1 == actor->xspr.data2)
SetSpriteState(actor, 1);
SetSpriteState(actor, 1, initiator);
else
SetSpriteState(actor, 0);
SetSpriteState(actor, 0, initiator);
}
}
break;
@ -1900,7 +1908,7 @@ void LinkSprite(DBloodActor* actor, EVENT event)
{
actor->xspr.busy = nBusy;
if ((actor->xspr.busy & 0xffff) == 0)
SetSpriteState(actor, FixedToInt(nBusy));
SetSpriteState(actor, FixedToInt(nBusy), initiator);
}
break;
}
@ -1917,7 +1925,7 @@ void LinkWall(walltype* pWall, EVENT& event)
int nBusy = GetSourceBusy(event);
pWall->xw().busy = nBusy;
if ((pWall->xw().busy & 0xffff) == 0)
SetWallState(pWall, FixedToInt(nBusy));
SetWallState(pWall, FixedToInt(nBusy), event.initiator);
}
//---------------------------------------------------------------------------
@ -1926,7 +1934,7 @@ void LinkWall(walltype* pWall, EVENT& event)
//
//---------------------------------------------------------------------------
void trTriggerSector(sectortype* pSector, int command)
void trTriggerSector(sectortype* pSector, int command, DBloodActor* initiator)
{
auto pXSector = &pSector->xs();
if (!pXSector->locked && !pXSector->isTriggered) {
@ -1935,11 +1943,12 @@ void trTriggerSector(sectortype* pSector, int command)
pXSector->isTriggered = 1;
if (pXSector->decoupled && pXSector->txID > 0)
evSendSector(pSector, pXSector->txID, (COMMAND_ID)pXSector->command);
evSendSector(pSector, pXSector->txID, (COMMAND_ID)pXSector->command, initiator);
else {
EVENT event;
event.cmd = command;
event.initiator = gModernMap? initiator : nullptr;
OperateSector(pSector, event);
}
@ -1952,7 +1961,7 @@ void trTriggerSector(sectortype* pSector, int command)
//
//---------------------------------------------------------------------------
void trTriggerWall(walltype* pWall, int command)
void trTriggerWall(walltype* pWall, int command, DBloodActor* initiator)
{
if (!pWall->hasX()) return;
auto pXWall = &pWall->xw();
@ -1962,11 +1971,12 @@ void trTriggerWall(walltype* pWall, int command)
pXWall->isTriggered = 1;
if (pXWall->decoupled && pXWall->txID > 0)
evSendWall(pWall, pXWall->txID, (COMMAND_ID)pXWall->command);
evSendWall(pWall, pXWall->txID, (COMMAND_ID)pXWall->command, initiator);
else {
EVENT event;
event.cmd = command;
event.initiator = gModernMap ? initiator : nullptr;
OperateWall(pWall, event);
}
@ -1979,7 +1989,7 @@ void trTriggerWall(walltype* pWall, int command)
//
//---------------------------------------------------------------------------
void trTriggerSprite(DBloodActor* actor, int command)
void trTriggerSprite(DBloodActor* actor, int command, DBloodActor* initiator)
{
if (!actor->xspr.locked && !actor->xspr.isTriggered) {
@ -1987,11 +1997,12 @@ void trTriggerSprite(DBloodActor* actor, int command)
actor->xspr.isTriggered = 1;
if (actor->xspr.Decoupled && actor->xspr.txID > 0)
evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command);
evSendActor(actor, actor->xspr.txID, (COMMAND_ID)actor->xspr.command, initiator);
else {
EVENT event;
event.cmd = command;
event.initiator = gModernMap ? initiator : nullptr;
OperateSprite(actor, event);
}
@ -2198,7 +2209,7 @@ void AlignSlopes(void)
//
//---------------------------------------------------------------------------
int(*gBusyProc[])(sectortype*, unsigned int) =
int(*gBusyProc[])(sectortype*, unsigned int, DBloodActor*) =
{
VCrushBusy,
VSpriteBusy,
@ -2222,7 +2233,7 @@ void trProcessBusy(void)
int oldBusy = gBusy[i].busy;
gBusy[i].busy = ClipRange(oldBusy + gBusy[i].delta * 4, 0, 65536);
#ifdef NOONE_EXTENSIONS
if (!gModernMap || !gBusy[i].sect->xs().unused1) nStatus = gBusyProc[gBusy[i].type](gBusy[i].sect, gBusy[i].busy);
if (!gModernMap || !gBusy[i].sect->xs().unused1) nStatus = gBusyProc[gBusy[i].type](gBusy[i].sect, gBusy[i].busy, nullptr);
else nStatus = 3; // allow to pause/continue motion for sectors any time by sending special command
#else
nStatus = gBusyProc[gBusy[i].type](gBusy[i].at0, gBusy[i].at8);
@ -2382,9 +2393,9 @@ void trInit(TArray<DBloodActor*>& actors)
case kModernRandom2:
if (!gModernMap || actor->xspr.state == actor->xspr.restState) break;
evPostActor(actor, (120 * actor->xspr.busyTime) / 10, kCmdRepeat);
evPostActor(actor, (120 * actor->xspr.busyTime) / 10, kCmdRepeat, actor);
if (actor->xspr.waitTime > 0)
evPostActor(actor, (actor->xspr.waitTime * 120) / 10, actor->xspr.restState ? kCmdOn : kCmdOff);
evPostActor(actor, (actor->xspr.waitTime * 120) / 10, actor->xspr.restState ? kCmdOn : kCmdOff, actor);
break;
case kModernSeqSpawner:
case kModernObjDataAccumulator:
@ -2392,9 +2403,9 @@ void trInit(TArray<DBloodActor*>& actors)
case kModernEffectSpawner:
case kModernWindGenerator:
if (actor->xspr.state == actor->xspr.restState) break;
evPostActor(actor, 0, kCmdRepeat);
evPostActor(actor, 0, kCmdRepeat, actor);
if (actor->xspr.waitTime > 0)
evPostActor(actor, (actor->xspr.waitTime * 120) / 10, actor->xspr.restState ? kCmdOn : kCmdOff);
evPostActor(actor, (actor->xspr.waitTime * 120) / 10, actor->xspr.restState ? kCmdOn : kCmdOff, actor);
break;
#endif
case kGenTrigger:
@ -2473,7 +2484,7 @@ void InitGenerator(DBloodActor* actor)
break;
}
if (actor->xspr.state != actor->xspr.restState && actor->xspr.busyTime > 0)
evPostActor(actor, (120 * (actor->xspr.busyTime + Random2(actor->xspr.data1))) / 10, kCmdRepeat);
evPostActor(actor, (120 * (actor->xspr.busyTime + Random2(actor->xspr.data1))) / 10, kCmdRepeat, actor);
}
//---------------------------------------------------------------------------
@ -2550,7 +2561,7 @@ void MGunFireSeqCallback(int, DBloodActor* actor)
{
actor->xspr.data2--;
if (actor->xspr.data2 == 0)
evPostActor(actor, 1, kCmdOff);
evPostActor(actor, 1, kCmdOff, actor);
}
int dx = bcos(actor->spr.ang) + Random2(1000);
int dy = bsin(actor->spr.ang) + Random2(1000);

View file

@ -51,18 +51,18 @@ struct BUSY {
extern TArray<BUSY> gBusy;
void trTriggerSector(sectortype* pSector, int command);
void trTriggerSector(sectortype* pSector, int command, DBloodActor* initiator = nullptr);
void trMessageSector(sectortype* pSector, EVENT event);
void trTriggerWall(walltype*, int command);
void trTriggerWall(walltype*, int command, DBloodActor* initiator = nullptr);
void trMessageWall(walltype* pWall, EVENT& event);
void trTriggerSprite(DBloodActor* actor, int command);
void trTriggerSprite(DBloodActor* actor, int command, DBloodActor* initiator = nullptr);
void trMessageSprite(DBloodActor* actor, EVENT event);
void trProcessBusy(void);
void trInit(TArray<DBloodActor*>& actors);
void trTextOver(int nId);
bool SetSpriteState(DBloodActor* actor, int nState);
bool SetWallState(walltype* pWall, int nState);
bool SetSectorState(sectortype* pSector, int nState);
bool SetSpriteState(DBloodActor* actor, int nState, DBloodActor* initiator);
bool SetWallState(walltype* pWall, int nState, DBloodActor* initiator);
bool SetSectorState(sectortype* pSector, int nState, DBloodActor* initiator);
void TeleFrag(DBloodActor* killer, sectortype* pSector);
void SectorStartSound(sectortype* pSector, int nState);
void SectorEndSound(sectortype* pSector, int nState);

View file

@ -1198,7 +1198,7 @@ void ThrowCan(int, PLAYER* pPlayer)
{
sfxPlay3DSound(spawned, 441, 0, 0);
spawned->spr.shade = -128;
evPostActor(spawned, pPlayer->fuseTime, kCmdOn);
evPostActor(spawned, pPlayer->fuseTime, kCmdOn, pPlayer->actor);
spawned->xspr.Impact = 1;
UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
pPlayer->throwPower = 0;
@ -1217,7 +1217,7 @@ void DropCan(int, PLAYER* pPlayer)
auto spawned = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0);
if (spawned)
{
evPostActor(spawned, pPlayer->fuseTime, kCmdOn);
evPostActor(spawned, pPlayer->fuseTime, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
}
}
@ -1234,7 +1234,7 @@ void ExplodeCan(int, PLAYER* pPlayer)
auto spawned = playerFireThing(pPlayer, 0, 0, kThingArmedSpray, 0);
if (spawned)
{
evPostActor(spawned, 0, kCmdOn);
evPostActor(spawned, 0, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 6, gAmmoItemData[0].count);
StartQAV(pPlayer, kQAVCANBOOM);
pPlayer->curWeapon = kWeapNone;
@ -1259,7 +1259,7 @@ void ThrowBundle(int, PLAYER* pPlayer)
if (pPlayer->fuseTime < 0)
spawned->xspr.Impact = 1;
else
evPostActor(spawned, pPlayer->fuseTime, kCmdOn);
evPostActor(spawned, pPlayer->fuseTime, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 5, 1);
pPlayer->throwPower = 0;
}
@ -1277,7 +1277,7 @@ void DropBundle(int, PLAYER* pPlayer)
auto spawned = playerFireThing(pPlayer, 0, 0, kThingArmedTNTBundle, 0);
if (spawned)
{
evPostActor(spawned, pPlayer->fuseTime, kCmdOn);
evPostActor(spawned, pPlayer->fuseTime, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 5, 1);
}
}
@ -1294,7 +1294,7 @@ void ExplodeBundle(int, PLAYER* pPlayer)
auto spawned = playerFireThing(pPlayer, 0, 0, kThingArmedTNTBundle, 0);
if (spawned)
{
evPostActor(spawned, 0, kCmdOn);
evPostActor(spawned, 0, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 5, 1);
StartQAV(pPlayer, kQAVDYNEXPLO);
pPlayer->curWeapon = kWeapNone;
@ -1315,7 +1315,7 @@ void ThrowProx(int, PLAYER* pPlayer)
auto spawned = playerFireThing(pPlayer, 0, -9460, kThingArmedProxBomb, nSpeed);
if (spawned)
{
evPostActor(spawned, 240, kCmdOn);
evPostActor(spawned, 240, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 10, 1);
pPlayer->throwPower = 0;
}
@ -1332,7 +1332,7 @@ void DropProx(int, PLAYER* pPlayer)
auto spawned = playerFireThing(pPlayer, 0, 0, kThingArmedProxBomb, 0);
if (spawned)
{
evPostActor(spawned, 240, kCmdOn);
evPostActor(spawned, 240, kCmdOn, pPlayer->actor);
UseAmmo(pPlayer, 10, 1);
}
}