Ok, here is my rewrite of the function, including the changes from l0stmancd. I highlighted the section I changed in green (can't make a normal diff atm).
tradeskills.cpp
Code:
void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo)
{
if (!user || !in_augment)
{
LogFile->write(EQEMuLog::Error, "Client or AugmentItem_Struct not set in Object::HandleAugmentation");
return;
}
ItemInst* container = NULL;
if (worldo)
{
container = worldo->m_inst;
}
else
{
// Check to see if they have an inventory container type 53 that is used for this.
Inventory& user_inv = user->GetInv();
ItemInst* inst = NULL;
inst = user_inv.GetItem(in_augment->container_slot);
if (inst)
{
const Item_Struct* item = inst->GetItem();
if (item && inst->IsType(ItemClassContainer) && item->BagType == 53)
{
// We have found an appropriate inventory augmentation sealer
container = inst;
// Verify that no more than two items are in container to guarantee no inadvertant wipes.
uint8 itemsFound = 0;
for (uint8 i=0; i<10; i++)
{
const ItemInst* inst = container->GetItem(i);
if (inst)
{
itemsFound++;
}
}
if (itemsFound != 2)
{
user->Message(13, "Error: Too many/few items in augmentation container.");
return;
}
}
}
}
if(!container)
{
LogFile->write(EQEMuLog::Error, "Player tried to augment an item without a container set.");
user->Message(13, "Error: This item is not a container!");
return;
}
ItemInst *tobe_auged, *auged_with = NULL;
sint8 slot=-1;
// Verify 2 items in the augmentation device
if (container->GetItem(0) && container->GetItem(1))
{
// Verify 1 item is augmentable and the other is not
if (container->GetItem(0)->IsAugmentable() && !container->GetItem(1)->IsAugmentable())
{
tobe_auged = container->GetItem(0);
auged_with = container->GetItem(1);
}
else if (!container->GetItem(0)->IsAugmentable() && container->GetItem(1)->IsAugmentable())
{
tobe_auged = container->GetItem(1);
auged_with = container->GetItem(0);
}
else
{
// Either 2 augmentable items found or none found
// This should never occur due to client restrictions, but prevent in case of a hack
user->Message(13, "Error: Must be 1 augmentable item in the sealer");
// May want to user->Kick() them to prevent potential inventory sync issues if it happened legitimately
return;
}
}
else
{
// Less than 2 items in the augmentation device
// This should never occur due to client restrictions, but prevent in case of a hack
if (!container->GetItem(0))
{
user->Message(13, "Error: No item in slot 0 of sealer");
}
if (!container->GetItem(1))
{
user->Message(13, "Error: No item in slot 1 of sealer");
}
// May want to user->Kick() them to prevent potential inventory sync issues if it happened legitimately
return;
}
bool deleteItems = false;
ItemInst *itemOneToPush = NULL, *itemTwoToPush = NULL;
// Adding augment
if (in_augment->augment_slot == -1)
{
if (((slot=tobe_auged->AvailableAugmentSlot(auged_with->GetAugmentType()))!=-1) && (tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots)))
{
tobe_auged->PutAugment(slot,*auged_with);
itemOneToPush = tobe_auged->Clone();
deleteItems = true;
}
else
{
user->Message(13, "Error: No available slot for augment");
}
}
else
{
ItemInst *old_aug=NULL;
const uint32 id=auged_with->GetID();
if (id==40408 || id==40409 || id==40410)
tobe_auged->DeleteAugment(in_augment->augment_slot);
else
old_aug=tobe_auged->RemoveAugment(in_augment->augment_slot);
itemOneToPush = tobe_auged->Clone();
if (old_aug)
itemTwoToPush = old_aug->Clone();
deleteItems = true;
}
if (deleteItems)
{
if (worldo)
{
container->Clear();
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClearObject, sizeof(ClearObject_Struct));
ClearObject_Struct *cos = (ClearObject_Struct *)outapp->pBuffer;
cos->Clear = 1;
user->QueuePacket(outapp);
safe_delete(outapp);
database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID());
}
else
{
// Delete items in our inventory container...
for (uint8 i=0; i<10; i++)
{
const ItemInst* inst = container->GetItem(i);
if (inst)
{
user->DeleteItemInInventory(Inventory::CalcSlotId(in_augment->container_slot,i),0,true);
}
}
// Explicitly mark container as cleared.
container->Clear();
}
}
// Must push items after the items in inventory are deleted - necessary due to lore items...
if (itemOneToPush)
{
user->PushItemOnCursor(*itemOneToPush,true);
}
if (itemTwoToPush)
{
user->PushItemOnCursor(*itemTwoToPush,true);
}
}
Hopefully I have some time to actually test these changes myself. I dunno if that will be soon or when. If l0stmancd or anyone else wants to run it through some decent testing, feel free. I will probably run it on my server for a day or so to make sure there are no major issues with it before committing it. If anyone sees any potential issues with the code, lemme know as well.