cl_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 "client.h"
00027 #include "cl_game.h"
00028 #include "cl_team.h"
00029 #include "battlescape/cl_localentity.h"
00030 #include "battlescape/cl_actor.h"
00031 #include "cl_inventory.h"
00032 #include "battlescape/events/e_parse.h"
00033 #include "ui/ui_data.h"
00034 #include "ui/ui_nodes.h"
00035 #include "battlescape/events/e_main.h"
00036 #include "campaign/save/save_character.h"
00037 #include "campaign/save/save_inventory.h"
00038 
00040 chrList_t chrDisplayList;
00041 
00046 customSkin_t* Com_AllocateCustomSkin (void)
00047 {
00048     const int index = cls.numCustomSkins;
00049     customSkin_t *skin;
00050 
00051     if (cls.numCustomSkins >= lengthof(cls.customSkins))
00052         Sys_Error("Com_AllocateCustomSkin: Max customskin hit");
00053 
00054     skin = &cls.customSkins[index];
00055     memset(skin, 0, sizeof(*skin));
00056     skin->idx = cls.numCustomSkins;
00057 
00058     cls.numCustomSkins++;
00059     return skin;
00060 }
00061 
00066 static customSkin_t* Com_GetCustomSkinByIDS (int idx)
00067 {
00068     if (idx >= cls.numCustomSkins)
00069         return NULL;
00070     return &cls.customSkins[idx];
00071 }
00072 
00078 static const char* CL_GetTeamSkinName (int id)
00079 {
00080     customSkin_t *skin = Com_GetCustomSkinByIDS(id);
00081     if (skin == NULL)
00082         Com_Error(ERR_DROP, "CL_GetTeamSkinName: Unknown skin id %i", id);
00083     return skin->name;
00084 }
00085 
00086 static void CL_CharacterSkillAndScoreCvars (const character_t *chr, const char* cvarPrefix)
00087 {
00088     Cvar_ForceSet(va("%s%s", cvarPrefix, "name"), chr->name);
00089     Cvar_ForceSet(va("%s%s", cvarPrefix, "body"), CHRSH_CharGetBody(chr));
00090     Cvar_ForceSet(va("%s%s", cvarPrefix, "head"), CHRSH_CharGetHead(chr));
00091     Cvar_ForceSet(va("%s%s", cvarPrefix, "skin"), va("%i", chr->skin));
00092     Cvar_ForceSet(va("%s%s", cvarPrefix, "skinname"), CL_GetTeamSkinName(chr->skin));
00093 
00094     Cvar_Set(va("%s%s", cvarPrefix, "vpwr"), va("%i", chr->score.skills[ABILITY_POWER]));
00095     Cvar_Set(va("%s%s", cvarPrefix, "vspd"), va("%i", chr->score.skills[ABILITY_SPEED]));
00096     Cvar_Set(va("%s%s", cvarPrefix, "vacc"), va("%i", chr->score.skills[ABILITY_ACCURACY]));
00097     Cvar_Set(va("%s%s", cvarPrefix, "vmnd"), va("%i", chr->score.skills[ABILITY_MIND]));
00098     Cvar_Set(va("%s%s", cvarPrefix, "vcls"), va("%i", chr->score.skills[SKILL_CLOSE]));
00099     Cvar_Set(va("%s%s", cvarPrefix, "vhvy"), va("%i", chr->score.skills[SKILL_HEAVY]));
00100     Cvar_Set(va("%s%s", cvarPrefix, "vass"), va("%i", chr->score.skills[SKILL_ASSAULT]));
00101     Cvar_Set(va("%s%s", cvarPrefix, "vsnp"), va("%i", chr->score.skills[SKILL_SNIPER]));
00102     Cvar_Set(va("%s%s", cvarPrefix, "vexp"), va("%i", chr->score.skills[SKILL_EXPLOSIVE]));
00103     Cvar_Set(va("%s%s", cvarPrefix, "vpwri"), va("%i", chr->score.initialSkills[ABILITY_POWER]));
00104     Cvar_Set(va("%s%s", cvarPrefix, "vspdi"), va("%i", chr->score.initialSkills[ABILITY_SPEED]));
00105     Cvar_Set(va("%s%s", cvarPrefix, "vacci"), va("%i", chr->score.initialSkills[ABILITY_ACCURACY]));
00106     Cvar_Set(va("%s%s", cvarPrefix, "vmndi"), va("%i", chr->score.initialSkills[ABILITY_MIND]));
00107     Cvar_Set(va("%s%s", cvarPrefix, "vclsi"), va("%i", chr->score.initialSkills[SKILL_CLOSE]));
00108     Cvar_Set(va("%s%s", cvarPrefix, "vhvyi"), va("%i", chr->score.initialSkills[SKILL_HEAVY]));
00109     Cvar_Set(va("%s%s", cvarPrefix, "vassi"), va("%i", chr->score.initialSkills[SKILL_ASSAULT]));
00110     Cvar_Set(va("%s%s", cvarPrefix, "vsnpi"), va("%i", chr->score.initialSkills[SKILL_SNIPER]));
00111     Cvar_Set(va("%s%s", cvarPrefix, "vexpi"), va("%i", chr->score.initialSkills[SKILL_EXPLOSIVE]));
00112     Cvar_Set(va("%s%s", cvarPrefix, "vhp"), va("%i", chr->HP));
00113     Cvar_Set(va("%s%s", cvarPrefix, "vhpmax"), va("%i", chr->maxHP));
00114 
00115     Cvar_Set(va("%s%s", cvarPrefix, "tpwr"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[ABILITY_POWER]), chr->score.skills[ABILITY_POWER]));
00116     Cvar_Set(va("%s%s", cvarPrefix, "tspd"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[ABILITY_SPEED]), chr->score.skills[ABILITY_SPEED]));
00117     Cvar_Set(va("%s%s", cvarPrefix, "tacc"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[ABILITY_ACCURACY]), chr->score.skills[ABILITY_ACCURACY]));
00118     Cvar_Set(va("%s%s", cvarPrefix, "tmnd"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[ABILITY_MIND]), chr->score.skills[ABILITY_MIND]));
00119     Cvar_Set(va("%s%s", cvarPrefix, "tcls"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[SKILL_CLOSE]), chr->score.skills[SKILL_CLOSE]));
00120     Cvar_Set(va("%s%s", cvarPrefix, "thvy"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[SKILL_HEAVY]), chr->score.skills[SKILL_HEAVY]));
00121     Cvar_Set(va("%s%s", cvarPrefix, "tass"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[SKILL_ASSAULT]), chr->score.skills[SKILL_ASSAULT]));
00122     Cvar_Set(va("%s%s", cvarPrefix, "tsnp"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[SKILL_SNIPER]), chr->score.skills[SKILL_SNIPER]));
00123     Cvar_Set(va("%s%s", cvarPrefix, "texp"), va("%s (%i)", CL_ActorGetSkillString(chr->score.skills[SKILL_EXPLOSIVE]), chr->score.skills[SKILL_EXPLOSIVE]));
00124     Cvar_Set(va("%s%s", cvarPrefix, "thp"), va("%i (%i)", chr->HP, chr->maxHP));
00125 }
00126 
00138 static void CL_ActorCvars (const character_t * chr, const char* cvarPrefix)
00139 {
00140     invList_t *weapon;
00141     assert(chr);
00142 
00143     /* visible equipment */
00144     weapon = RIGHT(chr);
00145     if (weapon)
00146         Cvar_Set(va("%s%s", cvarPrefix, "rweapon"), weapon->item.t->model);
00147     else
00148         Cvar_Set(va("%s%s", cvarPrefix, "rweapon"), "");
00149     weapon = LEFT(chr);
00150     if (weapon)
00151         Cvar_Set(va("%s%s", cvarPrefix, "lweapon"), weapon->item.t->model);
00152     else
00153         Cvar_Set(va("%s%s", cvarPrefix, "lweapon"), "");
00154 }
00155 
00167 static void CL_UGVCvars (const character_t *chr)
00168 {
00169     Cvar_Set("mn_lweapon", "");
00170     Cvar_Set("mn_rweapon", "");
00171     Cvar_Set("mn_vmnd", "0");
00172     Cvar_Set("mn_tmnd", va("%s (0)", CL_ActorGetSkillString(chr->score.skills[ABILITY_MIND])));
00173 }
00174 
00175 void CL_UpdateCharacterValues (const character_t *chr, const char *cvarPrefix)
00176 {
00177     CL_CharacterSkillAndScoreCvars(chr, cvarPrefix);
00178 
00179     if (chr->teamDef->race == RACE_ROBOT)
00180         CL_UGVCvars(chr);
00181     else
00182         CL_ActorCvars(chr, cvarPrefix);
00183 
00184     GAME_CharacterCvars(chr);
00185 }
00186 
00192 qboolean CL_SaveCharacterXML (mxml_node_t *p, const character_t* chr)
00193 {
00194     mxml_node_t *sScore;
00195     mxml_node_t *sInventory;
00196     int k;
00197     const chrScoreGlobal_t *score;
00198 
00199     assert(chr);
00200     Com_RegisterConstList(saveCharacterConstants);
00201     /* Store the character data */
00202     mxml_AddString(p, SAVE_CHARACTER_NAME, chr->name);
00203     mxml_AddString(p, SAVE_CHARACTER_BODY, chr->body);
00204     mxml_AddString(p, SAVE_CHARACTER_PATH, chr->path);
00205     mxml_AddString(p, SAVE_CHARACTER_HEAD, chr->head);
00206     mxml_AddInt(p, SAVE_CHARACTER_SKIN, chr->skin);
00207     mxml_AddString(p, SAVE_CHARACTER_TEAMDEF, chr->teamDef->id);
00208     mxml_AddInt(p, SAVE_CHARACTER_GENDER, chr->gender);
00209     mxml_AddInt(p, SAVE_CHARACTER_UCN, chr->ucn);
00210     mxml_AddInt(p, SAVE_CHARACTER_MAXHP, chr->maxHP);
00211     mxml_AddInt(p, SAVE_CHARACTER_HP, chr->HP);
00212     mxml_AddInt(p, SAVE_CHARACTER_STUN, chr->STUN);
00213     mxml_AddInt(p, SAVE_CHARACTER_MORALE, chr->morale);
00214     mxml_AddInt(p, SAVE_CHARACTER_FIELDSIZE, chr->fieldSize);
00215     mxml_AddIntValue(p, SAVE_CHARACTER_STATE, chr->state);
00216 
00217     score = &chr->score;
00218 
00219     sScore = mxml_AddNode(p, SAVE_CHARACTER_SCORES);
00220     /* Store skills */
00221     for (k = 0; k <= SKILL_NUM_TYPES; k++) {
00222         if (score->experience[k] || score->initialSkills[k]
00223          || (k < SKILL_NUM_TYPES && score->skills[k])) {
00224             mxml_node_t *sSkill = mxml_AddNode(sScore, SAVE_CHARACTER_SKILLS);
00225             const int initial = score->initialSkills[k];
00226             const int experience = score->experience[k];
00227 
00228             mxml_AddString(sSkill, SAVE_CHARACTER_SKILLTYPE, Com_GetConstVariable(SAVE_CHARACTER_SKILLTYPE_NAMESPACE, k));
00229             mxml_AddIntValue(sSkill, SAVE_CHARACTER_INITSKILL, initial);
00230             mxml_AddIntValue(sSkill, SAVE_CHARACTER_EXPERIENCE, experience);
00231             if (k < SKILL_NUM_TYPES) {
00232                 const int skills = *(score->skills + k);
00233                 const int improve = skills - initial;
00234                 mxml_AddIntValue(sSkill, SAVE_CHARACTER_SKILLIMPROVE, improve);
00235             }
00236         }
00237     }
00238     /* Store kills */
00239     for (k = 0; k < KILLED_NUM_TYPES; k++) {
00240         mxml_node_t *sKill;
00241         if (score->kills[k] || score->stuns[k]) {
00242             sKill = mxml_AddNode(sScore, SAVE_CHARACTER_KILLS);
00243             mxml_AddString(sKill, SAVE_CHARACTER_KILLTYPE, Com_GetConstVariable(SAVE_CHARACTER_KILLTYPE_NAMESPACE, k));
00244             mxml_AddIntValue(sKill, SAVE_CHARACTER_KILLED, score->kills[k]);
00245             mxml_AddIntValue(sKill, SAVE_CHARACTER_STUNNED, score->stuns[k]);
00246         }
00247     }
00248     mxml_AddIntValue(sScore, SAVE_CHARACTER_SCORE_ASSIGNEDMISSIONS, score->assignedMissions);
00249     mxml_AddInt(sScore, SAVE_CHARACTER_SCORE_RANK, score->rank);
00250 
00251     /* Store inventories */
00252     sInventory = mxml_AddNode(p, SAVE_INVENTORY_INVENTORY);
00253     CL_SaveInventoryXML(sInventory, &chr->i);
00254 
00255     Com_UnregisterConstList(saveCharacterConstants);
00256     return qtrue;
00257 }
00258 
00264 qboolean CL_LoadCharacterXML (mxml_node_t *p, character_t *chr)
00265 {
00266     const char *s;
00267     mxml_node_t *sScore;
00268     mxml_node_t *sSkill;
00269     mxml_node_t *sKill;
00270     mxml_node_t *sInventory;
00271     qboolean success = qtrue;
00272 
00273     /* Load the character data */
00274     Q_strncpyz(chr->name, mxml_GetString(p, SAVE_CHARACTER_NAME), sizeof(chr->name));
00275     Q_strncpyz(chr->body, mxml_GetString(p, SAVE_CHARACTER_BODY), sizeof(chr->body));
00276     Q_strncpyz(chr->path, mxml_GetString(p, SAVE_CHARACTER_PATH), sizeof(chr->path));
00277     Q_strncpyz(chr->head, mxml_GetString(p, SAVE_CHARACTER_HEAD), sizeof(chr->head));
00278 
00279     chr->skin = mxml_GetInt(p, SAVE_CHARACTER_SKIN, 0);
00280     chr->gender = mxml_GetInt(p, SAVE_CHARACTER_GENDER, 0);
00281     chr->ucn = mxml_GetInt(p, SAVE_CHARACTER_UCN, 0);
00282     chr->maxHP = mxml_GetInt(p, SAVE_CHARACTER_MAXHP, 0);
00283     chr->HP = mxml_GetInt(p, SAVE_CHARACTER_HP, 0);
00284     chr->STUN = mxml_GetInt(p, SAVE_CHARACTER_STUN, 0);
00285     chr->morale = mxml_GetInt(p, SAVE_CHARACTER_MORALE, 0);
00286     chr->fieldSize = mxml_GetInt(p, SAVE_CHARACTER_FIELDSIZE, 1);
00287     chr->state = mxml_GetInt(p, SAVE_CHARACTER_STATE, 0);
00288 
00289     /* Team-definition */
00290     s = mxml_GetString(p, SAVE_CHARACTER_TEAMDEF);
00291     chr->teamDef = Com_GetTeamDefinitionByID(s);
00292     if (!chr->teamDef)
00293         return qfalse;
00294 
00295     Com_RegisterConstList(saveCharacterConstants);
00296 
00297     sScore = mxml_GetNode(p, SAVE_CHARACTER_SCORES);
00298     /* Load Skills */
00299     for (sSkill = mxml_GetNode(sScore, SAVE_CHARACTER_SKILLS); sSkill; sSkill = mxml_GetNextNode(sSkill, sScore, SAVE_CHARACTER_SKILLS)) {
00300         int idx;
00301         const char *type = mxml_GetString(sSkill, SAVE_CHARACTER_SKILLTYPE);
00302 
00303         if (!Com_GetConstIntFromNamespace(SAVE_CHARACTER_SKILLTYPE_NAMESPACE, type, &idx)) {
00304             Com_Printf("Invalid skill type '%s' for %s (ucn: %i)\n", type, chr->name, chr->ucn);
00305             success = qfalse;
00306             break;
00307         }
00308 
00309         chr->score.initialSkills[idx] = mxml_GetInt(sSkill, SAVE_CHARACTER_INITSKILL, 0);
00310         chr->score.experience[idx] = mxml_GetInt(sSkill, SAVE_CHARACTER_EXPERIENCE, 0);
00311         if (idx < SKILL_NUM_TYPES) {
00312             chr->score.skills[idx] = chr->score.initialSkills[idx];
00313             chr->score.skills[idx] += mxml_GetInt(sSkill, SAVE_CHARACTER_SKILLIMPROVE, 0);
00314         }
00315     }
00316 
00317     if (!success) {
00318         Com_UnregisterConstList(saveCharacterConstants);
00319         return qfalse;
00320     }
00321 
00322     /* Load kills */
00323     for (sKill = mxml_GetNode(sScore, SAVE_CHARACTER_KILLS); sKill; sKill = mxml_GetNextNode(sKill, sScore, SAVE_CHARACTER_KILLS)) {
00324         int idx;
00325         const char *type = mxml_GetString(sKill, SAVE_CHARACTER_KILLTYPE);
00326 
00327         if (!Com_GetConstIntFromNamespace(SAVE_CHARACTER_KILLTYPE_NAMESPACE, type, &idx)) {
00328             Com_Printf("Invalid kill type '%s' for %s (ucn: %i)\n", type, chr->name, chr->ucn);
00329             success = qfalse;
00330             break;
00331         }
00332         chr->score.kills[idx] = mxml_GetInt(sKill, SAVE_CHARACTER_KILLED, 0);
00333         chr->score.stuns[idx] = mxml_GetInt(sKill, SAVE_CHARACTER_STUNNED, 0);
00334     }
00335 
00336     if (!success) {
00337         Com_UnregisterConstList(saveCharacterConstants);
00338         return qfalse;
00339     }
00340 
00341     chr->score.assignedMissions = mxml_GetInt(sScore, SAVE_CHARACTER_SCORE_ASSIGNEDMISSIONS, 0);
00342     chr->score.rank = mxml_GetInt(sScore, SAVE_CHARACTER_SCORE_RANK, -1);
00343 
00344     cls.i.DestroyInventory(&cls.i, &chr->i);
00345     sInventory = mxml_GetNode(p, SAVE_INVENTORY_INVENTORY);
00346     CL_LoadInventoryXML(sInventory, &chr->i);
00347 
00348     Com_UnregisterConstList(saveCharacterConstants);
00349     return qtrue;
00350 }
00351 
00361 static void CL_SaveItemXML (mxml_node_t *p, item_t item, containerIndex_t container, int x, int y)
00362 {
00363     assert(item.t);
00364 
00365     mxml_AddString(p, SAVE_INVENTORY_CONTAINER, csi.ids[container].name);
00366     mxml_AddInt(p, SAVE_INVENTORY_X, x);
00367     mxml_AddInt(p, SAVE_INVENTORY_Y, y);
00368     mxml_AddIntValue(p, SAVE_INVENTORY_ROTATED, item.rotated);
00369     mxml_AddString(p, SAVE_INVENTORY_WEAPONID, item.t->id);
00371     mxml_AddInt(p, SAVE_INVENTORY_AMOUNT, item.amount);
00372     if (item.a > NONE_AMMO) {
00373         mxml_AddString(p, SAVE_INVENTORY_MUNITIONID, item.m->id);
00374         mxml_AddInt(p, SAVE_INVENTORY_AMMO, item.a);
00375     }
00376 }
00377 
00385 void CL_SaveInventoryXML (mxml_node_t *p, const inventory_t *i)
00386 {
00387     containerIndex_t container;
00388 
00389     for (container = 0; container < csi.numIDs; container++) {
00390         invList_t *ic = i->c[container];
00391 
00392         /* ignore items linked from any temp container */
00393         if (INVDEF(container)->temp)
00394             continue;
00395 
00396         for (; ic; ic = ic->next) {
00397             mxml_node_t *s = mxml_AddNode(p, SAVE_INVENTORY_ITEM);
00398             CL_SaveItemXML(s, ic->item, container, ic->x, ic->y);
00399         }
00400     }
00401 }
00402 
00412 static void CL_LoadItemXML (mxml_node_t *n, item_t *item, containerIndex_t *container, int *x, int *y)
00413 {
00414     const char *itemID = mxml_GetString(n, SAVE_INVENTORY_WEAPONID);
00415     const char *contID = mxml_GetString(n, SAVE_INVENTORY_CONTAINER);
00416     int i;
00417 
00418     /* reset */
00419     memset(item, 0, sizeof(*item));
00420 
00421     for (i = 0; i < csi.numIDs; i++) {
00422         if (!strcmp(csi.ids[i].name, contID))
00423             break;
00424     }
00425     if (i >= csi.numIDs) {
00426         Com_Printf("Invalid container id '%s'\n", contID);
00427     }
00428     *container = i;
00429 
00430     item->t = INVSH_GetItemByID(itemID);
00431     *x = mxml_GetInt(n, SAVE_INVENTORY_X, 0);
00432     *y = mxml_GetInt(n, SAVE_INVENTORY_Y, 0);
00433     item->rotated = mxml_GetInt(n, SAVE_INVENTORY_ROTATED, 0);
00434     item->amount = mxml_GetInt(n, SAVE_INVENTORY_AMOUNT, 1);
00435     item->a = mxml_GetInt(n, SAVE_INVENTORY_AMMO, NONE_AMMO);
00436     if (item->a > NONE_AMMO) {
00437         itemID = mxml_GetString(n, SAVE_INVENTORY_MUNITIONID);
00438         item->m = INVSH_GetItemByID(itemID);
00439 
00440         /* reset ammo count if ammunition (item) not found */
00441         if (!item->m)
00442             item->a = NONE_AMMO;
00443     }
00444 }
00445 
00454 void CL_LoadInventoryXML (mxml_node_t *p, inventory_t *i)
00455 {
00456     mxml_node_t *s;
00457 
00458     for (s = mxml_GetNode(p, SAVE_INVENTORY_ITEM); s; s = mxml_GetNextNode(s, p, SAVE_INVENTORY_ITEM)) {
00459         item_t item;
00460         containerIndex_t container;
00461         int x, y;
00462 
00463         CL_LoadItemXML(s, &item, &container, &x, &y);
00464         if (!cls.i.AddToInventory(&cls.i, i, item, INVDEF(container), x, y, 1))
00465             Com_Printf("Could not add item '%s' to inventory\n", item.t ? item.t->id : "NULL");
00466     }
00467 }
00468 
00474 void CL_GenerateCharacter (character_t *chr, const char *teamDefName)
00475 {
00476     memset(chr, 0, sizeof(*chr));
00477 
00478     /* link inventory */
00479     cls.i.DestroyInventory(&cls.i, &chr->i);
00480 
00481     /* get ucn */
00482     chr->ucn = cls.nextUniqueCharacterNumber++;
00483 
00484     CL_ActorSetShotSettings(chr, ACTOR_HAND_NOT_SET, -1, NULL);
00485 
00486     Com_GetCharacterValues(teamDefName, chr);
00487     /* Create attributes. */
00488     CHRSH_CharGenAbilitySkills(chr, GAME_IsMultiplayer());
00489 }
00490 
00494 static void CL_InitSkin_f (void)
00495 {
00496     /* create option for singleplayer skins */
00497     if (UI_GetOption(OPTION_SINGLEPLAYER_SKINS) == NULL) {
00498         uiNode_t *skins = NULL;
00499         int idx = 0;
00500         customSkin_t *skin;
00501         while ((skin = Com_GetCustomSkinByIDS(idx++))) {
00502             if (!skin->singleplayer)
00503                 continue;
00504             UI_AddOption(&skins, skin->id, skin->name, va("%d", skin->idx));
00505         }
00506         UI_RegisterOption(OPTION_SINGLEPLAYER_SKINS, skins);
00507     }
00508 
00509     /* create option for multiplayer skins */
00510     if (UI_GetOption(OPTION_MULTIPLAYER_SKINS) == NULL) {
00511         uiNode_t *skins = NULL;
00512         int idx = 0;
00513         customSkin_t *skin;
00514         while ((skin = Com_GetCustomSkinByIDS(idx++))) {
00515             if (!skin->multiplayer)
00516                 continue;
00517             UI_AddOption(&skins, skin->id, skin->name, va("%d", skin->idx));
00518         }
00519         UI_RegisterOption(OPTION_MULTIPLAYER_SKINS, skins);
00520     }
00521 }
00522 
00526 static int CL_FixCustomSkinIDX (int idx)
00527 {
00528     customSkin_t *skin = Com_GetCustomSkinByIDS(idx);
00529 
00531     if (skin == NULL) {
00532         idx = 0;
00533     } else {
00534         if (GAME_IsSingleplayer() && !skin->singleplayer)
00535             idx = 0;
00536         if (GAME_IsMultiplayer() && !skin->multiplayer)
00537             idx = 0;
00538     }
00539     return idx;
00540 }
00541 
00545 static void CL_ChangeSkin_f (void)
00546 {
00547     const int sel = cl_selected->integer;
00548 
00549     if (sel >= 0 && sel < chrDisplayList.num) {
00550         int newSkin = Cvar_GetInteger("mn_skin");
00551         newSkin = CL_FixCustomSkinIDX(newSkin);
00552 
00553         if (chrDisplayList.chr[sel]) {
00556             chrDisplayList.chr[sel]->skin = newSkin;
00557 
00558             Cvar_SetValue("mn_skin", newSkin);
00559             Cvar_Set("mn_skinname", CL_GetTeamSkinName(newSkin));
00560         }
00561     }
00562 }
00563 
00567 static void CL_ChangeSkinForWholeTeam_f (void)
00568 {
00569     int newSkin, i;
00570 
00571     /* Get selected skin and fall back to default skin if it is not valid. */
00572     newSkin = Cvar_GetInteger("mn_skin");
00573     newSkin = CL_FixCustomSkinIDX(newSkin);
00574 
00575     /* Apply new skin to all (shown/displayed) team-members. */
00577     for (i = 0; i < chrDisplayList.num; i++) {
00578         assert(chrDisplayList.chr[i]);
00581         chrDisplayList.chr[i]->skin = newSkin;
00582     }
00583 }
00584 
00585 void TEAM_InitStartup (void)
00586 {
00587     Cmd_AddCommand("team_initskin", CL_InitSkin_f, "Init skin according to the game mode");
00588     Cmd_AddCommand("team_changeskin", CL_ChangeSkin_f, "Change the skin of the soldier");
00589     Cmd_AddCommand("team_changeskinteam", CL_ChangeSkinForWholeTeam_f, "Change the skin for the whole current team");
00590 }

Generated by  doxygen 1.6.2