Histórico de Edições
Please note that revisions older than 15 days are pruned and will no longer show here
Não há histórico de edição para mostrar, ou este comentário foi editado por um moderador.
-
Quem Está Navegando 0 membros estão online
Nenhum usuário registrado visualizando esta página.
-
Conteúdo Similar
-
Por Johncore
Otg Server Global
Somos o Otg Server, projeto baseado no TFS 1.3 e OTX3.2,
Se trata de um servidor baseado no GLOBAL MAP RL.
Aqui você encontrará baixo uso de recursos como CPU / memoria, prezamos muito por estabilidade e atualizações constantes.
Agradecemos primeiramente ao Tibiaking pela oportunidade nos concedida,
somos parceiros oficiais do Tibiaking.com melhor Forum Brasileiro!
Especificações :
- Global Map FULL RL
- Maioria das Quests com Quest Log 100%
- Anti Rollback + Auto Restart 100%
- Source Otimizada (baixo consumo de CPU e memoria)
- Sem Bug de Clonar dinheiro (Npcs Refeitos
- Exercise Training 100%
- Raids 100%
- Monstros 100%
Imagens :
THAIS TEMPLE
FALCONS
NEW ASURAS
WZ 4,5,6
Downloads :
PROJETO OFFICIAL GITHUB:
https://github.com/otg-br/global-11x
TUTORIAL PARA COMPILAÇÃO:
https://github.com/otg-br/global-11x/wiki
EXE compilado WIN11 64bits:
https://github.com/otg-br/global-11x/blob/main/Executavel compilado win11 64bits.rar
GRUPO WHATSAPP OTG SERVER:
https://chat.whatsapp.com/EWV3dVvS6nt1em7q23FGu7
Créditos :
The Forgotten Server
Otland
Mark Samman
Mattyx Otx
Erick Nunes
Johncore
Otg Server contribuidores
OTX contribuidores
Otservbr
Leu
Marcomoa
Marson Schneider
Leandro Baldissera
-
Por L3K0T
Bom, como todos sabem, existe o shop.lua em servidores 0.4 para receber itens. Muitos deles têm loops infinitos ou fazem uma varredura completa no banco de dados, o que pode deixá-los instáveis. Isso ocorre principalmente quando o script não verifica adequadamente se há itens para processar ou se o banco de dados está sobrecarregado com consultas desnecessárias.
No entanto, com algumas melhorias, podemos otimizar esse processo, garantindo que o servidor se mantenha estável e eficiente. No nosso exemplo, aplicamos algumas mudanças importantes:
Checagem eficiente de itens pendentes: A consulta ao banco de dados foi otimizada para verificar se existem realmente itens pendentes para o jogador. Se não houver itens, o script termina sua execução rapidamente, evitando sobrecarga.
Evitar loops infinitos: O loop foi ajustado para garantir que, se não houver mais itens para processar, o script saia sem continuar verificando o banco de dados, prevenindo loops desnecessários.
Logs: Foi adicionado um sistema de logs, onde cada transação bem sucedida do jogador é registrada com data e hora, além de informações sobre o jogador e os itens recebidos.
Execução controlada com intervalos: Ao invés de fazer consultas contínuas ao banco de dados, o script executa checagens de tempos em tempos, configuráveis pelo parâmetro SQL_interval. Isso distribui as verificações ao longo do tempo e evita que o servidor fique sobrecarregado com solicitações simultâneas.
Segue o scripts:
data/globalevents/scripts/shop.lua
function getCurrentDateTime() local currentDateTime = os.date("%Y-%m-%d %H:%M:%S") return currentDateTime end function createDirectoryIfNotExists(dir) local command = "mkdir -p " .. dir os.execute(command) end function saveLog(message) local logFilePath = "data/logs/shop/shop.txt" local logDir = "data/logs/shop/" createDirectoryIfNotExists(logDir) local currentDateTime = getCurrentDateTime() local logMessage = string.format("[%s] %s\n", currentDateTime, message) local file = io.open(logFilePath, "a") if file then file:write(logMessage) file:close() else print("Erro ao tentar escrever no arquivo de log.") end end SHOP_MSG_TYPE = 19 SQL_interval = 5 function onThink(interval, lastExecution) local result_plr = db.getResult("SELECT * FROM z_ots_comunication WHERE `type` = 'login';") if result_plr:getID() == -1 then return true end local hasMoreItems = false while true do local id = tonumber(result_plr:getDataInt("id")) local cid = getCreatureByName(tostring(result_plr:getDataString("name"))) if isPlayer(cid) then hasMoreItems = true local itemtogive_id = tonumber(result_plr:getDataInt("param1")) local itemtogive_count = tonumber(result_plr:getDataInt("param2")) local add_item_name = tostring(result_plr:getDataString("param6")) local received_item = 0 local full_weight = 0 if isItemRune(itemtogive_id) then full_weight = getItemWeightById(itemtogive_id, 1) else full_weight = getItemWeightById(itemtogive_id, itemtogive_count) end local free_cap = getPlayerFreeCap(cid) if full_weight <= free_cap then local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) received_item = doPlayerAddItemEx(cid, new_item) if received_item == RETURNVALUE_NOERROR then doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você recebeu >> %s << da loja.", add_item_name)) doPlayerSave(cid) db.executeQuery("DELETE FROM `z_ots_comunication` WHERE `id` = " .. id .. ";") db.executeQuery("UPDATE `z_shop_history` SET `trans_state`='realized', `trans_real`=" .. os.time() .. " WHERE id = " .. id .. ";") saveLog(string.format("[%s] %s (ID: %d), Você recebeu >> %s << da loja.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name)) end else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você não tem capacidade suficiente para >> %s <<. Necessário: %.2f oz. Disponível: %.2f oz.", add_item_name, full_weight, free_cap)) saveLog(string.format("[%s] %s (ID: %d), Tentou comprar >> %s <<, mas não tinha capacidade suficiente. Necessário: %.2f oz. Disponível: %.2f oz.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name, full_weight, free_cap)) end end if not result_plr:next() then break end end result_plr:free() if not hasMoreItems then return false end return true end
data/globalevents/globalevents.xml
<globalevent name="shop" interval="30000" script="shop.lua"/>
*Testado em Myaac
*Testado em OTX2 8.60
*Testado em Ubuntu 20.04
*Não precisa criar pasta, ele mesmo cria.
Com essas melhorias, a performance do servidor foi significativamente melhorada, garantindo que o sistema de loja funcione de forma mais estável e eficiente, sem sobrecarregar o banco de dados ou causar lags. Agora, a transação de itens na loja ocorre de forma mais controlada e com menos chance de erros ou travamentos. by @L3K0T
-
Por L3K0T
Como diz o título? Você pode gerar as funções do seu TFS em um arquivo de texto. Para fazer isso, basta ir em uma das bibliotecas (LIB) e adicionar o seguinte código no final.
-- Função para obter todas as funções disponíveis no ambiente Lua
function getLuaFunctions()
local function iterateTable(tbl, prefix)
local str = ""
for key, value in pairs(tbl) do
if type(value) == 'function' then
str = str .. prefix .. key .. ','
elseif type(value) == 'table' then
str = str .. iterateTable(value, prefix .. key .. '.')
end
end
return str
end
local str = iterateTable(_G, "")
return string.explode(str, ',')
end
-- Obtém todas as funções disponíveis
local functionsList = getLuaFunctions()
-- Ordena a lista de funções
table.sort(functionsList)
-- Cria uma string de data no formato 'YYYY-MM-DD'
local currentDate = os.date('%Y-%m-%d')
-- Salva a lista de funções em um arquivo de texto com a data atual
local fileName = 'funcoes_do_seu_servidor_' .. currentDate .. '.txt'
local file = io.open(fileName, 'w')
for i, funcName in ipairs(functionsList) do
if funcName ~= "" then
file:write((i - 1) .. ' - ' .. funcName .. '\n')
end
end
file:close()
-- Criado por L3K0T
Depois, é só iniciar o seu servidor e assim todas as funções do seu servidor vão aparecer no arquivo TXT com a data de criação.
"Isso é útil para resolver problemas de scripts e trabalhar de forma mais eficiente, manipulando as funções."
-
Por FeeTads
SALVE rapaziada do TK, esses dias vim pensando em novos scripts pro meu OT, e em um deles eu precisava que determinada area não contasse frag pro player que matasse outros, PORÉM eu precisava que os players que morressem nessa area ainda assim tivessem as penalidades da sua morte, procurei por ai, achei alguns scripts que apenas tiravam o SKULL e não realmente o FRAG do player.
**script atualizado 22/10/2023** - melhorado e otimizado, levei o script pra puxar as infos por .lua / creatureScripts
vou disponibilizar o code aqui, e o que fazer pra determinada area não contar frag.
SOURCE OTX 2 / TFS 0.x, Funciona em TFS 1.x mudando as tags e ajeitando as sintaxes.
vá em creatureevent.cpp
procure por:
else if(type == "preparedeath") _type = CREATURE_EVENT_PREPAREDEATH;
Adiciona abaixo:
else if(type == "nocountfrag") _type = CREATURE_EVENT_NOCOUNTFRAG;
procure por:
case CREATURE_EVENT_PREPAREDEATH: return "onPrepareDeath";
Adicione abaixo:
case CREATURE_EVENT_NOCOUNTFRAG: return "noCountFragArea";
procure por:
case CREATURE_EVENT_PREPAREDEATH: return "cid, deathList";
Adicione abaixo:
case CREATURE_EVENT_NOCOUNTFRAG: return "cid, target";
agora no mesmo arquivo, vá até o final do arquivo e adicione essa função:
uint32_t CreatureEvent::executeNoCountFragArea(Creature* creature, Creature* target) { //noCountFragArea(cid, target) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::ostringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; scriptstream << "local target = " << env->addThing(target) << 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::ostringstream desc; desc << creature->getName(); 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)); lua_pushnumber(L, env->addThing(target)); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::noCountFragArea] Call stack overflow." << std::endl; return 0; } }
agora vá em creatureevent.h
procure por:
CREATURE_EVENT_PREPAREDEATH
adicione abaixo:
CREATURE_EVENT_NOCOUNTFRAG
procure por:
uint32_t executePrepareDeath(Creature* creature, DeathList deathList);
Adicione abaixo:
uint32_t executeNoCountFragArea(Creature* creature, Creature* target);
agora vá em player.cpp
procure por:
bool Player::onKilledCreature(Creature* target, DeathEntry& entry)
abaixo de:
War_t enemy; if(targetPlayer->getEnemy(this, enemy)) { if(entry.isLast()) IOGuild::getInstance()->updateWar(enemy); entry.setWar(enemy); }
Adicione o seguinte código:
if (targetPlayer){ CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_NOCOUNTFRAG); for (const auto &event : killEvents) { if (!event->executeNoCountFragArea(this, target)) { return true; } } }
//
Feito isso, tudo completo na sua source, agora é necessário adicionar o creaturescript dentro do servidor
vá até creaturescripts/scripts
crie um arquivo chamado, "noCountFragInArea.lua"
e dentro dele cole o código:
--[[ script feito por feetads / TibiaKing ]]-- --[[ discord: feetads / FeeTads#0246 ]]-- -- Add positions here for which you do not want to count frags local areas = { [1] = {from = {x = 91, y = 122, z = 7}, to = {x = 98, y = 127, z = 7}}, -- from = area superior esquerda / to = area inferior direita (formando um quadrado) } local onlyKillerInArea = false -- only killer need to be in area? function noCountFragArea(cid, target) if not isCreature(cid) or not isCreature(target) then return true end local posKiller = getPlayerPosition(cid) local posTarget = getPlayerPosition(target) for i = 1, #areas do local area = areas[i] if isInArea(posKiller, area.from, area.to) then if onlyKillerInArea then return false elseif isInArea(posTarget, area.from, area.to) then return false end end end return true end
agora em creaturescripts.xml
<event type="nocountfrag" name="fragarea" event="script" value="noCountFragInArea.lua"/>
agora em creaturescripts/scripts/login.lua
procure por OU semelhante a esse:
registerCreatureEvent(cid, "AdvanceSave")
e abaixo adicione:
registerCreatureEvent(cid, "fragarea")
//
Agora tudo certo, quando quiser adiciona uma area que não pega frag, vá até o script e apenas coloque a area, igual o demonstrado no script
Exemplo:
local areas = { [1] = {from = {x = 91, y = 122, z = 7}, to = {x = 98, y = 127, z = 7}}, [2] = {from = {x = 1000, y = 1000, z = 7}, to = {x = 1100, y = 1100, z = 7}}, }
assim somente colocando a area no script e abrindo o server ou dando /reload, já funcionará a area como não pegar frag.
Esse sistema pode ser bom pra areas de pvp ativo, onde você ainda quer que o player que morrer perca os atributos, como se fosse uma morte normal, porém não conta frag pra quem matar.
Bom pra sistemas tipo castle 48h (guild war), onde há diversas mortes e risco de pegar red, atrapalhando a war.
Façam bom proveito dos scripts, e deixem os créditos no script rsrs
**Eu fiz as alterações e o simples código por isso vim disponibilizar, créditos meus**
-
Por Diego767
Boa tarde, estou com o problema no meu Prey System, onde todos os chares sempre ficam com a mesma Prey independente do monstro.
Alguem sabe o que pode ter de errado?
Prey = {
Credits = "System remake: Westwol ~ Packet logic: Cjaker ~ Formulas: slavidodo",
Version = "4.0",
LastUpdate = "07/07/19",
}
CONST_PREY_SLOT_FIRST = 0
CONST_PREY_SLOT_SECOND = 1
CONST_PREY_SLOT_THIRD = 2
CONST_MONSTER_TIER_BRONZE = 0
CONST_MONSTER_TIER_SILVER = 1
CONST_MONSTER_TIER_GOLD = 2
CONST_MONSTER_TIER_GOLD = 3
CONST_MONSTER_TIER_PLATINUM = 4
CONST_BONUS_DAMAGE_BOOST = 0
CONST_BONUS_DAMAGE_REDUCTION = 1
CONST_BONUS_XP_BONUS = 2
CONST_BONUS_IMPROVED_LOOT = 3
Prey.Config = {
ListRerollPrice = 2000
}
Prey.S_Packets = {
ShowDialog = 0xED,
PreyRerollPrice = 0xE9,
PreyData = 0xE8,
PreyTimeLeft = 0xE7
}
Prey.StateTypes = {
LOCKED = 0,
INACTIVE = 1,
ACTIVE = 2,
SELECTION = 3,
SELECTION_CHANGE_MONSTER = 4
}
Prey.UnlockTypes = {
PREMIUM_OR_STORE = 0,
STORE = 1,
NONE = 2
}
Prey.Actions = {
NEW_LIST = 0,
NEW_BONUS = 1,
SELECT = 2,
}
Prey.C_Packets = {
RequestData = 0xED,
PreyAction = 0xEB
}
Prey.Bonuses = {
[CONST_BONUS_DAMAGE_BOOST] = {step = 2, min = 7, max = 25},
[CONST_BONUS_DAMAGE_REDUCTION] = {step = 2, min = 12, max = 30},
[CONST_BONUS_XP_BONUS] = {step = 3, min = 13, max = 40},
[CONST_BONUS_IMPROVED_LOOT] = {step = 3, min = 13, max = 40}
}
Prey.MonsterList = {
[CONST_MONSTER_TIER_BRONZE] = {
"Rotworm", "Carrion Worm", "Skeleton", "Ghoul", "Cyclops", "Cyclops Drone", "Cyclops Smith", "Dark Magician",
"Beholder", "Dragon", "Dragon Hatchling", "Dwarf", "Dwarf Guard", "Dwarf Geomancer", "Dwarf Soldier", "Earth Elemental",
"Fire Elemental", "Gargoyle", "Merlkin", "Minotaur", "Minotaur Guard", "Minotaur Mage", "Minotaur Archer", "Nomad",
"Amazon", "Hunter", "Orc", "Orc Berserker", "Orc Leader", "Orc Shaman", "Orc Spearman", "Orc Warlord", "Panda",
"Rotworm Queen", "Tarantula", "Scarab", "Skeleton Warrior", "Smuggler"
},
[CONST_MONSTER_TIER_SILVER] = {
"Pirate Buccaneer", "Pirate Ghost", "Pirate Marauder", "Pirate Skeleton", "Dragon Lord Hatchling", "Frost Dragon Hatchling",
"Behemoth", "Faun", "Dark Faun", "Dragon Lord", "Frost Dragon", "Hydra", "Hero", "Bullwark", "Giant Spider", "Crystal Spider",
"Deepling Brawler", "Deepling Elite", "Deepling Guard", "Deepling Master Librarian", "Deepling Tyrant", "Deepling Warrior",
"Wyrm", "Elder Wyrm", "Fleshslicer", "Frost Giant", "Ghastly Dragon", "Ice Golem", "Infernalist", "Warlock", "Lich",
"Lizard Chosen", "Lizard Dragon Priest", "Lizard High Guard", "Lizard Legionnaire", "Lizard Zaogun", "Massive Energy Elemental",
"Massive Fire Elemental", "Massive Water Elemental", "Minotaur Amazon", "Execowtioner", "Minotaur Hunter", "Mooh'Tah Warrior",
"Mutated Bat", "Mutated Human", "Necromancer", "Nightmare", "Nightmare Scion", "Ogre Brute", "Ogre Savage", "Ogre Shaman",
"Orclops Doomhauler", "Orclops Ravager", "Quara Constrictor", "Quara Constrictor Scout", "Quara Hydromancer", "Quara Mantassin",
"Quara Pincher", "Quara Predator", "Sea Serpent", "Shaper Matriarch", "Silencer", "Spitter", "Worker Golem", "Werewolf",
"Hellspawn", "Shadow Tentacle", "Vampire Bride", "Dragonling", "Shock Head", "Frazzlemaw",
},
[CONST_MONSTER_TIER_GOLD] = {
"Plaguesmith", "Demon", "Crystal Spider", "Defiler", "Destroyer", "Diamond Servant", "Draken Elite",
"Draken Spellweaver", "Draken Warmaster", "Draken Abomination", "Feversleep", "Terrorsleep", "Draptor",
"Grim Reaper", "Guzzlemaw", "Hellfire Fighter", "Hand of Cursed Fate", "Hellhound", "Juggernaut",
"Sparkion", "Dark Torturer", "Undead Dragon", "Retching Horror", "Choking Fear", "Choking Fear",
"Shiversleep", "Sight Of Surrender", "Demon Outcast", "Blightwalker", "Grimeleech", "Vexclaw", "Grimeleech",
"Dawnfire Asura", "Midnight Asura", "Frost Flower Asura", "True Dawnfire Asura", "True Frost Flower Asura",
"True Midnight Asura"
}
}
-- Communication functions
function Player.sendResource(self, resourceType, value)
local typeByte = 0
if resourceType == "bank" then
typeByte = 0x00
elseif resourceType == "inventory" then
typeByte = 0x01
elseif resourceType == "prey" then
typeByte = 0x0A
end
local msg = NetworkMessage()
msg:addByte(0xEE)
msg:addByte(typeByte)
msg:addU64(value)
msg:sendToPlayer(self)
end
function Player.sendErrorDialog(self, error)
local msg = NetworkMessage()
msg:addByte(Prey.S_Packets.ShowDialog)
msg:addByte(0x15)
msg:addString(error)
msg:sendToPlayer(self)
end
-- Core functions
function Player.setRandomBonusValue(self, slot, bonus, typeChange)
local type = self:getPreyBonusType(slot)
local min = Prey.Bonuses[type].min
local max = Prey.Bonuses[type].max
local step = Prey.Bonuses[type].step
if bonus then
if typeChange then
self:setPreyBonusValue(slot, math.random(min, max))
else
local oldValue = self:getPreyBonusValue(slot)
if (oldValue + step >= max) then
self:setPreyBonusValue(slot, max)
else
while (self:getPreyBonusValue(slot) - oldValue < step) do
self:setPreyBonusValue(slot, math.random(min, max))
end
end
end
else
self:setPreyBonusValue(slot, math.random(min, max))
end
self:setPreyBonusGrade(slot, math.floor((self:getPreyBonusValue(slot) - min) / (max - min) * 10))
if (self:getPreyBonusGrade(slot) == 10 and self:getPreyBonusValue(slot) < max) then
self:setPreyBonusGrade(slot, self:getPreyBonusGrade(slot) - 1)
end
end
function Player.getMonsterTier(self)
if self:getLevel() > 0 and self:getLevel() < 60 then
return CONST_MONSTER_TIER_BRONZE
elseif self:getLevel() >= 60 and self:getLevel() < 160 then
return CONST_MONSTER_TIER_SILVER
elseif self:getLevel() >= 160 then
return CONST_MONSTER_TIER_GOLD
end
end
function Player.createMonsterList(self)
-- Do not allow repeated monsters
local repeatedList = {}
for slot = CONST_PREY_SLOT_FIRST, CONST_PREY_SLOT_THIRD do
if (self:getPreyCurrentMonster(slot) ~= '') then
repeatedList[#repeatedList + 1] = self:getPreyCurrentMonster(slot)
end
if (self:getPreyMonsterList(slot) ~= '') then
local currentList = self:getPreyMonsterList(slot):split(";")
for i = 1, #currentList do
repeatedList[#repeatedList + 1] = currentList
end
end
end
-- Generating monsterList
local monsters = {}
while (#monsters ~= 9) do
local randomMonster = Prey.MonsterList[self:getMonsterTier()][math.random(#Prey.MonsterList[self:getMonsterTier()])]
-- Verify that monster actually exists
if MonsterType(randomMonster) and not table.contains(monsters, randomMonster) and not table.contains(repeatedList, randomMonster) then
monsters[#monsters + 1] = randomMonster
end
end
return table.concat(monsters, ";")
end
function Player.resetPreySlot(self, slot, from)
self:setPreyMonsterList(slot, self:createMonsterList())
self:setPreyState(slot, from)
return self:sendPreyData(slot)
end
function Player.getMinutesUntilFreeReroll(self, slot)
local currentTime = os.time()
if (self:getPreyNextUse(slot) <= currentTime) then
return 0
end
return math.floor((self:getPreyNextUse(slot) - currentTime) / 60)
end
function Player.getRerollPrice(self)
return (self:getLevel() / 2) * 100
end
function onRecvbyte(player, msg, byte)
if (byte == Prey.C_Packets.RequestData) then
player:sendPreyData(CONST_PREY_SLOT_FIRST)
player:sendPreyData(CONST_PREY_SLOT_SECOND)
player:sendPreyData(CONST_PREY_SLOT_THIRD)
elseif (byte == Prey.C_Packets.PreyAction) then
player:preyAction(msg)
end
end
function Player.preyAction(self, msg)
local slot = msg:getByte()
local action = msg:getByte()
if not slot then
return self:sendErrorDialog("Sorry, there was an issue, please relog-in.")
end
-- Verify whether the slot is unlocked
if (self:getPreyUnlocked(slot) ~= 1) then
return self:sendErrorDialog("Sorry, you don't have this slot unlocked yet.")
end
-- Listreroll
if (action == Prey.Actions.NEW_LIST) then
-- Verifying state
if (self:getPreyState(slot) ~= Prey.StateTypes.ACTIVE and self:getPreyState(slot) ~= Prey.StateTypes.SELECTION and self:getPreyState(slot) ~= Prey.StateTypes.SELECTION_CHANGE_MONSTER) then
return self:sendErrorDialog("This is slot is not even active.")
end
-- If free reroll is available
if (self:getMinutesUntilFreeReroll(slot) == 0) then
self:setPreyNextUse(slot, os.time() + 20 * 60 * 60)
elseif (not self:removeMoneyNpc(self:getRerollPrice())) then
return self:sendErrorDialog("You do not have enough money to perform this action.")
end
self:setPreyCurrentMonster(slot, "")
self:setPreyMonsterList(slot, self:createMonsterList())
self:setPreyState(slot, Prey.StateTypes.SELECTION_CHANGE_MONSTER)
-- Bonus reroll
elseif (action == Prey.Actions.NEW_BONUS) then
-- Verifying state
if (self:getPreyState(slot) ~= Prey.StateTypes.ACTIVE) then
return self:sendErrorDialog("This is slot is not even active.")
end
if (self:getPreyBonusRerolls() < 1) then
return self:sendErrorDialog("You don't have any bonus rerolls.")
end
-- Removing bonus rerolls
self:setPreyBonusRerolls(self:getPreyBonusRerolls() - 1)
-- Calculating new bonus
local oldType = self:getPreyBonusType(slot)
self:setPreyBonusType(slot, math.random(CONST_BONUS_DAMAGE_BOOST, CONST_BONUS_IMPROVED_LOOT))
self:setRandomBonusValue(slot, true, (oldType ~= self:getPreyBonusType(slot) and true or false))
-- Select monster from list
elseif (action == Prey.Actions.SELECT) then
local selectedMonster = msg:getByte()
local monsterList = self:getPreyMonsterList(slot):split(";")
-- Verify if the monster exists.
local monster = MonsterType(monsterList[selectedMonster + 1])
if not monster then
return self:sendPreyData(slot)
end
-- Verifying slot state
if (self:getPreyState(slot) ~= Prey.StateTypes.SELECTION and self:getPreyState(slot) ~= Prey.StateTypes.SELECTION_CHANGE_MONSTER) then
return self:sendErrorDialog("This slot can't select monsters.")
end
-- Proceeding to prey monster selection
self:selectPreyMonster(slot, monsterList[selectedMonster + 1])
end
-- Perfom slot update
return self:sendPreyData(slot)
end
function Player.selectPreyMonster(self, slot, monster)
-- Verify if the monster exists.
local monster = MonsterType(monster)
if not monster then
return self:sendPreyData(slot)
end
local msg = NetworkMessage()
-- Only first/expired selection list gets new prey bonus
if (self:getPreyState(slot) == Prey.StateTypes.SELECTION) then
-- Generating random prey type
self:setPreyBonusType(slot, math.random(CONST_BONUS_DAMAGE_BOOST, CONST_BONUS_IMPROVED_LOOT))
-- Generating random bonus stats
self:setRandomBonusValue(slot, false, false)
end
-- Setting current monster
self:setPreyCurrentMonster(slot, monster:getName())
-- Setting preySlot state
self:setPreyState(slot, Prey.StateTypes.ACTIVE)
-- Cleaning up monsterList
self:setPreyMonsterList(slot, "")
-- Time left
self:setPreyTimeLeft(slot, 7200) -- 2 hours
end
function Player.sendPreyData(self, slot)
if not slot then
return true
end
local slotState = self:getPreyState(slot)
local msg = NetworkMessage()
msg:addByte(Prey.S_Packets.PreyData) -- packet header
msg:addByte(slot) -- slot number
msg:addByte(slotState) -- slot state
-- This slot will preserve the same bonus and % but the monster might be changed
if slotState == Prey.StateTypes.SELECTION_CHANGE_MONSTER then
-- This values have to be stored on each slot
msg:addByte(self:getPreyBonusType(slot))
msg:addU16(self:getPreyBonusValue(slot))
msg:addByte(self:getPreyBonusGrade(slot))
-- MonsterList already exists in the slot
local monsterList = self:getPreyMonsterList(slot):split(";")
msg:addByte(#monsterList)
for i = 1, #monsterList do
local monster = MonsterType(monsterList)
if monster then
msg:addString(monster:getName())
msg:addU16(monster:getOutfit().lookType or 21)
msg:addByte(monster:getOutfit().lookHead or 0x00)
msg:addByte(monster:getOutfit().lookBody or 0x00)
msg:addByte(monster:getOutfit().lookLegs or 0x00)
msg:addByte(monster:getOutfit().lookFeet or 0x00)
msg:addByte(monster:getOutfit().lookAddons or 0x00)
else
-- Reset slot as it got bugged
return self:resetPreySlot(slot, Prey.StateTypes.SELECTION_CHANGE_MONSTER)
end
end
-- This slot will have a new monsterList and a random bonus
elseif slotState == Prey.StateTypes.SELECTION then
-- If list is empty, then we will create a new one and assign it to the monsterList or timeleft = 0
local preyMonsterList = self:getPreyMonsterList(slot)
if preyMonsterList == '' then
self:setPreyMonsterList(slot, self:createMonsterList())
-- Resending this preySlot as there was a change.
return self:sendPreyData(slot)
end
local monsterList = preyMonsterList:split(";")
msg:addByte(#monsterList)
for i = 1, #monsterList do
local monster = MonsterType(monsterList)
if monster then
msg:addString(monster:getName())
msg:addU16(monster:getOutfit().lookType or 21)
msg:addByte(monster:getOutfit().lookHead or 0x00)
msg:addByte(monster:getOutfit().lookBody or 0x00)
msg:addByte(monster:getOutfit().lookLegs or 0x00)
msg:addByte(monster:getOutfit().lookFeet or 0x00)
msg:addByte(monster:getOutfit().lookAddons or 0x00)
else
-- Reset slot as it got bugged
return self:resetPreySlot(slot, Prey.StateTypes.SELECTION)
end
end
-- This slot is active and will show current monster and bonus
elseif slotState == Prey.StateTypes.ACTIVE then
-- Getting current monster
local monster = MonsterType(self:getPreyCurrentMonster(slot))
if monster then
msg:addString(monster:getName())
msg:addU16(monster:getOutfit().lookType or 21)
msg:addByte(monster:getOutfit().lookHead or 0x00)
msg:addByte(monster:getOutfit().lookBody or 0x00)
msg:addByte(monster:getOutfit().lookLegs or 0x00)
msg:addByte(monster:getOutfit().lookFeet or 0x00)
msg:addByte(monster:getOutfit().lookAddons or 0x00)
msg:addByte(self:getPreyBonusType(slot))
msg:addU16(self:getPreyBonusValue(slot))
msg:addByte(self:getPreyBonusGrade(slot))
msg:addU16(self:getPreyTimeLeft(slot))
else
-- Reset slot as it got expired or bugged.
return self:resetPreySlot(slot, Prey.StateTypes.SELECTION)
end
-- This slot is inactive and will not take any extra bytes
elseif slotState == Prey.StateTypes.INACTIVE then
elseif slotState == Prey.StateTypes.LOCKED then
msg.addByte(Prey.UnlockTypes.PREMIUM_OR_STORE) -- Store unlock method
end
-- Resources and times are always sent
msg:addU16(self:getMinutesUntilFreeReroll(slot)) -- next prey reroll here
-- Client 11.9+ compat, feature unavailable.
if self:getClient().version >= 1190 then
msg:addByte(0x00) -- preyWildCards
end
msg:addByte(0xEC)
self:sendResource("prey", self:getPreyBonusRerolls())
self:sendResource("bank", self:getBankBalance())
self:sendResource("inventory", self:getMoney())
-- List reroll price
msg:addByte(Prey.S_Packets.PreyRerollPrice)
msg:addU32(self:getRerollPrice())
-- Client 11.9+ compat, feature unavailable.
if self:getClient().version >= 1190 then
msg:addByte(0x00)
msg:addByte(0x00)
end
-- Sending message to client
msg:sendToPlayer(self)
end
-
-
Estatísticas dos Fóruns
96849
Tópicos519614
Posts