GDLib 2 #1 Posted March 16, 2008 Olá a todos, para quem não sabe, sou Nostradamus e a algum tempo, tive minha atividade cessada no projeto OpenTibia como Scripting Leader Developer, mas, não estou afim de sair de uma comunidade que me fez descobrir uma das linguagens que mais uso hoje profissionalmente, Lua. Depois de ler um post do Forger sobre motivação, resolvi dar uma última oportunidade a todos, de experimentarem o verdadeiro OpenTibia. Fiquei encarregado de criar um NPC System para substituir o do Jiddo no OpenTibia oficial, eu poderia muito bem fazer sozinho, ou dizer não a eles, mas resolvi que todos irão participar dessa façanha. Por meio desse post, irei desenvolver junto com todos vocês, o sistema, partindo de sugestões, idéias, opiniões, patchs, críticas, algorítimos, enfim, quero a sua ajuda, não me interessa se você sabe ou não Lua, eu quero a sua opinião de como deveseria ser um NPC System bom, fácil, rápido e decente. Eis aqui umas condições de como ajudar: É terminantemente proibido a rippagem de códigos de outros sem a devida autorização dos autores. As contribuições devem ser postadas com escrita correta. Não é permitido offtopics nesse post. As idéias que forem idênticas umas das outras, permanecerá os créditos do primeiro idealizador (o que postar primeiro). Sua contribuição é algo formal ao projeto, portanto, seja o mais formal possível e esteja crente que estará ajudando toda a comunidade OpenTibia. Desenvolvedores Ambiente orientado a objetos Uso incessante de tabelas para configuração Debug strackback Changelogs Tratamento de erros dinâmizados Condicionamento baseado em eventos Modulação Convenções baseadas no padrão OpenTibia (ver Guidelines Script inicial --[[ The OpenTibia NPC System 0.1 Features ratePrice multiplier Buy/Sell/Teleport/Spell modules Dynamic error threatment Todo Debugger Strackback (configurable tables and advanced error reporting) Otmization of all the functions Rewrite doPlayerAddMoney (that one from Piterb sucks) onThink and onQueue events onTalk event with dynamic uses of talkstates and so on sub-talkstates will be sub-arrays of the main talkstate refered to it messages will be handled into arrays with the input and output of the NPC (message and answer subarrays) Function to list buying/selling items, teleport places and spells Study the possibility of the usage of a new "msgContains" function with tolerance (if a player write the "key" wrong, it will return the correct input) Promote and quest module Extra module to get the statitics (how much items were sold, bought, etc) Optmize Buy/Sell functions to accept containers with items Study the possibility to divide the class "NPC" into modules or events Notes Since this script uses object orientation with a default class, there isn't reasons to make conditions considering if there is or not a value, since it will always be called when executing this script. The array "NPC" is a global array that will handle with all NPC scripts and with all the functions of that class. --]] NPC = { ratePrice = 1, -- This arrays are used only if not declared in the script, it will be always global values (access by the global table [_G]) BUY_LIST = { ["item_name"] = {id = , price = , count = } }, SELL_LIST = { ["item_name"] = {id = , price = , count = } }, TELEPORT_PLACES = { ["name"] = {pos = {x = , y = , z = }, price = } }, SPELL_LIST = { ["name"] = {words = , price = , level =, maglevel = } }, -- In the future, it will be used as a debugger strackback ERRORS = { maxCount = "Item count should be less then 100.", noCount = "Item count should be especified.", noMoney = "The player does not have enought money.", noItem = "Desired item not found in the buying list.", noPlayerItem = "The player does not have the item to sell it.", noPlace = "Desired place does not exists." } } -- NPC Class Instance function NPC:new() o = o or {} return setmetatable(o, self) self.__index = self return o end -- TODO: optmize this function function NPC.doPlayerAddMoney(cid, amount) local crystals = math.floor(amount / 10000) amount = amount - crystals * 10000 local platinum = math.floor(amount / 100) amount = amount - platinum * 100 local gold, ret = amount, 0 if (crystals > 0) then ret = doPlayerAddItem(cid, ITEM_CRYSTAL_COIN, crystals) if (ret ~= LUA_NO_ERROR) then return LUA_ERROR end end if (platinum > 0) then ret = doPlayerAddItem(cid, ITEM_PLATINUM_COIN, platinum) if (ret ~= LUA_NO_ERROR) then return LUA_ERROR end end if (gold > 0) then ret = doPlayerAddItem(cid, ITEM_GOLD_COIN, gold) if (ret ~= LUA_NO_ERROR) then return LUA_ERROR end end return LUA_NO_ERROR end function NPC:Buy(cid, itemName, count, array) -- Maybe should be moved into the main scope in the future if (array ~= nil) then item = self.BUY_LIST[itemName] else item = array[itemName] end local totalCount, totalPrice = item.count + count, (item.price * count) * self.ratePrice if (item ~= nil) then if (doPlayerRemoveMoney(cid, totalPrice) == TRUE) then if (item.count ~= nil) then if (totalCount <= 100) then -- TODO: Support to charges and counts separately doPlayerAddItem(cid, item.id, totalCount) doPlayerRemoveMoney(cid, totalPrice) return TRUE else return self.ERRORS.maxCount end else return self.ERRORS.noCount end else return self.ERRORS.noMoney end else return self.ERRORS.noItem --[[ for i = array[1], #array do return i.name .. i.price .. i.count end --]] end end function NPC:Sell(cid, itemName, count, array) -- Maybe should be moved into the main scope in the future if (array ~= nil) then item = self.SELL_LIST[itemName] else item = array[itemName] end local totalCount, totalPrice = item.count + count, (item.price * count) * self.ratePrice if (item ~= nil) then if (getPlayerItemCount(cid) >= count) then if (item.count ~= nil) then if (totalCount <= 100) then doPlayerRemoveItem(cid, item.id, totalCount) self.doPlayerAddMoney(cid, totalPrice) return TRUE else return self.ERRORS.maxCount end else return self.ERRORS.noCount end else return self.ERRORS.noPlayerItem end else return self.ERRORS.noItem --[[ for i = array[1], #array do return i.name .. i.price .. i.count end --]] end end function NPC:Teleport(cid, placeName, array) if (array ~= nil) then place = self.TELEPORT_PLACES[placeName] else place = array[placeName] end if (place ~= nil) then if (doPlayerRemoveMoney(cid, place.price + self.ratePrice) == TRUE) then doTeleportThing(cid, place.pos) else return self.ERRORS.noMoney end else return self.ERRORS.noPlace end end function NPC:doPlayerLearnSpell(cid, spellName, array) if (array ~= nil) then spell = self.SPELL_LIST[spellName] else spell = array[spellName] end if (spell ~= nil) then if (getPlayerLearnedInstantSpell(cid, spellName) == TRUE) then return self.ERRORS.alreadyLearned elseif (spell.level > getPlayerLevel(cid)) then return self.ERRORS.noLevel elseif (spell.maglevel > getPlayerMagLevel(cid)) then return self.ERRORS.noMagLevel elseif (canPlayerLearnInstantSpell(cid, spellName) == FALSE) then return self.ERRORS.noVocation elseif (doPlayerRemoveMoney(cid, spell.price == TRUE) then playerLearnInstantSpell(cid, spellName) else return self.ERRORS.unknown else return self.ERRORS.noSpell end end -- Incomplete function NPC:onSay(msg, delay) if (msg ~= nil) then if (delay > 0) then -- Incomplete else selfSay(msg) end end end -- Incomplete local messages = { [talkstate] = {message = "Hi", answer = "Hello"} } function NPC:onTalk(msgArray) -- Incomplete end Modelo de sugestão Deveria-se haver um modo de se configurar o NPC de forma mais dinâmica e claro de modo que o script não tenha muitas linhas. (Nostradamus) Modelo de idéia Talktimes e eventos deveriam ser revistos, talvez haja uma maneira mais dinâmica de se fazer sub-conversas. (Nostradamus) Modelo de post Sugestão (e/ou) idéia (e/ou) patch (e/ou) crítica Pedido Gostaria de pedir à administração do OTNet para que encarregue um moderador para que o mesmo delete posts considerados inúteis ou que fogem das regras. O custeador (OTNet) será creditado na Official OpenTibia Project. Boa sorte a todos! 1 kalegrx reacted to this Share this post Link to post Share on other sites
Forger 2 #2 Posted March 16, 2008 Gostei bastante da idéia. Na verdade, estava começando a desenvolver um NPC System também. ^^ Acredito que posso te ajudar nessa tarefa como developer. Vou te enviar por PM algumas idéias que tinha, como seria, etc. Esperemos que esse projeto dê certo. Share this post Link to post Share on other sites