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(); }
bool Corpse::Save() { if (!is_player_corpse) return true; if (!is_corpse_changed) return true; uint32 tmp = this->CountItems(); uint32 tmpsize = sizeof(PlayerCorpse_Struct) + (tmp * sizeof(player_lootitem::ServerLootItem_Struct)); PlayerCorpse_Struct* dbpc = (PlayerCorpse_Struct*) new uchar[tmpsize]; memset(dbpc, 0, tmpsize); dbpc->itemcount = tmp; dbpc->size = this->size; dbpc->locked = is_locked; dbpc->copper = this->copper; dbpc->silver = this->silver; dbpc->gold = this->gold; dbpc->plat = this->platinum; dbpc->race = this->race; dbpc->class_ = class_; dbpc->gender = gender; dbpc->deity = deity; dbpc->level = level; dbpc->texture = this->texture; dbpc->helmtexture = this->helmtexture; dbpc->exp = rez_experience; memcpy(dbpc->item_tint, item_tint, sizeof(dbpc->item_tint)); dbpc->haircolor = haircolor; dbpc->beardcolor = beardcolor; dbpc->eyecolor2 = eyecolor1; dbpc->hairstyle = hairstyle; dbpc->face = luclinface; dbpc->beard = beard; dbpc->drakkin_heritage = drakkin_heritage; dbpc->drakkin_tattoo = drakkin_tattoo; dbpc->drakkin_details = drakkin_details; uint32 x = 0; ItemList::iterator cur, end; cur = itemlist.begin(); end = itemlist.end(); for (; cur != end; ++cur) { ServerLootItem_Struct* item = *cur; memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(ServerLootItem_Struct)); } /* Create New Corpse*/ if (corpse_db_id == 0) { corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position); } /* Update Corpse Data */ else{ corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed()); } safe_delete_array(dbpc); return true; }
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard) { uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid); auto buffer = new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))]; PlayerCorpse_Struct *pcs = (PlayerCorpse_Struct*)buffer; database.LoadCharacterCorpseData(in_dbid, pcs); /* Load Items */ ItemList itemlist; ServerLootItem_Struct* tmp = 0; for (unsigned int i = 0; i < pcs->itemcount; i++) { tmp = new ServerLootItem_Struct; memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct)); itemlist.push_back(tmp); } /* Create Corpse Entity */ auto pc = new Corpse(in_dbid, // uint32 in_dbid in_charid, // uint32 in_charid in_charname.c_str(), // char* in_charname &itemlist, // ItemList* in_itemlist pcs->copper, // uint32 in_copper pcs->silver, // uint32 in_silver pcs->gold, // uint32 in_gold pcs->plat, // uint32 in_plat position, pcs->size, // float in_size pcs->gender, // uint8 in_gender pcs->race, // uint16 in_race pcs->class_, // uint8 in_class pcs->deity, // uint8 in_deity pcs->level, // uint8 in_level pcs->texture, // uint8 in_texture pcs->helmtexture, // uint8 in_helmtexture pcs->exp, // uint32 in_rezexp was_at_graveyard // bool wasAtGraveyard ); if (pcs->locked) pc->Lock(); /* Load Item Tints */ pc->item_tint.Head.Color = pcs->item_tint.Head.Color; pc->item_tint.Chest.Color = pcs->item_tint.Chest.Color; pc->item_tint.Arms.Color = pcs->item_tint.Arms.Color; pc->item_tint.Wrist.Color = pcs->item_tint.Wrist.Color; pc->item_tint.Hands.Color = pcs->item_tint.Hands.Color; pc->item_tint.Legs.Color = pcs->item_tint.Legs.Color; pc->item_tint.Feet.Color = pcs->item_tint.Feet.Color; pc->item_tint.Primary.Color = pcs->item_tint.Primary.Color; pc->item_tint.Secondary.Color = pcs->item_tint.Secondary.Color; /* Load Physical Appearance */ pc->haircolor = pcs->haircolor; pc->beardcolor = pcs->beardcolor; pc->eyecolor1 = pcs->eyecolor1; pc->eyecolor2 = pcs->eyecolor2; pc->hairstyle = pcs->hairstyle; pc->luclinface = pcs->face; pc->beard = pcs->beard; pc->drakkin_heritage = pcs->drakkin_heritage; pc->drakkin_tattoo = pcs->drakkin_tattoo; pc->drakkin_details = pcs->drakkin_details; pc->IsRezzed(rezzed); pc->become_npc = false; pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values safe_delete_array(pcs); return pc; }