mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
Enemy roles improvement:
- lowered ENEMYROLES_TURNSTOUNCOVER - increased ENEMY_MEDICS_SEARCHRADIUS - new option: ENEMY_MEDICS_WOUND_MINAMOUNT controls how serious a wound must be before a medic considers it worthy of attention - new option: ENEMY_MEDICS_HEAL_SELF: medics can heal themselves - new option: ENEMY_OFFICERS_SURRENDERSTRENGTHBONUS adds a team surrender strength bonus for officers - tanks cannot become medics, and can't be treated by them either - Menubutton for Role symbol toggle is red if off and green if on - wounded soldiers seek medics, max range is ENEMY_MEDICS_SEARCHRADIUS / 2 - direct sight line between medic and target is no longer required - if hostile civilians allied to the army are in sector, their surrender strength is added to the enemy team git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7080 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -2312,6 +2312,13 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
break;
|
||||
|
||||
case AI_ACTION_DOCTOR_SELF:
|
||||
{
|
||||
pSoldier->AIDoctorSelf();
|
||||
ActionDone( pSoldier );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef BETAVERSION
|
||||
NumMessage("ExecuteAction - Illegal action type = ",pSoldier->aiData.bAction);
|
||||
|
||||
+67
-5
@@ -595,6 +595,7 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
|
||||
break;
|
||||
|
||||
case AI_ACTION_DOCTOR:
|
||||
case AI_ACTION_DOCTOR_SELF:
|
||||
bMinPointsNeeded = 20; // TODO
|
||||
break;
|
||||
|
||||
@@ -3089,6 +3090,10 @@ UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au
|
||||
// must be on the same level
|
||||
if ( pFriend->pathing.bLevel != pSoldier->pathing.bLevel )
|
||||
continue;
|
||||
|
||||
// this is not for tanks
|
||||
if ( TANK(pFriend) )
|
||||
return FALSE;
|
||||
|
||||
// skip if this guy is dead
|
||||
if ( pFriend->stats.bLife <= 0 )
|
||||
@@ -3131,16 +3136,20 @@ UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au
|
||||
if (!pFriend)
|
||||
continue;
|
||||
|
||||
// skip ourselves
|
||||
if (pFriend->ubID == pSoldier->ubID)
|
||||
// skip ourselves (if not allowed)
|
||||
if ( !gGameExternalOptions.fEnemyMedicsHealSelf && pFriend->ubID == pSoldier->ubID)
|
||||
continue;
|
||||
|
||||
// must be on the same level
|
||||
if ( pFriend->pathing.bLevel != pSoldier->pathing.bLevel )
|
||||
continue;
|
||||
|
||||
// this is not for tanks
|
||||
if ( TANK(pFriend) )
|
||||
return FALSE;
|
||||
|
||||
// skip if this guy is dead, not wounded or cannot be healed
|
||||
if ( pFriend->stats.bLife <= 0 || pFriend->iHealableInjury <= 0 || pFriend->stats.bLife >= pFriend->stats.bLifeMax )
|
||||
// skip if this guy is dead, or not wounded (enough)
|
||||
if ( pFriend->stats.bLife <= 0 || pFriend->iHealableInjury < gGameExternalOptions.sEnemyMedicsWoundMinAmount )
|
||||
continue;
|
||||
|
||||
// are we close enough?
|
||||
@@ -3148,7 +3157,60 @@ UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au
|
||||
if ( friendrange < range)
|
||||
{
|
||||
// can we see this guy?
|
||||
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pFriend->sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
|
||||
//if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pFriend->sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
|
||||
{
|
||||
range = friendrange;
|
||||
id = pFriend->ubID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// get the id of the closest medic (closer than x tiles) of a specific team
|
||||
UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam )
|
||||
{
|
||||
UINT8 id = NOBODY;
|
||||
UINT32 uiLoop;
|
||||
SOLDIERTYPE * pFriend;
|
||||
INT16 range = aRange;
|
||||
|
||||
// go through each soldier, looking for "friends" (soldiers on same team)
|
||||
for (uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop < gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
|
||||
{
|
||||
pFriend = MercPtrs[ uiLoop ];
|
||||
|
||||
// if this merc is inactive, not in sector, or dead
|
||||
if (!pFriend)
|
||||
continue;
|
||||
|
||||
// skip ourselves (we seek OTHER people)
|
||||
if ( pFriend->ubID == pSoldier->ubID)
|
||||
continue;
|
||||
|
||||
// must be on the same level
|
||||
if ( pFriend->pathing.bLevel != pSoldier->pathing.bLevel )
|
||||
continue;
|
||||
|
||||
// this is not for tanks
|
||||
if ( TANK(pFriend) )
|
||||
return FALSE;
|
||||
|
||||
// skip this guy if he is dead or unconscious
|
||||
if ( pFriend->stats.bLife < OKLIFE )
|
||||
continue;
|
||||
|
||||
// skip if this guy if he is no medic
|
||||
if ( !pFriend->CanMedicAI() )
|
||||
continue;
|
||||
|
||||
// are we close enough?
|
||||
INT16 friendrange = SpacesAway(pSoldier->sGridNo, pFriend->sGridNo);
|
||||
if ( friendrange < range)
|
||||
{
|
||||
// can we see this guy?
|
||||
//if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pFriend->sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
|
||||
{
|
||||
range = friendrange;
|
||||
id = pFriend->ubID;
|
||||
|
||||
@@ -936,7 +936,20 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
UINT8 ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
// are we ourselves the patient?
|
||||
if ( ubPerson == pSoldier->ubID )
|
||||
{
|
||||
// if not already crouched, crouch down first
|
||||
if ( gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_CROUCH && IsValidStance( pSoldier, ANIM_CROUCH ) && GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) <= pSoldier->bActionPoints )
|
||||
{
|
||||
pSoldier->aiData.usActionData = ANIM_CROUCH;
|
||||
|
||||
return(AI_ACTION_CHANGE_STANCE);
|
||||
}
|
||||
|
||||
return(AI_ACTION_DOCTOR_SELF);
|
||||
}
|
||||
else if ( ubPerson != NOBODY )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
|
||||
{
|
||||
@@ -965,6 +978,24 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
|
||||
|
||||
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we are not a medic, but are wounded, seek a medic
|
||||
else if ( pSoldier->iHealableInjury >= gGameExternalOptions.sEnemyMedicsWoundMinAmount )
|
||||
{
|
||||
UINT8 ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) > 1 )
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
|
||||
|
||||
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
@@ -1619,7 +1650,20 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
UINT8 ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
// are we ourselves the patient?
|
||||
if ( ubPerson == pSoldier->ubID )
|
||||
{
|
||||
// if not already crouched, crouch down first
|
||||
if ( gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_CROUCH && IsValidStance( pSoldier, ANIM_CROUCH ) && GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) <= pSoldier->bActionPoints )
|
||||
{
|
||||
pSoldier->aiData.usActionData = ANIM_CROUCH;
|
||||
|
||||
return(AI_ACTION_CHANGE_STANCE);
|
||||
}
|
||||
|
||||
return(AI_ACTION_DOCTOR_SELF);
|
||||
}
|
||||
else if ( ubPerson != NOBODY )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
|
||||
{
|
||||
@@ -1648,6 +1692,24 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
|
||||
|
||||
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we are not a medic, but are wounded, seek a medic
|
||||
else if ( pSoldier->iHealableInjury >= gGameExternalOptions.sEnemyMedicsWoundMinAmount )
|
||||
{
|
||||
UINT8 ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) > 1 )
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
|
||||
|
||||
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
@@ -2943,7 +3005,20 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
{
|
||||
UINT8 ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
// are we ourselves the patient?
|
||||
if ( ubPerson == pSoldier->ubID )
|
||||
{
|
||||
// if not already crouched, crouch down first
|
||||
if ( gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_CROUCH && IsValidStance( pSoldier, ANIM_CROUCH ) && GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) <= pSoldier->bActionPoints )
|
||||
{
|
||||
pSoldier->aiData.usActionData = ANIM_CROUCH;
|
||||
|
||||
return(AI_ACTION_CHANGE_STANCE);
|
||||
}
|
||||
|
||||
return(AI_ACTION_DOCTOR_SELF);
|
||||
}
|
||||
else if ( ubPerson != NOBODY )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
|
||||
{
|
||||
@@ -2972,6 +3047,24 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
|
||||
|
||||
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we are not a medic, but are wounded, seek a medic
|
||||
else if ( pSoldier->iHealableInjury >= gGameExternalOptions.sEnemyMedicsWoundMinAmount )
|
||||
{
|
||||
UINT8 ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
{
|
||||
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) > 1 )
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
|
||||
|
||||
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
|
||||
@@ -105,6 +105,7 @@ typedef enum
|
||||
AI_ACTION_FREE_PRISONER, // added by Flugente: free a prisoner
|
||||
AI_ACTION_USE_SKILL, // added by Flugente: perform a skill, which one is stored in usAISkillUse
|
||||
AI_ACTION_DOCTOR, // added by Flugente: AI-ONLY! bandage/surgery on fellow AI. DO NOT USE THIS FOR MERCS!!!
|
||||
AI_ACTION_DOCTOR_SELF, // added by Flugente: AI-ONLY! bandage/surgery on self. DO NOT USE THIS FOR MERCS!!!
|
||||
} ActionType;
|
||||
|
||||
|
||||
@@ -266,4 +267,7 @@ UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au
|
||||
// get the id of the closest soldier (closer than x tiles) of a specific team that is wounded that we can currently see
|
||||
UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam );
|
||||
|
||||
// get the id of the closest medic (closer than x tiles) of a specific team
|
||||
UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam );
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user