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;
}
Exemple #2
0
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();
}