void ScriptSupport::setPlayerPosition(uint64 playerId, uint64 cellId, float posX, float posY, float posZ)
{
    PlayerObject* player = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(playerId));
    if (player)
    {
        // Anh_Math::Quaternion	direction;
        glm::vec3 position;
        position.x = posX;
        position.y = posY;
        position.z = posZ;

        player->mPosition = position;
        player->setParentId(cellId);

        if (cellId)
        {
            // We are inside a cell.
            gMessageLib->sendDataTransformWithParent053(player);
            gMessageLib->sendUpdateTransformMessageWithParent(player);
        }
        else
        {
            gMessageLib->sendDataTransform053(player);
            gMessageLib->sendUpdateTransformMessage(player);
            //If our player is mounted move his mount aswell
            if(player->checkIfMounted() && player->getMount())
            {
                player->getMount()->mPosition = position;
                gMessageLib->sendDataTransform053(player->getMount());
                gMessageLib->sendUpdateTransformMessage(player->getMount());
            }
        }
    }
}
Example #2
0
void VehicleController::DismountPlayer() {
    if(!body_) {
		LOG(error) << "Vehicle::DismountPlayer() no vehicle body!";
        return;
    }

	PlayerObject* owner = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(owner_));
	CreatureObject*		owner_creature = owner->GetCreature();

    if(!owner->checkIfMounted()) {
        LOG(error) << "Vehicle::DismountPlayer() no vehicle body!";
        return;
    }

    //For safe measures make the player equipped by nothing
	body_->RemoveObject(owner, owner_creature);
	gMessageLib->sendContainmentMessage_InRange(owner_creature->getId(), 0, owner_creature->GetArrangementId(), owner_creature);
	gMessageLib->sendUpdateTransformMessage(body_);

    // TODO: make this more automatic...
    gStateManager.removeActionState(owner_creature, CreatureState_RidingMount);   
    gStateManager.removeActionState(body_, CreatureState_MountedCreature);   

    owner->setMounted(false);
    gMessageLib->sendPostureAndStateUpdate(owner_creature);  
    gMessageLib->sendUpdateMovementProperties(owner);
}
Example #3
0
void MountObject::prepareCustomRadialMenu(CreatureObject* creature, uint8_t item_count) {

	PlayerObject*	player	= creature->GetGhost();// dynamic_cast<PlayerObject*>(creature);

    if (!player) {
        // Verify the data passed in is what is expected. In debug mode the assert will
        // trigger and crash the server.
        assert(false && "MountObject::handleObjectMenuSelect - Menu preparation requested for a non-player object.");
        return;
    }

    // Reset the radial menu with a new instance.
    mRadialMenu.reset(new RadialMenu());

    // Add the radial options for the custom menu.
    mRadialMenu->addItem(1, 0, radId_examine, radAction_Default);

    // Check to see if the player requesting the menu is the owner of the mount.
    if(player->getId() == owner_)	{

        // Check to see if the player is mounted or not and display the appropriate exit/enter option.
        if(player->checkIfMounted())	{
            mRadialMenu->addItem(2, 0, radId_serverVehicleExit,radAction_Default, "@pet/pet_menu:menu_enter_exit");
        }	else {
            mRadialMenu->addItem(2, 0, radId_serverVehicleEnter,radAction_Default, "@pet/pet_menu:menu_enter_exit");
        }

        mRadialMenu->addItem(3, 0, radId_vehicleStore,radAction_ObjCallback, "@pet/pet_menu:menu_store");

        // @TODO: Check if near a garage then add repair
    }
}
void VehicleController::DismountPlayer() {
    if(!body_) {
		LOG(error) << "Vehicle::DismountPlayer() no vehicle body!";
        return;
    }

	LOG(error) << "Vehicle::DismountPlayer()";

	PlayerObject* owner = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(owner_));
	CreatureObject*		owner_creature = owner->GetCreature();

    if(!owner->checkIfMounted()) {
        LOG(error) << "Vehicle::DismountPlayer() no vehicle body!";
        return;
    }

    //see elaboration downstairs
	// body_->RemoveObject(owner, owner_creature);
	gMessageLib->sendContainmentMessage_InRange(owner_creature->getId(), 0, 0, owner_creature);
	//gMessageLib->sendUpdateTransformMessage(body_);

    // TODO: make this more automatic...
    gStateManager.removeActionState(owner_creature, CreatureState_RidingMount);   
	gStateManager.setCurrentLocomotionState(owner_creature, CreatureLocomotion_Standing);
	gStateManager.setCurrentPostureState(owner_creature, CreaturePosture_Upright);

	gStateManager.removeActionState(body_, CreatureState_MountedCreature);   

    owner->setMounted(false);

    gMessageLib->sendUpdateMovementProperties(owner);
}
Example #5
0
void ObjectController::_handleMount(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties)
{
    // The very idea with using ID's instead of object refs are that you can TEST them without using the object itself.
    // And some parameter validation...
    if (targetId == 0)
    {
        DLOG(info) << "ObjectController::_handleMount : Cannot find vehicle ID :(";
        return;
    }

    PlayerObject* player	= dynamic_cast<PlayerObject*>(mObject);

    if (player && player->getMount() && (player->getParentId() == 0))
    {
        // Do we have a valid target?
        if (!player->checkIfMounted())
        {
            // verify its player's mount
            MountObject* pet	= dynamic_cast<MountObject*>(gWorldManager->getObjectById(targetId));
            if (pet && (pet->owner() == player->getId()))
            {
                // get the mount Vehicle object by the id (Creature object id - 1 )

                if(VehicleController* vehicle = dynamic_cast<VehicleController*>(gWorldManager->getObjectById(pet->controller())))
                {
                    //The /mount command can work up to 32m on live
                    if(glm::distance(vehicle->body()->mPosition, player->mPosition) <= 32)	{
                        //change locomotion
                        vehicle->MountPlayer();
                    }	else {
                        gMessageLib->SendSystemMessage(L"Your target is too far away to mount.", player);
                    }
                }
                else
                {
                    DLOG(info) << "ObjectController::_handleMount : Cannot find vehicle";
                }
            }
        } else {
            gMessageLib->SendSystemMessage(L"You cannot mount this because you are already mounted.", player);
        }
    }
}
//===============================================================================================
//stores the physical body
void VehicleController::Store()
{
    if(!body_)    {
        DLOG(info) << "Vehicle::store() Error: Store was called for a nonexistant body object!";
        return;
    }

	PlayerObject* owner = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(owner_));

    if(!owner_ || owner->GetCreature()->isDead() || owner->GetCreature()->isIncapacitated())    {
        DLOG(info) << "Vehicle::store() couldnt find owner";
        return;
    }

    // todo auto dismount
    if(owner->checkIfMounted())
    {
		DLOG(info) << "Vehicle::store() dismounted";
        DismountPlayer();
    }

    if(!owner->checkIfMountCalled())
    {
        DLOG(info) << "Vehicle::store() Mount wasnt called !!!";
        return;
    }

	//the body is a creature_object!!!
	gSpatialIndexManager->RemoveObjectFromWorld(body_);

    owner->setMount(NULL);

    owner->setMounted(false);
    owner->setMountCalled(false);

    // finally unload & destroy the vehicle creature
    gWorldManager->destroyObject(body_);

    // null the reference
    body_ = NULL;

}
Example #7
0
void ObjectController::_handleDismount(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties)
{
    // The very idea with using ID's instead of object refs are that you can TEST them without using the object itself.
    // And some parameter validation...

    PlayerObject*	player	= dynamic_cast<PlayerObject*>(mObject);

    if (player && player->getMount() && (player->getParentId() == 0))
    {
        if (player->checkIfMounted())
        {
            // verify its player's mount
            MountObject* pet = NULL;
            if (targetId == 0)
            {
                // No object targeted, assume the one we are riding.	- what else should we dismount ???
                pet	= player->getMount();
            }
            else
            {
                pet = dynamic_cast<MountObject*>(gWorldManager->getObjectById(targetId));
            }

            if (pet && (pet->owner() == player->getId()))
            {
                // get the pets controller for a swoop its the vehicle
                if(VehicleController* vehicle = dynamic_cast<VehicleController*>(gWorldManager->getObjectById(pet->controller())))
                {
                    vehicle->DismountPlayer();
                }
            }
        }
        else
        {
            gMessageLib->SendSystemMessage(L"You are not mounted to perform this action.", player);
        }
    }
}
Example #8
0
bool CombatManager::_verifyCombatState(CreatureObject* attacker, uint64 defenderId)
{
	PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker);
	CreatureObject* defender = dynamic_cast<CreatureObject*>(gWorldManager->getObjectById(defenderId));

	if (!defender)
	{
		// No such object.
		return(false);
	}

	// Do not try to attack already incapped or dead objects.
	if (defender->isIncapacitated() || defender->isDead())
	{
		return false;
	}

	//Do not attack if we are incapped or already dead or mounted.
	if (attacker->isIncapacitated() || attacker->isDead() || playerAttacker->checkIfMounted())
	{
		return false;
	}

	// make sure we got both objects
	if (playerAttacker && defender)
	{
		//Do not attack if we are mounted
		if(playerAttacker->checkIfMounted())
		{
			return false;
		}

		// if our target is a player, he must be dueling us or both need to be overt(TODO)
		if (PlayerObject* defenderPlayer = dynamic_cast<PlayerObject*>(defender))
		{
			// also return, if our target is incapacitated or dead
			if(!playerAttacker->checkDuelList(defenderPlayer) || !defenderPlayer->checkDuelList(playerAttacker)
			|| defenderPlayer == playerAttacker)
			{
				return(false);
			}

			if(defenderPlayer->isIncapacitated())
			{
				// gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap");
				return(false);
			}
			else if(defenderPlayer->isDead())
			{
				// gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead");
				return(false);
			}

			// put us in combat state	
			gStateManager.setCurrentActionState(attacker, CreatureState_Combat);
            gStateManager.setCurrentActionState(attacker, CreatureState_CombatAttitudeNormal);
			// put our target in combat state
			if(!defenderPlayer->states.checkState(CreatureState_Combat))
			{

				gStateManager.setCurrentActionState(defender, CreatureState_Combat);
                gStateManager.setCurrentActionState(defender, CreatureState_CombatAttitudeNormal);
			}

			// update our defender list
			if (!playerAttacker->checkDefenderList(defenderPlayer->getId()))
			{
				playerAttacker->AddDefender(defenderPlayer->getId());
			}

			// update our targets defender list
			if (!defenderPlayer->checkDefenderList(playerAttacker->getId()))
			{
				playerAttacker->AddDefender(defenderPlayer->getId());
			}

			if (!defenderPlayer->autoAttackEnabled())
			{
				// Player can/may start auto-attack if idle.
				defenderPlayer->getController()->enqueueAutoAttack(playerAttacker->getId());
			}

		}
		else
		{
			// our target is a creature
			if (defender->isIncapacitated())
			{
				// gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap");
				return(false);
			}
			else if (defender->isDead())
			{
				// gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead");
				return(false);
			}

			// Vefify that out target is attackable. It's not nice to spam attacks at innocent npc's.
			if (!(defender->getPvPStatus() & CreaturePvPStatus_Attackable))
			{
				return(false);
			}

			// put us in combat state
			// if (!playerAttacker->states.checkState((CreatureState)(CreatureState_Combat + CreatureState_CombatAttitudeNormal)))
			{
				// playerAttacker->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable + CreaturePvPStatus_Aggressive + CreaturePvPStatus_Enemy));
				gMessageLib->sendUpdatePvpStatus(playerAttacker,playerAttacker, playerAttacker->getPvPStatus() | CreaturePvPStatus_Attackable);

				// TEST STATE MANAGER!
				gStateManager.setCurrentActionState(attacker, CreatureState_Combat);
                gStateManager.setCurrentActionState(attacker, CreatureState_CombatAttitudeNormal);
				
			}

			if (!defender->states.checkState((CreatureState_Combat)))
			{
				// Creature was NOT in combat before, and may very well be dormant.
				// Wake him up.
				gWorldManager->forceHandlingOfDormantNpc(defender->getId());
				gWorldManager->forceHandlingOfReadyNpc(defender->getId());

				// Creature may need some aggro built up before going into combat state??
			
				gStateManager.setCurrentActionState(defender, CreatureState_Combat);
                gStateManager.setCurrentActionState(defender, CreatureState_CombatAttitudeNormal);
			}

			gMessageLib->sendUpdatePvpStatus(defender, playerAttacker, defender->getPvPStatus() | CreaturePvPStatus_Attackable | CreaturePvPStatus_Enemy);

			// update our defender list
			if (!playerAttacker->checkDefenderList(defender->getId()))
			{
				playerAttacker->AddDefender(defenderPlayer->getId());
			}

			// update our targets defender list
			if (!defender->checkDefenderList(playerAttacker->getId()))
			{
				playerAttacker->AddDefender(defenderPlayer->getId());
			}
		}
	}
	else
	{
		return(false);
	}
	 
	return(true);
}
bool ObjectController::_destroyOutOfRangeObjects(ObjectSet *inRangeObjects)
{
    //TODO: when a container gets out of range
    //we need to destroy the children, too!!!!!!!

    // iterate our knowns
    PlayerObject*				player			= dynamic_cast<PlayerObject*>(mObject);
    ObjectSet*					knownObjects	= player->getKnownObjects();
    ObjectSet::iterator			objIt			= knownObjects->begin();
    PlayerObjectSet*			knownPlayers	= player->getKnownPlayers();
    PlayerObjectSet::iterator	playerIt		= knownPlayers->begin();

    const uint32 objectDestroyLimit = 5000;

    // update players
    while(playerIt != knownPlayers->end())
    {
        PlayerObject* playerObject = (*playerIt);

        // if its not in the current inrange queries result, destroy it
        if(inRangeObjects->find(playerObject) == inRangeObjects->end())
        {
            // send a destroy to us
            gMessageLib->sendDestroyObject(playerObject->getId(),player);

            //If player is mounted destroy his mount too
            if(playerObject->checkIfMounted() && playerObject->getMount())
            {
                gMessageLib->sendDestroyObject(playerObject->getMount()->getId(),player);

                player->removeKnownObject(playerObject->getMount());
                playerObject->getMount()->removeKnownObject(player);

            }

            //send a destroy to him
            gMessageLib->sendDestroyObject(player->getId(),playerObject);

            //If we're mounted destroy our mount too
            if(player->checkIfMounted() && playerObject->getMount())
            {
                gMessageLib->sendDestroyObject(player->getMount()->getId(),playerObject);
                playerObject->removeKnownObject(player->getMount());
                player->getMount()->removeKnownObject(playerObject);

            }

            // we don't know each other anymore
            knownPlayers->erase(playerIt++);
            playerObject->removeKnownObject(player);


            continue;
        }
        ++playerIt;
    }

    // We may want to limit the amount of messages sent in one session.
    uint32 messageCount = 0;

    // update objects
    //for(ObjectSet::const_iterator	objIt	= knownObjects->begin(); objIt != knownObjects->end(); objIt++)

    //we access the list above so it needs to be reset to the beginning
    objIt		= knownObjects->begin();
    while(objIt != knownObjects->end())
    {
        Object* object = (*objIt);

        // if its not in the current inrange queries result, destroy it
        if(inRangeObjects->find(object) == inRangeObjects->end())
        {

            if(object->getType() == ObjType_Structure)//ObjType_Tangible
            {

            }
            // send a destroy to us
            gMessageLib->sendDestroyObject(object->getId(),player);

            // we don't know each other anymore
            knownObjects->erase(objIt++);
            object->removeKnownObject(player);

            if (++messageCount >= objectDestroyLimit)
            {
                break;
            }
            continue;
        }

        ++objIt;
    }
    // For test
    bool allDestroyed = false;
    if (objIt == knownObjects->end())
    {
        allDestroyed = true;
    }
    return allDestroyed;
}
Example #10
0
bool ArtisanManager::handleRequestCoreSample(Object* player,Object* target, Message* message,ObjectControllerCmdProperties* cmdProperties)
{
    PlayerObject*		playerObject = dynamic_cast<PlayerObject*>(player);
    if(cmdProperties)
        // unfortunately it's not in this opcode
        // hardcode for now
        //mSampleActionCost = cmdProperties->mActionCost;
        mSampleActionCost = 150;

    if(playerObject->GetCreature()->getPerformingState() != PlayerPerformance_None || playerObject->checkIfMounted() || playerObject->GetCreature()->isDead() || playerObject->GetCreature()->states.checkState(CreatureState_Combat))
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), playerObject);
        return false;
    }
    // can't sample while surveying
    if(playerObject->getSurveyState())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_survey"), playerObject);
        return false;
    }
    // don't allow sampling in buildings
    if(playerObject->getParentId())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), playerObject);
        return false;
    }

    uint64 localTime = Anh_Utils::Clock::getSingleton()->getLocalTime();
    // don't allow more than one sample at a time
    if(playerObject->getSamplingState())
    {
        playerObject->getSampleData()->mPendingSample = false;
        playerObject->setNextSampleTime(localTime + 18000);
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "tool_recharge_time", 0, 0, 0, (int32)(playerObject->getNextSampleTime() - localTime) / 1000), playerObject);
        return false;
    }

    if(!playerObject->getNextSampleTime() || (int32)(playerObject->getNextSampleTime() - localTime) <= 0)
    {
        playerObject->getSampleData()->mPendingSample = false;
        playerObject->setNextSampleTime(localTime + 18000);
    }
    else
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "tool_recharge_time", 0, 0, 0, (int32)(playerObject->getNextSampleTime() - localTime) / 1000), playerObject);
        return false;
    }

    SurveyTool*			tool		= dynamic_cast<SurveyTool*>(target);
    CurrentResource*	resource	= NULL;

    BString resourceName;

    message->getStringUnicode16(resourceName);
    resourceName.convert(BSTRType_ANSI);

    resource = reinterpret_cast<CurrentResource*>(gResourceManager->getResourceByNameCRC(resourceName.getCrc()));

    if(resource == NULL || tool == NULL)
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_noresource"), playerObject);
        return false;
    }

    if((resource->getType()->getCategoryId() == 903)||(resource->getType()->getCategoryId() == 904))
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "must_have_harvester"), playerObject);
        return false;
    }
    playerObject->setSamplingState(true);
    
	auto terrain = gWorldManager->getKernel()->GetServiceManager()->GetService<swganh::terrain::TerrainService>("TerrainService");
	
	if(terrain->IsWater(gWorldManager->getZoneId(), playerObject->mPosition.x, playerObject->mPosition.z))
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_swimming"), playerObject);
        return false;
    }

	resourceName.convert(BSTRType_Unicode16);
    gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "start_sampling", L"", L"", resourceName.getUnicode16()), playerObject);

    // change posture
    gStateManager.setCurrentPostureState(playerObject->GetCreature(), CreaturePosture_Crouched);
    // play animation
    gWorldManager->getClientEffect(tool->getInternalAttribute<uint32>("sample_effect"));
    // schedule execution
    
	std::shared_ptr<SimpleEvent> start_sample_event = nullptr;
    start_sample_event = std::make_shared<SimpleEvent>(EventType("start_sample"), 0, 2000,
                         std::bind(&ArtisanManager::sampleEvent,this, playerObject, resource, tool));
    // notify any listeners
    
	gEventDispatcher.Notify(start_sample_event);
	
    return true;
}
Example #11
0
bool ArtisanManager::handleRequestCoreSample(Object* player,Object* target, Message* message,ObjectControllerCmdProperties* cmdProperties)
{
    PlayerObject*		playerObject = dynamic_cast<PlayerObject*>(player);
    if(cmdProperties)		
        // unfortunately it's not in this opcode
        // hardcode for now
        //mSampleActionCost = cmdProperties->mActionCost;
        mSampleActionCost = 150;
        
    if(playerObject->getPerformingState() != PlayerPerformance_None || playerObject->checkIfMounted() || playerObject->isDead())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), playerObject);
        return false;
    }
    // can't sample while surveying
    if(playerObject->getSurveyState())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_survey"), playerObject);
        return false;
    }
    // don't allow sampling in buildings
    if(playerObject->getParentId())
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), playerObject);
        return false;
    }

    uint64 localTime = Anh_Utils::Clock::getSingleton()->getLocalTime();
    // don't allow more than one sample at a time
    if(playerObject->getSamplingState())
    {
        playerObject->getSampleData()->mPendingSample = false;
        playerObject->setNextSampleTime(localTime + 18000);
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "tool_recharge_time", 0, 0, 0, (int32)(playerObject->getNextSampleTime() - localTime) / 1000), playerObject);
        return false;
    }

    if(!playerObject->getNextSampleTime() || (int32)(playerObject->getNextSampleTime() - localTime) <= 0)
    {
        playerObject->getSampleData()->mPendingSample = false;
        playerObject->setNextSampleTime(localTime + 18000);
    }
    else
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "tool_recharge_time", 0, 0, 0, (int32)(playerObject->getNextSampleTime() - localTime) / 1000), playerObject);
        return false;
    }

    SurveyTool*			tool		= dynamic_cast<SurveyTool*>(target);
    CurrentResource*	resource	= NULL;

    BString resourceName;

    message->getStringUnicode16(resourceName);
    resourceName.convert(BSTRType_ANSI);

    resource = reinterpret_cast<CurrentResource*>(gResourceManager->getResourceByNameCRC(resourceName.getCrc()));

    if(resource == NULL || tool == NULL)
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_noresource"), playerObject);
        return false;
    }

    if((resource->getType()->getCategoryId() == 903)||(resource->getType()->getCategoryId() == 904))
    {
        gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "must_have_harvester"), playerObject);
        return false;
    }
    playerObject->setSamplingState(true);
    ArtisanHeightmapAsyncContainer* container = new ArtisanHeightmapAsyncContainer(this, HeightmapCallback_ArtisanSurvey);
    container->addToBatch(playerObject->mPosition.x,playerObject->mPosition.z);

    container->playerObject = playerObject;
    container->resource = resource;
    container->resourceName = resourceName;
    container->tool = tool;

    gHeightmap->addNewHeightMapJob(container);

    return true;
}
bool ObjectController::_destroyOutOfRangeObjects(ObjectSet *inRangeObjects)
{
	//TODO: when a container gets out of range
	//we need to destroy the children, too!!!!!!!

	// iterate our knowns
	PlayerObject*				player			= dynamic_cast<PlayerObject*>(mObject);
	ObjectSet*					knownObjects	= player->getKnownObjects();
	ObjectSet::iterator			objIt			= knownObjects->begin();
	PlayerObjectSet*			knownPlayers	= player->getKnownPlayers();
	PlayerObjectSet::iterator	playerIt		= knownPlayers->begin();

	const uint32 objectDestroyLimit = 5000;

	// update players
	while(playerIt != knownPlayers->end())
	{
		PlayerObject* playerObject = (*playerIt);

		// if its not in the current inrange queries result, destroy it
		if(inRangeObjects->find(playerObject) == inRangeObjects->end())
		{
			// send a destroy to us
			gMessageLib->sendDestroyObject(playerObject->getId(),player);

			//If player is mounted destroy his mount too
			if(playerObject->checkIfMounted() && playerObject->getMount())
			{
				gMessageLib->sendDestroyObject(playerObject->getMount()->getId(),player);
				
				player->removeKnownObject(playerObject->getMount());
				playerObject->getMount()->removeKnownObject(player);
				
			}

			//send a destroy to him
			gMessageLib->sendDestroyObject(player->getId(),playerObject);

			//If we're mounted destroy our mount too
			if(player->checkIfMounted() && playerObject->getMount())
			{
				gMessageLib->sendDestroyObject(player->getMount()->getId(),playerObject);
				playerObject->removeKnownObject(player->getMount());
				player->getMount()->removeKnownObject(playerObject);
				
			}

			// we don't know each other anymore
			knownPlayers->erase(playerIt++);
			playerObject->removeKnownObject(player);


			continue;
		}
		++playerIt;
	}

	// We may want to limit the amount of messages sent in one session.
	uint32 messageCount = 0;

	// update objects
	while(objIt != knownObjects->end())
	{
		Object* object = (*objIt);

		// if its not in the current inrange queries result, destroy it
		if(inRangeObjects->find(object) == inRangeObjects->end())
		{

			if(object->getType() == ObjType_Structure)
			{
				if(FactoryObject* factory = dynamic_cast<FactoryObject*>(object))
				{
					//delete the hoppers contents
					TangibleObject* hopper = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById(factory->getIngredientHopper()));
					if(hopper)
					{
							ObjectIDList*			ol = hopper->getObjects();
							ObjectIDList::iterator	it = ol->begin();

							while(it != ol->end())
							{
								TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById((*it)));
								if(!tO)
								{
									assert(false && "ObjectController::_destroyOutOfRangeObjects WorldManager unable to find TangibleObject instance");
								}

								tO->removeKnownObject(player);
								player->removeKnownObject(tO);
								gMessageLib->sendDestroyObject(tO->getId(),player);
								it++;
							}
					
							hopper->removeKnownObject(player);
							player->removeKnownObject(hopper);
							
							gMessageLib->sendDestroyObject(hopper->getId(),player);					
					}

					hopper = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById(factory->getOutputHopper()));
					if(hopper)
					{
							ObjectIDList*			ol = hopper->getObjects();
							ObjectIDList::iterator	it = ol->begin();

							while(it != ol->end())
							{
								TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById((*it)));
								if(!tO)
								{
									assert(false && "ObjectController::_destroyOutOfRangeObjects WorldManager unable to find TangibleObject instance");
								}

								//PlayerObject* player = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(targetObject->getId()));
								tO->removeKnownObject(player);
								player->removeKnownObject(tO);
								gMessageLib->sendDestroyObject(tO->getId(),player);
								
								it++;
							}
					
							hopper->removeKnownObject(player);
							player->removeKnownObject(hopper);
							gMessageLib->sendDestroyObject(hopper->getId(),player);					
					}

				}
			}
			// send a destroy to us
			gMessageLib->sendDestroyObject(object->getId(),player);

			// we don't know each other anymore
			knownObjects->erase(objIt++);
			object->removeKnownObject(player);

			if (++messageCount >= objectDestroyLimit)
			{
				// gLogger->logMsg("Pausing sendDestroyObject()-calls.");
				break;
			}
			continue;
		}

		++objIt;
	}
	// For test
	bool allDestroyed = false;
	if (objIt == knownObjects->end())
	{
		// gLogger->logMsg("Finished sendDestroyObject()-calls.");
		allDestroyed = true;
	}
	return allDestroyed;
}
void ObjectController::handleDataTransform(Message* message,bool inRangeUpdate)
{
	PlayerObject*			player = dynamic_cast<PlayerObject*>(mObject);

	if (!player)
	{
		gLogger->logMsgF("ObjectController::handleDataTransform Object is NOT A PLAYER, id = %"PRIu64"", MSG_HIGH, mObject->getId());
		return;
	}

    glm::vec3		pos;
    glm::quat       dir;
	uint32			inMoveCount;
	uint32			tickCount;
	float			speed;
	bool updateAll = false;

	// get tick and move counters
	tickCount	= message->getUint32();
	inMoveCount = message->getUint32();

	// gLogger->logMsg("ObjectController::handleDataTransform");
	//uint64 localTimeStart = Anh_Utils::Clock::getSingleton()->getLocalTime();

	// only process if its in sequence
	if(player->getInMoveCount() >= inMoveCount)
	{
		return;
	}
	//uint32 ticks = tickCount - player->getClientTickCount();

	// update tick and move counters...
	player->setLastMoveTick(tickCount);
	player->setClientTickCount(tickCount);

	player->setInMoveCount(inMoveCount);

	if(player->checkIfMounted() && player->getMount())
	{
		//Player is mounted lets update his mount too
		player->getMount()->setLastMoveTick(tickCount);
		//player->getMount()->setInMoveCount((inMoveCount+1));
		player->getMount()->setInMoveCount((inMoveCount)); // + 1 or nor does not matter, as long as we update inMoveCount.
	}


	// get new direction, position and speed
	dir.x = message->getFloat();
	dir.y = message->getFloat();	 
	dir.z = message->getFloat();
	dir.w = message->getFloat();

	pos.x = message->getFloat();
	pos.y = message->getFloat();
	pos.z = message->getFloat();
	speed  = message->getFloat();

	// gLogger->logMsgF("Position outside = %.2f, %.2f, %.2f",MSG_NORMAL, pos.x,  pos.y, pos.z);
	/*
	if (Heightmap::isHeightmapCacheAvaliable())
	{
	gLogger->logMsgF("Heightmap value = %.2f",MSG_NORMAL, Heightmap::Instance()->getCachedHeightAt2DPosition(pos.x, pos.z));
	}
	*/

	// gLogger->logMsgF("Direction = %f, %f, %f, %f",MSG_NORMAL, dir.x, dir.y, dir.z, dir.w);

	// stop entertaining, if we were
	// important is, that if we move we change our posture to NOT skill animating anymore!
	// so only stop entertaining when we are performing and NOT skillanimationg
	if(player->getPerformingState() != PlayerPerformance_None && player->getPosture() != CreaturePosture_SkillAnimating)
	{
		gEntertainerManager->stopEntertaining(player);
	}

	// if we just left a building
	if(player->getParentId() != 0)
	{
		updateAll = true;

		// Testing with 4 for add and 0 for remove.
		// Remove us from previous cell.
		gMessageLib->broadcastContainmentMessage(player->getId(),player->getParentId(),0,player);

		// remove us from the last cell we were in
		if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())))
		{
			cell->removeObject(player);
		}
		else
		{
			gLogger->logMsgF("Error removing %"PRIu64" from cell(%"PRIu64")",MSG_HIGH,player->getId(),player->getParentId());
		}

		// we are outside again
		player->setParentId(0);
		player->mPosition = pos;
		// Add us to the world.
		gMessageLib->broadcastContainmentMessage(player->getId(),0,4,player);

		// add us to the qtree

		if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z))
		{
			player->setSubZoneId((uint32)newRegion->getId());
			newRegion->mTree->addObject(player);
		}
		else
		{
			// we should never get here !
			gLogger->logMsg("ObjController::handleDataTransform: could not find zone region in map");
			gLogger->logMsg("ObjController:: probably a bot : %i64u",static_cast<int>(player->getId()));

			// hammertime !
			//muglies botter sometimes sends us weird positions
			//however other 3rd party tools might do the same

			gWorldManager->addDisconnectedPlayer(player);
			return;
		}
		// Inform tutorial about cell change.
		if (gWorldConfig->isTutorial())
		{
			player->getTutorial()->setCellId(0);
		}

	}
	else //we are not in a building
	{
		// we should be in a qt at this point
		// get the qt of the new position
		if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z))
		{
			// we didnt change so update the old one
			if((uint32)newRegion->getId() == player->getSubZoneId())
			{
				// this also updates the players position
				newRegion->mTree->updateObject(player,pos);
				//If our player is mounted lets update his mount aswell
				if(player->checkIfMounted() && player->getMount())
				{
					newRegion->mTree->updateObject(player->getMount(),pos);
				}
			}
			else
			{
				updateAll = true;

				gLogger->logMsg("ObjController::DataTransform: Changing subzone");
				// remove from old
				if(QTRegion* oldRegion = gWorldManager->getQTRegion(player->getSubZoneId()))
				{
					oldRegion->mTree->removeObject(player);
					//If our player is mounted lets update his mount aswell
					if(player->checkIfMounted() && player->getMount())
					{
						oldRegion->mTree->removeObject(player->getMount());
					}
				}

				// update players position
				player->mPosition = pos;
				//If our player is mounted lets update his mount aswell
				if(player->checkIfMounted() && player->getMount())
				{
					player->getMount()->mPosition = pos;
				}

				// put into new
				player->setSubZoneId((uint32)newRegion->getId());
				newRegion->mTree->addObject(player);
				//If our player is mounted lets update his mount aswell
				if(player->checkIfMounted() && player->getMount())
				{
					player->getMount()->setSubZoneId((uint32)newRegion->getId());
					newRegion->mTree->addObject(player->getMount());
				}

			}
		}
		else
		{
			// we should never get here !
			gLogger->logMsg("ObjController::DataTransform: could not find zone region in map");

			gLogger->logMsg("ObjController:: probably a bot : %I64u",static_cast<int>(player->getId()));

			// hammertime !
			// muglies botter sometimes sends us weird positions  with X or Y far out of possible regions
			// however other 3rd party tools might do the same
			// we need to get rid of the client at this point nad probably should ban the player / add him to
			// a monitoring list when the coordinates were indeed out of bounds

			gWorldManager->addDisconnectedPlayer(player);
			return;
		}
	}

	player->mDirection = dir;
	player->setCurrentSpeed(speed);

	//If our player is mounted lets update his mount aswell
	if(player->checkIfMounted() && player->getMount())
	{
		player->getMount()->mDirection = dir;
		player->getMount()->setCurrentSpeed(speed);
	}


	// destroy the instanced instrument if out of range
	if (player->getPlacedInstrumentId())
	{
		if (!gWorldManager->objectsInRange(player->getId(), player->getPlacedInstrumentId(), 5.0))
		{
			if (Item* item = dynamic_cast<Item*>(gWorldManager->getObjectById(player->getPlacedInstrumentId())))
			{
				destroyObject(item->getId());
			}
		}
	}

	// Terminate active conversation with npc if to far away (trainers only so far).
	ActiveConversation* ac = gConversationManager->getActiveConversation(player->getId());
	if (ac != NULL)
	{
		// We do have a npc conversation going.
		if (!gWorldManager->objectsInRange(player->getId(), (ac->getNpc())->getId(), 11.0))
		{
			// Terminate conversation, since we are out of range.
			gMessageLib->sendSystemMessage(player,L"","system_msg","out_of_range");
			gConversationManager->stopConversation(player, true);			// We will get the current dialog text in a chat bubble, only seen by me. Impressive :)
		}
	}

	if (updateAll)
	{
		// Update our world.
		playerWorldUpdate(true);

		// Speed up the timed update, if any pending.
		gWorldManager->addPlayerMovementUpdateTime(player, 250);
	}
	else
	{
		if (!gWorldConfig->isInstance())
		{

			//If player is mounted... move his mount too!
			if(player->checkIfMounted() && player->getMount())
			{
				//gMessageLib->sendDataTransform(player->getMount());
				gMessageLib->sendUpdateTransformMessage(player->getMount());
			}
			else
			{
				// send out position updates to known players
				// please note that these updates mess up our dance performance
				if(player->getPerformingState() == PlayerPerformance_None)
				{
					gMessageLib->sendUpdateTransformMessage(player);
				}
		

			}

		}
		else
		{
			// send out position updates to known players in group or self only
			gMessageLib->sendUpdateTransformMessage(player, player);
		}
	}

	 //uint64 localTimeEnd = Anh_Utils::Clock::getSingleton()->getLocalTime();
	 //gLogger->logMsgF("Exec time PRId32",MSG_NORMAL, localTimeEnd - localTimeStart);
}
void ObjectController::handleDataTransformWithParent(Message* message,bool inRangeUpdate)
{
	// FIXME: for now assume we only get messages from players
	PlayerObject*	player = dynamic_cast<PlayerObject*>(mObject);
    glm::vec3       pos;
    glm::quat       dir;
	uint32          inMoveCount;
	uint32			tickCount;
	uint64			parentId;
	float			speed;
	bool			updateAll = false;

	// get tick and move counters
	tickCount	= message->getUint32();
	inMoveCount = message->getUint32();

	// only process if its in sequence
	if (player->getInMoveCount() <= inMoveCount)
	{
		uint64 oldParentId = player->getParentId();

		//uint32 ticks = tickCount - player->getClientTickCount();

		// update tick and move counters
		player->setClientTickCount(tickCount);
		player->setInMoveCount(inMoveCount);

		// get new direction, position, parent and speed
		parentId = message->getUint64();
		dir.x = message->getFloat();
		dir.y = message->getFloat();
		dir.z = message->getFloat();
		dir.w = message->getFloat();
		pos.x = message->getFloat();
		pos.y = message->getFloat();
		pos.z = message->getFloat();
		speed  = message->getFloat();


		// gLogger->logMsgF("Position inside = %f, %f, %f",MSG_NORMAL, pos.x,  pos.y, pos.z);
		// gLogger->logMsgF("Direction = %f, %f, %f, %f",MSG_NORMAL, dir.x, dir.y, dir.z, dir.w);

		// stop entertaining, if we were
		if(player->getPerformingState() != PlayerPerformance_None && player->getPosture() != CreaturePosture_SkillAnimating)
		{
			gEntertainerManager->stopEntertaining(player);
		}

		// if we changed cell
		if (oldParentId != parentId)
		{

			

			CellObject* cell = NULL;

			// gLogger->logMsgF("We changed cell from (%"PRIu64") to (%"PRIu64")",MSG_NORMAL, oldParentId, parentId);

			// Remove us from whatever we where in before.
			// (4 for add and 0 for remove)
			gMessageLib->broadcastContainmentMessage(player->getId(),oldParentId,0,player);

			// only remove us from si, if we just entered the building
			if (oldParentId != 0)
			{
				if((cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(oldParentId))))
				{
					cell->removeObject(player);
					// Done above.. gMessageLib->broadcastContainmentMessage(player->getId(),parentId,4,player);
				}
				else
				{
					gLogger->logMsgF("Error removing %"PRIu64" from cell(%"PRIu64")",MSG_NORMAL,player->getId(),oldParentId);
				}
			}
			else
			{
				updateAll = true;		// We just entered the building.

				// remove us from qt
				if(player->getSubZoneId())
				{
					if(QTRegion* region = gWorldManager->getQTRegion(player->getSubZoneId()))
					{
						player->setSubZoneId(0);
						region->mTree->removeObject(player);
						//If our player is mounted lets update his mount aswell
						if(player->checkIfMounted() && player->getMount())
						{
							player->getMount()->setSubZoneId(0);
							region->mTree->removeObject(player->getMount());

							//Can't ride into a building with a mount! :-p
							//However, its easy to do so we have handling incase the client is tricked.


							// the vehicle is the INTANGIBLE Datapad Controller
							// the *vehicle* itself is the BODY
							if(Vehicle* datapad_pet = dynamic_cast<Vehicle*>(gWorldManager->getObjectById(player->getMount()->getPetController())))
							{
								datapad_pet->dismountPlayer();
								datapad_pet->store();
							}
						}
					}
				}
			}

			// put us into new one
			gMessageLib->broadcastContainmentMessage(player->getId(),parentId,4,player);
			if((cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(parentId))))
			{

				cell->addObjectSecure(player);

				// Inform tutorial about cell change.
				if (gWorldConfig->isTutorial())
				{
					player->getTutorial()->setCellId(parentId);
					// gLogger->logMsgF("handleDataTransformWithParent: Adding %"PRIu64" to cell(%"PRIu64")",MSG_NORMAL,player->getId(),parentId);
				}
			}
			else
			{
				gLogger->logMsgF("Error adding %"PRIu64" to cell(%"PRIu64")",MSG_NORMAL,player->getId(),parentId);
			}
		}

		// update the player
		player->setParentId(parentId);
		player->mDirection = dir;
		player->mPosition  = pos;
		player->setCurrentSpeed(speed);

		// destroy the instanced instrument if out of range
		if (player->getPlacedInstrumentId())
		{
			if (!gWorldManager->objectsInRange(player->getId(), player->getPlacedInstrumentId(), 5.0))
			{
				if (Item* item = dynamic_cast<Item*>(gWorldManager->getObjectById(player->getPlacedInstrumentId())))
				{
					destroyObject(item->getId());
				}
			}
		}

		// Terminate active conversation with npc if to far away (trainers only so far).
		ActiveConversation* ac = gConversationManager->getActiveConversation(player->getId());
		if (ac != NULL)
		{
			// We do have a npc conversation going.
			if (!gWorldManager->objectsInRange(player->getId(), (ac->getNpc())->getId(), 11.0))
			{
				// Terminate conversation, since we are out of range.
				gMessageLib->sendSystemMessage(player,L"","system_msg","out_of_range");
				gConversationManager->stopConversation(player, true);			// We will get the current dialog text in a chat bubble, only seen by me. Impressive :)
			}
		}

		if (updateAll)
		{
			// Update our world.
			playerWorldUpdate(true);

			// Speed up the timed update, if any pending.
			gWorldManager->addPlayerMovementUpdateTime(player, 250);
		}
		else
		{
			if (!gWorldConfig->isInstance())
			{
				// send out updates
				gMessageLib->sendUpdateTransformMessageWithParent(player);
			}
			else
			{
				// send out position updates to known players in group or self only
				gMessageLib->sendUpdateTransformMessageWithParent(player, player);
			}
		}
	}
}
uint64 ObjectController::playerWorldUpdate(bool forcedUpdate)
{
	PlayerObject* player = dynamic_cast<PlayerObject*>(mObject);

	// If we already are busy, don't start another update.
	// ie if this is called by the worldmanager timer because we still have unupdated objects
	// in our resultmap
	if (!(mUpdatingObjects || mDestroyOutOfRangeObjects || forcedUpdate))
	{
		// If we have been inactive for too long, let's update the world.
		if (player->getCurrentSpeed() == 0.0)
		{
			//is  this the amount of full updates already running ?
			if (++mFullUpdateTrigger >= 15)		// We only check this when we are running idle with low frequency
			{
				// gLogger->logMsg("... sitting still to long!");
				// Let's update the world
				forcedUpdate = true;
				mFullUpdateTrigger = 0;
			}
		}
		else
		{
			mFullUpdateTrigger = 0;
		}
	}

	// Are we inside or outside?
	if (player->getParentId() != 0)
	{
		// We are inside.
		if (mUpdatingObjects || forcedUpdate)
		{
			// Just entered the building?
			// if (!mUpdatingObjects)
			// We need to abort any pending operation if we get a forcedUpdate (meaning entered, changed or left a cell or subzone).
			if (forcedUpdate)
			{
				// Update all.
				// gLogger->logMsg("ObjController::handleDataTransformWithParent: _findInRangeObjectsInside(true)");
				_findInRangeObjectsInside(true);
			}
		}
		else
		{
			// This is the faster update, stil based on SI though.
			_findInRangeObjectsInside(false);
		}
		// Update some of the objects we found.
		mUpdatingObjects = !_updateInRangeObjectsInside();

	}
	else
	{
		// We are outside.
		bool OutOfUpdateRange = false;

		// If we "just stopped" and not busy with updating, make a full update.
		if (!mUpdatingObjects && !mDestroyOutOfRangeObjects)
		{
			// We are not "busy" processing anything from previous sessions.
			if (player->getCurrentSpeed() == 0.0)
			{
				if (mMovementInactivityTrigger > 0)
				{
					if (--mMovementInactivityTrigger == 0)
					{
						// gLogger->logMsg("We are not moving...");
						// We are not moving, but how far are we from last full update pos?
                        if (glm::distance(player->mPosition, player->getLastUpdatePosition()) < 16)
						{
							// Force a full update, inclusive of saving current "update pos".
							// gLogger->logMsg("... forced update!");
							OutOfUpdateRange = true;
						}
						else
						{
							// gLogger->logMsgF("... but to close to last update pos, %.1f",MSG_NORMAL, player->mPosition.distance2D(player->getLastUpdatePosition()));
						}
					}
				}
			}
			else
			{
				mMovementInactivityTrigger = 2;		// We only check this when we are running idle with slow frequency
													// Need to be standstill for this amount of seconds * 5 (or whatever time we use for slow updates) before we update.
			}
		}

		// Position check for SI-update.
        OutOfUpdateRange |= !(glm::distance(player->mPosition, player->getLastUpdatePosition()) < 64.0f);
		//OutOfUpdateRange |= !(player->mPosition.inRange2D(player->getLastUpdatePosition(),64.0f));

		// gLogger->logMsgF("Distance = %f",MSG_NORMAL, player->mPosition.distance2D(player->getLastUpdatePosition()));

		if (mUpdatingObjects || forcedUpdate || OutOfUpdateRange)
		{
			// More than 64 m from where we loaded SI, reload it.
			// We need to abort any pending operation if we get a forcedUpdate (meaning entered, changed or left a cell or subzone).
			if ((forcedUpdate) || OutOfUpdateRange)
			{
				// Save these coordinates
				// gLogger->logMsg("forcedUpdate");

				mDestroyOutOfRangeObjects = false;	// Stop the destroy-messages, in case we already have started to send them.
				if (OutOfUpdateRange)
				{
					// gLogger->logMsg("Out of 64m range");
					player->setLastUpdatePosition(player->mPosition);

					//If our player is mounted let's update his mount
					if(player->checkIfMounted() && player->getMount())
					{
						player->getMount()->setLastUpdatePosition(player->mPosition);
					}

					// We shall destroy out of range objects when we are done with the update of known objects.
					mDestroyOutOfRangeObjects = true;
				}
				_findInRangeObjectsOutside(true);
			}
		}
		else if (!mDestroyOutOfRangeObjects)
		{
			// This is the fast update, based on qt.
			// gLogger->logMsg("_findInRangeObjectsOutside(false)");

			_findInRangeObjectsOutside(false);
		}

		// Update some of the objects we found.
		mUpdatingObjects = !_updateInRangeObjectsOutside();

		if (!mUpdatingObjects)
		{
			// We are not updating new objects.
			if (mDestroyOutOfRangeObjects)
			{
				// We are ready to destroy objects out of range.
				if (_destroyOutOfRangeObjects(&mInRangeObjects))
				{
					// All objects are now destroyed.
					mDestroyOutOfRangeObjects = false;

					// If active target out of range, clear.
					if (player->getTarget())
					{
						// gLogger->logMsgF("playerWorldUpdate have a Target of type %d", MSG_NORMAL, player->getTarget()->getType());

						// The list of objects we shall check for untargeting consist of all objects that we can "interact with".
						if ((player->getTarget()->getType() & (ObjType_Player | ObjType_NPC | ObjType_Creature)) ||
							((player->getTarget()->getType() == ObjType_Tangible) && (dynamic_cast<TangibleObject*>(player->getTarget())->getTangibleGroup() == TanGroup_TicketCollector)))
						{
							if (!(player->checkKnownObjects(player->getTarget())))
							{
								player->setTarget(NULL);
								gMessageLib->sendTargetUpdateDeltasCreo6(player);
								// gLogger->logMsg("playerWorldUpdate clear Target");
							}
						}
					}
				}
			}
		}

	}

	uint64 msToWait = 4900;		// Will give 5 sec.

	if (mUpdatingObjects || mDestroyOutOfRangeObjects)
	{
		// We are busy, need to continue processing asap.
		msToWait = 900;		// This should make us tick every second, since that's the base time for the timer we use.
	}
	return msToWait;
}
Example #16
0
//=============================================================================
//
// incap
//
void CreatureObject::incap()
{
	// sanity check
	if (isIncapacitated() || isDead())
	{
		return;
	}

	if (this->getType() == ObjType_Player)
	{
		// gLogger->logMsgF("Player incapped, mIncapCount = %u.", MSG_NORMAL, mIncapCount);

		// first incap, update the initial time
		uint64 localTime = Anh_Utils::Clock::getSingleton()->getLocalTime();
		if(!mIncapCount)
		{
			mFirstIncapTime = localTime;
		}
		// reset the counter if the reset time has passed
		else if(mIncapCount != 0 && (localTime - mFirstIncapTime) >= gWorldConfig->getIncapResetTime() * 1000)
		{
			// gLogger->logMsgF("Time since first incap = %"PRIu64"", MSG_NORMAL, localTime - mFirstIncapTime);
			// gLogger->logMsgF("Resetting mFirstIncapTime", MSG_NORMAL);

			mIncapCount = 0;
			mFirstIncapTime = localTime;
		}
		/*
		if (mIncapCount != 0)
		{
			gLogger->logMsgF("Time since first incap = %"PRIu64"", MSG_NORMAL, localTime - mFirstIncapTime);
		}
		*/

		PlayerObject* player = dynamic_cast<PlayerObject*>(this);
		if (player)
		{
			player->disableAutoAttack();
		}

		//See if our player is mounted -- if so dismount him 
		if(player->checkIfMounted())
		{
			//Get the player's mount
			if(Vehicle* vehicle = dynamic_cast<Vehicle*>(gWorldManager->getObjectById(player->getMount()->getPetController())))
			{
				//Now dismount
				vehicle->dismountPlayer();
			}

		}

		// advance incaps counter
		if(++mIncapCount < gWorldConfig->getConfiguration("Player_Incapacitation",3))
		{
			// gLogger->logMsgF("Player incapped, mIncapCount set to = %u, setting timer..", MSG_NORMAL, mIncapCount);

			// update the posture
			mPosture = CreaturePosture_Incapacitated;

			// send timer updates
			mCurrentIncapTime = gWorldConfig->getBaseIncapTime() * 1000;
			gMessageLib->sendIncapTimerUpdate(this);

			// schedule recovery event
			mObjectController.addEvent(new IncapRecoveryEvent(),mCurrentIncapTime);

			// reset states
			mState = 0;

			// reset ham regeneration
			mHam.updateRegenRates();
			gWorldManager->removeCreatureHamToProcess(mHam.getTaskId());
			mHam.setTaskId(0);

			updateMovementProperties();

			gMessageLib->sendPostureAndStateUpdate(this);

			if(PlayerObject* player = dynamic_cast<PlayerObject*>(this))
			{
				gMessageLib->sendUpdateMovementProperties(player);
				gMessageLib->sendSelfPostureUpdate(player);
			}
		}
		// we hit the max -> death
		else
		{
			// gLogger->logMsgF("Player died.", MSG_NORMAL);
			die();
		}
	}
	else if (this->getType() == ObjType_Creature)	// A Creature.
	{
		die();
	}
	else
	{
		gLogger->logMsgF("CreatureObject::incap Incapped unsupported type %u\n", MSG_NORMAL, this->getType());
	}

}
void ObjectController::handleDataTransform(Message* message,bool inRangeUpdate)
{
    PlayerObject*			player = dynamic_cast<PlayerObject*>(mObject);

    if (!player)
    {
        return;
    }

    glm::vec3		pos;
    glm::quat       dir;
    uint32			inMoveCount;
    uint32			tickCount;
    float			speed;
    bool updateAll = false;

    // get tick and move counters
    tickCount	= message->getUint32();
    inMoveCount = message->getUint32();

    // only process if its in sequence
    if(player->getInMoveCount() >= inMoveCount)
    {
        return;
    }
    //uint32 ticks = tickCount - player->getClientTickCount();

    // update tick and move counters...
    player->setLastMoveTick(tickCount);
    player->setClientTickCount(tickCount);

    player->setInMoveCount(inMoveCount);


    // get new direction, position and speed
    dir.x = message->getFloat();
    dir.y = message->getFloat();
    dir.z = message->getFloat();
    dir.w = message->getFloat();

    pos.x = message->getFloat();
    pos.y = message->getFloat();
    pos.z = message->getFloat();
    speed  = message->getFloat();

    // stop entertaining ???
    // important is, that if we move we change our posture to NOT skill animating anymore!
    // so only stop entertaining when we are performing and NOT skillanimationg
    if(player->getPerformingState() != PlayerPerformance_None && player->states.getPosture() != CreaturePosture_SkillAnimating)
    {
        gEntertainerManager->stopEntertaining(player);
    }

    // if we just left a building
    if(player->getParentId() != 0)
    {
        updateAll = true;

        // Testing with 4 for add and 0 for remove.
        // Remove us from previous cell.
        gMessageLib->broadcastContainmentMessage(player->getId(),player->getParentId(),0,player);

        // remove us from the last cell we were in
        if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())))
        {
            cell->removeObject(player);
        }
        else
        {
			DLOG(INFO) << "Error removing" << player->getId() << " from cell " << player->getParentId();
        }

        // we are outside again
        player->setParentId(0);
        player->mPosition = pos;
        // Add us to the world.
        gMessageLib->broadcastContainmentMessage(player->getId(),0,4,player);

        // add us to the qtree

        if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z))
        {
            player->setSubZoneId((uint32)newRegion->getId());
            player->setSubZone(newRegion);
            newRegion->mTree->addObject(player);
        }
        else
        {
            // we should never get here !
            // it basically means we left the map
            DLOG(INFO) << "ObjController::handleDataTransform: could not find zone region in map";
            DLOG(INFO) << "ObjController:: probably a bot : " << player->getId();

            // hammertime !
            //muglies botter sometimes sends us weird positions
            //however other 3rd party tools might do the same

            gWorldManager->addDisconnectedPlayer(player);
            return;
        }
        // Inform tutorial about cell change.
        if (gWorldConfig->isTutorial())
        {
            player->getTutorial()->setCellId(0);
        }
    }
    else //we are not in a building
    {
        // we should be in a qt at this point check our qt if we still are inside its bounds
        // please note, that there is exactly *one* qtregion per planet and qtregions do *not* overlap
        // so there is no need to search the region everytime even if we should decide to add more qtregions
        // subzone is NULL however, when we just left a building
        if(player->getSubZone() && player->getSubZone()->checkPlayerPosition(pos.x, pos.z))
        {
            // this also updates the players position
            player->getSubZone()->mTree->updateObject(player,pos);
            //If our player is mounted lets update his mount aswell
            if(player->checkIfMounted() && player->getMount())
            {
                player->getSubZone()->mTree->updateObject(player->getMount(),pos);
            }
        }
        else
            //do an intersectsWithQuery of objects in the si to find our new region -
            //CAVE shouldnt it be a contains query ?
            //what do we do if several regions overlap ?
            if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z))
            {
                updateAll = true;

                // remove from old
                if(QTRegion* oldRegion = player->getSubZone())
                {
                    oldRegion->mTree->removeObject(player);
                    //If our player is mounted lets update his mount aswell
                    if(player->checkIfMounted() && player->getMount())
                    {
                        oldRegion->mTree->removeObject(player->getMount());
                    }
                }

                // update players position
                player->mPosition = pos;
                //If our player is mounted lets update his mount aswell
                if(player->checkIfMounted() && player->getMount())
                {
                    player->getMount()->mPosition = pos;
                }

                // put into new
                player->setSubZoneId((uint32)newRegion->getId());
                player->setSubZone(newRegion);

                newRegion->mTree->addObject(player);
                //If our player is mounted lets update his mount aswell
                if(player->checkIfMounted() && player->getMount())
                {
                    player->getMount()->setSubZoneId((uint32)newRegion->getId());
                    newRegion->mTree->addObject(player->getMount());
                }
            }
            else
            {
                // we should never get here !
                DLOG(INFO) << "ObjController::handleDataTransform: could not find zone region in map";
	            DLOG(INFO) << "ObjController:: probably a bot : " << player->getId();

                // hammertime !
                // muglies botter sometimes sends us weird positions  with X or Y far out of possible regions
                // however other 3rd party tools might do the same
                // we need to get rid of the client at this point nad probably should ban the player / add him to
                // a monitoring list when the coordinates were indeed out of bounds

                gWorldManager->addDisconnectedPlayer(player);
                return;
            }
    }

    player->mDirection = dir;
    player->setCurrentSpeed(speed);

    // destroy the instanced instrument if out of range
    if (player->getPlacedInstrumentId())
    {
        if (!gWorldManager->objectsInRange(player->getId(), player->getPlacedInstrumentId(), 5.0))
        {
            if (Item* item = dynamic_cast<Item*>(gWorldManager->getObjectById(player->getPlacedInstrumentId())))
            {
                destroyObject(item->getId());
            }
        }
    }

    // Terminate active conversation with npc if to far away (trainers only so far).
    ActiveConversation* ac = gConversationManager->getActiveConversation(player->getId());
    if (ac != NULL)
    {
        // We do have a npc conversation going.
        if (!gWorldManager->objectsInRange(player->getId(), (ac->getNpc())->getId(), 11.0))
        {
            // Terminate conversation, since we are out of range.
            gMessageLib->SendSystemMessage(::common::OutOfBand("system_msg", "out_of_range"), player);
            gConversationManager->stopConversation(player, true);			// We will get the current dialog text in a chat bubble, only seen by me. Impressive :)
        }
    }

    if (updateAll)
    {
        // Update our world.
        playerWorldUpdate(true);

        // Speed up the timed update, if any pending.
        gWorldManager->addPlayerMovementUpdateTime(player, 250);
    }
    else
    {
        if (!gWorldConfig->isInstance())
        {

            //If player is mounted... move his mount too!
            if(player->checkIfMounted() && player->getMount())
            {
                //gMessageLib->sendDataTransform(player->getMount());
                player->getMount()->mDirection = dir;
                player->getMount()->setCurrentSpeed(speed);
                player->getMount()->setLastMoveTick(tickCount);
                player->getMount()->setInMoveCount((inMoveCount)); // + 1 or nor does not matter, as long as we update inMoveCount.
                gMessageLib->sendUpdateTransformMessage(player->getMount());


            }
            else
            {
                // send out position updates to known players
                // please note that these updates mess up our dance performance
                /*if(player->getPerformingState() == PlayerPerformance_None)
                {*/
                gMessageLib->sendUpdateTransformMessage(player);
                //}


            }

        }
        else
        {
            // send out position updates to known players in group or self only
            gMessageLib->sendUpdateTransformMessage(player, player);
        }
    }
}