1 /* GemRB - Infinity Engine Emulator 2 * Copyright (C) 2003 The GemRB Project 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 * 19 */ 20 21 /** 22 * @file Inventory.h 23 * Declares Inventory, class implementing creatures' and containers' 24 * inventory and item management 25 * @author The GemRB Project 26 */ 27 28 #ifndef INVENTORY_H 29 #define INVENTORY_H 30 31 #include "exports.h" 32 #include "ie_types.h" 33 34 #include "Item.h" //needs item for itmextheader 35 #include "Store.h" 36 37 #include <vector> 38 39 namespace GemRB { 40 41 class Map; 42 class StringBuffer; 43 44 //AddSlotItem return values 45 #define ASI_FAILED 0 46 #define ASI_PARTIAL 1 47 #define ASI_SUCCESS 2 48 #define ASI_SWAPPED 3 //not returned normally, but Gui uses this value 49 50 //AddSlotItem extra slot ID's 51 #define SLOT_AUTOEQUIP -1 52 #define SLOT_ONLYINVENTORY -3 53 54 //slottypes (bitfield) 55 #define SLOT_HELM 1 56 #define SLOT_ARMOUR 2 57 #define SLOT_SHIELD 4 58 #define SLOT_GLOVE 8 59 #define SLOT_RING 16 60 #define SLOT_AMULET 32 61 #define SLOT_BELT 64 62 #define SLOT_BOOT 128 63 #define SLOT_WEAPON 256 64 #define SLOT_QUIVER 512 65 #define SLOT_CLOAK 1024 66 #define SLOT_ITEM 2048 //quick item 67 #define SLOT_SCROLL 4096 68 #define SLOT_BAG 8192 69 #define SLOT_POTION 16384 70 #define SLOT_ANY 32767 71 #define SLOT_INVENTORY 32768 72 #define SLOT_ALL 65535 73 74 //weapon slot types (1000==not equipped) 75 #define IW_NO_EQUIPPED 1000 76 77 /** Inventory types */ 78 typedef enum ieInventoryType { 79 INVENTORY_HEAP = 0, 80 INVENTORY_CREATURE = 1 81 } ieInventoryType; 82 83 // !!! Keep these synchronized with GUIDefines.py !!! 84 typedef enum ieCREItemFlagBits : uint32_t { 85 IE_INV_ITEM_IDENTIFIED = 1, 86 IE_INV_ITEM_UNSTEALABLE = 2, 87 IE_INV_ITEM_STOLEN = 4, // denotes steel items in pst 88 //in iwd/iwd2 this flag means 'magical', some hack is needed 89 IE_INV_ITEM_UNDROPPABLE =8, 90 //just recently acquired 91 IE_INV_ITEM_ACQUIRED = 0x10, //this is a gemrb extension 92 //is this item destructible normally? 93 IE_INV_ITEM_DESTRUCTIBLE = 0x20,//this is a gemrb extension 94 //is this item already equipped? 95 IE_INV_ITEM_EQUIPPED = 0x40, //this is a gemrb extension 96 //selected for sale, using the same bit, hope it is ok 97 IE_INV_ITEM_SELECTED = 0x40, //this is a gemrb extension 98 //is this item stackable? 99 IE_INV_ITEM_STACKED = 0x80, //this is a gemrb extension 100 //these flags are coming from the original item, but these are immutable 101 IE_INV_ITEM_CRITICAL = 0x100, //coming from original item 102 IE_INV_ITEM_TWOHANDED = 0x200, 103 IE_INV_ITEM_MOVABLE = 0x400, //same as undroppable 104 IE_INV_ITEM_RESELLABLE = 0x800, //item will appear in shop when sold 105 IE_INV_ITEM_CURSED = 0x1000, //item is cursed 106 IE_INV_ITEM_UNKNOWN2000 = 0x2000, //totally unknown 107 IE_INV_ITEM_MAGICAL = 0x4000, //magical 108 IE_INV_ITEM_BOW = 0x8000, // 109 IE_INV_ITEM_SILVER = 0x10000, 110 IE_INV_ITEM_COLDIRON = 0x20000, 111 IE_INV_ITEM_STOLEN2 = 0x40000, //same as 4 112 IE_INV_ITEM_CONVERSABLE = 0x80000, 113 IE_INV_ITEM_PULSATING = 0x100000 114 } ieCREItemFlagBits; 115 116 #define IE_INV_DEPLETABLE (IE_INV_ITEM_MAGICAL|IE_INV_ITEM_DESTRUCTIBLE) 117 118 //equip flags 119 #define EQUIP_ANY 0 120 #define EQUIP_MELEE 1 121 #define EQUIP_RANGED 2 122 123 //FIXME: 124 //actually this header shouldn't be THIS large, i was just 125 //lazy to pick the interesting elements 126 //it could be possible that some elements need to be added from the 127 //item header itself 128 struct ItemExtHeader { 129 ieDword slot; 130 ieDword headerindex; 131 //from itmextheader 132 ieByte AttackType; 133 ieByte IDReq; 134 ieByte Location; 135 ieByte unknown1; 136 ieResRef UseIcon; 137 ieStrRef Tooltip; 138 ieByte Target; 139 ieByte TargetNumber; 140 ieWord Range; 141 //This was commented out in ITMExtHeader 142 //ieWord ProjectileType; 143 ieWord Speed; 144 ieWord THAC0Bonus; 145 ieWord DiceSides; 146 ieWord DiceThrown; 147 ieWordSigned DamageBonus; //this must be signed!!! 148 ieWord DamageType; 149 ieWord FeatureCount; 150 ieWord FeatureOffset; 151 ieWord Charges; 152 ieWord ChargeDepletion; 153 ieDword RechargeFlags; //this is a bitfield with many bits 154 ieWord ProjectileAnimation; 155 ieWord MeleeAnimation[3]; 156 int ProjectileQualifier; //this is a derived value determined on load time 157 //other data 158 ieResRef itemname; 159 }; 160 161 /** 162 * @class CREItem 163 * Class holding Item instance specific values and providing link between 164 * an Inventory and a stack of Items. 165 * It's keeping info on whether Item was identified, for example. 166 */ 167 168 class GEM_EXPORT CREItem { 169 public: 170 ieResRef ItemResRef; 171 //recent research showed that this field is used by the create item 172 //for days effect. This field shows the expiration in gametime hours 173 ieWord Expired; 174 ieWord Usages[CHARGE_COUNTERS]; 175 uint32_t Flags; 176 // 2 cached values from associated item. LEAVE IT SIGNED! 177 /** Weight of each item in the stack */ 178 int Weight; 179 /** Maximum amount of items in this stack */ 180 int MaxStackAmount; 181 CREItem()182 CREItem() 183 { 184 Weight=-1; //invalid weight 185 MaxStackAmount=0; 186 Flags = 0; 187 Expired = 0; 188 }; CREItem(STOItem * item)189 CREItem(STOItem *item) 190 { 191 CopySTOItem(item); 192 }; CopySTOItem(STOItem * item)193 void CopySTOItem(STOItem *item) 194 { 195 CopyResRef(ItemResRef, item->ItemResRef); 196 Expired = 0; // PurchasedAmount in STOItem 197 memcpy(Usages, item->Usages, sizeof(ieWord)*CHARGE_COUNTERS); 198 Flags = item->Flags; 199 Weight = item->Weight; 200 MaxStackAmount = item->MaxStackAmount; 201 }; 202 }; 203 204 /** 205 * @class Inventory 206 * Class implementing creatures' and containers' inventory and item management 207 */ 208 209 class GEM_EXPORT Inventory { 210 private: 211 std::vector<CREItem*> Slots; 212 Actor* Owner; 213 int InventoryType; 214 /** Total weight of all items in Inventory */ 215 int Weight; 216 217 ieWordSigned Equipped; 218 ieWord EquippedHeader; 219 /** this isn't saved */ 220 ieDword ItemExcl; 221 ieDword ItemTypes[8]; //256 bits 222 public: 223 Inventory(); 224 virtual ~Inventory(); 225 226 /** duplicates the source inventory into the current one, marking items as undroppable */ 227 void CopyFrom(const Actor *source); 228 /** Removes an item from the inventory, destroys slot. 229 * Use it for containers only */ 230 CREItem *GetItem(unsigned int idx); 231 /** adds an item to the inventory */ 232 void AddItem(CREItem *item); 233 /** Returns number of items in the inventory */ 234 int CountItems(const char *resref, bool charges) const; 235 /** looks for a particular item in a slot */ 236 bool HasItemInSlot(const char *resref, unsigned int slot) const; 237 /** returns true if contains one itemtype equipped */ 238 bool HasItemType(ieDword type) const; 239 /** Looks for a particular item in the inventory. 240 * flags: see ieCREItemFlagBits */ 241 bool HasItem(const char *resref, ieDword flags) const; 242 243 void SetInventoryType(int arg); SetOwner(Actor * act)244 void SetOwner(Actor* act) { Owner = act; } 245 246 /** returns number of all slots in the inventory */ GetSlotCount()247 int GetSlotCount() const { return (int)Slots.size(); } 248 249 /** sets inventory size, for the first time */ 250 void SetSlotCount(unsigned int size); 251 252 253 /** Returns CREItem in specified slot. 254 * If count !=0 it splits the item and returns only requested amount */ 255 CREItem* RemoveItem(unsigned int slot, unsigned int count = 0); 256 /** returns slot of removed item, you can delete the removed item */ 257 int RemoveItem(const char* resref, unsigned int flags, CREItem **res_item, int count = 0); 258 259 /** adds CREItem to the inventory. If slot == -1, finds 260 ** first eligible slot, eventually splitting the item to 261 ** more slots. If slot == -3 then finds the first empty inventory slot 262 ** Returns 2 if completely successful, 1 if partially, 0 else. 263 ** slottype is an optional filter for searching eligible slots */ 264 int AddSlotItem(CREItem* item, int slot, int slottype = -1, bool ranged = false); 265 /** tries to equip all inventory items in a given slot */ 266 void TryEquipAll(int slot); 267 /** Adds STOItem to the inventory, it is never wielded, action might be STA_STEAL or STA_BUY */ 268 /** The amount of items is stored in PurchasedAmount */ 269 int AddStoreItem(STOItem* item, int action); 270 271 /** flags: see ieCREItemFlagBits */ 272 /** count == ~0 means to destroy all */ 273 /** returns the number of destroyed items */ 274 unsigned int DestroyItem(const char *resref, ieDword flags, ieDword count); 275 void SetSlotItem(CREItem* item, unsigned int slot); GetWeight()276 int GetWeight() const {return Weight;} 277 278 bool ItemsAreCompatible(const CREItem* target, const CREItem* source) const; 279 //depletes charged items 280 int DepleteItem(ieDword flags); 281 //charges recharging items 282 void ChargeAllItems(int hours); 283 /** Finds the first slot of named item, if resref is empty, finds the first filled! slot */ 284 int FindItem(const char *resref, unsigned int flags, unsigned int skip=0) const; 285 bool DropItemAtLocation(unsigned int slot, unsigned int flags, Map *map, const Point &loc); 286 bool DropItemAtLocation(const char *resref, unsigned int flags, Map *map, const Point &loc); 287 bool SetEquippedSlot(ieWordSigned slotcode, ieWord header, bool noFX=false); 288 int GetEquipped() const; 289 int GetEquippedHeader() const; 290 ITMExtHeader *GetEquippedExtHeader(int header=0) const; 291 void SetEquipped(ieWordSigned slot, ieWord header); 292 //right hand 293 int GetEquippedSlot() const; 294 //left hand 295 int GetShieldSlot() const; 296 void AddSlotEffects( ieDword slot); 297 //void AddAllEffects(); 298 /** Returns item in specified slot. Does NOT change inventory */ 299 CREItem* GetSlotItem(ieDword slot) const; 300 /** Returns the item's inventory flags */ 301 ieDword GetItemFlag(unsigned int slot) const; 302 /** Changes the inventory flags */ 303 /** flags: see ieCREItemFlagBits */ 304 bool ChangeItemFlag(ieDword slot, ieDword value, int mode); 305 /** Equips the item, don't use it directly for weapons */ 306 bool EquipItem(ieDword slot); 307 bool UnEquipItem(ieDword slot, bool removecurse) const; 308 /** Returns equipped weapon, also its slot */ 309 CREItem *GetUsedWeapon(bool leftorright, int &slot) const; 310 /** returns slot of launcher weapon currently equipped */ 311 int FindRangedWeapon() const; 312 /** returns slot of launcher weapon for specified projectile type */ 313 int FindTypedRangedWeapon(unsigned int type) const; 314 /** returns slot of launcher weapon for projectile in specified slot */ 315 int FindSlotRangedWeapon(ieDword slot) const; 316 /** Returns a slot which might be empty, or capable of holding item (or part of it) */ 317 int FindCandidateSlot(int slottype, size_t first_slot, const char *resref = NULL) const; 318 /** Creates an item in the slot*/ 319 void SetSlotItemRes(const ieResRef ItemResRef, int Slot, int Charge0=1, int Charge1=0, int Charge2=0); 320 /** Adds item to slot*/ 321 void AddSlotItemRes(const ieResRef ItemResRef, int Slot, int Charge0=1, int Charge1=0, int Charge2=0); 322 /** returns the itemtype held in the left hand */ 323 ieWord GetShieldItemType() const; 324 /** returns the itemtype of the item in the armor slot, mostly used in IWD2 */ 325 ieWord GetArmorItemType() const; 326 /** breaks the item (weapon) in slot */ 327 void BreakItemSlot(ieDword slot); 328 /** Lists all items in the Inventory on terminal for debugging */ 329 void dump() const; 330 /// List all items in the Inventory to the given buffer */ 331 void dump(StringBuffer&) const; 332 /** Equips best weapon */ 333 void EquipBestWeapon(int flags); 334 /** returns the struct of the usable items, returns true if there are more */ 335 bool GetEquipmentInfo(ItemExtHeader *array, int startindex, int count); 336 /** returns the exclusion bits */ 337 ieDword GetEquipExclusion(int index) const; 338 /** returns if a slot is temporarily blocked */ 339 bool IsSlotBlocked(int slot) const; 340 /** returns true if a two handed weapon is in slot */ 341 inline bool TwoHandedInSlot(int slot) const; 342 /** returns the strref for the reason why the item cannot be equipped */ 343 int WhyCantEquip(int slot, int twohanded, bool ranged = false) const; 344 /** returns a slot that has a stealable item */ 345 int FindStealableItem(); 346 /** checks if any equipped item provides critical hit aversion */ 347 bool ProvidesCriticalAversion(); 348 /** tries to merge the passed item with the one in the passed slot */ 349 int MergeItems(int slot, CREItem *item); 350 bool FistsEquipped() const; 351 bool MagicSlotEquipped() const; 352 //setting important constants 353 static void Init(); 354 static void SetArmorSlot(int arg); 355 static void SetHeadSlot(int arg); 356 static void SetFistSlot(int arg); 357 static void SetMagicSlot(int arg); 358 static void SetWeaponSlot(int arg); 359 static void SetRangedSlot(int arg); 360 static void SetQuickSlot(int arg); 361 static void SetInventorySlot(int arg); 362 static void SetShieldSlot(int arg); 363 static int GetArmorSlot(); 364 static int GetHeadSlot(); 365 static int GetFistSlot(); 366 static int GetMagicSlot(); 367 static int GetWeaponSlot(); 368 static int GetWeaponQuickSlot(int weaponslot); 369 static int GetWeaponSlot(int quickslot); 370 static int GetRangedSlot(); 371 static int GetQuickSlot(); 372 static int GetInventorySlot(); 373 private: 374 void CalculateWeight(void); 375 int FindRangedProjectile(unsigned int type) const; 376 // called by KillSlot 377 void RemoveSlotEffects( /*CREItem* slot*/ ieDword slot ); 378 void KillSlot(unsigned int index); 379 inline Item *GetItemPointer(ieDword slot, CREItem *&Slot) const; 380 void UpdateWeaponAnimation(); 381 void UpdateShieldAnimation(const Item *it); 382 }; 383 384 } 385 386 #endif 387