Doggynub
LUA / C++
- Joined
- Sep 28, 2008
- Messages
- 2,541
- Reaction score
- 186
support : 0.4 - 0.3.6
Okay the function is a bit long, but i have tryed to make it short but failed so , it works.
SetUp :
#go to creatureEvent.h :
find
replace the line under it exactly with this
find
paste after
-------------------------------------------------------------------------------------------------------
#goto creatureEvent.cpp
find
under it
find
under it
find
under it
now go to the end of file paste this
for 0.4
for 0.3.6
-------------------------------------------------------------------------------------------------------------------------------------
# goto game.cpp
replace this function all of it
with this
for 0.4
Okay the function is a bit long, but i have tryed to make it short but failed so , it works.
Code:
function onMoveItem(cid, item, formPosition, toPosition, fromItem, toItem, fromGround, toGround, status)
Structure :
fromItem, toItem = -- return the item just below the moveditem, or returns the container it was moved from
fromGround, toGround = --returns the tile , so if tile have many items and u removed first one, you can get the gorund moved from
status.inInv = 0 -- unwearing
1 -- wearing
2 -- rearrange in inventory
3 -- action not included in inventory
status.inInvBag= 0 -- removeing from bags
1 -- holding in bags
2 -- rearrange in bags
3 -- action not included in bags
status.Slot = contain the slot that the item is moved to if it is included in inventory
status.inDepot= 0 -- removeing from depot
1 -- holding in depot
2 -- rearrange in depot
3 -- action not included in depot
SetUp :
#go to creatureEvent.h :
find
Code:
CREATURE_EVENT_DEATH,
replace the line under it exactly with this
Code:
CREATURE_EVENT_PREPAREDEATH,
//custom move
CREATURE_EVENT_ONMOVE
//
find
Code:
uint32_t executePrepareDeath(Creature* creature, DeathList deathList);
paste after
Code:
//custom move
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);
//
#goto creatureEvent.cpp
find
Code:
else if(tmpStr == "preparedeath")
m_type = CREATURE_EVENT_PREPAREDEATH;
Code:
//custom move
else if(tmpStr == "move")
m_type = CREATURE_EVENT_ONMOVE;
//
find
Code:
case CREATURE_EVENT_PREPAREDEATH:
return "onPrepareDeath";
under it
Code:
//custom move
case CREATURE_EVENT_ONMOVE:
return "onMoveItem";
//
Code:
case CREATURE_EVENT_PREPAREDEATH:
return "cid, deathList";
under it
Code:
//custom move
case CREATURE_EVENT_ONMOVE:
return "cid, item, formPosition, toPosition, fromItem, toItem, fromGround, toGround, status";
//
now go to the end of file paste this
for 0.4
Code:
// 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;
}
}
//
for 0.3.6
Code:
//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, 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;
}
}
-------------------------------------------------------------------------------------------------------------------------------------
# goto game.cpp
replace this function all of it
Code:
bool Game::playerMoveItem(uint32_t playerId, const Position& fromPos,
uint16_t spriteId, int16_t fromStackpos, const Position& toPos, uint8_t count)
with this
for 0.4
Code:
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;
}
Last edited: