View Full Version : HUGE Bug - Attuneable items don't work
ChaosSlayer
06-27-2008, 04:16 PM
I just discovered that Attuneable items revert to dropeable state as soon as you zone after been attuned.
this is realy bad. my entire server is build on attuneable items actualy becomign no drop - as they should - as global part fo server economy, in order for whoel thing to function.
could you guys look into this please?
AndMetal
06-27-2008, 04:24 PM
Off the top of my head, because making a specific item NODROP where the global item is not, it would require something being defined, probably in the inventory table in the database, that says so.
Checking the Wiki for the inventory table (http://www.eqemulator.net/wiki/wikka.php?wakka=EQEmuDBSchemainventory), there is a column called instnodrop:
instnodrop
* This might keep a record of whether an attunable item has been attuned so that it is now no trade. But not completely certain on that.
I would start by checking the item in your inventory table to see if that is set. If not, we'd have to start look through the source to find out why not.
Theeper
07-01-2008, 10:07 AM
I don't think attuneable items work at all. They will attune, but once you zone, it's not attuned anymore. It doesn't appear to set the "instnodrop" field in the inventory table when you attune the item. Even manually setting the field doesn't seem to do anything .. unless it's supposed to be some odd value that I didn't try.
I can't find anything about attuneable items in the opcodes, so either it's called something else, or it's not there at all.
AndMetal
07-01-2008, 02:26 PM
Well, it looks like it was added into the source:
==01/15/2005
Doodman: Fixed charges/quantity
Doodman: Fixed IsStackable()
Doodman: Fixed some empty Handle() functons.
Doodman: Added instance level nodrop.
Required SQL:
alter table inventory add instnodrop tinyint(1) unsigned default 0 not null;
The following is where instnodrop is referenced in the source:
common/patches/Titanium.cpp (http://eqemulator.cvs.sourceforge.net/eqemulator/EQEmuCVS/Source/common/patches/Titanium.cpp?revision=1.8&view=markup#l_745)
common/Item.h (http://eqemulator.cvs.sourceforge.net/eqemulator/EQEmuCVS/Source/common/Item.h?revision=1.18&view=markup#l_236)
common/Item.cpp (http://eqemulator.cvs.sourceforge.net/eqemulator/EQEmuCVS/Source/common/Item.cpp?revision=1.29&view=markup#l_41)
common/shareddb.cpp (http://eqemulator.cvs.sourceforge.net/eqemulator/EQEmuCVS/Source/common/shareddb.cpp?revision=1.14&view=markup#l_174)
Looking at all of that, it seems the main issue is that SetInstNodrop() (http://eqemulator.cvs.sourceforge.net/eqemulator/EQEmuCVS/Source/common/Item.h?revision=1.18&view=markup#l_321) is never called anywhere, but it seems like the client sets it, which is probably why it shows as nodrop until you zone. I have a feeling this probably is related to a missing OpCode or some other packet telling the server it's now nodrop.
ChaosSlayer
01-24-2009, 01:17 PM
BUMP!
So guys- any new info on this one? :cool:
Theeper
02-25-2009, 09:21 AM
Here's a start on getting attuneable items working. Items are flagged as No Trade and remain No Trade when zoning
and logging off.
This is with rev 361 compiled Windows XP.
Set the instnodrop flag when an item is placed into a gear slot that has it's attuneable flag set. (This probably needs to be done somewhere else).
In zone\inventory.cpp around line 901 change
// Not dealing with charges - just do direct swap
if(src_inst && dst_slot_id<22 && dst_slot_id>0)
SetMaterial(dst_slot_id,src_inst->GetItem()->ID);
mlog(INVENTORY__SLOTS, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id);
m_inv.SwapItem(src_slot_id, dst_slot_id);
to
// Not dealing with charges - just do direct swap
if(src_inst && dst_slot_id<22 && dst_slot_id>0) {
if (src_inst->GetItem()->Attuneable) {
src_inst->SetInstNoDrop(true);
}
SetMaterial(dst_slot_id,src_inst->GetItem()->ID);
}
mlog(INVENTORY__SLOTS, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id);
m_inv.SwapItem(src_slot_id, dst_slot_id);
Then, move the instnodrop field in the item serialization code a couple spots over in the Titanium patch file.
In patches\Titanium.cpp near line 871, change
MakeAnyLenString(&instance,
"%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|",
stackable ? charges : 0,
0,
(merchant_slot==0) ? slot_id : merchant_slot,
inst->GetPrice(),
(merchant_slot==0) ? 1 : inst->GetMerchantCount(),
0,
//merchant_slot, //instance ID, bullshit for now
(merchant_slot==0) ? inst->GetSerialNumber() : merchant_slot,
inst->IsInstNoDrop() ? 1 : 0, //not sure where this field is
(stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges),
0,
0
);
to
MakeAnyLenString(&instance,
"%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|",
stackable ? charges : 0,
0,
(merchant_slot==0) ? slot_id : merchant_slot,
inst->GetPrice(),
(merchant_slot==0) ? 1 : inst->GetMerchantCount(),
0,
//merchant_slot, //instance ID, bullshit for now
(merchant_slot==0) ? inst->GetSerialNumber() : merchant_slot,
0,
(stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges),
inst->IsInstNoDrop() ? 1 : 0,
0
);
- You can still trade attuned items to NPC's and maybe sell in the bazaar, but you can't trade to players or sell to vendors. I will put in some checks for these later.
- When items are autoequipped from loot, it bypasses the "Attune" popup that happens when you manually equip stuff. Need to at least put a check on startup to flag the items. I'm not sure of the popup behaviour on Live though.
- I didn't look into the other client serializations because I can't test them.
I thought ChaosSlayer might want to test it out now though.
ChaosSlayer
02-25-2009, 07:12 PM
Thank you for this submission Theeper
Unfortunately I can't realy test any new code myself at this time due to number of reasons, So I am hopping that Trev, Cavedude or KLS can try this fix and hopefuly it will work :cool:
Theeper
02-25-2009, 07:54 PM
After looking through the nodrop checks, it looks like in most places, it's just reading the pointer to the base item flag directly.
It seems like it would make sense to create an IsNoDrop() function inside the ItemInst class to check both flags. Then replace all the existing nodrop checks throughout ... as opposed to adding an instance no drop check each time a normal no drop check is done.
Also, any thoughts on how it worked when you looted an attuneable item on Live ? .. If the item auto equipped, did the "Are you sure you want to attune?" popup window work?
It seems like there was some odd issue with attuneable items back then, but It's been too long.
As usual, there's probably a function somewhere I missed and KLS will rewrite the whole thing in one line.
ChaosSlayer
02-25-2009, 08:27 PM
as far as I can tell on LIVE attuneable item did not tried to auto-equip itself - it went directly into your bags
Theeper
02-25-2009, 10:55 PM
Good point. Here is a simple change to make them not auto equip.
In zone\inventory.cpp around line 381
Change
// #1: Try to auto equip
if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level)
to
// #1: Try to auto equip
if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && !inst.GetItem()->Attuneable)
And this will set the instnodrop flag upon zoning if the item was equipped somehow (like with MQ) and bypasses the popup window.
in common\shareddb.cpp around line 483
Change
if (item) {
sint16 put_slot_id = SLOT_INVALID;
ItemInst inst(item, charges);
if (instnodrop)
inst.SetInstNoDrop(true);
if (color > 0)
inst.SetColor(color);
if(charges==255)
inst.SetCharges(-1);
else
to
if (item) {
sint16 put_slot_id = SLOT_INVALID;
ItemInst inst(item, charges);
if (instnodrop || (slot_id >= 0 && slot_id <= 21 && inst.GetItem()->Attuneable))
inst.SetInstNoDrop(true);
if (color > 0)
inst.SetColor(color);
if(charges==255)
inst.SetCharges(-1);
else
cavedude
02-26-2009, 12:19 AM
I just tested this out, attuneable items do persist over zoning/camping and no longer auto-loot. However, they lose their no drop flag when you loot the item off your corpse. We're probably losing the flag when it gets transferred to the corpse.
Also, I confirmed that you can trade them to NPCs, however you can't sell them in bazaar. Since they are no drop, they won't appear in your item list after placing in the trader's satchel.
So, all that needs to be done is put in a NPC trade check, and correct the transfer to corpses and back then this will be 100%.
Secrets
02-26-2009, 12:30 AM
Have not tested this, but this should work hopefully. I probably messed it up but something along the lines of this should work, heh.
PlayerCorpse.cpp
void Corpse::MoveItemToCorpse(Client *client, ItemInst *item, sint16 equipslot)
{
int bagindex;
sint16 interior_slot;
ItemInst *interior_item;
AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4));
if(item->IsType(ItemClassContainer))
{
for(bagindex = 0; bagindex <= 10; bagindex++)
{
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
interior_item = client->GetInv().GetItem(interior_slot);
if(interior_item->IsInstNoDrop)
{
interior_item->SetInstNoDrop(true);
}
if(interior_item)
{
AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
client->DeleteItemInInventory(interior_slot);
}
}
}
client->DeleteItemInInventory(equipslot);
}
Theeper
02-26-2009, 10:25 AM
Thanks guys, I'll try to get the NPC trade thing and the corpse flag done when I get home tonite.
Secrets, this doesn't look proper though. You're setting a flag that is already set.
if(interior_item->IsInstNoDrop)
{
interior_item->SetInstNoDrop(true);
}
I'm wondering if you meant to do..
if(item->IsInstNoDrop())
{
interior_item->SetInstNoDrop(true);
}
cavedude
02-26-2009, 03:06 PM
The PlayerCorpse change is a bad, bad change! :) I accidentally put it up on TGC without testing and it caused players to lose all but 1 bag in their top inventory slot when they died, and caused a zone crash. That'll teach me to upload files when I am half asleep. Good thing we keep daily backups.
Theeper: Yes, if the change was good that's the syntax you'd use.
Secrets
02-26-2009, 09:43 PM
The PlayerCorpse change is a bad, bad change! :) I accidentally put it up on TGC without testing and it caused players to lose all but 1 bag in their top inventory slot when they died, and caused a zone crash. That'll teach me to upload files when I am half asleep. Good thing we keep daily backups.
Theeper: Yes, if the change was good that's the syntax you'd use.
Heh, yeah. I'm still learning C++. Sorry about that.
I guess that doesn't work, then. Back to the drawing board!
Theeper
02-26-2009, 10:08 PM
I think the corpse issue will involve adding an 'instnodrop' field to the ServerLootItem_Struct struct and setting it when a corpse is made so it's saved into the item list in the corpse blob, then setting the item instance flag and the DB flag upon looting.
I'm short on time today, but I'll look through it tomorrow after work.
cavedude
02-26-2009, 10:21 PM
Heh, yeah. I'm still learning C++. Sorry about that.
I guess that doesn't work, then. Back to the drawing board!
Nah, it was totally my fault. That could have just as easily been my broken code getting into TGC. We all have to start somewhere, and I applaud you for contributing :)
Theeper
03-09-2009, 08:55 AM
Here is another step closer to having attuneable items working. This will make corpses properly handle the instnodrop flag .. almost.
It works fine except for on bagged items. They lose the flag upon looting. It's set on the corpse, and set when looted, but I can't figure out why it's getting unset. I was hoping someone else would put their eyes on it and tell me what I missed.
I am not sure how this works with PVP looting and shared bank as I haven't tested them.
This one is kinda long, so I made a diff against rev 373. This is on windows with PEQ.
Index: common/shareddb.cpp
================================================== =================
--- common/shareddb.cpp (revision 373)
+++ common/shareddb.cpp (working copy)
@@ -1201,7 +1201,7 @@
// Create appropriate ItemInst class
-ItemInst* SharedDatabase::CreateItem(uint32 item_id, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
+ItemInst* SharedDatabase::CreateItem(uint32 item_id, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool instnodrop)
{
const Item_Struct* item = NULL;
ItemInst* inst = NULL;
@@ -1213,6 +1213,7 @@
inst->PutAugment(this, 2, aug3);
inst->PutAugment(this, 3, aug4);
inst->PutAugment(this, 4, aug5);
+ inst->SetInstNoDrop(instnodrop);
}
@@ -1221,7 +1222,7 @@
// Create appropriate ItemInst class
-ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
+ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool instnodrop)
{
ItemInst* inst = NULL;
if (item) {
@@ -1234,6 +1235,7 @@
inst->PutAugment(this, 3, aug4);
inst->PutAugment(this, 4, aug5);
inst->SetCharges(charges);
+ inst->SetInstNoDrop(instnodrop);
}
return inst;
Index: common/shareddb.h
================================================== =================
--- common/shareddb.h (revision 373)
+++ common/shareddb.h (working copy)
@@ -58,8 +58,8 @@
/*
* Item Methods
*/
- ItemInst* CreateItem(uint32 item_id, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
- ItemInst* CreateItem(const Item_Struct* item, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
+ ItemInst* CreateItem(uint32 item_id, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool instnodrop = false);
+ ItemInst* CreateItem(const Item_Struct* item, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool instnodrop = false);
/*
Index: zone/PlayerCorpse.cpp
================================================== =================
--- zone/PlayerCorpse.cpp (revision 373)
+++ zone/PlayerCorpse.cpp (working copy)
@@ -293,7 +293,7 @@
sint16 interior_slot;
ItemInst *interior_item;
- AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4));
+ AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4), item->IsInstNoDrop());
if(item->IsType(ItemClassContainer))
{
for(bagindex = 0; bagindex <= 10; bagindex++)
@@ -303,7 +303,7 @@
if(interior_item)
{
- AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
+ AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4), interior_item->IsInstNoDrop());
client->DeleteItemInInventory(interior_slot);
}
}
@@ -456,7 +456,7 @@
return itemlist.size();
}
-void Corpse::AddItem(uint32 itemnum, int8 charges, sint16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) {
+void Corpse::AddItem(uint32 itemnum, int8 charges, sint16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool instnodrop) {
if (!database.GetItem(itemnum))
return;
pIsChanged = true;
@@ -470,6 +470,7 @@
item->aug3=aug3;
item->aug4=aug4;
item->aug5=aug5;
+ item->instnodrop = instnodrop;
itemlist.push_back(item);
}
@@ -822,7 +823,7 @@
item = database.GetItem(item_data->item_id);
if (client && item)
{
- ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5);
+ ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5, item_data->instnodrop);
if (inst)
{
client->SendItemPacket(i + 22, inst, ItemPacketLoot);
@@ -888,7 +889,7 @@
if (item != 0)
{
if(item_data)
- inst = database.CreateItem(item, item_data?item_data->charges:0, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5);
+ inst = database.CreateItem(item, item_data?item_data->charges:0, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5, item_data->instnodrop);
else
inst = database.CreateItem(item);
Index: zone/PlayerCorpse.h
================================================== =================
--- zone/PlayerCorpse.h (revision 373)
+++ zone/PlayerCorpse.h (working copy)
@@ -57,7 +57,7 @@
void SetDecayTimer(int32 decaytime);
bool IsEmpty() const;
- void AddItem(uint32 itemnum, int8 charges, sint16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
+ void AddItem(uint32 itemnum, int8 charges, sint16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool instnodrop=false);
uint32 GetWornItem(sint16 equipSlot) const;
ServerLootItem_Struct* GetItem(int16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void RemoveItem(int16 lootslot);
Index: zone/zonedump.h
================================================== =================
--- zone/zonedump.h (revision 373)
+++ zone/zonedump.h (working copy)
@@ -155,6 +155,7 @@
uint32 aug3;
uint32 aug4;
uint32 aug5;
+ bool instnodrop;
};
struct DBPlayerCorpse_Struct {
Theeper
03-27-2009, 06:39 PM
I got the flag to persist through bagged items now. This seems to make attuneable items work properly in my limited testing.
Here's a diff against 397.
Index: common/shareddb.cpp
================================================== =================
--- common/shareddb.cpp (revision 397)
+++ common/shareddb.cpp (working copy)
@@ -1229,7 +1229,7 @@
// Create appropriate ItemInst class
-ItemInst* SharedDatabase::CreateItem(uint32 item_id, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
+ItemInst* SharedDatabase::CreateItem(uint32 item_id, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool instnodrop)
{
const Item_Struct* item = NULL;
ItemInst* inst = NULL;
@@ -1241,6 +1241,7 @@
inst->PutAugment(this, 2, aug3);
inst->PutAugment(this, 3, aug4);
inst->PutAugment(this, 4, aug5);
+ inst->SetInstNoDrop(instnodrop);
}
@@ -1249,7 +1250,7 @@
// Create appropriate ItemInst class
-ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
+ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, sint16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool instnodrop)
{
ItemInst* inst = NULL;
if (item) {
@@ -1262,6 +1263,7 @@
inst->PutAugment(this, 3, aug4);
inst->PutAugment(this, 4, aug5);
inst->SetCharges(charges);
+ inst->SetInstNoDrop(instnodrop);
}
return inst;
Index: common/shareddb.h
================================================== =================
--- common/shareddb.h (revision 397)
+++ common/shareddb.h (working copy)
@@ -60,8 +60,8 @@
/*
* Item Methods
*/
- ItemInst* CreateItem(uint32 item_id, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
- ItemInst* CreateItem(const Item_Struct* item, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
+ ItemInst* CreateItem(uint32 item_id, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool instnodrop = false);
+ ItemInst* CreateItem(const Item_Struct* item, sint16 charges=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool instnodrop = false);
/*
Index: zone/inventory.cpp
================================================== =================
--- zone/inventory.cpp (revision 397)
+++ zone/inventory.cpp (working copy)
@@ -330,7 +330,7 @@
{
if(bag_item_data[i] == NULL)
continue;
- const ItemInst *bagitem = database.CreateItem(bag_item_data[i]->item_id, bag_item_data[i]->charges);
+ const ItemInst *bagitem = database.CreateItem(bag_item_data[i]->item_id, bag_item_data[i]->charges, bag_item_data[i]->aug1, bag_item_data[i]->aug2, bag_item_data[i]->aug3, bag_item_data[i]->aug4, bag_item_data[i]->aug5, bag_item_data[i]->instnodrop);
interior_slot = Inventory::CalcSlotId(slot_id, i);
mlog(INVENTORY__SLOTS, "Putting bag loot item %s (%d) into slot %d (bag slot %d)", inst.GetItem()->Name, inst.GetItem()->ID, interior_slot, i);
PutLootInInventory(interior_slot, *bagitem);
Index: zone/PlayerCorpse.cpp
================================================== =================
--- zone/PlayerCorpse.cpp (revision 397)
+++ zone/PlayerCorpse.cpp (working copy)
@@ -309,7 +309,7 @@
sint16 interior_slot;
ItemInst *interior_item;
- AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4));
+ AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4), item->IsInstNoDrop());
if(item->IsType(ItemClassContainer))
{
for(bagindex = 0; bagindex <= 10; bagindex++)
@@ -319,7 +319,7 @@
if(interior_item)
{
- AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
+ AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4), interior_item->IsInstNoDrop());
client->DeleteItemInInventory(interior_slot);
}
}
@@ -488,7 +488,7 @@
return itemlist.size();
}
-void Corpse::AddItem(uint32 itemnum, int8 charges, sint16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) {
+void Corpse::AddItem(uint32 itemnum, int8 charges, sint16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool instnodrop) {
if (!database.GetItem(itemnum))
return;
pIsChanged = true;
@@ -502,6 +502,7 @@
item->aug3=aug3;
item->aug4=aug4;
item->aug5=aug5;
+ item->instnodrop = instnodrop;
itemlist.push_back(item);
}
@@ -854,7 +855,7 @@
item = database.GetItem(item_data->item_id);
if (client && item)
{
- ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5);
+ ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5, item_data->instnodrop);
if (inst)
{
client->SendItemPacket(i + 22, inst, ItemPacketLoot);
@@ -920,7 +921,7 @@
if (item != 0)
{
if(item_data)
- inst = database.CreateItem(item, item_data?item_data->charges:0, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5);
+ inst = database.CreateItem(item, item_data?item_data->charges:0, item_data->aug1, item_data->aug2, item_data->aug3, item_data->aug4, item_data->aug5, item_data->instnodrop);
else
inst = database.CreateItem(item);
Index: zone/PlayerCorpse.h
================================================== =================
--- zone/PlayerCorpse.h (revision 397)
+++ zone/PlayerCorpse.h (working copy)
@@ -57,7 +57,7 @@
void SetDecayTimer(int32 decaytime);
bool IsEmpty() const;
- void AddItem(uint32 itemnum, int8 charges, sint16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
+ void AddItem(uint32 itemnum, int8 charges, sint16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, bool instnodrop=false);
uint32 GetWornItem(sint16 equipSlot) const;
ServerLootItem_Struct* GetItem(int16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void RemoveItem(int16 lootslot);
Index: zone/zonedump.h
================================================== =================
--- zone/zonedump.h (revision 397)
+++ zone/zonedump.h (working copy)
@@ -155,6 +155,7 @@
uint32 aug3;
uint32 aug4;
uint32 aug5;
+ bool instnodrop;
};
struct DBPlayerCorpse_Struct {
Zeice
05-04-2009, 10:22 AM
This is working for people in the titanium client, but not for the SoF client. Everytime I zone with an attuneable item equipped it loses it's no trade flag. I would assume that this has something to do with the titanium.cpp being edited for this but not the sof.cpp. I tried changing around closer to what was done with titanium, but I haven't had any luck so far. I'm by no means a coder so I was hoping someone could look into this?
What it looks like in titanium.
MakeAnyLenString(&instance,
"%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|",
stackable ? charges : 0,
0,
(merchant_slot==0) ? slot_id : merchant_slot,
inst->GetPrice(),
(merchant_slot==0) ? 1 : inst->GetMerchantCount(),
0,
//merchant_slot, //instance ID, bullshit for now
(merchant_slot==0) ? inst->GetSerialNumber() : merchant_slot,
0,
(stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges),
inst->IsInstNoDrop() ? 1 : 0,
0
);
What I changed in SoF.cpp (not working)
hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot;
hdr.price = inst->GetPrice();
hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount();
hdr.unknown020 = 0;
hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot;
0,
hdr.potion_type = (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges);
hdr.inst_nodrop = inst->IsInstNoDrop() ? 1 : 0;
hdr.charges = charges;
hdr.unknown040 = 0;
hdr.unknown044 = 0;
hdr.unknown048 = 0;
hdr.unknown052 = 0;
hdr.unknown056 = 0;
hdr.unknown060 = 0;
hdr.unknown061 = 0;
hdr.ItemClass = item->ItemClass;
trevius
05-04-2009, 04:25 PM
It is on the list of things left to do in SoF in the Development Tracking thread. I update it regularly so that it stays current. This is something I would like to get working. Maybe I can figure it out later. Been focusing on other things lately like AAs and such. Hadn't looked too closely at this yet, but it should just be a part of the serialization that we need to set. What you have set is probably close, but the attuned check might be in another unknown spot of the serialization. It is hard to know for sure without seeing an item from live, or just guessing at it until you get it right.
Theeper
05-04-2009, 05:19 PM
I just guessed where it was in the serialization code for Titanium since it was in the wrong spot. It took a couple tries to find the right place. I didn't bother with the serialization for SoF since I don't have it yet, and I assume the item struct is radically different.
I guess I could get off my lazy butt and buy SoF and figure it out.
realityincarnate
05-04-2009, 06:09 PM
I found the variable that is supposed to be the instance no drop flag. It's currently labelled as unknown40 in the header. I'll rename it and merge it to the SVN later tonight, but for now the quick fix is to change the serialization code to
SoF.cpp
hdr.charges = charges;
hdr.unknown040 = inst->IsInstNoDrop() ? 1 : 0;
hdr.unknown044 = 0;
Zeice
05-05-2009, 12:39 AM
Yeah, this works now. Thanks realityincarnate! Another SoF issue to cross off the list. =)
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.