-
Total de itens
164 -
Registro em
-
Última visita
-
Dias Ganhos
20
Tudo que El Rusher postou
-
Aqui está o script completo para o sistema de gema que funciona para todas as vocações, usando uma única gema (ID: 2156), com uma magia que mata o jogador instantaneamente e adiciona um efeito visual multicolorido ao redor do alvo. local gemID = 2156 -- ID da Gema local instantKillSpell = true -- Habilidade que mata o alvo instantaneamente -- Função para gerar o efeito multicolorido local colors = {TEXTCOLOR_RED, TEXTCOLOR_GREEN, TEXTCOLOR_BLUE, TEXTCOLOR_YELLOW} local function applyMulticolorEffect(position) local rnd = {"´ . ,", ". ´ ,", "` . ,", ", ` ."} -- Efeito visual randômico for i = 1, #rnd do doSendAnimatedText(position, rnd[math.random(1, #rnd)], colors[math.random(1, #colors)]) end end -- Função para matar instantaneamente o jogador local function instantKill(target) if isPlayer(target) then local targetPosition = getCreaturePosition(target) doCreatureAddHealth(target, -getCreatureHealth(target)) -- Mata o jogador instantaneamente applyMulticolorEffect(targetPosition) -- Aplica o efeito multicolorido end end -- Função principal que detecta o uso da gema function onUse(cid, item, fromPosition, itemEx, toPosition) if item.itemid == gemID and isPlayer(itemEx.uid) then local target = itemEx.uid -- Verifica se o jogador pode ser atacado (não está em uma zona de proteção) if not isInPz(target) and canAttack(cid, target) then instantKill(target) doRemoveItem(item.uid, 1) -- Remove a gema após o uso doSendMagicEffect(getCreaturePosition(target), CONST_ME_EXPLOSIONHIT) -- Efeito de morte else doPlayerSendCancel(cid, "Você não pode atacar este jogador.") end else doPlayerSendCancel(cid, "Use a gema em um jogador.") end return true end Explicação do Script Identificador da Gema: O script usa a gema de ID: 2156. Quando o jogador clica nela e a usa em um outro jogador, o script é ativado. Verificação de Jogador-Alvo: O script verifica se o alvo é um jogador usando isPlayer(itemEx.uid). Também verifica se o alvo pode ser atacado, garantindo que não esteja em uma zona de proteção com isInPz(target). Morte Instantânea: Ao usar a gema, o jogador alvo tem sua vida reduzida a zero com doCreatureAddHealth(target, -getCreatureHealth(target)), matando-o instantaneamente. Efeito Multicolorido: A função applyMulticolorEffect(position) é usada para criar um efeito visual ao redor do alvo morto. São geradas animações de texto aleatórias (rnd) com cores variadas (colors), como vermelho, verde, azul e amarelo. Remoção da Gema: Após o uso, a gema é consumida com doRemoveItem(item.uid, 1). Efeito Visual na Morte: Além do efeito multicolorido, um efeito visual adicional de explosão (CONST_ME_EXPLOSIONHIT) é mostrado na posição do jogador morto. Você pode alterar os efeitos visuais e as cores ao seu gosto, modificando as tabelas rnd e colors.
-
Para evitar a criação de monstros em paredes, você precisa verificar se o local gerado aleatoriamente é um local "walkable" (ou seja, acessível para o monstro andar). O TFS tem uma função chamada isWalkable que pode ser usada para validar as posições antes de gerar um Pokémon. local config = { [17003] = { nameDz = "Bronze", chave = 2155, count = 1, areas = { -- Criei uma tabela de áreas para simplificar {fromx = 1712, fromy = 1211, fromz = 15, tox = 1966, toy = 1303, toz= 15}, {fromx = 1712, fromy = 1319, fromz = 15, tox = 1966, toy = 1411, toz= 15}, {fromx = 1712, fromy = 1427, fromz = 15, tox = 1966, toy = 1519, toz= 15}, {fromx = 1712, fromy = 1535, fromz = 15, tox = 1966, toy = 1627, toz= 15} }, teleport = { -- Criado teleporte para cada área {x = 1789, y = 1288, z = 15}, {x = 1789, y = 1396, z = 15}, {x = 1789, y = 1504, z = 15}, {x = 1789, y = 1612, z = 15} }, pokemons = {"Elder Zubat", "Elder Rattata", "Shiny Golbat", "Shiny Raticate"}, spawnCount = 64 } } -- Função para verificar se o local é walkable function isPositionWalkable(pos) local tile = Tile(pos) return tile and not tile:hasFlag(TILESTATE_PROTECTIONZONE) and not tile:getCreatureCount() > 0 end -- Função para spawnar Pokémons na área correta function spawnPokemons(area, pokemons, spawnCount) for i = 1, spawnCount do local posX = math.random(area.fromx, area.tox) local posY = math.random(area.fromy, area.toy) local posZ = area.fromz local position = {x = posX, y = posY, z = posZ} -- Verifica se a posição é "walkable" if isPositionWalkable(position) then local chosenPokemon = pokemons[math.random(1, #pokemons)] doCreateMonster(chosenPokemon, position) else i = i - 1 -- Se a posição não for válida, tenta novamente end end end function onUse(cid, item, fromPosition, itemEx, toPosition) local cfg = config[item.actionid] if not cfg then return true end if isRiderOrFlyOrSurf(cid) then doPlayerSendCancel(cid, "Saia do ride ou fly para acessar a dungeon.") return true end if getPlayerStorageValue(cid, 468703) - os.time() > 0 then doPlayerSendCancel(cid, "Aguarde "..convertTime(getPlayerStorageValue(cid, 468703) - os.time()).." para entrar na Dungeon.") return true end if getPlayerItemCount(cid, cfg.chave) >= cfg.count then for i, area in ipairs(cfg.areas) do if #getPlayersInArea(area) < 1 then -- Remove monstros existentes e inicia os novos spawns removeNpcInArea({x = area.fromx, y = area.fromy, z = area.fromz}, {x = area.tox, y = area.toy, z = area.toz}, true, false) creatureInSurvival({x = area.fromx, y = area.fromy, z = area.fromz}, {x = area.tox, y = area.toy, z = area.toz}, true, false) -- Teleporta o jogador para a área correspondente doTeleportThing(cid, cfg.teleport[i]) setPlayerStorageValue(cid, 2154600, 1) doPlayerRemoveItem(cid, cfg.chave, cfg.count) addEvent(doTeleportFinish2, 15 * 60 * 1000, cid) doSendPlayerExtendedOpcode(cid, 133, 899) -- Spawna os Pokémons spawnPokemons(area, cfg.pokemons, cfg.spawnCount) return true end end doPlayerSendCancel(cid, "Nao tem Zonas disponiveis no momento, tente mais tarde!") else doPlayerSendCancel(cid, "Você precisa de uma Bronze Dimensional Key para acessar essa Dungeon.") end return true end Validação de Local Walkable: Foi adicionada a função isPositionWalkable para garantir que o Pokémon não seja criado em locais inacessíveis (como paredes). Identificação da Sala: Cada sala tem uma área e um ponto de teleporte definidos. A função percorre as áreas (cfg.areas) e verifica se há jogadores. Se não houver, o jogador é teleportado e os Pokémons são gerados nessa área. Loop para Encontrar Área Livre: O script agora percorre todas as áreas da configuração e tenta encontrar uma disponível para o jogador entrar. Novo Teleporte e Spawn para Cada Sala: Cada área tem seu próprio teleporte, e os Pokémons são gerados na área correspondente. Esse ajuste deve resolver os problemas de criação em áreas incorretas e o erro de geração em paredes.
-
function onKill(cid, target) if isPlayer(cid) and isPlayer(target) then local targetPosition = getCreaturePosition(target) if targetPosition then doSendAnimatedText(targetPosition, "[OWNED!]", TEXTCOLOR_RED) -- Usando uma cor padrão de texto end end return true end
-
O problema está nos parâmetros passados para getPathTo, onde os parâmetros que controlam a passagem por obstáculos estão definidos como false. Isso permite que a criatura atravesse elementos bloqueantes. Além disso, podemos ajustar alguns detalhes para garantir um movimento mais seguro e fluido. Script Ajustado function pokemonWalk(summon, position, maxDistance, extra) -- Tenta encontrar um caminho para a posição desejada local path = summon:getPathTo(position, 0, maxDistance, true, false, 15) -- O terceiro parâmetro (true) indica que a criatura não pode atravessar bloqueios (como paredes). -- O quarto parâmetro (false) indica que a criatura pode atravessar outros monstros. if not path or #path == 0 then return false end setCreatureIdle(summon:getId(), #path * 500 + 10000) walkToPosition(summon:getId(), path, 1, extra) return true end function walkToPosition(cid, path, count, extra) local creature = Creature(cid) if not creature then return true end if creature:getCondition(CONDITION_MOVING) == nil then return true end local dir = path[count] creature:move(dir) count = count + 1 if count <= #path then addEvent(walkToPosition, creature:getWalkDelay(dir), cid, path, count, extra) end end function setCreatureIdle(cid, time) local creature = Creature(cid) if not creature then return true end local condition = Condition(CONDITION_MOVING) condition:setParameter(CONDITION_PARAM_TICKS, time) creature:addCondition(condition) end Mudanças Feitas: Parâmetro de Caminho: getPathTo(position, 0, maxDistance, true, false, 15) O terceiro parâmetro (true) agora assegura que a criatura não atravessará obstáculos sólidos como paredes ou itens que bloqueiam a passagem. Verificação de Caminho: Agora verificamos se path é válido e se contém direções antes de continuar com a função walkToPosition. Execução Recursiva de Movimento: A função walkToPosition só continua se houver mais direções a seguir no caminho (count <= #path). Como Funciona Agora: O Pokémon vai calcular um caminho válido para a posição alvo, evitando obstáculos como paredes. O movimento é executado passo a passo, verificando se há condições que podem interromper o movimento (como uma condição de movimento já existente). O movimento continua até que o Pokémon tenha atingido a posição final, sem atravessar paredes ou objetos intransponíveis.
-
você pode seguir essa lógica: -- Defina a área e a lista de Pokémons local area1 = { fromx = 1712, fromy = 1211, fromz = 15, tox = 1966, toy = 1303, toz = 15 } local pokemons = {"Bulbasaur", "Charmander", "Squirtle", "Torchic", "Treecko", "Mudkip", "Totodile", "Chikorita", "Cyndaquil"} local spawnCount = 64 -- Número de Pokémons a serem gerados function spawnPokemons() for i = 1, spawnCount do -- Gere coordenadas aleatórias dentro da área local posX = math.random(area1.fromx, area1.tox) local posY = math.random(area1.fromy, area1.toy) local posZ = area1.fromz -- Mantenha a mesma altura (z) local position = {x = posX, y = posY, z = posZ} -- Escolha um Pokémon aleatoriamente da lista local chosenPokemon = pokemons[math.random(1, #pokemons)] -- Crie o Pokémon na posição escolhida doCreateMonster(chosenPokemon, position) end end -- Chame a função para spawnar os Pokémons spawnPokemons() Explicação do Script Área de Spawn: A área é definida pelas coordenadas fromx, fromy, fromz (canto superior esquerdo) e tox, toy, toz (canto inferior direito). Lista de Pokémons: A lista pokemons contém os nomes dos Pokémons que podem ser gerados. Função spawnPokemons: Gera 64 posições aleatórias dentro da área especificada. Seleciona aleatoriamente um Pokémon da lista para cada posição. Usa a função doCreateMonster para criar o Pokémon na posição especificada. Execução: A função spawnPokemons é chamada para executar o spawn dos Pokémons.
-
O erro que você está enfrentando "[Warning - ProtocolGame::sendFYIBox] Trying to send an empty or too huge message" geralmente ocorre quando uma mensagem enviada para o cliente do jogo é muito longa ou está vazia. No código login.lua que você forneceu, há várias mensagens de boas-vindas e outras informações sendo enviadas ao jogador através de funções como doPlayerSendTextMessage e doCreatureSay. O problema pode ser causado por uma dessas mensagens sendo muito longa ou por estar vazia, o que resulta no erro. Aqui estão algumas sugestões para corrigir o problema: Verifique o Tamanho das Mensagens: O cliente do Tibia (8.60) tem uma limitação no tamanho das mensagens que pode exibir. Tente encurtar as mensagens ou dividir informações muito longas em várias partes. Remova ou Comente Algumas Mensagens: Tente comentar algumas das mensagens para verificar se o erro desaparece. Se funcionar, você poderá reintroduzir as mensagens de maneira mais curta e adequada. Verifique Mensagens Vazias: Certifique-se de que nenhuma das variáveis de loginmsg esteja vazia antes de serem enviadas. Exemplo de como encurtar uma das mensagens: local loginmsg = "[Bem-Vindo!] Fique ligado nas features e eventos! Mais updates em breve. Contato: bit.ly/3UaRZcB." doCreatureSay(getCreatureByName(getCreatureName(cid)), loginmsg, TALKTYPE_PRIVATE, false, cid)
-
O problema no script fornecido é que ele está configurado para garantir que o monstro seja imortal, mas a lógica pode estar se comportando de forma inadequada, especialmente em relação ao combate e ao tipo de dano que o monstro recebe. Aqui está uma revisão do script para garantir que o monstro seja imortal, mas também para assegurar que o código esteja funcionando corretamente com a versão do TFS 0.3.6 (8.60): local monsterName = "Rotworm" local immortal = true -- Define como 'true' para tornar o monstro imortal function onStatsChange(cid, attacker, type, combat, value) if isCreature(cid) and getCreatureName(cid):lower() == monsterName:lower() then if type == STATSCHANGE_HEALTHLOSS and immortal then -- Previne a perda de vida doSendAnimatedText(getCreaturePosition(cid), "Immortal", TEXTCOLOR_RED) return false -- Impede que o monstro receba dano end end return true end Adicione o script ao seu servidor e salve-o, por exemplo, como immortal_monster.lua. Registre o evento no arquivo creaturescripts.xml para que o script seja ativado: <event type="statschange" name="ImmortalMonster" script="immortal_monster.lua"/> 3. Adicione o evento ao monstro em monster.xml ou no script que o cria: <event type="statschange" name="ImmortalMonster"/>
-
local chance_percent = 100 -- Chance percentual para headshot local extra_damage_percent = 1000 -- Percentual de dano extra function onLogin(cid) registerCreatureEvent(cid, "HeadshotCritical") return true end function onStatsChange(cid, attacker, type, combat, value) if type ~= STATSCHANGE_HEALTHLOSS then return true end if isPlayer(attacker) and getPlayerStorageValue(cid, 71257) < 1 then if math.random(100) <= chance_percent then local dmg = value * (extra_damage_percent / 100) setPlayerStorageValue(cid, 71257, 1) doTargetCombatHealth(attacker, cid, combat, -dmg, -dmg, 255) setPlayerStorageValue(cid, 71257, -1) -- Verifica se o dano causado é letal if getCreatureHealth(cid) <= dmg then doCreatureSay(cid, "HEADSHOT!", TALKTYPE_MONSTER) end return false end end return true end Como o script funciona: Chance de Headshot: O código mantém a chance de "headshot" e o dano adicional, como no script original. Verificação de Morte: Antes de exibir a mensagem "HEADSHOT!", o script verifica se o dano causado é suficiente para matar o alvo (getCreatureHealth(cid) <= dmg). Se for letal, a mensagem é exibida. Mensagem de "HEADSHOT!": A mensagem só aparecerá se o jogador morrer pelo ataque que causou o dano crítico. Como usar: Adicione o script ao seu servidor. Registre o evento no creaturescripts.xml: <event type="statschange" name="HeadshotCritical" script="headshot.lua"/> Reinicie o servidor para que as alterações entrem em vigor. Com essas alterações, o efeito "HEADSHOT!" só aparecerá quando um jogador matar outro jogador com um ataque crítico. Isso evita que a mensagem apareça a cada ataque, melhorando a experiência de jogo.
-
Olá! Isso acontece porque cada depot no Tibia é vinculado a uma determinada "town" (cidade). Quando você coloca um depot em uma house, ele é tratado como um novo depot separado do depot original localizado no CP (temple) da cidade. Para resolver esse problema, você precisará garantir que ambos os depots (o da house e o do CP) estejam vinculados à mesma "town ID" e que eles compartilhem a mesma "depot ID" Verifique a Town ID: Certifique-se de que a "town ID" do depot na house seja a mesma do depot original no CP. Essa informação geralmente está definida no arquivo map ou no código da script que cria o depot. Vincule o Depot ID: Verifique o depotid do depot da house e do depot no CP. Ambos precisam compartilhar o mesmo depotid para que os itens sejam acessíveis de qualquer um dos depots. Scripts e Configurações: Em alguns casos, pode ser necessário ajustar o código do servidor para garantir que os depots compartilhem o mesmo inventário. Dependendo do código do servidor, você pode precisar revisar as funções que lidam com a criação e gestão de depots para garantir que eles estejam corretamente sincronizados. Outra opção é criar ou modificar um script LUA que faz a checagem e sincronização entre os depots. Isso pode ser feito no evento de abertura do depot, onde você sincroniza os itens entre os depots do CP e da casa do jogador. Um exemplo básico de script: local function syncDepots(player) local mainDepot = player:getDepot(1) -- CP depot ID local houseDepot = player:getDepot(2) -- House depot ID (ajuste conforme o ID do depot na casa) -- Sincroniza itens do depot da casa com o CP for i = 0, houseDepot:getCapacity() - 1 do local item = houseDepot:getItem(i) if item then mainDepot:addItemEx(item) end end end function onUse(player, item, fromPosition, target, toPosition, isHotkey) syncDepots(player) -- Continuar a lógica normal de abrir o depot... end
-
<?xml version="1.0" encoding="ISO-8859-1"?> <mod name="Characters Market System" version="1.0" author="LuckOake" contact="none" enabled="yes"> ------------------------------------------------------------------------------------ <config name="market"><![CDATA[ price = 27112 owner = 27113 level = 717217 -- Level min of character.-- min_price = 1 -- Price min of character (in currency 6535)-- max_price = 1000000000 -- Price maximum of character (in currency 6535)-- function doTransferCharacter(cid, accId) local playerGuid = getPlayerGUIDByName(cid) if not playerGuid then return false, "Player GUID not found." end return db.executeQuery("UPDATE `players` SET `account_id` = "..accId.." WHERE `id` = "..playerGuid.."") end function doOfflinePlayerAddMoney(guid, money, itemID) local playerGuid = getPlayerGUIDByName(guid) if not playerGuid then return false, "Player GUID not found." end return db.executeQuery("UPDATE `players` SET `balance` = `balance` + '"..money.."' WHERE `id` = '"..playerGuid.."';") end function setOfflinePlayerStorageValue(name, key, value) local playerGuid = getPlayerGUIDByName(name) if not playerGuid then return false, "Player GUID not found." end local result = db.getResult("SELECT * FROM `player_storage` WHERE `player_id` = ".. playerGuid .." AND `key` = ".. key ..";") if result:getID() == -1 then return db.executeQuery("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES (".. playerGuid ..", ".. key ..", ".. value ..");") else result:free() return db.executeQuery("UPDATE `player_storage` SET `value` = ".. value .." WHERE `player_id` = ".. playerGuid .." AND `key` = ".. key ..";") end end function getOfflinePlayerStorageValue(name, key) local playerGuid = getPlayerGUIDByName(name) if not playerGuid then return nil end local result = db.getResult("SELECT `value` FROM `player_storage` WHERE `player_id` = '".. playerGuid .."' AND `key` = ".. key ..";") if result:getID() == -1 then return nil end local ret = result:getDataInt("value") result:free() return ret end function getOfflinePlayerValue(name, value) local playerGuid = getPlayerGUIDByName(name) if not playerGuid then return nil end local result = db.getResult("SELECT `"..value.."` FROM `players` WHERE `id` = "..playerGuid..";") if result:getID() == -1 then return nil end local ret = result:getDataInt(value) result:free() return ret end function isCharacterForSale(name) local charPrice = getOfflinePlayerStorageValue(name, price) if not charPrice or charPrice < 1 then return false else return true end end ]]></config> ------------------------------------------------------------------------------------ <talkaction words="!character" event="buffer"><![CDATA[ domodlib('market') local t = string.explode(param, ",") if t[1] == "sell" then if not t[3] or not tonumber(t[3]) or t[4] or tonumber(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Incorrect Params. Specify the character name and the price.") return true elseif getPlayerAccountId(cid) ~= getAccountIdByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This is not your character.") return true elseif isCharacterForSale(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character is already for sale.") return true elseif getPlayerGUIDByName(t[2]) == getPlayerGUID(cid) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "You cannot sell yourself.") return true elseif getPlayerByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "The character must be offline to be sold.") return true elseif getOfflinePlayerValue(t[2], "level") < level then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Your character can't be sold until it has level "..level..".") return true elseif tonumber(t[3]) < min_price then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Sorry, but the minimum price for selling a character is "..min_price.." currency units.") return true elseif tonumber(t[3]) > max_price then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Sorry, but the maximum price for selling a character is "..max_price.." currency units.") return true end setOfflinePlayerStorageValue(t[2], price, t[3]) setOfflinePlayerStorageValue(t[2], owner, getPlayerGUID(cid)) doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, 'Your character "'..t[2]..'" is now for sale for the price of "'..t[3]..'" currency units.') elseif t[1] == "buy" then if not t[2] then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Incorrect Params. Specify the character name.") return true elseif not playerExists(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character doesn't exist.") return true elseif getPlayerAccountId(cid) == getAccountIdByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "You can't buy your own character.") return true elseif not isCharacterForSale(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character is not for sale.") return true elseif not doPlayerRemoveItem(cid, 6535, getOfflinePlayerStorageValue(t[2], price)) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Not enough currency. This character's price is "..getOfflinePlayerStorageValue(t[2], price).." currency units.") return true end if not getPlayerByGUID(getOfflinePlayerStorageValue(t[2], owner)) then doOfflinePlayerAddItem(getPlayerNameByGUID(getOfflinePlayerStorageValue(t[2], owner)), getOfflinePlayerStorageValue(t[2], price), 6535) setOfflinePlayerStorageValue(getPlayerNameByGUID(getOfflinePlayerStorageValue(t[2], owner)), 41792, getPlayerGUIDByName(t[2])) else doPlayerAddItem(getPlayerByGUID(getOfflinePlayerStorageValue(t[2], owner)), 6535, getOfflinePlayerStorageValue(t[2], price)) doPlayerSendTextMessage(getPlayerByGUID(getOfflinePlayerStorageValue(t[2], owner)), MESSAGE_STATUS_CONSOLE_BLUE, 'Your character "'..t[2]..'" has been sold for the price of '..getOfflinePlayerStorageValue(t[2], price)..' currency units.') end doTransferCharacter(t[2], getPlayerAccountId(cid)) doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, 'You bought the character "'..t[2]..'" for the price of '..getOfflinePlayerStorageValue(t[2], price)..' currency units.') setOfflinePlayerStorageValue(t[2], owner, -1) setOfflinePlayerStorageValue(t[2], price, -1) return true elseif t[1] == "remove" then if not t[2] then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Incorrect Params. Specify the character name.") return true elseif getPlayerAccountId(cid) ~= getAccountIdByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This is not your character.") return true elseif not isCharacterForSale(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character is not for sale.") return true end setOfflinePlayerStorageValue(t[2], price, -1) doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, 'You removed the character "'..t[2]..'" from the Characters Market.') return true elseif t[1] == "list" then local result = db.getResult("SELECT `name` FROM `players`") if result:getID() == -1 then return true end local msg = "Characters For Sale:\n\n" while true do local name = result:getDataString("name") if isCharacterForSale(name) then local sex = getOfflinePlayerValue(name, "sex") == 1 and "Male" or "Female" msg = ""..msg.." - ".. name .." (Level: "..getOfflinePlayerValue(name, "level").." / Vocation: "..getVocationInfo(getOfflinePlayerValue(name, "vocation")).name.." / Sex: "..sex.." / Owner: "..getPlayerNameByGUID(getOfflinePlayerStorageValue(name, owner))..") [Price: "..getOfflinePlayerStorageValue(name, price).."] \n" end if not result:next() then break end end doPlayerPopupFYI(cid, msg) return true elseif not t[1] or t[1] ~= "buy" or t[1] ~= "sell" or t[1] ~= "remove" or t[1] ~= "list" then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Incorrect params. You can only 'buy' or 'sell' a character, 'remove' it from the Characters Market or see the 'list' of characters for sale.") return true end return true ]]></talkaction> ------------------------------------------------------------------------------------ <event type="login" name="MarketLogin" event="script"><![CDATA[ function onLogin(cid) domodlib('market') if getPlayerStorageValue(cid, price) > 0 then return false elseif getPlayerStorageValue(cid, 41792) ~= -1 then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "You sold the character "..getPlayerNameByGUID(getPlayerStorageValue(cid, 41792))..". The money is in your bank account.") setPlayerStorageValue(cid, 41792, -1) end return true end ]]></event> </mod> Mudanças Realizadas Modificação para usar a moeda com ID 6535: No código doPlayerRemoveItem e doPlayerAddItem ao invés de doPlayerRemoveMoney e doPlayerAddMoney para a transação. Verificação de parâmetros: Ajuste na verificação e mensagem de erro para refletir a moeda correta. Configurações mínimas e máximas de preço: Atualização das variáveis min_price e max_price para refletir os valores corretos na nova moeda. Com essas alterações, o script agora utiliza a moeda com ID 6535 para a compra e permite que os jogadores definam a quantidade desejada ao vender um personagem.
-
Site [WONRS] não seleciona vocação para criação
pergunta respondeu ao menina sexy de El Rusher em Websites
1. Verifique o Código JavaScript O botão de seleção de vocação e o valor do campo pdt_id são definidos pelo JavaScript. Certifique-se de que o JavaScript está funcionando corretamente e que o valor está sendo corretamente atribuído ao campo pdt_id. Aqui está um exemplo de função JavaScript que deve estar presente para selecionar a vocação: function selectpdt(id) { document.getElementById('pdt_id').value = id; var buttons = document.getElementsByClassName('pdt_blc'); for (var i = 0; i < buttons.length; i++) { buttons[i].style.border = 'none'; } document.getElementById('b' + id).style.border = '2px solid #f00'; // Ajuste a borda para indicar seleção } 2. Verifique o HTML do Formulário Assegure-se de que o formulário HTML está configurado corretamente para enviar os dados: O campo oculto para vocação (pdt_id) deve estar presente e ser atualizado pelo JavaScript quando uma vocação é selecionada. O botão de submit (Criar Personagem) deve estar habilitado quando todos os campos forem preenchidos. No seu código, o botão de submit está desabilitado (disabled), o que pode ser a causa do problema. Verifique se o JavaScript está habilitando o botão após a seleção da vocação e o preenchimento dos campos obrigatórios. 3. Verifique a Função selectpdt Verifique se a função JavaScript selectpdt está sendo chamada corretamente ao clicar em uma vocação. Você pode adicionar um console.log para depuração: function selectpdt(id) { console.log('Vocation selected:', id); // Adicione isso para verificar se a função é chamada document.getElementById('pdt_id').value = id; // Resto do código } 4. Verifique o Código PHP para Processamento de Dados Certifique-se de que o valor de $_POST['pdt_id'] está sendo corretamente verificado e validado no código PHP. Aqui está uma parte relevante do seu código: // Validate vocation id if (!in_array((int)$_POST['pdt_id'], $config['available_vocations'])) { $errors[] = 'Permissão negada. Vocação errada.'; } Certifique-se de que o $_POST['pdt_id'] está sendo enviado corretamente e contém um ID válido. atualizando seu código deve ficar mais ou menos assim: <?php require_once 'engine/init.php'; protect_page(); include 'layout/overall/header.php'; $imagem = 'http://' . $_SERVER['HTTP_HOST'] . '/layout/images/vocstatus'; $statusid = 1; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $required_fields = array('name', 'selected_town', 'pdt_id'); $errors = array(); foreach ($required_fields as $field) { if (empty($_POST[$field])) { $errors[] = 'You need to fill in all fields.'; break; } } if (empty($errors)) { if (!Token::isValid($_POST['token'])) { $errors[] = 'O token é inválido.'; } $_POST['name'] = validate_name($_POST['name']); if ($_POST['name'] === false) { $errors[] = 'Seu nome não pode conter mais de 2 palavras.'; } else { if (user_character_exist($_POST['name']) !== false) { $errors[] = 'Desculpe, esse nome de personagem já existe.'; } if (!preg_match("/^[a-zA-Z_ ]+$/", $_POST['name'])) { $errors[] = 'Seu nome pode conter apenas a-z, A-Z e espaços.'; } if (strlen($_POST['name']) < $config['minL'] || strlen($_POST['name']) > $config['maxL']) { $errors[] = 'O nome do seu personagem deve estar entre ' . $config['minL'] . ' - ' . $config['maxL'] . ' caracteres longos.'; } if (in_array(strtolower($_POST['name']), $config['invalidNames'])) { $errors[] = 'Este nome de usuario esta bloqueado.'; } $resname = explode(" ", $_POST['name']); foreach ($resname as $res) { if (in_array(strtolower($res), $config['invalidNameTags'])) { $errors[] = 'Seu nome de usuário contém uma palavra restrita.'; } else if (strlen($res) == 1) { $errors[] = 'Palavras muito curtas em seu nome.'; } } if (!in_array((int)$_POST['pdt_id'], $config['available_vocations'])) { $errors[] = 'Permissão negada. Vocação errada.'; } $char_count = user_character_list_count($session_user_id); if ($char_count >= $config['max_characters']) { $errors[] = 'Sua conta não tem permissão para ter mais de ' . $config['max_characters'] . ' personagens.'; } if (validate_ip(getIP()) === false && $config['validate_IP'] === true) { $errors[] = 'Falha ao reconhecer o seu endereço IP. (Não é um endereço IPv4 válido).'; } } } } ?> <div id="title"> <div class="name">Criar novo personagem</div> </div> <br> <?php if (isset($_GET['success']) && empty($_GET['success'])) { echo 'Parabéns! Seu personagem foi criado. Te vejo no jogo!'; } else { if ($_SERVER['REQUEST_METHOD'] === 'POST' && empty($errors)) { if ($config['log_ip']) { znote_visitor_insert_detailed_data(2); } // Register $character_data = array( 'name' => format_character_name($_POST['name']), 'elo_points' => 0, 'account_id' => $session_user_id, 'vocation' => $_POST['pdt_id'], 'lastip' => getIPLong(), 'created' => time() ); user_create_character($character_data); header('Location: createcharacter.php?success'); exit(); } else if (!empty($errors)) { echo '<font color="red"><b>'; echo output_errors($errors); echo '</b></font>'; } ?> <br> <link rel="stylesheet" type="text/css" href="layout/css/style.css"> <script type="text/javascript" src="/layout/js/selection.js"></script> <center> <div class="Text"> <br>Selecione o personagem desejado:</div> <div class="caixa" style="width: 600px;height: 300px;overflow: auto;"> <table border="0" cellspacing="10" cellpadding="0"> <?php $y = 0; $i = 0; foreach ($config['available_vocations'] as $id) { if ($i == 0) { echo '<tr>'; } $i++; $y++; ?> <td> <table style="width:115px;" border="0" cellspacing="0" cellpadding="0"> <tr style="height:75px;"> <td> <div id="i<?php echo $id; ?>" class="pdt_cls" style="background-image:url('<?php echo $config['images']['selectVocation']; ?>/<?php echo $id; ?>.png'), url(/layout/images/donate/back.png);"> <div id="b<?php echo $id; ?>" class="pdt_blc" value="<?php echo $id; ?>" onclick="selectpdt(<?php echo $id; ?>);"></div> </div> </td> </tr> <tr> <td> <center> <div class="pdt_nme"><?php echo vocation_id_to_name($id); ?></div> </center> </td> </tr> </table> </td> <td> <div style="width:20px;"></div> </td> <?php if ($i == 3) { echo '</tr>'; $i = 0; } } ?> </table> </div> <br> <form action="" method="post"> <li> <font color="white">Digite o nome para seu personagem:</font> <br> <input type="text" name="name"> </li> <input id="pdt_id" name="pdt_id" type="hidden" value="0" /> <table> <tr> <td> <input id="ckb_obs" name="ckb_obs" onclick="chkbox();" type="checkbox" /> </td> <td> <label class="Text" style="width:100%;" for="ckb_obs"> <center>Estou ciente das <a href="/termos.php" style="font-family:monospace; font-size:13px; font-weight:bold;">observações referentes a criação do personagem.</a></center> </label> </td> </tr> </table> <input type="hidden" name="token" value="<?php echo Token::generate(); ?>" /> <div style="height:20px;"></div> <input id="Button" type="submit" value="Criar Personagem" /> </form> </center> <?php } include 'layout/overall/footer.php'; ?> -
Database error. Unknown database type
pergunta respondeu ao luanaaaaaaaaaaaaa de El Rusher em Websites
Parece que há dois problemas distintos com sua configuração: 1. Erro ao Abrir o Arquivo de Configuração O erro indica que o arquivo config.lua não pôde ser encontrado no caminho especificado. Verifique o seguinte: Caminho do Arquivo: Certifique-se de que o caminho D:/OTServ8.60/config.lua está correto e que o arquivo config.lua realmente existe nesse diretório. Permissões de Arquivo: Verifique se o servidor web (por exemplo, Apache no XAMPP) tem permissões suficientes para ler o arquivo config.lua. Extensão do Arquivo: Confirme se o arquivo realmente tem a extensão .lua e não .txt ou outra extensão. 2. Erro de Tipo de Banco de Dados O segundo erro indica que o tipo de banco de dados não está sendo reconhecido corretamente. Pode ser que o problema esteja na forma como o arquivo config.lua está sendo lido e interpretado. A configuração que você forneceu parece correta, mas vamos verificar algumas possíveis soluções: Passos para Resolver o Problema Verifique a Leitura do Arquivo config.lua Certifique-se de que o PHP está configurado corretamente para ler arquivos .lua. Muitas vezes, o PHP pode ter problemas com formatos de arquivo que não são padrão. Em vez de parse_ini_file, você pode usar outra abordagem para carregar e interpretar o arquivo Lua. Valide a Sintaxe do Arquivo config.lua Embora o conteúdo pareça correto, o formato do arquivo Lua deve ser adequado. Aqui está um exemplo básico de como o config.lua pode estar estruturado: sqlType = "mysql" sqlHost = "localhost" sqlPort = 3306 sqlUser = "root" sqlPass = "" sqlDatabase = "hogwarts" sqliteDatabase = "orion.s3db" sqlKeepAlive = 0 mysqlReadTimeout = 10 mysqlWriteTimeout = 10 encryptionType = "sha1" Certifique-se de que não há caracteres extras ou formatação incorreta. Verifique a Configuração do PHP Se o PHP está tentando abrir o arquivo .lua como se fosse um arquivo INI, você pode ter que ajustar o código PHP. Em vez de parse_ini_file, você pode precisar usar uma biblioteca Lua específica ou ler o arquivo Lua manualmente e processá-lo. Por exemplo: // Exemplo de leitura manual $config = file_get_contents('D:/OTServ8.60/config.lua'); // Faça o parsing necessário aqui Verifique a Configuração do Banco de Dados Certifique-se de que seu banco de dados está configurado corretamente e que o nome do banco de dados (hogwarts) existe. Além disso, o tipo de banco de dados deve ser mysql conforme definido em sqlType. -
Abra o arquivo config.lua: Este arquivo geralmente está localizado na pasta de configuração do seu servidor, como data/ ou config/. Procure por definições relacionadas a canais de NPC: O ID do canal NPC pode estar definido diretamente no arquivo ou pode haver uma referência para a tabela de canais. Você pode procurar por algo semelhante a: -- Definições de canais channels = { [1] = {name = "Default", description = "Canal padrão"}, [2] = {name = "NPC", description = "Canal dos NPCs"}, -- Outros canais } Verifique o Código-Fonte do Servidor Localize o arquivo de definição de canais: Isso pode estar em um arquivo relacionado a canais ou mensagens. Pode ser algo como channels.cpp ou um arquivo similar. Procure pela definição do canal NPC: Procure por IDs ou definições que correspondam ao canal de NPCs.
-
Encontre o arquivo de configuração do cliente: Normalmente, isso pode ser um arquivo .cfg, .ini ou um arquivo XML/JSON, dependendo do cliente que você está usando. Abra o arquivo de configuração: Use um editor de texto para abrir o arquivo. Procure por configurações relacionadas à barra de saúde: Algo como healthinfo ou statusbar. Se o seu cliente usa XML para configurações, você pode encontrar algo assim: <interface> <healthinfo visible="false" /> </interface> Você precisaria alterar visible="false" para visible="true": <interface> <healthinfo visible="true" /> </interface> 2. Modificação no Código-Fonte Se a configuração não estiver diretamente disponível em um arquivo de configuração, você pode precisar modificar o código-fonte do cliente. Aqui está um exemplo de como você pode fazer isso em C++: Exemplo em C++ Encontre a função de inicialização da interface do cliente: Esta função geralmente é responsável por configurar e renderizar os elementos da interface do usuário quando o cliente é iniciado. Adicione o código para tornar a barra de saúde visível: Isso pode ser algo assim: void Interface::initialize() { // Outras inicializações // Certifique-se de que a barra de saúde esteja visível healthInfoBar->setVisible(true); }
-
[C++] -=[TFS]=- 0.3.6 - 8.60 [BUG] PLAYER ENTRA DENTRO DO PLAYER NO DEPOT
pergunta respondeu ao Muvuka de El Rusher em Programação
Para ajustar o código e garantir que um jogador não possa atravessar outro jogador no depósito, você pode modificar a função canWalkthrough para retornar false quando os jogadores estiverem no depósito. Aqui está uma versão atualizada da função que adiciona esta verificação: bool Player::canWalkthrough(const Creature* creature) const { if (creature == this || hasCustomFlag(PlayerCustomFlag_CanWalkthrough) || creature->isWalkable() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if (!player) return false; // Verifica se os jogadores estão no depósito if (player->getTile()->hasFlag(TILESTATE_DEPOT) || this->getTile()->hasFlag(TILESTATE_DEPOT)) { return false; } if ((((g_game.getWorldType() == WORLD_TYPE_NO_PVP && player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); } Aqui, adicionamos a verificação: if (player->getTile()->hasFlag(TILESTATE_DEPOT) || this->getTile()->hasFlag(TILESTATE_DEPOT)) { return false; } -
Os erros indicam que a função getPlayerGUIDByName está retornando nil para os nomes de personagens fornecidos. Isso pode ocorrer devido a vários motivos, como o personagem não existir na base de dados, erros de sintaxe nos nomes dos personagens, ou problemas de conexão com o banco de dados. Vamos ajustar o script para lidar melhor com esses casos e garantir que a função getPlayerGUIDByName esteja retornando valores corretos ou tratando os erros adequadamente. Vou também adicionar mais debug prints para ajudar a identificar a causa exata dos problemas. <?xml version="1.0" encoding="ISO-8859-1"?> <mod name="Characters Market System" version="1.0" author="LuckOake" contact="none" enabled="yes"> <config name="market"><![CDATA[ price = 27112 owner = 27113 level = 717217 -- Level min of character. -- min_price = 10000000000000 -- Price min of character -- max_price = 10000000000000 -- Price maximum of character -- function doTransferCharacter(cid, accId) local playerGUID = getPlayerGUIDByName(cid) print("doTransferCharacter - Player GUID for", cid, "is", playerGUID) if playerGUID then return db.executeQuery("UPDATE `players` SET `account_id` = " .. accId .. " WHERE `id` = " .. playerGUID) else print("Error: Player GUID for " .. cid .. " is nil.") return false end end function doOfflinePlayerAddMoney(guid, money) local playerGUID = getPlayerGUIDByName(guid) print("doOfflinePlayerAddMoney - Player GUID for", guid, "is", playerGUID) if playerGUID then return db.executeQuery("UPDATE `players` SET `balance` = `balance` + " .. money .. " WHERE `id` = " .. playerGUID .. ";") else print("Error: Player GUID for " .. guid .. " is nil.") return false end end function setOfflinePlayerStorageValue(name, key, value) local playerGUID = getPlayerGUIDByName(name) print("setOfflinePlayerStorageValue - Player GUID for", name, "is", playerGUID) if playerGUID then local result = db.getResult("SELECT * FROM `player_storage` WHERE `player_id` = " .. playerGUID .. " AND `key` = " .. key .. ";") if result:getID() == -1 then print("setOfflinePlayerStorageValue - No existing storage value found, inserting new value") return db.executeQuery("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES (" .. playerGUID .. ", " .. key .. ", " .. value .. ");") else result:free() print("setOfflinePlayerStorageValue - Existing storage value found, updating value") return db.executeQuery("UPDATE `player_storage` SET `value` = " .. value .. " WHERE `player_id` = " .. playerGUID .. " AND `key` = " .. key .. ";") end else print("Error: Player GUID for " .. name .. " is nil.") return false end end function getOfflinePlayerStorageValue(name, key) local playerGUID = getPlayerGUIDByName(name) print("getOfflinePlayerStorageValue - Player GUID for", name, "is", playerGUID) if playerGUID then local result = db.getResult("SELECT `value` FROM `player_storage` WHERE `player_id` = " .. playerGUID .. " AND `key` = " .. key .. ";") if result:getID() == -1 then print("getOfflinePlayerStorageValue - No storage value found for", name, "with key", key) return nil end local ret = result:getDataInt("value") print("getOfflinePlayerStorageValue - Retrieved storage value for", name, "with key", key, "is", ret) result:free() return ret else print("Error: Player GUID for " .. name .. " is nil.") return nil end end function getOfflinePlayerValue(name, value) local playerGUID = getPlayerGUIDByName(name) print("getOfflinePlayerValue - Player GUID for", name, "is", playerGUID) if playerGUID then local result = db.getResult("SELECT `" .. value .. "` FROM `players` WHERE `id` = " .. playerGUID .. ";") if result:getID() == -1 then print("getOfflinePlayerValue - No value found for", name, "with field", value) return nil end local ret = result:getDataInt(value) print("getOfflinePlayerValue - Retrieved value for", name, "with field", value, "is", ret) result:free() return ret else print("Error: Player GUID for " .. name .. " is nil.") return nil end end function isCharacterForSale(name) local playerGUID = getPlayerGUIDByName(name) print("isCharacterForSale - Player GUID for", name, "is", playerGUID) if playerGUID and getOfflinePlayerStorageValue(name, price) and getOfflinePlayerStorageValue(name, price) > 0 then return true else return false end end ]]></config> <talkaction words="!character" event="buffer"><![CDATA[ domodlib('market') local t = string.explode(param, ",") if t[1] == "sell" then if not t[3] or not tonumber(t[3]) or t[4] or tonumber(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Incorrect Params. Specify the character name and the price.") return true elseif getPlayerAccountId(cid) ~= getAccountIdByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This is not your character.") return true elseif isCharacterForSale(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character is already for sale.") return true elseif getPlayerGUIDByName(t[2]) == getPlayerGUID(cid) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "You cannot sell yourself.") return true elseif getPlayerByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "The character must be offline to be sold.") return true elseif getOfflinePlayerValue(t[2], "level") < level then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Your character can't be sold until it has level "..level..".") return true elseif tonumber(t[3]) < min_price then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Sorry, but the minimum price for selling a character is "..min_price..".") return true elseif tonumber(t[3]) > max_price then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Sorry, but the maximum price for selling a character is "..max_price..".") return true end setOfflinePlayerStorageValue(t[2], price, t[3]) setOfflinePlayerStorageValue(t[2], owner, getPlayerGUID(cid)) doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, 'Your character "'..t[2]..'" is now for sale for the price of "'..t[3]..'" gold coins.') elseif t[1] == "buy" then if not t[2] then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Incorrect Params. Specify the character name.") return true elseif not playerExists(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character doesn't exist.") return true elseif getPlayerAccountId(cid) == getAccountIdByName(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "You can't buy your own character.") return true elseif not isCharacterForSale(t[2]) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "This character is not for sale.") return true elseif not doPlayerRemoveMoney(cid, getOfflinePlayerStorageValue(t[2], price)) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, "Not enough money. This character's price is "..getOfflinePlayerStorageValue(t[2], price).." gold coins.") return true end if not getPlayerByGUID(getOfflinePlayerStorageValue(t[2], owner)) then doOfflinePlayerAddMoney(getPlayerNameByGUID(getOfflinePlayerStorageValue(t[2], owner)), getOfflinePlayerStorageValue(t[2], price)) setOfflinePlayerStorageValue(getPlayerNameByGUID(getOfflinePlayerStorageValue(t[2], owner)), 41792, getPlayerGUIDByName(t[2])) else doPlayerAddMoney(getPlayerByGUID(getOfflinePlayerStorageValue(t[2], owner)), getOfflinePlayerStorageValue(t[2], price)) end doTransferCharacter(t[2], getPlayerAccountId(cid)) setOfflinePlayerStorageValue(t[2], price, 0) setOfflinePlayerStorageValue(t[2], owner, 0) doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, 'You have bought the character "'..t[2]..'" for "'..getOfflinePlayerStorageValue(t[2], price)..'" gold coins.') elseif t[1] == "list" then doPlayerPopupFYI(cid, "Houses for sale") end return true ]]></talkaction> </mod>
-
A variável talkUser foi ajustada para garantir que a conversa seja atribuída corretamente ao jogador. substitua: local talkUser = cid por: local talkUser = NPCHANDLER_CONVbehavior == CONVERSATION_DEFAULT and 0 or cid A lógica para verificar e atualizar a vocação e o nível do jogador foi revisada para garantir que esteja funcionando corretamente. if isInArray({"promotion", "promot", "promo"}, msg) then selfSay('Você precisa ter 100 [VIP COINS] e estar no level 717217!', cid) talkState[talkUser] = 1 elseif msg == "yes" and talkState[talkUser] == 1 then local playerVocation = getPlayerVocation(cid) if vocation[playerVocation] then if getPlayerLevel(cid) >= level then if getPlayerItemCount(cid, 11192) >= 100 then doPlayerRemoveItem(cid, 11192, 100) local newVocationId = vocation[playerVocation] doPlayerSetVocation(cid, newVocationId) doSendMagicEffect(getPlayerPosition(cid), 12) selfSay("Parabéns, você foi promovido!", cid) else selfSay("Você não tem 100 [VIP COINS] suficientes para ser promovido.", cid) end else selfSay("Desculpe, você precisa estar no level " .. level .. " ou acima para ser promovido!", cid) end else selfSay("Desculpe, você não pode receber promoção.", cid) end talkState[talkUser] = 0 end script completo corrigido: local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local talkState = {} local vocation = { [2] = 6, [3] = 7, [4] = 8 } function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onThink() npcHandler:onThink() end function creatureSayCallback(cid, type, msg) if (not npcHandler:isFocused(cid)) then return false end local talkUser = NPCHANDLER_CONVbehavior == CONVERSATION_DEFAULT and 0 or cid msg = string.lower(msg) local level = 717217 if isInArray({"promotion", "promot", "promo"}, msg) then selfSay('Você precisa ter 100 [VIP COINS] e estar no level 717217!', cid) talkState[talkUser] = 1 elseif msg == "yes" and talkState[talkUser] == 1 then local playerVocation = getPlayerVocation(cid) if vocation[playerVocation] then if getPlayerLevel(cid) >= level then if getPlayerItemCount(cid, 11192) >= 100 then doPlayerRemoveItem(cid, 11192, 100) local newVocationId = vocation[playerVocation] doPlayerSetVocation(cid, newVocationId) doSendMagicEffect(getPlayerPosition(cid), 12) selfSay("Parabéns, você foi promovido!", cid) else selfSay("Você não tem 100 [VIP COINS] suficientes para ser promovido.", cid) end else selfSay("Desculpe, você precisa estar no level " .. level .. " ou acima para ser promovido!", cid) end else selfSay("Desculpe, você não pode receber promoção.", cid) end talkState[talkUser] = 0 end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new())
-
descreva o sistema que eu faço pra tu meu nobre
-
pode ser privilegio de GM / ADM
-
function onSay(cid, words, param) local guilds = {} local guild_rank = {} -- Seleciona o level e a guild de cada jogador com guild e com level maior que 10, ordenados pelo level local query = db.getResult("SELECT level, guild_id FROM players WHERE guild_id > 0 AND level > 10 ORDER BY level DESC") -- Caso nenhum jogador seja selecionado, retorna verdadeiro if query:getID() == -1 then return true end repeat local level = query:getDataInt("level") local guild_id = query:getDataInt("guild_id") -- Cria uma tabela dentro da tabela guilds para cada guilda if not guilds[guild_id] then guilds[guild_id] = {level = level, members = 1} -- Se a tabela já existir e o número de membros for menor que 10, soma o level e +1 ao número de membros elseif guilds[guild_id].members < 10 then guilds[guild_id].level = guilds[guild_id].level + level guilds[guild_id].members = guilds[guild_id].members + 1 end -- Termina se não existirem mais resultados until not query:next() query:free() -- Passa os resultados obtidos para a tabela guild_rank, para ordená-la com table.sort for i, k in pairs(guilds) do table.insert(guild_rank, {id = i, level = k.level}) end -- Ordena a tabela guild_rank de acordo com a soma dos levels table.sort(guild_rank, function(a, b) return a.level > b.level end) local i = 0 local str = ' Guild Rank\n' -- Crie uma string com o nome das guildas em um ranking for _, info in pairs(guild_rank) do i = i + 1 str = str .. i .. ' - '.. getGuildNameById(info.id) .. ' - ' .. info.level .. '\n' if i == 10 then break end end -- Se algum erro ocorrer e o ranking não tiver informações, manda a mensagem "No Guild Information..." local ret = str ~= ' Guild Rank\n' and str or "No guild information to be displayed." doPlayerPopupFYI(cid, ret) return true end O erro que você está encontrando, SQLITE ERROR: no such column: guild_id, indica que a coluna guild_id não existe na tabela players. adicione no seu banco de dados: ALTER TABLE players ADD COLUMN guild_id INTEGER DEFAULT 0;
-
boa noite Script de Ação para "DANGER!" local config = { effectonuse = 65, -- Efeito visual ao usar o item levelscrit = 100, -- Nível máximo do crítico lvlcritDanger = 48913 -- Storage para crítico "DANGER!" } function onUse(cid, item, frompos, item2, topos) local currentLevel = getPlayerStorageValue(cid, config.lvlcritDanger) or 0 if currentLevel < config.levelscrit then doRemoveItem(item.uid, 1) doSendMagicEffect(topos, config.effectonuse) doPlayerSendTextMessage(cid, 22, "You've Leveled your Critical Skill to [" .. (currentLevel + 1) .. "/" .. config.levelscrit .. "].") setPlayerStorageValue(cid, config.lvlcritDanger, currentLevel + 1) else doPlayerSendTextMessage(cid, 22, "You've already reached the MAX level of Critical Skill.\nCongratulations!!!!") return 0 end return 1 end Script de Combate local lvlcrit = 48904 local lvlcritDanger = 48913 function onCombat(cid, target) if isPlayer(cid) and isCreature(target) then local criticalChance = getPlayerStorageValue(cid, lvlcrit) or 0 local criticalDangerChance = getPlayerStorageValue(cid, lvlcritDanger) or 0 local chance = math.random(1, 1000) -- Mantém um intervalo razoável -- Verifica primeiro o crítico perigoso if chance <= (criticalDangerChance * 3) then local damage = 100 -- Valor do dano crítico "DANGER!" (ajuste conforme necessário) doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -damage, -damage, 255) doSendAnimatedText(getCreaturePos(target), "DANGER!", 190) doSendMagicEffect(getCreaturePosition(cid), 52) elseif chance <= (criticalChance * 3) then local damage = 100 -- Valor do dano crítico "BOOSTER" (ajuste conforme necessário) doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -damage, -damage, 255) doSendAnimatedText(getCreaturePos(target), "+BOOSTER!", 31) doSendMagicEffect(getCreaturePosition(cid), 54) end end return true end
-
local MONEY_AMOUNT = 1000000 -- Quantidade de dinheiro (em gold coins) que o player necessitará para reviver local MAGIC_EFFECT_TELEPORT = 65 -- Efeito que aparecerá quando o player for teleportado local PLAYER_REBORN_POSITION_X = 66541 local PLAYER_REBORN_POSITION_Y = 66542 local PLAYER_REBORN_POSITION_Z = 66543 local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local talkState = {} function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onThink() npcHandler:onThink() end function creatureSayCallback(cid, type, msg) if not npcHandler:isFocused(cid) then return false end local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid if msgcontains(msg, 'reviver') or msgcontains(msg, 'revive') then selfSay('Você precisa de ' .. MONEY_AMOUNT .. ' gold(s) para ressuscitar no local onde você morreu recentemente', cid) talkState[talkUser] = 1 elseif msgcontains(msg, 'yes') and talkState[talkUser] == 1 then if getPlayerMoney(cid) >= MONEY_AMOUNT then doPlayerRemoveMoney(cid, MONEY_AMOUNT) if teleportPlayerToPositionReborn(cid) then doTeleportThing(cid, {x = PLAYER_REBORN_POSITION_X, y = PLAYER_REBORN_POSITION_Y, z = PLAYER_REBORN_POSITION_Z}) doSendMagicEffect(getCreaturePosition(cid), MAGIC_EFFECT_TELEPORT) selfSay('Ok, você foi ressuscitado', cid) end else selfSay('Desculpe, mas você não possui dinheiro suficiente.', cid) end talkState[talkUser] = 0 elseif msgcontains(msg, 'no') and talkState[talkUser] == 1 then talkState[talkUser] = 0 selfSay('Ok, até mais.', cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new()) function teleportPlayerToPositionReborn(cid) local playerRebornPositionX = getPlayerStorageValue(cid, PLAYER_REBORN_POSITION_X) local playerRebornPositionY = getPlayerStorageValue(cid, PLAYER_REBORN_POSITION_Y) local playerRebornPositionZ = getPlayerStorageValue(cid, PLAYER_REBORN_POSITION_Z) if playerRebornPositionX == -1 or playerRebornPositionY == -1 or playerRebornPositionZ == -1 then selfSay('Você não morreu nenhuma vez ainda.', cid) return false end doTeleportThing(cid, {x = playerRebornPositionX, y = playerRebornPositionY, z = playerRebornPositionZ}) return true end Correção na Função teleportPlayerToPositionReborn: Os valores PLAYER_REBORN_POSITION_X, PLAYER_REBORN_POSITION_Y e PLAYER_REBORN_POSITION_Z devem ser usados corretamente para obter a posição armazenada do jogador. Correção na Lógica de Teleporte: A função doTeleportThing é chamada uma vez no teleportPlayerToPositionReborn e não precisa ser chamada novamente na função principal. Adição de Mensage
-
boa noite local lvlcrit = 48913 -- armazenamento para críticos normais local lvlcritDanger = 48904 -- armazenamento para críticos perigosos local multiplier = 1.5 -- multiplicador de dano function onCombat(cid, target) print("onCombat chamado com cid: " .. tostring(cid) .. " target: " .. tostring(target)) if isPlayer(cid) and isCreature(target) then local criticalChance = getPlayerStorageValue(cid, lvlcrit) or 0 local criticalDangerChance = getPlayerStorageValue(cid, lvlcritDanger) or 0 local chance = math.random(1, 1000) -- Mantém um intervalo razoável print("Chances de crítico: normal=" .. criticalChance .. " perigo=" .. criticalDangerChance .. " sorteio=" .. chance) -- Verifica se a chance de crítico BOOSTER é atingida if chance <= (criticalChance * 3) then print("Crítico BOOSTER atingido!") local damage = 100 -- Valor do dano crítico BOOSTER (ajuste conforme necessário) doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -damage, -damage, 255) doSendAnimatedText(getCreaturePosition(target), "+BOOSTER!", 31) doSendMagicEffect(getCreaturePosition(cid), 54) return true end -- Verifica se a chance de crítico DANGER é atingida if chance <= (criticalDangerChance * 3) then print("Crítico DANGER atingido!") local damage = 100 -- Valor do dano crítico DANGER (ajuste conforme necessário) doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -damage, -damage, 255) doSendAnimatedText(getCreaturePosition(target), "DANGER!", 190) doSendMagicEffect(getCreaturePosition(cid), 52) return true end end return true end
-
local config = AscendingFerumbrasConfig local crystals = { [1] = { fromPosition = Position(33389, 31467, 14), toPosition = Position(33391, 31469, 14), crystalPosition = Position(33390, 31468, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal1 }, [2] = { fromPosition = Position(33393, 31467, 14), toPosition = Position(33395, 31469, 14), crystalPosition = Position(33394, 31468, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal2 }, [3] = { fromPosition = Position(33396, 31470, 14), toPosition = Position(33398, 31472, 14), crystalPosition = Position(33397, 31471, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal3 }, [4] = { fromPosition = Position(33396, 31474, 14), toPosition = Position(33398, 31476, 14), crystalPosition = Position(33397, 31475, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal4 }, [5] = { fromPosition = Position(33393, 31477, 14), toPosition = Position(33395, 31479, 14), crystalPosition = Position(33394, 31478, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal5 }, [6] = { fromPosition = Position(33389, 31477, 14), toPosition = Position(33391, 31479, 14), crystalPosition = Position(33390, 31478, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal6 }, [7] = { fromPosition = Position(33386, 31474, 14), toPosition = Position(33388, 31476, 14), crystalPosition = Position(33387, 31475, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal7 }, [8] = { fromPosition = Position(33386, 31470, 14), toPosition = Position(33388, 31472, 14), crystalPosition = Position(33387, 31471, 14), globalStorage = GlobalStorage.FerumbrasAscendant.Crystals.Crystal8 }, } local function createDestabilizedFerumbrasIfNeeded() local essenceCount = Game.getStorageValue(GlobalStorage.FerumbrasAscendant.FerumbrasEssence) if essenceCount == 8 then Game.createMonster("Destabilized Ferumbras", config.bossPos, true, true) for i = 1, config.maxSummon do local summonPos = Position(math.random(33381, 33403), math.random(31462, 31483), 14) if not Game.createMonster("Rift Fragment", summonPos, true, true) then print(string.format("Error: Could not create Rift Fragment at position %s", summonPos)) end end end end local riftInvaderDeath = CreatureEvent("RiftInvaderDeath") function riftInvaderDeath.onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) local name = creature:getName():lower() if name == "rift invader" then for i = 1, #crystals do local crystal = crystals[i] if creature:getPosition():isInRange(crystal.fromPosition, crystal.toPosition) then if Game.getStorageValue(crystal.globalStorage) > 6 then local item = Tile(crystal.crystalPosition):getItemById(14955) if item then item:transform(14961) Game.setStorageValue(GlobalStorage.FerumbrasAscendant.Crystals.AllCrystals, Game.getStorageValue(GlobalStorage.FerumbrasAscendant.Crystals.AllCrystals) + 1) lasthitkiller:say("The negative energy of the rift creature is absorbed by the crystal!", TALKTYPE_MONSTER_SAY, nil, nil, crystal.crystalPosition) lasthitkiller:say("ARGH!", TALKTYPE_MONSTER_SAY, nil, nil, Position(33392, 31473, 14)) end end Game.setStorageValue(crystal.globalStorage, Game.getStorageValue(crystal.globalStorage) + 1) end end local pool = Tile(creature:getPosition()):getItemById(2886) if pool then pool:remove() end local vortex = Game.createItem(config.vortex, 1, creature:getPosition()) if vortex then addEvent(function(creaturePos) local tile = Tile(creaturePos) if tile then local vortexItem = tile:getItemById(config.vortex) if vortexItem then vortexItem:remove(1) end end end, 10 * 1000, creature:getPosition()) end createDestabilizedFerumbrasIfNeeded() end return true end riftInvaderDeath:register() local vortex = Action() function vortex.onStepIn(creature, item, position, fromPosition) local monster = creature:getMonster() if monster and monster:getName():lower() == "ferumbras essence" then monster:remove() position:sendMagicEffect(CONST_ME_POFF) local essenceCount = Game.getStorageValue(GlobalStorage.FerumbrasAscendant.FerumbrasEssence) if essenceCount < 0 then essenceCount = 0 end essenceCount = essenceCount + 1 Game.setStorageValue(GlobalStorage.FerumbrasAscendant.FerumbrasEssence, essenceCount) if essenceCount >= 8 then createDestabilizedFerumbrasIfNeeded() end end return true end vortex:uid(1022) vortex:register() Neste código revisado, eu movi a criação do "Destabilized Ferumbras" para uma função separada chamada createDestabilizedFerumbrasIfNeeded. Esta função é chamada tanto na função riftInvaderDeath.onDeath quanto na função vortex.onStepIn, sempre que uma essência é transformada em cristal ou quando uma essência entra no vortex.
-
vamos alterar a lógica entao: function vortex.onStepIn(creature, item, position, fromPosition) local monster = creature:getMonster() if not monster or monster:getName():lower() ~= "ferumbras essence" then return true end print("Ferumbras Essence entrou no vortex") monster:remove() position:sendMagicEffect(CONST_ME_POFF) local essenceCount = Game.getStorageValue(GlobalStorage.FerumbrasAscendant.FerumbrasEssence) if essenceCount < 0 then essenceCount = 0 end essenceCount = essenceCount + 1 Game.setStorageValue(GlobalStorage.FerumbrasAscendant.FerumbrasEssence, essenceCount) print("Número atual de essências:", essenceCount) if essenceCount >= 8 then print("Todas as essências transformadas, criando Destabilized Ferumbras") Game.createMonster("Destabilized Ferumbras", config.bossPos, true, true) for i = 1, config.maxSummon do local summonPos = Position(math.random(33381, 33403), math.random(31462, 31483), 14) if not Game.createMonster("Rift Fragment", summonPos, true, true) then print(string.format("Error: Could not create Rift Fragment at position %s", summonPos)) end end end return true end
-
Quem Está Navegando 0 membros estão online
- Nenhum usuário registrado visualizando esta página.