View Single Post
  #5  
Old 01-11-2009, 11:59 PM
Congdar
Developer
 
Join Date: Jul 2007
Location: my own little world
Posts: 751
Default

Try this new code out. I've fixed the Spinechill Silk combine and the Spellbook Scribe crash.
If somebody could list some thing to test or items that currently go away when the charges are used but aren't supposed to, that would be great.

Things I've tested with this new update:
Tradeskills:
Created Fish Rolls by combining 1 Fresh Fish and 1 Bat Wings. Stacked supplies correctly subtracted.
Created Spinechill Silk by combining 1 Spinechill Ichor Vial and 2 Spinechill Silk. Unstackable supplies correctly subtracted.

Worn items with charges:
Cleric/Paladin Shield - Aegis of Life 1 charge of Superior Healing. Charge used, Item not deleted.
Journeyman's Boots. Unlimited charges, not deleted.

Inventory items with charges:
Prayers of Life 5 charges of Word of Healing. Charges used, Item deleted.
Crystalized Pumice 5 charges of Nullify Magic. Charges used, Item deleted.
Stack of 10 Cloudy Potions. Stack decremented correctly and last one deleted.
5 Dose Cloudy Potion. Charges used, Item deleted.
Stack of Bandages. Took some damage and used Bind Wound skill. Bandages decremented correctly.

Spell Scribing:
Wizard memorized Gate spell. Spell scroll deleted, no crash.

Merchants:
Purchased stackable items
Purchased unstackable items
Sold stackable items
Sold unstackable items

Bots:
Trade with bots to give them equipment works.
#bot inventory remove used successfully

GM:
#si [itemid] worked.
#nukeitem [itemid] worked.

You will still need the item.h and Item.cpp changes from the first post.

This is the spell scribing fix:
\zone\client_process.cpp void Client::OPMemorizeSpell(const EQApplicationPacket* app)
Replace the case statement for memSpellScribing:
Code:
		case memSpellScribing:	{	// scribing spell to book
			ItemInst* inst = m_inv.PopItem(SLOT_CURSOR);
			
			if(inst && inst->IsType(ItemClassCommon))
			{
				const Item_Struct* item = inst->GetItem();
				
				if(item && item->Scroll.Effect == (sint32)(memspell->spell_id))
				{
					ScribeSpell(memspell->spell_id, memspell->slot);

					// Destroy scroll on cursor
					EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
					MoveItem_Struct* spellmoveitem = (MoveItem_Struct*) outapp->pBuffer;
					spellmoveitem->from_slot = SLOT_CURSOR;
					spellmoveitem->to_slot = SLOT_INVALID;
					spellmoveitem->number_in_stack = 0;
					QueuePacket(outapp);
					safe_delete(outapp);

					DeleteItemInInventory(SLOT_CURSOR);
					
				}
				else 
					Message(0,"Scribing spell: inst exists but item does not or spell ids do not match.");
			}
			else
				Message(0,"Scribing a spell without an inst on your cursor?");
			break;

			}
with
Code:
		case memSpellScribing:	{	// scribing spell to book
			const ItemInst* inst = m_inv[SLOT_CURSOR];

			if(inst && inst->IsType(ItemClassCommon))
			{
				const Item_Struct* item = inst->GetItem();
				
				if(item && item->Scroll.Effect == (sint32)(memspell->spell_id))
				{
					ScribeSpell(memspell->spell_id, memspell->slot);
					DeleteItemInInventory(SLOT_CURSOR, 1, true);
				}
				else 
					Message(0,"Scribing spell: inst exists but item does not or spell ids do not match.");
			}
			else
				Message(0,"Scribing a spell without an inst on your cursor?");
			break;
		}
Here's a complete replacement again for the method \zone\inventory.cpp Client::DeleteItemInInventory(sint16 slot_id, sint8 quantity, bool client_update)
Code:
// Remove item from inventory
void Client::DeleteItemInInventory(sint16 slot_id, sint8 quantity, bool client_update) {
	#if (EQDEBUG >= 5)
		LogFile->write(EQEMuLog::Debug, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false");
	#endif

	if(!m_inv[slot_id]) {
		return;
	}

	bool isDeleted = false;
	if(m_inv[slot_id]->GetItem()->Click.Type == ET_EquipClick) {
		isDeleted = m_inv.DeleteItem(slot_id, quantity, true);
	}
	else {
		isDeleted = m_inv.DeleteItem(slot_id, quantity);
	}

	const ItemInst* inst=NULL;
	if(slot_id==SLOT_CURSOR) {
		list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
		database.SaveCursor(character_id, s, e);
	}
	else {
		// Save change to database
		inst = m_inv[slot_id];
		database.SaveInventory(character_id, inst, slot_id);
	}

	if(client_update) {
		EQApplicationPacket* outapp;
		if(inst) {
			if(!inst->IsStackable() && !isDeleted) 
				// Non stackable item with charges = Item with clicky spell effect ? Delete a charge.
				outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct));
			else
				// Stackable, arrows, etc ? Delete one from the stack
				outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct));

			DeleteItem_Struct* delitem	= (DeleteItem_Struct*)outapp->pBuffer;
			delitem->from_slot		= slot_id;
			delitem->to_slot		= 0xFFFFFFFF;
			delitem->number_in_stack	= 0xFFFFFFFF;
			for(int loop=0;loop<quantity;loop++)
				QueuePacket(outapp);
			safe_delete(outapp);
		}
		else {
			outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
			MoveItem_Struct* delitem	= (MoveItem_Struct*)outapp->pBuffer;
			delitem->from_slot		= slot_id;
			delitem->to_slot		= 0xFFFFFFFF;
			delitem->number_in_stack	= 0xFFFFFFFF;
			QueuePacket(outapp);
			safe_delete(outapp);
		}
	}
}
Reply With Quote