mp_team.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.m
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../cl_shared.h"
00027 #include "../cl_game.h"
00028 #include "../cl_inventory.h"
00029 #include "../cl_team.h"
00030 #include "../ui/ui_main.h"
00031 #include "../ui/ui_popup.h"
00032 #include "../ui/node/ui_node_container.h"   
00033 #include "mp_team.h"
00034 #include "save_multiplayer.h"
00035 
00036 #define MPTEAM_SAVE_FILE_VERSION 4
00037 
00038 static inventory_t mp_inventory;
00039 
00040 static qboolean characterActive[MAX_ACTIVETEAM];
00041 
00042 typedef struct mpSaveFileHeader_s {
00043     uint32_t version; 
00044     uint32_t soldiercount; 
00045     char name[32]; 
00046     uint32_t xmlSize; 
00047 } mpSaveFileHeader_t;
00048 
00049 static void MP_UpdateActiveTeamList (void)
00050 {
00051     int i;
00052 
00053     memset(characterActive, 0, sizeof(characterActive));
00054     for (i = 0; i < chrDisplayList.num; i++)
00055         characterActive[i] = qtrue;
00056 
00057     UI_ExecuteConfunc("mp_checkboxes_update %i", chrDisplayList.num);
00058 }
00059 
00060 void MP_AutoTeam_f (void)
00061 {
00062     GAME_MP_AutoTeam();
00063 
00064     MP_UpdateActiveTeamList();
00065 }
00066 
00071 void MP_ToggleActorForTeam_f (void)
00072 {
00073     int num;
00074     int value;
00075 
00076     if (Cmd_Argc() != 3) {
00077         Com_Printf("Usage: %s <num> <value>\n", Cmd_Argv(0));
00078         return;
00079     }
00080 
00081     num = atoi(Cmd_Argv(1));
00082     value = atoi(Cmd_Argv(2));
00083     if (num < 0 || num >= chrDisplayList.num)
00084         value = 0;
00085 
00086     characterActive[num] = (value != 0);
00087 }
00088 
00093 void MP_SaveTeamState_f (void)
00094 {
00095     int i, num;
00096 
00097     num = 0;
00098     for (i = 0; i < chrDisplayList.num; i++) {
00099         chrDisplayList.chr[num]->ucn -= (i -num);
00100         if (characterActive[i]) {
00101             assert(chrDisplayList.chr[i] != NULL);
00102             chrDisplayList.chr[num++] = chrDisplayList.chr[i];
00103         }
00104     }
00105     chrDisplayList.num = num;
00106 }
00107 
00111 void MP_MultiplayerTeamSlotComments_f (void)
00112 {
00113     int i;
00114 
00115     for (i = 0; i < 8; i++) {
00116         /* open file */
00117         qFILE f;
00118 
00119         FS_OpenFile(va("save/team%i.mpt", i), &f, FILE_READ);
00120         if (f.f || f.z) {
00121             mpSaveFileHeader_t header;
00122             const int clen = sizeof(header);
00123             if (FS_Read(&header, clen, &f) != clen) {
00124                 Com_Printf("Warning: Could not read %i bytes from savefile\n", clen);
00125                 FS_CloseFile(&f);
00126                 Cvar_Set(va("mn_slot%i", i), "");
00127                 continue;
00128             }
00129             FS_CloseFile(&f);
00130             if (LittleLong(header.version) == MPTEAM_SAVE_FILE_VERSION) {
00131                 UI_ExecuteConfunc("set_slotname %i %i \"%s\"", i, LittleLong(header.soldiercount), header.name);
00132             } else {
00133                 Cvar_Set(va("mn_slot%i", i), "");
00134             }
00135         } else {
00136             Cvar_Set(va("mn_slot%i", i), "");
00137         }
00138     }
00139 }
00140 
00146 static void MP_SaveTeamMultiplayerInfo (mxml_node_t *p)
00147 {
00148     int i;
00149 
00150     /* header */
00151     Com_DPrintf(DEBUG_CLIENT, "Saving %i teammembers\n", chrDisplayList.num);
00152     for (i = 0; i < chrDisplayList.num; i++) {
00153         const character_t *chr = chrDisplayList.chr[i];
00154         mxml_node_t *n = mxml_AddNode(p, SAVE_MULTIPLAYER_CHARACTER);
00155         CL_SaveCharacterXML(n, chr);
00156     }
00157 }
00158 
00164 static void MP_LoadTeamMultiplayerInfo (mxml_node_t *p)
00165 {
00166     int i;
00167     mxml_node_t *n;
00168     const size_t size = GAME_GetCharacterArraySize();
00169 
00170     GAME_ResetCharacters();
00171     memset(characterActive, 0, sizeof(characterActive));
00172 
00173     /* header */
00174     for (i = 0, n = mxml_GetNode(p, SAVE_MULTIPLAYER_CHARACTER); n && i < size; i++, n = mxml_GetNextNode(n, p, SAVE_MULTIPLAYER_CHARACTER)) {
00175         character_t *chr = GAME_GetCharacter(i);
00176         CL_LoadCharacterXML(n, chr);
00177         assert(i < lengthof(chrDisplayList.chr));
00178         chrDisplayList.chr[i] = chr;
00179     }
00180     chrDisplayList.num = i;
00181 
00182     MP_UpdateActiveTeamList();
00183 
00184     Com_DPrintf(DEBUG_CLIENT, "Loaded %i teammembers\n", chrDisplayList.num);
00185 }
00186 
00192 static qboolean MP_SaveTeamMultiplayer (const char *filename, const char *name)
00193 {
00194     int requiredBufferLength;
00195     byte *buf, *fbuf;
00196     mpSaveFileHeader_t header;
00197     char dummy[2];
00198     int i;
00199     mxml_node_t *topNode, *node, *snode;
00200     equipDef_t *ed = GAME_GetEquipmentDefinition();
00201 
00202     topNode = mxmlNewXML("1.0");
00203     node = mxml_AddNode(topNode, SAVE_MULTIPLAYER_ROOTNODE);
00204     memset(&header, 0, sizeof(header));
00205     header.version = LittleLong(MPTEAM_SAVE_FILE_VERSION);
00206     header.soldiercount = LittleLong(chrDisplayList.num);
00207     Q_strncpyz(header.name, name, sizeof(header.name));
00208 
00209     snode = mxml_AddNode(node, SAVE_MULTIPLAYER_TEAM);
00210     MP_SaveTeamMultiplayerInfo(snode);
00211 
00212     snode = mxml_AddNode(node, SAVE_MULTIPLAYER_EQUIPMENT);
00213     for (i = 0; i < csi.numODs; i++) {
00214         const objDef_t *od = INVSH_GetItemByIDX(i);
00215         if (ed->numItems[od->idx] || ed->numItemsLoose[od->idx]) {
00216             mxml_node_t *ssnode = mxml_AddNode(snode, SAVE_MULTIPLAYER_ITEM);
00217             mxml_AddString(ssnode, SAVE_MULTIPLAYER_ID, od->id);
00218             mxml_AddIntValue(ssnode, SAVE_MULTIPLAYER_NUM, ed->numItems[od->idx]);
00219             mxml_AddIntValue(ssnode, SAVE_MULTIPLAYER_NUMLOOSE, ed->numItemsLoose[od->idx]);
00220         }
00221     }
00222     requiredBufferLength = mxmlSaveString(topNode, dummy, 2, MXML_NO_CALLBACK);
00223     /* required for storing compressed */
00224     header.xmlSize = LittleLong(requiredBufferLength);
00225 
00226     buf = (byte *) Mem_PoolAlloc(sizeof(byte) * requiredBufferLength + 1, cl_genericPool, 0);
00227     if (!buf) {
00228         mxmlDelete(topNode);
00229         Com_Printf("Error: Could not allocate enough memory to save this game\n");
00230         return qfalse;
00231     }
00232     mxmlSaveString(topNode, (char*)buf, requiredBufferLength + 1, MXML_NO_CALLBACK);
00233     mxmlDelete(topNode);
00234 
00235     fbuf = (byte *) Mem_PoolAlloc(requiredBufferLength + 1 + sizeof(header), cl_genericPool, 0);
00236     memcpy(fbuf, &header, sizeof(header));
00237     memcpy(fbuf + sizeof(header), buf, requiredBufferLength + 1);
00238     Mem_Free(buf);
00239 
00240     /* last step - write data */
00241     FS_WriteFile(fbuf, requiredBufferLength + 1 + sizeof(header), filename);
00242     Mem_Free(fbuf);
00243 
00244     return qtrue;
00245 }
00246 
00250 void MP_SaveTeamMultiplayer_f (void)
00251 {
00252     if (!chrDisplayList.num) {
00253         UI_Popup(_("Note"), _("Error saving team. Nothing to save yet."));
00254         return;
00255     } else {
00256         char filename[MAX_OSPATH];
00257         int index;
00258         const char *name;
00259 
00260         if (Cmd_Argc() != 2) {
00261             Com_Printf("Usage: %s <slotindex>\n", Cmd_Argv(0));
00262             return;
00263         }
00264 
00265         index = atoi(Cmd_Argv(1));
00266 
00267         name = Cvar_GetString(va("mn_slot%i", index));
00268         if (name[0] == '\0')
00269             name = _("NewTeam");
00270 
00271         /* save */
00272         Com_sprintf(filename, sizeof(filename), "save/team%i.mpt", index);
00273         if (!MP_SaveTeamMultiplayer(filename, name))
00274             UI_Popup(_("Note"), _("Error saving team. Check free disk space!"));
00275     }
00276 }
00277 
00283 static qboolean MP_LoadTeamMultiplayer (const char *filename)
00284 {
00285     uLongf len;
00286     qFILE f;
00287     byte *cbuf;
00288     int clen;
00289     mxml_node_t *topNode, *node, *snode, *ssnode;
00290     mpSaveFileHeader_t header;
00291     equipDef_t *ed;
00292 
00293     /* open file */
00294     FS_OpenFile(filename, &f, FILE_READ);
00295     if (!f.f && !f.z) {
00296         Com_Printf("Couldn't open file '%s'\n", filename);
00297         return qfalse;
00298     }
00299 
00300     clen = FS_FileLength(&f);
00301     cbuf = (byte *) Mem_PoolAlloc(sizeof(byte) * clen, cl_genericPool, 0);
00302     if (FS_Read(cbuf, clen, &f) != clen) {
00303         Com_Printf("Warning: Could not read %i bytes from savefile\n", clen);
00304         FS_CloseFile(&f);
00305         Mem_Free(cbuf);
00306         return qfalse;
00307     }
00308     FS_CloseFile(&f);
00309 
00310     memcpy(&header, cbuf, sizeof(header));
00311     /* swap all int values if needed */
00312     header.version = LittleLong(header.version);
00313     header.xmlSize = LittleLong(header.xmlSize);
00314     len = header.xmlSize + 1 + sizeof(header);
00315 
00316     if (header.version != MPTEAM_SAVE_FILE_VERSION) {
00317         Com_Printf("Invalid version number\n");
00318         return qfalse;
00319     }
00320 
00321     Com_Printf("Loading multiplayer team (size %d / %i)\n", clen, header.xmlSize);
00322 
00323     topNode = mxmlLoadString(NULL, (char*)(cbuf + sizeof(header)) , mxml_ufo_type_cb);
00324     Mem_Free(cbuf);
00325     if (!topNode) {
00326         Com_Printf("Error: Failure in loading the xml data!");
00327         return qfalse;
00328     }
00329 
00330     node = mxml_GetNode(topNode, SAVE_MULTIPLAYER_ROOTNODE);
00331     if (!node) {
00332         mxmlDelete(topNode);
00333         Com_Printf("Error: Failure in loading the xml data! (node 'multiplayer' not found)\n");
00334         return qfalse;
00335     }
00336     Cvar_Set("mn_teamname", header.name);
00337 
00338     snode = mxml_GetNode(node, SAVE_MULTIPLAYER_TEAM);
00339     if (!snode) {
00340         mxmlDelete(topNode);
00341         Mem_Free(cbuf);
00342         Com_Printf("Error: Failure in loading the xml data! (node 'team' not found)\n");
00343         return qfalse;
00344     }
00345     MP_LoadTeamMultiplayerInfo(snode);
00346 
00347     snode = mxml_GetNode(node, SAVE_MULTIPLAYER_EQUIPMENT);
00348     if (!snode) {
00349         mxmlDelete(topNode);
00350         Mem_Free(cbuf);
00351         Com_Printf("Error: Failure in loading the xml data! (node 'equipment' not found)\n");
00352         return qfalse;
00353     }
00354 
00355     ed = GAME_GetEquipmentDefinition();
00356     for (ssnode = mxml_GetNode(snode, SAVE_MULTIPLAYER_ITEM); ssnode; ssnode = mxml_GetNextNode(ssnode, snode, SAVE_MULTIPLAYER_ITEM)) {
00357         const char *objID = mxml_GetString(ssnode, SAVE_MULTIPLAYER_ID);
00358         const objDef_t *od = INVSH_GetItemByID(objID);
00359 
00360         if (od) {
00361             ed->numItems[od->idx] = mxml_GetInt(snode, SAVE_MULTIPLAYER_NUM, 0);
00362             ed->numItemsLoose[od->idx] = mxml_GetInt(snode, SAVE_MULTIPLAYER_NUMLOOSE, 0);
00363         }
00364     }
00365 
00366     Com_Printf("File '%s' loaded.\n", filename);
00367 
00368     mxmlDelete(topNode);
00369 
00370     return qtrue;
00371 }
00372 
00373 qboolean MP_LoadDefaultTeamMultiplayer (void)
00374 {
00375     return MP_LoadTeamMultiplayer("save/team0.mpt");
00376 }
00377 
00381 void MP_LoadTeamMultiplayer_f (void)
00382 {
00383     char filename[MAX_OSPATH];
00384     int index;
00385 
00386     if (Cmd_Argc() != 2) {
00387         Com_Printf("Usage: %s <slotindex>\n", Cmd_Argv(0));
00388         return;
00389     }
00390 
00391     index = atoi(Cmd_Argv(1));
00392 
00393     /* first try to load the xml file, if this does not succeed, try the old file */
00394     Com_sprintf(filename, sizeof(filename), "save/team%i.mpt", index);
00395     MP_LoadTeamMultiplayer(filename);
00396 }
00397 
00402 static void MP_GetEquipment (void)
00403 {
00404     const equipDef_t *edFromScript;
00405     const char *teamID = Com_ValueToStr(&cl_team->integer, V_TEAM, 0);
00406     char equipmentName[MAX_VAR];
00407     equipDef_t unused;
00408     equipDef_t *ed;
00409 
00410     Com_sprintf(equipmentName, sizeof(equipmentName), "multiplayer_%s", teamID);
00411 
00412     /* search equipment definition */
00413     edFromScript = INV_GetEquipmentDefinitionByID(equipmentName);
00414 
00415     if (chrDisplayList.num > 0)
00416         ui_inventory = &chrDisplayList.chr[0]->i;
00417     else
00418         ui_inventory = NULL;
00419 
00420     ed = GAME_GetEquipmentDefinition();
00421     *ed = *edFromScript;
00422 
00423     /* we don't want to lose anything from ed - so we copy it and screw the copied stuff afterwards */
00424     unused = *edFromScript;
00425     /* manage inventory */
00426     UI_ContainerNodeUpdateEquipment(&mp_inventory, &unused);
00427 }
00428 
00433 void MP_UpdateMenuParameters_f (void)
00434 {
00435     int i;
00436     const size_t size = lengthof(chrDisplayList.chr);
00437 
00438     /* reset description */
00439     Cvar_Set("mn_itemname", "");
00440     Cvar_Set("mn_item", "");
00441     UI_ResetData(TEXT_STANDARD);
00442 
00443     for (i = 0; i < size; i++) {
00444         const char *name;
00445         if (i < chrDisplayList.num)
00446             name = chrDisplayList.chr[i]->name;
00447         else
00448             name = "";
00449         Cvar_Set(va("mn_name%i", i), name);
00450     }
00451 
00452     MP_GetEquipment();
00453 }
00454 
00455 void MP_TeamSelect_f (void)
00456 {
00457     const int old = cl_selected->integer;
00458     int num;
00459 
00460     /* check syntax */
00461     if (Cmd_Argc() < 2) {
00462         Com_Printf("Usage: %s <num>\n", Cmd_Argv(0));
00463         return;
00464     }
00465 
00466     num = atoi(Cmd_Argv(1));
00467     if (num < 0 || num >= chrDisplayList.num)
00468         return;
00469 
00470     UI_ExecuteConfunc("mp_soldier_select %i", num);
00471     UI_ExecuteConfunc("mp_soldier_unselect %i", old);
00472     Cmd_ExecuteString(va("actor_select_equip %i", num));
00473 }

Generated by  doxygen 1.6.2