- abstracted access to event target objects.

This commit is contained in:
Christoph Oelckers 2021-11-23 17:45:42 +01:00
parent 32874414fd
commit 5bec3be5e9
5 changed files with 109 additions and 65 deletions

View file

@ -577,14 +577,14 @@ void evKillActor(DBloodActor* actor, CALLBACK_ID cb)
evKill_(actor, 0, SS_SPRITE, cb); evKill_(actor, 0, SS_SPRITE, cb);
} }
void evKillWall(int wal) void evKillWall(walltype* wal)
{ {
evKill_(nullptr, wal, SS_WALL); evKill_(nullptr, wallnum(wal), SS_WALL);
} }
void evKillSector(int sec) void evKillSector(sectortype* sec)
{ {
evKill_(nullptr, sec, SS_SECTOR); evKill_(nullptr, sectnum(sec), SS_SECTOR);
} }
// these have no target. // these have no target.

View file

@ -198,6 +198,39 @@ struct EVENT
{ {
return (this->type == type && (this->type != SS_SPRITE ? (this->index_ == index) : (this->actor == actor))); return (this->type == type && (this->type != SS_SPRITE ? (this->index_ == index) : (this->actor == actor)));
} }
bool isActor() const
{
return type == SS_SPRITE;
}
bool isSector() const
{
return type == SS_SECTOR;
}
bool isWall() const
{
return type == SS_WALL;
}
DBloodActor* getActor() const
{
assert(isActor());
return actor;
}
sectortype* getSector() const
{
assert(isSector());
return &sector[index_];
}
walltype* getWall() const
{
assert(isWall());
return &wall[index_];
}
}; };
void evInit(void); void evInit(void);

View file

