Líderes
Conteúdo Popular
Exibindo conteúdo com a maior reputação em 12/06/15 em %
-
Evento de Scripting?
Administrador e um outro reagiu a Killua por um tópico no fórum
Eu topo participar e acho boa a ideia do Daniel de fazer com base em uma frase tema. Quando só dá um tema tipo "dia das bruxas" fica muito em aberto e até difícil de ter ideia. Também acho legal ser liberado pra qualquer tfs e ter bastante peso a questão de "complexidade", tempo de execução e consumo de memória2 pontos -
Reward Chest & Boss Reward
SkyLigh reagiu a MatheusGlad por um tópico no fórum
Creditos: Baseado no code do cbrm: https://otland.net/threads/reward-chest-boss-reward-tfs-1-2.233397/ Instruções:: src/const.h: Embaixo de... ITEM_MARKET = 14405, ...Adicione: ITEM_REWARD_BAG = 21518, ITEM_REWARD_CHEST = 21584, REWARD_CHEST_DEPOTID = 99, src/depotchest.h: Embaixo de... explicit DepotChest(uint16_t _type); ...Adicione: uint32_t getDepotId() const { return depotId; } void setDepotId(uint32_t id) { depotId = id; } Embaixo de... uint32_t maxDepotItems; ...Adicione: uint32_t depotId; src/depotchest.cpp: Embaixo de... maxDepotItems = 1500; ...Adicione: depotId = 0; Em cima de... return Container::queryAdd(index, thing, count, flags, actor); ...Adicione: if (actor != nullptr && getDepotId() == REWARD_CHEST_DEPOTID) { return RETURNVALUE_NOTPOSSIBLE; } src/depotlocker.h: Em cima de... //cylinder implementations ...Adicione: void setMaxLockerItems(uint32_t maxitems) { maxSize = maxitems; } src/player.h: Embaixo de... DepotLocker* getDepotLocker(uint32_t depotId); ...Adicione: DepotChest* getRewardBag(uint32_t depotId, bool autoCreate); DepotLocker* getRewardChest(uint16_t itemId); src/player.cpp: Em cima de... void Player::sendCancelMessage(ReturnValue message) const ...Adicione: DepotChest* Player::getRewardBag(uint32_t depotId, bool autoCreate) { auto it = depotChests.find(depotId); if (it != depotChests.end()) { return it->second; } if (!autoCreate) { return nullptr; } DepotChest* bagReward = new DepotChest(ITEM_REWARD_BAG); bagReward->setDepotId(depotId); bagReward->incrementReferenceCounter(); bagReward->setMaxDepotItems(getMaxDepotItems()); depotChests[depotId] = bagReward; return bagReward; } DepotLocker* Player::getRewardChest(uint16_t itemId) { auto it = depotLockerMap.find(REWARD_CHEST_DEPOTID); if (it != depotLockerMap.end()) { it->second->setID(itemId); return it->second; } DepotLocker* rewardChest = new DepotLocker(ITEM_REWARD_CHEST); rewardChest->setID(itemId); rewardChest->setDepotId(REWARD_CHEST_DEPOTID); rewardChest->setMaxLockerItems(1); rewardChest->internalAddThing(getRewardBag(REWARD_CHEST_DEPOTID, true)); depotLockerMap[REWARD_CHEST_DEPOTID] = rewardChest; return rewardChest; } Em player.cpp, container.cpp, inbox.cpp: Mude: if (!item->isPickupable()) { Por: if (item->getID() != 21518 && !item->isPickupable()) { src/actions.cpp: Mude: //depot container if (DepotLocker* depot = container->getDepotLocker()) { DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId()); myDepotLocker->setParent(depot->getParent()->getTile()); openContainer = myDepotLocker; player->setLastDepotId(depot->getDepotId()); } else { openContainer = container; } Por: //reward chest and depot container if (item->getActionId() == ITEM_REWARD_CHEST || item->getID() == ITEM_REWARD_CHEST) { DepotLocker* myRewardChest = player->getRewardChest(item->getID()); myRewardChest->setParent(item->getTile()); openContainer = myRewardChest; player->setLastDepotId(REWARD_CHEST_DEPOTID); } else if (DepotLocker* depot = container->getDepotLocker()) { DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId()); myDepotLocker->setParent(depot->getParent()->getTile()); openContainer = myDepotLocker; player->setLastDepotId(depot->getDepotId()); } else { openContainer = container; } src/game.cpp: Em cima de... if (!item->isPushable() || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { ...Adicione: if (item->getID() == ITEM_REWARD_BAG || item->getActionId() == ITEM_REWARD_CHEST) { player->sendCancelMessage(RETURNVALUE_NOTMOVEABLE); return; } src/monsters.h: Embaixo de... int32_t subType; int32_t actionId; std::string text; ...Adicione: bool uniquedrop; Embaixo de... actionId = -1; ...Adicione: uniquedrop = false; Embaixo de... bool hiddenHealth; ...Adicione: bool rewardChest; src/monsters.cpp: Embaixo de... healthMax = 100; ...Adicione: rewardChest = false; Embaixo de... } else if (strcasecmp(attrName, "hidehealth") == 0) { mType->hiddenHealth = attr.as_bool(); ...Adicione: } else if (strcasecmp(attrName, "rewardchest") == 0) { mType->rewardChest = attr.as_bool(); Em cima de... if ((attr = node.attribute("actionId"))) { ...Adicione: if ((attr = node.attribute("uniquedrop"))) { lootBlock.uniquedrop = attr.as_bool(); } src/iologindata.cpp: Embaixo de... //load depot items ...Adicione: player->getRewardChest(ITEM_REWARD_CHEST); Mude: if (pid >= 0 && pid < 100) { DepotChest* depotChest = player->getDepotChest(pid, true); if (depotChest) { depotChest->internalAddThing(item); } Por: if (pid >= 0 && pid < 100) { if (pid == REWARD_CHEST_DEPOTID) { DepotChest* depotChest = player->getRewardBag(pid, true); if (depotChest) { depotChest->internalAddThing(item); } } else { DepotChest* depotChest = player->getDepotChest(pid, true); if (depotChest) { depotChest->internalAddThing(item); } } src/luascript.h: Em cima de... // Combat ...Adicione: // Reward static int luaItemGetNameDescription(lua_State* L); static int luaMonsterTypeUseRewardChest(lua_State* L); src/luascript.cpp: Em cima de... // Party registerClass("Party", "", nullptr); ...Adicione: // Reward registerMethod("MonsterType", "useRewardChest", LuaScriptInterface::luaMonsterTypeUseRewardChest); registerMethod("Item", "getNameDescription", LuaScriptInterface::luaItemGetNameDescription); Em cima de... // Combat int LuaScriptInterface::luaCombatCreate(lua_State* L) ...Adicione: int LuaScriptInterface::luaItemGetNameDescription(lua_State* L) { // item:getNameDescription() const Item* item = getUserdata<const Item>(L, 1); int32_t subType; bool addArticle = true; if (item) { subType = item->getSubType(); const ItemType& it = Item::items[item->getID()]; std::ostringstream s; const std::string& name = (item ? item->getName() : it.name); if (!name.empty()) { if (it.stackable && subType > 1) { if (it.showCount) { s << subType << ' '; } s << (item ? item->getPluralName() : it.getPluralName()); } else { if (addArticle) { const std::string& article = (item ? item->getArticle() : it.article); if (!article.empty()) { s << article << ' '; } } s << name; } } else { s << "an item of type " << it.id; } pushString(L, s.str()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeUseRewardChest(lua_State* L) { // monsterType:useRewardChest() MonsterType* monsterType = getUserdata<MonsterType>(L, 1); if (monsterType) { pushBoolean(L, monsterType->rewardChest); } else { lua_pushnil(L); } return 1; } Mude: int LuaScriptInterface::luaMonsterTypeGetLoot(lua_State* L) { // monsterType:getLoot() MonsterType* monsterType = getUserdata<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } static const std::function<void(const std::vector<LootBlock>&)> parseLoot = [&](const std::vector<LootBlock>& lootList) { lua_createtable(L, lootList.size(), 0); int index = 0; for (const auto& lootBlock : lootList) { lua_createtable(L, 0, 7); setField(L, "itemId", lootBlock.id); setField(L, "chance", lootBlock.chance); setField(L, "subType", lootBlock.subType); setField(L, "maxCount", lootBlock.countmax); setField(L, "actionId", lootBlock.actionId); setField(L, "text", lootBlock.text); parseLoot(lootBlock.childLoot); lua_setfield(L, -2, "childLoot"); lua_rawseti(L, -2, ++index); } }; parseLoot(monsterType->lootItems); return 1; } Por: int LuaScriptInterface::luaMonsterTypeGetLoot(lua_State* L) { // monsterType:getLoot() MonsterType* monsterType = getUserdata<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } static const std::function<void(const std::vector<LootBlock>&)> parseLoot = [&](const std::vector<LootBlock>& lootList) { lua_createtable(L, lootList.size(), 0); int index = 0; for (const auto& lootBlock : lootList) { lua_createtable(L, 0, 8); setField(L, "itemId", lootBlock.id); setField(L, "chance", lootBlock.chance); setField(L, "subType", lootBlock.subType); setField(L, "maxCount", lootBlock.countmax); setField(L, "actionId", lootBlock.actionId); setField(L, "text", lootBlock.text); pushBoolean(L, lootBlock.uniquedrop); lua_setfield(L, -2, "uniquedrop"); parseLoot(lootBlock.childLoot); lua_setfield(L, -2, "childLoot"); lua_rawseti(L, -2, ++index); } }; parseLoot(monsterType->lootItems); return 1; } Pronto, a parte de C++ acabou agora o resto: Adicione @ data/items/items/xml <item id="21518" article="a" name="reward container"> <attribute key="weight" value="1800" /> <attribute key="containersize" value="100" /> <attribute key="slotType" value="backpack" /> </item> <item id="21584" article="a" name="reward chest"> <attribute key="type" value="depot" /> <attribute key="containerSize" value="1" /> <attribute key="description" value="This chest contains your rewards earned in battles." /> </item> Adicione @ data/creaturescripts/creaturescripts.xml <event type="kill" name="RewardLoot" script="rewardloot.lua"/> Registre @ data/creaturescripts/scripts/login.lua player:registerEvent("RewardLoot") Crie data/creaturescripts/scripts/rewardloot.lua: function sort_descending(t) local tmp = {} for k, v in pairs(t) do table.insert(tmp, {k, v}) end table.sort(tmp, function(a, b) return a[2] > b[2] end) return tmp end function table.find(t, v) for i,x in pairs(t) do if x == v then return true end end end function Player:addItemRewardBag(itemid, count) local rewardbag = self:getDepotChest(99) return rewardbag:addItem(itemid, count) end function MonsterType:getBossReward(chance, unique) local ret = {} local function randomItem(lootBlock, chance) local randvalue = math.random(0, 100000) / (getConfigInfo("rateLoot") * chance) if randvalue < lootBlock.chance then if (ItemType(lootBlock.itemId):isStackable()) then return (randvalue%lootBlock.maxCount) + 1 else return 1 end end end local lootBlockList = self:getLoot() for _, loot in pairs(lootBlockList) do local rd = randomItem(loot, chance) if rd then if loot.uniquedrop then if unique then table.insert(ret, {loot, rd}) end else table.insert(ret, {loot, rd}) end end end return ret end BossLoot = {} BossUids = {} function BossLoot:new(boss) if not table.find(BossUids, boss:getId()) then table.insert(BossUids, boss:getId()) return setmetatable({creature=boss}, {__index = BossLoot}) end end function BossLoot:updateDamage() if self.creature then local tmp = {} local totaldmg = 0 for killer, damage in pairs(self.creature:getDamageMap()) do totaldmg = totaldmg+damage.total tmp[killer] = damage.total end self.players = sort_descending(tmp) self.totaldmg = totaldmg else error("Creature not found.") end end function BossLoot:setRewards() if self.totaldmg and self.creature then if getConfigInfo("rateLoot") > 0 then local mt = MonsterType(self.creature:getName()) for i, playertab in ipairs(self.players) do local loot if i == 1 then loot = mt:getBossReward(playertab[2] / self.totaldmg, true) else loot = mt:getBossReward(playertab[2] / self.totaldmg, false) end table.insert(self.players[i], loot) end end else error("Error") end end function BossLoot:addRewards() if self.players and self.players[1] and self.players[1][3] then for i, playertab in ipairs(self.players) do local player = Player(playertab[1]) if player then local str = "The following items are available in your reward chest: " for i, lootTable in ipairs(playertab[3]) do local item = player:addItemRewardBag(lootTable[1].itemId, math.ceil(lootTable[2])) if item then str = str .. item:getNameDescription() .. ", " end end str = str:sub(1, #str-2) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, str) end end else error("Error") end end function onKill(creature, target) if (Monster(target) ~= nil) then local mt = MonsterType(target:getName()) if mt:useRewardChest() then local loot = BossLoot:new(target) if loot then local corpse = Item(doCreateItem(MonsterType(target:getName()):getCorpseId(), 1, target:getPosition())) corpse:decay() target:setDropLoot(false) loot:updateDamage() loot:setRewards() loot:addRewards() corpse:setAttribute('aid', 21584) end end end end COMO USAR !! Simplesmente adicione essa flag no monstro: <flag rewardchest="1" /> Você tambem pode fazer um drop ser unique, assim somente a pessoa que fez a maior parte do dano vai pegar esse item. <item id="5903" chance="100000" uniquedrop="1" /><!-- ferumbras' hat -->1 ponto -
Evento de Scripting? Criamos essa pesquisa para saber quantas pessoas estão dispostas a participar do concurso e de que forma isso possa ser divertido e dinâmico para todos. Pretendemos criar um evento que proporcione tempo razoável de participação e aprendizado dentro de um conceito que permita a participação de todos. Por favor, deixe sua sugestão e o seu voto para que possamos criar algo bem legal para você.1 ponto
-
Mudanças Dezembro
Yan Liima reagiu a Administrador por um tópico no fórum
Hail xTibianos trago um pacote de novidades bem interessantes para a comunidade, e tenho expectativas de que todos gostarão. A um tempo atrás iniciamos a mudança das PIPS do fórum, que são essas plaquinhas que estão em baixo da sua imagem e, hoje, estamos lançando as PIPS oficiais do xTibia. As placas atuais foram produzidas por mim e estou de ouvidos abertos à criticas e mudanças são possíveis. Confiram também outras novidades que você pode não estar por dentro: • • • • Portal Novo Após as reclamações constantes do Portal antigo, em relação ao uso do xTibia nos aparelhos celulares, decidimos reformular o portal e manter um padrão agradável e prático. Esperamos, todos nós, que tenham gostado do visual. • Menu Rápido Seguindo o mesmo conceito do Menu Alternativo, restirado à uns meses atrás devido a problemas. O Menu Rápido foi adicionado ao portal para facilitar a busca pelo conteúdo do fórum. Não há previsões para adição de novas seções no Menu. • Like System O nosso querido Like System foi desativado e agora compartilhamos todos de um lindo botão (que todos conhecemos): Bom, pelo menos agora o ranking reputação faz sentido, . Staff Novas PIPS Veja abaixo todas as novas placas para membros. (Ou, clique aqui) Elas mudam conforme a sua quantidade de posts, sendo: 0; 50; 100; 250; 500; 700; 1000; 1500; 2000; 3000 e 5000. •1 ponto -
Algumas Sprites criadas pela equipe Pokéxchama. 5 Geração. v0.1= Clique Aqui Atualizações: v0.2 = Clique Aqui obs: Adicionado Tornadus. v0.3= Em breve.1 ponto
-
Comando !cp teleportar após 10 segundos. Como fazer?
arkanctrus reagiu a Eskylo por uma questão
bem observado, fiz algumas alterações e corrigi isso local teleport_time, exhaust = 10, 20 --Respectivamente, tempo para teleportar e cooldown. function channel_teleport(cid, time) if not isPlayer(cid) then return true elseif getCreatureCondition(cid, CONDITION_INFIGHT) then doPlayerSendCancel(cid, "You can't teleport while in battle.") setPlayerStorageValue(cid, 2911, -1) return true elseif time <= 0 then doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid))) setPlayerStorageValue(cid, 2910, os.time() + exhaust * 60) return true end doPlayerSendTextMessage(cid, 27, time) addEvent(channel_teleport, 1000, cid, time - 1) end function onSay(cid) if getPlayerStorageValue(cid, 2910) > os.time() then doPlayerSendCancel(cid, "This command is still in cooldown. Wait "..(getPlayerStorageValue(cid, 2910) - os.time()).." seconds to use it again.") return true elseif getCreatureCondition(cid, CONDITION_INFIGHT) then doPlayerSendCancel(cid, "You can't use this command in battle.") return true end if getPlayerStorageValue(cid, 2911) > os.time() then return false else setPlayerStorageValue(cid, 2911, os.time()+teleport_time) end channel_teleport(cid, teleport_time) return true end1 ponto -
Comando !cp teleportar após 10 segundos. Como fazer?
arkanctrus reagiu a RodriigoRobson por uma questão
Voce ta querendo impedir que os Players abusam do Comando? - Isso ae nao vai adiantar e so esperar um "x" Tempo o player pode estar em qualquer lugar e vai sempre abusar do Comando - Oque voce deveria fazer e Colocar: Tempo + Limite de Uso do Comando - A mais pq colocar um Limite? - Para nao abusarem do Comando e caso Atinge o Limite de Uso Voce pode puxar o Player ou Colocar um Sistema (Globalevent) de Zerar o Limite 1x por Dia - Eu odeio esse Comando pq muitas Pessoas Aproveita disso e para Nao abusarem eu Fiz isso - Ta ae o Script do Comando:1 ponto -
1 ponto
-
Vanaheim global open source
sandrodiegoadao reagiu a Bruno por um tópico no fórum
Amigo, não tem necessidade, este post está com a ultima versão do tfs, na qual este bug já está corrido, veja você mesmo: https://github.com/brunominervino/forgottenserver/blob/master/src/player.cpp#L322 Att.1 ponto
