Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime) // vesuvias - appearence fix : Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),BT_Humanoid,//bodytype added in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0, in_npc->GetPosition(), in_npc->GetInnateLightValue(), in_npc->GetTexture(),in_npc->GetHelmTexture(), 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0), corpse_decay_timer(in_decaytime), corpse_rez_timer(0), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), corpse_graveyard_timer(0), loot_cooldown_timer(10) { corpse_graveyard_timer.Disable(); memset(item_tint, 0, sizeof(item_tint)); is_corpse_changed = false; is_player_corpse = false; is_locked = false; being_looted_by = 0xFFFFFFFF; if (in_itemlist) { itemlist = *in_itemlist; in_itemlist->clear(); } SetCash(in_npc->GetCopper(), in_npc->GetSilver(), in_npc->GetGold(), in_npc->GetPlatinum()); npctype_id = in_npctypeid; SetPlayerKillItemID(0); char_id = 0; corpse_db_id = 0; player_corpse_depop = false; strcpy(corpse_name, in_npc->GetName()); strcpy(name, in_npc->GetName()); for(int count = 0; count < 100; count++) { if ((level >= npcCorpseDecayTimes[count].minlvl) && (level <= npcCorpseDecayTimes[count].maxlvl)) { corpse_decay_timer.SetTimer(npcCorpseDecayTimes[count].seconds*1000); break; } } if(IsEmpty()) { corpse_decay_timer.SetTimer(RuleI(NPC,EmptyNPCCorpseDecayTimeMS)+1000); } if(in_npc->HasPrivateCorpse()) { corpse_delay_timer.SetTimer(corpse_decay_timer.GetRemainingTime() + 1000); } for (int i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } this->rez_experience = 0; UpdateEquipLightValue(); spell_light = NOT_USED; UpdateActiveLightValue(); }
// To be called from LoadFromDBData Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const glm::vec4& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture,uint32 in_rezexp, bool wasAtGraveyard) : Mob("Unnamed_Corpse", "", 0, 0, in_gender, in_race, in_class, BT_Humanoid, in_deity, in_level, 0, in_size, 0, position, 0, // verified for client innate_light value in_texture, in_helmtexture, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)), loot_cooldown_timer(10) { LoadPlayerCorpseDecayTime(in_dbid); if (!zone->HasGraveyard() || wasAtGraveyard) corpse_graveyard_timer.Disable(); memset(item_tint, 0, sizeof(item_tint)); is_corpse_changed = false; is_player_corpse = true; is_locked = false; being_looted_by = 0xFFFFFFFF; corpse_db_id = in_dbid; player_corpse_depop = false; char_id = in_charid; itemlist = *in_itemlist; in_itemlist->clear(); strcpy(corpse_name, in_charname); strcpy(name, in_charname); this->copper = in_copper; this->silver = in_silver; this->gold = in_gold; this->platinum = in_plat; rez_experience = in_rezexp; for (int i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } SetPlayerKillItemID(0); UpdateEquipmentLight(); m_Light.Level.Spell = m_Light.Type.Spell = 0; UpdateActiveLight(); }
Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( "Unnamed_Corpse", // const char* in_name, "", // const char* in_lastname, 0, // int32 in_cur_hp, 0, // int32 in_max_hp, client->GetGender(), // uint8 in_gender, client->GetRace(), // uint16 in_race, client->GetClass(), // uint8 in_class, BT_Humanoid, // bodyType in_bodytype, client->GetDeity(), // uint8 in_deity, client->GetLevel(), // uint8 in_level, 0, // uint32 in_npctype_id, client->GetSize(), // float in_size, 0, // float in_runspeed, client->GetPosition(), client->GetInnateLightType(), // uint8 in_light, - verified for client innate_light value client->GetTexture(), // uint8 in_texture, client->GetHelmTexture(), // uint8 in_helmtexture, 0, // uint16 in_ac, 0, // uint16 in_atk, 0, // uint16 in_str, 0, // uint16 in_sta, 0, // uint16 in_dex, 0, // uint16 in_agi, 0, // uint16 in_int, 0, // uint16 in_wis, 0, // uint16 in_cha, client->GetPP().haircolor, // uint8 in_haircolor, client->GetPP().beardcolor, // uint8 in_beardcolor, client->GetPP().eyecolor1, // uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? client->GetPP().eyecolor2, // uint8 in_eyecolor2, client->GetPP().hairstyle, // uint8 in_hairstyle, client->GetPP().face, // uint8 in_luclinface, client->GetPP().beard, // uint8 in_beard, client->GetPP().drakkin_heritage, // uint32 in_drakkin_heritage, client->GetPP().drakkin_tattoo, // uint32 in_drakkin_tattoo, client->GetPP().drakkin_details, // uint32 in_drakkin_details, 0, // uint32 in_armor_tint[_MaterialCount], 0xff, // uint8 in_aa_title, 0, // uint8 in_see_invis, // see through invis 0, // uint8 in_see_invis_undead, // see through invis vs. undead 0, // uint8 in_see_hide, 0, // uint8 in_see_improved_hide, 0, // int32 in_hp_regen, 0, // int32 in_mana_regen, 0, // uint8 in_qglobal, 0, // uint8 in_maxlevel, 0, // uint32 in_scalerate 0, // uint8 in_armtexture, 0, // uint8 in_bracertexture, 0, // uint8 in_handtexture, 0, // uint8 in_legtexture, 0 // uint8 in_feettexture, ), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)), loot_cooldown_timer(10) { int i; PlayerProfile_Struct *pp = &client->GetPP(); ItemInst *item; /* Check if Zone has Graveyard First */ if(!zone->HasGraveyard()) { corpse_graveyard_timer.Disable(); } memset(item_tint, 0, sizeof(item_tint)); for (i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } is_corpse_changed = true; rez_experience = in_rezexp; can_corpse_be_rezzed = true; is_player_corpse = true; is_locked = false; being_looted_by = 0xFFFFFFFF; char_id = client->CharacterID(); corpse_db_id = 0; player_corpse_depop = false; copper = 0; silver = 0; gold = 0; platinum = 0; strcpy(corpse_name, pp->name); strcpy(name, pp->name); /* become_npc was not being initialized which led to some pretty funky things with newly created corpses */ become_npc = false; SetPlayerKillItemID(0); /* Check Rule to see if we can leave corpses */ if(!RuleB(Character, LeaveNakedCorpses) || RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) { // cash // Let's not move the cash when 'RespawnFromHover = true' && 'client->GetClientVersion() < EQClientSoF' since the client doesn't. // (change to first client that supports 'death hover' mode, if not SoF.) if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < ClientVersion::SoF) { SetCash(pp->copper, pp->silver, pp->gold, pp->platinum); pp->copper = 0; pp->silver = 0; pp->gold = 0; pp->platinum = 0; } // get their tints memcpy(item_tint, &client->GetPP().item_tint, sizeof(item_tint)); // TODO soulbound items need not be added to corpse, but they need // to go into the regular slots on the player, out of bags std::list<uint32> removed_list; for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; ++i) { if(i == MainAmmo && client->GetClientVersion() >= ClientVersion::SoF) { item = client->GetInv().GetItem(MainPowerSource); if (item != nullptr) { if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent)) MoveItemToCorpse(client, item, MainPowerSource, removed_list); } } item = client->GetInv().GetItem(i); if (item == nullptr) { continue; } if(!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent)) MoveItemToCorpse(client, item, i, removed_list); } database.TransactionBegin(); // I have an untested process that avoids this snarl up when all possessions inventory is removed..but this isn't broke if (!removed_list.empty()) { std::stringstream ss(""); ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID(); ss << " AND ("; std::list<uint32>::const_iterator iter = removed_list.begin(); bool first = true; while (iter != removed_list.end()) { if (first) { first = false; } else { ss << " OR "; } ss << "slotid=" << (*iter); ++iter; } ss << ")"; database.QueryDatabase(ss.str().c_str()); } auto start = client->GetInv().cursor_cbegin(); auto finish = client->GetInv().cursor_cend(); database.SaveCursor(client->CharacterID(), start, finish); client->CalcBonuses(); client->Save(); IsRezzed(false); Save(); database.TransactionCommit(); UpdateEquipmentLight(); UpdateActiveLight(); return; } //end "not leaving naked corpses" UpdateEquipmentLight(); UpdateActiveLight(); IsRezzed(false); Save(); }
void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* This gets sent no matter what as a sort of ACK */ client->QueuePacket(app); if (!loot_cooldown_timer.Check()) { SendEndLootErrorPacket(client); //unlock corpse for others if (this->being_looted_by = client->GetID()) { being_looted_by = 0xFFFFFFFF; } return; } /* To prevent item loss for a player using 'Loot All' who doesn't have inventory space for all their items. */ if (RuleB(Character, CheckCursorEmptyWhenLooting) && !client->GetInv().CursorEmpty()) { client->Message(13, "You may not loot an item while you have an item on your cursor."); SendEndLootErrorPacket(client); /* Unlock corpse for others */ if (this->being_looted_by = client->GetID()) { being_looted_by = 0xFFFFFFFF; } return; } LootingItem_Struct* lootitem = (LootingItem_Struct*)app->pBuffer; if (this->being_looted_by != client->GetID()) { client->Message(13, "Error: Corpse::LootItem: BeingLootedBy != client"); SendEndLootErrorPacket(client); return; } if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) { client->Message(13, "Error: This is a player corpse and you dont own it."); SendEndLootErrorPacket(client); return; } if (is_locked && client->Admin() < 100) { SendLootReqErrorPacket(client, 0); client->Message(13, "Error: Corpse locked by GM."); return; } if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){ client->Message(13, "Error: You cannot loot any more items from this corpse."); SendEndLootErrorPacket(client); being_looted_by = 0xFFFFFFFF; return; } const Item_Struct* item = 0; ItemInst *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; memset(bag_item_data, 0, sizeof(bag_item_data)); if (GetPlayerKillItem() > 1){ item = database.GetItem(GetPlayerKillItem()); } else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){ item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward } else{ item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN, bag_item_data); } if (GetPlayerKillItem()<=1 && item_data != 0) { item = database.GetItem(item_data->item_id); } if (item != 0) { if (item_data){ inst = database.CreateItem(item, item_data ? item_data->charges : 0, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); } else { inst = database.CreateItem(item); } } if (client && inst) { if (client->CheckLoreConflict(item)) { client->Message_StringID(0, LOOT_LORE_ERROR); SendEndLootErrorPacket(client); being_looted_by = 0; delete inst; return; } if (inst->IsAugmented()) { for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { ItemInst *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { client->Message_StringID(0, LOOT_LORE_ERROR); SendEndLootErrorPacket(client); being_looted_by = 0; delete inst; return; } } } } char buf[88]; char corpse_name[64]; strcpy(corpse_name, corpse_name); snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name)); buf[87] = '\0'; std::vector<EQEmu::Any> args; args.push_back(inst); args.push_back(this); parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args); parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { if (client && !client->GetGM() && !client->IsDiscovered(inst->GetItem()->ID)) client->DiscoverItem(inst->GetItem()->ID); } if (zone->adv_data) { ServerZoneAdventureDataReply_Struct *ad = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; if (ad->type == Adventure_Collect && !IsPlayerCorpse()) { if (ad->data_id == inst->GetItem()->ID) { zone->DoAdventureCountIncrease(); } } } /* First add it to the looter - this will do the bag contents too */ if (lootitem->auto_loot) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) client->PutLootInInventory(MainCursor, *inst, bag_item_data); } else { client->PutLootInInventory(MainCursor, *inst, bag_item_data); } /* Update any tasks that have an activity to loot this item */ if (RuleB(TaskSystem, EnableTaskSystem)) client->UpdateTasksForItem(ActivityLoot, item->ID); /* Remove it from Corpse */ if (item_data){ /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, item_data->equip_slot, item_data->item_id); /* Delete Item Instance */ RemoveItem(item_data->lootslot); } /* Remove Bag Contents */ if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { for (int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); /* Delete Item Instance */ RemoveItem(bag_item_data[i]); } } } if (GetPlayerKillItem() != -1) { SetPlayerKillItemID(0); } /* Send message with item link to groups and such */ Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); if (!IsPlayerCorpse()) { Group *g = client->GetGroup(); if(g != nullptr) { g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); } else { Raid *r = client->GetRaid(); if(r != nullptr) { r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); } } } } else { SendEndLootErrorPacket(client); safe_delete(inst); return; } if (IsPlayerCorpse()){ client->SendItemLink(inst); } else{ client->SendItemLink(inst, true); } safe_delete(inst); }