Nome: onMove
Tipo: Creaturescript/C++
Autor: Doggynub
Este é um código C++ extra para os servidores, um creaturescript, que facilita muito a programação de variados scripts. É possível criar um script que bloqueia que itens sejam jogados em teleports, por exemplo.
Em creatureevent.h, procure por:
CREATURE_EVENT_PREPAREDEATH,
Logo abaixo, adicione:
CREATURE_EVENT_ONMOVE
Procure por:
uint32_t executePrepareDeath(Creature* creature, DeathList deathList);
E logo abaixo, adicione:
uint32_t executeOnMove(Player* player, Item* item, const Position& fromPosition, const Position& toPosition, Item* fromItem, Item* toItem, Item* fromGround, Item* toGround, std::map<std::string,int> status);
Em creatureevent.cpp, procure por:
else if(tmpStr == "preparedeath") m_type = CREATURE_EVENT_PREPAREDEATH;
Logo abaixo, adicione:
else if(tmpStr == "move") m_type = CREATURE_EVENT_ONMOVE;
Procure por:
case CREATURE_EVENT_PREPAREDEATH: return "onPrepareDeath";
Abaixo, adicione:
case CREATURE_EVENT_ONMOVE: return "onMoveItem";
Procure por:
case CREATURE_EVENT_PREPAREDEATH: return "cid, deathList";
Abaixo, adicione:
case CREATURE_EVENT_ONMOVE: return "cid, item, formPosition, toPosition, fromItem, toItem, fromGround, toGround, status";
No fim do arquivo, adicione:
0.4
// custom move uint32_t CreatureEvent::executeOnMove(Player* player, Item* item, const Position& fromPosition, const Position& toPosition, Item* fromItem, Item* toItem, Item* fromGround, Item* toGround, std::map<std::string,int> status) { //onMoveItem(cid, item, formPosition, toPosition, fromItem, toItem, fromGround, toGround, status) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(player->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(player) << std::endl; env->streamThing(scriptstream, "item" ,item, env->addThing(item)); env->streamPosition(scriptstream, "fromPosition", fromPosition); env->streamPosition(scriptstream, "toPosition", toPosition); env->streamThing(scriptstream, "fromItem",fromItem, env->addThing(fromItem)); env->streamThing(scriptstream, "toItem",toItem, env->addThing(toItem)); env->streamThing(scriptstream, "fromGround",fromGround, env->addThing(fromGround)); env->streamThing(scriptstream, "toGround",toGround, env->addThing(toGround)); scriptstream << "local status = {}" << std::endl; for(std::map<std::string,int>::iterator it = status.begin(); it != status.end(); ++it) { scriptstream << "status."<< it->first << " = " << it->second; } if(m_scriptData) scriptstream << *m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[30]; sprintf(desc, "%s", player->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(player->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(player)); LuaInterface::pushThing(L, item, env->addThing(item)); LuaInterface::pushPosition(L, fromPosition); LuaInterface::pushPosition(L, toPosition); LuaInterface::pushThing(L, fromItem, env->addThing(fromItem)); LuaInterface::pushThing(L, toItem, env->addThing(toItem)); LuaInterface::pushThing(L, fromGround, env->addThing(fromGround)); LuaInterface::pushThing(L, toGround, env->addThing(toGround)); lua_newtable(L); std::map<std::string,int>::iterator it = status.begin(); for(std::map<std::string,int>::iterator it = status.begin(); it != status.end(); ++it) { LuaInterface::setField(L, it->first.c_str(), it->second); } bool result = m_interface->callFunction(9); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::executeMove] Call stack overflow." << std::endl; return 0; } } //
0.3.6
uint32_t CreatureEvent::executeOnMove(Player* player, Item* item, const Position& fromPosition, const Position& toPosition, Item* fromItem, Item* toItem, Item* fromGround, Item* toGround, std::map<std::string,int> status) { //onMoveItem(cid, item, formPosition, toPosition, fromItem, toItem, fromGround, toGround, move) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(player->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(player) << std::endl; env->streamThing(scriptstream, "item" ,item, env->addThing(item)); env->streamPosition(scriptstream, "fromPosition", fromPosition); env->streamPosition(scriptstream, "toPosition", toPosition); env->streamThing(scriptstream, "fromItem",fromItem, env->addThing(fromItem)); env->streamThing(scriptstream, "toItem",toItem, env->addThing(toItem)); env->streamThing(scriptstream, "fromGround",fromGround, env->addThing(fromGround)); env->streamThing(scriptstream, "toGround",toGround, env->addThing(toGround)); scriptstream << "local status = {}" << std::endl; for(std::map<std::string,int>::iterator it = status.begin(); it != status.end(); ++it) { scriptstream << "status."<< it->first << " = " << it->second; } scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[30]; sprintf(desc, "%s", player->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(player->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(player)); LuaScriptInterface::pushThing(L, item, env->addThing(item)); LuaScriptInterface::pushPosition(L, fromPosition); LuaScriptInterface::pushPosition(L, toPosition); LuaScriptInterface::pushThing(L, fromItem, env->addThing(fromItem)); LuaScriptInterface::pushThing(L, toItem, env->addThing(toItem)); LuaScriptInterface::pushThing(L, fromGround, env->addThing(fromGround)); LuaScriptInterface::pushThing(L, toGround, env->addThing(toGround)); lua_newtable(L); std::map<std::string,int>::iterator it = status.begin(); for(std::map<std::string,int>::iterator it = status.begin(); it != status.end(); ++it) { LuaScriptInterface::setField(L, it->first.c_str(), it->second); } bool result = m_interface->callFunction(9); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::executeMove] Call stack overflow." << std::endl; return 0; } }
No arquivo game.cpp, procure:
bool Game::playerMoveItem(uint32_t playerId, const Position& fromPos, uint16_t spriteId, int16_t fromStackpos, const Position& toPos, uint8_t count)
Troque TODA ELA pelo conteúdo abaixo:
0.3.6
bool Game::playerMoveItem(uint32_t playerId, const Position& fromPos, uint16_t spriteId, int16_t fromStackpos, const Position& toPos, uint8_t count) { Player* player = getPlayerByID(playerId); //custom move bool equip = false, deequip =false,fromDepot = false, toDepot = false; // if(!player || player->isRemoved() || player->hasFlag(PlayerFlag_CannotMoveItems)) return false; if(!player->canDoAction()) { uint32_t delay = player->getNextActionTime(); SchedulerTask* task = createSchedulerTask(delay, boost::bind(&Game::playerMoveItem, this, playerId, fromPos, spriteId, fromStackpos, toPos, count)); player->setNextActionTask(task); return false; } player->setNextActionTask(NULL); Cylinder* fromCylinder = internalGetCylinder(player, fromPos); //custom move Item* fromItem = NULL; Item* fromGround = NULL; Player* fromPlayer= 0; // uint8_t fromIndex = 0; if(fromPos.x == 0xFFFF) { if(fromPos.y & 0x40) { fromIndex = static_cast<uint8_t>(fromPos.z); fromItem = fromCylinder->getItem(); if (fromItem) { fromPlayer = fromItem->getHoldingPlayer(); Item* parentFromItem = fromItem->getTopParent()->getItem(); if (fromItem->isDepot() || (parentFromItem && parentFromItem->isDepot()) ) fromDepot = true; } } else { fromIndex = static_cast<uint8_t>(fromPos.y); //custom move deequip = true; // } } else { fromIndex = fromStackpos; const TileItemVector* items = fromCylinder->getTile()->getItemList(); Thing* thing = internalGetThing(player, fromPos, fromIndex, spriteId, STACKPOS_MOVE); if(thing && thing->getItem()) { Item* movingItem = thing->getItem(); fromItem = NULL; fromGround = fromCylinder->getTile()->ground; for(ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it) { if((*it) != movingItem) fromItem = (*it); } if(!fromItem || fromItem == movingItem ) fromItem = fromGround ; } } Thing* thing = internalGetThing(player, fromPos, fromIndex, spriteId, STACKPOS_MOVE); if(!thing || !thing->getItem()) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } Item* item = thing->getItem(); Cylinder* toCylinder = internalGetCylinder(player, toPos); //custom move Item* toItem = NULL; Item* toGround=NULL; Player* toPlayer = NULL; uint8_t toIndex = 0; if(toPos.x == 0xFFFF) { if(toPos.y & 0x40) { toIndex = static_cast<uint8_t>(toPos.z); if(toCylinder) { toItem = toCylinder->getItem(); if(toItem) { toPlayer = toItem->getHoldingPlayer(); Item* parentToItem = toItem->getTopParent()->getItem(); if (toItem->isDepot() || (parentToItem && parentToItem->isDepot()) ) toDepot = true; } } } else { toIndex = static_cast<uint8_t>(toPos.y); equip = true; //custom move Item* inveItem = player->getInventoryItem((slots_t)(unsigned)toIndex); if (inveItem && inveItem->isContainer()) toItem = inveItem; // } } else { if(toCylinder) { toItem = toCylinder->getTile()->getTopDownItem(); toGround = toCylinder->getTile()->ground; if(!toItem) toItem = toGround; } } //custom move Item* toSlotItem= (player->getInventoryItem((slots_t)((unsigned)toIndex))); bool checkToSlot = false; if (toSlotItem) checkToSlot= toSlotItem->isContainer();; // if(!fromCylinder || !toCylinder || !item || item->getClientID() != spriteId) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } if(!player->hasCustomFlag(PlayerCustomFlag_CanPushAllItems) && (!item->isPushable() || (item->isLoadedFromMap() && (item->getUniqueId() != 0 || (item->getActionId() != 0 && item->getContainer()))))) { player->sendCancelMessage(RET_NOTMOVEABLE); return false; } const Position& mapFromPos = fromCylinder->getTile()->getPosition(); const Position& mapToPos = toCylinder->getTile()->getPosition(); const Position& playerPos = player->getPosition(); if(playerPos.z > mapFromPos.z && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_FIRSTGOUPSTAIRS); return false; } if(playerPos.z < mapFromPos.z && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS); return false; } if(!Position::areInRange<1,1,0>(playerPos, mapFromPos) && !player->hasCustomFlag(PlayerCustomFlag_CanMoveFromFar)) { //need to walk to the item first before using it std::list<Direction> listDir; if(getPathToEx(player, item->getPosition(), listDir, 0, 1, true, true)) { Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::playerAutoWalk, this, player->getID(), listDir))); SchedulerTask* task = createSchedulerTask(player->getStepDuration(), boost::bind(&Game::playerMoveItem, this, playerId, fromPos, spriteId, fromStackpos, toPos, count)); player->setNextWalkActionTask(task); return true; } player->sendCancelMessage(RET_THEREISNOWAY); return false; } //hangable item specific code if(item->isHangable() && toCylinder->getTile()->hasProperty(SUPPORTHANGABLE)) { //destination supports hangable objects so need to move there first if(toCylinder->getTile()->hasProperty(ISVERTICAL)) { if(player->getPosition().x + 1 == mapToPos.x) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } } else if(toCylinder->getTile()->hasProperty(ISHORIZONTAL)) { if(player->getPosition().y + 1 == mapToPos.y) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } } if(!Position::areInRange<1,1,0>(playerPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanMoveFromFar)) { Position walkPos = mapToPos; if(toCylinder->getTile()->hasProperty(ISVERTICAL)) walkPos.x -= -1; if(toCylinder->getTile()->hasProperty(ISHORIZONTAL)) walkPos.y -= -1; Position itemPos = fromPos; int16_t itemStackpos = fromStackpos; if(fromPos.x != 0xFFFF && Position::areInRange<1,1,0>(mapFromPos, player->getPosition()) && !Position::areInRange<1,1,0>(mapFromPos, walkPos)) { //need to pickup the item first Item* moveItem = NULL; ReturnValue ret = internalMoveItem(player, fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem); if(ret != RET_NOERROR) { player->sendCancelMessage(ret); return false; } //changing the position since its now in the inventory of the player internalGetPosition(moveItem, itemPos, itemStackpos); } std::list<Direction> listDir; if(map->getPathTo(player, walkPos, listDir)) { Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::playerAutoWalk, this, player->getID(), listDir))); SchedulerTask* task = createSchedulerTask(player->getStepDuration(), boost::bind(&Game::playerMoveItem, this, playerId, itemPos, spriteId, itemStackpos, toPos, count)); player->setNextWalkActionTask(task); return true; } player->sendCancelMessage(RET_THEREISNOWAY); return false; } } if(!player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { if((std::abs(playerPos.x - mapToPos.x) > item->getThrowRange()) || (std::abs(playerPos.y - mapToPos.y) > item->getThrowRange()) || (std::abs(mapFromPos.z - mapToPos.z) * 4 > item->getThrowRange())) { player->sendCancelMessage(RET_DESTINATIONOUTOFREACH); return false; } } if(!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_CANNOTTHROW); return false; } //custom move bool Out = (fromPlayer) ? true : false; bool In = (toPlayer) ? true : false; std::map<std::string,int> status; status["inInv"] = (equip && !deequip && !checkToSlot) ? 1:( (!equip && deequip) || (deequip && equip && checkToSlot) ) ? 0 : (equip && deequip && !checkToSlot) ? 2 :3; status["inDepot"] = (fromDepot && !toDepot) ? 0 : (!fromDepot && toDepot) ? 1: (fromDepot && toDepot) ? 2:3; status["inInvBag"] = (Out && !In && !checkToSlot )? 0:((In && !Out) || (!Out && equip && checkToSlot)) ? 1:((In && Out) || (Out && equip && checkToSlot))?2:3; status["slot"] = (int) toIndex; bool deny = false; CreatureEventList moveEvents = player->getCreatureEvents(CREATURE_EVENT_ONMOVE); for(CreatureEventList::iterator it = moveEvents.begin(); it != moveEvents.end(); ++it) { if(!(*it)->executeOnMove(player, item, mapFromPos, mapToPos, fromItem,toItem,fromGround,toGround,status)) deny = true; } if(deny) return false; ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL); if(ret == RET_NOERROR) return true; player->sendCancelMessage(ret); return false; }
0.4
bool Game::playerMoveItem(uint32_t playerId, const Position& fromPos, uint16_t spriteId, int16_t fromStackpos, const Position& toPos, uint8_t count) { Player* player = getPlayerByID(playerId); //Doggynub: custom move bool equip = false, deequip =false,fromDepot = false, toDepot = false; int32_t fr = 0,to = 0; // if(!player || player->isRemoved() || player->hasFlag(PlayerFlag_CannotMoveItems)) return false; if(!player->canDoAction()) { uint32_t delay = player->getNextActionTime(); SchedulerTask* task = createSchedulerTask(delay, boost::bind(&Game::playerMoveItem, this, playerId, fromPos, spriteId, fromStackpos, toPos, count)); player->setNextActionTask(task); return false; } player->setNextActionTask(NULL); Cylinder* fromCylinder = internalGetCylinder(player, fromPos); uint8_t fromIndex = 0; if(fromPos.x == 0xFFFF) { if(fromPos.y & 0x40) { fromIndex = static_cast<uint8_t>(fromPos.z); fr = 1; } else { fromIndex = static_cast<uint8_t>(fromPos.y); fr = 2; } } else { fromIndex = fromStackpos; fr = 3; } Thing* thing = internalGetThing(player, fromPos, fromIndex, spriteId, STACKPOS_MOVE); if(!thing || !thing->getItem()) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } Item* item = thing->getItem(); Cylinder* toCylinder = internalGetCylinder(player, toPos); uint8_t toIndex = 0; if(toPos.x == 0xFFFF) { if(toPos.y & 0x40) { toIndex = static_cast<uint8_t>(toPos.z); to = 1; } else { toIndex = static_cast<uint8_t>(toPos.y); to = 2; } } else to = 3; if(!fromCylinder || !toCylinder || !item || item->getClientID() != spriteId) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } if(!player->hasCustomFlag(PlayerCustomFlag_CanPushAllItems) && (!item->isPushable() || (item->isLoadedFromMap() && (item->getUniqueId() != 0 || (item->getActionId() != 0 && item->getContainer()))))) { player->sendCancelMessage(RET_NOTMOVABLE); return false; } const Position &mapToPos = toCylinder->getTile()->getPosition(), &playerPos = player->getPosition(), &mapFromPos = fromCylinder->getTile()->getPosition(); if(playerPos.z > mapFromPos.z && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_FIRSTGOUPSTAIRS); return false; } if(playerPos.z < mapFromPos.z && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS); return false; } if(!Position::areInRange<1,1,0>(playerPos, mapFromPos) && !player->hasCustomFlag(PlayerCustomFlag_CanMoveFromFar)) { //need to walk to the item first before using it std::list<Direction> listDir; if(getPathToEx(player, item->getPosition(), listDir, 0, 1, true, true)) { Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::playerAutoWalk, this, player->getID(), listDir))); SchedulerTask* task = createSchedulerTask(std::max((int32_t)SCHEDULER_MINTICKS, player->getStepDuration()), boost::bind(&Game::playerMoveItem, this, playerId, fromPos, spriteId, fromStackpos, toPos, count)); player->setNextWalkActionTask(task); return true; } player->sendCancelMessage(RET_THEREISNOWAY); return false; } //hangable item specific code if(item->isHangable() && toCylinder->getTile()->hasProperty(SUPPORTHANGABLE)) { //destination supports hangable objects so need to move there first if(toCylinder->getTile()->hasProperty(ISVERTICAL)) { if(player->getPosition().x + 1 == mapToPos.x) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } } else if(toCylinder->getTile()->hasProperty(ISHORIZONTAL)) { if(player->getPosition().y + 1 == mapToPos.y) { player->sendCancelMessage(RET_NOTPOSSIBLE); return false; } } if(!Position::areInRange<1,1,0>(playerPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanMoveFromFar)) { Position walkPos = mapToPos; if(toCylinder->getTile()->hasProperty(ISVERTICAL)) walkPos.x -= -1; if(toCylinder->getTile()->hasProperty(ISHORIZONTAL)) walkPos.y -= -1; Position itemPos = fromPos; int16_t itemStackpos = fromStackpos; if(fromPos.x != 0xFFFF && Position::areInRange<1,1,0>(mapFromPos, player->getPosition()) && !Position::areInRange<1,1,0>(mapFromPos, walkPos)) { //need to pickup the item first Item* moveItem = NULL; ReturnValue ret = internalMoveItem(player, fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem); if(ret != RET_NOERROR) { player->sendCancelMessage(ret); return false; } //changing the position since its now in the inventory of the player internalGetPosition(moveItem, itemPos, itemStackpos); } std::list<Direction> listDir; if(map->getPathTo(player, walkPos, listDir)) { Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::playerAutoWalk, this, player->getID(), listDir))); SchedulerTask* task = createSchedulerTask(std::max((int32_t)SCHEDULER_MINTICKS, player->getStepDuration()), boost::bind(&Game::playerMoveItem, this, playerId, itemPos, spriteId, itemStackpos, toPos, count)); player->setNextWalkActionTask(task); return true; } player->sendCancelMessage(RET_THEREISNOWAY); return false; } } if(!player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { if((std::abs(playerPos.x - mapToPos.x) > item->getThrowRange()) || (std::abs(playerPos.y - mapToPos.y) > item->getThrowRange()) || (std::abs(mapFromPos.z - mapToPos.z) * 4 > item->getThrowRange())) { player->sendCancelMessage(RET_DESTINATIONOUTOFREACH); return false; } } if(!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_CANNOTTHROW); return false; } //Doggynub: custom move if(!item->getParent()) { assert(fromCylinder == item->getParent()); } Item* toItem = NULL; Item* fromItem = NULL; Item* toGround=NULL; Item* fromGround=NULL; Player* toPlayer = NULL; Player* fromPlayer= NULL; Item* toSlotItem= (player->getInventoryItem((slots_t)((unsigned)toIndex))); bool checkToSlot = false; if (toSlotItem) checkToSlot= toSlotItem->isContainer(); if (fr == 1) { fromItem = fromCylinder->getItem(); if (fromItem) { fromPlayer = fromItem->getHoldingPlayer(); Item* parentFromItem = fromItem->getTopParent()->getItem(); if (fromItem->isDepot() || (parentFromItem && parentFromItem->isDepot()) ) fromDepot = true; } } else if (fr == 2) deequip = true; else { const TileItemVector* items = fromCylinder->getTile()->getItemList(); fromItem = NULL; fromGround = fromCylinder->getTile()->ground; for(ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it) { if((*it) != item) fromItem = (*it); } if(!fromItem || fromItem == item ) fromItem = fromGround ; } if(to == 1) { toItem = toCylinder->getItem(); if(toItem) { toPlayer = toItem->getHoldingPlayer(); Item* parentToItem = toItem->getTopParent()->getItem(); if (toItem->isDepot() || (parentToItem && parentToItem->isDepot()) ) toDepot = true; } } else if(to == 2) { equip = true; Item* inveItem = player->getInventoryItem((slots_t)(unsigned)toIndex); if (inveItem && inveItem->isContainer()) toItem = inveItem; } else { toItem = toCylinder->getTile()->getTopDownItem(); toGround = toCylinder->getTile()->ground; if(!toItem) toItem = toGround; } bool Out = (fromPlayer) ? true : false; bool In = (toPlayer) ? true : false; std::map<std::string,int> status; status["inInv"] = (equip && !deequip && !checkToSlot) ? 1:( (!equip && deequip) || (deequip && equip && checkToSlot) ) ? 0 : (equip && deequip && !checkToSlot) ? 2 :3; status["inDepot"] = (fromDepot && !toDepot) ? 0 : (!fromDepot && toDepot) ? 1: (fromDepot && toDepot) ? 2:3; status["inInvBag"] = (Out && !In && !checkToSlot )? 0:((In && !Out) || (!Out && equip && checkToSlot)) ? 1:((In && Out) || (Out && equip && checkToSlot))?2:3; status["slot"] = (int) toIndex; bool deny = false; CreatureEventList moveEvents = player->getCreatureEvents(CREATURE_EVENT_ONMOVE); for(CreatureEventList::iterator it = moveEvents.begin(); it != moveEvents.end(); ++it) { if(!(*it)->executeOnMove(player, item, mapFromPos, mapToPos, fromItem,toItem,fromGround,toGround,status)) deny = true; } if(deny) return false; //end ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL); if(ret != RET_NOERROR) { player->sendCancelMessage(ret); return false; } player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL) - 10); return true; }
O código C++ acima como dito anteriormente, abre um leque grande de possibilidades de novos scripts para seu servidor.
As versões mais atuais do Open Tibia, como o The Forgotten Server, já possuem algo parecido compilado, um creaturescript chamado onThrow, embora este não tenha tantos extras como o passado no tópico.