//recharge items on rest, if rest was partial, recharge only 'hours' //if this latter functionality is unwanted, then simply don't recharge if //hours != 0 void Inventory::ChargeAllItems(int hours) { //this loop is going from start for (size_t i = 0; i < Slots.size(); i++) { CREItem *item = Slots[i]; if (!item) { continue; } Item *itm = gamedata->GetItem( item->ItemResRef ); if (!itm) continue; for(int h=0;h<CHARGE_COUNTERS;h++) { ITMExtHeader *header = itm->GetExtHeader(h); if (header && (header->RechargeFlags&IE_ITEM_RECHARGE)) { unsigned short add = header->Charges; if (hours && add>hours) add=hours; add+=item->Usages[h]; if(add>header->Charges) add=header->Charges; item->Usages[h]=add; } } gamedata->FreeItem( itm, item->ItemResRef, false ); } }
//This hack sets the charge counters for non-rechargeable items, //if their charge is zero inline void HackCharges(CREItem *item) { Item *itm = gamedata->GetItem( item->ItemResRef ); if (itm) { for (int i=0;i<3;i++) { if (item->Usages[i]) { continue; } ITMExtHeader *h = itm->GetExtHeader(i); if (h && !(h->RechargeFlags&IE_ITEM_RECHARGE)) { //HACK: the original (bg2) allows for 0 charged gems if (h->Charges) { item->Usages[i] = h->Charges; } else { item->Usages[i] = 1; } } } gamedata->FreeItem( itm, item->ItemResRef, false ); } }
//some stores can recharge items - in original engine apparently all stores //did this. In gemrb there is a flag. void Store::RechargeItem(CREItem *item) { Item *itm = gamedata->GetItem(item->ItemResRef); if (!itm) { return; } //gemrb extension, some shops won't recharge items //containers' behaviour is inverted //bag 0 1 0 1 //flag 0 0 1 1 //recharge 1 0 0 1 if (IsBag() != !(Flags&IE_STORE_RECHARGE)) { bool feature = core->HasFeature(GF_SHOP_RECHARGE); for (int i=0;i<CHARGE_COUNTERS;i++) { ITMExtHeader *h = itm->GetExtHeader(i); if (h && (feature || h->RechargeFlags&IE_ITEM_RECHARGE) && item->Usages[i] < h->Charges) item->Usages[i] = h->Charges; } } gamedata->FreeItem(itm, item->ItemResRef, 0); }
//this is the low level equipping //all checks have been made previously bool Inventory::EquipItem(unsigned int slot) { ITMExtHeader *header; if (!Owner) { //maybe assertion too? return false; } CREItem *item = GetSlotItem(slot); if (!item) { return false; } int weaponslot; // add effects of an item just being equipped to actor's effect queue int effect = core->QuerySlotEffects( slot ); Item *itm = gamedata->GetItem(item->ItemResRef); if (!itm) { printf("Invalid item Equipped: %s Slot: %d\n", item->ItemResRef, slot); return false; } switch (effect) { case SLOT_EFFECT_LEFT: //no idea if the offhand weapon has style, or simply the right //hand style is dominant UpdateShieldAnimation(itm); break; case SLOT_EFFECT_MELEE: //if weapon is ranged, then find quarrel for it and equip that slot -= SLOT_MELEE; weaponslot = slot; EquippedHeader = 0; header = itm->GetExtHeader(EquippedHeader); if (header && header->AttackType == ITEM_AT_BOW) { //find the ranged projectile associated with it. slot = FindRangedProjectile(header->ProjectileQualifier); EquippedHeader = itm->GetWeaponHeaderNumber(true); } else if (header && header->AttackType == ITEM_AT_PROJECTILE) { EquippedHeader = itm->GetWeaponHeaderNumber(true); } else { EquippedHeader = itm->GetWeaponHeaderNumber(false); } header = itm->GetExtHeader(EquippedHeader); if (header) { SetEquippedSlot(slot, EquippedHeader); if (slot != IW_NO_EQUIPPED) { Owner->SetupQuickSlot(ACT_WEAPON1+weaponslot, slot+SLOT_MELEE, EquippedHeader); } effect = 0; // SetEquippedSlot will already call AddSlotEffects UpdateWeaponAnimation(); } break; case SLOT_EFFECT_MISSILE: //Get the ranged header of the projectile (so we theoretically allow shooting of daggers) EquippedHeader = itm->GetWeaponHeaderNumber(true); header = itm->GetExtHeader(EquippedHeader); if (header) { weaponslot = FindTypedRangedWeapon(header->ProjectileQualifier); if (weaponslot != SLOT_FIST) { weaponslot -= SLOT_MELEE; SetEquippedSlot((ieWordSigned) (slot-SLOT_MELEE), EquippedHeader); //It is unsure if we can have multiple equipping headers for bows/arrow //It is unclear which item's header index should go there Owner->SetupQuickSlot(ACT_WEAPON1+weaponslot, slot, 0); } UpdateWeaponAnimation(); } break; case SLOT_EFFECT_HEAD: Owner->SetUsedHelmet(itm->AnimationType); break; case SLOT_EFFECT_ITEM: //adjusting armour level if needed { int l = itm->AnimationType[0]-'1'; if (l>=0 && l<=3) { Owner->SetBase(IE_ARMOR_TYPE, l); } else { UpdateShieldAnimation(itm); } } break; } gamedata->FreeItem(itm, item->ItemResRef, false); if (effect) { if (item->Flags & IE_INV_ITEM_CURSED) { item->Flags|=IE_INV_ITEM_UNDROPPABLE; } AddSlotEffects( slot ); } return true; }