exported the main structures in Blood that make up a BloodActor.

nnext stuff was omitted for now.
This also eliminates the DUDEEXTRA_STATS substructure and integrates its content directly into DUDEEXTRA.
This commit is contained in:
Christoph Oelckers 2023-10-01 22:25:08 +02:00
parent fe02190604
commit 762263671a
19 changed files with 310 additions and 141 deletions

View file

@ -724,6 +724,11 @@ struct AFuncDesc
extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \
MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname;
#define DEFINE_FIELD_NAMED_UNSIZED(cls, name, scriptname) \
static const FieldDesc VMField_##cls##_##scriptname = { #cls, #scriptname, (unsigned)myoffsetof(cls, name), ~0u, 0 }; \
extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \
MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname;
#define DEFINE_FIELD_BIT(cls, name, scriptname, bitval) \
static const FieldDesc VMField_##cls##_##scriptname = { #cls, #scriptname, (unsigned)myoffsetof(cls, name), (unsigned)sizeof(cls::name), bitval }; \
extern FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr; \

View file

@ -443,7 +443,6 @@ void InitThingdef()
collstruct->Size = sizeof(CollisionBase);
collstruct->Align = alignof(CollisionBase);
auto sidestruct = NewStruct("tspritetype", nullptr, true);
sidestruct->Size = sizeof(tspritetype);
sidestruct->Align = alignof(tspritetype);

View file

@ -3472,17 +3472,17 @@ void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damag
break;
case kDudeSpiderBrown:
if (Owner) Owner->dudeExtra.stats.birthCounter--;
if (Owner) Owner->dudeExtra.birthCounter--;
genericDeath(actor, nSeq, 1803, pDudeInfo->seqStartID + nSeq);
break;
case kDudeSpiderRed:
if (Owner) Owner->dudeExtra.stats.birthCounter--;
if (Owner) Owner->dudeExtra.birthCounter--;
genericDeath(actor, nSeq, 1803, pDudeInfo->seqStartID + nSeq);
break;
case kDudeSpiderBlack:
if (Owner) Owner->dudeExtra.stats.birthCounter--;
if (Owner) Owner->dudeExtra.birthCounter--;
genericDeath(actor, nSeq, 1803, pDudeInfo->seqStartID + nSeq);
break;

View file

