cp_nation.c

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2002-2010 UFO: Alien Invasion.
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019 See the GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00024 
00025 */
00026 
00027 #include "../client.h"
00028 #include "../cl_shared.h"
00029 #include "../ui/ui_main.h"
00030 #include "../ui/node/ui_node_linechart.h"
00031 #include "../../shared/parse.h"
00032 #include "cp_campaign.h"
00033 #include "cp_map.h"
00034 #include "cp_ufo.h"
00035 #include "save/save_nation.h"
00036 
00037 nation_t *NAT_GetNationByIDX (const int index)
00038 {
00039     assert(index >= 0);
00040     assert(index < ccs.numNations);
00041 
00042     return &ccs.nations[index];
00043 }
00044 
00050 nation_t *NAT_GetNationByID (const char *nationID)
00051 {
00052     int i;
00053 
00054     if (!nationID) {
00055         Com_Printf("NAT_GetNationByID: NULL nationID\n");
00056         return NULL;
00057     }
00058     for (i = 0; i < ccs.numNations; i++) {
00059         nation_t *nation = &ccs.nations[i];
00060         if (!strcmp(nation->id, nationID))
00061             return nation;
00062     }
00063 
00064     Com_Printf("NAT_GetNationByID: Could not find nation '%s'\n", nationID);
00065 
00066     /* No matching nation found - ERROR */
00067     return NULL;
00068 }
00069 
00070 
00076 void NAT_UpdateHappinessForAllNations (void)
00077 {
00078     const linkedList_t *list = ccs.missions;
00079 
00080     for (;list; list = list->next) {
00081         const mission_t *mission = (mission_t *)list->data;
00082         nation_t *nation = MAP_GetNation(mission->pos);
00083         /* Difficulty modifier range is [0, 0.02f] */
00084 
00085         /* Some non-water location have no nation */
00086         if (nation) {
00087             float happinessFactor;
00088             switch (mission->stage) {
00089             case STAGE_TERROR_MISSION:
00090             case STAGE_SUBVERT_GOV:
00091             case STAGE_RECON_GROUND:
00092             case STAGE_SPREAD_XVI:
00093             case STAGE_HARVEST:
00094                 happinessFactor = HAPPINESS_ALIEN_MISSION_LOSS;
00095                 break;
00096             default:
00097                 /* mission is not active on earth or does not have any influence
00098                  * on the nation happiness, skip this mission */
00099                 continue;
00100             }
00101 
00102             NAT_SetHappiness(nation, nation->stats[0].happiness + happinessFactor);
00103             Com_DPrintf(DEBUG_CLIENT, "Happiness of nation %s decreased: %.02f\n", nation->name, nation->stats[0].happiness);
00104         }
00105     }
00106 }
00107 
00115 int NAT_GetFunding (const nation_t* const nation, int month)
00116 {
00117     return nation->maxFunding * nation->stats[month].happiness;
00118 }
00119 
00126 const char* NAT_GetHappinessString (const nation_t* nation)
00127 {
00128     if (nation->stats[0].happiness < 0.015)
00129         return _("Giving up");
00130     else if (nation->stats[0].happiness < 0.025)
00131         return _("Furious");
00132     else if (nation->stats[0].happiness < 0.04)
00133         return _("Angry");
00134     else if (nation->stats[0].happiness < 0.06)
00135         return _("Mad");
00136     else if (nation->stats[0].happiness < 0.10)
00137         return _("Upset");
00138     else if (nation->stats[0].happiness < 0.20)
00139         return _("Tolerant");
00140     else if (nation->stats[0].happiness < 0.30)
00141         return _("Neutral");
00142     else if (nation->stats[0].happiness < 0.50)
00143         return _("Content");
00144     else if (nation->stats[0].happiness < 0.70)
00145         return _("Pleased");
00146     else if (nation->stats[0].happiness < 0.95)
00147         return _("Happy");
00148     else
00149         return _("Exuberant");
00150 }
00151 
00157 void NAT_SetHappiness (nation_t *nation, const float happiness)
00158 {
00159     const char *oldString = NAT_GetHappinessString(nation);
00160     const char *newString;
00161     const float oldHappiness = nation->stats[0].happiness;
00162     const float middleHappiness = (ccs.curCampaign->minhappiness + 1.0) / 2;
00163     notify_t notifyType = NT_NUM_NOTIFYTYPE;
00164 
00165     nation->stats[0].happiness = happiness;
00166     if (nation->stats[0].happiness < 0.0f)
00167         nation->stats[0].happiness = 0.0f;
00168     else if (nation->stats[0].happiness > 1.0f)
00169         nation->stats[0].happiness = 1.0f;
00170 
00171     newString = NAT_GetHappinessString(nation);
00172 
00173     if (oldString != newString) {
00174         Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer),
00175             _("Nation %s changed happiness from %s to %s"), _(nation->name), oldString, newString);
00176         notifyType = NT_HAPPINESS_CHANGED;
00177     } else if (oldHappiness > middleHappiness && happiness < middleHappiness) {
00178         Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer),
00179             _("Nation %s changed happiness to %s"), _(nation->name), newString);
00180         notifyType = NT_HAPPINESS_PLEASED;
00181     } else if (happiness < ccs.curCampaign->minhappiness && oldHappiness > ccs.curCampaign->minhappiness) {
00182         Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), 
00183             _("Happiness of nation %s is %s and less than minimal happiness allowed to the campaign"), _(nation->name), newString);
00184         notifyType = NT_HAPPINESS_MIN;
00185     } else {
00186         return;
00187     }
00188 
00189     MSO_CheckAddNewMessage(notifyType, _("Nation changed happiness"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
00190 }
00191 
00196 qboolean NAT_SaveXML (mxml_node_t *p)
00197 {
00198     int i;
00199     mxml_node_t *n = mxml_AddNode(p, SAVE_NATION_NATIONS);
00200 
00201     for (i = 0; i < ccs.numNations; i++) {
00202         nation_t *nation = NAT_GetNationByIDX(i);
00203         mxml_node_t *s;
00204         int j;
00205 
00206         if (!nation)
00207             continue;
00208 
00209         s = mxml_AddNode(n, SAVE_NATION_NATION);
00210         mxml_AddString(s, SAVE_NATION_ID, nation->id);
00211         for (j = 0; j < MONTHS_PER_YEAR; j++) {
00212             mxml_node_t *ss;
00213 
00214             if (!nation->stats[j].inuse)
00215                 continue;
00216 
00217             ss = mxml_AddNode(s, SAVE_NATION_MONTH);
00218             mxml_AddInt(ss, SAVE_NATION_MONTH_IDX, j);
00219             mxml_AddFloat(ss, SAVE_NATION_HAPPINESS, ccs.nations[i].stats[j].happiness);
00220             mxml_AddInt(ss, SAVE_NATION_XVI, ccs.nations[i].stats[j].xviInfection);
00221         }
00222     }
00223     return qtrue;
00224 }
00225 
00230 qboolean NAT_LoadXML (mxml_node_t * p)
00231 {
00232     mxml_node_t *n;
00233     mxml_node_t *s;
00234 
00235     n = mxml_GetNode(p, SAVE_NATION_NATIONS);
00236     if (!n)
00237         return qfalse;
00238 
00239     /* nations loop */
00240     for (s = mxml_GetNode(n, SAVE_NATION_NATION); s; s = mxml_GetNextNode(s, n, SAVE_NATION_NATION)) {
00241         mxml_node_t *ss;
00242         nation_t *nation = NAT_GetNationByID(mxml_GetString(s, SAVE_NATION_ID));
00243 
00244         if (!nation)
00245             return qfalse;
00246 
00247         /* month loop */
00248         for (ss = mxml_GetNode(s, SAVE_NATION_MONTH); ss; ss = mxml_GetNextNode(ss, s, SAVE_NATION_MONTH)) {
00249             int monthIDX = mxml_GetInt(ss, SAVE_NATION_MONTH_IDX, MONTHS_PER_YEAR);
00250 
00251             if (monthIDX < 0 || monthIDX >= MONTHS_PER_YEAR)
00252                 return qfalse;
00253 
00254             nation->stats[monthIDX].inuse = qtrue;
00255             nation->stats[monthIDX].happiness = mxml_GetFloat(ss, SAVE_NATION_HAPPINESS, 0.0);
00256             nation->stats[monthIDX].xviInfection = mxml_GetInt(ss, SAVE_NATION_XVI, 0);
00257         }
00258     }
00259     return qtrue;
00260 }
00261 
00262 /*==========================================
00263 Parsing
00264 ==========================================*/
00265 
00266 static const value_t nation_vals[] = {
00267     {"name", V_TRANSLATION_STRING, offsetof(nation_t, name), 0},
00268     {"pos", V_POS, offsetof(nation_t, pos), MEMBER_SIZEOF(nation_t, pos)},
00269     {"color", V_COLOR, offsetof(nation_t, color), MEMBER_SIZEOF(nation_t, color)},
00270     {"funding", V_INT, offsetof(nation_t, maxFunding), MEMBER_SIZEOF(nation_t, maxFunding)},
00271     {"happiness", V_FLOAT, offsetof(nation_t, stats[0].happiness), MEMBER_SIZEOF(nation_t, stats[0].happiness)},
00272     {"soldiers", V_INT, offsetof(nation_t, maxSoldiers), MEMBER_SIZEOF(nation_t, maxSoldiers)},
00273     {"scientists", V_INT, offsetof(nation_t, maxScientists), MEMBER_SIZEOF(nation_t, maxScientists)},
00274 
00275     {NULL, 0, 0, 0}
00276 };
00277 
00286 void CL_ParseNations (const char *name, const char **text)
00287 {
00288     const char *errhead = "CL_ParseNations: unexpected end of file (nation ";
00289     nation_t *nation;
00290     const value_t *vp;
00291     const char *token;
00292     int i;
00293 
00294     if (ccs.numNations >= MAX_NATIONS) {
00295         Com_Printf("CL_ParseNations: nation number exceeding maximum number of nations: %i\n", MAX_NATIONS);
00296         return;
00297     }
00298 
00299     /* search for nations with same name */
00300     for (i = 0; i < ccs.numNations; i++)
00301         if (!strncmp(name, ccs.nations[i].id, sizeof(ccs.nations[i].id)))
00302             break;
00303     if (i < ccs.numNations) {
00304         Com_Printf("CL_ParseNations: nation def \"%s\" with same name found, second ignored\n", name);
00305         return;
00306     }
00307 
00308     /* initialize the nation */
00309     nation = &ccs.nations[ccs.numNations];
00310     memset(nation, 0, sizeof(*nation));
00311     nation->idx = ccs.numNations;
00312     ccs.numNations++;
00313 
00314     Com_DPrintf(DEBUG_CLIENT, "...found nation %s\n", name);
00315     nation->id = Mem_PoolStrDup(name, cp_campaignPool, 0);
00316 
00317     nation->stats[0].inuse = qtrue;
00318 
00319     /* get it's body */
00320     token = Com_Parse(text);
00321 
00322     if (!*text || *token != '{') {
00323         Com_Printf("CL_ParseNations: nation def \"%s\" without body ignored\n", name);
00324         ccs.numNations--;
00325         return;
00326     }
00327 
00328     do {
00329         token = Com_EParse(text, errhead, name);
00330         if (!*text)
00331             break;
00332         if (*token == '}')
00333             break;
00334 
00335         /* check for some standard values */
00336         for (vp = nation_vals; vp->string; vp++)
00337             if (!strcmp(token, vp->string)) {
00338                 /* found a definition */
00339                 token = Com_EParse(text, errhead, name);
00340                 if (!*text)
00341                     return;
00342 
00343                 switch (vp->type) {
00344                 case V_TRANSLATION_STRING:
00345                     token++;
00346                 case V_CLIENT_HUNK_STRING:
00347                     Mem_PoolStrDupTo(token, (char**) ((char*)nation + (int)vp->ofs), cp_campaignPool, 0);
00348                     break;
00349                 default:
00350                     if (Com_EParseValue(nation, token, vp->type, vp->ofs, vp->size) == -1)
00351                         Com_Printf("CL_ParseNations: Wrong size for value %s\n", vp->string);
00352                     break;
00353                 }
00354                 break;
00355             }
00356 
00357         if (!vp->string) {
00358             Com_Printf("CL_ParseNations: unknown token \"%s\" ignored (nation %s)\n", token, name);
00359             Com_EParse(text, errhead, name);
00360         }
00361     } while (*text);
00362 }
00363 
00364 static const value_t city_vals[] = {
00365     {"name", V_TRANSLATION_STRING, offsetof(city_t, name), 0},
00366     {"pos", V_POS, offsetof(city_t, pos), MEMBER_SIZEOF(city_t, pos)},
00367 
00368     {NULL, 0, 0, 0}
00369 };
00370 
00379 void CL_ParseCities (const char *name, const char **text)
00380 {
00381     const char *errhead = "CL_ParseCities: unexpected end of file (nation ";
00382     city_t newCity;
00383     linkedList_t *cities;
00384     const value_t *vp;
00385     const char *token;
00386 
00387     /* search for cities with same name */
00388     for (cities = ccs.cities; cities != NULL; cities = cities->next) {
00389         const city_t *cty = (city_t*) cities->data;
00390 
00391         assert(cty);
00392         if (!strcmp(name, cty->id))
00393             break;
00394     }
00395     if (cities != NULL) {
00396         Com_Printf("CL_ParseCities: city def \"%s\" with same name found, second ignored\n", name);
00397         return;
00398     }
00399 
00400     /* initialize the nation */
00401     memset(&newCity, 0, sizeof(newCity));
00402     newCity.idx = ccs.numCities;
00403     ccs.numCities++;
00404 
00405     Com_DPrintf(DEBUG_CLIENT, "...found city %s\n", name);
00406     newCity.id = Mem_PoolStrDup(name, cp_campaignPool, 0);
00407 
00408     /* get it's body */
00409     token = Com_Parse(text);
00410 
00411     if (!*text || *token != '{') {
00412         Com_Printf("CL_ParseCities: city def \"%s\" without body ignored\n", name);
00413         ccs.numCities--;
00414         return;
00415     }
00416 
00417     do {
00418         token = Com_EParse(text, errhead, name);
00419         if (!*text)
00420             break;
00421         if (*token == '}')
00422             break;
00423 
00424         /* check for some standard values */
00425         for (vp = city_vals; vp->string; vp++)
00426             if (!strcmp(token, vp->string)) {
00427                 /* found a definition */
00428                 token = Com_EParse(text, errhead, name);
00429                 if (!*text)
00430                     return;
00431 
00432                 switch (vp->type) {
00433                 case V_TRANSLATION_STRING:
00434                     token++;
00435                 case V_CLIENT_HUNK_STRING:
00436                     Mem_PoolStrDupTo(token, (char**) ((char*)&newCity + (int)vp->ofs), cp_campaignPool, 0);
00437                     break;
00438                 default:
00439                     if (Com_EParseValue(&newCity, token, vp->type, vp->ofs, vp->size) == -1)
00440                         Com_Printf("CL_ParseCities: Wrong size for value %s\n", vp->string);
00441                     break;
00442                 }
00443                 break;
00444             }
00445 
00446         if (!vp->string) {
00447             Com_Printf("CL_ParseCities: unknown token \"%s\" ignored (nation %s)\n", token, name);
00448             Com_EParse(text, errhead, name);
00449         }
00450     } while (*text);
00451 
00452     /* Add city to the list */
00453     LIST_Add(&ccs.cities, (byte*) &newCity, sizeof(newCity));
00454 }
00455 
00460 qboolean NAT_ScriptSanityCheck (void)
00461 {
00462     int i;
00463     int error = 0;
00464     linkedList_t *cities;
00465 
00466     /* Check if there is at least one map fitting city parameter for terror mission */
00467     for (cities = ccs.cities; cities != NULL; cities = cities->next) {
00468         int mapIdx;
00469         city_t *city = (city_t*) cities->data;
00470         const vec2_t pos = {city->pos[0], city->pos[1]};
00471         qboolean cityCanBeUsed = qfalse;
00472         qboolean parametersFit = qfalse;
00473         ufoType_t ufoTypes[UFO_MAX];
00474         int numTypes;
00475 
00476         if (!city->name) {
00477             error++;
00478             Com_Printf("...... city '%s' has no name\n", city->id);
00479         }
00480 
00481         numTypes = CP_TerrorMissionAvailableUFOs(NULL, ufoTypes);
00482 
00483         for (mapIdx = 0; mapIdx < cls.numMDs; mapIdx++) {
00484             const mapDef_t const *md = Com_GetMapDefByIDX(mapIdx);
00485 
00486             if (md->storyRelated)
00487                 continue;
00488 
00489             if (MAP_PositionFitsTCPNTypes(pos, md->terrains, md->cultures, md->populations, NULL)) {
00490                 /* this map fits city parameter, check if we have some terror mission UFOs available for this map */
00491 
00492                 parametersFit = qtrue;
00493 
00494                 /* no UFO on this map (LIST_ContainsString doesn't like empty string) */
00495                 if (!md->ufos) {
00496                     continue;
00497                 }
00498 
00499                 /* loop must be backward, as we remove items */
00500                 for (i = numTypes - 1 ; i >= 0; i--) {
00501                     if (LIST_ContainsString(md->ufos, Com_UFOTypeToShortName(ufoTypes[i]))) {
00502                         REMOVE_ELEM(ufoTypes, i, numTypes);
00503                     }
00504                 }
00505             }
00506             if (numTypes == 0) {
00507                 cityCanBeUsed = qtrue;
00508                 break;
00509             }
00510         }
00511 
00512         if (!cityCanBeUsed) {
00513             error++;
00514             Com_Printf("...... city '%s' can't be used in game: it has no map fitting parameters\n", city->id);
00515             if (parametersFit) {
00516                 Com_Printf("      (No map fitting");
00517                 for (i = 0 ; i < numTypes; i++)
00518                     Com_Printf(" %s", Com_UFOTypeToShortName(ufoTypes[i]));
00519                 Com_Printf(")\n");
00520             }
00521             MAP_PrintParameterStringByPos(pos);
00522         }
00523     }
00524 
00525     return !error;
00526 }
00527 
00528 /*=====================================
00529 Menu functions
00530 =====================================*/
00531 
00532 
00533 static void CP_NationStatsClick_f (void)
00534 {
00535     int num;
00536 
00537     if (Cmd_Argc() < 2) {
00538         Com_Printf("Usage: %s <num>\n", Cmd_Argv(0));
00539         return;
00540     }
00541 
00542     /* Which entry in the list? */
00543     num = atoi(Cmd_Argv(1));
00544     if (num < 0 || num >= ccs.numNations)
00545         return;
00546 
00547     UI_PushWindow("nations", NULL);
00548     Cbuf_AddText(va("nation_select %i;", num));
00549 }
00550 
00552 static screenPoint_t fundingPts[MAX_NATIONS][MONTHS_PER_YEAR];
00553 static int usedFundPtslist = 0;
00555 static screenPoint_t colorLinePts[MAX_NATIONS][2];
00556 static int usedColPtslists = 0;
00557 
00558 static const vec4_t graphColors[MAX_NATIONS] = {
00559     {1.0, 0.5, 0.5, 1.0},
00560     {0.5, 1.0, 0.5, 1.0},
00561     {0.5, 0.5, 1.0, 1.0},
00562     {1.0, 0.0, 0.0, 1.0},
00563     {0.0, 1.0, 0.0, 1.0},
00564     {0.0, 0.0, 1.0, 1.0},
00565     {1.0, 1.0, 0.0, 1.0},
00566     {0.0, 1.0, 1.0, 1.0}
00567 };
00568 static const vec4_t graphColorSelected = {1, 1, 1, 1};
00569 
00577 static int CL_NationsMaxFunding (void)
00578 {
00579     int m, n;
00580     int max = 0;
00581 
00582     for (n = 0; n < ccs.numNations; n++) {
00583         const nation_t *nation = &ccs.nations[n];
00584         for (m = 0; m < MONTHS_PER_YEAR; m++) {
00585             if (nation->stats[m].inuse) {
00586                 const int funding = NAT_GetFunding(nation, m);
00587                 if (max < funding)
00588                     max = funding;
00589             } else {
00590                 /* Abort this months-loops */
00591                 break;
00592             }
00593         }
00594     }
00595     return max;
00596 }
00597 
00598 static int selectedNation = 0;
00599 
00600 static lineStrip_t fundingLineStrip[MAX_NATIONS];
00601 
00611 static void CL_NationDrawStats (const nation_t *nation, uiNode_t *node, lineStrip_t *funding, int maxFunding, int color)
00612 {
00613     int width, height, dx;
00614     int m;
00615     int minFunding = 0;
00616     int ptsNumber = 0;
00617     float dy;
00618 
00619     if (!nation || !node)
00620         return;
00621 
00623     width   = (int)node->size[0];
00624     height  = (int)node->size[1];
00625     dx = (int)(width / MONTHS_PER_YEAR);
00626 
00627     if (minFunding != maxFunding)
00628         dy = (float) height / (maxFunding - minFunding);
00629     else
00630         dy = 0;
00631 
00632     /* Generate pointlist. */
00634     for (m = 0; m < MONTHS_PER_YEAR; m++) {
00635         if (nation->stats[m].inuse) {
00636             const int fund = NAT_GetFunding(nation, m);
00637             fundingPts[usedFundPtslist][m].x = (m * dx);
00638             fundingPts[usedFundPtslist][m].y = height - dy * (fund - minFunding);
00639             ptsNumber++;
00640         } else {
00641             break;
00642         }
00643     }
00644 
00645     /* Guarantee displayable data even for only one month */
00646     if (ptsNumber == 1) {
00647         /* Set the second point half the distance to the next month to the right - small horizontal line. */
00648         fundingPts[usedFundPtslist][1].x = fundingPts[usedFundPtslist][0].x + (int)(0.5 * width / MONTHS_PER_YEAR);
00649         fundingPts[usedFundPtslist][1].y = fundingPts[usedFundPtslist][0].y;
00650         ptsNumber++;
00651     }
00652 
00653     /* Link graph to node */
00654     funding->pointList = (int*)fundingPts[usedFundPtslist];
00655     funding->numPoints = ptsNumber;
00656     if (color < 0) {
00657         Cvar_Set("mn_nat_symbol", va("nations/%s", ccs.nations[selectedNation].id));
00658         Vector4Copy(graphColorSelected, funding->color);
00659     } else {
00660         Vector4Copy(graphColors[color], funding->color);
00661     }
00662 
00663     usedFundPtslist++;
00664 }
00665 
00666 static lineStrip_t colorLineStrip[MAX_NATIONS];
00667 
00672 static void CL_NationStatsUpdate_f (void)
00673 {
00674     int i;
00675     uiNode_t *colorNode;
00676     uiNode_t *graphNode;
00677     int dy = 10;
00678 
00679     usedColPtslists = 0;
00680 
00681     colorNode = UI_GetNodeByPath("nations.nation_graph_colors");
00682     if (colorNode) {
00683         dy = (int)(colorNode->size[1] / MAX_NATIONS);
00684     }
00685 
00686     for (i = 0; i < ccs.numNations; i++) {
00687         nation_t *nation = &ccs.nations[i];
00688         lineStrip_t *color = &colorLineStrip[i];
00689         const int funding = NAT_GetFunding(nation, 0);
00690 
00691         memset(color, 0, sizeof(*color));
00692 
00693         if (i > 0)
00694             colorLineStrip[i - 1].next = color;
00695 
00696         if (selectedNation == i) {
00697             UI_ExecuteConfunc("nation_marksel %i", i);
00698         } else {
00699             UI_ExecuteConfunc("nation_markdesel %i", i);
00700         }
00701         Cvar_Set(va("mn_nat_name%i",i), _(nation->name));
00702         Cvar_Set(va("mn_nat_fund%i",i), va("%i", funding));
00703 
00704         if (colorNode) {
00705             colorLinePts[usedColPtslists][0].x = 0;
00706             colorLinePts[usedColPtslists][0].y = (int)colorNode->size[1] - (int)colorNode->size[1] + dy * i;
00707             colorLinePts[usedColPtslists][1].x = (int)colorNode->size[0];
00708             colorLinePts[usedColPtslists][1].y = colorLinePts[usedColPtslists][0].y;
00709 
00710             color->pointList = (int*)colorLinePts[usedColPtslists];
00711             color->numPoints = 2;
00712 
00713             if (i == selectedNation) {
00714                 Vector4Copy(graphColorSelected, color->color);
00715             } else {
00716                 Vector4Copy(graphColors[i], color->color);
00717             }
00718 
00719             usedColPtslists++;
00720         }
00721     }
00722 
00723     UI_RegisterLineStrip(LINESTRIP_COLOR, &colorLineStrip[0]);
00724 
00725     /* Hide unused nation-entries. */
00726     for (i = ccs.numNations; i < MAX_NATIONS; i++) {
00727         UI_ExecuteConfunc("nation_hide %i", i);
00728     }
00729 
00732     /* Display graph of nations-values so far. */
00733     graphNode = UI_GetNodeByPath("nations.nation_graph_funding");
00734     if (graphNode) {
00735         const int maxFunding = CL_NationsMaxFunding();
00736         usedFundPtslist = 0;
00737         for (i = 0; i < ccs.numNations; i++) {
00738             nation_t *nation = &ccs.nations[i];
00739             lineStrip_t *funding = &fundingLineStrip[i];
00740 
00741             /* init the structure */
00742             memset(funding, 0, sizeof(funding));
00743 
00744             if (i > 0)
00745                 fundingLineStrip[i - 1].next = funding;
00746 
00747             if (i == selectedNation) {
00748                 CL_NationDrawStats(nation, graphNode, funding, maxFunding, -1);
00749             } else {
00750                 CL_NationDrawStats(nation, graphNode, funding, maxFunding, i);
00751             }
00752         }
00753 
00754         UI_RegisterLineStrip(LINESTRIP_FUNDING, &fundingLineStrip[0]);
00755     }
00756 }
00757 
00761 static void CL_NationSelect_f (void)
00762 {
00763     int nat;
00764 
00765     if (Cmd_Argc() < 2) {
00766         Com_Printf("Usage: %s <nat_idx>\n", Cmd_Argv(0));
00767         return;
00768     }
00769 
00770     nat = atoi(Cmd_Argv(1));
00771     if (nat < 0 || nat >= ccs.numNations) {
00772         Com_Printf("Invalid nation index: %is\n",nat);
00773         return;
00774     }
00775 
00776     selectedNation = nat;
00777     CL_NationStatsUpdate_f();
00778 }
00779 
00780 #ifdef DEBUG
00781 
00785 static void NAT_ListCities_f (void)
00786 {
00787     linkedList_t *cities;
00788 
00789     for (cities = ccs.cities; cities != NULL; cities =cities->next) {
00790         const city_t const *city = (city_t*) cities->data;
00791 
00792         assert(city);
00793         Com_Printf("City '%s' -- position (%0.1f, %0.1f)\n", city->id, city->pos[0], city->pos[1]);
00794         MAP_PrintParameterStringByPos(city->pos);
00795     }
00796 }
00797 
00802 static void NAT_NationList_f (void)
00803 {
00804     int i;
00805     for (i = 0; i < ccs.numNations; i++) {
00806         Com_Printf("Nation ID: %s\n", ccs.nations[i].id);
00807         Com_Printf("...max-funding %i c\n", ccs.nations[i].maxFunding);
00808         Com_Printf("...happiness %0.2f\n", ccs.nations[i].stats[0].happiness);
00809         Com_Printf("...xviInfection %i\n", ccs.nations[i].stats[0].xviInfection);
00810         Com_Printf("...max-soldiers %i\n", ccs.nations[i].maxSoldiers);
00811         Com_Printf("...max-scientists %i\n", ccs.nations[i].maxScientists);
00812         Com_Printf("...color r:%.2f g:%.2f b:%.2f a:%.2f\n", ccs.nations[i].color[0], ccs.nations[i].color[1], ccs.nations[i].color[2], ccs.nations[i].color[3]);
00813         Com_Printf("...pos x:%.0f y:%.0f\n", ccs.nations[i].pos[0], ccs.nations[i].pos[1]);
00814     }
00815 }
00816 #endif
00817 
00818 void NAT_InitStartup (void)
00819 {
00820     Cmd_AddCommand("nation_stats_click", CP_NationStatsClick_f, NULL);
00821     Cmd_AddCommand("nation_update", CL_NationStatsUpdate_f, "Shows the current nation list + statistics.");
00822     Cmd_AddCommand("nation_select", CL_NationSelect_f, "Select nation and display all relevant information for it.");
00823 #ifdef DEBUG
00824     Cmd_AddCommand("debug_listcities", NAT_ListCities_f, "Debug function to list all cities in game.");
00825     Cmd_AddCommand("debug_listnations", NAT_NationList_f, "List all nations on the game console");
00826 #endif
00827 }
00828 

Generated by  doxygen 1.6.2