40typedef enum autoMission_teamType_s {
48#define MAX_SOLDIERS_AUTOMISSION MAX_TEAMS * AUTOMISSION_TEAM_TYPE_MAX
54typedef struct autoUnit_s {
65typedef struct autoMissionBattle_s {
86#define SKILL_AWARD_SCALE 0.3f
87#define ABILITY_AWARD_SCALE 0.06f
89#define AM_IsPlayer(type) ((type) == AUTOMISSION_TEAM_TYPE_PLAYER)
90#define AM_IsAlien(type) ((type) == AUTOMISSION_TEAM_TYPE_ALIEN)
91#define AM_IsCivilian(type) ((type) == AUTOMISSION_TEAM_TYPE_CIVILIAN)
92#define AM_SetHostile(battle, team, otherTeam, value) (battle)->isHostile[(team)][(otherTeam)] = (value)
93#define AM_IsHostile(battle, team, otherTeam) ((battle)->isHostile[(team)][(otherTeam)])
95#define AM_GetUnit(battle, teamIdx, unitIdx) (&battle->units[teamIdx][unitIdx])
96#define AM_IsUnitActive(unit) (((unit)->chr->HP > 0) && ((unit)->chr->HP > (unit)->chr->STUN))
104 assert(battle !=
nullptr);
115 battle->
isHostile[team][otherTeam] =
true;
138 assert(battle !=
nullptr);
139 assert(aircraft !=
nullptr);
146 unit->
chr = &employee->chr;
147 unit->
team = teamNum;
148 unit->
idx = teamSize;
151 if (employee->chr.HP > 0)
157 battle->
nUnits[teamNum] = teamSize;
158 battle->
actUnits[teamNum] = unitsAlive;
161 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Warning: Attempt to add soldiers to an auto-mission from an aircraft with no soldiers onboard.\n");
162 cgi->Com_DPrintf(
DEBUG_CLIENT,
"--- Note: Aliens might win this mission by default because they are un-challenged, with no resistance!\n");
164 if (unitsAlive == 0) {
165 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Warning: Attempt to add team to auto battle where all the units on the team are DEAD!\n");
166 cgi->Com_DPrintf(
DEBUG_CLIENT,
"--- Note: This team will LOSE the battle by default.\n");
216 cgi->CL_GenerateCharacter(unit->
chr, teamDef->
id);
228 cgi->INV_DestroyInventory(&unit->
chr->
inv);
240 assert(missionParams);
245 if (missionParams->
aliens > 0) {
248 for (
int unitIDX = 0; unitIDX < missionParams->
aliens; unitIDX++) {
264 for (
int unitIDX = 0; unitIDX < missionParams->
civilians; unitIDX++) {
284 bool civsInverted = !civsInfected;
294 if (battle->
actUnits[otherTeam] <= 0)
330 int isHostileTotal = 0;
331 int totalActiveTeams = 0;
332 int lastActiveTeam = -1;
345 unitTotal += battle->
nUnits[team];
348 lastActiveTeam = team;
352 if (battle->
nUnits[isHostileCount] <= 0)
362 cgi->Com_Error(
ERR_DROP,
"Grand total of ZERO units are fighting in auto battle, something is wrong.");
365 cgi->Com_Error(
ERR_DROP,
"Negative number of total units are fighting in auto battle, something is VERY wrong!");
367 if (isHostileTotal <= 0)
368 cgi->Com_Error(
ERR_DROP,
"No team has any other team hostile toward it, no battle is possible!");
370 if (totalActiveTeams <= 0)
371 cgi->Com_Error(
ERR_DROP,
"No Active teams detected in Auto Battle!");
373 if (totalActiveTeams == 1) {
374 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Note: Only one active team detected, this team will win the auto mission battle by default.\n");
381 teamPooledHealth[team] = 0.0;
382 teamPooledHealthMax[team] = 0.0;
383 teamPooledUnitsHealthy[team] = 0.0;
384 teamPooledUnitsTotal[team] = 0.0;
388 double skillAdjCalcAbs;
390 for (
int currentUnit = 0; currentUnit < battle->
nUnits[team]; currentUnit++) {
397 teamPooledHealth[team] += chr->
HP;
398 teamPooledHealthMax[team] += chr->
maxHP;
399 teamPooledUnitsTotal[team] += 1.0;
401 teamPooledUnitsHealthy[team] += 1.0;
404 assert(teamPooledHealthMax[team] > 0.0);
405 assert(teamPooledUnitsTotal[team] > 0.0);
407 teamRatioHealthTotal[team] = teamPooledHealth[team] / teamPooledHealthMax[team];
408 teamRatioHealthyUnits[team] = teamPooledUnitsHealthy[team] / teamPooledUnitsTotal[team];
412 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Team %i has calculated ratio of healthy units of %f.\n",
413 team, teamRatioHealthyUnits[team]);
414 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Team %i has calculated ratio of health values of %f.\n",
415 team, teamRatioHealthTotal[team]);
418 skillAdjCalc = teamRatioHealthyUnits[team] + teamRatioHealthTotal[team];
419 skillAdjCalc *= 0.50;
421 skillAdjCalc -= 0.50;
422 skillAdjCalcAbs = fabs(skillAdjCalc);
423 if (skillAdjCalc > 0.0)
425 else if (skillAdjCalc < 0.0)
429 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Team %i has adjusted skill rating of %f.\n",
481 if (battle->
nUnits[team] <= 0)
485 idx = rand() % battle->
nUnits[team];
495 for (nextIdx = (idx + 1) % battle->
nUnits[team]; nextIdx != idx; nextIdx = (nextIdx + 1) % battle->
nUnits[team]) {
552 double calcRand =
frand();
556 if (calcRand > effective)
561 if (calcRand >= (0.050 - (effective * 0.050)))
567 eChr->
HP = std::max(0, eChr->
HP - strikeDamage);
577 cgi->Com_Printf(
"AutoBattle: Team: %d Unit: %d killed Team: %d Unit: %d\n", currUnit->
team, currUnit->
idx, eUnit->
team, eUnit->
idx);
581 switch (currUnit->
team) {
583 switch (eUnit->
team) {
604 switch (eUnit->
team) {
622 switch (eUnit->
team) {
657 if (eUnit ==
nullptr)
661 if (!
AM_CheckFire(battle, currUnit, eUnit, effective)) {
664 if (eUnit !=
nullptr)
677 bool combatActive =
true;
680 cgi->Com_Printf(
"Auto battle started\n");
682 cgi->Com_Printf(
"Team %d Units: %d\n", teamID, battle->
nUnits[teamID]);
686 while (combatActive) {
699 for (
int currentUnit = 0; currentUnit < battle->
nUnits[team]; currentUnit++) {
703 const double hpLeftRatio = chr->
HP / chr->
maxHP;
709 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Unit %i on team %i has adjusted attack rating of %f.\n",
738 cgi->Cvar_SetValue(
"cp_mission_tryagain", 0);
740 cgi->UI_PushWindow(
"won");
744 MS_AddNewMessage(
_(
"Notice"),
_(
"You've defeated the enemy, but did poorly, and many civilians were killed"));
746 cgi->UI_PushWindow(
"lost");
758 assert(aircraft !=
nullptr);
759 assert(chr !=
nullptr);
764 Item* item =
nullptr;
837 cgi->Com_DPrintf(
DEBUG_CLIENT,
"AM_UpdateSurivorsAfterBattle: Soldier %s earned %d experience points in skill #%d (total experience: %d).\n",
845 cgi->Com_DPrintf(
DEBUG_CLIENT,
"AM_UpdateSurivorsAfterBattle: Soldier %s earned %d experience points in skill #%d (total experience: %d).\n",
852 cgi->Com_DPrintf(
DEBUG_CLIENT,
"AM_UpdateSurivorsAfterBattle: Soldier %s earned %d experience points in skill #%d (total experience: %d).\n",
901 cgi->Com_Printf(
"Story-related mission cannot be done via automission\n");
927 if (
ccs.missionResultCallback) {
928 ccs.missionResultCallback(results);
#define ABILITY_NUM_TYPES
Header file for inventory handling and Equipment menu.
Share stuff between the different cgame implementations.
short getRandomBodyPart(void) const
Item * getNextItem(const Item *prev) const
const Container * getNextCont(const Container *prev, bool inclTemp=false) const
item instance data, with linked list capability
const objDef_t * ammoDef(void) const
const objDef_t * def(void) const
void AII_CollectItem(aircraft_t *aircraft, const objDef_t *item, int amount)
Add an item to aircraft inventory.
bool AL_AddAlienTypeToAircraftCargo(aircraft_t *aircraft, const teamDef_t *teamDef, int amount, bool dead)
Adds an alientype to an aircraft cargo.
static void AM_CreateUnitChr(autoUnit_t *unit, const teamDef_t *teamDef, const equipDef_t *ed)
Create character for a Unit.
static void AM_DoFight(autoMissionBattle_t *battle)
Main Battle loop function.
#define ABILITY_AWARD_SCALE
void AM_Go(mission_t *mission, aircraft_t *aircraft, const campaign_t *campaign, const battleParam_t *battleParameters, missionResults_t *results)
Handles the auto mission.
static bool AM_UnitAttackEnemy(autoMissionBattle_t *battle, autoUnit_t *currUnit, const double effective)
Make Unit attack his enemies (or friends).
#define MAX_SOLDIERS_AUTOMISSION
static int AM_GetRandomTeam(autoMissionBattle_t *battle, int currTeam, bool enemy)
returns a randomly selected active team
#define AM_IsUnitActive(unit)
#define AM_IsPlayer(type)
static void AM_SetDefaultHostilities(autoMissionBattle_t *battle, const bool civsInfected)
Run this on an auto mission battle before the battle is actually simulated, to set default values for...
#define SKILL_AWARD_SCALE
Constants for automission experience gain factors.
void AM_InitStartup(void)
Init actions for automission-subsystem.
static void AM_MoveCharacterInventoryIntoItemCargo(aircraft_t *aircraft, character_t *chr)
Move equipment carried by the soldier/alien to the aircraft's itemcargo bay.
#define AM_IsHostile(battle, team, otherTeam)
static void AM_FillTeamFromAircraft(autoMissionBattle_t *battle, const autoMissionTeamType_t teamNum, const aircraft_t *aircraft, const campaign_t *campaign)
Adds team data for a specified team in an auto-mission object, from a (player) aircraft.
static autoUnit_t * AM_GetRandomActiveUnit(autoMissionBattle_t *battle, int currTeam, bool enemy)
returns a randomly selected active unit
#define AM_SetHostile(battle, team, otherTeam, value)
static void AM_AlienCollect(aircraft_t *aircraft, const autoMissionBattle_t *battle)
Collect alien bodies and items after battle.
static void AM_DisplayResults(const autoMissionBattle_t *battle)
This will display on-screen, for the player, results of the auto mission.
autoMissionTeamType_t
Possible types of teams that can fight in an auto mission battle.
@ AUTOMISSION_TEAM_TYPE_MAX
@ AUTOMISSION_TEAM_TYPE_ALIEN
@ AUTOMISSION_TEAM_TYPE_CIVILIAN
@ AUTOMISSION_TEAM_TYPE_PLAYER
void AM_Shutdown(void)
Closing actions for automission-subsystem.
static autoUnit_t * AM_GetRandomActiveUnitOfTeam(autoMissionBattle_t *battle, int team)
returns a randomly selected alive unit from a team
static void AM_FillTeamFromBattleParams(autoMissionBattle_t *battle, const battleParam_t *missionParams)
Creates team data for alien and civilian teams based on the mission parameters data.
static void AM_CleanBattleParameters(autoMissionBattle_t *battle)
Clean up alien and civilian teams.
static void AM_CalculateTeamScores(autoMissionBattle_t *battle)
Calcuates Team strength scores for autobattle.
static void AM_DestroyUnitChr(autoUnit_t *unit)
Destroys character of a Unit.
#define AM_IsCivilian(type)
#define AM_GetUnit(battle, teamIdx, unitIdx)
static void AM_UpdateSurivorsAfterBattle(const autoMissionBattle_t *battle, struct aircraft_s *aircraft)
This looks at a finished auto battle, and uses values from it to kill or lower health of surviving so...
static bool AM_CheckFire(autoMissionBattle_t *battle, autoUnit_t *currUnit, autoUnit_t *eUnit, const double effective)
Check and do attack on a team.
static void AM_ClearBattle(autoMissionBattle_t *battle)
Clears, initializes, or resets a single auto mission, sets default values.
Header file for single player automatic (quick, simulated) missions, without going to the battlescape...
memPool_t * cp_campaignPool
Header file for single player campaign control.
const cgame_import_t * cgi
int CHAR_GetMaxExperiencePerMission(const abilityskills_t skill)
Determines the maximum amount of XP per skill that can be gained from any one mission.
void CHAR_UpdateSkills(character_t *chr)
Updates the character skills after a mission.
Header file for character (soldier, alien) related campaign functions.
void E_RemoveInventoryFromStorage(Employee *employee)
Removes the items of an employee (soldier) from the base storage (s)he is hired at.
Header for Geoscape management.
uiMessageListNodeMessage_t * MS_AddNewMessage(const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup, bool playSound)
Adds a new message to message stack.
void MIS_InitResultScreen(const missionResults_t *results)
Updates mission result menu text with appropriate values.
header file UI callbacks for missions.
Campaign mission triggers.
Campaign missions headers.
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
float frand(void)
Return random values between 0 and 1.
#define Mem_PoolAllocType(type, pool)
An aircraft with all it's data.
alien team group definition.
const teamDef_t * alienTeams[MAX_TEAMS_PER_MISSION]
Data structure for a simulated or auto mission.
short nUnits[AUTOMISSION_TEAM_TYPE_MAX]
short actUnits[AUTOMISSION_TEAM_TYPE_MAX]
autoUnit_t units[AUTOMISSION_TEAM_TYPE_MAX][MAX_SOLDIERS_AUTOMISSION]
bool isHostile[AUTOMISSION_TEAM_TYPE_MAX][AUTOMISSION_TEAM_TYPE_MAX]
int teamAccomplishment[AUTOMISSION_TEAM_TYPE_MAX]
double scoreTeamEquipment[AUTOMISSION_TEAM_TYPE_MAX]
missionResults_t * results
double scoreTeamDifficulty[AUTOMISSION_TEAM_TYPE_MAX]
double scoreTeamSkill[AUTOMISSION_TEAM_TYPE_MAX]
One unit (soldier/alien/civilian) of the autobattle.
autoMissionTeamType_t team
alienTeamGroup_t * alienTeamGroup
char alienEquipment[MAX_VAR]
Describes a character with all its attributes.
const teamDef_t * teamDef
Structure of all stats collected for an actor over time.
int kills[KILLED_NUM_TYPES]
int experience[SKILL_NUM_TYPES+1]
Structure with mission info needed to create results summary at menu won.
int civiliansKilledFriendlyFire
const struct mission_s * mission
int ownKilledFriendlyFire
const objDef_t * onlyWeapon
const BodyData * bodyTemplate
int treatmentLevel[BODYPART_MAXTYPE]