@ -360,9 +360,9 @@ void aiActivateDude(DBloodActor* actor)
{
case kDudePhantasm:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 1;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
aiNewState(actor, &ghostSearch);
else
@ -378,8 +378,8 @@ void aiActivateDude(DBloodActor* actor)
case kDudeCultistTNT:
case kDudeCultistBeast:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 1;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
{
switch (actor->xspr.medium)
@ -422,8 +422,8 @@ void aiActivateDude(DBloodActor* actor)
#ifdef NOONE_EXTENSIONS
case kDudeModernCustom:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 1;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
{
if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW);
@ -444,8 +444,8 @@ void aiActivateDude(DBloodActor* actor)
#endif
case kDudeCultistTommyProne:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 1;
actor->dudeExtra.active = 1;
actor->ChangeType(kDudeCultistTommy);
if (actor->GetTarget() == nullptr)
{
@ -481,8 +481,8 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeCultistShotgunProne:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 1;
actor->dudeExtra.active = 1;
actor->ChangeType(kDudeCultistShotgun);
if (actor->GetTarget() == nullptr)
{
@ -524,9 +524,9 @@ void aiActivateDude(DBloodActor* actor)
break;
case kDudeBat:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 1;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 1;
if (!actor->spr.flags)
actor->spr.flags = 9;
if (actor->GetTarget() == nullptr)
@ -541,9 +541,9 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeBoneEel:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 1;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
aiNewState(actor, &eelSearch);
else
@ -558,11 +558,11 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeGillBeast:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
XSECTOR* pXSector = actor->sector()->hasX()? &actor->sector()->xs() : nullptr;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 1;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
{
if (pXSector && pXSector->Underwater)
@ -585,8 +585,8 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeZombieAxeNormal:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 1;
actor->dudeExtra.thinkTime = 1;
if (actor->GetTarget() == nullptr)
aiNewState(actor, &zombieASearch);
else
@ -614,22 +614,22 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeZombieAxeBuried:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 1;
actor->dudeExtra.thinkTime = 1;
if (actor->xspr.aiState == &zombieEIdle) aiNewState(actor, &zombieEUp);
break;
}
case kDudeZombieAxeLaying:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 1;
actor->dudeExtra.thinkTime = 1;
if (actor->xspr.aiState == &zombieSIdle) aiNewState(actor, &zombie13AC2C);
break;
}
case kDudeZombieButcher:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 1;
actor->dudeExtra.thinkTime = 1;
if (actor->GetTarget() == nullptr)
aiNewState(actor, &zombieFSearch);
else
@ -655,9 +655,9 @@ void aiActivateDude(DBloodActor* actor)
aiNewState(actor, &zombieFBurnChase);
break;
case kDudeGargoyleFlesh: {
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 1;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
aiNewState(actor, &gargoyleFSearch);
else
@ -672,9 +672,9 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeGargoyleStone:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 1;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 1;
if (actor->GetTarget() == nullptr)
aiNewState(actor, &gargoyleFSearch);
else
@ -792,8 +792,8 @@ void aiActivateDude(DBloodActor* actor)
break;
case kDudeSpiderMother:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 1;
actor->dudeExtra.active = 1;
actor->spr.flags |= 2;
actor->spr.cstat &= ~CSTAT_SPRITE_YFLIP;
if (actor->GetTarget() == nullptr)
@ -807,8 +807,8 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeTinyCaleb:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 1;
actor->dudeExtra.thinkTime = 1;
if (actor->GetTarget() == nullptr)
{
switch (actor->xspr.medium)
@ -839,8 +839,8 @@ void aiActivateDude(DBloodActor* actor)
}
case kDudeBeast:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 1;
actor->dudeExtra.thinkTime = 1;
if (actor->GetTarget() == nullptr)
{
switch (actor->xspr.medium)
@ -1669,11 +1669,11 @@ void aiInitSprite(DBloodActor* actor)
XSECTOR* pXSector = actor->sector()->hasX() ? &actor->sector()->xs() : nullptr;
DUDEEXTRA* pDudeExtra = &actor->dudeExtra;
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtra->teslaHit = 0;
pDudeExtra->time = 0;
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 0;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 0;
#ifdef NOONE_EXTENSIONS
unsigned int stateTimer = 0;
@ -1701,49 +1701,49 @@ void aiInitSprite(DBloodActor* actor)
case kDudeCultistTNT:
case kDudeCultistBeast:
{
pDudeExtraE->active = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &cultistIdle);
break;
}
case kDudeCultistTommyProne:
{
pDudeExtraE->active = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &fanaticProneIdle);
break;
}
case kDudeCultistShotgunProne:
{
pDudeExtraE->active = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &cultistProneIdle);
break;
}
case kDudeZombieButcher: {
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &zombieFIdle);
break;
}
case kDudeZombieAxeNormal: {
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &zombieAIdle);
break;
}
case kDudeZombieAxeLaying:
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &zombieSIdle);
actor->spr.flags &= ~1;
break;
}
case kDudeZombieAxeBuried: {
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &zombieEIdle);
actor->spr.flags &= ~1;
break;
}
case kDudeGargoyleFlesh:
case kDudeGargoyleStone: {
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 0;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &gargoyleFIdle);
break;
}
@ -1752,13 +1752,13 @@ void aiInitSprite(DBloodActor* actor)
aiNewState(actor, &gargoyleStatueIdle);
break;
case kDudeCerberusTwoHead: {
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &cerberusIdle);
break;
}
case kDudeCerberusOneHead: {
if (!VanillaMode()) {
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &cerberus2Idle);
break;
}
@ -1773,8 +1773,8 @@ void aiInitSprite(DBloodActor* actor)
break;
case kDudePhantasm:
{
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 0;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &ghostIdle);
break;
}
@ -1786,8 +1786,8 @@ void aiInitSprite(DBloodActor* actor)
break;
case kDudeBoneEel:
{
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 0;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &eelIdle);
break;
}
@ -1796,8 +1796,8 @@ void aiInitSprite(DBloodActor* actor)
break;
case kDudeBat:
{
pDudeExtraE->thinkTime = 0;
pDudeExtraE->active = 0;
actor->dudeExtra.thinkTime = 0;
actor->dudeExtra.active = 0;
aiNewState(actor, &batIdle);
break;
}
@ -1805,22 +1805,22 @@ void aiInitSprite(DBloodActor* actor)
case kDudeSpiderRed:
case kDudeSpiderBlack:
{
pDudeExtraE->active = 0;
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.active = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &spidIdle);
break;
}
case kDudeSpiderMother:
{
pDudeExtraE->active = 0;
pDudeExtraE->birthCounter = 0;
actor->dudeExtra.active = 0;
actor->dudeExtra.birthCounter = 0;
aiNewState(actor, &spidIdle);
break;
}
case kDudeTchernobog:
{
pDudeExtraE->active = 0;
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.active = 0;
actor->dudeExtra.thinkTime = 0;
aiNewState(actor, &tchernobogIdle);
break;
}

