Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Game::playerMoveItem(Player* player, const Position& fromPos,
- uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count, Item* item, Cylinder* toCylinder)
- {
- if (!player->canDoAction()) {
- uint32_t delay = player->getNextActionTime();
- SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::playerMoveItemByPlayerID, this,
- player->getID(), fromPos, spriteId, fromStackPos, toPos, count));
- player->setNextActionTask(task);
- return;
- }
- player->setNextActionTask(nullptr);
- if (item == nullptr) {
- uint8_t fromIndex = 0;
- if (fromPos.x == 0xFFFF) {
- if (fromPos.y & 0x40) {
- fromIndex = fromPos.z;
- } else {
- fromIndex = static_cast<uint8_t>(fromPos.y);
- }
- } else {
- fromIndex = fromStackPos;
- }
- Thing* thing = internalGetThing(player, fromPos, fromIndex, 0, STACKPOS_MOVE);
- if (!thing || !thing->getItem()) {
- player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
- return;
- }
- item = thing->getItem();
- }
- if (item->getClientID() != spriteId) {
- player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
- return;
- }
- Cylinder* fromCylinder = internalGetCylinder(player, fromPos);
- if (fromCylinder == nullptr) {
- player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
- return;
- }
- if (toCylinder == nullptr) {
- toCylinder = internalGetCylinder(player, toPos);
- if (toCylinder == nullptr) {
- player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
- return;
- }
- }
- if (!item->isPushable() || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) {
- player->sendCancelMessage(RETURNVALUE_NOTMOVEABLE);
- return;
- }
- const Position& playerPos = player->getPosition();
- const Position& mapFromPos = fromCylinder->getTile()->getPosition();
- if (playerPos.z != mapFromPos.z) {
- player->sendCancelMessage(playerPos.z > mapFromPos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS);
- return;
- }
- if (!Position::areInRange<1, 1>(playerPos, mapFromPos)) {
- //need to walk to the item first before using it
- std::forward_list<Direction> listDir;
- if (player->getPathTo(item->getPosition(), listDir, 0, 1, true, true)) {
- g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk,
- this, player->getID(), listDir)));
- SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this,
- player->getID(), fromPos, spriteId, fromStackPos, toPos, count));
- player->setNextWalkActionTask(task);
- } else {
- player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
- }
- return;
- }
- const Tile* toCylinderTile = toCylinder->getTile();
- const Position& mapToPos = toCylinderTile->getPosition();
- //hangable item specific code
- if (item->isHangable() && toCylinderTile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) {
- //destination supports hangable objects so need to move there first
- bool vertical = toCylinderTile->hasProperty(CONST_PROP_ISVERTICAL);
- if (vertical) {
- if (playerPos.x + 1 == mapToPos.x) {
- player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
- return;
- }
- } else { // horizontal
- if (playerPos.y + 1 == mapToPos.y) {
- player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
- return;
- }
- }
- if (!Position::areInRange<1, 1, 0>(playerPos, mapToPos)) {
- Position walkPos = mapToPos;
- if (vertical) {
- walkPos.x++;
- } else {
- walkPos.y++;
- }
- Position itemPos = fromPos;
- uint8_t itemStackPos = fromStackPos;
- if (fromPos.x != 0xFFFF && Position::areInRange<1, 1>(mapFromPos, playerPos)
- && !Position::areInRange<1, 1, 0>(mapFromPos, walkPos)) {
- //need to pickup the item first
- Item* moveItem = nullptr;
- ReturnValue ret = internalMoveItem(fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem);
- if (ret != RETURNVALUE_NOERROR) {
- player->sendCancelMessage(ret);
- return;
- }
- //changing the position since its now in the inventory of the player
- internalGetPosition(moveItem, itemPos, itemStackPos);
- }
- std::forward_list<Direction> listDir;
- if (player->getPathTo(walkPos, listDir, 0, 0, true, true)) {
- g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk,
- this, player->getID(), listDir)));
- SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this,
- player->getID(), itemPos, spriteId, itemStackPos, toPos, count));
- player->setNextWalkActionTask(task);
- } else {
- player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
- }
- return;
- }
- }
- if ((Position::getDistanceX(playerPos, mapToPos) > item->getThrowRange()) ||
- (Position::getDistanceY(playerPos, mapToPos) > item->getThrowRange()) ||
- (Position::getDistanceZ(mapFromPos, mapToPos) * 4 > item->getThrowRange())) {
- player->sendCancelMessage(RETURNVALUE_DESTINATIONOUTOFREACH);
- return;
- }
- if (!canThrowObjectTo(mapFromPos, mapToPos)) {
- player->sendCancelMessage(RETURNVALUE_CANNOTTHROW);
- return;
- }
- if (!g_events->eventPlayerOnMoveItem(player, item, count, fromPos, toPos)) {
- return;
- }
- uint8_t toIndex = 0;
- if (toPos.x == 0xFFFF) {
- if (toPos.y & 0x40) {
- toIndex = toPos.z;
- } else {
- toIndex = static_cast<uint8_t>(toPos.y);
- }
- }
- ReturnValue ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, item->isRune() ? item->getItemCount() : count, nullptr, 0, player);
- if (ret != RETURNVALUE_NOERROR) {
- player->sendCancelMessage(ret);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement