Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia /*=false*/) { Corpse* corpse = GetCorpseForPlayerGUID(player_guid); if (!corpse) { //in fact this function is called from several places //even when player doesn't have a corpse, not an error return NULL; } sLog->outStaticDebug("Deleting Corpse and spawned bones."); // Map can be NULL Map* map = corpse->FindMap(); // remove corpse from player_guid -> corpse map and from current map RemoveCorpse(corpse); // remove corpse from DB SQLTransaction trans = CharacterDatabase.BeginTransaction(); corpse->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); Corpse* bones = NULL; // create the bones only if the map and the grid is loaded at the corpse's location // ignore bones creating option in case insignia if (map && (insignia || (map->IsBattlegroundOrArena() ? sWorld->getBoolConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld->getBoolConfig(CONFIG_DEATH_BONES_WORLD))) && !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) { // Create bones, don't change Corpse bones = new Corpse; bones->Create(corpse->GetGUIDLow(), map); for (uint8 i = OBJECT_FIELD_TYPE + 1; i < CORPSE_END; ++i) // don't overwrite guid and object type bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); bones->SetGridCoord(corpse->GetGridCoord()); // bones->m_time = m_time; // don't overwrite time // bones->m_type = m_type; // don't overwrite type bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); bones->SetPhaseMask(corpse->GetPhaseMask(), false); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) { if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); } // add bones in grid store if grid loaded where corpse placed map->AddToMap(bones); } // all references to the corpse should be removed at this point delete corpse; return bones; }
Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia) { Corpse *corpse = GetCorpseForPlayerGUID(player_guid); if(!corpse) { //in fact this function is called from several places //even when player doesn't have a corpse, not an error //sLog.outError("Try remove corpse that not in map for GUID %ul", player_guid); return NULL; } DEBUG_LOG("Deleting Corpse and spawning bones."); // remove corpse from player_guid -> corpse map RemoveCorpse(corpse); // remove resurrectable corpse from grid object registry (loaded state checked into call) // do not load the map if it's not loaded Map *map = sMapMgr.FindMap(corpse->GetMapId(), corpse->GetInstanceId()); if(map) map->Remove(corpse, false); // remove corpse from DB corpse->DeleteFromDB(); Corpse *bones = NULL; // create the bones only if the map and the grid is loaded at the corpse's location // ignore bones creating option in case insignia if (map && (insignia || (map->IsBattleGroundOrArena() ? sWorld.getConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld.getConfig(CONFIG_DEATH_BONES_WORLD))) && !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) { // Create bones, don't change Corpse bones = new Corpse; bones->Create(corpse->GetGUIDLow()); for (int i = 3; i < CORPSE_END; ++i) // don't overwrite guid and object type bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); bones->SetGrid(corpse->GetGrid()); // bones->m_time = m_time; // don't overwrite time // bones->m_inWorld = m_inWorld; // don't overwrite world state // bones->m_type = m_type; // don't overwrite type bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); bones->SetPhaseMask(corpse->GetPhaseMask(), false); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); for (int i = 0; i < EQUIPMENT_SLOT_END; ++i) { if(corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); } // add bones in grid store if grid loaded where corpse placed map->Add(bones); } // all references to the corpse should be removed at this point delete corpse; return bones; }
void CAICorpseManager::Update( const float frameTime ) { const uint32 maxCorpsesToUpdateThisFrame = 4; const float cullPhysicsDistanceSqr = g_pGameCVars->g_aiCorpses_CullPhysicsDistance * g_pGameCVars->g_aiCorpses_CullPhysicsDistance; const float forceDeleteDistanceSqr = g_pGameCVars->g_aiCorpses_ForceDeleteDistance * g_pGameCVars->g_aiCorpses_ForceDeleteDistance; if (m_lastUpdatedCorpseIdx >= (uint32)m_corpsesArray.size()) m_lastUpdatedCorpseIdx = 0; const CCamera& viewCamera = gEnv->pSystem->GetViewCamera(); CryFixedArray<EntityId, maxCorpsesToUpdateThisFrame> corpsesToDelete; const uint32 corpsesEndIdx = min(m_lastUpdatedCorpseIdx + maxCorpsesToUpdateThisFrame, (uint32)m_corpsesArray.size()); for(uint32 i = m_lastUpdatedCorpseIdx; i < corpsesEndIdx; ++i) { CorpseInfo& corpseInfo = m_corpsesArray[i]; IEntity* pCorpseEntity = corpseInfo.GetCorpseEntity(); if(pCorpseEntity != NULL) { AABB corpseBbox; pCorpseEntity->GetWorldBounds(corpseBbox); corpseBbox.Expand(Vec3(0.1f, 0.1f, 0.1f)); const Vec3 corpsePosition = corpseBbox.GetCenter(); const float distanceSqr = (corpsePosition - viewCamera.GetPosition()).len2(); const bool attemptDeleteFarAway = (distanceSqr > forceDeleteDistanceSqr); const bool cullPhysics = (distanceSqr > cullPhysicsDistanceSqr); const bool isVisible = viewCamera.IsAABBVisible_F(corpseBbox); corpseInfo.flags.SetFlags( CorpseInfo::eFlag_FarAway, attemptDeleteFarAway ); if(attemptDeleteFarAway && !isVisible) { corpsesToDelete.push_back(corpseInfo.corpseId); } else if(cullPhysics != corpseInfo.flags.AreAllFlagsActive( CorpseInfo::eFlag_PhysicsDisabled )) { IEntityPhysicalProxy* pCorpsePhysicsProxy = static_cast<IEntityPhysicalProxy*>(pCorpseEntity->GetProxy( ENTITY_PROXY_PHYSICS )); if (pCorpsePhysicsProxy != NULL) { //Simulate entity event to enable/disable physics SEntityEvent visibilityEvent; visibilityEvent.event = cullPhysics ? ENTITY_EVENT_HIDE : ENTITY_EVENT_UNHIDE; pCorpsePhysicsProxy->ProcessEvent( visibilityEvent ); if(cullPhysics == false) { IPhysicalEntity* pCorpsePhysics = pCorpseEntity->GetPhysics(); if(pCorpsePhysics != NULL) { pe_action_awake awakeAction; awakeAction.bAwake = 0; pCorpsePhysics->Action( &awakeAction ); } } } corpseInfo.flags.SetFlags( CorpseInfo::eFlag_PhysicsDisabled, cullPhysics ); } } else { //This should not happen, but in case remove the entity from the list GameWarning("AICorpseManager - Detected corpse with no entity, removing from list"); corpsesToDelete.push_back(corpseInfo.corpseId); } } m_lastUpdatedCorpseIdx = corpsesEndIdx; for(uint32 i = 0; i < (uint32)corpsesToDelete.size(); ++i) { RemoveCorpse(corpsesToDelete[i]); } DebugDraw(); }