View file

@ -50,23 +50,6 @@ enum AI_SFX_PRIORITY {
};
struct DUDEEXTRA_STATS
{
union {
int thinkTime;
int birthCounter;
};
uint8_t active;
};
struct DUDEEXTRA
{
int time;
uint8_t teslaHit;
int prio;
DUDEEXTRA_STATS stats;
};
struct TARGETTRACK {
int TotalKills;
int Kills;

View file

@ -79,12 +79,12 @@ static void batThinkTarget(DBloodActor* actor)
{
assert(actor->IsDudeActor());
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
if (actor->dudeExtra.active && actor->dudeExtra.thinkTime < 10)
actor->dudeExtra.thinkTime++;
else if (actor->dudeExtra.thinkTime >= 10 && actor->dudeExtra.active)
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
actor->xspr.goalAng += DAngle45;
aiSetTarget(actor, actor->basePoint);
aiNewState(actor, &batTurn);
@ -370,8 +370,8 @@ void batMoveToCeil(DBloodActor* actor)
{
if (actor->spr.pos.Z - actor->xspr.TargetPos.Z < 0x10)
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
actor->spr.flags = 0;
aiNewState(actor, &batIdle);
}

View file

@ -91,12 +91,12 @@ static void eelThinkTarget(DBloodActor* actor)
{
assert(actor->IsDudeActor());
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
if (actor->dudeExtra.active && actor->dudeExtra.thinkTime < 10)
actor->dudeExtra.thinkTime++;
else if (actor->dudeExtra.thinkTime >= 10 && actor->dudeExtra.active)
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
actor->xspr.goalAng += DAngle45;
aiSetTarget(actor, actor->basePoint);
aiNewState(actor, &eelTurn);
@ -121,13 +121,13 @@ static void eelThinkTarget(DBloodActor* actor)
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, dvect.Angle());
if (nDist < pDudeInfo->SeeDist() && nDeltaAngle <= pDudeInfo->Periphery())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, pPlayer->actor);
aiActivateDude(actor);
}
else if (nDist < pDudeInfo->HearDist())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, ppos);
aiActivateDude(actor);
}
@ -375,8 +375,8 @@ void eelMoveToCeil(DBloodActor* actor)
{
if (actor->spr.pos.Z - actor->xspr.TargetPos.Z < 0x10)
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = 0;
actor->dudeExtra.active = 0;
actor->spr.flags = 0;
aiNewState(actor, &eelIdle);
}

View file

