void TicketCollector::handleObjectMenuSelect(uint8 messageType,Object* srcObject) { if(messageType == radId_itemUse) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(srcObject); // don't use while incapped or dead or in combat if(playerObject->isIncapacitated() || playerObject->isDead() || playerObject->states.checkState(CreatureState_Combat)) { return; } // in range check for shuttle not for the droid if(playerObject->getParentId() != mParentId || (glm::distance(playerObject->mPosition, mShuttle->mPosition) > 25.0f)) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "boarding_too_far"), playerObject); return; } if(playerObject->checkUIWindow("handleTicketSelect")) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "boarding_ticket_selection"), playerObject); return; } if(mShuttle) { mShuttle->useShuttle(playerObject); } } else DLOG(info) << "TravelTerminal: Unhandled MenuSelect: " << messageType; }
void ObjectController::_handleBoardTransport(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(mObject); ObjectSet inRangeObjects; float boardingRange = 25.0; if(playerObject->states.getPosture() == CreaturePosture_SkillAnimating) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), playerObject); return; } BString str; message->getStringUnicode16(str); str.convert(BSTRType_ANSI); str.toLower(); if((str.getCrc() != BString("transport").getCrc())) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "boarding_what_shuttle"), playerObject); return; } gSpatialIndexManager->getObjectsInRange(playerObject,&inRangeObjects,ObjType_Creature | ObjType_NPC, boardingRange, true); // iterate through the results ObjectSet::iterator it = inRangeObjects.begin(); while(it != inRangeObjects.end()) { if(Shuttle* shuttle = dynamic_cast<Shuttle*>(*it)) { // in range check if(playerObject->getParentId() != shuttle->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "boarding_too_far"), playerObject); return; } if (!shuttle->availableInPort()) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "shuttle_not_available"), playerObject); return; } shuttle->useShuttle(playerObject); return; } ++it; } gMessageLib->SendSystemMessage(::common::OutOfBand("structure/structure_messages", "boarding_what_shuttle"), playerObject); }
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); } } }
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); } } }
void ElevatorTerminal::handleObjectMenuSelect(uint8 messageType,Object* srcObject) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(srcObject); if(!playerObject || !playerObject->isConnected() || playerObject->getSamplingState() || playerObject->isIncapacitated() || playerObject->isDead()) { return; } if(messageType == radId_elevatorUp) { gMessageLib->sendPlayClientEffectObjectMessage(gWorldManager->getClientEffect(mEffectUp),"",playerObject); // remove player from current position, elevators can only be inside CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(playerObject->getParentId())); if(cell) { cell->removeObject(playerObject); } else { gLogger->logMsgF("could not find cell %"PRIu64"",MSG_HIGH,playerObject->getParentId()); } // put him into new one playerObject->mDirection = mDstDirUp; playerObject->mPosition = mDstPosUp; playerObject->setParentId(mDstCellUp); cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(mDstCellUp)); if(cell) { cell->addObjectSecure(playerObject); } else { gLogger->logMsgF("could not find cell %"PRIu64"",MSG_HIGH,mDstCellUp); } gMessageLib->sendDataTransformWithParent(playerObject); } else if(messageType == radId_elevatorDown) { gMessageLib->sendPlayClientEffectObjectMessage(gWorldManager->getClientEffect(mEffectDown),"",playerObject); // remove player from current position, elevators can only be inside CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(playerObject->getParentId())); if(cell) { cell->removeObject(playerObject); } else { gLogger->logMsgF("could not find cell %"PRIu64"",MSG_HIGH,playerObject->getParentId()); } // put him into new one playerObject->mDirection = mDstDirDown; playerObject->mPosition = mDstPosDown; playerObject->setParentId(mDstCellDown); cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(mDstCellDown)); if(cell) { cell->addObjectSecure(playerObject); } else { gLogger->logMsgF("could not find cell %"PRIu64"",MSG_HIGH,mDstCellDown); } gMessageLib->sendDataTransformWithParent(playerObject); } else { gLogger->logMsgF("ElevatorTerminal: Unhandled MenuSelect: %u",MSG_HIGH,messageType); } }
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); } } } }
//====================================================================================================================== // // moves an item // void ObjectController::HandleItemMoveDown_( uint64 targetId, Message* message, ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); if (!player) { assert(false && "ObjectController::HandleItemMoveDown_ Player not found"); return; } // Verify that there was a target passed. if (!targetId) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return; } Object* object = gWorldManager->getObjectById(targetId); if(!object) { assert(false && "ObjectController::HandleItemMoveDown_ item not found"); return; } // Verify that the item and player are in the same structure. // Verify that the item and player are in the same structure. CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())); if(!playerCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return; } uint64 playerStructure = playerCell->getParentId(); CellObject* objectCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(object->getParentId())); if(!objectCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return; } uint64 objectStructure = objectCell->getParentId(); if (objectStructure != playerStructure) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return; } // Verify that the player has appropriate rights on this structure. if (playerCell) { if (BuildingObject* building = dynamic_cast<BuildingObject*>(gWorldManager->getObjectById(playerCell->getParentId()))) { if (!building->hasAdminRights(player->getId())) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "admin_move_only"), player); return; } } else { assert(false && "ObjectController::HandleItemMoveDown_ no structure"); return; } } else { //were just outside?? return; } object->mPosition.y -= MOVE_INCREMENT; gMessageLib->sendDataTransformWithParent053(object); object->updateWorldPosition(); }
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; }
bool ObjectController::checkContainingContainer(uint64 containingContainer, uint64 playerId) { Object* container = gWorldManager->getObjectById(containingContainer); if(!container) { //it might be our inventory or the inventory of a creature were looting //PlayerObject* player = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(playerId)); if(containingContainer == (playerId + INVENTORY_OFFSET)) { //its our inventory ... - return true return true; } return false; } if(containingContainer == playerId) { //its us return true; } uint64 ownerId = gSpatialIndexManager->getObjectMainParent(container); Object* object = dynamic_cast<Object*>(gWorldManager->getObjectById(ownerId)); //it might be the inventory if(!object) { //Hack ourselves an inventory .... - its not part of the world ObjectMap if((ownerId - INVENTORY_OFFSET) == playerId) { object = gWorldManager->getObjectById(playerId); } } if(BuildingObject* building = dynamic_cast<BuildingObject*>(object)) { if(building->hasAdminRights(playerId) || gWorldConfig->isTutorial()) { return true; } return false; } if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(ownerId))) { if(BuildingObject* building = dynamic_cast<BuildingObject*>(gWorldManager->getObjectById(cell->getParentId()))) { if(building->hasAdminRights(playerId)) { //now test whether we are in the same building PlayerObject* player = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(playerId)); if(CellObject* playercell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId()))) { if(BuildingObject* playerparent = dynamic_cast<BuildingObject*>(gWorldManager->getObjectById(playercell->getParentId()))) { //still get in a range check ??? return true; } } } } return false; } if(PlayerObject* player = dynamic_cast<PlayerObject*>(object)) { if(player->getId() == playerId) { return true; } else return false; } //todo handle factory hoppers //todo handle loot permissions if(CreatureObject* creature = dynamic_cast<CreatureObject*>(object)) { } return true; }
bool ObjectController::_updateInRangeObjectsInside() { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())); // make sure we got a cell if (!playerCell) { gLogger->logMsgF("Error getting cell %"PRIu64" for %"PRIu64" type %u",MSG_NORMAL,player->getParentId(),player->getId(),player->getType()); return true; // We are done, nothing we can do... } // We may wan't to limit the amount of messages sent in one session. uint32 updatedObjects = 0; const uint32 objectSendLimit = 50; //what do we do if the object has been deleted in the meantime? //TODO while ((mObjectSetIt != mInRangeObjects.end()) && (updatedObjects < objectSendLimit)) { // Object* object = (*mObjectSetIt); // Needed since object may be invalid due to the multi-session approach of this function. Object* object = dynamic_cast<Object*>(*mObjectSetIt); // Create objects that are in the same building as we are OR outside near the building. if ((object) && (!player->checkKnownObjects(object))) { bool validObject = true; // Assume it's an object we shall add. // Object inside a building ? if (object->getParentId()) { validObject = false; // Yes, get the objects cell. CellObject* objectCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(object->getParentId())); if (objectCell) { // Are we in the same building? if (objectCell->getParentId() == playerCell->getParentId()) { // We are in the same building as the object. validObject = true; } } else { gLogger->logMsgF("Error getting cell %"PRIu64" for %"PRIu64" type %u",MSG_NORMAL,object->getParentId(),object->getId(),object->getType()); } } if (validObject) { // send the according create for the type of object #if defined(_MSC_VER) if (object->getId() > 0x0000000100000000) #else if (object->getId() > 0x0000000100000000LLU) #endif { //if its an instance and per chance *our* instance if (object->getPrivateOwner()&&object->isOwnedBy(player)) { gMessageLib->sendCreateObject(object,player); player->addKnownObjectSafe(object); object->addKnownObjectSafe(player); updatedObjects++; } else { //if(!player->checkKnownObjects(object)) //{ gMessageLib->sendCreateObject(object,player); player->addKnownObjectSafe(object); object->addKnownObjectSafe(player); updatedObjects++; //} } } } } ++mObjectSetIt; } return (mObjectSetIt == mInRangeObjects.end()); }
//====================================================================================================================== // // Modifies the Admin List // void ObjectController::_handleModifyPermissionList(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { CreatureObject* creature = dynamic_cast<CreatureObject*>(mObject); PlayerObject* player = creature->GetGhost(); if(!player) { DLOG(info) << " ObjectController::_handleModifyPermissionList Player not found"; return; } //find out where our structure is BString dataStr; message->getStringUnicode16(dataStr); BString playerStr,list,action; dataStr.convert(BSTRType_ANSI); int8 s1[64],s2[32],s3[32]; sscanf(dataStr.getAnsi(),"%32s %16s %16s",s1, s2, s3); playerStr = s1; list = s2; action = s3; if(playerStr.getLength() > 40) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "permission_40_char"), player); return; } //TODO is target a structure?? used when using the commandline option uint64 id = player->GetCreature()->getTargetId(); Object* object = gWorldManager->getObjectById(id); PlayerStructure* structure = dynamic_cast<PlayerStructure*>(object); //if we have no structure that way, see whether we have a structure were we just used the adminlist if(!structure) { id = player->getStructurePermissionId(); Object* object = gWorldManager->getObjectById(id); structure = dynamic_cast<PlayerStructure*>(object); } if(!structure) { return; } //is the structure in Range??? float fAdminListDistance = gWorldConfig->getConfiguration<float>("Player_Admin_List_Distance",(float)32.0); if(player->getParentId()) { if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId()))) { if(HouseObject* house = dynamic_cast<HouseObject*>(gWorldManager->getObjectById(cell->getParentId()))) { if(house->getId() != structure->getId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "command_no_building"), player); return; } } } } else if(glm::distance(player->GetCreature()->mPosition, structure->mPosition) > fAdminListDistance) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "command_no_building"), player); return; } player->setStructurePermissionId(0); StructureAsyncCommand command; command.PlayerId = player->getId(); command.StructureId = structure->getId(); command.List = list; command.PlayerStr = playerStr.getAnsi(); if(action == "add") { command.Command = Structure_Command_AddPermission; gStructureManager->checkNameOnPermissionList(structure->getId(),player->getId(),player->GetCreature()->getFirstName(),"ADMIN",command); //addNametoPermissionList(command.StructureId, command.PlayerId, command.PlayerStr, command.List); } if(action == "remove") { command.Command = Structure_Command_RemovePermission; gStructureManager->checkNameOnPermissionList(structure->getId(),player->getId(),player->GetCreature()->getFirstName(),"ADMIN",command); } }
void ObjectController::_handleNPCConversationStart(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); NPCObject* npc = dynamic_cast<NPCObject*>(gWorldManager->getObjectById(targetId)); if(!npc) { DLOG(info) << "ObjController::_handleNPCConversationStart: Couldn't find object " << targetId; return; } // in range check uint64 playerParentId = player->getParentId(); uint64 npcParentId = npc->getParentId(); bool inRange = true; uint64 playerBuildingId = 0; uint64 npcBuildingId = 0; //get building Ids if they are in buildings if(playerParentId) { playerBuildingId = gWorldManager->getObjectById(playerParentId)->getParentId(); } if(npcParentId) { npcBuildingId = gWorldManager->getObjectById(npcParentId)->getParentId(); } // not inside same parent, or out of range float distance = glm::distance(player->getWorldPosition(), npc->getWorldPosition()); if ((npcBuildingId != playerParentId) || distance > 10.0f) { inRange = false; } // we are out of range if(!inRange) { float distance = glm::distance(player->mPosition, npc->mPosition); char buffer[100]; sprintf(buffer, "You are out of range (%f m).", distance); BString msg(buffer); msg.convert(BSTRType_Unicode16); gMessageLib->SendSystemMessage(msg.getUnicode16(), player); // gMessageLib->sendSystemMessage(player,L"","system_msg","out_of_range"); return; } //check to see if he is part of a mission /*if(gMissionManager->checkDeliverMission(player,npc) || gMissionManager->checkCraftingMission(player,npc) ) return;*/ // we don't want him to talk if(npc->hasInternalAttribute("no_chat")) return; // initiate a conversation dialog if(npc->hasInternalAttribute("base_conversation")) { // Let the npc have your attention, and some npc-movement. npc->prepareConversation(player); gConversationManager->startConversation(npc,player); } // say some chatter else { // spam protection uint64 localTime = Anh_Utils::Clock::getSingleton()->getLocalTime(); if(npc->getLastConversationTarget() == player->getId()) { if(localTime - npc->getLastConversationRequest() < NPC_CHAT_SPAM_PROTECTION_TIME) { return; } else { npc->setLastConversationRequest(localTime); } } else { npc->setLastConversationRequest(localTime); npc->setLastConversationTarget(player->getId()); } // Let the npc have your attention, and some npc-movement. // Nope... npc->prepareConversation(player); std::wstring npc_chat; uint32_t animation = 0; // say a specific preset sentence if(npc->hasInternalAttribute("npc_chat")) { std::string tmp = npc->getInternalAttribute<std::string>("npc_chat"); npc_chat = std::wstring(tmp.begin(), tmp.end()); } else { std::pair<std::wstring,uint32> chat = gWorldManager->getRandNpcChatter(); npc_chat = chat.first; animation = chat.second; } if (!gWorldConfig->isInstance()) { gMessageLib->SendSpatialChat(npc, npc_chat, player); if (animation) gMessageLib->sendCreatureAnimation(npc,gWorldManager->getNpcConverseAnimation(animation)); } else { gMessageLib->SendSpatialChat(npc, npc_chat, player); if (animation) gMessageLib->sendCreatureAnimation(npc,gWorldManager->getNpcConverseAnimation(animation), player); } } }
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); }
bool ArtisanManager::handleRequestSurvey(Object* playerObject,Object* target,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(playerObject); std::shared_ptr<SimpleEvent> start_survey_event = nullptr; if(cmdProperties) mSurveyMindCost = cmdProperties->mMindCost; // don't allow survey in buildings if(player->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), player); return false; } if(player->getPerformingState() != PlayerPerformance_None) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), player); return false; } if(player->getSurveyState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_cant"), player); return false; } if(player->getSamplingState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_sample"), player); 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(tool && resource) { player->setSurveyState(true); // play effect std::string effect = gWorldManager->getClientEffect(tool->getInternalAttribute<uint32>("survey_effect")); gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,player); PlayerObjectSet* playerList = player->getKnownPlayers(); PlayerObjectSet::iterator it = playerList->begin(); while(it != playerList->end()) { gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,(*it)); ++it; } uint32 mindCost = mSurveyMindCost; Ham* hamz = player->getHam(); //are we able to sample in the first place ?? if(!hamz->checkMainPools(0,0,mindCost)) { int32 myMind = hamz->mAction.getCurrentHitPoints(); //return message for sampling cancel based on HAM if(myMind < (int32)mindCost) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "sample_mind"), player); } //message for stop sampling gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_cancel"), player); player->getSampleData()->mPendingSurvey = false; hamz->updateRegenRates(); player->updateMovementProperties(); return false; } hamz->performSpecialAction(0,0,(float)mindCost,HamProperty_CurrentHitpoints); // send system message resourceName.convert(BSTRType_Unicode16); gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "start_survey", L"", L"", resourceName.getUnicode16()), player); // schedule execution start_survey_event = std::make_shared<SimpleEvent>(EventType("start_survey"),0, 5000, std::bind(&ArtisanManager::surveyEvent, this, player, resource, tool)); } else { gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_nothingfound")); return false; } // notify any listeners if (start_survey_event) gEventDispatcher.Notify(start_survey_event); return true; }
bool WorldManager::addObject(Object* object,bool manual) { uint64 key = object->getId(); //make sure objects arnt added several times!!!! if(getObjectById(key)) { gLogger->logMsgF("WorldManager::addObject Object already existant added several times or ID messup ???",MSG_HIGH); return false; } mObjectMap.insert(key,object); // if we want to set the parent manually or the object is from the snapshots and not a building, return if(manual) { return true; } #if defined(_MSC_VER) if(object->getId() < 0x0000000100000000 && object->getType() != ObjType_Building) #else if(object->getId() < 0x0000000100000000LLU && object->getType() != ObjType_Building) #endif { // check if a crafting station - in that case add Item* item = dynamic_cast<Item*> (object); if(item) { if(!(item->getItemFamily() == ItemFamily_CraftingStations)) return true; } else { return true; } } switch(object->getType()) { // player, when a player enters a planet case ObjType_Player: { PlayerObject* player = dynamic_cast<PlayerObject*>(object); gLogger->logMsgF("New Player: %"PRIu64", Total Players on zone : %i",MSG_NORMAL,player->getId(),(getPlayerAccMap())->size() + 1); // insert into the player map mPlayerAccMap.insert(std::make_pair(player->getAccountId(),player)); // insert into cell if(player->getParentId()) { player->setSubZoneId(0); if(CellObject* cell = dynamic_cast<CellObject*>(getObjectById(player->getParentId()))) { cell->addObjectSecure(player); } else { gLogger->logMsgF("WorldManager::addObject: couldn't find cell %"PRIu64"",MSG_HIGH,player->getParentId()); } } // query the rtree for the qt region we are in else { if(QTRegion* region = mSpatialIndex->getQTRegion(player->mPosition.x,player->mPosition.z)) { player->setSubZoneId((uint32)region->getId()); region->mTree->addObject(player); } else { // we should never get here ! gLogger->logMsg("WorldManager::addObject: could not find zone region in map"); return false; } } // initialize initObjectsInRange(player); gMessageLib->sendCreatePlayer(player,player); // add ham to regeneration scheduler player->getHam()->updateRegenRates(); // ERU: Note sure if this is needed here. player->getHam()->checkForRegen(); // onPlayerEntered event, notify scripts string params; params.setLength(sprintf(params.getAnsi(),"%s %s %u",getPlanetNameThis(),player->getFirstName().getAnsi(),static_cast<uint32>(mPlayerAccMap.size()))); mWorldScriptsListener.handleScriptEvent("onPlayerEntered",params); // Start player world position update. Used when player don't get any events from client (player not moving). // addPlayerMovementUpdateTime(player, 1000); } break; case ObjType_Structure: { // HarvesterObject* harvester = dynamic_cast<HarvesterObject*>(object); mStructureList.push_back(object->getId()); mSpatialIndex->InsertPoint(key,object->mPosition.x,object->mPosition.z); } break; case ObjType_Building: { mStructureList.push_back(object->getId()); BuildingObject* building = dynamic_cast<BuildingObject*>(object); mSpatialIndex->InsertRegion(key,building->mPosition.x,building->mPosition.z,building->getWidth(),building->getHeight()); } break; case ObjType_Tangible: { uint64 parentId = object->getParentId(); if(parentId == 0) { mSpatialIndex->InsertPoint(key,object->mPosition.x,object->mPosition.z); } else { CellObject* cell = dynamic_cast<CellObject*>(getObjectById(parentId)); if(cell) cell->addObjectSecure(object); else gLogger->logMsgF("WorldManager::addObject couldn't find cell %"PRIu64"",MSG_NORMAL,parentId); } } break; // TODO: add moving creatures to qtregions case ObjType_NPC: case ObjType_Creature: case ObjType_Lair: { CreatureObject* creature = dynamic_cast<CreatureObject*>(object); if(creature->getCreoGroup() == CreoGroup_Shuttle) mShuttleList.push_back(dynamic_cast<Shuttle*>(creature)); uint64 parentId = creature->getParentId(); if(parentId) { CellObject* cell = dynamic_cast<CellObject*>(getObjectById(parentId)); if(cell) cell->addObjectSecure(creature); else gLogger->logMsgF("WorldManager::addObject: couldn't find cell %"PRIu64"",MSG_HIGH,parentId); } else { switch(creature->getCreoGroup()) { // moving creature, add to QT case CreoGroup_Vehicle : { if(QTRegion* region = mSpatialIndex->getQTRegion(creature->mPosition.x,creature->mPosition.z)) { creature->setSubZoneId((uint32)region->getId()); region->mTree->addObject(creature); } else { gLogger->logMsg("WorldManager::addObject: could not find zone region in map for creature"); return false; } } break; // still creature, add to SI default : { mSpatialIndex->InsertPoint(key,creature->mPosition.x,creature->mPosition.z); } } } } break; case ObjType_Region: { RegionObject* region = dynamic_cast<RegionObject*>(object); mRegionMap.insert(std::make_pair(key,region)); mSpatialIndex->InsertRegion(key,region->mPosition.x,region->mPosition.z,region->getWidth(),region->getHeight()); if(region->getActive()) addActiveRegion(region); } break; case ObjType_Intangible: { gLogger->logMsgF("Object of type ObjType_Intangible UNHANDLED in WorldManager::addObject:",MSG_HIGH); } break; default: { gLogger->logMsgF("Unhandled ObjectType in WorldManager::addObject: PRId32",MSG_HIGH,object->getType()); // Please, when adding new stufff, at least take the time to add a stub for that type. // Better fail always, than have random crashes. assert(false && "WorldManager::addObject Unhandled ObjectType"); } break; } return true; }
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; }
void WorldManager::savePlayerSync(uint32 accId,bool remove) { PlayerObject* playerObject = getPlayerByAccId(accId); Ham* ham = playerObject->getHam(); mDatabase->destroyResult(mDatabase->executeSynchSql("UPDATE characters SET parent_id=%"PRIu64",oX=%f,oY=%f,oZ=%f,oW=%f,x=%f,y=%f,z=%f,planet_id=%u WHERE id=%"PRIu64"",playerObject->getParentId() ,playerObject->mDirection.x,playerObject->mDirection.y,playerObject->mDirection.z,playerObject->mDirection.w ,playerObject->mPosition.x,playerObject->mPosition.y,playerObject->mPosition.z ,mZoneId,playerObject->getId())); mDatabase->destroyResult(mDatabase->executeSynchSql("UPDATE character_attributes SET health_current=%u,action_current=%u,mind_current=%u" ",health_wounds=%u,strength_wounds=%u,constitution_wounds=%u,action_wounds=%u,quickness_wounds=%u" ",stamina_wounds=%u,mind_wounds=%u,focus_wounds=%u,willpower_wounds=%u,battlefatigue=%u,posture=%u,moodId=%u,title=\'%s\'" ",character_flags=%u,states=%"PRIu64",language=%u, group_id=%"PRIu64" WHERE character_id=%"PRIu64"", ham->mHealth.getCurrentHitPoints() - ham->mHealth.getModifier(), //Llloydyboy Added the -Modifier so that when buffs are reinitialised, it doesn't screw up HAM ham->mAction.getCurrentHitPoints() - ham->mAction.getModifier(), //Llloydyboy Added the -Modifier so that when buffs are reinitialised, it doesn't screw up HAM ham->mMind.getCurrentHitPoints() - ham->mMind.getModifier(), //Llloydyboy Added the -Modifier so that when buffs are reinitialised, it doesn't screw up HAM ham->mHealth.getWounds(), ham->mStrength.getWounds(), ham->mConstitution.getWounds(), ham->mAction.getWounds(), ham->mQuickness.getWounds(), ham->mStamina.getWounds(), ham->mMind.getWounds(), ham->mFocus.getWounds(), ham->mWillpower.getWounds(), ham->getBattleFatigue(), playerObject->states.getPosture(), playerObject->getMoodId(), playerObject->getTitle().getAnsi(), playerObject->getPlayerFlags(), playerObject->states.getAction(), playerObject->getLanguage(), playerObject->getGroupId(), playerObject->getId())); gBuffManager->SaveBuffs(playerObject, GetCurrentGlobalTick()); if(remove) destroyObject(playerObject); }
void WorldManager::savePlayer(uint32 accId,bool remove, WMLogOut mLogout, CharacterLoadingContainer* clContainer) { PlayerObject* playerObject = getPlayerByAccId(accId); if(!playerObject) { DLOG(INFO) << "WorldManager::savePlayer could not find player with AccId:" <<accId<<", save aborted."; return; } // WMQuery_SavePlayer_Position is the query handler called by the buffmanager when all the buffcallbacks are finished // we prepare the asynccontainer here already WMAsyncContainer* asyncContainer = new(mWM_DB_AsyncPool.ordered_malloc()) WMAsyncContainer(WMQuery_SavePlayer_Position); if(remove) { asyncContainer->mBool = true; } //clarify what handler we have to call after saving - if any asyncContainer->mObject = playerObject; asyncContainer->mLogout = mLogout; asyncContainer->clContainer = clContainer; switch (mLogout) { case WMLogOut_LogOut: case WMLogOut_Char_Load: mDatabase->executeSqlAsync(this,asyncContainer,"UPDATE characters SET parent_id=%"PRIu64",oX=%f,oY=%f,oZ=%f,oW=%f,x=%f,y=%f,z=%f,planet_id=%u,jedistate=%u WHERE id=%"PRIu64"",playerObject->getParentId() ,playerObject->mDirection.x,playerObject->mDirection.y,playerObject->mDirection.z,playerObject->mDirection.w ,playerObject->mPosition.x,playerObject->mPosition.y,playerObject->mPosition.z ,mZoneId,playerObject->getJediState(),playerObject->getId()); break; case WMLogOut_No_LogOut: case WMLogOut_Zone_Transfer: //start by saving the buffs the buffmanager will deal with the buffspecific db callbacks and start the position safe at their end //which will return its callback to the worldmanager //if no buff was there to be saved we will continue directly if(playerObject && playerObject->isConnected() && !playerObject->isBeingDestroyed()) { if(!gBuffManager->SaveBuffsAsync(asyncContainer, this, playerObject, GetCurrentGlobalTick())) { // position save will be called by the buff callback if there is any buff mDatabase->executeSqlAsync(this,asyncContainer,"UPDATE characters SET parent_id=%"PRIu64",oX=%f,oY=%f,oZ=%f,oW=%f,x=%f,y=%f,z=%f,planet_id=%u,jedistate=%u WHERE id=%"PRIu64"",playerObject->getParentId() ,playerObject->mDirection.x,playerObject->mDirection.y,playerObject->mDirection.z,playerObject->mDirection.w ,playerObject->mPosition.x,playerObject->mPosition.y,playerObject->mPosition.z ,mZoneId,playerObject->getJediState(),playerObject->getId()); } } break; default: DLOG(INFO) << "We should never get in here, make sure to call savePlayer with the enum WMLogOut"; } }
void TicketCollector::handleUIEvent(uint32 action,int32 element,BString inputStr,UIWindow* window) { if (!action && element != -1 && mShuttle != NULL && mShuttle->availableInPort()) { uint32 zoneId = gWorldManager->getZoneId(); PlayerObject* playerObject = window->getOwner(); if(playerObject->getSurveyState() || playerObject->getSamplingState() || playerObject->isIncapacitated() || playerObject->isDead()) { return; } // in range check if(playerObject->getParentId() != mParentId || (glm::distance(playerObject->mPosition, this->mPosition) > 10.0f)) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "boarding_too_far"), playerObject); return; } ObjectIDList* invObjects = dynamic_cast<Inventory*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Inventory))->getObjects(); ObjectIDList::iterator it = invObjects->begin(); while(it != invObjects->end()) { if(TravelTicket* ticket = dynamic_cast<TravelTicket*>(gWorldManager->getObjectById((*it)))) { BString srcPoint = (int8*)((ticket->getAttribute<std::string>("travel_departure_point")).c_str()); BString dstPointStr = (int8*)((ticket->getAttribute<std::string>("travel_arrival_point")).c_str()); uint16 srcPlanetId = static_cast<uint16>(gWorldManager->getPlanetIdByName((int8*)((ticket->getAttribute<std::string>("travel_departure_planet")).c_str()))); uint16 dstPlanetId = static_cast<uint16>(gWorldManager->getPlanetIdByName((int8*)((ticket->getAttribute<std::string>("travel_arrival_planet")).c_str()))); BStringVector* items = (dynamic_cast<UIListBox*>(window))->getDataItems(); BString selectedDst = items->at(element); selectedDst.convert(BSTRType_ANSI); if(srcPlanetId == zoneId && (strcmp(srcPoint.getAnsi(),mPortDescriptor.getAnsi()) == 0) && (strcmp(dstPointStr.getAnsi(),selectedDst.getAnsi()) == 0)) { if(TravelPoint* dstPoint = gTravelMapHandler->getTravelPoint(dstPlanetId,dstPointStr)) { glm::vec3 destination; // getRand(5) return 0-4, then sub 2, and you get equal of random values at both sides of zero. (-2, -1, 0, 1, 2) destination.x = dstPoint->spawnX + (gRandom->getRand()%5 - 2); destination.y = dstPoint->spawnY; destination.z = dstPoint->spawnZ + (gRandom->getRand()%5 - 2); // If it's on this planet, then just warp, otherwize zone if(dstPlanetId == zoneId) { // only delete the ticket if we are warping on this planet. TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById(ticket->getParentId())); gContainerManager->deleteObject(ticket, tO); gWorldManager->warpPlanet(playerObject,destination,0); } else { gMessageLib->sendClusterZoneTransferRequestByTicket(playerObject, ticket->getId(), dstPoint->planetId); } } else { DLOG(info) << "TicketCollector: Error getting TravelPoint"; } break; } } ++it; } } }
//====================================================================================================================== // // rotates an item // void ObjectController::HandleRotateFurniture_( uint64 targetId, Message* message, ObjectControllerCmdProperties* cmdProperties) { CreatureObject* creature = dynamic_cast<CreatureObject*>(mObject); PlayerObject* player = creature->GetGhost(); if (!player) { assert(false && "ObjectController::HandleRotateFurniture_ Player not found"); return; } // Verify that there was a target passed. if (!targetId) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } Object* object = gWorldManager->getObjectById(targetId); if(!object) { assert(false && "ObjectController::HandleRotateFurniture_ item not found"); return; } // Verify that the item and player are in the same structure. CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())); if(!playerCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } uint64 playerStructure = playerCell->getParentId(); CellObject* objectCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(object->getParentId())); if(!objectCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } uint64 objectStructure = objectCell->getParentId(); if (objectStructure != playerStructure) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } // Verify that the player has appropriate rights on this structure. if (playerCell) { if (BuildingObject* building = dynamic_cast<BuildingObject*>(gWorldManager->getObjectById(playerCell->getParentId()))) { if (!building->getAdminData().check_admin(player->getId())) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "admin_move_only"), player); return; } } else { assert(false && "ObjectController::HandleRotateFurniture_ no structure"); return; } } else { //were just outside?? return; } // Read the message out of the packet. BString tmp; message->getStringUnicode16(tmp); // If the string has no length the message is ill-formatted, send the // proper format to the client. if (!tmp.getLength()) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "format_rotatefurniture_degrees"), player); return; } // Convert the string to an ansi string for ease with the regex. tmp.convert(BSTRType_ANSI); std::string input_string(tmp.getAnsi()); static const regex pattern("(right|left) ([0-9]+)"); smatch result; regex_search(input_string, result, pattern); // If the pattern doesn't match all elements then send the proper format // to the client. if (result.length() < 2) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "format_rotatefurniture_degrees"), player); return; } // Gather the results of the pattern for validation and use. std::string direction(result[1]); float degrees = boost::lexical_cast<float>(result[2]); // If the the specified amount is not within the valid range notify the client. if (degrees < 1.0f || degrees > 180.0f) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_params"), player); return; } // Rotate by the necessary amount. if (direction.compare("left") == 0) { object->rotateLeft(degrees); } else { object->rotateRight(degrees); } // Update the world with the changes. gMessageLib->sendDataTransformWithParent053(object); object->updateWorldPosition(); }
void SurveyTool::handleObjectMenuSelect(uint8 messageType,Object* srcObject) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(srcObject); if( !(playerObject->isConnected()) || playerObject->isDead()) return; // bring up the surve ui switch(messageType) { case radId_itemUse: { //We only need to check this when using the tool's functions! if(playerObject->getPerformingState() != PlayerPerformance_None || playerObject->isDead()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_cant"), playerObject); return; } // verify we are able to use this if(!(playerObject->verifyAbility(opOCsurvey))) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "insufficient_skill"), playerObject); return; } if(playerObject->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), playerObject); return; } //check whether the tool is initialized already - if not initialize int32 range = getInternalAttribute<int32>("survey_range"); if(range < 0 ) { _createRangeMenu(playerObject, true); return; } StartUsing(playerObject); } break; case radId_serverSurveyToolRange: { if(!(playerObject->verifyAbility(opOCsurvey))) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "insufficient_skill"), playerObject); return; } _createRangeMenu(playerObject); } break; } }
//========================================================================================= // // Find the objects observed/known objects when inside // void ObjectController::_findInRangeObjectsInside(bool updateAll) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); float viewingRange = _GetMessageHeapLoadViewingRange(); CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())); // Make Set ready, mInRangeObjects.clear(); // Init the iterator. mObjectSetIt = mInRangeObjects.begin(); // make sure we got a cell if (!playerCell) { gLogger->logMsg("ERROR: No playerCell."); return; } Object* object = gWorldManager->getObjectById(playerCell->getParentId()); //BuildingObject* building = dynamic_cast<BuildingObject*>(object); BuildingObject* building = dynamic_cast<BuildingObject*>(object); // make sure we got a building if (!building) { gLogger->logMsg("ERROR: No building."); return; } // mInRangeObjectIndex = 0; if (updateAll) { // This is good to use when entering a building. mSI->getObjectsInRange(player,&mInRangeObjects,(ObjType_Player | ObjType_Tangible | ObjType_NPC | ObjType_Creature | ObjType_Building | ObjType_Structure),viewingRange); // query the qtree based on the buildings world position if (QTRegion* region = mSI->getQTRegion(building->mPosition.x,building->mPosition.z)) { Anh_Math::Rectangle qRect = Anh_Math::Rectangle(building->mPosition.x - viewingRange,building->mPosition.z - viewingRange,viewingRange * 2,viewingRange * 2); // We need to find moving creatures outside... region->mTree->getObjectsInRange(player,&mInRangeObjects,ObjType_Player | ObjType_NPC | ObjType_Creature, &qRect); } } else { // This is good to use when running around inside a building. // We need to see player or creatures spawning inside. // Added ObjType_Tangible because Tutorial spawns ObjType_Tangible in a way we don't normally do. // If we need more speed in normal cases, just add a test for Tutorial and de-select ObjType_Tangible if not active. mSI->getObjectsInRange(player,&mInRangeObjects,(ObjType_Tangible | ObjType_Player | ObjType_Creature | ObjType_NPC),viewingRange); // query the qtree based on the buildings world position if (QTRegion* region = mSI->getQTRegion(building->mPosition.x,building->mPosition.z)) { Anh_Math::Rectangle qRect = Anh_Math::Rectangle(building->mPosition.x - viewingRange,building->mPosition.z - viewingRange,viewingRange * 2,viewingRange * 2); // We need to find moving creatures outside... region->mTree->getObjectsInRange(player,&mInRangeObjects,ObjType_Player | ObjType_NPC | ObjType_Creature,&qRect); } } // Update the iterator to start of Set. mObjectSetIt = mInRangeObjects.begin(); }
void BuffManager::handleDatabaseJobComplete(void *ref, DatabaseResult *result) { buffAsyncContainer* asyncContainer = reinterpret_cast<buffAsyncContainer*>(ref); if(!asyncContainer) { if(result) //mDatabase->DestroyResult(result); return; } switch(asyncContainer->mQueryType) { //we started saving a player ASync - give it back to the WorldManager case BMQuery_Save_Async: { //get the player and check whether this was the last buff callback PlayerObject* playerObject = asyncContainer->player; playerObject->DecBuffAsyncCount(); //if this is the last callback continue with saving the players data if(!playerObject->GetBuffAsyncCount()) { //the asynccontainer was prepared by the worldmanager WMAsyncContainer* asContainer = asyncContainer->asyncContainer; // position save - the callback will be in the worldmanager to proceed with the rest of the safe mDatabase->executeSqlAsync(reinterpret_cast<DatabaseCallback*>(asyncContainer->callBack),asContainer,"UPDATE %s.characters SET parent_id=%" PRIu64 ",oX=%f,oY=%f,oZ=%f,oW=%f,x=%f,y=%f,z=%f,planet_id=%u,jedistate=%u WHERE id=%" PRIu64 "", mDatabase->galaxy(),playerObject->getParentId() ,playerObject->mDirection.x,playerObject->mDirection.y,playerObject->mDirection.z,playerObject->mDirection.w ,playerObject->mPosition.x,playerObject->mPosition.y,playerObject->mPosition.z ,gWorldManager->getZoneId(),playerObject->getJediState(),playerObject->getId()); //Free up Memory SAFE_DELETE(asyncContainer); BuffList::iterator it = playerObject->GetBuffList()->begin(); while(it != playerObject->GetBuffList()->end()) { SAFE_DELETE(*it); it = playerObject->GetBuffList()->erase(it); } } } break; case BMQuery_Buffs: { LoadBuffsFromResult(asyncContainer, result); } break; case BMQuery_Buff_Attributes: { LoadBuffAttributesFromResult(asyncContainer, result); } break; case BMQuery_Delete: { SAFE_DELETE(asyncContainer); } break; case BMQuery_Null: { } break; default: { } break; } }
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; }
bool ArtisanManager::handleRequestSurvey(Object* playerObject,Object* target,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(playerObject); std::shared_ptr<SimpleEvent> start_survey_event = nullptr; if(cmdProperties) mSurveyMindCost = cmdProperties->mMindCost; // don't allow survey in buildings if(player->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), player); return false; } if(player->GetCreature()->getPerformingState() != PlayerPerformance_None) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), player); return false; } if(player->getSurveyState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_cant"), player); return false; } if(player->getSamplingState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_sample"), player); return false; } // checks if we are in combat, dead or incapacitated if (player->GetCreature()->states.checkState(CreatureState_Combat) || player->GetCreature()->states.checkPosture(CreaturePosture_Dead) || player->GetCreature()->states.checkLocomotion(CreatureLocomotion_Incapacitated)) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), player); 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(tool && resource) { player->setSurveyState(true); // play effect std::string effect = gWorldManager->getClientEffect(tool->getInternalAttribute<uint32>("survey_effect")); gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,player); gContainerManager->sendToRegisteredWatchers(player, [effect, player] (PlayerObject* const recipient) { gMessageLib->sendPlayClientEffectLocMessage(effect, player->mPosition, recipient); }); auto ham = gWorldManager->getKernel()->GetServiceManager()->GetService<swganh::ham::HamService>("HamService"); uint32 survey_cost = mSurveyMindCost; //are we able to sample in the first place ?? if(!ham->ApplyModifiedHamCosts(player->GetCreature(), 0, 0, survey_cost)) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "sample_mind"), player); //message for stop sampling gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_cancel"), player); player->getSampleData()->mPendingSurvey = false; player->GetCreature()->updateMovementProperties(); return false; } // send system message resourceName.convert(BSTRType_Unicode16); gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "start_survey", L"", L"", resourceName.getUnicode16()), player); // schedule execution start_survey_event = std::make_shared<SimpleEvent>(EventType("start_survey"),0, 5000, std::bind(&ArtisanManager::surveyEvent, this, player, resource, tool)); } else { gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_nothingfound")); return false; } // notify any listeners if (start_survey_event) gEventDispatcher.Notify(start_survey_event); return true; }
void TravelMapHandler::handleUIEvent(uint32 action,int32 element,BString inputStr,UIWindow* window) { if(!action && element != -1 ) { uint32 zoneId = gWorldManager->getZoneId(); PlayerObject* playerObject = window->getOwner(); UITicketSelectListBox* listBox = dynamic_cast<UITicketSelectListBox*>(window); if(playerObject->getSurveyState() || playerObject->getSamplingState() || !listBox) return; Shuttle* shuttle = listBox->getShuttle(); if(!shuttle) { return; } if (!shuttle->availableInPort()) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "shuttle_not_available"), playerObject); return; } if((playerObject->getParentId() != shuttle->getParentId()) || (glm::distance(playerObject->mPosition, shuttle->mPosition) > 25.0f)) { gMessageLib->SendSystemMessage(::common::OutOfBand("travel", "boarding_too_far"), playerObject); return; } ObjectIDList* invObjects = dynamic_cast<Inventory*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Inventory))->getObjects(); ObjectIDList::iterator it = invObjects->begin(); while(it != invObjects->end()) { TravelTicket* ticket = dynamic_cast<TravelTicket*>(gWorldManager->getObjectById((*it))); if(ticket) { BString srcPoint = (int8*)((ticket->getAttribute<std::string>("travel_departure_point")).c_str()); BString dstPointStr = (int8*)((ticket->getAttribute<std::string>("travel_arrival_point")).c_str()); uint16 srcPlanetId = static_cast<uint8>(gWorldManager->getPlanetIdByName((int8*)((ticket->getAttribute<std::string>("travel_departure_planet")).c_str()))); uint16 dstPlanetId = static_cast<uint8>(gWorldManager->getPlanetIdByName((int8*)((ticket->getAttribute<std::string>("travel_arrival_planet")).c_str()))); BStringVector* items = (dynamic_cast<UIListBox*>(window))->getDataItems(); BString selectedDst = items->at(element); selectedDst.convert(BSTRType_ANSI); if(srcPlanetId == zoneId && (strcmp(dstPointStr.getAnsi(),selectedDst.getAnsi()) == 0)&&(strcmp(srcPoint.getAnsi(),listBox->getPort().getAnsi()) == 0)) { TravelPoint* dstPoint = gTravelMapHandler->getTravelPoint(dstPlanetId,dstPointStr); if(dstPoint != NULL) { glm::vec3 destination; destination.x = dstPoint->spawnX + (gRandom->getRand()%5 - 2); destination.y = dstPoint->spawnY; destination.z = dstPoint->spawnZ + (gRandom->getRand()%5 - 2); // If it's on this planet, then just warp, otherwize zone if(dstPlanetId == zoneId) { // only delete the ticket if we are warping on this planet. TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById(ticket->getParentId())); gContainerManager->deleteObject(ticket, tO); gWorldManager->warpPlanet(playerObject,destination,0); } else { gMessageLib->sendClusterZoneTransferRequestByTicket(playerObject,ticket->getId(), dstPoint->planetId); } } else { } break; } } ++it; } } }
bool HandleMoveFurniture( Object* object, Object* target, Message* message, ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(object); if (!player) { assert(false && "ObjectController::HandleItemMoveDown_ Player not found"); return false; } // Verify that there was a target passed. if (!target) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return false; } if(!target) { assert(false && "ObjectController::HandleItemMoveDown_ item not found"); return false; } // Verify that the item and player are in the same structure. CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())); if(!playerCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return false; } uint64 playerStructure = playerCell->getParentId(); CellObject* objectCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(object->getParentId())); if(!objectCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return false; } uint64 objectStructure = objectCell->getParentId(); if (objectStructure != playerStructure) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "move_what"), player); return false; } // Verify that the player has appropriate rights on this structure. if (playerCell) { if (BuildingObject* building = dynamic_cast<BuildingObject*>(gWorldManager->getObjectById(playerCell->getParentId()))) { if (!building->getAdminData().check_admin(player->getId())) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "admin_move_only"), player); return false; } } else { assert(false && "ObjectController::HandleItemMoveDown_ no structure"); return false; } } else { //were just outside ?? return false; } // Read the message out of the packet. BString tmp; message->getStringUnicode16(tmp); // If the string has no length the message is ill-formatted, send the // proper format to the client. if (!tmp.getLength()) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "format_movefurniture_distance"), player); return false; } // Convert the string to an ansi string for ease with the regex. tmp.convert(BSTRType_ANSI); std::string input_string(tmp.getAnsi()); static const regex pattern("(forward|back|up|down) ([0-9]+)"); smatch result; regex_search(input_string, result, pattern); // If the pattern doesn't match all elements then send the proper format // to the client. if (result.length() < 2) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "format_movefurniture_distance"), player); return false; } // Gather the results of the pattern for validation and use. std::string direction(result[1]); float distance = boost::lexical_cast<float>(result[2]); // If the the specified amount is not within the valid range notify the client. if ((distance < 1.0f) || (distance > 500.0f)) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "movefurniture_params"), player); return false; } // Move object an MOVE_INCREMENT times by the amount and direction specified. if (direction == "forward") { target->move(player->mDirection, distance * MOVE_INCREMENT); } else if (direction == "back") { target->move(player->mDirection, -distance * MOVE_INCREMENT); } else if (direction == "up") { target->mPosition.y += distance * MOVE_INCREMENT; } else if (direction == "down") { target->mPosition.y -= distance * MOVE_INCREMENT; } // Update the world with the changes. gMessageLib->sendDataTransformWithParent053(target); target->updateWorldPosition(); return true; }
void ObjectController::handleObjectMenuRequest(Message* message) { //for ever item where we request a radial the client starts by displaying a radial on his own and additionally sends a //objectMenuRequest to the server //The server then either just resends the radial as send by the client or adds / modifies options on his own //this is why sometimes when lag is involved it takes some time for all options to display PlayerObject* playerObject = dynamic_cast<PlayerObject*>(mObject); message->getUint32(); // unknown uint64 requestedObjectId = message->getUint64(); message->getUint64(); // player id again ? Object* requestedObject = gWorldManager->getObjectById(requestedObjectId); uint32 itemCount = message->getUint32(); BString extendedDescription; MenuItemList menuItemList; MenuItem* menuItem; for(uint32 i = 0; i < itemCount; i++) { menuItem = new(MenuItem); menuItem->sItem = message->getUint8(); // item nr menuItem->sSubMenu = message->getUint8(); // submenu flag menuItem->sIdentifier = message->getUint8(); // item identifier menuItem->sOption = message->getUint8(); // extended option message->getStringUnicode16(extendedDescription); menuItemList.push_back(menuItem); } uint8 responseNr = message->getUint8(); if(!requestedObject) { if(playerObject->isConnected()) gMessageLib->sendEmptyObjectMenuResponse(requestedObjectId,playerObject,responseNr,menuItemList); //the list is cleared and items are destroyed in the message lib //for the default response return; } requestedObject->setMenuList(&menuItemList); //are we an item dropped in a structure awaiting to be moved or picked u`p? //just implement this virtual function for items as we need just one central point instead //of the same code over and over for all items CellObject* itemCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(requestedObject->getParentId())); Item* item = dynamic_cast<Item*>(requestedObject); ResourceContainer* rC = dynamic_cast<ResourceContainer*>(requestedObject); TangibleObject* tO = dynamic_cast<TangibleObject*>(requestedObject); //only display that menu when *we* and the item are in the same structure if((rC || item) && itemCell && (!tO->getStatic())) { CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(playerObject->getParentId())); if(playerCell && (playerCell->getParentId() == itemCell->getParentId())) { PlayerStructure* pS = dynamic_cast<PlayerStructure*>(gWorldManager->getObjectById(playerCell->getParentId())); if(pS) requestedObject->prepareCustomRadialMenuInCell(playerObject,static_cast<uint8>(itemCount)); } } /* if(rc && requestedObject->getParentId()) { if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(requestedObject->getParentId()))) { requestedObject->prepareCustomRadialMenuInCell(playerObject,static_cast<uint8>(itemCount)); } } */ //delete the radials after every use or provide every object with set rules when to delete it ? if(!requestedObject->getRadialMenu()) requestedObject->prepareCustomRadialMenu(playerObject,static_cast<uint8>(itemCount)); if (requestedObject->getRadialMenu()) { if(playerObject->isConnected()) { gMessageLib->sendObjectMenuResponse(requestedObject,playerObject,responseNr); } //they only reset if the objects virtual function does it //by default it stays requestedObject->ResetRadialMenu(); //the radial menu is supposed to be an intelligent pointer deleting itself when no reference is left //however during runtime the item always references the radialmenu that was generated for it on the first call. //when the circumstances of the item change we need to delete the pointer and thus force it to generate a new radial } else { // putting this for static objects/objects that are not known by the server yet // send a default menu,so client stops flooding us with requests //empty might just mean that the clients radial is sufficient if(playerObject->isConnected()) gMessageLib->sendEmptyObjectMenuResponse(requestedObjectId,playerObject,responseNr,menuItemList); //the list is cleared and items are destroyes in the message lib //for the default response } //we need to clear that if the messagelib wont clear it //still want to use it for the player radials at some point for(MenuItemList::iterator it=menuItemList.begin(); it != menuItemList.end(); it++) delete (*it); menuItemList.clear(); }
//====================================================================================================================== // // rotates an item 90d to right // void ObjectController::HandleItemRotateRight_( uint64 targetId, Message* message, ObjectControllerCmdProperties* cmdProperties) { CreatureObject* creature = dynamic_cast<CreatureObject*>(mObject); PlayerObject* player = creature->GetGhost(); if (!player) { assert(false && "ObjectController::HandleItemRotateRight_ Player not found"); return; } // Verify that there was a target passed. if (!targetId) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } Object* object = gWorldManager->getObjectById(targetId); if(!object) { assert(false && "ObjectController::HandleItemRotateRight_ item not found"); return; } // Verify that the item and player are in the same structure. // Verify that the item and player are in the same structure. CellObject* playerCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId())); if(!playerCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } uint64 playerStructure = playerCell->getParentId(); CellObject* objectCell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(object->getParentId())); if(!objectCell) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } uint64 objectStructure = objectCell->getParentId(); if (objectStructure != playerStructure) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "rotate_what"), player); return; } // Verify that the player has appropriate rights on this structure. if (playerCell) { if (BuildingObject* building = dynamic_cast<BuildingObject*>(gWorldManager->getObjectById(playerCell->getParentId()))) { if (!building->getAdminData().check_admin(player->getId())) { gMessageLib->SendSystemMessage(::common::OutOfBand("player_structure", "admin_move_only"), player); return; } } else { assert(false && "ObjectController::HandleItemRotateRight_ no structure"); return; } } else { //were just outside return; } // Rotate the object 90 degree's to the right object->rotateRight(ROTATE_INCREMENT); gMessageLib->sendDataTransformWithParent053(object); object->updateWorldPosition(); }
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); } } }