00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "client.h"
00027 #include "cl_game.h"
00028 #include "cl_team.h"
00029 #include "campaign/cp_campaign.h"
00030 #include "campaign/cp_missions.h"
00031 #include "campaign/cp_mission_triggers.h"
00032 #include "campaign/cp_team.h"
00033 #include "ui/ui_main.h"
00034 #include "ui/ui_nodes.h"
00035 #include "ui/node/ui_node_model.h"
00036 #include "ui/node/ui_node_text.h"
00037
00042 static void GAME_CP_MissionAutoGo_f (void)
00043 {
00044 if (!ccs.selectedMission) {
00045 Com_DPrintf(DEBUG_CLIENT, "GAME_CP_MissionAutoGo_f: No update after automission\n");
00046 return;
00047 }
00048
00049 if (!ccs.missionAircraft) {
00050 Com_Printf("GAME_CP_MissionAutoGo_f: No aircraft at target pos\n");
00051 return;
00052 }
00053
00054
00055 CL_GameAutoGo(ccs.selectedMission);
00056 }
00057
00065 static void GAME_CP_MissionAutoCheck_f (void)
00066 {
00067 if (!ccs.selectedMission || !ccs.interceptAircraft) {
00068 Com_DPrintf(DEBUG_CLIENT, "GAME_CP_MissionAutoCheck_f: No update after automission\n");
00069 return;
00070 }
00071
00072 if (ccs.selectedMission->mapDef->storyRelated) {
00073 Com_DPrintf(DEBUG_CLIENT, "GAME_CP_MissionAutoCheck_f: story related - auto mission is disabled\n");
00074 Cvar_Set("cp_mission_autogo_available", "0");
00075 } else {
00076 Com_DPrintf(DEBUG_CLIENT, "GAME_CP_MissionAutoCheck_f: auto mission is enabled\n");
00077 Cvar_Set("cp_mission_autogo_available", "1");
00078 }
00079 }
00080
00086 static void GAME_CP_Results_f (void)
00087 {
00088
00089 if (!ccs.selectedMission)
00090 return;
00091
00092
00093 if (Cvar_GetInteger("cp_mission_tryagain")) {
00094
00095 CP_StartSelectedMission();
00096 return;
00097 }
00098
00099 if (Cmd_Argc() < 2) {
00100 Com_Printf("Usage: %s <won:true|false>\n", Cmd_Argv(0));
00101 return;
00102 }
00103
00104 CP_MissionEnd(ccs.selectedMission, Com_ParseBoolean(Cmd_Argv(1)));
00105 }
00106
00111 static inline const char* CP_ToDifficultyName (int difficulty)
00112 {
00113 switch (difficulty) {
00114 case -4:
00115 return _("Chicken-hearted");
00116 case -3:
00117 return _("Very Easy");
00118 case -2:
00119 case -1:
00120 return _("Easy");
00121 case 0:
00122 return _("Normal");
00123 case 1:
00124 case 2:
00125 return _("Hard");
00126 case 3:
00127 return _("Very Hard");
00128 case 4:
00129 return _("Insane");
00130 default:
00131 Com_Error(ERR_DROP, "Unknown difficulty id %i", difficulty);
00132 }
00133 }
00134
00135 #define MAXCAMPAIGNTEXT 4096
00136 static char campaignDesc[MAXCAMPAIGNTEXT];
00140 static void GAME_CP_GetCampaigns_f (void)
00141 {
00142 int i;
00143 linkedList_t *campaignList = NULL;
00144
00145 *campaignDesc = '\0';
00146
00147 for (i = 0; i < ccs.numCampaigns; i++) {
00148 const campaign_t *c = &ccs.campaigns[i];
00149 if (c->visible)
00150 LIST_AddString(&campaignList, va("%s", _(c->name)));
00151 }
00152
00153 UI_RegisterText(TEXT_STANDARD, campaignDesc);
00154 UI_RegisterLinkedListText(TEXT_CAMPAIGN_LIST, campaignList);
00155
00156
00157 for (i = 0; i < ccs.numCampaigns; i++) {
00158 const campaign_t *c = &ccs.campaigns[i];
00159 if (!strcmp(c->id, "main")) {
00160 Cmd_ExecuteString(va("campaignlist_click %i", i));
00161 return;
00162 }
00163 }
00164 Cmd_ExecuteString("campaignlist_click 0");
00165 }
00166
00170 static void GAME_CP_CampaignListClick_f (void)
00171 {
00172 int num;
00173 const char *racetype;
00174 uiNode_t *campaignlist;
00175
00176 if (Cmd_Argc() < 2) {
00177 Com_Printf("Usage: %s <campaign list index>\n", Cmd_Argv(0));
00178 return;
00179 }
00180
00181
00182 num = atoi(Cmd_Argv(1));
00183 if (num < 0 || num >= ccs.numCampaigns)
00184 return;
00185
00186
00187 while (!ccs.campaigns[num].visible) {
00188 num++;
00189 if (num >= ccs.numCampaigns)
00190 return;
00191 }
00192
00193 Cvar_Set("cp_campaign", ccs.campaigns[num].id);
00194 if (ccs.campaigns[num].team == TEAM_PHALANX)
00195 racetype = _("Human");
00196 else
00197 racetype = _("Aliens");
00198
00199 Com_sprintf(campaignDesc, sizeof(campaignDesc), _("%s\n\nRace: %s\nRecruits: %i %s, %i %s, %i %s\n"
00200 "Credits: %ic\nDifficulty: %s\n"
00201 "Min. happiness of nations: %i %%\n"
00202 "Max. allowed debts: %ic\n"
00203 "%s\n"), _(ccs.campaigns[num].name), racetype,
00204 ccs.campaigns[num].soldiers, ngettext("soldier", "soldiers", ccs.campaigns[num].soldiers),
00205 ccs.campaigns[num].scientists, ngettext("scientist", "scientists", ccs.campaigns[num].scientists),
00206 ccs.campaigns[num].workers, ngettext("worker", "workers", ccs.campaigns[num].workers),
00207 ccs.campaigns[num].credits, CP_ToDifficultyName(ccs.campaigns[num].difficulty),
00208 (int)(round(ccs.campaigns[num].minhappiness * 100.0f)), ccs.campaigns[num].negativeCreditsUntilLost,
00209 _(ccs.campaigns[num].text));
00210 UI_RegisterText(TEXT_STANDARD, campaignDesc);
00211
00212
00213 campaignlist = UI_GetNodeByPath("campaigns.campaignlist");
00214 UI_TextNodeSelectLine(campaignlist, num);
00215 }
00216
00222 static void GAME_CP_Start_f (void)
00223 {
00224
00225 campaign_t *campaign = CL_GetCampaign(cp_campaign->string);
00226 if (!campaign)
00227 return;
00228
00229 CP_CampaignInit(campaign, qfalse);
00230
00231
00232 Cbuf_AddText("seq_start intro\n");
00233 }
00234
00246 void GAME_CP_Results (struct dbuffer *msg, int winner, int *numSpawned, int *numAlive, int numKilled[][MAX_TEAMS], int numStunned[][MAX_TEAMS])
00247 {
00248 int i, j;
00249 int ownSurvived, ownKilled, ownStunned;
00250 int aliensSurvived, aliensKilled, aliensStunned;
00251 int civiliansSurvived, civiliansKilled, civiliansStunned;
00252
00253 CP_ParseCharacterData(msg);
00254
00255 ownSurvived = ownKilled = ownStunned = 0;
00256 aliensSurvived = aliensKilled = aliensStunned = 0;
00257 civiliansSurvived = civiliansKilled = civiliansStunned = 0;
00258
00259 for (i = 0; i < MAX_TEAMS; i++) {
00260 if (i == cls.team)
00261 ownSurvived = numAlive[i];
00262 else if (i == TEAM_CIVILIAN)
00263 civiliansSurvived = numAlive[i];
00264 else
00265 aliensSurvived += numAlive[i];
00266 for (j = 0; j < MAX_TEAMS; j++)
00267 if (j == cls.team) {
00268 ownKilled += numKilled[i][j];
00269 ownStunned += numStunned[i][j]++;
00270 } else if (j == TEAM_CIVILIAN) {
00271 civiliansKilled += numKilled[i][j];
00272 civiliansStunned += numStunned[i][j]++;
00273 } else {
00274 aliensKilled += numKilled[i][j];
00275 aliensStunned += numStunned[i][j]++;
00276 }
00277 }
00278
00279 if (winner == cls.team) {
00280 ownSurvived += ownStunned;
00281 ownStunned = 0;
00282 } else
00283
00284 aliensStunned = 0;
00285
00286
00287 if (winner == cls.team)
00288 civiliansSurvived += civiliansStunned;
00289 else
00290 civiliansKilled += civiliansStunned;
00291
00292
00293 AII_CollectingItems(ccs.missionAircraft, winner == cls.team);
00294 if (winner == cls.team)
00295
00296 AL_CollectingAliens(ccs.missionAircraft);
00297
00298 ccs.aliensKilled += aliensKilled;
00299
00300 ccs.missionResults.aliensKilled = aliensKilled;
00301 ccs.missionResults.aliensStunned = aliensStunned;
00302 ccs.missionResults.aliensSurvived = aliensSurvived;
00303 ccs.missionResults.ownKilled = ownKilled - numKilled[cls.team][cls.team] - numKilled[TEAM_CIVILIAN][cls.team];
00304 ccs.missionResults.ownStunned = ownStunned;
00305 ccs.missionResults.ownKilledFriendlyFire = numKilled[cls.team][cls.team] + numKilled[TEAM_CIVILIAN][cls.team];
00306 ccs.missionResults.ownSurvived = ownSurvived;
00307 ccs.missionResults.civiliansKilled = civiliansKilled;
00308 ccs.missionResults.civiliansKilledFriendlyFire = numKilled[cls.team][TEAM_CIVILIAN] + numKilled[TEAM_CIVILIAN][TEAM_CIVILIAN];
00309 ccs.missionResults.civiliansSurvived = civiliansSurvived;
00310
00311 CP_InitMissionResults(winner == cls.team);
00312
00313 UI_InitStack("geoscape", "campaign_main", qtrue, qtrue);
00314
00315 CP_ExecuteMissionTrigger(ccs.selectedMission, winner == cls.team);
00316
00317 if (winner == cls.team) {
00318 UI_PushWindow("won", NULL);
00319 } else
00320 UI_PushWindow("lost", NULL);
00321
00322 CL_Disconnect();
00323 SV_Shutdown("Mission end", qfalse);
00324 }
00325
00326 qboolean GAME_CP_Spawn (void)
00327 {
00328 aircraft_t *aircraft = ccs.missionAircraft;
00329 base_t *base;
00330 linkedList_t* l;
00331
00332 if (!aircraft)
00333 return qfalse;
00334
00335
00336 for (l = aircraft->acTeam; l != NULL; l = l->next) {
00337 employee_t *employee = (employee_t *)l->data;
00338 cl.chrList.chr[cl.chrList.num] = &employee->chr;
00339 cl.chrList.num++;
00340 }
00341
00342 base = aircraft->homebase;
00343
00344
00345 CL_CleanTempInventory(base);
00346
00347
00348 UI_InitStack(mn_hud->string, NULL, qfalse, qtrue);
00349
00350 return qtrue;
00351 }
00352
00353 const mapDef_t* GAME_CP_MapInfo (int step)
00354 {
00355 return Com_GetMapDefByIDX(cls.currentSelectedMap);
00356 }
00357
00358 qboolean GAME_CP_ItemIsUseable (const objDef_t *od)
00359 {
00360 const technology_t *tech = RS_GetTechForItem(od);
00361 return RS_IsResearched_ptr(tech);
00362 }
00363
00364 int GAME_CP_GetTeam (void)
00365 {
00366 assert(ccs.curCampaign);
00367 return ccs.curCampaign->team;
00368 }
00369
00375 qboolean GAME_CP_TeamIsKnown (const teamDef_t *teamDef)
00376 {
00377 if (!CHRSH_IsTeamDefAlien(teamDef))
00378 return qtrue;
00379
00380 if (!ccs.teamDefTechs[teamDef->idx])
00381 Com_Error(ERR_DROP, "Could not find tech for teamdef '%s'", teamDef->id);
00382
00383 return RS_IsResearched_ptr(ccs.teamDefTechs[teamDef->idx]);
00384 }
00385
00386 void GAME_CP_Drop (void)
00387 {
00389 UI_InitStack("geoscape", "campaign_main", qtrue, qtrue);
00390
00391 SV_Shutdown("Mission end", qfalse);
00392 CL_Disconnect();
00393 }
00394
00395 void GAME_CP_Frame (void)
00396 {
00397
00398 if (cls.keyDest == key_console)
00399 return;
00400
00401
00402 CL_CampaignRun();
00403 }
00404
00413 const char* GAME_CP_GetModelForItem (const objDef_t *od)
00414 {
00415 const technology_t *tech = RS_GetTechForItem(od);
00416 if (tech->mdl) {
00417
00418
00419 return tech->mdl;
00420 }
00421 return NULL;
00422 }
00423
00428 void GAME_CP_InitializeBattlescape (const chrList_t *team)
00429 {
00430 int i;
00431 struct dbuffer *msg = new_dbuffer();
00432
00433 NET_WriteByte(msg, clc_initactorstates);
00434 NET_WriteByte(msg, team->num);
00435
00436 for (i = 0; i < team->num; i++) {
00437 const character_t *chr = team->chr[i];
00438 NET_WriteShort(msg, chr->ucn);
00439 NET_WriteShort(msg, chr->state);
00440 }
00441
00442 NET_WriteMsg(cls.netStream, msg);
00443 }
00444
00445 equipDef_t *GAME_CP_GetEquipmentDefinition (void)
00446 {
00447 return &ccs.eMission;
00448 }
00449
00450 void GAME_CP_CharacterCvars (const character_t *chr)
00451 {
00452
00453 if (chr->score.rank >= 0) {
00454 char buf[MAX_VAR];
00455 const rank_t *rank = CL_GetRankByIdx(chr->score.rank);
00456 Com_sprintf(buf, sizeof(buf), _("Rank: %s"), _(rank->name));
00457 Cvar_Set("mn_chrrank", buf);
00458 Cvar_Set("mn_chrrank_img", rank->image);
00459 } else {
00460 Cvar_Set("mn_chrrank_img", "");
00461 Cvar_Set("mn_chrrank", "");
00462 }
00463
00464 Cvar_Set("mn_chrmis", va("%i", chr->score.assignedMissions));
00465 Cvar_Set("mn_chrkillalien", va("%i", chr->score.kills[KILLED_ENEMIES]));
00466 Cvar_Set("mn_chrkillcivilian", va("%i", chr->score.kills[KILLED_CIVILIANS]));
00467 Cvar_Set("mn_chrkillteam", va("%i", chr->score.kills[KILLED_TEAM]));
00468 }
00469
00470 void GAME_CP_DisplayItemInfo (uiNode_t *node, const char *string)
00471 {
00472 const aircraft_t *aircraft = AIR_GetAircraftSilent(string);
00473 if (aircraft) {
00474 assert(aircraft->tech);
00475 UI_DrawModelNode(node, aircraft->tech->mdl);
00476 } else {
00477 const technology_t *tech = RS_GetTechByProvided(string);
00478 if (tech)
00479 UI_DrawModelNode(node, tech->mdl);
00480 else
00481 Com_Printf("UI_ItemNodeDraw: Unknown item: '%s'\n", string);
00482 }
00483 }
00484
00485 void GAME_CP_InitStartup (void)
00486 {
00487 Cmd_AddCommand("cp_results", GAME_CP_Results_f, "Parses and shows the game results");
00488 Cmd_AddCommand("cp_missionauto_check", GAME_CP_MissionAutoCheck_f, "Checks whether this mission can be done automatically");
00489 Cmd_AddCommand("cp_mission_autogo", GAME_CP_MissionAutoGo_f, "Let the current selection mission be done automatically");
00490 Cmd_AddCommand("campaignlist_click", GAME_CP_CampaignListClick_f, NULL);
00491 Cmd_AddCommand("cp_getcampaigns", GAME_CP_GetCampaigns_f, "Fill the campaign list with available campaigns");
00492 Cmd_AddCommand("cp_start", GAME_CP_Start_f, "Start the new campaign");
00493
00494 CP_InitStartup();
00495
00496 cp_campaign = Cvar_Get("cp_campaign", "main", 0, "Which is the current selected campaign id");
00497 cp_start_employees = Cvar_Get("cp_start_employees", "1", CVAR_ARCHIVE, "Start with hired employees");
00498
00499 Cvar_ForceSet("sv_maxclients", "1");
00500 Cvar_ForceSet("sv_ai", "1");
00501
00502
00503 CL_ResetSinglePlayerData();
00504 CL_ReadSinglePlayerData();
00505 }
00506
00507 void GAME_CP_Shutdown (void)
00508 {
00509 Cmd_RemoveCommand("cp_results");
00510 Cmd_RemoveCommand("cp_missionauto_check");
00511 Cmd_RemoveCommand("cp_mission_autogo");
00512 Cmd_RemoveCommand("campaignlist_click");
00513 Cmd_RemoveCommand("cp_getcampaigns");
00514 Cmd_RemoveCommand("cp_start");
00515
00516 CP_CampaignExit();
00517
00518 CL_ResetSinglePlayerData();
00519
00520 SV_Shutdown("Quitting server.", qfalse);
00521 }