cl_inventory.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_inventory.h"
00029 #include "cl_inventory_callbacks.h"
00030 #include "../shared/parse.h"
00031 
00041 const equipDef_t *INV_GetEquipmentDefinitionByID (const char *name)
00042 {
00043     int i;
00044 
00045     for (i = 0, csi.eds; i < csi.numEDs; i++)
00046         if (!strcmp(name, csi.eds[i].name))
00047             return &csi.eds[i];
00048 
00049     Com_Error(ERR_DROP, "Could not find equipment %s", name);
00050 }
00051 
00064 qboolean INV_MoveItem (inventory_t* inv, const invDef_t * toContainer, int px, int py,
00065     const invDef_t * fromContainer, invList_t *fItem)
00066 {
00067     int moved;
00068 
00069     if (px >= SHAPE_BIG_MAX_WIDTH || py >= SHAPE_BIG_MAX_HEIGHT)
00070         return qfalse;
00071 
00072     if (!fItem)
00073         return qfalse;
00074 
00075     /* move the item */
00076     moved = cls.i.MoveInInventory(&cls.i, inv, fromContainer, fItem, toContainer, px, py, NULL, NULL);
00077 
00078     switch (moved) {
00079     case IA_MOVE:
00080     case IA_ARMOUR:
00081         return qtrue;
00082     default:
00083         return qfalse;
00084     }
00085 }
00086 
00094 void INV_LoadWeapon (invList_t *weapon, inventory_t *inv, const invDef_t *srcContainer, const invDef_t *destContainer)
00095 {
00096     int equipType;
00097     invList_t *ic = NULL;
00098     int i = 0;
00099 
00100     assert(weapon);
00101 
00102     equipType = INV_GetFilterFromItem(weapon->item.t);
00103     /* search an ammo */
00104     while (i < weapon->item.t->numAmmos && !ic) {
00105         ic = INVSH_SearchInInventoryWithFilter(inv, srcContainer, NONE, NONE, weapon->item.t->ammos[i], equipType);
00106         i++;
00107     }
00108     if (ic)
00109         INV_MoveItem(inv, destContainer, weapon->x, weapon->y, srcContainer, ic);
00110 }
00111 
00119 qboolean INV_UnloadWeapon (invList_t *weapon, inventory_t *inv, const invDef_t *container)
00120 {
00121     assert(weapon);
00122     if (container && inv) {
00123         const item_t item = {NONE_AMMO, NULL, weapon->item.m, 0, 0};
00124         if (cls.i.AddToInventory(&cls.i, inv, item, container, NONE, NONE, 1) != NULL) {
00125             weapon->item.m = NULL;
00126             weapon->item.a = 0;
00127             return qtrue;
00128         }
00129     }
00130     return qfalse;
00131 }
00132 
00133 #ifdef DEBUG
00134 
00138 static void INV_InventoryList_f (void)
00139 {
00140     int i;
00141 
00142     for (i = 0; i < csi.numODs; i++) {
00143         objDef_t *od = INVSH_GetItemByIDX(i);
00144         Com_Printf("Item: %s\n", od->id);
00145         Com_Printf("... name          -> %s\n", od->name);
00146         Com_Printf("... type          -> %s\n", od->type);
00147         Com_Printf("... category      -> %i\n", od->animationIndex);
00148         Com_Printf("... weapon        -> %i\n", od->weapon);
00149         Com_Printf("... holdtwohanded -> %i\n", od->holdTwoHanded);
00150         Com_Printf("... firetwohanded -> %i\n", od->fireTwoHanded);
00151         Com_Printf("... thrown        -> %i\n", od->thrown);
00152         Com_Printf("... usable for weapon (if type is ammo):\n");
00153         for (i = 0; i < od->numWeapons; i++) {
00154             if (od->weapons[i])
00155                 Com_Printf("    ... %s\n", od->weapons[i]->name);
00156         }
00157         Com_Printf("\n");
00158     }
00159 }
00160 #endif
00161 
00167 static qboolean INV_EquipmentDefSanityCheck (void)
00168 {
00169     int i, j;
00170     int sum;
00171     qboolean result = qtrue;
00172 
00173     for (i = 0; i < csi.numEDs; i++) {
00174         const equipDef_t const *ed = &csi.eds[i];
00175         /* only check definitions used for generating teams */
00176         if (strncmp(ed->name, "alien", 5) && strncmp(ed->name, "phalanx", 7))
00177             continue;
00178 
00179         /* Check primary */
00180         sum = 0;
00181         for (j = 0; j < csi.numODs; j++) {
00182             const objDef_t const *obj = INVSH_GetItemByIDX(j);
00183             if (obj->weapon && obj->fireTwoHanded
00184              && (INV_ItemMatchesFilter(obj, FILTER_S_PRIMARY) || INV_ItemMatchesFilter(obj, FILTER_S_HEAVY)))
00185                 sum += ed->numItems[j];
00186         }
00187         if (sum > 100) {
00188             Com_Printf("INV_EquipmentDefSanityCheck: Equipment Def '%s' has a total probability for primary weapons greater than 100\n", ed->name);
00189             result = qfalse;
00190         }
00191 
00192         /* Check secondary */
00193         sum = 0;
00194         for (j = 0; j < csi.numODs; j++) {
00195             const objDef_t const *obj = INVSH_GetItemByIDX(j);
00196             if (obj->weapon && obj->reload && !obj->deplete && INV_ItemMatchesFilter(obj, FILTER_S_SECONDARY))
00197                 sum += ed->numItems[j];
00198         }
00199         if (sum > 100) {
00200             Com_Printf("INV_EquipmentDefSanityCheck: Equipment Def '%s' has a total probability for secondary weapons greater than 100\n", ed->name);
00201             result = qfalse;
00202         }
00203 
00204         /* Check armour */
00205         sum = 0;
00206         for (j = 0; j < csi.numODs; j++) {
00207             const objDef_t const *obj = INVSH_GetItemByIDX(j);
00208             if (INV_ItemMatchesFilter(obj, FILTER_S_ARMOUR))
00209                 sum += ed->numItems[j];
00210         }
00211         if (sum > 100) {
00212             Com_Printf("INV_EquipmentDefSanityCheck: Equipment Def '%s' has a total probability for armours greater than 100\n", ed->name);
00213             result = qfalse;
00214         }
00215 
00216         /* Don't check misc: the total probability can be greater than 100 */
00217     }
00218 
00219     return result;
00220 }
00221 
00222 itemFilterTypes_t INV_GetFilterFromItem (const objDef_t *obj)
00223 {
00224     assert(obj);
00225 
00226     /* heavy weapons may be primary too. check heavy first */
00227     if (obj->isHeavy)
00228         return FILTER_S_HEAVY;
00229     else if (obj->isPrimary)
00230         return FILTER_S_PRIMARY;
00231     else if (obj->isSecondary)
00232         return FILTER_S_SECONDARY;
00233     else if (obj->isMisc)
00234         return FILTER_S_MISC;
00235     else if (INV_IsArmour(obj))
00236         return FILTER_S_ARMOUR;
00237 
00239     Sys_Error("INV_GetFilterFromItem: unknown filter category for item '%s'", obj->id);
00240 }
00241 
00248 qboolean INV_ItemMatchesFilter (const objDef_t *obj, const itemFilterTypes_t filterType)
00249 {
00250     int i;
00251 
00252     if (!obj)
00253         return qfalse;
00254 
00255     switch (filterType) {
00256     case FILTER_S_PRIMARY:
00257         if (obj->isPrimary && !obj->isHeavy)
00258             return qtrue;
00259 
00260         /* Check if one of the items that uses this ammo matches this filter type. */
00261         for (i = 0; i < obj->numWeapons; i++) {
00262             if (obj->weapons[i] && obj->weapons[i] != obj && INV_ItemMatchesFilter(obj->weapons[i], filterType))
00263                 return qtrue;
00264         }
00265         break;
00266 
00267     case FILTER_S_SECONDARY:
00268         if (obj->isSecondary && !obj->isHeavy)
00269             return qtrue;
00270 
00271         /* Check if one of the items that uses this ammo matches this filter type. */
00272         for (i = 0; i < obj->numWeapons; i++) {
00273             if (obj->weapons[i] && obj->weapons[i] != obj && INV_ItemMatchesFilter(obj->weapons[i], filterType))
00274                 return qtrue;
00275         }
00276         break;
00277 
00278     case FILTER_S_HEAVY:
00279         if (obj->isHeavy)
00280             return qtrue;
00281 
00282         /* Check if one of the items that uses this ammo matches this filter type. */
00283         for (i = 0; i < obj->numWeapons; i++) {
00284             if (obj->weapons[i] && obj->weapons[i] != obj && INV_ItemMatchesFilter(obj->weapons[i], filterType))
00285                 return qtrue;
00286         }
00287         break;
00288 
00289     case FILTER_S_ARMOUR:
00290         return INV_IsArmour(obj);
00291 
00292     case FILTER_S_MISC:
00293         return obj->isMisc;
00294 
00295     case FILTER_CRAFTITEM:
00297         return INV_IsCraftItem(obj);
00298 
00299     case FILTER_UGVITEM:
00300         return obj->isUGVitem;
00301 
00302     case FILTER_DUMMY:
00303         return obj->isDummy;
00304 
00305     case FILTER_AIRCRAFT:
00306         return !strcmp(obj->type, "aircraft");
00307 
00308     case FILTER_DISASSEMBLY:
00310         break;
00311 
00312     case MAX_SOLDIER_FILTERTYPES:
00313     case MAX_FILTERTYPES:
00314     case FILTER_ENSURE_32BIT:
00315         Com_Printf("INV_ItemMatchesFilter: Unknown filter type for items: %i\n", filterType);
00316         break;
00317     }
00318 
00319     /* The given filter type is unknown. */
00320     return qfalse;
00321 }
00322 
00334 invList_t *INVSH_SearchInInventoryWithFilter (const inventory_t* const i, const invDef_t * container, int x, int y, objDef_t *item,  const itemFilterTypes_t filterType)
00335 {
00336     invList_t *ic;
00337 
00338     if (item == NULL)
00339         return NULL;
00340 
00341     for (ic = i->c[container->id]; ic; ic = ic->next) {
00342         /* Search only in the items that could get displayed. */
00343         if (ic && ic->item.t && (INV_ItemMatchesFilter(ic->item.t, filterType) || filterType == MAX_FILTERTYPES)) {
00344             /* We search _everything_, no matter what location it is (i.e. x/y are ignored). */
00345             if (item == ic->item.t)
00346                 return ic;
00347         }
00348     }
00349 
00350     /* No item with these coordinates (or matching item) found. */
00351     return NULL;
00352 }
00353 
00356 static const char *filterTypeNames[MAX_FILTERTYPES] = {
00357     "primary",      
00358     "secondary",    
00359     "heavy",        
00360     "misc",         
00361     "armour",       
00362     "",             
00363     "craftitem",    
00364     "ugvitem",      
00365     "aircraft",     
00366     "dummy",        
00367     "disassembly"   
00368 };
00369 CASSERT(lengthof(filterTypeNames) == MAX_FILTERTYPES);
00370 
00375 itemFilterTypes_t INV_GetFilterTypeID (const char * filterTypeID)
00376 {
00377     itemFilterTypes_t i;
00378 
00379     if (!filterTypeID)
00380         return MAX_FILTERTYPES;
00381 
00382     /* default filter type is primary */
00383     if (filterTypeID[0] == '\0')
00384         return FILTER_S_PRIMARY;
00385 
00386     for (i = 0; i < MAX_FILTERTYPES; i++) {
00387         if (filterTypeNames[i] && !strcmp(filterTypeNames[i], filterTypeID))
00388             return i;
00389     }
00390 
00391     /* No matching filter type found, returning max value. */
00392     return MAX_FILTERTYPES;
00393 }
00394 
00398 const char *INV_GetFilterType (const int id)
00399 {
00400     assert(id >= 0);
00401     assert(id < MAX_FILTERTYPES);
00402     return filterTypeNames[id];
00403 }
00404 
00405 void INV_InitStartup (void)
00406 {
00407 #ifdef DEBUG
00408     Cmd_AddCommand("debug_listinventory", INV_InventoryList_f, "Print the current inventory to the game console");
00409 #endif
00410     INV_InitCallbacks();
00411 
00412     INV_EquipmentDefSanityCheck();
00413 }
00414 

Generated by  doxygen 1.6.2