@ -4769,9 +4769,11 @@ void modernTypeSendCommand(DBloodActor* actor, int destChannel, COMMAND_ID comma
void modernTypeTrigger(int destObjType, int destObjIndex, DBloodActor* destactor, const EVENT& event) void modernTypeTrigger(int destObjType, int destObjIndex, DBloodActor* destactor, const EVENT& event)
{ {
if (event.type != OBJ_SPRITE || !event.actor || !event.actor->hasX()) return; if (!event.isActor()) return;
spritetype* pSource = &event.actor->s(); auto pActor = event.getActor();
XSPRITE* pXSource = &event.actor->x(); if (!pActor || !pActor->hasX()) return;
spritetype* pSource = &pActor->s();
XSPRITE* pXSource = &pActor->x();
switch (destObjType) { switch (destObjType) {
case OBJ_SECTOR: case OBJ_SECTOR:
@ -4803,14 +4805,14 @@ void modernTypeTrigger(int destObjType, int destObjIndex, DBloodActor* destactor
case kModernSequentialTX: case kModernSequentialTX:
if (pSpr->flags & kModernTypeFlag1) if (pSpr->flags & kModernTypeFlag1)
{ {
seqTxSendCmdAll(destactor, event.actor, (COMMAND_ID)pXSource->command, true); seqTxSendCmdAll(destactor, pActor, (COMMAND_ID)pXSource->command, true);
return; return;
} }
useSequentialTx(destactor, (COMMAND_ID)pXSource->command, false); // set next TX id useSequentialTx(destactor, (COMMAND_ID)pXSource->command, false); // set next TX id
break; break;
} }
if (pXSpr->txID <= 0 || pXSpr->txID >= kChannelUserMax) return; if (pXSpr->txID <= 0 || pXSpr->txID >= kChannelUserMax) return;
modernTypeSendCommand(event.actor, pXSpr->txID, (COMMAND_ID)pXSource->command); modernTypeSendCommand(pActor, pXSpr->txID, (COMMAND_ID)pXSource->command);
return; return;
} }
break; break;
@ -4824,7 +4826,7 @@ void modernTypeTrigger(int destObjType, int destObjIndex, DBloodActor* destactor
// allows teleport any sprite from any location to the source destination // allows teleport any sprite from any location to the source destination
case kMarkerWarpDest: case kMarkerWarpDest:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useTeleportTarget(event.actor, destactor); useTeleportTarget(pActor, destactor);
break; break;
// changes slope of sprite or sector // changes slope of sprite or sector
case kModernSlopeChanger: case kModernSlopeChanger:
@ -4832,7 +4834,7 @@ void modernTypeTrigger(int destObjType, int destObjIndex, DBloodActor* destactor
{ {
case OBJ_SPRITE: case OBJ_SPRITE:
case OBJ_SECTOR: case OBJ_SECTOR:
useSlopeChanger(event.actor, destObjType, destObjIndex, destactor); useSlopeChanger(pActor, destObjType, destObjIndex, destactor);
break; break;
} }
break; break;
@ -4842,73 +4844,73 @@ void modernTypeTrigger(int destObjType, int destObjIndex, DBloodActor* destactor
{ {
case OBJ_SPRITE: case OBJ_SPRITE:
case OBJ_SECTOR: case OBJ_SECTOR:
useSpriteDamager(event.actor, destObjType, destObjIndex, destactor); useSpriteDamager(pActor, destObjType, destObjIndex, destactor);
break; break;
} }
break; break;
// can spawn any effect passed in data2 on it's or txID sprite // can spawn any effect passed in data2 on it's or txID sprite
case kModernEffectSpawner: case kModernEffectSpawner:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useEffectGen(event.actor, destactor); useEffectGen(pActor, destactor);
break; break;
// takes data2 as SEQ ID and spawns it on it's or TX ID object // takes data2 as SEQ ID and spawns it on it's or TX ID object
case kModernSeqSpawner: case kModernSeqSpawner:
useSeqSpawnerGen(event.actor, destObjType, destObjIndex, destactor); useSeqSpawnerGen(pActor, destObjType, destObjIndex, destactor);
break; break;
// creates wind on TX ID sector // creates wind on TX ID sector
case kModernWindGenerator: case kModernWindGenerator:
if (destObjType != OBJ_SECTOR || pXSource->data2 < 0) break; if (destObjType != OBJ_SECTOR || pXSource->data2 < 0) break;
useSectorWindGen(event.actor, &sector[destObjIndex]); useSectorWindGen(pActor, &sector[destObjIndex]);
break; break;
// size and pan changer of sprite/wall/sector via TX ID // size and pan changer of sprite/wall/sector via TX ID
case kModernObjSizeChanger: case kModernObjSizeChanger:
useObjResizer(event.actor, destObjType, destObjIndex, destactor); useObjResizer(pActor, destObjType, destObjIndex, destactor);
break; break;
// iterate data filed value of destination object // iterate data filed value of destination object
case kModernObjDataAccumulator: case kModernObjDataAccumulator:
useIncDecGen(event.actor, destObjType, destObjIndex, destactor); useIncDecGen(pActor, destObjType, destObjIndex, destactor);
break; break;
// change data field value of destination object // change data field value of destination object
case kModernObjDataChanger: case kModernObjDataChanger:
useDataChanger(event.actor, destObjType, destObjIndex, destactor); useDataChanger(pActor, destObjType, destObjIndex, destactor);
break; break;
// change sector lighting dynamically // change sector lighting dynamically
case kModernSectorFXChanger: case kModernSectorFXChanger:
if (destObjType != OBJ_SECTOR) break; if (destObjType != OBJ_SECTOR) break;
useSectorLightChanger(event.actor, &sector[destObjIndex]); useSectorLightChanger(pActor, &sector[destObjIndex]);
break; break;
// change target of dudes and make it fight // change target of dudes and make it fight
case kModernDudeTargetChanger: case kModernDudeTargetChanger:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useTargetChanger(event.actor, destactor); useTargetChanger(pActor, destactor);
break; break;
// change picture and palette of TX ID object // change picture and palette of TX ID object
case kModernObjPicnumChanger: case kModernObjPicnumChanger:
usePictureChanger(event.actor, destObjType, destObjIndex, destactor); usePictureChanger(pActor, destObjType, destObjIndex, destactor);
break; break;
// change various properties // change various properties
case kModernObjPropertiesChanger: case kModernObjPropertiesChanger:
usePropertiesChanger(event.actor, destObjType, destObjIndex, destactor); usePropertiesChanger(pActor, destObjType, destObjIndex, destactor);
break; break;
// updated vanilla sound gen that now allows to play sounds on TX ID sprites // updated vanilla sound gen that now allows to play sounds on TX ID sprites
case kGenModernSound: case kGenModernSound:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useSoundGen(event.actor, destactor); useSoundGen(pActor, destactor);
break; break;
// updated ecto skull gen that allows to fire missile from TX ID sprites // updated ecto skull gen that allows to fire missile from TX ID sprites
case kGenModernMissileUniversal: case kGenModernMissileUniversal:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useUniMissileGen(event.actor, destactor); useUniMissileGen(pActor, destactor);
break; break;
// spawn enemies on TX ID sprites // spawn enemies on TX ID sprites
case kMarkerDudeSpawn: case kMarkerDudeSpawn:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useDudeSpawn(event.actor, destactor); useDudeSpawn(pActor, destactor);
break; break;
// spawn custom dude on TX ID sprites // spawn custom dude on TX ID sprites
case kModernCustomDudeSpawn: case kModernCustomDudeSpawn:
if (destObjType != OBJ_SPRITE) break; if (destObjType != OBJ_SPRITE) break;
useCustomDudeSpawn(event.actor, destactor); useCustomDudeSpawn(pActor, destactor);
break; break;
} }
} }
@ -5301,11 +5303,12 @@ void sectorKillSounds(int nSector)
void sectorPauseMotion(int nSector) void sectorPauseMotion(int nSector)
{ {
if (!sector[nSector].hasX()) return; auto pSector = &sector[nSector];
XSECTOR* pXSector = &sector[nSector].xs(); if (!pSector->hasX()) return;
XSECTOR* pXSector = &pSector->xs();
pXSector->unused1 = 1; pXSector->unused1 = 1;
evKillSector(nSector); evKillSector(pSector);
sectorKillSounds(nSector); sectorKillSounds(nSector);
if ((pXSector->busy == 0 && !pXSector->state) || (pXSector->busy == 65536 && pXSector->state)) if ((pXSector->busy == 0 && !pXSector->state) || (pXSector->busy == 65536 && pXSector->state))
@ -5500,7 +5503,7 @@ void useDudeSpawn(DBloodActor* pSource, DBloodActor* pSprite)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool modernTypeOperateSprite(DBloodActor* actor, EVENT event) bool modernTypeOperateSprite(DBloodActor* actor, const EVENT& event)
{ {
auto pSprite = &actor->s(); auto pSprite = &actor->s();
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
@ -5533,21 +5536,24 @@ bool modernTypeOperateSprite(DBloodActor* actor, EVENT event)
} }
else if (event.cmd == kCmdDudeFlagsSet) else if (event.cmd == kCmdDudeFlagsSet)
{ {
if (event.type != OBJ_SPRITE) if (!event.isActor())
{ {
viewSetSystemMessage("Only sprites can use command #%d", event.cmd); viewSetSystemMessage("Only sprites can use command #%d", event.cmd);
return true; return true;
} }
else if (event.actor && event.actor->hasX()) else
{ {
auto pEvActor = event.getActor();
if (pEvActor && pEvActor->hasX())
{
// copy dude flags from the source to destination sprite // copy dude flags from the source to destination sprite
aiPatrolFlagsMgr(event.actor, actor, true, false); aiPatrolFlagsMgr(pEvActor, actor, true, false);
}
}
} }
}
if (pSprite->statnum == kStatDude && actor->IsDudeActor()) if (pSprite->statnum == kStatDude && actor->IsDudeActor())
{ {
switch (event.cmd) switch (event.cmd)
@ -5571,8 +5577,12 @@ bool modernTypeOperateSprite(DBloodActor* actor, EVENT event)
break; break;
case kCmdDudeFlagsSet: case kCmdDudeFlagsSet:
if (!event.actor || !event.actor->hasX()) break; if (event.isActor())
else aiPatrolFlagsMgr(event.actor, actor, false, true); // initialize patrol dude with possible new flags {
auto pEvActor = event.getActor();
if (!pEvActor || !pEvActor->hasX()) break;
else aiPatrolFlagsMgr(pEvActor, actor, false, true); // initialize patrol dude with possible new flags
}
break; break;
default: default:
@ -6204,24 +6214,28 @@ int useCondition(DBloodActor* sourceactor, const EVENT& event)
spritetype* pSource = &sourceactor->s(); spritetype* pSource = &sourceactor->s();
auto pXSource = &sourceactor->x(); auto pXSource = &sourceactor->x();
int objType = event.type;
int objIndex = event.index_;
bool srcIsCondition = false; bool srcIsCondition = false;
if (objType == OBJ_SPRITE && event.actor == nullptr) return -1;
if (objType == OBJ_SPRITE && event.actor != sourceactor) int objType = event.isActor() ? SS_SPRITE : event.isSector() ? SS_SECTOR : SS_WALL;
srcIsCondition = (event.actor->s().type == kModernCondition || event.actor->s().type == kModernConditionFalse); int objIndex = event.isActor() ? -1 : event.isSector() ? sectnum(event.getSector()) : wallnum(event.getWall());
auto pActor = event.isActor() ? event.getActor() : nullptr;
if (event.isActor() && pActor == nullptr) return -1;
if (event.isActor() && pActor != sourceactor)
srcIsCondition = (pActor->s().type == kModernCondition || pActor->s().type == kModernConditionFalse);
// if it's a tracking condition, it must ignore all the commands sent from objects // if it's a tracking condition, it must ignore all the commands sent from objects
if (pXSource->busyTime > 0 && event.funcID != kCallbackMax) return -1; if (pXSource->busyTime > 0 && event.funcID != kCallbackMax) return -1;
else if (!srcIsCondition) // save object serials in the stack and make copy of initial object else if (!srcIsCondition) // save object serials in the stack and make copy of initial object
{ {
condPush(sourceactor, objType, objIndex, event.actor); condPush(sourceactor, objType, objIndex, pActor);
condBackup(sourceactor); condBackup(sourceactor);
} }
else // or grab serials of objects from previous conditions else // or grab serials of objects from previous conditions
{ {
sourceactor->condition[0] = event.actor->condition[0]; sourceactor->condition[0] = pActor->condition[0];
sourceactor->condition[1] = event.actor->condition[1]; sourceactor->condition[1] = pActor->condition[1];
} }
@ -6279,7 +6293,7 @@ int useCondition(DBloodActor* sourceactor, const EVENT& event)
// send it for object currently in the focus // send it for object currently in the focus
if (pSource->flags & kModernTypeFlag1) if (pSource->flags & kModernTypeFlag1)
{ {
nnExtTriggerObject(objType, objIndex, event.actor, pXSource->command); nnExtTriggerObject(objType, objIndex, pActor, pXSource->command);
} }
// send it for initial object // send it for initial object

View file

@ -335,7 +335,7 @@ void trPlayerCtrlStopScene(PLAYER* pPlayer);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
void modernTypeTrigger(int type, int nDest, DBloodActor* actor, const EVENT& event); void modernTypeTrigger(int type, int nDest, DBloodActor* actor, const EVENT& event);
bool modernTypeOperateSector(int nSector, sectortype* pSector, XSECTOR* pXSector, const EVENT& event); bool modernTypeOperateSector(int nSector, sectortype* pSector, XSECTOR* pXSector, const EVENT& event);
bool modernTypeOperateSprite(DBloodActor*, EVENT event); bool modernTypeOperateSprite(DBloodActor*, const EVENT& event);
bool modernTypeOperateWall(int nWall, walltype* pWall, XWALL* pXWall, EVENT event); bool modernTypeOperateWall(int nWall, walltype* pWall, XWALL* pXWall, EVENT event);
void modernTypeSendCommand(DBloodActor* nSprite, int channel, COMMAND_ID command); void modernTypeSendCommand(DBloodActor* nSprite, int channel, COMMAND_ID command);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //

View file

@ -82,7 +82,7 @@ bool SetWallState(walltype* pWall, int nState)
return 0; return 0;
pXWall->busy = IntToFixed(nState); pXWall->busy = IntToFixed(nState);
pXWall->state = nState; pXWall->state = nState;
evKillWall(wallnum(pWall)); evKillWall(pWall);
if (pXWall->restState != nState && pXWall->waitTime > 0) 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);
if (pXWall->txID) if (pXWall->txID)
@ -102,7 +102,7 @@ bool SetSectorState(int nSector, XSECTOR *pXSector, int nState)
return 0; return 0;
pXSector->busy = IntToFixed(nState); pXSector->busy = IntToFixed(nState);
pXSector->state = nState; pXSector->state = nState;
evKillSector(nSector); evKillSector(pSector);
if (nState == 1) if (nState == 1)
{ {
if (pXSector->command != kCmdLink && pXSector->triggerOn && pXSector->txID) if (pXSector->command != kCmdLink && pXSector->triggerOn && pXSector->txID)
@ -167,25 +167,22 @@ void ReverseBusy(int a1, BUSYID a2)
} }
} }
unsigned int GetSourceBusy(EVENT a1) unsigned int GetSourceBusy(const EVENT& a1)
{ {
int nIndex = a1.index_; if (a1.isSector())
switch (a1.type)
{ {
case 6: auto sect = a1.getSector();
{
auto sect = &sector[nIndex];
return sect->hasX()? sect->xs().busy : 0; return sect->hasX()? sect->xs().busy : 0;
} }
case 0: else if (a1.isWall())
{ {
auto wal = &wall[nIndex]; auto wal = a1.getWall();
return wal->hasX()? wal->xw().busy : 0; return wal->hasX()? wal->xw().busy : 0;
} }
case 3: else if (a1.isActor())
{ {
return a1.actor && a1.actor->hasX() ? a1.actor->x().busy : false; auto pActor = a1.getActor();
} return pActor && pActor->hasX() ? pActor->x().busy : false;
} }
return 0; return 0;
} }
@ -1686,9 +1683,9 @@ void LinkSprite(DBloodActor* actor, EVENT event)
switch (pSprite->type) { switch (pSprite->type) {
case kSwitchCombo: case kSwitchCombo:
{ {
if (event.type == OBJ_SPRITE) if (event.isActor())
{ {
auto actor2 = event.actor; auto actor2 = event.getActor();
pXSprite->data1 = actor2 && actor2->hasX()? actor2->x().data1 : 0; pXSprite->data1 = actor2 && actor2->hasX()? actor2->x().data1 : 0;
if (pXSprite->data1 == pXSprite->data2) if (pXSprite->data1 == pXSprite->data2)