Ir para conteúdo

HSinhori

Membro
  • Registro em

  • Última visita

  1. HSinhori postou uma resposta no tópico em Outros Clients
    Eu já procurei em varios lugares, achei varios artigos sobre, porém nenhum resolveu, alguém sabe como eu faço para tanto o "soul" quanto as "skills" passarem de 256 no client? Eu sei que no servidor ela passa, pois aparece que eu avancei para o skill 300+, mas no cliente, quando é pra estar 257 ele zera e recomeça... Eu acredito que possa ser no client, posso estar errado, alguem sabe onde é, e como resolver? Eu uso OTClient e tfs 0.4 rev 4393
  2. HSinhori postou uma resposta no tópico em Outros Clients
    Gostaria de pedir uma ajuda pra adicionar um botão no final de cada skill que ao ser clicado chama uma talkaction, um botão tipo esse: Ficaria tipo: Magic Level 10 Fist Fighting 10 e por ai vai.... Alguém saberia me ajudar, esses são os arquivos do otclient skills.lua skill.otui
  3. Um específico
  4. Eu estou usando tfs 0.4, 8.7, eu procurei mas não encontrei, como eu faço um npc abrir diferentes janelas de trade de acordo com a vocation do player, se knight, abre o trade com itens de knight, se rp, abre o trade com itens de rp, alguém tem algum npc assim?
  5. Não é god, pq a armadura não vai Mano, eu sou muito burro, eu tava adicionando o war hammer com elemento de fire no movements e fazia o normal pra testar, hahah, deu certo agora, obg mano
  6. sim, lá também tem, tanto que aparece na descrição do war hammer
  7. eu coloquei, na armadura funcionou, porém nas armas (weapons) ele ignora e equipa de qualquer forma
  8. ficou assim: <movevent type="Equip" level="45" itemid="7758" slot="left-hand" event="function" value="onEquipItem"/> <movevent type="DeEquip" level="45" itemid="7758" slot="left-hand" event="function" value="onDeEquipItem"/> porém ainda é equipado Na real, deu certo até certa parte, armaduras não são equipadas, porém as armas são equipadas ainda
  9. coloquei assim <movevent type="Equip" itemid="7758" slot="left-hand" event="function" value="onEquipItem"/> <movevent type="DeEquip" itemid="7758" slot="left-hand" event="function" value="onDeEquipItem"/> no movements.xml e o item continua sendo equipado
  10. Opa, preciso de ajuda com uma coisa, alguns itens como zaoan armor e war hammer possuem level mínimo necessário, porém pelo menos no meu servidor eles podem ser equipados e eu gostaria que se o level não for o necessário, o item não seja equipado, eu uso TFS 04 rev4393, eu acredito que seja no movements.cpp, eu tentei mexer, mas meu conhecimento em C/C++ é bem fraco, alguém poderia me ajudar? Por script eu sei fazer, mas gostaria que fosse diretamente nas sources pra ser automático já //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include "movement.h" #include "tools.h" #include "creature.h" #include "player.h" #include "tile.h" #include "vocation.h" #include "combat.h" #include "game.h" extern Game g_game; extern MoveEvents* g_moveEvents; MoveEvent* MoveEventScript::event = NULL; void MoveEventScript::registerFunctions() { LuaInterface::registerFunctions(); lua_register(m_luaState, "callFunction", MoveEventScript::luaCallFunction); } int32_t MoveEventScript::luaCallFunction(lua_State* L) { //callFunction(...) MoveEvent* event = MoveEventScript::event; if(!event) { error(__FUNCTION__, "MoveEvent not set!"); lua_pushboolean(L, false); return 1; } if(event->getEventType() == MOVE_EVENT_EQUIP || event->getEventType() == MOVE_EVENT_DE_EQUIP) { ScriptEnviroment* env = getEnv(); bool boolean = popNumber(L); slots_t slot = (slots_t)popNumber(L); Item* item = env->getItemByUID(popNumber(L)); if(!item) { error(__FUNCTION__, getError(LUA_ERROR_ITEM_NOT_FOUND)); lua_pushboolean(L, false); return 1; } Player* player = env->getPlayerByUID(popNumber(L)); if(!player) { error(__FUNCTION__, getError(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushboolean(L, false); return 1; } if(event->getEventType() != MOVE_EVENT_EQUIP) lua_pushboolean(L, MoveEvent::DeEquipItem(event, player, item, slot, boolean)); else lua_pushboolean(L, MoveEvent::EquipItem(event, player, item, slot, boolean)); return 1; } else if(event->getEventType() == MOVE_EVENT_STEP_IN) { ScriptEnviroment* env = getEnv(); Item* item = env->getItemByUID(popNumber(L)); if(!item) { error(__FUNCTION__, getError(LUA_ERROR_ITEM_NOT_FOUND)); lua_pushboolean(L, false); return 1; } Creature* creature = env->getCreatureByUID(popNumber(L)); if(!creature) { error(__FUNCTION__, getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); return 1; } lua_pushboolean(L, MoveEvent::StepInField(creature, item)); return 1; } else if(event->getEventType() == MOVE_EVENT_ADD_ITEM) { ScriptEnviroment* env = getEnv(); Item* item = env->getItemByUID(popNumber(L)); if(!item) { error(__FUNCTION__, getError(LUA_ERROR_ITEM_NOT_FOUND)); lua_pushboolean(L, false); return 1; } lua_pushboolean(L, MoveEvent::AddItemField(item)); return 1; } error(__FUNCTION__, "callFunction not available for current event."); lua_pushboolean(L, false); return 1; } MoveEvents::MoveEvents(): m_lastCacheTile(NULL) { m_interface.initState(); } inline void MoveEvents::clearMap(MoveListMap& map) { for(MoveListMap::iterator it = map.begin(); it != map.end(); ++it) { for(int32_t i = MOVE_EVENT_FIRST; i <= MOVE_EVENT_LAST; ++i) { EventList& moveEventList = it->second.moveEvent[i]; for(EventList::iterator it = moveEventList.begin(); it != moveEventList.end(); ++it) delete (*it); moveEventList.clear(); } } map.clear(); } void MoveEvents::clear() { clearMap(m_itemIdMap); clearMap(m_actionIdMap); clearMap(m_uniqueIdMap); for(MovePosListMap::iterator it = m_positionMap.begin(); it != m_positionMap.end(); ++it) { for(int32_t i = MOVE_EVENT_FIRST; i <= MOVE_EVENT_LAST; ++i) { EventList& moveEventList = it->second.moveEvent[i]; for(EventList::iterator it = moveEventList.begin(); it != moveEventList.end(); ++it) delete (*it); moveEventList.clear(); } } m_positionMap.clear(); m_interface.reInitState(); m_lastCacheTile = NULL; m_lastCacheItemVector.clear(); } Event* MoveEvents::getEvent(const std::string& nodeName) { std::string tmpNodeName = asLowerCaseString(nodeName); if(tmpNodeName == "movevent" || tmpNodeName == "moveevent" || tmpNodeName == "movement") return new MoveEvent(&m_interface); return NULL; } bool MoveEvents::registerEvent(Event* event, xmlNodePtr p, bool override) { MoveEvent* moveEvent = dynamic_cast<MoveEvent*>(event); if(!moveEvent) return false; std::string strValue, endStrValue; MoveEvent_t eventType = moveEvent->getEventType(); if((eventType == MOVE_EVENT_ADD_ITEM || eventType == MOVE_EVENT_REMOVE_ITEM) && readXMLString(p, "tileitem", strValue) && booleanString(strValue)) { switch(eventType) { case MOVE_EVENT_ADD_ITEM: moveEvent->setEventType(MOVE_EVENT_ADD_TILEITEM); break; case MOVE_EVENT_REMOVE_ITEM: moveEvent->setEventType(MOVE_EVENT_REMOVE_TILEITEM); break; default: break; } } StringVec strVector; IntegerVec intVector, endIntVector; bool success = true; if(readXMLString(p, "itemid", strValue)) { strVector = explodeString(strValue, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { intVector = vectorAtoi(explodeString((*it), "-")); if(!intVector[0]) continue; bool equip = moveEvent->getEventType() == MOVE_EVENT_EQUIP; addEvent(moveEvent, intVector[0], m_itemIdMap, override); if(equip) { ItemType& it = Item::items.getItemType(intVector[0]); it.wieldInfo = moveEvent->getWieldInfo(); it.minReqLevel = moveEvent->getReqLevel(); it.minReqMagicLevel = moveEvent->getReqMagLv(); it.vocationString = moveEvent->getVocationString(); } if(intVector.size() > 1) { while(intVector[0] < intVector[1]) { addEvent(new MoveEvent(moveEvent), ++intVector[0], m_itemIdMap, override); if(equip) { ItemType& tit = Item::items.getItemType(intVector[0]); tit.wieldInfo = moveEvent->getWieldInfo(); tit.minReqLevel = moveEvent->getReqLevel(); tit.minReqMagicLevel = moveEvent->getReqMagLv(); tit.vocationString = moveEvent->getVocationString(); } } } } } if(readXMLString(p, "fromid", strValue) && readXMLString(p, "toid", endStrValue)) { intVector = vectorAtoi(explodeString(strValue, ";")); endIntVector = vectorAtoi(explodeString(endStrValue, ";")); if(intVector[0] && endIntVector[0] && intVector.size() == endIntVector.size()) { for(size_t i = 0, size = intVector.size(); i < size; ++i) { bool equip = moveEvent->getEventType() == MOVE_EVENT_EQUIP; addEvent(moveEvent, intVector[i], m_itemIdMap, override); if(equip) { ItemType& it = Item::items.getItemType(intVector[i]); it.wieldInfo = moveEvent->getWieldInfo(); it.minReqLevel = moveEvent->getReqLevel(); it.minReqMagicLevel = moveEvent->getReqMagLv(); it.vocationString = moveEvent->getVocationString(); } while(intVector[i] < endIntVector[i]) { addEvent(new MoveEvent(moveEvent), ++intVector[i], m_itemIdMap, override); if(equip) { ItemType& tit = Item::items.getItemType(intVector[i]); tit.wieldInfo = moveEvent->getWieldInfo(); tit.minReqLevel = moveEvent->getReqLevel(); tit.minReqMagicLevel = moveEvent->getReqMagLv(); tit.vocationString = moveEvent->getVocationString(); } } } } else std::clog << "[Warning - MoveEvents::registerEvent] Malformed entry (from item: \"" << strValue << "\", to item: \"" << endStrValue << "\")" << std::endl; } if(readXMLString(p, "uniqueid", strValue)) { strVector = explodeString(strValue, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { intVector = vectorAtoi(explodeString((*it), "-")); if(!intVector[0]) continue; addEvent(moveEvent, intVector[0], m_uniqueIdMap, override); if(intVector.size() > 1) { while(intVector[0] < intVector[1]) addEvent(new MoveEvent(moveEvent), ++intVector[0], m_uniqueIdMap, override); } } } if(readXMLString(p, "fromuid", strValue) && readXMLString(p, "touid", endStrValue)) { intVector = vectorAtoi(explodeString(strValue, ";")); endIntVector = vectorAtoi(explodeString(endStrValue, ";")); if(intVector[0] && endIntVector[0] && intVector.size() == endIntVector.size()) { for(size_t i = 0, size = intVector.size(); i < size; ++i) { addEvent(moveEvent, intVector[i], m_uniqueIdMap, override); while(intVector[i] < endIntVector[i]) addEvent(new MoveEvent(moveEvent), ++intVector[i], m_uniqueIdMap, override); } } else std::clog << "[Warning - MoveEvents::registerEvent] Malformed entry (from unique: \"" << strValue << "\", to unique: \"" << endStrValue << "\")" << std::endl; } if(readXMLString(p, "actionid", strValue) || readXMLString(p, "aid", strValue)) { strVector = explodeString(strValue, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { intVector = vectorAtoi(explodeString((*it), "-")); if(!intVector[0]) continue; addEvent(moveEvent, intVector[0], m_actionIdMap, override); if(intVector.size() > 1) { while(intVector[0] < intVector[1]) addEvent(new MoveEvent(moveEvent), ++intVector[0], m_actionIdMap, override); } } } if(readXMLString(p, "fromaid", strValue) && readXMLString(p, "toaid", endStrValue)) { intVector = vectorAtoi(explodeString(strValue, ";")); endIntVector = vectorAtoi(explodeString(endStrValue, ";")); if(intVector[0] && endIntVector[0] && intVector.size() == endIntVector.size()) { for(size_t i = 0, size = intVector.size(); i < size; ++i) { addEvent(moveEvent, intVector[i], m_actionIdMap, override); while(intVector[i] < endIntVector[i]) addEvent(new MoveEvent(moveEvent), ++intVector[i], m_actionIdMap, override); } } else std::clog << "[Warning - MoveEvents::registerEvent] Malformed entry (from action: \"" << strValue << "\", to action: \"" << endStrValue << "\")" << std::endl; } if(readXMLString(p, "pos", strValue) || readXMLString(p, "position", strValue)) { strVector = explodeString(strValue, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { intVector = vectorAtoi(explodeString((*it), ",")); if(intVector.size() > 2) addEvent(moveEvent, Position(intVector[0], intVector[1], intVector[2]), m_positionMap, override); else success = false; } } return success; } void MoveEvents::addEvent(MoveEvent* moveEvent, int32_t id, MoveListMap& map, bool override) { MoveListMap::iterator it = map.find(id); if(it != map.end()) { EventList& moveEventList = it->second.moveEvent[moveEvent->getEventType()]; for(EventList::iterator it = moveEventList.begin(); it != moveEventList.end(); ++it) { if((*it)->getSlot() != moveEvent->getSlot()) continue; if(override) { delete *it; *it = moveEvent; } else std::clog << "[Warning - MoveEvents::addEvent] Duplicate move event found: " << id << std::endl; return; } moveEventList.push_back(moveEvent); } else { MoveEventList moveEventList; moveEventList.moveEvent[moveEvent->getEventType()].push_back(moveEvent); map[id] = moveEventList; } } MoveEvent* MoveEvents::getEvent(Item* item, MoveEvent_t eventType) { MoveListMap::iterator it; if(item->getUniqueId()) { it = m_uniqueIdMap.find(item->getUniqueId()); if(it != m_uniqueIdMap.end()) { EventList& moveEventList = it->second.moveEvent[eventType]; if(!moveEventList.empty()) return *moveEventList.begin(); } } if(item->getActionId()) { it = m_actionIdMap.find(item->getActionId()); if(it != m_actionIdMap.end()) { EventList& moveEventList = it->second.moveEvent[eventType]; if(!moveEventList.empty()) return *moveEventList.begin(); } } it = m_itemIdMap.find(item->getID()); if(it != m_itemIdMap.end()) { EventList& moveEventList = it->second.moveEvent[eventType]; if(!moveEventList.empty()) return *moveEventList.begin(); } return NULL; } MoveEvent* MoveEvents::getEvent(Item* item, MoveEvent_t eventType, slots_t slot) { uint32_t slotp = 0; switch(slot) { case SLOT_HEAD: slotp = SLOTP_HEAD; break; case SLOT_NECKLACE: slotp = SLOTP_NECKLACE; break; case SLOT_BACKPACK: slotp = SLOTP_BACKPACK; break; case SLOT_ARMOR: slotp = SLOTP_ARMOR; break; case SLOT_RIGHT: slotp = SLOTP_RIGHT; break; case SLOT_LEFT: slotp = SLOTP_LEFT; break; case SLOT_LEGS: slotp = SLOTP_LEGS; break; case SLOT_FEET: slotp = SLOTP_FEET; break; case SLOT_AMMO: slotp = SLOTP_AMMO; break; case SLOT_RING: slotp = SLOTP_RING; break; default: break; } MoveListMap::iterator it = m_itemIdMap.find(item->getID()); if(it == m_itemIdMap.end()) return NULL; EventList& moveEventList = it->second.moveEvent[eventType]; for(EventList::iterator it = moveEventList.begin(); it != moveEventList.end(); ++it) { if(((*it)->getSlot() & slotp)) return *it; } return NULL; } void MoveEvents::addEvent(MoveEvent* moveEvent, Position pos, MovePosListMap& map, bool override) { MovePosListMap::iterator it = map.find(pos); if(it != map.end()) { bool add = true; if(!it->second.moveEvent[moveEvent->getEventType()].empty()) { if(!override) { std::clog << "[Warning - MoveEvents::addEvent] Duplicate move event found: " << pos << std::endl; add = false; } else it->second.moveEvent[moveEvent->getEventType()].clear(); } if(add) it->second.moveEvent[moveEvent->getEventType()].push_back(moveEvent); } else { MoveEventList moveEventList; moveEventList.moveEvent[moveEvent->getEventType()].push_back(moveEvent); map[pos] = moveEventList; } } MoveEvent* MoveEvents::getEvent(const Tile* tile, MoveEvent_t eventType) { MovePosListMap::iterator it = m_positionMap.find(tile->getPosition()); if(it == m_positionMap.end()) return NULL; EventList& moveEventList = it->second.moveEvent[eventType]; if(!moveEventList.empty()) return *moveEventList.begin(); return NULL; } bool MoveEvents::hasEquipEvent(Item* item) { MoveEvent* event = NULL; return (event = getEvent(item, MOVE_EVENT_EQUIP)) && !event->isScripted() && (event = getEvent(item, MOVE_EVENT_DE_EQUIP)) && !event->isScripted(); } bool MoveEvents::hasTileEvent(Item* item) { return getEvent(item, MOVE_EVENT_STEP_IN) || getEvent(item, MOVE_EVENT_STEP_OUT) || getEvent( item, MOVE_EVENT_ADD_TILEITEM) || getEvent(item, MOVE_EVENT_REMOVE_TILEITEM); } uint32_t MoveEvents::onCreatureMove(Creature* actor, Creature* creature, const Tile* fromTile, const Tile* toTile, bool isStepping) { MoveEvent_t eventType = MOVE_EVENT_STEP_OUT; const Tile* tile = fromTile; if(isStepping) { eventType = MOVE_EVENT_STEP_IN; tile = toTile; } Position fromPos; if(fromTile) fromPos = fromTile->getPosition(); Position toPos; if(toTile) toPos = toTile->getPosition(); uint32_t ret = 1; MoveEvent* moveEvent = NULL; if((moveEvent = getEvent(tile, eventType))) ret &= moveEvent->fireStepEvent(actor, creature, NULL, Position(), fromPos, toPos); Item* tileItem = NULL; if(m_lastCacheTile == tile) { if(m_lastCacheItemVector.empty()) return ret; //We cannot use iterators here since the scripts can invalidate the iterator for(uint32_t i = 0; i < m_lastCacheItemVector.size(); ++i) { if((tileItem = m_lastCacheItemVector[i]) && (moveEvent = getEvent(tileItem, eventType))) ret &= moveEvent->fireStepEvent(actor, creature, tileItem, tile->getPosition(), fromPos, toPos); } return ret; } m_lastCacheTile = tile; m_lastCacheItemVector.clear(); //We cannot use iterators here since the scripts can invalidate the iterator Thing* thing = NULL; for(int32_t i = tile->__getFirstIndex(), j = tile->__getLastIndex(); i < j; ++i) //already checked the ground { if(!(thing = tile->__getThing(i)) || !(tileItem = thing->getItem())) continue; if((moveEvent = getEvent(tileItem, eventType))) { m_lastCacheItemVector.push_back(tileItem); ret &= moveEvent->fireStepEvent(actor, creature, tileItem, tile->getPosition(), fromPos, toPos); } else if(hasTileEvent(tileItem)) m_lastCacheItemVector.push_back(tileItem); } return ret; } bool MoveEvents::onPlayerEquip(Player* player, Item* item, slots_t slot, bool isCheck) { if(MoveEvent* moveEvent = getEvent(item, MOVE_EVENT_EQUIP, slot)) return moveEvent->fireEquip(player, item, slot, isCheck); return true; } bool MoveEvents::onPlayerDeEquip(Player* player, Item* item, slots_t slot, bool isRemoval) { if(MoveEvent* moveEvent = getEvent(item, MOVE_EVENT_DE_EQUIP, slot)) return moveEvent->fireEquip(player, item, slot, isRemoval); return true; } uint32_t MoveEvents::onItemMove(Creature* actor, Item* item, Tile* tile, bool isAdd) { MoveEvent_t eventType = MOVE_EVENT_REMOVE_ITEM, tileEventType = MOVE_EVENT_REMOVE_TILEITEM; if(isAdd) { eventType = MOVE_EVENT_ADD_ITEM; tileEventType = MOVE_EVENT_ADD_TILEITEM; } uint32_t ret = 1; MoveEvent* moveEvent = getEvent(tile, eventType); if(moveEvent) ret &= moveEvent->fireAddRemItem(actor, item, NULL, tile->getPosition()); moveEvent = getEvent(item, eventType); if(moveEvent) ret &= moveEvent->fireAddRemItem(actor, item, NULL, tile->getPosition()); Item* tileItem = NULL; if(m_lastCacheTile == tile) { if(m_lastCacheItemVector.empty()) return ret; //We cannot use iterators here since the scripts can invalidate the iterator for(uint32_t i = 0; i < m_lastCacheItemVector.size(); ++i) { if((tileItem = m_lastCacheItemVector[i]) && tileItem != item && (moveEvent = getEvent(tileItem, tileEventType))) ret &= moveEvent->fireAddRemItem(actor, item, tileItem, tile->getPosition()); } return ret; } m_lastCacheTile = tile; m_lastCacheItemVector.clear(); //we cannot use iterators here since the scripts can invalidate the iterator Thing* thing = NULL; for(int32_t i = tile->__getFirstIndex(), j = tile->__getLastIndex(); i < j; ++i) //already checked the ground { if(!(thing = tile->__getThing(i)) || !(tileItem = thing->getItem()) || tileItem == item) continue; if((moveEvent = getEvent(tileItem, tileEventType))) { m_lastCacheItemVector.push_back(tileItem); ret &= moveEvent->fireAddRemItem(actor, item, tileItem, tile->getPosition()); } else if(hasTileEvent(tileItem)) m_lastCacheItemVector.push_back(tileItem); } return ret; } void MoveEvents::onAddTileItem(const Tile* tile, Item* item) { if(m_lastCacheTile != tile) return; std::vector<Item*>::iterator it = std::find(m_lastCacheItemVector.begin(), m_lastCacheItemVector.end(), item); if(it == m_lastCacheItemVector.end() && hasTileEvent(item)) m_lastCacheItemVector.push_back(item); } void MoveEvents::onRemoveTileItem(const Tile* tile, Item* item) { if(m_lastCacheTile != tile) return; for(uint32_t i = 0; i < m_lastCacheItemVector.size(); ++i) { if(m_lastCacheItemVector[i] != item) continue; m_lastCacheItemVector[i] = NULL; break; } } MoveEvent::MoveEvent(LuaInterface* _interface): Event(_interface) { m_eventType = MOVE_EVENT_NONE; stepFunction = NULL; moveFunction = NULL; equipFunction = NULL; slot = SLOTP_WHEREEVER; wieldInfo = 0; reqLevel = 0; reqMagLevel = 0; premium = false; } MoveEvent::MoveEvent(const MoveEvent* copy): Event(copy) { m_eventType = copy->m_eventType; stepFunction = copy->stepFunction; moveFunction = copy->moveFunction; equipFunction = copy->equipFunction; slot = copy->slot; if(copy->m_eventType == MOVE_EVENT_EQUIP) { wieldInfo = copy->wieldInfo; reqLevel = copy->reqLevel; reqMagLevel = copy->reqMagLevel; vocationString = copy->vocationString; premium = copy->premium; vocEquipMap = copy->vocEquipMap; } } MoveEvent::~MoveEvent() { // } std::string MoveEvent::getScriptEventName() const { switch(m_eventType) { case MOVE_EVENT_STEP_IN: return "onStepIn"; case MOVE_EVENT_STEP_OUT: return "onStepOut"; case MOVE_EVENT_EQUIP: return "onEquip"; case MOVE_EVENT_DE_EQUIP: return "onDeEquip"; case MOVE_EVENT_ADD_ITEM: return "onAddItem"; case MOVE_EVENT_REMOVE_ITEM: return "onRemoveItem"; default: break; } std::clog << "[Error - MoveEvent::getScriptEventName] No valid event type." << std::endl; return ""; } std::string MoveEvent::getScriptEventParams() const { switch(m_eventType) { case MOVE_EVENT_STEP_IN: case MOVE_EVENT_STEP_OUT: return "cid, item, position, lastPosition, fromPosition, toPosition, actor"; case MOVE_EVENT_EQUIP: case MOVE_EVENT_DE_EQUIP: return "cid, item, slot, boolean"; case MOVE_EVENT_ADD_ITEM: case MOVE_EVENT_REMOVE_ITEM: return "moveItem, tileItem, position, cid"; default: break; } std::clog << "[Error - MoveEvent::getScriptEventParams] No valid event type." << std::endl; return ""; } bool MoveEvent::configureEvent(xmlNodePtr p) { std::string strValue; int32_t intValue; if(readXMLString(p, "type", strValue) || readXMLString(p, "event", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "stepin") m_eventType = MOVE_EVENT_STEP_IN; else if(tmpStrValue == "stepout") m_eventType = MOVE_EVENT_STEP_OUT; else if(tmpStrValue == "equip") m_eventType = MOVE_EVENT_EQUIP; else if(tmpStrValue == "deequip") m_eventType = MOVE_EVENT_DE_EQUIP; else if(tmpStrValue == "additem") m_eventType = MOVE_EVENT_ADD_ITEM; else if(tmpStrValue == "removeitem") m_eventType = MOVE_EVENT_REMOVE_ITEM; else { if(tmpStrValue == "function" || tmpStrValue == "buffer" || tmpStrValue == "script") std::clog << "[Error - MoveEvent::configureMoveEvent] No event type found." << std::endl; else std::clog << "[Error - MoveEvent::configureMoveEvent] Unknown event type \"" << strValue << "\"" << std::endl; return false; } if(m_eventType == MOVE_EVENT_EQUIP || m_eventType == MOVE_EVENT_DE_EQUIP) { if(readXMLString(p, "slot", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "head") slot = SLOTP_HEAD; else if(tmpStrValue == "necklace") slot = SLOTP_NECKLACE; else if(tmpStrValue == "backpack") slot = SLOTP_BACKPACK; else if(tmpStrValue == "armor") slot = SLOTP_ARMOR; else if(tmpStrValue == "left-hand") slot = SLOTP_LEFT; else if(tmpStrValue == "right-hand") slot = SLOTP_RIGHT; else if(tmpStrValue == "hands" || tmpStrValue == "two-handed") slot = SLOTP_TWO_HAND; else if(tmpStrValue == "hand" || tmpStrValue == "shield") slot = SLOTP_RIGHT | SLOTP_LEFT; else if(tmpStrValue == "legs") slot = SLOTP_LEGS; else if(tmpStrValue == "feet") slot = SLOTP_FEET; else if(tmpStrValue == "ring") slot = SLOTP_RING; else if(tmpStrValue == "ammo" || tmpStrValue == "ammunition") slot = SLOTP_AMMO; else if(tmpStrValue == "pickupable") slot = SLOTP_RIGHT | SLOTP_LEFT | SLOTP_AMMO; else if(tmpStrValue == "wherever" || tmpStrValue == "any") slot = SLOTP_WHEREEVER; else std::clog << "[Warning - MoveEvent::configureMoveEvent] Unknown slot type \"" << strValue << "\"" << std::endl; } wieldInfo = 0; if(readXMLInteger(p, "lvl", intValue) || readXMLInteger(p, "level", intValue)) { reqLevel = intValue; if(reqLevel > 0) wieldInfo |= WIELDINFO_LEVEL; } if(readXMLInteger(p, "maglv", intValue) || readXMLInteger(p, "maglevel", intValue)) { reqMagLevel = intValue; if(reqMagLevel > 0) wieldInfo |= WIELDINFO_MAGLV; } if(readXMLString(p, "prem", strValue) || readXMLString(p, "premium", strValue)) { premium = booleanString(strValue); if(premium) wieldInfo |= WIELDINFO_PREMIUM; } StringVec vocStringVec; std::string error = ""; for(xmlNodePtr vocationNode = p->children; vocationNode; vocationNode = vocationNode->next) { if(!parseVocationNode(vocationNode, vocEquipMap, vocStringVec, error)) std::clog << "[Warning - MoveEvent::configureEvent] " << error << std::endl; } if(!vocEquipMap.empty()) wieldInfo |= WIELDINFO_VOCREQ; vocationString = parseVocationString(vocStringVec); } } else { std::clog << "[Error - MoveEvent::configureMoveEvent] No event type found." << std::endl; return false; } return true; } bool MoveEvent::loadFunction(const std::string& functionName) { std::string tmpFunctionName = asLowerCaseString(functionName); if(tmpFunctionName == "onstepinfield") stepFunction = StepInField; else if(tmpFunctionName == "onaddfield") moveFunction = AddItemField; else if(tmpFunctionName == "onequipitem") equipFunction = EquipItem; else if(tmpFunctionName == "ondeequipitem") equipFunction = DeEquipItem; else { std::clog << "[Warning - MoveEvent::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; return false; } m_scripted = EVENT_SCRIPT_FALSE; return true; } MoveEvent_t MoveEvent::getEventType() const { if(m_eventType == MOVE_EVENT_NONE) std::clog << "[Error - MoveEvent::getEventType] MOVE_EVENT_NONE" << std::endl; return m_eventType; } void MoveEvent::setEventType(MoveEvent_t type) { m_eventType = type; } uint32_t MoveEvent::StepInField(Creature* creature, Item* item) { if(MagicField* field = item->getMagicField()) { field->onStepInField(creature, creature->getPlayer()); return 1; } return LUA_ERROR_ITEM_NOT_FOUND; } uint32_t MoveEvent::AddItemField(Item* item) { if(MagicField* field = item->getMagicField()) { if(Tile* tile = item->getTile()) { if(CreatureVector* creatures = tile->getCreatures()) { for(CreatureVector::iterator cit = creatures->begin(); cit != creatures->end(); ++cit) field->onStepInField(*cit); } } return 1; } return LUA_ERROR_ITEM_NOT_FOUND; } bool MoveEvent::EquipItem(MoveEvent* moveEvent, Player* player, Item* item, slots_t slot, bool isCheck) { if(player->isItemAbilityEnabled(slot)) return true; if(!player->hasFlag(PlayerFlag_IgnoreEquipCheck) && moveEvent->getWieldInfo() != 0) { if(player->getLevel() < (uint32_t)moveEvent->getReqLevel() || player->getMagicLevel() < (uint32_t)moveEvent->getReqMagLv()) return false; if(moveEvent->isPremium() && !player->isPremium()) return false; if(!moveEvent->getVocEquipMap().empty() && moveEvent->getVocEquipMap().find(player->getVocationId()) == moveEvent->getVocEquipMap().end()) return false; } if(isCheck) return true; const ItemType& it = Item::items[item->getID()]; if(it.transformEquipTo) { Item* newItem = g_game.transformItem(item, it.transformEquipTo); g_game.startDecay(newItem); } player->setItemAbility(slot, true); if(it.abilities.invisible) { Condition* condition = Condition::createCondition((ConditionId_t)slot, CONDITION_INVISIBLE, -1, 0); player->addCondition(condition); } if(it.abilities.manaShield) { Condition* condition = Condition::createCondition((ConditionId_t)slot, CONDITION_MANASHIELD, -1, 0); player->addCondition(condition); } if(it.abilities.speed) g_game.changeSpeed(player, it.abilities.speed); if(it.abilities.conditionSuppressions) { player->setConditionSuppressions(it.abilities.conditionSuppressions, false); player->sendIcons(); } if(it.abilities.regeneration) { Condition* condition = Condition::createCondition((ConditionId_t)slot, CONDITION_REGENERATION, -1, 0); if(it.abilities.healthGain) condition->setParam(CONDITIONPARAM_HEALTHGAIN, it.abilities.healthGain); if(it.abilities.healthTicks) condition->setParam(CONDITIONPARAM_HEALTHTICKS, it.abilities.healthTicks); if(it.abilities.manaGain) condition->setParam(CONDITIONPARAM_MANAGAIN, it.abilities.manaGain); if(it.abilities.manaTicks) condition->setParam(CONDITIONPARAM_MANATICKS, it.abilities.manaTicks); player->addCondition(condition); } bool needUpdateSkills = false; for(uint32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { if(it.abilities.skills[i]) { player->setVarSkill((skills_t)i, it.abilities.skills[i]); if(!needUpdateSkills) needUpdateSkills = true; } if(it.abilities.skillsPercent[i]) { player->setVarSkill((skills_t)i, (int32_t)(player->getSkill((skills_t)i, SKILL_LEVEL) * ((it.abilities.skillsPercent[i] - 100) / 100.f))); if(!needUpdateSkills) needUpdateSkills = true; } } if(needUpdateSkills) player->sendSkills(); bool needUpdateStats = false; for(uint32_t s = STAT_FIRST; s <= STAT_LAST; ++s) { if(it.abilities.stats[s]) { player->setVarStats((stats_t)s, it.abilities.stats[s]); if(!needUpdateStats) needUpdateStats = true; } if(it.abilities.statsPercent[s]) { player->setVarStats((stats_t)s, (int32_t)(player->getDefaultStats((stats_t)s) * ((it.abilities.statsPercent[s] - 100) / 100.f))); if(!needUpdateStats) needUpdateStats = true; } } if(needUpdateStats) player->sendStats(); return true; } bool MoveEvent::DeEquipItem(MoveEvent*, Player* player, Item* item, slots_t slot, bool isRemoval) { if(!player->isItemAbilityEnabled(slot)) return true; const ItemType& it = Item::items[item->getID()]; if(isRemoval && it.transformDeEquipTo) { g_game.transformItem(item, it.transformDeEquipTo); g_game.startDecay(item); } player->setItemAbility(slot, false); if(it.abilities.invisible) player->removeCondition(CONDITION_INVISIBLE, (ConditionId_t)slot); if(it.abilities.manaShield) player->removeCondition(CONDITION_MANASHIELD, (ConditionId_t)slot); if(it.abilities.speed) g_game.changeSpeed(player, -it.abilities.speed); if(it.abilities.conditionSuppressions) { player->setConditionSuppressions(it.abilities.conditionSuppressions, true); player->sendIcons(); } if(it.abilities.regeneration) player->removeCondition(CONDITION_REGENERATION, (ConditionId_t)slot); bool needUpdateSkills = false; for(uint32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { if(it.abilities.skills[i]) { needUpdateSkills = true; player->setVarSkill((skills_t)i, -it.abilities.skills[i]); } if(it.abilities.skillsPercent[i]) { needUpdateSkills = true; player->setVarSkill((skills_t)i, -(int32_t)(player->getSkill((skills_t)i, SKILL_LEVEL) * ((it.abilities.skillsPercent[i] - 100) / 100.f))); } } if(needUpdateSkills) player->sendSkills(); bool needUpdateStats = false; for(uint32_t s = STAT_FIRST; s <= STAT_LAST; ++s) { if(it.abilities.stats[s]) { needUpdateStats = true; player->setVarStats((stats_t)s, -it.abilities.stats[s]); } if(it.abilities.statsPercent[s]) { needUpdateStats = true; player->setVarStats((stats_t)s, -(int32_t)(player->getDefaultStats((stats_t)s) * ((it.abilities.statsPercent[s] - 100) / 100.f))); } } if(needUpdateStats) player->sendStats(); return true; } uint32_t MoveEvent::fireStepEvent(Creature* actor, Creature* creature, Item* item, const Position& pos, const Position& fromPos, const Position& toPos) { if(isScripted()) return executeStep(actor, creature, item, pos, fromPos, toPos); return stepFunction(creature, item); } uint32_t MoveEvent::executeStep(Creature* actor, Creature* creature, Item* item, const Position& pos, const Position& fromPos, const Position& toPos) { //onStepIn(cid, item, position, lastPosition, fromPosition, toPosition, actor) //onStepOut(cid, item, position, lastPosition, fromPosition, toPosition, actor) if(m_interface->reserveEnv()) { MoveEventScript::event = this; ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; env->streamThing(scriptstream, "item", item, env->addThing(item)); env->streamPosition(scriptstream, "position", pos, 0); env->streamPosition(scriptstream, "lastPosition", creature->getLastPosition(), 0); env->streamPosition(scriptstream, "fromPosition", fromPos, 0); env->streamPosition(scriptstream, "toPosition", toPos, 0); scriptstream << "local actor = " << env->addThing(actor) << std::endl; 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__ std::stringstream desc; desc << creature->getName() << " itemid: " << item->getID() << " - " << pos; env->setEvent(desc.str()); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); LuaInterface::pushThing(L, item, env->addThing(item)); LuaInterface::pushPosition(L, pos, 0); LuaInterface::pushPosition(L, creature->getLastPosition(), 0); LuaInterface::pushPosition(L, fromPos, 0); LuaInterface::pushPosition(L, toPos, 0); lua_pushnumber(L, env->addThing(actor)); bool result = m_interface->callFunction(7); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - MoveEvent::executeStep] Call stack overflow." << std::endl; return 0; } } bool MoveEvent::fireEquip(Player* player, Item* item, slots_t slot, bool boolean) { if(isScripted()) return executeEquip(player, item, slot, boolean); return equipFunction(this, player, item, slot, boolean); } bool MoveEvent::executeEquip(Player* player, Item* item, slots_t slot, bool boolean) { //onEquip(cid, item, slot, boolean) //onDeEquip(cid, item, slot, boolean) if(m_interface->reserveEnv()) { MoveEventScript::event = this; 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)); scriptstream << "local slot = " << slot << std::endl; scriptstream << "local boolean = " << (boolean ? "true" : "false") << std::endl; 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__ std::stringstream desc; desc << player->getName() << " itemid: " << item->getID() << " slot: " << slot; env->setEvent(desc.str()); #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)); lua_pushnumber(L, slot); lua_pushboolean(L, boolean); bool result = m_interface->callFunction(4); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - MoveEvent::executeEquip] Call stack overflow." << std::endl; return false; } } uint32_t MoveEvent::fireAddRemItem(Creature* actor, Item* item, Item* tileItem, const Position& pos) { if(isScripted()) return executeAddRemItem(actor, item, tileItem, pos); return moveFunction(item); } uint32_t MoveEvent::executeAddRemItem(Creature* actor, Item* item, Item* tileItem, const Position& pos) { //onAddItem(moveItem, tileItem, position, cid) //onRemoveItem(moveItem, tileItem, position, cid) if(m_interface->reserveEnv()) { MoveEventScript::event = this; ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(pos); std::stringstream scriptstream; env->streamThing(scriptstream, "moveItem", item, env->addThing(item)); env->streamThing(scriptstream, "tileItem", tileItem, env->addThing(tileItem)); env->streamPosition(scriptstream, "position", pos, 0); scriptstream << "local cid = " << env->addThing(actor) << std::endl; 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__ std::stringstream desc; if(tileItem) desc << "tileid: " << tileItem->getID(); desc << " itemid: " << item->getID() << " - " << pos; env->setEvent(desc.str()); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(pos); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); LuaInterface::pushThing(L, item, env->addThing(item)); LuaInterface::pushThing(L, tileItem, env->addThing(tileItem)); LuaInterface::pushPosition(L, pos, 0); lua_pushnumber(L, env->addThing(actor)); bool result = m_interface->callFunction(4); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - MoveEvent::executeAddRemItem] Call stack overflow." << std::endl; return 0; } }
  11. function doPlayerGiveItem(cid, itemid, amount, subType) local item = 0 if(isItemStackable(itemid)) then item = doCreateItemEx(itemid, amount) if(doPlayerAddItemEx(cid, item, true) ~= RETURNVALUE_NOERROR) then return false end else for i = 1, amount do item = doCreateItemEx(itemid, subType) if(doPlayerAddItemEx(cid, item, true) ~= RETURNVALUE_NOERROR) then return false end end end return true end function doPlayerGiveItemContainer(cid, containerid, itemid, amount, subType) for i = 1, amount do local container = doCreateItemEx(containerid, 1) for x = 1, getContainerCapById(containerid) do doAddContainerItem(container, itemid, subType) end if(doPlayerAddItemEx(cid, container, true) ~= RETURNVALUE_NOERROR) then return false end end return true end function doPlayerTakeItem(cid, itemid, amount) return getPlayerItemCount(cid, itemid) >= amount and doPlayerRemoveItem(cid, itemid, amount) end function doPlayerBuyItem(cid, itemid, count, cost, charges) return doPlayerRemoveMoney(cid, cost) and doPlayerGiveItem(cid, itemid, count, charges) end function doPlayerBuyItemContainer(cid, containerid, itemid, count, cost, charges) return doPlayerRemoveMoney(cid, cost) and doPlayerGiveItemContainer(cid, containerid, itemid, count, charges) end function doPlayerSellItem(cid, itemid, count, cost) if(not doPlayerTakeItem(cid, itemid, count)) then return false end if(not doPlayerAddMoney(cid, cost)) then error('[doPlayerSellItem] Could not add money to: ' .. getPlayerName(cid) .. ' (' .. cost .. 'gp).') end return true end function doPlayerWithdrawMoney(cid, amount) if(not getBooleanFromString(getConfigInfo('bankSystem'))) then return false end local balance = getPlayerBalance(cid) if(amount > balance or not doPlayerAddMoney(cid, amount)) then return false end doPlayerSetBalance(cid, balance - amount) return true end function doPlayerDepositMoney(cid, amount) if(not getBooleanFromString(getConfigInfo('bankSystem'))) then return false end if(not doPlayerRemoveMoney(cid, amount)) then return false end doPlayerSetBalance(cid, getPlayerBalance(cid) + amount) return true end function doPlayerAddStamina(cid, minutes) return doPlayerSetStamina(cid, getPlayerStamina(cid) + minutes) end function isPremium(cid) return (isPlayer(cid) and (getPlayerPremiumDays(cid) > 0 or getBooleanFromString(getConfigValue('freePremium')))) end function getMonthDayEnding(day) if(day == "01" or day == "21" or day == "31") then return "st" elseif(day == "02" or day == "22") then return "nd" elseif(day == "03" or day == "23") then return "rd" end return "th" end function getMonthString(m) return os.date("%B", os.time{year = 1970, month = m, day = 1}) end function getArticle(str) return str:find("[AaEeIiOoUuYy]") == 1 and "an" or "a" end function isNumeric(str) return tonumber(str) ~= nil end function doNumberFormat(i) local str, found = string.gsub(i, "(%d)(%d%d%d)$", "%1,%2", 1), 0 repeat str, found = string.gsub(str, "(%d)(%d%d%d),", "%1,%2,", 1) until found == 0 return str end function doPlayerAddAddons(cid, addon) for i = 0, table.maxn(maleOutfits) do doPlayerAddOutfit(cid, maleOutfits[i], addon) end for i = 0, table.maxn(femaleOutfits) do doPlayerAddOutfit(cid, femaleOutfits[i], addon) end end function doPlayerWithdrawAllMoney(cid) return doPlayerWithdrawMoney(cid, getPlayerBalance(cid)) end function doPlayerDepositAllMoney(cid) return doPlayerDepositMoney(cid, getPlayerMoney(cid)) end function doPlayerTransferAllMoneyTo(cid, target) return doPlayerTransferMoneyTo(cid, target, getPlayerBalance(cid)) end function playerExists(name) return getPlayerGUIDByName(name) ~= nil end function getTibiaTime() local minutes, hours = getWorldTime(), 0 while (minutes > 60) do hours = hours + 1 minutes = minutes - 60 end return {hours = hours, minutes = minutes} end function doWriteLogFile(file, text) local f = io.open(file, "a+") if(not f) then return false end f:write("[" .. os.date("%d/%m/%Y %H:%M:%S") .. "] " .. text .. "\n") f:close() return true end function getExperienceForLevel(lv) lv = lv - 1 return ((50 * lv * lv * lv) - (150 * lv * lv) + (400 * lv)) / 3 end function doMutePlayer(cid, time) local condition = createConditionObject(CONDITION_MUTED) setConditionParam(condition, CONDITION_PARAM_TICKS, time == -1 and time or time * 1000) return doAddCondition(cid, condition) end function getPlayerGroupName(cid) return getGroupInfo(getPlayerGroupId(cid)).name end function getPlayerVocationName(cid) return getVocationInfo(getPlayerVocation(cid)).name end function getPromotedVocation(vid) return getVocationInfo(vid).promotedVocation end function doPlayerRemovePremiumDays(cid, days) return doPlayerAddPremiumDays(cid, -days) end function getPlayerMasterPos(cid) return getTownTemplePosition(getPlayerTown(cid)) end function getHouseOwner(houseId) return getHouseInfo(houseId).owner end function getHouseName(houseId) return getHouseInfo(houseId).name end function getHouseEntry(houseId) return getHouseInfo(houseId).entry end function getHouseRent(houseId) return getHouseInfo(houseId).rent end function getHousePrice(houseId) return getHouseInfo(houseId).price end function getHouseTown(houseId) return getHouseInfo(houseId).town end function getHouseDoorsCount(houseId) return table.maxn(getHouseInfo(houseId).doors) end function getHouseBedsCount(houseId) return table.maxn(getHouseInfo(houseId).beds) end function getHouseTilesCount(houseId) return table.maxn(getHouseInfo(houseId).tiles) end function getItemNameById(itemid) return getItemDescriptionsById(itemid).name end function getItemPluralNameById(itemid) return getItemDescriptionsById(itemid).plural end function getItemArticleById(itemid) return getItemDescriptionsById(itemid).article end function getItemName(uid) return getItemDescriptions(uid).name end function getItemPluralName(uid) return getItemDescriptions(uid).plural end function getItemArticle(uid) return getItemDescriptions(uid).article end function getItemText(uid) return getItemDescriptions(uid).text end function getItemSpecialDescription(uid) return getItemDescriptions(uid).special end function getItemWriter(uid) return getItemDescriptions(uid).writer end function getItemDate(uid) return getItemDescriptions(uid).date end function getTilePzInfo(pos) return getTileInfo(pos).protection end function getTileZoneInfo(pos) local tmp = getTileInfo(pos) if(tmp.pvp) then return 2 end if(tmp.nopvp) then return 1 end return 0 end function doShutdown() return doSetGameState(GAMESTATE_SHUTDOWN) end function doSummonCreature(name, pos, displayError) local displayError, cid = displayError or true, doCreateMonster(name, pos, false, false, displayError) if(not cid) then cid = doCreateNpc(name, pos, displayError) end return cid end function getOnlinePlayers() local players = {} for i, cid in ipairs(getPlayersOnline()) do table.insert(players, getCreatureName(cid)) end return players end function getPlayerByName(name) local cid = getCreatureByName(name) return isPlayer(cid) and cid or nil end function isPlayer(cid) return isCreature(cid) and cid >= AUTOID_PLAYERS and cid < AUTOID_MONSTERS end function isPlayerGhost(cid) return isPlayer(cid) and (getCreatureCondition(cid, CONDITION_GAMEMASTER, GAMEMASTER_INVISIBLE) or getPlayerFlagValue(cid, PLAYERFLAG_CANNOTBESEEN)) end function isMonster(cid) return isCreature(cid) and cid >= AUTOID_MONSTERS and cid < AUTOID_NPCS end function isNpc(cid) return isCreature(cid) and cid >= AUTOID_NPCS end function doPlayerSetExperienceRate(cid, value) return doPlayerSetRate(cid, SKILL__LEVEL, value) end function doPlayerSetMagicRate(cid, value) return doPlayerSetRate(cid, SKILL__MAGLEVEL, value) end function doPlayerAddLevel(cid, amount, round) local experience, level, amount = 0, getPlayerLevel(cid), amount or 1 if(amount > 0) then experience = getExperienceForLevel(level + amount) - (round and getPlayerExperience(cid) or getExperienceForLevel(level)) else experience = -((round and getPlayerExperience(cid) or getExperienceForLevel(level)) - getExperienceForLevel(level + amount)) end return doPlayerAddExperience(cid, experience) end function doPlayerAddMagLevel(cid, amount) for i = 1, amount do doPlayerAddSpentMana(cid, getPlayerRequiredMana(cid, getPlayerMagLevel(cid, true) + 1) - getPlayerSpentMana(cid), false) end return true end function doPlayerAddSkill(cid, skill, amount, round) local amount = amount or 1 if(skill == SKILL__LEVEL) then return doPlayerAddLevel(cid, amount, round) elseif(skill == SKILL__MAGLEVEL) then return doPlayerAddMagLevel(cid, amount) end for i = 1, amount do doPlayerAddSkillTry(cid, skill, getPlayerRequiredSkillTries(cid, skill, getPlayerSkillLevel(cid, skill) + 1) - getPlayerSkillTries(cid, skill), false) end return true end function getPartyLeader(cid) local party = getPartyMembers(cid) if(type(party) ~= 'table') then return 0 end return party[1] end function isInParty(cid) return type(getPartyMembers(cid)) == 'table' end function isPrivateChannel(channelId) return channelId >= CHANNEL_PRIVATE end function doPlayerResetIdleTime(cid) return doPlayerSetIdleTime(cid, 0) end function doBroadcastMessage(text, class) local class = class or MESSAGE_STATUS_WARNING if(type(class) == 'string') then local className = MESSAGE_TYPES[class] if(className == nil) then return false end class = className elseif(class < MESSAGE_FIRST or class > MESSAGE_LAST) then return false end for _, pid in ipairs(getPlayersOnline()) do doPlayerSendTextMessage(pid, class, text) end print("> Broadcasted message: \"" .. text .. "\".") return true end function doPlayerBroadcastMessage(cid, text, class, checkFlag, ghost) local checkFlag, ghost, class = checkFlag or true, ghost or false, class or TALKTYPE_BROADCAST if(checkFlag and not getPlayerFlagValue(cid, PLAYERFLAG_CANBROADCAST)) then return false end if(type(class) == 'string') then local className = TALKTYPE_TYPES[class] if(className == nil) then return false end class = className elseif(class < TALKTYPE_FIRST or class > TALKTYPE_LAST) then return false end for _, pid in ipairs(getPlayersOnline()) do doCreatureSay(cid, text, class, ghost, pid) end print("> " .. getCreatureName(cid) .. " broadcasted message: \"" .. text .. "\".") return true end function getBooleanFromString(input) local tmp = type(input) if(tmp == 'boolean') then return input end if(tmp == 'number') then return input > 0 end local str = string.lower(tostring(input)) return (str == "yes" or str == "true" or (tonumber(str) ~= nil and tonumber(str) > 0)) end function doCopyItem(item, attributes) local attributes = ((type(attributes) == 'table') and attributes or { "aid" }) local ret = doCreateItemEx(item.itemid, item.type) for _, key in ipairs(attributes) do local value = getItemAttribute(item.uid, key) if(value ~= nil) then doItemSetAttribute(ret, key, value) end end if(isContainer(item.uid)) then for i = (getContainerSize(item.uid) - 1), 0, -1 do local tmp = getContainerItem(item.uid, i) if(tmp.itemid > 0) then doAddContainerItemEx(ret, doCopyItem(tmp, true).uid) end end end return getThing(ret) end function doRemoveThing(uid) if(isCreature(uid)) then return doRemoveCreature(uid) end return doRemoveItem(uid) end function setAttackFormula(combat, type, minl, maxl, minm, maxm, min, max) local min, max = min or 0, max or 0 return setCombatFormula(combat, type, -1, 0, -1, 0, minl, maxl, minm, maxm, -min, -max) end function setHealingFormula(combat, type, minl, maxl, minm, maxm, min, max) local min, max = min or 0, max or 0 return setCombatFormula(combat, type, 1, 0, 1, 0, minl, maxl, minm, maxm, min, max) end function doChangeTypeItem(uid, subtype) local thing = getThing(uid) if(thing.itemid < 100) then return false end local subtype = subtype or 1 return doTransformItem(thing.uid, thing.itemid, subtype) end function doSetItemText(uid, text, writer, date) local thing = getThing(uid) if(thing.itemid < 100) then return false end doItemSetAttribute(uid, "text", text) if(writer ~= nil) then doItemSetAttribute(uid, "writer", tostring(writer)) if(date ~= nil) then doItemSetAttribute(uid, "date", tonumber(date)) end end return true end function doItemSetActionId(uid, aid) return doItemSetAttribute(uid, "aid", aid) end function getFluidSourceType(itemid) local item = getItemInfo(itemid) return item and item.fluidSource or false end function getDepotId(uid) return getItemAttribute(uid, "depotid") or false end function getItemDescriptions(uid) local thing = getThing(uid) if(thing.itemid < 100) then return false end local item = getItemInfo(thing.itemid) return { name = getItemAttribute(uid, "name") or item.name, plural = getItemAttribute(uid, "pluralname") or item.plural, article = getItemAttribute(uid, "article") or item.article, special = getItemAttribute(uid, "description") or "", text = getItemAttribute(uid, "text") or "", writer = getItemAttribute(uid, "writer") or "", date = getItemAttribute(uid, "date") or 0 } end function getItemWeightById(itemid, count, precision) local item, count, precision = getItemInfo(itemid), count or 1, precision or false if(not item) then return false end if(count > 100) then -- print a warning, as its impossible to have more than 100 stackable items without "cheating" the count print('[Warning] getItemWeightById', 'Calculating weight for more than 100 items!') end local weight = item.weight * count --[[if(precision) then return weight end local t = string.explode(tostring(weight), ".") if(table.maxn(t) == 2) then return tonumber(t[1] .. "." .. string.sub(t[2], 1, 2)) end]]-- return weight end function getItemWeaponType(uid) local thing = getThing(uid) if(thing.itemid < 100) then return false end return getItemInfo(thing.itemid).weaponType end function getItemRWInfo(uid) local thing = getThing(uid) if(thing.itemid < 100) then return false end local item, flags = getItemInfo(thing.itemid), 0 if(item.readable) then flags = 1 end if(item.writable) then flags = flags + 2 end return flags end function getItemLevelDoor(itemid) local item = getItemInfo(itemid) return item and item.levelDoor or false end function isContainer(uid) local thing = getThing(uid) return thing.uid > 0 and thing.items ~= nil end function isItemStackable(itemid) local item = getItemInfo(itemid) return item and item.stackable or false end function isItemRune(itemid) local item = getItemInfo(itemid) return item and item.type == ITEM_TYPE_RUNE or false end function isItemDoor(itemid) local item = getItemInfo(itemid) return item and item.type == ITEM_TYPE_DOOR or false end function isItemContainer(itemid) local item = getItemInfo(itemid) return item and item.group == ITEM_GROUP_CONTAINER or false end function isItemFluidContainer(itemid) local item = getItemInfo(itemid) return item and item.group == ITEM_GROUP_FLUID or false end function isItemMovable(itemid) local item = getItemInfo(itemid) return item and item.movable or false end function isCorpse(uid) local thing = getThing(uid) if(thing.itemid < 100) then return false end local item = getItemInfo(thing.itemid) return item and item.corpseType ~= 0 or false end function getContainerCapById(itemid) local item = getItemInfo(itemid) if(not item or item.group ~= 2) then return false end return item.maxItems end function getMonsterAttackSpells(name) local monster = getMonsterInfo(name) return monster and monster.attacks or false end function getMonsterHealingSpells(name) local monster = getMonsterInfo(name) return monster and monster.defenses or false end function getMonsterLootList(name) local monster = getMonsterInfo(name) return monster and monster.loot or false end function getMonsterSummonList(name) local monster = getMonsterInfo(name) return monster and monster.summons or false end function choose(...) local arg = {...} return arg[math.random(1, table.maxn(arg))] end
  12. Buenas a todos, eu uso TFS 0.4, rev 4393 (8.71), eu gostaria que o NPC ao vender algo na loja, consultasse se o main backpack (a que fica no inventário) tem slot disponível pra concluir a venda, se não ele não vende e avisa o motivo. Eu acredito que seja no "sendGoods()" em algum desses arquivos a seguir, porém eu não sei fazer, alguém consegue me ajudar? PLAYER.CPP void Player::updateInventoryGoods(uint32_t itemId) { if(Item::items[itemId].worth) { sendGoods(); return; } for(ShopInfoList::iterator it = shopOffer.begin(); it != shopOffer.end(); ++it) { if(it->itemId != itemId) continue; sendGoods(); break; } } NPC.CPP (provavelmente na penúltima linha desse) void Npc::onPlayerTrade(Player* player, ShopEvent_t type, int32_t callback, uint16_t itemId, uint8_t count, uint8_t amount, bool ignore/* = false*/, bool inBackpacks/* = false*/) { if(type == SHOPEVENT_BUY) { if(NpcState* npcState = getState(player, true)) { npcState->amount = amount; npcState->subType = count; npcState->itemId = itemId; npcState->buyPrice = getListItemPrice(itemId, SHOPEVENT_BUY); npcState->ignore = ignore; npcState->inBackpacks = inBackpacks; const NpcResponse* response = getResponse(player, npcState, EVENT_PLAYER_SHOPBUY); executeResponse(player, npcState, response); } } else if(type == SHOPEVENT_SELL) { if(NpcState* npcState = getState(player, true)) { npcState->amount = amount; npcState->subType = count; npcState->itemId = itemId; npcState->sellPrice = getListItemPrice(itemId, SHOPEVENT_SELL); npcState->ignore = ignore; const NpcResponse* response = getResponse(player, npcState, EVENT_PLAYER_SHOPSELL); executeResponse(player, npcState, response); } } if(m_npcEventHandler) m_npcEventHandler->onPlayerTrade(player, callback, itemId, count, amount, ignore, inBackpacks); player->sendGoods(); } PROTOCOLGAME.CPP void ProtocolGame::sendGoods(const ShopInfoList& shop) { NetworkMessage_ptr msg = getOutputBuffer(); if(msg) { TRACK_MESSAGE(msg); msg->put<char>(0x7B); msg->put<uint32_t>((uint32_t)g_game.getMoney(player)); std::map<uint32_t, uint32_t> goodsMap; if(shop.size() >= 5) { for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit) { if(sit->sellPrice < 0) continue; int8_t subType = -1; if(sit->subType) { const ItemType& it = Item::items[sit->itemId]; if(it.hasSubType() && !it.stackable) subType = sit->subType; } uint32_t count = player->__getItemTypeCount(sit->itemId, subType); if(count > 0) goodsMap[sit->itemId] = count; } } else { std::map<uint32_t, uint32_t> tmpMap; player->__getAllItemTypeCount(tmpMap); for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit) { if(sit->sellPrice < 0) continue; int8_t subType = -1; const ItemType& it = Item::items[sit->itemId]; if(sit->subType && it.hasSubType() && !it.stackable) subType = sit->subType; if(subType != -1) { uint32_t count = subType; if(!it.isFluidContainer() && !it.isSplash()) count = player->__getItemTypeCount(sit->itemId, subType); if(count > 0) goodsMap[sit->itemId] = count; else goodsMap[sit->itemId] = 0; } else goodsMap[sit->itemId] = tmpMap[sit->itemId]; } } msg->put<char>(std::min(goodsMap.size(), (size_t)255)); std::map<uint32_t, uint32_t>::const_iterator it = goodsMap.begin(); for(uint32_t i = 0; it != goodsMap.end() && i < 255; ++it, ++i) { msg->putItemId(it->first); msg->put<char>(std::min(it->second, (uint32_t)255)); } } }
  13. Uso tfs 0.4 Rev 4393 (v8.7), eu estou procurando e até agora não encontrei as duas coisas que procuro: 1° - Gostaria de um sistema em que o npc aceite outras moedas além dos gold pieces, achei uns mas não é bem o que procuro, eu queria que ao colocar um item a venda no npc, eu coloco qual tipo de moeda de troca é(por exemplo, um cooper shield) e a quantidade, e na janela de trade aparece que a moeda de troca é um cooper shield por aquele item específico. 2° - Gostaria que ao comprar um item do npc, ele não vá para bags por exemplo, apenas para backpacks, mesmo tendo espaço na bag, a transação não será efetuada
  14. Desculpa reviver depois de tanto tempo, mas, os kills contam de todos do servidor ou cada player tem uma contagem?
  15. Eu uso tfs 0.4 E gostaria de saber se da pra fazer o seguinte: Quando um número X de um monster Y for morto no servidor, uma Raid Z acontece no servidor, por exemplo: Ao ser morto 10.000 dragons no servidor (conta os kills de todos os players do servidor) a Raid de Demodras acontece **(conta os dragons, Dragon lords e os hatchlings)** Desde já agradeço a quem puder ajudar.

Informação Importante

Confirmação de Termo