#include "q_shared.h" #include "..\ghoul\ighoul.h" #include "w_public.h" #include "w_types.h" #include "w_weapons.h" #include "w_utils.h" #include "player.h" #include "../gamecpp/game.h" #include "w_equipment.h" #include "../strings/items.h" extern player_com_import_t picom; extern player_cl_import_t picl; extern player_sv_import_t pisv; extern int isClient; itemInfo_c noItem; flashpackInfo flashpack; //neuralGrenadeInfo neuralGrenade; c4Info c4; lightGogglesInfo lightGoggles; claymoreInfo claymore; medkitInfo medkit; grenadeInfo grenade; flagInfo flag; itemInfo_c *itInfo[SFE_NUMITEMS] = { &noItem, &flashpack, // &neuralGrenade, &c4, &lightGoggles, &claymore, &medkit, &grenade, &flag, }; //------------------------------------------------------------------------------------ itemSlot_c::itemSlot_c(void) { clear(); } void itemSlot_c::useAmmo(sharedEdict_t &ent) { // 1/10/00 kef -- the light goggles are different. annoying, too. if (itemType == SFE_LIGHT_GOGGLES) { // since lightGogglesInfo::frameUpdate() will take care of the current power (ammo) for the //goggles, don't update ammo here. if (ammo-1 <= 0) { int nBreak =1 ; } // kef -- Eric said get rid of this message for the light goggles /* if(!isClient) { pisv.SP_Print(ent.edict, ITEMS_AMMO_COUNT, ammo, itInfo[itemType]->getName()); } */ return; } ammo--; if(ammo <= 0) { if(!isClient) pisv.SP_Print(ent.edict, ITEMS_AMMO_GONE, itInfo[itemType]->getName()); itemType = SFE_EMPTYSLOT; status = 0; inven(ent)->getItems()->setNextCommand(PEC_ITEMNEXT); } else { if(!isClient) pisv.SP_Print(ent.edict, ITEMS_AMMO_COUNT, ammo, itInfo[itemType]->getName()); } } void itemSlot_c::clear(void) { itemType = SFE_EMPTYSLOT; ammo = 0; status = 0; nextupdate=0.0; } //------------------------------------------------------------------------------------ item_c::item_c(void) { curSlotNum = 0; nextCommand = PEC_NOCOMMAND; lastUseTime = 0; } int item_c::getSlotNumFromName(char *itemName) { int type=-1; if(!stricmp (itemName,"fpak")) type=SFE_FLASHPACK; else if(!stricmp (itemName,"c4")) type=SFE_C4; else if(!stricmp (itemName,"goggles")) type=SFE_LIGHT_GOGGLES; else if(!stricmp (itemName,"medkit")) type=SFE_MEDKIT; else if(!stricmp (itemName,"grenade")) type=SFE_GRENADE; else if(!stricmp (itemName,"ctf_flag")) type=SFE_CTFFLAG; if(type<0) return(-2); for(int i = 0; i < MAXITEMS; i++) if(slots[i].getSlotType() == type) return(i); return(-1); } int item_c::addItemType(int type, int amount, int maxAmount) { int i; for(i = 0; i < MAXITEMS; i++) { if(slots[i].getSlotType() == type) { // Do some tests to see if this many can actually be held. if (maxAmount != -1) // Do we have a defined maximum? { if ((slots[i].getSlotCount() + amount) > maxAmount) // we can't pick up ALL of these { if(slots[i].getSlotCount() < maxAmount) // but we can pick up SOME of them { slots[i].setSlotCount(maxAmount); return 1; } else // nope, no room at the inn, we're full { return 0; } } } slots[i].setSlotCount(slots[i].getSlotCount() + amount); return 1; } } for(i = 0; i < MAXITEMS; i++) { // Okay, add it to an empty slot then. if(slots[i].getSlotType() == SFE_EMPTYSLOT) { slots[i].setSlotType(type); // Do some tests to see if this many can actually be held. In this case, we're checking in case for SOME reason // we don't have ANY of an item, but the item pickup actually has MORE than we are allowed to carry. Proper design // should render this test unnecessary, but... if (maxAmount != -1) // Do we have a defined maximum? { if ((slots[i].getSlotCount() + amount) > maxAmount) // we can't pick up ALL of these { if(slots[i].getSlotCount() < maxAmount) // but we can pick up SOME of them { slots[i].setSlotCount(maxAmount); return 1; } else // nope, no room at the inn, we're full { return 0; } } } slots[i].setSlotCount(amount); return 1; } } return 0; } int item_c::hasItemType(int type) { for(int i = 0; i < MAXITEMS; i++) { if(slots[i].getSlotType() == type) return 1; } return(0); } void item_c::HandleInput(sharedEdict_t &ent) { int startSlot; if(nextCommand == PEC_NOCOMMAND) return; startSlot = curSlotNum; if(nextCommand == PEC_DROP) { if(getCurSlot()->getSlotType()!=SFE_EMPTYSLOT) { // Handle deactivation of item, where required. itInfo[getCurSlot()->getSlotType()]->deactivate(*(ent.edict), *getCurSlot()); // Some items like the light-goggles are unique in the inventory but // have ammo / charge so we need to ensure the dropped item has this much ammo. // Other items like flahsbangs exist in multiples and we just drop one at a time. int amount=(itInfo[getCurSlot()->getSlotType()]->itemExistsAsUnique())?getCurSlot()->getSlotCount():1; // Drop an in-world entity. if(!isClient) pisv.ItemDrop(inven(ent)->getOwner()->edict,getCurSlot()->getSlotType(),amount); if(itInfo[getCurSlot()->getSlotType()]->itemExistsAsUnique()) { // Claer the item slot 'cos we just dropped a unique item (e.g. light-goggles). getCurSlot()->clear(); // Select the next item slot. nextCommand = PEC_ITEMNEXT; } else { // Decrement the ammo count for the slot by 1 as we just dropped one :). getCurSlot()->useAmmo(ent); } } } if((nextCommand >= PEC_USEITEM)&&(nextCommand < PEC_USEITEMFIRST + MAXITEMS)) { if(!isClient) { if(lastUseTime + ITEM_USE_TIME > *pisv.levelTime) { // Can't mash on the item_c use button. return; } } else { if(lastUseTime + ITEM_USE_TIME > *picl.levelTime) { // Can't mash on the item_c use button. return; } } itemSlot_c *slot; if(nextCommand == PEC_USEITEM) { slot=getCurSlot(); } else { slot=&slots[nextCommand-PEC_USEITEMFIRST]; } if(slot->getSlotCount()) { if(ent.inv->inDisguise()) { // If we try to use anything other than medkit whilst disguised, // we toggle outa disguise! if(slot->getSlotType() != SFE_MEDKIT) ent.inv->becomeDisguised(); } // Can't use the CTF FLAG!! if (slot->getSlotType() == SFE_CTFFLAG) return; if (!isClient) pisv.ShowItemUse(ent.edict, slot->getSlotType()); int lastCmd=nextCommand; if (itInfo[slot->getSlotType()]->use(*(ent.edict), *slot)) slot->useAmmo(ent); if((nextCommand==PEC_ITEMNEXT)&&(lastCmd>PEC_USEITEM)&&(slot!=getCurSlot())) { // PEC_ITEMNEXT can be issued if all slot's ammo was used. Don't // want this though if a shortcut was used and it wasn't the current // slot. nextCommand=PEC_NOCOMMAND; } } if(!isClient) lastUseTime = *pisv.levelTime; else lastUseTime = *picl.levelTime; } if(nextCommand == PEC_ITEMNEXT) { do { curSlotNum++; if(curSlotNum >= MAXITEMS) { curSlotNum = 0; } }while((curSlotNum != startSlot)&&(getCurSlot()->getSlotType() == SFE_EMPTYSLOT)); } else if(nextCommand == PEC_ITEMPREV) { do { curSlotNum--; if(curSlotNum < 0) { curSlotNum = MAXITEMS - 1; } }while((curSlotNum != startSlot)&&(getCurSlot()->getSlotType() == SFE_EMPTYSLOT)); } nextCommand = PEC_NOCOMMAND; } void item_c::frameUpdate(sharedEdict_t &ent) { int i; HandleInput(ent); for(i = 0; i < MAXITEMS; i++) { itInfo[slots[i].getSlotType()]->frameUpdate(ent, slots[i]); } } int item_c::handleDamage(sharedEdict_t &ent, int initDamage) { int i; int curDamage = initDamage; for(i = 0; i < MAXITEMS; i++) { // FIXME: Will this change? curDamage = itInfo[slots[i].getSlotType()]->handleDamage(ent, curDamage, slots[i]); } return curDamage; } void item_c::deactivate(sharedEdict_t &ent) { for(int i = 0; i < MAXITEMS; i++) { itInfo[slots[i].getSlotType()]->deactivate(*(ent.edict), *getCurSlot()); } }