@ -220,10 +220,10 @@ static void cerberusThinkTarget(DBloodActor* actor)
return;
}
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
if (actor->dudeExtra.active && actor->dudeExtra.thinkTime < 10)
actor->dudeExtra.thinkTime++;
else if (actor->dudeExtra.thinkTime >= 10 && actor->dudeExtra.active)
{
actor->xspr.goalAng += DAngle45;
aiSetTarget(actor, actor->basePoint);
@ -252,13 +252,13 @@ static void cerberusThinkTarget(DBloodActor* actor)
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, dvect.Angle());
if (nDist < pDudeInfo->SeeDist() && nDeltaAngle <= pDudeInfo->Periphery())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, pPlayer->actor);
aiActivateDude(actor);
}
else if (nDist < pDudeInfo->HearDist())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, ppos);
aiActivateDude(actor);
}

View file

@ -179,10 +179,10 @@ static void gargThinkTarget(DBloodActor* actor)
return;
}
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
if (actor->dudeExtra.active && actor->dudeExtra.thinkTime < 10)
actor->dudeExtra.thinkTime++;
else if (actor->dudeExtra.thinkTime >= 10 && actor->dudeExtra.active)
{
actor->xspr.goalAng += DAngle45;
aiSetTarget(actor, actor->basePoint);
@ -208,13 +208,13 @@ static void gargThinkTarget(DBloodActor* actor)
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, dvect.Angle());
if (nDist < pDudeInfo->SeeDist() && nDeltaAngle <= pDudeInfo->Periphery())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, pPlayer->actor);
aiActivateDude(actor);
}
else if (nDist < pDudeInfo->HearDist())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, ppos);
aiActivateDude(actor);
}

View file

@ -160,10 +160,10 @@ static void ghostThinkTarget(DBloodActor* actor)
return;
}
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
if (actor->dudeExtra.active && actor->dudeExtra.thinkTime < 10)
actor->dudeExtra.thinkTime++;
else if (actor->dudeExtra.thinkTime >= 10 && actor->dudeExtra.active)
{
actor->xspr.goalAng += DAngle45;
aiSetTarget(actor, actor->basePoint);
@ -189,14 +189,14 @@ static void ghostThinkTarget(DBloodActor* actor)
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, dvect.Angle());
if (nDist < pDudeInfo->SeeDist() && nDeltaAngle <= pDudeInfo->Periphery())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, pPlayer->actor);
aiActivateDude(actor);
return;
}
else if (nDist < pDudeInfo->HearDist())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, ppos);
aiActivateDude(actor);
return;

View file

@ -135,13 +135,13 @@ void SpidBirthSeqCallback(int, DBloodActor* actor)
DUDEINFO* pDudeInfo = getDudeInfo(actor);
if (!actor->ValidateTarget(__FUNCTION__)) return;
auto target = actor->GetTarget();
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
auto dvec = actor->xspr.TargetPos.XY() - actor->spr.pos.XY();
DAngle nAngle = dvec.Angle();
double nDist = dvec.Length();
DBloodActor* spawned = nullptr;
if (target->IsPlayerActor() && pDudeExtraE->birthCounter < 10)
if (target->IsPlayerActor() && actor->dudeExtra.birthCounter < 10)
{
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, nAngle);
if (nDist < 0x1a0 && nDist > 0x140 && nDeltaAngle < pDudeInfo->Periphery())
@ -153,7 +153,7 @@ void SpidBirthSeqCallback(int, DBloodActor* actor)
if (spawned)
{
pDudeExtraE->birthCounter++;
actor->dudeExtra.birthCounter++;
spawned->SetOwner(spawned);
if (AllowedKillType(spawned)) Level.addKillCount();
}

View file

@ -184,10 +184,10 @@ static void sub_725A4(DBloodActor* actor)
return;
}
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
if (pDudeExtraE->active && pDudeExtraE->thinkTime < 10)
pDudeExtraE->thinkTime++;
else if (pDudeExtraE->thinkTime >= 10 && pDudeExtraE->active)
if (actor->dudeExtra.active && actor->dudeExtra.thinkTime < 10)
actor->dudeExtra.thinkTime++;
else if (actor->dudeExtra.thinkTime >= 10 && actor->dudeExtra.active)
{
actor->xspr.goalAng += DAngle45;
aiSetTarget(actor, actor->basePoint);
@ -215,13 +215,13 @@ static void sub_725A4(DBloodActor* actor)
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, nAngle);
if (nDist < pDudeInfo->SeeDist() && abs(nDeltaAngle) <= pDudeInfo->Periphery())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, pPlayer->actor);
aiActivateDude(actor);
}
else if (nDist < pDudeInfo->HearDist())
{
pDudeExtraE->thinkTime = 0;
actor->dudeExtra.thinkTime = 0;
aiSetTarget(actor, ppos);
aiActivateDude(actor);
}

