//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 );
	}
}
Esempio n. 3
0
//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;
}