This code adds a SetRestrictedLooter function on corpse objects so only the character id specified can ever loot it (disables the corpse unlock timer). Developed this around the idea of some epic 1.5 fights. Also added two new exports to EVENT_LOOT for the corpse_id being looted and the npctype id of the corpse. Example uses below code.
Code:
Index: EQEmuServer/utils/perlxs/PlayerCorpse.h
===================================================================
--- EQEmuServer/utils/perlxs/PlayerCorpse.h (revision 1989)
+++ EQEmuServer/utils/perlxs/PlayerCorpse.h (working copy)
@@ -26,3 +26,5 @@
void AllowMobLoot(Mob *them, int8 slot);
void AddLooter(Mob *who);
bool IsRezzed() { return isrezzed; }
+ void SetRestrictedLooter(int charid);
+
\ No newline at end of file
Index: EQEmuServer/zone/embparser.cpp
===================================================================
--- EQEmuServer/zone/embparser.cpp (revision 1989)
+++ EQEmuServer/zone/embparser.cpp (working copy)
@@ -635,6 +635,8 @@
ExportVar(packagename.c_str(), "looted_id", sep->arg[0]);
ExportVar(packagename.c_str(), "looted_charges", sep->arg[1]);
ExportVar(packagename.c_str(), "corpse", sep->arg[2]);
+ ExportVar(packagename.c_str(), "corpse_id", sep->arg[3]);
+ ExportVar(packagename.c_str(), "npc_id", sep->arg[4]);
safe_delete(sep);
break;
}
Index: EQEmuServer/zone/perl_PlayerCorpse.cpp
===================================================================
--- EQEmuServer/zone/perl_PlayerCorpse.cpp (revision 1989)
+++ EQEmuServer/zone/perl_PlayerCorpse.cpp (working copy)
@@ -783,6 +783,30 @@
XSRETURN(1);
}
+XS(XS_Corpse_SetRestrictedLooter); /* prototype to pass -Wmissing-prototypes */
+XS(XS_Corpse_SetRestrictedLooter)
+{
+ dXSARGS;
+ if (items != 2)
+ Perl_croak(aTHX_ "Usage: Corpse::SetRestrictedLooter(THIS, charid)");
+ {
+ Corpse * THIS;
+ int charid = (int)SvIV(ST(1));
+
+ if (sv_derived_from(ST(0), "Corpse")) {
+ IV tmp = SvIV((SV*)SvRV(ST(0)));
+ THIS = INT2PTR(Corpse *,tmp);
+ }
+ else
+ Perl_croak(aTHX_ "THIS is not of type Corpse");
+ if(THIS == NULL)
+ Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
+
+ THIS->SetRestrictedLooter(charid);
+ }
+ XSRETURN_EMPTY;
+}
+
#ifdef __cplusplus
extern "C"
#endif
@@ -832,6 +856,7 @@
newXSproto(strcpy(buf, "AllowMobLoot"), XS_Corpse_AllowMobLoot, file, "$$$");
newXSproto(strcpy(buf, "AddLooter"), XS_Corpse_AddLooter, file, "$$");
newXSproto(strcpy(buf, "IsRezzed"), XS_Corpse_IsRezzed, file, "$");
+ newXSproto(strcpy(buf, "SetRestrictedLooter"), XS_Corpse_SetRestrictedLooter, file, "$");
XSRETURN_YES;
}
Index: EQEmuServer/zone/PlayerCorpse.cpp
===================================================================
--- EQEmuServer/zone/PlayerCorpse.cpp (revision 1989)
+++ EQEmuServer/zone/PlayerCorpse.cpp (working copy)
@@ -830,6 +830,15 @@
looters[slot] = them->CastToClient()->CharacterID();
}
+void Corpse::SetRestrictedLooter(int charid)
+{
+ looters[0] = charid;
+ for(int i=1; i<MAX_LOOTERS; i++) {
+ looters[i] = 0;
+ }
+ corpse_delay_timer.Disable();
+}
+
// @merth: this function needs some work
void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) {
// Added 12/08. Started compressing loot struct on live.
@@ -1112,11 +1121,11 @@
}
}
- char buf[88];
+ char buf[104];
char corpse_name[64];
strcpy(corpse_name, orgname);
- snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name));
- buf[87] = '\0';
+ snprintf(buf, 103, "%d %d %s %d %u", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name), GetID(), GetNPCTypeID());
+ buf[103] = '\0';
parse->EventPlayer(EVENT_LOOT, client, buf, 0);
if (zone->lootvar != 0)
Index: EQEmuServer/zone/PlayerCorpse.h
===================================================================
--- EQEmuServer/zone/PlayerCorpse.h (revision 1989)
+++ EQEmuServer/zone/PlayerCorpse.h (working copy)
@@ -103,6 +103,7 @@
bool Rezzed() { return rez; }
void Rezzed(bool in_rez) { rez = in_rez; }
void Spawn();
+ void SetRestrictedLooter(int charid);
char orgname[64];
int32 GetEquipment(int8 material_slot) const; // returns item id
SetRestrictedLooter example:
Code:
my $npcid = 0;
my $character_id = undef;
sub EVENT_SPAWN {
$npcid = $npc->GetID();
}
sub EVENT_SAY {
if($text=~/hail/i) {
$character_id = $client->CharacterID();
quest::say("If I die, $name, only you may ever loot my corpse. ($character_id)");
}
}
sub EVENT_DEATH {
if(defined($character_id)) {
quest::say("I'm dead. Only the character that hailed me with character id $character_id may ever loot me.");
my $corpse_obj = $entity_list->GetCorpseByID($npcid);
if($corpse_obj) {
quest::say("got the corpse obj from $npcid");
$corpse_obj->SetRestrictedLooter($character_id);
}
}
}
EVENT_LOOT exports
Code:
sub EVENT_LOOT {
# old way to get the corpse object; have to know npc type prior
# note: $entity_list->GetCorpseByName($corpse) and $entity_list->GetMob($corpse) both fail
#my $corpse_looted_obj = undef;
#my @corpse_list = $entity_list->GetCorpseList();
#foreach $c (@corpse_list) {
# my $mob = $c->CastToMob();
# if($mob->GetNPCTypeID() == 111111) { # check if this corpse's npc type is the one we want
# $corpse_looted_obj = $c; # set the corpse object of the npc
# }
#}
# code change now exports $corpse_id and $npc_id; no need to know the npc type prior
my $corpse_looted_obj = $entity_list->GetCorpseByID($corpse_id);
if($npc_id == 111111) { #if we want to check the npc id though..
quest::say("This corpse belongs to the desired npc type");
}
if($corpse_looted_obj) {
quest::say("Looted item id: $looted_id. Placing the item back on the corpse for other players to loot");
$corpse_looted_obj->AddItem($looted_id, 0); # put the item back on the corpse
}
}