View file

@ -2501,8 +2501,8 @@ void aiGenDudeInitSprite(DBloodActor* actor)
{
case kDudeModernCustom:
{
DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats;
pDudeExtraE->active = pDudeExtraE->thinkTime = 0;
actor->dudeExtra.active = actor->dudeExtra.thinkTime = 0;
aiGenDudeNewState(actor, &genDudeIdleL);
break;
}

View file

@ -5,7 +5,6 @@
BEGIN_BLD_NS
class DBloodActor;
struct SPRITEHIT
{
@ -13,6 +12,8 @@ struct SPRITEHIT
Collision hit, ceilhit, florhit;
};
class DBloodActor;
class DBloodActor : public DCoreActor
{
DECLARE_CLASS(DBloodActor, DCoreActor)
@ -21,16 +22,18 @@ class DBloodActor : public DCoreActor
public:
double dudeSlope; // Q18.14 format
bool hasx;
bool explosionhackflag; // this originally hijacked the target field which is not safe when working with pointers.
XSPRITE xspr;
SPRITEHIT hit;
DUDEEXTRA dudeExtra;
TObjPtr<DBloodActor*> ownerActor; // was previously stored in the sprite's owner field.
// nnext stuff. For now not exported to scripting.
SPRITEMASS spriteMass;
GENDUDEEXTRA genDudeExtra;
TObjPtr<DBloodActor*> prevmarker; // needed by the nnext marker code. This originally hijacked targetX in XSPRITE
TObjPtr<DBloodActor*> ownerActor; // was previously stored in the sprite's owner field.
DVector3 basePoint;
EventObject condition[2];
bool explosionhackflag; // this originally hijacked the target field which is not safe when working with pointers.
// transient data (not written to savegame)
int cumulDamage;

View file

@ -448,12 +448,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DUDEEXTRA& w, DUDE
if (arc.BeginObject(keyname))
{
// Note: birthCounter/thinkTime are a union and share the same value (this is used for savefile backwards compatibility - see correct implementation below)
arc("time", w.time, &empty)
("teslaHit", w.teslaHit, &empty2)
("prio", w.prio, &empty)
("thinkTime", w.stats.thinkTime, &empty)
("active", w.stats.active, &empty2)
("thinkTime", w.thinkTime, &empty)
("birthCounter", w.birthCounter, &empty)
("active", w.active, &empty2)
.EndObject();
}
return arc;

View file

@ -1,4 +1,4 @@
// This is separate because the map loader needs knowledge about these types to allocate their instances.
// This is separate because the map loader and script compiler needs knowledge about these types to allocate their instances so it needs to be usable from shared code.
#pragma once
#include "ns.h"
@ -266,4 +266,15 @@ struct XWALL {
uint8_t key; // Key
};
struct DUDEEXTRA
{
int time;
uint8_t teslaHit;
uint8_t active;
int prio;
int thinkTime;
int birthCounter;
};
END_BLD_NS

View file

@ -76,6 +76,64 @@ DEFINE_FIELD_NAMED_X(XWALL, XWALL, panVel.X, panVelX) // VM does not support int
DEFINE_FIELD_NAMED_X(XWALL, XWALL, panVel.Y, panVelY)
DEFINE_FIELD_X(XWALL, XWALL, key)
DEFINE_FIELD_X(XSPRITE, XSPRITE, aiState)
DEFINE_FIELD_X(XSPRITE, XSPRITE, flags)
DEFINE_FIELD_X(XSPRITE, XSPRITE, target)
DEFINE_FIELD_X(XSPRITE, XSPRITE, burnSource)
DEFINE_FIELD_X(XSPRITE, XSPRITE, TargetPos)
DEFINE_FIELD_X(XSPRITE, XSPRITE, goalAng)
DEFINE_FIELD_X(XSPRITE, XSPRITE, sysData1)
DEFINE_FIELD_X(XSPRITE, XSPRITE, sysData2)
DEFINE_FIELD_X(XSPRITE, XSPRITE, scale)
DEFINE_FIELD_X(XSPRITE, XSPRITE, physAttr)
DEFINE_FIELD_X(XSPRITE, XSPRITE, health)
DEFINE_FIELD_X(XSPRITE, XSPRITE, busy)
DEFINE_FIELD_X(XSPRITE, XSPRITE, data1)
DEFINE_FIELD_X(XSPRITE, XSPRITE, data2)
DEFINE_FIELD_X(XSPRITE, XSPRITE, data3)
DEFINE_FIELD_X(XSPRITE, XSPRITE, txID)
DEFINE_FIELD_X(XSPRITE, XSPRITE, rxID)
DEFINE_FIELD_X(XSPRITE, XSPRITE, command)
DEFINE_FIELD_X(XSPRITE, XSPRITE, busyTime)
DEFINE_FIELD_X(XSPRITE, XSPRITE, waitTime)
DEFINE_FIELD_X(XSPRITE, XSPRITE, data4)
DEFINE_FIELD_X(XSPRITE, XSPRITE, burnTime)
DEFINE_FIELD_X(XSPRITE, XSPRITE, height)
DEFINE_FIELD_X(XSPRITE, XSPRITE, stateTimer)
DEFINE_FIELD_X(XSPRITE, XSPRITE, respawnPending)
DEFINE_FIELD_X(XSPRITE, XSPRITE, dropMsg)
DEFINE_FIELD_X(XSPRITE, XSPRITE, key)
DEFINE_FIELD_X(XSPRITE, XSPRITE, lSkill)
DEFINE_FIELD_X(XSPRITE, XSPRITE, lockMsg)
DEFINE_FIELD_X(XSPRITE, XSPRITE, dodgeDir)
DEFINE_FIELD_X(XSPRITE, XSPRITE, wave)
DEFINE_FIELD_X(XSPRITE, XSPRITE, medium)
DEFINE_FIELD_X(XSPRITE, XSPRITE, respawn)
DEFINE_FIELD_X(XSPRITE, XSPRITE, modernFlags)
DEFINE_FIELD_X(XSPRITE, XSPRITE, sightstuff)
DEFINE_FIELD_X(XSPRITE, XSPRITE, patrolturndelay)
DEFINE_FIELD_X(DUDEEXTRA, DUDEEXTRA, time)
DEFINE_FIELD_X(DUDEEXTRA, DUDEEXTRA, teslaHit)
DEFINE_FIELD_X(DUDEEXTRA, DUDEEXTRA, active)
DEFINE_FIELD_X(DUDEEXTRA, DUDEEXTRA, prio)
DEFINE_FIELD_X(DUDEEXTRA, DUDEEXTRA, thinkTime)
DEFINE_FIELD_X(DUDEEXTRA, DUDEEXTRA, birthCounter)
DEFINE_FIELD_UNSIZED(SPRITEHIT, SPRITEHIT, hit)
DEFINE_FIELD_UNSIZED(SPRITEHIT, SPRITEHIT, ceilhit)
DEFINE_FIELD_UNSIZED(SPRITEHIT, SPRITEHIT, florhit)
DEFINE_FIELD(DBloodActor, dudeSlope)
DEFINE_FIELD(DBloodActor, hasx)
DEFINE_FIELD(DBloodActor, explosionhackflag)
DEFINE_FIELD_UNSIZED(BloodActor, DBloodActor, hit)
DEFINE_FIELD_UNSIZED(BloodActor, DBloodActor, dudeExtra)
DEFINE_FIELD_UNSIZED(BloodActor, DBloodActor, xspr)
DEFINE_FIELD(DBloodActor, ownerActor)
DEFINE_FIELD(DBloodActor, cumulDamage)
DEFINE_FIELD(DBloodActor, interpolated)
void Blood_ChangeType(DBloodActor* self, PClassActor* type)
{

View file

@ -1,5 +1,115 @@
struct XSPRITE {
//AISTATE* aiState; // ai
uint flags;
native BloodActor target; // target sprite
native BloodActor burnSource;
native Vector3 TargetPos;
native double goalAng; // Dude goal ang
native int sysData1; // used to keep here various system data, so user can't change it in map editor
native int sysData2; //
native int scale; // used for scaling SEQ size on sprites
native uint physAttr; // currently used by additional physics sprites to keep its attributes.
native uint health;
native uint busy;
native int16 data1; // Data 1
native int16 data2; // Data 2
native int16 data3; // Data 3
native uint16 txID; // TX ID
native uint16 rxID; // RX ID
native uint16 command; // Cmd
native uint16 busyTime; // busyTime
native uint16 waitTime; // waitTime
native uint16 data4; // Data 4
native uint16 burnTime;
native uint16 height;
native uint16 stateTimer; // ai timer
native uint8 respawnPending; // respawnPending
native uint8 dropMsg; // Drop Item
native uint8 key; // Key
native uint8 lSkill; // Launch 12345
native uint8 lockMsg; // Lock msg
native int8 dodgeDir; // Dude dodge direction
native uint8 wave; // Wave
native uint8 medium; // medium
native uint8 respawn; // Respawn option
native uint8 modernFlags; // modern flags
native uint8 sightstuff; // something about sight checks
native uint8 patrolturndelay; // patrol turn delay
flagdef internal state: flags, 0;
flagdef internal triggerOn: flags, 1;
flagdef internal triggerOff: flags, 2;
flagdef internal restState: flags, 3;
flagdef internal interruptable: flags, 4;
flagdef internal Decoupled: flags, 5;
flagdef internal triggerOnce: flags, 6;
flagdef internal isTriggered: flags, 7;
flagdef internal Push: flags, 8;
flagdef internal Vector: flags, 9;
flagdef internal Impact: flags, 10;
flagdef internal Pickup: flags, 11;
flagdef internal Touch: flags, 12;
flagdef internal Sight: flags, 13;
flagdef internal Proximity: flags, 14;
flagdef internal lS: flags, 15;
flagdef internal lB: flags, 16;
flagdef internal lT: flags, 17;
flagdef internal lC: flags, 18;
flagdef internal DudeLockout: flags, 19;
flagdef internal locked: flags, 20;
flagdef internal dudeDeaf: flags, 21;
flagdef internal dudeAmbush: flags, 22;
flagdef internal dudeGuard: flags, 23;
flagdef internal dudeFlag4: flags, 24;
flagdef internal patrolstate: flags, 25;
}
struct SPRITEHIT
{
native CollisionData hit, ceilhit, florhit;
}
struct DUDEEXTRA
{
native int time;
native uint8 teslaHit;
native uint8 active;
native int prio;
native int thinkTime;
native int birthCounter;
}
class BloodActor : CoreActor native
{
native double dudeSlope;
native readonly bool hasx;
native bool explosionhackflag; // this originally hijacked the target field which is not safe when working with pointers.
native XSPRITE xspr;
native SPRITEHIT hit;
native DUDEEXTRA dudeExtra;
native BloodActor ownerActor; // was previously stored in the sprite's owner field.
// nnext stuff. For now not exported to scripting.
//SPRITEMASS spriteMass;
//GENDUDEEXTRA genDudeExtra;
//TObjPtr<DBloodActor*> prevmarker; // needed by the nnext marker code. This originally hijacked targetX in XSPRITE
//DVector3 basePoint;
//EventObject condition[2];
// transient data (not written to savegame)
native int cumulDamage;
native bool interpolated;
native void ChangeType(class<BloodActor> newtype);
}

View file

@ -338,8 +338,8 @@ struct sectortype native
//=============================================================================
struct XWALL native {
struct XWALL native
{
native uint flags;
native uint busy;
native int16 data;