Go Back   EQEmulator Home > EQEmulator Forums > Quests > Quests::Q&A

Quests::Q&A This is the quest support section

Reply
 
Thread Tools Display Modes
  #1  
Old 02-15-2012, 03:05 PM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default $corpse->RemoveItem($slotID) issue

Any suggestions as to why RemoveItem() might not work on an NPC corpse? I'm trying to delete the last item the NPC was manually given after spawning and having it killed using a line such as this one:

$corpse->RemoveItem($corpse->CountItems());

I'm currently using $corpse->Delete() to keep the item in question from being retrieved, but I'd like to be able to keep the original loot generated upon spawning.

NOTE:
I've looked in the source and nothing is really standing out to indicate I'm way off base in my understanding of how this function should work.
Reply With Quote
  #2  
Old 02-15-2012, 08:32 PM
pfyon's Avatar
pfyon
Discordant
 
Join Date: Mar 2009
Location: Ottawa
Posts: 495
Default

I haven't looked at the documentation for the perl function or the source, but are items enumerated from 0? If so, you might need something like

Code:
$corpse->RemoveItem($corpse->CountItems() - 1);
to remove the last item (since item 1 is at index 0, last item would be at index -1).
Reply With Quote
  #3  
Old 02-15-2012, 08:48 PM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default

yeah, sorry. i guess i forgot to mention that i've tried that as well before posting my question.
Reply With Quote
  #4  
Old 02-16-2012, 01:12 AM
Noport
Opcode Ninja
 
Join Date: Mar 2009
Location: San francisco
Posts: 426
Default

just for grins try this opcode OP_LootComplete=0x528f see if that helps
Reply With Quote
  #5  
Old 02-16-2012, 01:37 AM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default

Quote:
Originally Posted by Noport View Post
just for grins try this opcode OP_LootComplete=0x528f see if that helps
while i've not used perl to send packets to clients, i'm not sure how it would help in this case. please explain.

UPDATE: i wrote the following test plugin to make absolutely certain the issue wasn't with the slot numbers

Code:
sub DeleteAllLoot {

    my $corpse      = NULL;
    my $npc         = plugin::val('$npc');
    my $entity_list = plugin::val('$entity_list');

    foreach $corpse ($entity_list->GetCorpseList()) {
        if ($corpse->GetOwnerName() eq $npc->GetName() && $corpse->CountItems()) {
            for (my $slot = 0; $slot >= $corpse->CountItems(); $slot++) {
                $corpse->RemoveItem($slot);
            }
            return 1;
        }
    }

    return 0;

}
i know it's finding the correct corpse, but RemoveItem() is not deleting any items from NPC corpses.
Reply With Quote
  #6  
Old 02-16-2012, 02:46 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,742
Default

Well, let's look at the code, it's pretty short and simple.

Code:
void Corpse::RemoveItem(int16 lootslot)
{

	if (lootslot == 0xFFFF)
		return;
	
	ItemList::iterator cur,end;
	cur = itemlist.begin();
	end = itemlist.end();
	for(; cur != end; cur++) {
		ServerLootItem_Struct* sitem = *cur;
		if (sitem->lootslot == lootslot)
		{
			RemoveItem(sitem);
			return;
		}
	}
}
Ok, it's looking for the slot number you pass in to match the lootslot on the ServerLootItem. So, let's look where that is assigned.

The only place I can see is Corpse::MakeLootRequestPackets where it is assigned 0xFFFF, and then a few lines later to a sequential value.

That function appears to be called when someone actually clicks on a corpse to loot it which may be later than you run your perl code.

NPC::AddLootDrop seems like a logical place to assign a value to ServerLootItem_Struct::lootslot, but I didn't see anything in there that would do so. ServerLootItem_Struct has no constructor, so what ends up in there by default is probably uninitialized garbage of some sort.

Short answer is I would guess that function isn't all that useful the way it is now. Maybe it should just take an index into the list of items and delete that index which is what it seems you want. Even if the code you're using is in EVENT_LOOT, I'm not sure it's possible to prevent the current item from being looted by deleting it, but that's just my guess.
Reply With Quote
  #7  
Old 02-16-2012, 04:16 AM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default

well hell, that makes PERFECT sense. now i'm not sure why the function was exposed to perl at all. i can't wrap my head around how it would be used. i'm going to go to sleep and see if i can't sort something out tomorrow. looks like the only way to do what i'm trying to do is to modify the source. i was trying to avoid that, but oh well. thanks.
Reply With Quote
  #8  
Old 02-16-2012, 04:22 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

If you are trying to delete items from the NPC when it dies during EVENT_DEATH or something like that directly on the NPC's perl script, you will need to be using $npc commands, not $corpse stuff. At that time, I don't think the $corpse entity exists yet for that NPC.

Under the NPC class, there is this quest object:
Code:
RemoveItem(item_id, quantity= 0, slot= 0)
Unfortunately, I don't see any quest object yet to find items or item slots on an NPC. One could certainly be created though easy enough I am sure. But, in the mean-time, if you know the item IDs that you want to delete, you could just do a for loop through each possible slot 0 to 25 or something and try to delete the item you want deleted. If you don't know what item ID that would be, it may get a little more complicated. You would just need to create an array of item IDs when someone hands items to the NPC then just run the for loop on each item ID in that array. Should work fine.

Removing it from the corpse itself would probably be easier, but you would need to do it from something like player.pl or something. Since you can't really use EVENT_LOOT for that (I don't think), you may just need to send a signal to another NPC when the main NPC is killed and then have a timer that waits a second (to allow the corpse to be created) then searches all corpses and removes those items at that time.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #9  
Old 02-16-2012, 04:39 AM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default

EVENT_DEATH is parsed after the corpse created and the npc is removed from the entity list, at the tail end of NPC:eath(). the corpse's item list would already have been populated at that point. i'm probably going to have to add a function such as $corpse->RemoveItemByID() to be able to do what i'm looking to do. i'll have the item id stored in the script for the npc that i'll need to delete from the corpse. working on a method to generate random loot for npcs on spawn (in addition to normal loot table drops) and means to delete said randomly generated loot if the kill was trivial to anyone on the npc's hate list on death. everything else is working flawlessly except for this one part. for the time being, i have the corpse poofing entirely, but i'd rather just remove the one item.

EDIT:
hmmm... i guess i could always cause the item to poof after it was looted in EVENT_LOOT via player.pl, but that'd surely cause an uproar from the player base. haha.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 01:41 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3