UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_statistics.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23*/
24
25#include "../../cl_shared.h"
26#include "../../ui/ui_dataids.h"
27#include "cp_campaign.h"
28#include "cp_xvi.h"
30
31#define MAX_STATS_BUFFER 2048
36static void STATS_Update_f (void)
37{
38 const campaign_t* campaign = ccs.curCampaign;
39 static char statsBuffer[MAX_STATS_BUFFER];
40 OBJZERO(statsBuffer);
41 char* pos = statsBuffer;
42 /* campaign */
43 cgi->UI_RegisterText(TEXT_GENERIC, pos);
44 Q_strcat(pos, (ptrdiff_t)(&statsBuffer[MAX_STATS_BUFFER] - pos), _("Max. allowed debts: %ic\n"), campaign->negativeCreditsUntilLost);
45
46 /* only show the xvi spread data when it's available */
47 if (CP_IsXVIVisible()) {
48 Q_strcat(pos, (ptrdiff_t)(&statsBuffer[MAX_STATS_BUFFER] - pos),
49 _("Max. allowed eXtraterrestial Viral Infection: %i%%\n"
50 "Current eXtraterrestial Viral Infection: %i%%"),
53 }
54}
55
59static void STAT_GetExpenses_f (void)
60{
61 const int argCount = cgi->Cmd_Argc();
62 if (argCount < 2) {
63 cgi->Com_Printf("Usage: %s <confunc>\n", cgi->Cmd_Argv(0));
64 return;
65 }
66 char callback[MAX_VAR];
67 Q_strncpyz(callback, cgi->Cmd_Argv(1), sizeof(callback));
68
70 const campaign_t* campaign = ccs.curCampaign;
71 const salary_t* salary = &campaign->salaries;
72
73 int count = 0;
74 int cost = 0;
75 for (int i = 0; i < MAX_EMPL; i++) {
76 E_Foreach(i, employee) {
77 if (!employee->isHired())
78 continue;
79 cost += employee->salary();
80 count++;
81 }
82
83 }
84 cgi->UI_ExecuteConfunc("%s %s \"%s\" %d",
85 callback,
86 "employee",
87 ngettext("Salary", "Salaries", count),
88 cost
89 );
90
91 count = 0;
92 cost = 0;
93 AIR_Foreach(aircraft) {
94 if (aircraft->status == AIR_CRASHED)
95 continue;
96 cost += aircraft->price * salary->aircraftFactor / salary->aircraftDivisor;
97 count++;
98 }
99 cgi->UI_ExecuteConfunc("%s %s \"%s\" %d",
100 callback,
101 "aircraft",
102 ngettext("Aircraft", "Aircraft", count),
103 cost
104 );
105
106 base_t* base = nullptr;
107 while ((base = B_GetNext(base)) != nullptr) {
108 cost = CP_GetSalaryUpKeepBase(salary, base);
109 cgi->UI_ExecuteConfunc("%s base_%d \"%s: %s\" %d",
110 callback,
111 base->idx,
112 _("Base"),
113 base->name,
114 cost
115 );
116 }
117
118 if (ccs.credits < 0) {
119 const float interest = ccs.credits * campaign->salaries.debtInterest;
120 cgi->UI_ExecuteConfunc("%s %s \"%s\" %d",
121 callback,
122 "interest",
123 _("Debt interest:"),
124 (int)ceil(interest)
125 );
126 }
127}
128
129
135{
136 xmlNode_t* stats;
137
138 stats = cgi->XML_AddNode(parent, SAVE_STATS_STATS);
139
140 cgi->XML_AddIntValue(stats, SAVE_STATS_MISSIONS, ccs.campaignStats.missions);
141 cgi->XML_AddIntValue(stats, SAVE_STATS_MISSIONSWON, ccs.campaignStats.missionsWon);
142 cgi->XML_AddIntValue(stats, SAVE_STATS_MISSIONSLOST, ccs.campaignStats.missionsLost);
143 cgi->XML_AddIntValue(stats, SAVE_STATS_BASESBUILT, ccs.campaignStats.basesBuilt);
144 cgi->XML_AddIntValue(stats, SAVE_STATS_BASESATTACKED, ccs.campaignStats.basesAttacked);
145 cgi->XML_AddIntValue(stats, SAVE_STATS_INSTALLATIONSBUILT, ccs.campaignStats.installationsBuilt);
146 cgi->XML_AddIntValue(stats, SAVE_STATS_INTERCEPTIONS, ccs.campaignStats.interceptions);
147 cgi->XML_AddIntValue(stats, SAVE_STATS_SOLDIERSLOST, ccs.campaignStats.soldiersLost);
148 cgi->XML_AddIntValue(stats, SAVE_STATS_SOLDIERSNEW, ccs.campaignStats.soldiersNew);
149 cgi->XML_AddIntValue(stats, SAVE_STATS_KILLEDALIENS, ccs.campaignStats.killedAliens);
150 cgi->XML_AddIntValue(stats, SAVE_STATS_CAPTUREDALIENS, ccs.campaignStats.capturedAliens);
151 cgi->XML_AddIntValue(stats, SAVE_STATS_RESCUEDCIVILIANS, ccs.campaignStats.rescuedCivilians);
152 cgi->XML_AddIntValue(stats, SAVE_STATS_RESEARCHEDTECHNOLOGIES, ccs.campaignStats.researchedTechnologies);
153 cgi->XML_AddIntValue(stats, SAVE_STATS_MONEYINTERCEPTIONS, ccs.campaignStats.moneyInterceptions);
154 cgi->XML_AddIntValue(stats, SAVE_STATS_MONEYBASES, ccs.campaignStats.moneyBases);
155 cgi->XML_AddIntValue(stats, SAVE_STATS_MONEYRESEARCH, ccs.campaignStats.moneyResearch);
156 cgi->XML_AddIntValue(stats, SAVE_STATS_MONEYWEAPONS, ccs.campaignStats.moneyWeapons);
157 cgi->XML_AddIntValue(stats, SAVE_STATS_UFOSDETECTED, ccs.campaignStats.ufosDetected);
158 cgi->XML_AddIntValue(stats, SAVE_STATS_ALIENBASESBUILT, ccs.campaignStats.alienBasesBuilt);
159 cgi->XML_AddIntValue(stats, SAVE_STATS_UFOSSTORED, ccs.campaignStats.ufosStored);
160 cgi->XML_AddIntValue(stats, SAVE_STATS_AIRCRAFTHAD, ccs.campaignStats.aircraftHad);
161
162 return true;
163}
164
170{
171 xmlNode_t* stats;
172 bool success = true;
173
174 stats = cgi->XML_GetNode(parent, SAVE_STATS_STATS);
175 if (!stats) {
176 cgi->Com_Printf("Did not find stats entry in xml!\n");
177 return false;
178 }
179 ccs.campaignStats.missions = cgi->XML_GetInt(stats, SAVE_STATS_MISSIONS, 0);
180 ccs.campaignStats.missionsWon = cgi->XML_GetInt(stats, SAVE_STATS_MISSIONSWON, 0);
181 ccs.campaignStats.missionsLost = cgi->XML_GetInt(stats, SAVE_STATS_MISSIONSLOST, 0);
182 ccs.campaignStats.basesBuilt = cgi->XML_GetInt(stats, SAVE_STATS_BASESBUILT, 0);
183 ccs.campaignStats.basesAttacked = cgi->XML_GetInt(stats, SAVE_STATS_BASESATTACKED, 0);
184 ccs.campaignStats.installationsBuilt = cgi->XML_GetInt(stats, SAVE_STATS_INSTALLATIONSBUILT, 0);
185 ccs.campaignStats.interceptions = cgi->XML_GetInt(stats, SAVE_STATS_INTERCEPTIONS, 0);
186 ccs.campaignStats.soldiersLost = cgi->XML_GetInt(stats, SAVE_STATS_SOLDIERSLOST, 0);
187 ccs.campaignStats.soldiersNew = cgi->XML_GetInt(stats, SAVE_STATS_SOLDIERSNEW, 0);
188 ccs.campaignStats.killedAliens = cgi->XML_GetInt(stats, SAVE_STATS_KILLEDALIENS, 0);
189 ccs.campaignStats.capturedAliens = cgi->XML_GetInt(stats, SAVE_STATS_CAPTUREDALIENS, 0);
190 ccs.campaignStats.rescuedCivilians = cgi->XML_GetInt(stats, SAVE_STATS_RESCUEDCIVILIANS, 0);
191 ccs.campaignStats.researchedTechnologies = cgi->XML_GetInt(stats, SAVE_STATS_RESEARCHEDTECHNOLOGIES, 0);
192 ccs.campaignStats.moneyInterceptions = cgi->XML_GetInt(stats, SAVE_STATS_MONEYINTERCEPTIONS, 0);
193 ccs.campaignStats.moneyBases = cgi->XML_GetInt(stats, SAVE_STATS_MONEYBASES, 0);
194 ccs.campaignStats.moneyResearch = cgi->XML_GetInt(stats, SAVE_STATS_MONEYRESEARCH, 0);
195 ccs.campaignStats.moneyWeapons = cgi->XML_GetInt(stats, SAVE_STATS_MONEYWEAPONS, 0);
196 ccs.campaignStats.ufosDetected = cgi->XML_GetInt(stats, SAVE_STATS_UFOSDETECTED, 0);
197 ccs.campaignStats.alienBasesBuilt = cgi->XML_GetInt(stats, SAVE_STATS_ALIENBASESBUILT, 0);
198 ccs.campaignStats.ufosStored = cgi->XML_GetInt(stats, SAVE_STATS_UFOSSTORED, 0);
199 ccs.campaignStats.aircraftHad = cgi->XML_GetInt(stats, SAVE_STATS_AIRCRAFTHAD, 0);
200
201 /* freeing the memory below this node */
202 mxmlDelete(stats);
203 return success;
204}
205
207 {"stats_update", STATS_Update_f, "Update capaign statistics UI"},
208 {"stats_getexpenses", STAT_GetExpenses_f, "Gather expenses for the statistics UI"},
209 {nullptr, nullptr, nullptr}
210};
211
212
214{
215 cgi->Cmd_TableAddList(statisticsCallbacks);
216}
217
218void STATS_ShutDown (void)
219{
220 cgi->Cmd_TableRemoveList(statisticsCallbacks);
221}
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
#define AIR_Foreach(var)
iterates trough all aircraft
@ AIR_CRASHED
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
Definition cp_base.cpp:286
int CP_GetSalaryUpKeepBase(const salary_t *salary, const base_t *base)
ccs_t ccs
Header file for single player campaign control.
const cgame_import_t * cgi
@ MAX_EMPL
Definition cp_employee.h:36
#define E_Foreach(employeeType, var)
bool STATS_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
static void STATS_Update_f(void)
Shows the current stats from stats_t stats.
static const cmdList_t statisticsCallbacks[]
bool STATS_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
void STATS_ShutDown(void)
static void STAT_GetExpenses_f(void)
Console command for UI to gather expenses.
#define MAX_STATS_BUFFER
void STATS_InitStartup(void)
bool CP_IsXVIVisible(void)
Returns true if the XVI effect should be visible to the player.
Definition cp_xvi.cpp:196
int CP_GetAverageXVIRate(void)
Return the average XVI rate.
Definition cp_xvi.cpp:163
Campaign XVI header.
#define ngettext(x, y, cnt)
Definition g_local.h:40
QGL_EXTERN GLuint count
Definition r_gl.h:99
QGL_EXTERN GLint i
Definition r_gl.h:113
XML tag constants for savegame.
#define SAVE_STATS_INSTALLATIONSBUILT
#define SAVE_STATS_RESEARCHEDTECHNOLOGIES
#define SAVE_STATS_AIRCRAFTHAD
#define SAVE_STATS_MONEYINTERCEPTIONS
#define SAVE_STATS_KILLEDALIENS
#define SAVE_STATS_SOLDIERSNEW
#define SAVE_STATS_MONEYWEAPONS
#define SAVE_STATS_MONEYBASES
#define SAVE_STATS_INTERCEPTIONS
#define SAVE_STATS_RESCUEDCIVILIANS
#define SAVE_STATS_SOLDIERSLOST
#define SAVE_STATS_MISSIONS
#define SAVE_STATS_BASESBUILT
#define SAVE_STATS_CAPTUREDALIENS
#define SAVE_STATS_ALIENBASESBUILT
#define SAVE_STATS_MISSIONSWON
#define SAVE_STATS_MISSIONSLOST
#define SAVE_STATS_UFOSDETECTED
#define SAVE_STATS_BASESATTACKED
#define SAVE_STATS_UFOSSTORED
#define SAVE_STATS_STATS
#define SAVE_STATS_MONEYRESEARCH
#define OBJZERO(obj)
Definition shared.h:178
#define MAX_VAR
Definition shared.h:36
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
A base with all it's data.
Definition cp_base.h:84
int idx
Definition cp_base.h:85
char name[MAX_VAR]
Definition cp_base.h:86
salary_t salaries
int maxAllowedXVIRateUntilLost
int negativeCreditsUntilLost
int aircraftFactor
float debtInterest
int aircraftDivisor
@ TEXT_GENERIC
Definition ui_dataids.h:56
#define xmlNode_t
Definition xml.h:24