Uleat |
08-14-2012 05:49 PM |
Ok, here is everything so far diff'd off of rev 2185.
Code:
Index: client_packet.cpp
===================================================================
--- client_packet.cpp (revision 2185)
+++ client_packet.cpp (working copy)
@@ -3310,6 +3310,55 @@
return;
}
}
+
+ // Added checks for illegal bagslot swaps..should help with certain cheats (currently checks personal and cursor bag slots.)
+ // - if a player has used an illegal inventory cheat, they can lose items to bugged corpses at some point.
+ //* Start
+ bool mi_hack = false;
+
+ if (mi->from_slot >= 251 && mi->from_slot <= 340) {
+ if (mi->from_slot > 330)
+ mi_hack = true; // why are we moving from a cursor bagslot when you can't open it?
+ else {
+ sint16 from_invslot = Inventory::CalcSlotId(mi->from_slot);
+ const ItemInst *from_invslotitem = GetInv().GetItem(from_invslot);
+
+ if (!from_invslotitem) // trying to move from bag slots when parent inventory slot is empty
+ mi_hack = true;
+ else if (from_invslotitem->GetItem()->ItemClass == 1) { // checking the parent inventory slot for container
+ if ((Inventory::CalcBagIdx(mi->from_slot) + 1) > from_invslotitem->GetItem()->BagSlots)
+ mi_hack = true; // trying to move from slots beyond parent container size
+ }
+ else // trying to move from bag slots when inventory slot item is not a container
+ mi_hack = true;
+ }
+ }
+
+ if (mi->to_slot >= 251 && mi->to_slot <= 340) {
+ if (mi->to_slot > 330)
+ mi_hack = true; // why are we moving to a cursor bagslot when you can't open it?
+ else {
+ sint16 to_invslot = Inventory::CalcSlotId(mi->to_slot);
+ const ItemInst *to_invslotitem = GetInv().GetItem(to_invslot);
+
+ if (!to_invslotitem) // trying to move into bag slots when parent inventory slot is empty
+ mi_hack = true;
+ else if (to_invslotitem->GetItem()->ItemClass == 1) { // checking the parent inventory slot for container
+ if ((Inventory::CalcBagIdx(mi->to_slot) + 1) > to_invslotitem->GetItem()->BagSlots)
+ mi_hack = true; // trying to move into slots beyond parent container size
+ }
+ else // trying to move into bag slots when inventory slot item is not a container
+ mi_hack = true;
+ }
+ }
+
+ if (mi_hack) { // a CSD can also cause this condition, but more likely the use of a cheat
+ Message(13, "Hack detected: Illegal use of inventory bag slots!");
+ // TODO: Decide whether to log player as hacker - currently has no teeth...
+ // Kick();
+ // return;
+ } // End */
+
SwapItem(mi);
return;
}
Index: command.cpp
===================================================================
--- command.cpp (revision 2185)
+++ command.cpp (working copy)
@@ -456,7 +456,8 @@
command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", 0, command_sensetrap) ||
command_add("picklock", "Analog for ldon pick lock for the newer clients since we still don't have it working.", 0, command_picklock) ||
command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) ||
- command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", 250, command_xtargets)
+ command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", 250, command_xtargets) ||
+ command_add("zopp", "Troubleshooting command - Sends a fake item packet to you. No server reference is created.", 250, command_zopp)
)
{
command_deinit();
@@ -3035,15 +3036,17 @@
item = (inst) ? inst->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "WornSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
}
}
@@ -3055,15 +3058,17 @@
item = (inst) ? inst->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
if (inst && inst->IsType(ItemClassContainer)) {
@@ -3072,17 +3077,19 @@
item = (instbag) ? instbag->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:instbag->GetCharges()));
}
else
{
- c->Message((item==0), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:instbag->GetCharges()));
}
}
}
@@ -3091,50 +3098,73 @@
{
const ItemInst* inst = client->GetInv().GetItem(9999);
item = (inst) ? inst->GetItem() : NULL;
- c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", 9999,
+ c->Message((item==0), "InvSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", 9999,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
}
+
+ // Changed to show 'empty' cursors and not to show bag slots on 'queued' cursor slots (cursor bag slots 331 to 340 are not arrayed...)
+ // - was pointless to show bags on anything after slot 30[0], because it only repeated the 30[0] bag items.
if (bAll || (strcasecmp(sep->arg[1], "cursor")==0)) {
// Personal inventory items
bFound = true;
iter_queue it;
int i=0;
- for(it=client->GetInv().cursor_begin();it!=client->GetInv().cursor_end();it++,i++) {
- const ItemInst* inst = *it;
- item = (inst) ? inst->GetItem() : NULL;
+
+ if(client->GetInv().CursorEmpty()) { // Display 'front' cursor slot even if 'empty' (item(30[0]) == null)
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", SLOT_CURSOR,i,
- ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+ 0, 0x12, 0, "null", 0x12, 0);
}
else
{
- c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", SLOT_CURSOR,i,
- ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+ 0, 0x12, 0, "null", 0x12, 0);
}
+ }
+ else {
+ for(it=client->GetInv().cursor_begin();it!=client->GetInv().cursor_end();it++,i++) {
+ const ItemInst* inst = *it;
+ item = (inst) ? inst->GetItem() : NULL;
+ if (c->GetClientVersion() >= EQClientSoF)
+ {
+ c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+ ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
+ }
+ else
+ {
+ c->Message((item==0), "CursorSlot: %i, Depth: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", SLOT_CURSOR,i,
+ ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
+ }
- if (inst && inst->IsType(ItemClassContainer)) {
- for (uint8 j=0; j<10; j++) {
- const ItemInst* instbag = client->GetInv().GetItem(SLOT_CURSOR, j);
- item = (instbag) ? instbag->GetItem() : NULL;
- if (c->GetClientVersion() >= EQClientSoF)
- {
- c->Message((item==0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
- Inventory::CalcSlotId(SLOT_CURSOR, j),
- SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ if (inst && inst->IsType(ItemClassContainer) && i==0) { // only display contents of slot 30[0] container..higher ones don't exist
+ for (uint8 j=0; j<10; j++) {
+ const ItemInst* instbag = client->GetInv().GetItem(SLOT_CURSOR, j);
+ item = (instbag) ? instbag->GetItem() : NULL;
+ if (c->GetClientVersion() >= EQClientSoF)
+ {
+ c->Message((item==0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
+ Inventory::CalcSlotId(SLOT_CURSOR, j),
+ SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:instbag->GetCharges()));
+ }
+ else
+ {
+ c->Message((item==0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
+ Inventory::CalcSlotId(SLOT_CURSOR, j),
+ SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:instbag->GetCharges()));
+ }
}
- else
- {
- c->Message((item==0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
- Inventory::CalcSlotId(SLOT_CURSOR, j),
- SLOT_CURSOR, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
- }
}
}
}
@@ -3148,15 +3178,17 @@
item = (inst) ? inst->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "TributeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
}
}
@@ -3170,15 +3202,17 @@
item = (inst) ? inst->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "BankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
if (inst && inst->IsType(ItemClassContainer)) {
@@ -3187,17 +3221,19 @@
item = (instbag) ? instbag->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
}
}
@@ -3207,15 +3243,17 @@
item = (inst) ? inst->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "ShBankSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
if (inst && inst->IsType(ItemClassContainer)) {
@@ -3224,17 +3262,19 @@
item = (instbag) ? instbag->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), " ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), " ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " ShBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
}
}
@@ -3248,15 +3288,17 @@
item = (inst) ? inst->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c)", i,
+ c->Message((item==0), "TradeSlot: %i, Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i", i,
((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
if (inst && inst->IsType(ItemClassContainer)) {
@@ -3265,17 +3307,19 @@
item = (instbag) ? instbag->GetItem() : NULL;
if (c->GetClientVersion() >= EQClientSoF)
{
- c->Message((item==0), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X00000000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
else
{
- c->Message((item==0), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c)",
+ c->Message((item==0), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%c%06X000000000000000000000000000000000000000%s%c), Charges: %i",
Inventory::CalcSlotId(i, j),
i, j, ((item==0)?0:item->ID),0x12, ((item==0)?0:item->ID),
- ((item==0)?"null":item->Name), 0x12);
+ ((item==0)?"null":item->Name), 0x12,
+ ((item==0)?0:inst->GetCharges()));
}
}
@@ -3286,7 +3330,7 @@
if (!bFound)
{
c->Message(0, "Usage: #peekinv [worn|cursor|inv|bank|trade|trib|all]");
- c->Message(0, " Displays a portion of the targetted user's inventory");
+ c->Message(0, " Displays a portion of the targeted user's inventory");
c->Message(0, " Caution: 'all' is a lot of information!");
}
}
@@ -3727,6 +3771,12 @@
else
c->Message(0, "Insufficient status to modify player corpse.");
}
+ else if (strcasecmp(sep->arg[1], "InspectLoot") == 0) {
+ if (target == 0 || !target->IsCorpse())
+ c->Message(0, "Error: Target must be a corpse.");
+ else
+ target->CastToCorpse()->QueryLoot(c);
+ }
else if (strcasecmp(sep->arg[1], "lock") == 0) {
if (target == 0 || !target->IsCorpse())
c->Message(0, "Error: Target must be a corpse.");
@@ -3777,6 +3827,7 @@
c->Message(0, " Lock - GM locks the corpse - cannot be looted by non-GM");
c->Message(0, " UnLock");
c->Message(0, " RemoveCash");
+ c->Message(0, " InspectLoot");
c->Message(0, " [to remove items from corpses, loot them]");
c->Message(0, "Lead-GM status required to delete/modify player corpses");
c->Message(0, " DeletePlayerCorpses");
@@ -11529,3 +11580,40 @@
else
t->ShowXTargets(c);
}
+
+void command_zopp(Client *c, const Seperator *sep)
+{ // - Owner only command..non-targetable to eliminate malicious or mischievious activities.
+ if (!c)
+ return;
+ if (sep->argnum < 2 || sep->argnum > 3)
+ c->Message(0, "Usage: #zopp [slot id] [item id] [*charges]");
+ else if (!sep->IsNumber(1) || !sep->IsNumber(2) || (sep->argnum == 3 && !sep->IsNumber(3)))
+ c->Message(0, "Usage: #zopp [slot id] [item id] [*charges]");
+ else {
+ sint16 slotid = atoi(sep->arg[1]);
+ int32 itemid = atoi(sep->arg[2]);
+ sint16 charges = sep->argnum == 3 ? atoi(sep->arg[3]) : 1; // defaults to 1 charge if not specified
+
+ const Item_Struct* FakeItem = database.GetItem(itemid);
+
+ if (!FakeItem) {
+ c->Message(13, "Error: Item [%u] is not a valid item id.", itemid);
+ return;
+ }
+
+ if (database.GetItemStatus(itemid) > c->Admin()) {
+ c->Message(13, "Error: Insufficient status to use this command.");
+ return;
+ }
+
+ if (charges < 0 || charges > FakeItem->StackSize) {
+ c->Message(13, "Warning: The specified charge count does not meet expected criteria!");
+ c->Message(0, "Processing request..results may cause unpredictable behavior.");
+ }
+
+ ItemInst* FakeItemInst = database.CreateItem(FakeItem, charges);
+ c->SendItemPacket(slotid, FakeItemInst, ItemPacketTrade);
+ c->Message(0, "Sending zephyr op packet to client - %s (%u) with %i %s to slot %i.", FakeItem->Name, itemid, charges, abs(charges==1)?"charge":"charges", slotid);
+ safe_delete(FakeItemInst);
+ }
+}
\ No newline at end of file
Index: command.h
===================================================================
--- command.h (revision 2185)
+++ command.h (working copy)
@@ -320,6 +320,7 @@
void command_qtest(Client *c, const Seperator *sep);
void command_mysql(Client *c, const Seperator *sep);
void command_xtargets(Client *c, const Seperator *sep);
+void command_zopp(Client *c, const Seperator *sep);
#ifdef EMBPERL
void command_embperl_plugin(Client *c, const Seperator *sep);
Index: inventory.cpp
===================================================================
--- inventory.cpp (revision 2185)
+++ inventory.cpp (working copy)
@@ -222,6 +222,14 @@
inst->SetCharges(1);
if ((inst->GetCharges()>0))
inst->SetCharges(inst->GetCharges());
+
+ // Added reduction of overcharged items to maximum stacksize
+ if ((inst->GetCharges()>inst->GetItem()->StackSize)) {
+ inst->SetCharges(inst->GetItem()->StackSize);
+ Message(0, "Your summoned item is charged beyond maximum allowable - adjusting to %i charges.", inst->GetCharges());
+ }
+
+ // Corrected the augment references to reflect augment name/id instead of base item name/id
if (aug1) {
const Item_Struct* augitem1 = database.GetItem(aug1);
if (augitem1) {
@@ -229,7 +237,7 @@
inst->PutAugment(&database, 0, aug1);
}
else {
- Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+ Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem1->Name, aug1);
}
}
}
@@ -240,7 +248,7 @@
inst->PutAugment(&database, 1, aug2);
}
else {
- Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+ Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem2->Name, aug2);
}
}
}
@@ -251,7 +259,7 @@
inst->PutAugment(&database, 2, aug3);
}
else {
- Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+ Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem3->Name, aug3);
}
}
}
@@ -262,7 +270,7 @@
inst->PutAugment(&database, 3, aug4);
}
else {
- Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+ Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem4->Name, aug4);
}
}
}
@@ -273,7 +281,7 @@
inst->PutAugment(&database, 4, aug5);
}
else {
- Message(0, "You already have a %s (%i) in your inventory!", item->Name, item_id);
+ Message(0, "You already have a %s (%u) in your inventory - Augment not added!", augitem5->Name, aug5);
}
}
}
@@ -397,9 +405,11 @@
LogFile->write(EQEMuLog::Debug, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false");
#endif
+ // Added 'IsSlotValid(slot_id)' check to both segments of client packet processing.
+ // - cursor queue slots were slipping through and crashing client
if(!m_inv[slot_id]) {
// Make sure the client deletes anything in this slot to match the server.
- if(client_update) {
+ if(client_update && IsValidSlot(slot_id)) {
EQApplicationPacket* outapp;
outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
@@ -427,7 +437,7 @@
database.SaveInventory(character_id, inst, slot_id);
}
- if(client_update) {
+ if(client_update && IsValidSlot(slot_id)) {
EQApplicationPacket* outapp;
if(inst) {
if(!inst->IsStackable() && !isDeleted)
Index: PlayerCorpse.cpp
===================================================================
--- PlayerCorpse.cpp (revision 2185)
+++ PlayerCorpse.cpp (working copy)
@@ -353,6 +353,8 @@
pp->gold = 0;
pp->platinum = 0;
+ // 'RespawnFromHover = true' adversely affects client money removal. Server amount remains correct.
+
// get their tints
memcpy(item_tint, &client->GetPP().item_tint, sizeof(item_tint));
@@ -367,23 +369,28 @@
item = client->GetInv().GetItem(i);
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
{
- MoveItemToCorpse(client, item, i);
- removed_list.push_back(i);
+ removed_list.merge(MoveItemToCorpse(client, item, i));
}
}
- // cursor queue
- iter_queue it;
- for(it=client->GetInv().cursor_begin(),i=8000; it!=client->GetInv().cursor_end(); it++,i++) {
- item = *it;
- if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
- {
- MoveItemToCorpse(client, item, i);
- cursor = true;
+ // cursor queue // change to first client that supports 'death hover' mode, if not SoF.
+ if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < EQClientSoF) {
+
+ // bumped starting assignment to 8001 because any in-memory 'slot 8000' item was moved above as 'slot 30'
+ // this was mainly for client profile state reflection..should match db player inventory entries now.
+
+ iter_queue it;
+ for(it=client->GetInv().cursor_begin(),i=8001; it!=client->GetInv().cursor_end(); it++,i++) {
+ item = *it;
+ if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
+ {
+ removed_list.merge(MoveItemToCorpse(client, item, i));
+ cursor = true;
+ }
}
}
- if(removed_list.size() != 0) {
+ if(removed_list.size() != 0) {
std::stringstream ss("");
ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID();
ss << " AND (";
@@ -401,14 +408,18 @@
ss << ")";
database.RunQuery(ss.str().c_str(), ss.str().length());
}
-
- if(cursor) {
- std::list<ItemInst*>::const_iterator start = client->GetInv().cursor_begin();
- std::list<ItemInst*>::const_iterator finish = client->GetInv().cursor_end();
- database.SaveCursor(client->CharacterID(),
- start, finish);
+
+ if(cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
+ while(!client->GetInv().CursorEmpty())
+ client->DeleteItemInInventory(SLOT_CURSOR, 0, false, false);
}
+ else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
+ std::list<ItemInst*>::const_iterator start = client->GetInv().cursor_begin();
+ std::list<ItemInst*>::const_iterator finish = client->GetInv().cursor_end();
+ database.SaveCursor(client->CharacterID(), start, finish);
+ }
+ // client->CalcBonuses(); // will only affect offline profile viewing of dead characters..unneeded overhead
client->Save();
} //end "not leaving naked corpses"
@@ -417,28 +428,35 @@
}
// solar: helper function for client corpse constructor
-void Corpse::MoveItemToCorpse(Client *client, ItemInst *item, sint16 equipslot)
+std::list<uint32> Corpse::MoveItemToCorpse(Client *client, ItemInst *item, sint16 equipslot)
{
int bagindex;
sint16 interior_slot;
ItemInst *interior_item;
+ std::list<uint32> returnlist;
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))
+ returnlist.push_back(equipslot);
+
+ // Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
+ if(item->IsType(ItemClassContainer) && ((equipslot >= 22 && equipslot <=30))) // Limit the bag check to inventory and cursor slots.
{
for(bagindex = 0; bagindex <= 10; bagindex++)
{
+ // For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
interior_item = client->GetInv().GetItem(interior_slot);
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));
+ returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
client->DeleteItemInInventory(interior_slot, 0, true, false);
}
}
}
client->DeleteItemInInventory(equipslot, 0, true, false);
+ return returnlist;
}
// To be called from LoadFromDBData
@@ -981,19 +999,41 @@
ItemList::iterator cur,end;
cur = itemlist.begin();
end = itemlist.end();
+
+ int corpselootlimit = 30; // 30 is the original value // con check value in QueryLoot needs to reflect this value
+
+ /* need actual corpse limit values per client (or client range)..if always 30, then these con checks are unneeded
+ // enumeration shouldn't be needed unless someone finds a use for this info elsewhere
+
+ if (client->GetClientVersion()>=EQClientVoA)
+ corpselootlimit=30;
+ else if (client->GetClientVersion()>=EQClientHoT)
+ corpselootlimit=30;
+ else if (client->GetClientVersion()>=EQClientUnderfoot)
+ corpselootlimit=30;
+ else if (client->GetClientVersion()>=EQClientSoD)
+ corpselootlimit=30;
+ else if (client->GetClientVersion()>=EQClientSoF) // SoF has 32 visible slots..change untested
+ corpselootlimit=30;
+ else if (client->GetClientVersion()>=EQClientTitanium)
+ corpselootlimit=30;
+ else if (client->GetClientVersion()>=EQClient62)
+ corpselootlimit=30;
+ else
+ corpselootlimit=30; // */
+
for(; cur != end; cur++) {
ServerLootItem_Struct* item_data = *cur;
item_data->lootslot = 0xFFFF;
+
+ // Dont display the item if it's in a bag
- // Dont display the item if it's in a bag
- if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || tCanLoot>=3)
+ // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
+ if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || tCanLoot>=3 ||
+ (item_data->equipSlot >= 8000 && item_data->equipSlot <= 8999))
{
- if (i >= 30)
+ if (i < corpselootlimit) // < 30 (0 - 29)
{
- Message(13, "Warning: Too many items to display. Loot some then re-loot the corpse to see the rest");
- }
- else
- {
item = database.GetItem(item_data->item_id);
if (client && item)
{
@@ -1006,9 +1046,24 @@
item_data->lootslot = i;
}
}
+ else if (i == corpselootlimit) // = 30
+ {
+ client->Message(13, "*** This corpse contains more items than can be displayed! ***");
+ client->Message(0, "Remove items and re-loot corpse to access remaining inventory.");
+ }
i++;
}
}
+ if (i > corpselootlimit) // > 30 (remember 'i' is increased again after the last iteration, so no '=')
+ client->Message(0, "(%s contains %i additional %s.)", GetName(), (i-corpselootlimit), (i-corpselootlimit)==1?"item":"items");
+
+ if (IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, corpse contains items, but client doesn't see them...
+ client->Message(13, "This corpse contains items that you do not have permission to access!");
+ client->Message(0, "Contact a GM for assistance to see if item replacement is necessary.");
+ client->Message(0, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetDBID(), GetName(), itemlist.size());
+ // if needed/wanted - create log dump->iterate corpse list..need pointer to log file
+ // could add code to check for owning client and give list of bugged items on corpse
+ }
}
// Disgrace: Client seems to require that we send the packet back...
@@ -1296,7 +1351,7 @@
}
void Corpse::QueryLoot(Client* to) {
- int x = 0;
+ int x = 0, y = 0; // x = visible items, y = total items
to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper);
ItemList::iterator cur,end;
@@ -1304,14 +1359,44 @@
end = itemlist.end();
for(; cur != end; cur++) {
ServerLootItem_Struct* sitem = *cur;
- const Item_Struct* item = database.GetItem(sitem->item_id);
- if (item)
- to->Message(0, " %d: %s", item->ID, item->Name);
- else
- to->Message(0, " Error: 0x%04x", sitem->item_id);
- x++;
+
+ if (IsPlayerCorpse()) {
+ if (sitem->equipSlot >= 251 && sitem->equipSlot <= 340)
+ sitem->lootslot = 0xFFFF;
+ else
+ x < 30 ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; // this con value needs to reflect corpselootlimit in MakeLootRequestPackets
+
+ const Item_Struct* item = database.GetItem(sitem->item_id);
+
+ if (item)
+ to->Message((sitem->lootslot == 0xFFFF), " LootSlot: %i (EquipSlot: %i) Item: %s (%d) with %i %s", sitem->lootslot, sitem->equipSlot, item->Name, item->ID, sitem->charges, sitem->charges==1?"charge":"charges");
+ else
+ to->Message((sitem->lootslot == 0xFFFF), " Error: 0x%04x", sitem->item_id);
+
+ if (sitem->lootslot != 0xFFFF)
+ x++;
+
+ y++;
+ }
+ else {
+ sitem->lootslot=y;
+ const Item_Struct* item = database.GetItem(sitem->item_id);
+
+ if (item)
+ to->Message(0, " LootSlot: %i Item: %s (%d) with %i %s", sitem->lootslot, item->Name, item->ID, sitem->charges, sitem->charges==1?"charge":"charges");
+ else
+ to->Message(0, " Error: 0x%04x", sitem->item_id);
+
+ y++;
+ }
}
- to->Message(0, "%i items on %s.", x, this->GetName());
+
+ if (IsPlayerCorpse()) {
+ to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetDBID());
+ }
+ else {
+ to->Message(0, "%i %s on %s.", y, y==1?"item":"items", this->GetName());
+ }
}
bool Corpse::Summon(Client* client, bool spell, bool CheckDistance)
Index: PlayerCorpse.h
===================================================================
--- PlayerCorpse.h (revision 2185)
+++ PlayerCorpse.h (working copy)
@@ -111,7 +111,7 @@
inline int GetRezzExp() { return rezzexp; }
protected:
- void MoveItemToCorpse(Client *client, ItemInst *item, sint16 equipslot);
+ std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, sint16 equipslot);
private:
bool p_PlayerCorpse;
No more updates to this portion of code unless I, or someone else, finds a major flaw in it.
I can post test procedures if anyone needs specific criteria.
|