- several aiFight functions.

This commit is contained in:
Christoph Oelckers 2021-10-03 12:34:47 +02:00
parent ca3d7c9bdf
commit 57c3571555
2 changed files with 63 additions and 63 deletions

View file

@ -4846,17 +4846,17 @@ DBloodActor* aiFightGetTargetInRange(DBloodActor* actor, int minDist, int maxDis
BloodStatIterator it(kStatDude); BloodStatIterator it(kStatDude);
while (auto targactor = it.Next()) while (auto targactor = it.Next())
{ {
if (!aiFightDudeCanSeeTarget(actor, pDudeInfo, targactor)) continue;
auto pTarget = &targactor->s(); auto pTarget = &targactor->s();
auto pXTarget = &targactor->x(); auto pXTarget = &targactor->x();
if (!aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pTarget)) continue;
int dist = aiFightGetTargetDist(pSprite, pDudeInfo, pTarget); int dist = aiFightGetTargetDist(pSprite, pDudeInfo, pTarget);
if (dist < minDist || dist > maxDist) continue; if (dist < minDist || dist > maxDist) continue;
else if (actor->GetTarget() == targactor) return targactor; else if (actor->GetTarget() == targactor) return targactor;
else if (!targactor->IsDudeActor() || targactor == actor || targactor->IsPlayerActor()) continue; else if (!targactor->IsDudeActor() || targactor == actor || targactor->IsPlayerActor()) continue;
else if (IsBurningDude(pTarget) || !IsKillableDude(pTarget) || pTarget->owner == pSprite->index) continue; else if (IsBurningDude(pTarget) || !IsKillableDude(pTarget) || pTarget->owner == pSprite->index) continue;
else if ((teamMode == 1 && aiFightIsMateOf(pXSprite, pXTarget)) || aiFightMatesHaveSameTarget(pXSprite, pTarget, 1)) continue; else if ((teamMode == 1 && aiFightIsMateOf(pXSprite, pXTarget)) || aiFightMatesHaveSameTarget(actor, targactor, 1)) continue;
else if (data == 666 || pXTarget->data1 == data) else if (data == 666 || pXTarget->data1 == data)
{ {
if (actor->GetTarget()) if (actor->GetTarget())
@ -4879,15 +4879,11 @@ DBloodActor* aiFightGetTargetInRange(DBloodActor* actor, int minDist, int maxDis
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite) DBloodActor* aiFightTargetIsPlayer(DBloodActor* actor)
{ {
auto targ = actor->GetTarget();
if (pXSprite->target_i >= 0) { if (targ && targ->IsPlayerActor()) return targ;
if (IsPlayerSprite(&sprite[pXSprite->target_i])) return nullptr;
return &sprite[pXSprite->target_i];
}
return NULL;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -4896,9 +4892,9 @@ spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
spritetype* aiFightGetMateTargets(XSPRITE* pXSprite) DBloodActor* aiFightGetMateTargets(DBloodActor* actor)
{ {
auto actor = &bloodActors[pXSprite->reference]; auto pXSprite = &actor->x();
int rx = pXSprite->rxID; int rx = pXSprite->rxID;
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++)
@ -4912,7 +4908,7 @@ spritetype* aiFightGetMateTargets(XSPRITE* pXSprite)
if (mate->GetTarget()) if (mate->GetTarget())
{ {
if (!mate->GetTarget()->IsPlayerActor()) if (!mate->GetTarget()->IsPlayerActor())
return &mate->GetTarget()->s(); return mate->GetTarget();
} }
} }
} }
@ -4925,20 +4921,21 @@ spritetype* aiFightGetMateTargets(XSPRITE* pXSprite)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool aiFightMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allow) { bool aiFightMatesHaveSameTarget(DBloodActor* leaderactor, DBloodActor* targetactor, int allow)
auto actor = &bloodActors[pXLeader->reference]; {
int rx = pXLeader->rxID; spritetype* pMate = NULL; XSPRITE* pXMate = NULL; auto pXLeader = &leaderactor->x();
int rx = pXLeader->rxID;
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++) for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++)
{ {
if (rxBucket[i].type != OBJ_SPRITE) if (rxBucket[i].type != OBJ_SPRITE)
continue; continue;
auto mate = rxBucket[i].GetActor(); auto mate = rxBucket[i].actor;
if (!mate || !mate->hasX() || mate == actor || !mate->IsDudeActor()) if (!mate || !mate->hasX() || mate == leaderactor || !mate->IsDudeActor())
continue; continue;
if (&(mate->GetTarget()->s()) == pTarget && allow-- <= 0) if (mate->GetTarget() == targetactor && allow-- <= 0)
return true; return true;
} }
return false; return false;
@ -4950,8 +4947,12 @@ bool aiFightMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allo
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool aiFightDudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget) { bool aiFightDudeCanSeeTarget(DBloodActor* dudeactor, DUDEINFO* pDudeInfo, DBloodActor* targetactor)
spritetype* pDude = &sprite[pXDude->reference]; {
auto pDude = &dudeactor->s();
auto pXDude = &dudeactor->x();
auto pTarget = &targetactor->s();
int dx = pTarget->x - pDude->x; int dy = pTarget->y - pDude->y; int dx = pTarget->x - pDude->x; int dy = pTarget->y - pDude->y;
// check target // check target
@ -5000,17 +5001,15 @@ void aiFightActivateDudes(int rx)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void aiFightFreeTargets(int nSprite) { void aiFightFreeTargets(DBloodActor* actor)
int nTarget; {
StatIterator it(kStatDude); BloodStatIterator it(kStatDude);
while ((nTarget = it.NextIndex()) >= 0) while (auto targetactor = it.Next())
{ {
if (!IsDudeSprite(&sprite[nTarget]) || sprite[nTarget].extra < 0) continue; if (!targetactor->IsDudeActor() || !targetactor->hasX()) continue;
else if (xsprite[sprite[nTarget].extra].target_i == nSprite) else if (targetactor->GetTarget() == actor)
aiSetTarget_(&xsprite[sprite[nTarget].extra], sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z); aiSetTarget(targetactor, targetactor->s().x, targetactor->s().y, targetactor->s().z);
} }
return;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -5019,14 +5018,14 @@ void aiFightFreeTargets(int nSprite) {
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void aiFightFreeAllTargets(XSPRITE* pXSource) { void aiFightFreeAllTargets(DBloodActor* sourceactor)
if (pXSource->txID <= 0) return; {
for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++) auto txID = sourceactor->x().txID;
{ if (txID <= 0) return;
if (rxBucket[i].type != OBJ_SPRITE) continue; for (int i = bucketHead[txID]; i < bucketHead[txID + 1]; i++)
auto rxactor = rxBucket[i].GetActor(); {
if (rxactor && rxactor->hasX()) if (rxBucket[i].type == OBJ_SPRITE && rxBucket[i].actor && rxBucket[i].actor->hasX())
aiFightFreeTargets(rxactor->s().index); aiFightFreeTargets(rxBucket[i].actor);
} }
} }
@ -5089,7 +5088,7 @@ void aiFightAlarmDudesInSight(spritetype* pSprite, int max) {
if (pDude->index == pSprite->index || !IsDudeSprite(pDude) || pDude->extra < 0) if (pDude->index == pSprite->index || !IsDudeSprite(pDude) || pDude->extra < 0)
continue; continue;
pXDude = &xsprite[pDude->extra]; pXDude = &xsprite[pDude->extra];
if (aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pDude)) { if (aiFightDudeCanSeeTarget(&bloodActors[pXSprite->reference], pDudeInfo, &bloodActors[nSprite])) {
if (pXDude->target_i != -1 || pXDude->rxID > 0) if (pXDude->target_i != -1 || pXDude->rxID > 0)
continue; continue;
@ -5557,7 +5556,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
[[fallthrough]]; [[fallthrough]];
case kCmdRepeat: case kCmdRepeat:
if (pXSprite->txID <= 0 || !aiFightGetDudesForBattle(pXSprite)) { if (pXSprite->txID <= 0 || !aiFightGetDudesForBattle(pXSprite)) {
aiFightFreeAllTargets(pXSprite); aiFightFreeAllTargets(actor);
evPostActor(actor, 0, kCmdOff); evPostActor(actor, 0, kCmdOff);
break; break;
} else { } else {
@ -6449,7 +6448,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
// make current target and all other dudes not attack this dude anymore // make current target and all other dudes not attack this dude anymore
case kThingBloodBits: case kThingBloodBits:
case kThingBloodChunks: case kThingBloodChunks:
aiFightFreeTargets(pSprite->index); aiFightFreeTargets(&bloodActors[pSprite->index]);
return; return;
default: default:
return; return;
@ -6484,9 +6483,11 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
} }
} }
spritetype* pPlayer = aiFightTargetIsPlayer(pXSprite); auto playeractor = aiFightTargetIsPlayer(actor);
// special handling for player(s) if target changer data4 > 2. // special handling for player(s) if target changer data4 > 2.
if (pPlayer != NULL) { if (playeractor != nullptr)
{
auto pPlayer = &playeractor->s();
auto actLeech = leechIsDropped(actor); auto actLeech = leechIsDropped(actor);
if (pXSource->data4 == 3) { if (pXSource->data4 == 3) {
aiSetTarget_(pXSprite, pSprite->x, pSprite->y, pSprite->z); aiSetTarget_(pXSprite, pSprite->x, pSprite->y, pSprite->z);
@ -6501,7 +6502,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
} }
int maxAlarmDudes = 8 + Random(8); int maxAlarmDudes = 8 + Random(8);
if (pXSprite->target_i > -1 && sprite[pXSprite->target_i].extra > -1 && pPlayer == NULL) { if (pXSprite->target_i > -1 && sprite[pXSprite->target_i].extra > -1 && playeractor == nullptr) {
pTarget = &sprite[pXSprite->target_i]; pXTarget = &xsprite[pTarget->extra]; pTarget = &sprite[pXSprite->target_i]; pXTarget = &xsprite[pTarget->extra];
if (aiFightUnitCanFly(pSprite) && aiFightIsMeleeUnit(pTarget) && !aiFightUnitCanFly(pTarget)) if (aiFightUnitCanFly(pSprite) && aiFightIsMeleeUnit(pTarget) && !aiFightUnitCanFly(pTarget))
@ -6509,7 +6510,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
else if (aiFightUnitCanFly(pSprite)) else if (aiFightUnitCanFly(pSprite))
pSprite->flags &= ~0x0002; pSprite->flags &= ~0x0002;
if (!IsDudeSprite(pTarget) || pXTarget->health < 1 || !aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pTarget)) { if (!IsDudeSprite(pTarget) || pXTarget->health < 1 || !aiFightDudeCanSeeTarget(actor, pDudeInfo, &bloodActors[pTarget->index])) {
aiSetTarget_(pXSprite, pSprite->x, pSprite->y, pSprite->z); aiSetTarget_(pXSprite, pSprite->x, pSprite->y, pSprite->z);
} }
// dude attack or attacked by target that does not fit by data id? // dude attack or attacked by target that does not fit by data id?
@ -6566,7 +6567,8 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
} }
// check if targets aims player then force this target to fight with dude // check if targets aims player then force this target to fight with dude
else if (aiFightTargetIsPlayer(pXTarget) != NULL) { else if (aiFightTargetIsPlayer(actor) != nullptr)
{
aiSetTarget_(pXTarget, pSprite->index); aiSetTarget_(pXTarget, pSprite->index);
} }
@ -6608,7 +6610,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
} }
} }
if ((pXSprite->target_i < 0 || pPlayer != NULL) && (PlayClock & 32) != 0) { if ((pXSprite->target_i < 0 || playeractor != nullptr) && (PlayClock & 32) != 0) {
// try find first target that dude can see // try find first target that dude can see
int nSprite; int nSprite;
StatIterator it(kStatDude); StatIterator it(kStatDude);
@ -6624,14 +6626,15 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
// skip non-dudes and players // skip non-dudes and players
if (!IsDudeSprite(pTarget) || (IsPlayerSprite(pTarget) && pXSource->data4 > 0) || pTarget->owner == pSprite->index) continue; if (!IsDudeSprite(pTarget) || (IsPlayerSprite(pTarget) && pXSource->data4 > 0) || pTarget->owner == pSprite->index) continue;
// avoid self aiming, those who dude can't see, and those who dude own // avoid self aiming, those who dude can't see, and those who dude own
else if (!aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pTarget) || pSprite->index == pTarget->index) continue; else if (!aiFightDudeCanSeeTarget(actor, pDudeInfo, &bloodActors[pTarget->index]) || pSprite->index == pTarget->index) continue;
// if Target Changer have data1 = 666, everyone can be target, except AI team mates. // if Target Changer have data1 = 666, everyone can be target, except AI team mates.
else if (pXSource->data1 != 666 && pXSource->data1 != pXTarget->data1) continue; else if (pXSource->data1 != 666 && pXSource->data1 != pXTarget->data1) continue;
// don't attack immortal, burning dudes and mates // don't attack immortal, burning dudes and mates
if (IsBurningDude(pTarget) || !IsKillableDude(pTarget) || (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, pXTarget))) if (IsBurningDude(pTarget) || !IsKillableDude(pTarget) || (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, pXTarget)))
continue; continue;
if (pXSource->data2 == 0 || (pXSource->data2 == 1 && !aiFightMatesHaveSameTarget(pXSprite, pTarget, matesPerEnemy))) { if (pXSource->data2 == 0 || (pXSource->data2 == 1 && !aiFightMatesHaveSameTarget(&bloodActors[pXSprite->reference], &bloodActors[pTarget->index], matesPerEnemy)))
{
// Change target for dude // Change target for dude
aiSetTarget_(pXSprite, pTarget->index); aiSetTarget_(pXSprite, pTarget->index);
@ -6641,7 +6644,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
// ...and change target of target to dude to force it fight // ...and change target of target to dude to force it fight
if (pXSource->data3 > 0 && pXTarget->target_i != pSprite->index) { if (pXSource->data3 > 0 && pXTarget->target_i != pSprite->index) {
aiSetTarget_(pXTarget, pSprite->index); aiSetTarget_(pXTarget, pSprite->index);
if (pPlayer == NULL && !isActive(pTarget->index)) if (playeractor == NULL && !isActive(pTarget->index))
aiActivateDude(&bloodActors[pXTarget->reference]); aiActivateDude(&bloodActors[pXTarget->reference]);
if (pXSource->data3 == 2) if (pXSource->data3 == 2)
@ -6656,11 +6659,13 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
} }
// got no target - let's ask mates if they have targets // got no target - let's ask mates if they have targets
if ((pXSprite->target_i < 0 || pPlayer != NULL) && pXSource->data2 == 1 && (PlayClock & 64) != 0) { if ((pXSprite->target_i < 0 || playeractor != NULL) && pXSource->data2 == 1 && (PlayClock & 64) != 0) {
spritetype* pMateTarget = NULL; DBloodActor* pMateTargetActor = aiFightGetMateTargets(actor);
if ((pMateTarget = aiFightGetMateTargets(pXSprite)) != NULL && pMateTarget->extra > 0) { if (pMateTargetActor != nullptr && pMateTargetActor->hasX())
XSPRITE* pXMateTarget = &xsprite[pMateTarget->extra]; {
if (aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pMateTarget)) { auto pMateTarget = &pMateTargetActor->s();
XSPRITE* pXMateTarget = &pMateTargetActor->x();
if (aiFightDudeCanSeeTarget(actor, pDudeInfo, pMateTargetActor)) {
if (pXMateTarget->target_i < 0) { if (pXMateTarget->target_i < 0) {
aiSetTarget_(pXMateTarget, pSprite->index); aiSetTarget_(pXMateTarget, pSprite->index);
if (IsDudeSprite(pMateTarget) && !isActive(pMateTarget->index)) if (IsDudeSprite(pMateTarget) && !isActive(pMateTarget->index))
@ -6673,7 +6678,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
return; return;
// try walk in mate direction in case if not see the target // try walk in mate direction in case if not see the target
} else if (pXMateTarget->target_i >= 0 && aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, &sprite[pXMateTarget->target_i])) { } else if (pXMateTarget->target_i >= 0 && aiFightDudeCanSeeTarget(actor, pDudeInfo, &bloodActors[pXMateTarget->target_i])) {
spritetype* pMate = &sprite[pXMateTarget->target_i]; spritetype* pMate = &sprite[pXMateTarget->target_i];
pXSprite->target_i = pMateTarget->index; pXSprite->target_i = pMateTarget->index;
pXSprite->targetX = pMate->x; pXSprite->targetX = pMate->x;

View file

@ -314,20 +314,15 @@ void aiSetGenIdleState(DBloodActor*);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
int aiFightGetTargetDist(spritetype* pSprite, DUDEINFO* pDudeInfo, spritetype* pTarget); int aiFightGetTargetDist(spritetype* pSprite, DUDEINFO* pDudeInfo, spritetype* pTarget);
int aiFightGetFineTargetDist(spritetype* pSprite, spritetype* pTarget); int aiFightGetFineTargetDist(spritetype* pSprite, spritetype* pTarget);
bool aiFightDudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget); bool aiFightDudeCanSeeTarget(DBloodActor* pXDude, DUDEINFO* pDudeInfo, DBloodActor* pTarget);
bool aiFightUnitCanFly(spritetype* pDude); bool aiFightUnitCanFly(spritetype* pDude);
bool aiFightIsMeleeUnit(spritetype* pDude); bool aiFightIsMeleeUnit(spritetype* pDude);
bool aiFightDudeIsAffected(XSPRITE* pXDude); bool aiFightDudeIsAffected(XSPRITE* pXDude);
bool aiFightMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allow); bool aiFightMatesHaveSameTarget(DBloodActor* leaderactor, DBloodActor* targetactor, int allow);
bool aiFightGetDudesForBattle(XSPRITE* pXSprite); bool aiFightGetDudesForBattle(XSPRITE* pXSprite);
bool aiFightIsMateOf(XSPRITE* pXDude, XSPRITE* pXSprite); bool aiFightIsMateOf(XSPRITE* pXDude, XSPRITE* pXSprite);
void aiFightAlarmDudesInSight(spritetype* pSprite, int max); void aiFightAlarmDudesInSight(spritetype* pSprite, int max);
void aiFightActivateDudes(int rx); void aiFightActivateDudes(int rx);
void aiFightFreeTargets(int nSprite);
void aiFightFreeAllTargets(XSPRITE* pXSource);
spritetype* aiFightGetTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode);
spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite);
spritetype* aiFightGetMateTargets(XSPRITE* pXSprite);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
void useSlopeChanger(XSPRITE* pXSource, int objType, int objIndex); void useSlopeChanger(XSPRITE* pXSource, int objType, int objIndex);
void damageSprites(DBloodActor* pXSource, DBloodActor* pSprite); void damageSprites(DBloodActor* pXSource, DBloodActor* pSprite);