39#define HAPPINESS_ALIEN_MISSION_LOSS -0.02
40#define HAPPINESS_MAX_MISSION_IMPACT 0.07
48 const int nationIndex = rand() %
ccs.numNations;
66 if (nationID ==
nullptr) {
67 cgi->Com_Printf(
"NAT_GetNationByID: nullptr nationID\n");
71 if (
Q_streq(nation->id, nationID))
75 cgi->Com_Printf(
"NAT_GetNationByID: Could not find nation '%s'\n", nationID);
94 float happinessFactor;
96 switch (mission->stage) {
135 return &nation->
stats[0];
146 if (happiness < 0.015)
147 return _(
"Giving up");
148 else if (happiness < 0.025)
150 else if (happiness < 0.04)
152 else if (happiness < 0.06)
154 else if (happiness < 0.10)
156 else if (happiness < 0.20)
157 return _(
"Tolerant");
158 else if (happiness < 0.30)
160 else if (happiness < 0.50)
162 else if (happiness < 0.70)
164 else if (happiness < 0.95)
167 return _(
"Exuberant");
192 const char* newString;
194 const float oldHappiness = stats->
happiness;
195 const float middleHappiness = (minhappiness + 1.0) / 2;
206 if (oldString != newString) {
208 _(
"Nation %s changed happiness from %s to %s"),
_(nation->
name), oldString, newString);
210 }
else if (oldHappiness > middleHappiness && happiness < middleHappiness) {
212 _(
"Nation %s changed happiness to %s"),
_(nation->
name), newString);
214 }
else if (happiness < minhappiness && oldHappiness > minhappiness) {
216 _(
"Happiness of nation %s is %s and less than minimal happiness allowed to the campaign"),
_(nation->
name), newString);
269 float performanceAlien;
270 float performanceCivilian;
271 float deltaHappiness = 0.0f;
272 float happinessDivisor = 5.0f;
273 float victoryBonusPerAlien = 0.1f;
281 if (civilianSum <= 1) {
282 performanceCivilian = 0.0f;
297 performance = performanceCivilian + performanceAlien;
300 deltaHappiness = 0.004 * civilianSum + 0.004 * alienSum;
308 float happinessFactor;
311 if (nation == affectedNation)
312 happinessFactor = deltaHappiness;
314 happinessFactor = deltaHappiness / happinessDivisor;
388 cgi->Com_Printf(
"CL_ParseNations: nation def \"%s\" with same name found, second ignored\n",
name);
396 nation.
idx =
ccs.numNations;
452 cgi->Com_Printf(
"CITY_Parse: city def \"%s\" with same name found, second ignored\n",
name);
476 bool cityCanBeUsed =
false;
477 bool parametersFit =
false;
484 cgi->Com_Printf(
"...... city '%s' has no name\n", city->id);
489 cgi->Com_Printf(
"...... city '%s' has a position in the water\n", city->id);
500 parametersFit =
true;
508 for (
int i = numTypes - 1 ;
i >= 0;
i--) {
509 if (
cgi->LIST_ContainsString(md->
ufos,
cgi->Com_UFOTypeToShortName(ufoTypes[
i]))) {
515 cityCanBeUsed =
true;
520 if (!cityCanBeUsed) {
522 cgi->Com_Printf(
"...... city '%s' can't be used in game: it has no map fitting parameters\n", city->id);
524 cgi->Com_Printf(
" (No map fitting");
525 for (
int i = 0 ;
i < numTypes;
i++)
526 cgi->Com_Printf(
" %s",
cgi->Com_UFOTypeToShortName(ufoTypes[
i]));
527 cgi->Com_Printf(
")\n");
545 const int argCount =
cgi->Cmd_Argc();
547 cgi->Com_Printf(
"Usage: %s <confunc> [nationID] [monthIDX]\n",
cgi->Cmd_Argv(0));
554 if (argCount >= 3 && !
Q_streq(nation->id,
cgi->Cmd_Argv(1)))
558 if (!nation->stats[monthIDX].inuse)
561 if (argCount >= 4 && monthIDX != -1 * atoi(
cgi->Cmd_Argv(3)))
564 cgi->UI_ExecuteConfunc(
"%s %s \"%s\" %d %.4f \"%s\" %d \"%f, %f, %f, %f\"",
569 nation->stats[monthIDX].happiness,
586 const int argCount =
cgi->Cmd_Argc();
588 cgi->Com_Printf(
"Usage: %s <stat_type> <chartnode> <width> <height>\n",
cgi->Cmd_Argv(0));
596 const int width = atoi(
cgi->Cmd_Argv(3));
597 const int height = atoi(
cgi->Cmd_Argv(4));
598 if (width <= 0 || height <= 0)
609 if (!nation->stats[monthIdx].inuse)
612 if (nationIdx == 0 && monthIdx == 0) {
614 maxXVI = nation->stats[monthIdx].xviInfection;
618 if (maxXVI < nation->stats[monthIdx].xviInfection)
619 maxXVI = nation->stats[monthIdx].xviInfection;
625 const float dyFunding = (0 != maxFunding) ? (
float) height / maxFunding : 1;
626 const float dyXvi = (0 != maxXVI) ? (
float) height / maxXVI : 1;
629 if (chart ==
nullptr) {
630 cgi->Com_Printf(
"chart node not found\n");
635 cgi->UI_ExecuteConfunc(
"ui_nation_graph_add_line %s %s %f %f %f %f %s %d",
648 if (!nation->stats[monthIdx].inuse)
653 cgi->UI_ExecuteConfunc(
"ui_nation_graph_add_point %s %d %f",
654 nation->id, (monthIdx * dx), height - dyFunding * funding);
656 cgi->UI_ExecuteConfunc(
"ui_nation_graph_add_point %s %d %f",
657 nation->id, (monthIdx * dx), height - (height * nation->stats[monthIdx].happiness));
659 const int xviInfection= nation->stats[monthIdx].xviInfection;
660 cgi->UI_ExecuteConfunc(
"ui_nation_graph_add_point %s %d %f",
661 nation->id, (monthIdx * dx), height - dyXvi * xviInfection);
673static void NAT_ListCities_f (
void)
676 cgi->Com_Printf(
"City '%s' -- position (%0.1f, %0.1f)\n", city->id, city->pos[0], city->pos[1]);
685static void NAT_NationList_f (
void)
688 cgi->Com_Printf(
"Nation ID: %s\n", nation->id);
689 cgi->Com_Printf(
"...max-funding %i c\n", nation->maxFunding);
690 cgi->Com_Printf(
"...happiness %0.2f\n", nation->stats[0].happiness);
691 cgi->Com_Printf(
"...xviInfection %i\n", nation->stats[0].xviInfection);
692 cgi->Com_Printf(
"...max-soldiers %i\n", nation->maxSoldiers);
693 cgi->Com_Printf(
"...max-scientists %i\n", nation->maxScientists);
694 cgi->Com_Printf(
"...max-workers %i\n", nation->maxWorkers);
695 cgi->Com_Printf(
"...max-pilots %i\n", nation->maxPilots);
696 cgi->Com_Printf(
"...color r:%.2f g:%.2f b:%.2f a:%.2f\n", nation->color[0], nation->color[1], nation->color[2], nation->color[3]);
697 cgi->Com_Printf(
"...pos x:%.0f y:%.0f\n", nation->pos[0], nation->pos[1]);
719 int totalExpenditure = 0;
720 int initialCredits =
ccs.credits;
726 int newScientists = 0, newSoldiers = 0, newPilots = 0, newWorkers = 0;
728 totalIncome += funding;
730 for (
int j = 0; 0.25 + j < (float) nation->maxScientists * stats->
happiness *
ccs.curCampaign->employeeRate; j++) {
737 for (
int j = 0; 0.25 + j < (float) nation->maxSoldiers * stats->
happiness *
ccs.curCampaign->employeeRate; j++) {
745 for (
int j = 0; 0.25 + j < (float) nation->maxPilots * stats->
happiness *
ccs.curCampaign->employeeRate; j++) {
752 for (
int j = 0; 0.25 + j * 2 < (float) nation->maxWorkers * stats->
happiness *
ccs.curCampaign->employeeRate; j++) {
758 Com_sprintf(message,
sizeof(message),
_(
"Gained %i %s, %i %s, %i %s, %i %s, and %i %s from nation %s (%s)"),
759 funding,
ngettext(
"credit",
"credits", funding),
760 newScientists,
ngettext(
"scientist",
"scientists", newScientists),
761 newSoldiers,
ngettext(
"soldier",
"soldiers", newSoldiers),
762 newPilots,
ngettext(
"pilot",
"pilots", newPilots),
763 newWorkers,
ngettext(
"worker",
"workers", newWorkers),
772 if (!employee->isHired())
774 cost += employee->salary();
777 totalExpenditure += cost;
792 totalExpenditure += cost;
795 Com_sprintf(message,
sizeof(message),
_(
"Paid %i credits for aircraft"), cost);
800 while ((base =
B_GetNext(base)) !=
nullptr) {
802 totalExpenditure += cost;
804 Com_sprintf(message,
sizeof(message),
_(
"Paid %i credits for upkeep of %s"), cost, base->
name);
808 if (initialCredits < 0) {
811 cost = (
int)ceil(interest);
812 Com_sprintf(message,
sizeof(message),
_(
"Paid %i credits in interest on your debt."), cost);
813 totalExpenditure += cost;
834 nation->stats[
i] = nation->stats[
i - 1];
840 {
"nation_getstats",
NAT_ListStats_f,
"Returns nation happiness and funding stats through a UI callback."},
841 {
"nation_drawcharts",
NAT_DrawCharts_f,
"Draws nation happiness and funding charts."},
843 {
"debug_listcities", NAT_ListCities_f,
"Debug function to list all cities in game."},
844 {
"debug_listnations", NAT_NationList_f,
"List all nations on the game console"},
846 {
nullptr,
nullptr,
nullptr}
862 cgi->LIST_Delete(&
ccs.cities);
863 cgi->LIST_Delete(&
ccs.nations);
DateTime class definition.
CGAME_HARD_LINKED_FUNCTIONS linkedList_t * LIST_Add(linkedList_t **listDest, void const *data, size_t length)
Share stuff between the different cgame implementations.
#define MapDef_ForeachSingleplayerCampaign(var)
static const short MONTHS_PER_YEAR
#define REMOVE_ELEM(array, index, n)
#define AIR_Foreach(var)
iterates trough all aircraft
@ INTERESTCATEGORY_TERROR_ATTACK
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
memPool_t * cp_campaignPool
int CP_GetSalaryUpKeepBase(const salary_t *salary, const base_t *base)
void CP_UpdateCredits(int credits)
Sets credits and update mn_credits cvar.
Header file for single player campaign control.
const cgame_import_t * cgi
Employee * E_CreateEmployee(employeeType_t type, const nation_t *nation, const ugv_t *ugvType)
Creates an entry of a new employee in the global list and assignes it to no building/base.
const char * E_GetEmployeeString(employeeType_t type, int n)
Convert employeeType_t to translated string.
employeeType_t
The types of employees.
#define E_Foreach(employeeType, var)
bool GEO_PositionFitsTCPNTypes(const vec2_t pos, const linkedList_t *terrainTypes, const linkedList_t *cultureTypes, const linkedList_t *populationTypes, const linkedList_t *nations)
Checks for a given location, if it fulfills all criteria given via parameters (terrain,...
nation_t * GEO_GetNation(const vec2_t pos)
Translate nation map color to nation.
const byte * GEO_GetColor(const vec2_t pos, mapType_t type, bool *coast)
Returns the color value from geoscape of a certain mask (terrain, culture or population) at a given p...
void GEO_PrintParameterStringByPos(const vec2_t pos)
Prints positions parameter in console.
Header for Geoscape management.
#define MapIsWater(color)
uiMessageListNodeMessage_t * MSO_CheckAddNewMessage(const notify_t messagecategory, const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup)
Adds a new message to message stack. It uses message settings to verify whether sound should be playe...
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.
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Campaign missions headers.
#define MIS_Foreach(var)
iterates through missions
bool NAT_SaveXML(xmlNode_t *p)
Nation saving callback.
void NAT_HandleBudget(const campaign_t *campaign)
Update the nation data from all parsed nation each month.
#define HAPPINESS_MAX_MISSION_IMPACT
int NAT_GetFunding(const nation_t *const nation, int month)
Get the funding of a nation at a certain month.
void NAT_SetHappiness(const float minhappiness, nation_t *nation, const float happiness)
Updates the nation happiness.
nation_t * NAT_GetNationByID(const char *nationID)
Return a nation-pointer by the nations id.
static const cmdList_t nationCmds[]
static const value_t nation_vals[]
void NAT_BackupMonthlyData(void)
Backs up each nation's relationship values.
bool NAT_LoadXML(xmlNode_t *p)
Nation loading xml callback.
static void NAT_DrawCharts_f(void)
Console command for UI to draw charts.
nation_t * NAT_GetRandom(void)
Return a pointer to a random nation.
city_t * CITY_GetByPos(vec2_t pos)
Finds a city by it's geoscape coordinates.
void NAT_UpdateHappinessForAllNations(const float minhappiness)
Lower happiness of nations depending on alien activity.
const nationInfo_t * NAT_GetCurrentMonthInfo(const nation_t *const nation)
Get the current month nation stats.
static void NAT_ListStats_f(void)
Console command for UI to gather nation statistics.
void CITY_Parse(const char *name, const char **text)
Parse the city data from script file.
void CL_ParseNations(const char *name, const char **text)
Parse the nation data from script file.
void NAT_InitStartup(void)
Init actions for nation-subsystem.
void NAT_Shutdown(void)
Closing actions for nation-subsystem.
bool NAT_ScriptSanityCheck(void)
Checks the parsed nations and cities for errors.
void CP_HandleNationData(float minHappiness, mission_t *mis, const nation_t *affectedNation, const missionResults_t *results, bool won)
Updates each nation's happiness. Should be called at the completion or expiration of every mission....
const char * NAT_GetCurrentHappinessString(const nation_t *nation)
Translates the current nation happiness float value to a string.
#define HAPPINESS_ALIEN_MISSION_LOSS
const char * NAT_GetHappinessString(const float happiness)
Translates the nation happiness float value to a string.
static const value_t city_vals[]
city_t * CITY_GetById(const char *cityId)
Finds a city by it's scripted identifier.
#define NAT_Foreach(var)
iterates trough nations
void CP_GameTimeStop(void)
Stop game time speed.
Campaign geoscape time header.
int UFO_GetAvailableUFOsForMission(const interestCategory_t missionType, ufoType_t *ufoTypes, bool checkInterest)
Fill an array with available UFOs for the mission type.
#define ngettext(x, y, cnt)
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 ...
Shared parsing functions.
QGL_EXTERN GLint GLenum type
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
XML tag constants for savegame.
#define SAVE_NATION_NATIONS
#define SAVE_NATION_MONTH
#define SAVE_NATION_MONTH_IDX
#define SAVE_NATION_HAPPINESS
#define SAVE_NATION_NATION
#define MEMBER_SIZEOF(TYPE, MEMBER)
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
A base with all it's data.
float victoryBonusPerAlien
linkedList_t * populations
Structure with mission info needed to create results summary at menu won.
int civiliansKilledFriendlyFire
nationInfo_t stats[DateTime::MONTHS_PER_YEAR]
Detailed information about the nation relationship (currently per month, but could be used elsewhere)...
Atomic structure used to define most of the UI.
#define Vector2Equal(a, b)