- 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);
while (auto targactor = it.Next())
{
if (!aiFightDudeCanSeeTarget(actor, pDudeInfo, targactor)) continue;
auto pTarget = &targactor->s();
auto pXTarget = &targactor->x();
if (!aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pTarget)) continue;
int dist = aiFightGetTargetDist(pSprite, pDudeInfo, pTarget);
if (dist < minDist || dist > maxDist) continue;
else if (actor->GetTarget() == targactor) return targactor;
else if (!targactor->IsDudeActor() || targactor == actor || targactor->IsPlayerActor()) 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)
{
if (actor->GetTarget())
@ -4879,15 +4879,11 @@ DBloodActor* aiFightGetTargetInRange(DBloodActor* actor, int minDist, int maxDis
//
//---------------------------------------------------------------------------
spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite)
DBloodActor* aiFightTargetIsPlayer(DBloodActor* actor)
{
if (pXSprite->target_i >= 0) {
if (IsPlayerSprite(&sprite[pXSprite->target_i]))
return &sprite[pXSprite->target_i];
}
return NULL;
auto targ = actor->GetTarget();
if (targ && targ->IsPlayerActor()) return targ;
return nullptr;
}
//---------------------------------------------------------------------------
@ -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;
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++)
@ -4912,7 +4908,7 @@ spritetype* aiFightGetMateTargets(XSPRITE* pXSprite)
if (mate->GetTarget())
{
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) {
auto actor = &bloodActors[pXLeader->reference];
int rx = pXLeader->rxID; spritetype* pMate = NULL; XSPRITE* pXMate = NULL;
bool aiFightMatesHaveSameTarget(DBloodActor* leaderactor, DBloodActor* targetactor, int allow)
{
auto pXLeader = &leaderactor->x();
int rx = pXLeader->rxID;
for (int i = bucketHead[rx]; i < bucketHead[rx + 1]; i++)
{
if (rxBucket[i].type != OBJ_SPRITE)
continue;
auto mate = rxBucket[i].GetActor();
if (!mate || !mate->hasX() || mate == actor || !mate->IsDudeActor())
auto mate = rxBucket[i].actor;
if (!mate || !mate->hasX() || mate == leaderactor || !mate->IsDudeActor())
continue;
if (&(mate->GetTarget()->s()) == pTarget && allow-- <= 0)
if (mate->GetTarget() == targetactor && allow-- <= 0)
return true;
}
return false;
@ -4950,8 +4947,12 @@ bool aiFightMatesHaveSameTarget(XSPRITE* pXLeader, spritetype* pTarget, int allo
//
//---------------------------------------------------------------------------
bool aiFightDudeCanSeeTarget(XSPRITE* pXDude, DUDEINFO* pDudeInfo, spritetype* pTarget) {
spritetype* pDude = &sprite[pXDude->reference];
bool aiFightDudeCanSeeTarget(DBloodActor* dudeactor, DUDEINFO* pDudeInfo, DBloodActor* targetactor)
{
auto pDude = &dudeactor->s();
auto pXDude = &dudeactor->x();
auto pTarget = &targetactor->s();
int dx = pTarget->x - pDude->x; int dy = pTarget->y - pDude->y;
// check target
@ -5000,17 +5001,15 @@ void aiFightActivateDudes(int rx)
//
//---------------------------------------------------------------------------
void aiFightFreeTargets(int nSprite) {
int nTarget;
StatIterator it(kStatDude);
while ((nTarget = it.NextIndex()) >= 0)
void aiFightFreeTargets(DBloodActor* actor)
{
BloodStatIterator it(kStatDude);
while (auto targetactor = it.Next())
{
if (!IsDudeSprite(&sprite[nTarget]) || sprite[nTarget].extra < 0) continue;
else if (xsprite[sprite[nTarget].extra].target_i == nSprite)
aiSetTarget_(&xsprite[sprite[nTarget].extra], sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z);
if (!targetactor->IsDudeActor() || !targetactor->hasX()) continue;
else if (targetactor->GetTarget() == actor)
aiSetTarget(targetactor, targetactor->s().x, targetactor->s().y, targetactor->s().z);
}
return;
}
//---------------------------------------------------------------------------
@ -5019,14 +5018,14 @@ void aiFightFreeTargets(int nSprite) {
//
//---------------------------------------------------------------------------
void aiFightFreeAllTargets(XSPRITE* pXSource) {
if (pXSource->txID <= 0) return;
for (int i = bucketHead[pXSource->txID]; i < bucketHead[pXSource->txID + 1]; i++)
{
if (rxBucket[i].type != OBJ_SPRITE) continue;
auto rxactor = rxBucket[i].GetActor();
if (rxactor && rxactor->hasX())
aiFightFreeTargets(rxactor->s().index);
void aiFightFreeAllTargets(DBloodActor* sourceactor)
{
auto txID = sourceactor->x().txID;
if (txID <= 0) return;
for (int i = bucketHead[txID]; i < bucketHead[txID + 1]; i++)
{
if (rxBucket[i].type == OBJ_SPRITE && rxBucket[i].actor && rxBucket[i].actor->hasX())
aiFightFreeTargets(rxBucket[i].actor);
}
}
@ -5089,7 +5088,7 @@ void aiFightAlarmDudesInSight(spritetype* pSprite, int max) {
if (pDude->index == pSprite->index || !IsDudeSprite(pDude) || pDude->extra < 0)
continue;
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)
continue;
@ -5557,7 +5556,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
[[fallthrough]];
case kCmdRepeat:
if (pXSprite->txID <= 0 || !aiFightGetDudesForBattle(pXSprite)) {
aiFightFreeAllTargets(pXSprite);
aiFightFreeAllTargets(actor);
evPostActor(actor, 0, kCmdOff);
break;
} else {
@ -6449,7 +6448,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
// make current target and all other dudes not attack this dude anymore
case kThingBloodBits:
case kThingBloodChunks:
aiFightFreeTargets(pSprite->index);
aiFightFreeTargets(&bloodActors[pSprite->index]);
return;
default:
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.
if (pPlayer != NULL) {
if (playeractor != nullptr)
{
auto pPlayer = &playeractor->s();
auto actLeech = leechIsDropped(actor);
if (pXSource->data4 == 3) {
aiSetTarget_(pXSprite, pSprite->x, pSprite->y, pSprite->z);
@ -6501,7 +6502,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
}
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];
if (aiFightUnitCanFly(pSprite) && aiFightIsMeleeUnit(pTarget) && !aiFightUnitCanFly(pTarget))
@ -6509,7 +6510,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
else if (aiFightUnitCanFly(pSprite))
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);
}
// 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
else if (aiFightTargetIsPlayer(pXTarget) != NULL) {
else if (aiFightTargetIsPlayer(actor) != nullptr)
{
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
int nSprite;
StatIterator it(kStatDude);
@ -6624,14 +6626,15 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
// skip non-dudes and players
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
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.
else if (pXSource->data1 != 666 && pXSource->data1 != pXTarget->data1) continue;
// don't attack immortal, burning dudes and mates
if (IsBurningDude(pTarget) || !IsKillableDude(pTarget) || (pXSource->data2 == 1 && aiFightIsMateOf(pXSprite, pXTarget)))
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
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
if (pXSource->data3 > 0 && pXTarget->target_i != pSprite->index) {
aiSetTarget_(pXTarget, pSprite->index);
if (pPlayer == NULL && !isActive(pTarget->index))
if (playeractor == NULL && !isActive(pTarget->index))
aiActivateDude(&bloodActors[pXTarget->reference]);
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
if ((pXSprite->target_i < 0 || pPlayer != NULL) && pXSource->data2 == 1 && (PlayClock & 64) != 0) {
spritetype* pMateTarget = NULL;
if ((pMateTarget = aiFightGetMateTargets(pXSprite)) != NULL && pMateTarget->extra > 0) {
XSPRITE* pXMateTarget = &xsprite[pMateTarget->extra];
if (aiFightDudeCanSeeTarget(pXSprite, pDudeInfo, pMateTarget)) {
if ((pXSprite->target_i < 0 || playeractor != NULL) && pXSource->data2 == 1 && (PlayClock & 64) != 0) {
DBloodActor* pMateTargetActor = aiFightGetMateTargets(actor);
if (pMateTargetActor != nullptr && pMateTargetActor->hasX())
{
auto pMateTarget = &pMateTargetActor->s();
XSPRITE* pXMateTarget = &pMateTargetActor->x();
if (aiFightDudeCanSeeTarget(actor, pDudeInfo, pMateTargetActor)) {
if (pXMateTarget->target_i < 0) {
aiSetTarget_(pXMateTarget, pSprite->index);
if (IsDudeSprite(pMateTarget) && !isActive(pMateTarget->index))
@ -6673,7 +6678,7 @@ void useTargetChanger(XSPRITE* pXSource, spritetype* pSprite) {
return;
// 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];
pXSprite->target_i = pMateTarget->index;
pXSprite->targetX = pMate->x;

View file

@ -314,20 +314,15 @@ void aiSetGenIdleState(DBloodActor*);
// ------------------------------------------------------------------------- //
int aiFightGetTargetDist(spritetype* pSprite, DUDEINFO* pDudeInfo, 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 aiFightIsMeleeUnit(spritetype* pDude);
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 aiFightIsMateOf(XSPRITE* pXDude, XSPRITE* pXSprite);
void aiFightAlarmDudesInSight(spritetype* pSprite, int max);
void aiFightActivateDudes(int rx);
void aiFightFreeTargets(int nSprite);
void aiFightFreeAllTargets(XSPRITE* pXSource);
spritetype* aiFightGetTargetInRange(spritetype* pSprite, int minDist, int maxDist, short data, short teamMode);
spritetype* aiFightTargetIsPlayer(XSPRITE* pXSprite);
spritetype* aiFightGetMateTargets(XSPRITE* pXSprite);
// ------------------------------------------------------------------------- //
void useSlopeChanger(XSPRITE* pXSource, int objType, int objIndex);
void damageSprites(DBloodActor* pXSource, DBloodActor* pSprite);