Histórico de Curtidas
-
Henriquegb recebeu reputação de Dine em Erro High Level , Poke muito forteisso acontece com qualquer valor muito alto em dano.
por exemplo se você editar uma espada e colocar ela com dano maximo.
alguns hits dela vão healar (muito). não sei se tem como resolver isso.
-
Henriquegb deu reputação a xWhiteWolf em [Duvida] registrar informaçõeseu sabia menos de Lua que você.. só treinei bastante hahaha
-
Henriquegb deu reputação a xWhiteWolf em [Duvida] registrar informaçõesvê se vc entende agora:
o storage inicialmente é -1 então ele cai no else ali e vai setar o valor como sendo o valor do dice (1~6).
Aí no próximo ataque ele vai cair no elseif stor > 0 e setar o valor que estava (1~6) + 10 * (1~6), ou seja vai ficar (10~60)+ (1~6).
No próximo ataque ele vai cair no elseif stor > 10 e setar o valor que estava (10~60)+ (1~6) + 100* (1~6) ou seja, vai ficar (100~600)+(10~60)+ (1~6).
No ultimo ataque ele vai cair no if stor > 100 e aí ele passa o valor pra variável dmg e zera o storage.
Nessa parte que ele faz isso, vc pode fazer oque vc quiser com a sequência de dices que caiu.. se cair 3 no primeiro, 4 no segundo e 1 no terceiro o numero salvo em dmg será 143. Entendeu agora?
-
Henriquegb deu reputação a xWhiteWolf em [Duvida] registrar informaçõesnão precisa abrir mão, dá pra vc fazer uma lógica que inclua isso.
guardar os storages multiplicáveis? como assim?
Dá pra configurar de forma precisa sim, uma vez que vc tem todos os valores salvos por ordem e por valor.
Se vc declarar dice ele vai pegar o valor salvo pelo primeiro math.random gerado, se vc quiser fazer outro use a função math.random(1,6) ao invés da variável.
-
Henriquegb deu reputação a xWhiteWolf em [Duvida] registrar informaçõessim, toda vez que for executado o callback ele irá gerar um novo math.random mas cada vez que vc usar dice o valor será do primeiro math.random
-
Henriquegb deu reputação a xWhiteWolf em [Duvida] registrar informaçõesvc tava querendo pegar a vida do atacante fora do callback (nesse momento não existe atacante ainda) e tava falando pro uid falar as frases.. na vdd tinha que ser o cid
-
Henriquegb deu reputação a xWhiteWolf em [Duvida] registrar informaçõesse vc usar dice1..dice2..dice3 ele retorna uma string com os 3 valores de dice.
vamos supor 1, 4, e 2
vai retornar "142"
-
Henriquegb recebeu reputação de David Otserver em (Resolvido)Como colocar Sistema de Matar Player em Poketibiavamos por partes porque eu não entendo muito de servidores derivados.
a função PK (skull) ainda funciona no servidor derivado? ou seja, quando vc mata alguem vc fica com skull?
se a resposta for sim da pra fazer algo acredito.
-
Henriquegb recebeu reputação de David Otserver em (Resolvido)Como colocar Sistema de Matar Player em PoketibiaOs players quando morrem geralmente perdem Exp, acredito q isso seja no config.lua.
mas, esse script deve funcionar para o seu fim. (ao matar player ganhar 1 lvl)
function onDeath(cid, corpse, killer) if isPlayer(cid) then doPlayerAddLevel(killer, 1) else end end nem testei, e nem sei se é exatamente isso q quer.
teste e diga.
-
Henriquegb recebeu reputação de David Otserver em (Resolvido)Como colocar Sistema de Matar Player em PoketibiaVocê deve colocar na sua pasta Creaturescripts.
e também deve criar uma tag no arquivo Creaturescripts.xml
-
Henriquegb deu reputação a xWhiteWolf em Tibia Guitar Hero [0.3.6~0.4]Fala pessoal, hoje vim trazer pra vocês um sistema que eu desenvolvi em outro fórum e decidi trazer pra cá
Chega de falatório e vamos direto aos negócios:
Introdução: O sistema em si é uma cópia dos jogos de ritmo (GuitarFreaks, Band Hero, Rocksmith e o próprio Guitar Hero). Neste jogo pequenas notas irão cair pela tela até atingir um local especial, onde você poderá usar as teclas (Shift + 7, Shift + 8, Shift + 9, ou apenas 7, 9 e 9 [com Num Lock desativado]) para escolher as direções que as notas estão afim de "ativá-las". Uma vez ativada a nota ela será "queimada" e será considerado 1 acerto. Caso você não consiga ativar a nota e ela passar direto, um efeito de fumaça indicará o "Miss", o mesmo vale para se você tentar ativar uma região sem notas.
Sistema de pontuação: Haverão 3 classificadores estatísticos para cada música tocada, sendo eles:
Notas acertadas: O principal fator de ponto, ele que definirá seu recorde e o valor máximo q ele pode assumir será o número de notas da música.
Movimentos errados: Quantidade de movimentos que você fez para alguma região que não possuia notas, conta como pontuação punitiva.
Notas passadas/erradas: Quantidade de notas que você deixou escapar, note que as notas acertadas + notas passadas compõe o número total de notas da música.
Por enquanto o sistema não possui nenhum preço para se jogar mas também não possui nenhuma recompensa, fiz com o intuito de ser apenas um mini game divertido dentro do Tibia. Porém o código é livre e está disponibilizado aqui embaixo pra qualquer um modificar como desejar.
Video explicativo: Dificuldades: O mini game possui 3 dificuldades, porém essa quantidade é tão configurável quanto as pré definições de cada dificuldade. Além da quantidade de notas ser diferente, a velocidade com que elas descem e consequentemente o tempo que você tem pra acertá-las fica diminuido.
Diferenciais: Um forte diferencial desse sistema é que ele foi feito seguindo todas as regras possíveis pra melhorar seu desempenho, desde funções recursivas leves até separação em funções encapsuladas que carregam apenas as informações necessárias. O sistema contém também algumas seguranças que serão explicadas mais abaixo juntamente com o código para prevenir bugs e garantir diversão sem dores de cabeça!
Instalação (Map Editor): Primeiramente faça uma área parecida com essa daqui:
Não precisa ser igualzinha, apenas seguir a mesma proporção
Agora use a ferramenta de No-Logout para setar os quadradinhos que contém UID e UID2 escritos como No-Logout, isso vai impedir que players desloguem e fiquem presos dentro da sala (se eles derem exit, quando eles relogarem estarão do lado de fora da sala)
Ainda olhando a foto acima, coloque 42320 nos pisos que estão escritos UID, e 42319 no piso que contém UID2.
Nas alavancas, coloque uid 2819 em todas elas e coloque actionid 101 para a alavanca do fácil, 102 na alavanca do médio e 103 na do dificil;
A regra é sempre 100 + dificuldade, como nós estamos utilizando apenas 3 será do 101 ao 103.
Note que se você esquecer ou colocar uma dificuldade não existente o sistema adotará a dificuldade 1 como padrão para aquela alavanca.
Se chegou até aqui, meus parabéns. Muito provável que você tenha feito tudo certo. Agora vamos à parte do código.
Instalação (scripts): Em actions.xml insira essa linha
<action uniqueid="2819" event="script" value="GHtest.lua"/> Agora em data/actions/scripts crie um arquivo com extensão.lua e chameo de GHtest. Insira o seguinte bloco de instruções dentro dele:
<movevent type="StepIn" uniqueid="42320;42319" event="script" value="GHTestmov.lua"/> Por fim crie um arquivo chamado GHTestmov.lua em data/movements/scripts e preencha seu conteúdo com as linhas abaixo:
Configurando seu sistema (básico):
Para as pessoas que querem configurar apenas as coisas básicas, você pode fazê-lo nas primeiras linhas de cada script (actions/movements) ou alterando diretamente na lib, irei ensinar passo a passo aqui oque significa cada coisa.
Alterando a lib As coisas básicas que podem ser alteradas na lib são as seguintes:
dif = { -- [dificuldade] = notas que serao tocadas (nil = vazio, 0 = primeira posicao, 1 = segunda e 2 = terceira) [1] = {nil,nil,0,1,2,nil,nil,2,1,1,0,0,2,0,1}, [2] = {nil,nil,0,1,1,2,1,1,0,0,2,0,1,nil,1,2,1,1,0,0,2,0,1}, [3] = {nil,nil,0,nil,1,nil,1,1,0,0,2,0,1,1,1,nil,0,2,1,1,0,0,2,1,1,0,nil,2,2,1,1,1,1,2} } delay = { -- delay entre cada nota de acordo com a dificuldade [dificuldade] = delay [1] = 500, [2] = 400, [3] = 300 } recorde = { -- salva os recordes de cada dificuldade separadamente [1] = 12724, [2] = 12725, [3] = 12726 } dif separa como será cada música de cada dificuldade, as notas sempre serão nesse exato formato. nil significa que não estarei usando posição nenhuma naquela linha, 0 significa a primeira posição (nota verde), 1 significa segunda opção (nota vermelha) e 2 significa terceira opção (nota azul). Eu aconselho a começar todas as músicas com 2 ou mais 'nil' para dar tempo de o player entender que vai começar. A distribuição que eu usei foi meio que aleatória então sinta-se a vontade pra mudar tanto o tamanho das musicas quanto a variedade de notas.
delay é a tabela que oganiza os delays de cada dificuldade, isso significa que para a dificuldade 1(fácil) nós temos 500 milisegundos para cada mudança de nota (1000 milisegundos = 1 segundo), ou seja, a cada 2 passadas de nota temos 1 segundo dentro da sala. No modo hard a cada 300 milisegundos mudamos a nota, deixando o jogo muito mais rápido e dificil.
recorde é a tabela que possui os storages que irão salvar os recordes nas respectivas dificuldades.
Alterando actions local storage_point = 12721 -- storage que salva os pontos local storage_erradas = 12722 -- storage que salva as notas erradas local storage_passadas = 12723 -- storage que salva as notas que passaram Apenas mude os storages
Alterando movements local itemid = 1680 --- coloque o id da nota do meio local npos = {x = 141, y = 51, z = 7} -- posicao que ira nascer a primeira nota local storage_point = 12721 -- storage que salva os pontos local storage_erradas = 12722 -- storage que salva as notas erradas local storage_passadas = 12723 -- storage que salva as notas que passaram aconselho mexer somente nos storages, mantendo igual à action.
Só abra o spoiler abaixo se você estiver descontente com a forma que seu código roda e tiver certeza absoluta de que você tem o conhecimento necessário para alterar as coisas que vou explicar.
-
Henriquegb recebeu reputação de Reds em Regen Soulverifiquei aqui, e o local onde determina esse ganho de souls realmente é em player.CPP
pra ser mais especifico, este codigo:
//soul regeneration if(gainExp >= level) { if(Condition* condition = Condition::createCondition( CONDITIONID_DEFAULT, CONDITION_SOUL, 4 * 60 * 1000)) { condition->setParam(CONDITIONPARAM_SOULGAIN, vocation->getGainAmount(GAIN_SOUL)); condition->setParam(CONDITIONPARAM_SOULTICKS, (vocation->getGainTicks(GAIN_SOUL) * 1000)); addCondition(condition); } } se for realmente editar suas sourcers, sugiro que dê uma olhada também nos outros codigos que também citam as souls (condition.cpp, condition.h e muitos outros) só pra garantir que não dê nenhum conflito ( o que é pouco provavel, porque o pouco que busquei conclui que o que vc pediu se resolve somente nesse codigo ai que se localiza em player.cpp)
Boa sorte.
--edit
caso isso resolva seu problema escolha como melhor resposta, a resposta do Vankk. afinal o conhecimento do assunto era dele.
boa sorte².
-
Henriquegb deu reputação a Wakon em (Resolvido)Script infuncional (com e sem erro no distro)Fiz um aqui pra você, veja se lhe agrada:
local storage, escudo = 40955, 2520 function onCastSpell(cid, var) local slot1, slot2 = getPlayerSlotItem(cid, CONST_SLOT_RIGHT).itemid, getPlayerSlotItem(cid, CONST_SLOT_LEFT).itemid local target, pos = getCreatureTarget(cid), getCreaturePosition if isPlayer(target) then if slot1 == escudo or slot2 == escudo then setPlayerStorageValue(target, storage, 1) doCreatureSay(target, 'Charged!', TALKTYPE_MONSTER) doSendMagicEffect(pos(target), CONST_ME_STUN) addEvent(function() setPlayerStorageValue(target, storage, -1) doCreatureSay(target, 'Charged lost!', TALKTYPE_MONSTER) doSendMagicEffect(pos(target), CONST_ME_MAGIC_GREEN) end, 4000) else doSendMagicEffect(pos(cid), CONST_ME_POFF) return doPlayerSendCancel(cid, 'Você só pode usar esta magia com o escudo "'.. getItemNameById(escudo) ..'" equiipado.') and false end else doSendMagicEffect(pos(cid), CONST_ME_POFF) return doPlayerSendCancel(cid, 'Você só pode usar em jogadores.') and false end return true end
-
Henriquegb deu reputação a Wakon em (Resolvido)Script infuncional (com e sem erro no distro)Sim é possível declarar um else para cada if, sobre a função no meio da frase, acho que da maneira que eu coloquei deu a entender errado, coloquei essas aspas para citar o nome do shield na frase, então não é necessário colocar as aspas, você abre o texto utilizando ' ou " e caso queira adicionar uma função no meio você fecha ' ou ", adiciona a .. função .., abre o texto de novo e termina de digitar, no final fecha novamente. Exemplo:
doPlayerSendCancel(cid, "Aqui é o texto e fecha ".. função aqui .." abre novamente e fecha.")
ou utilizando apenas '
doPlayerSendCancel(cid, 'Aqui é o texto e fecha '.. função aqui ..' abre novamente e fecha.')
Agora sobre o addEvent, não, pois o addEvent já é "iniciado" assim que manda a magia, sendo assim target do addEvent será o que você lançou a magia.
Espero que tenha entendido, não sou muito bom em explicar.
-
Henriquegb deu reputação a xWhiteWolf em New Library v. 1.2Fala galera, hoje vim trazer pra vocês uma nova biblioteca de funções que eu venho desenvolvendo, pretendo ir atualizando esse tópico constantemente sempre adicionando funções novas e explicando a utilização delas. Algumas funções que eu coloquei aqui estão presentes na OTAL também, porém algumas eu fiz pequenas correções de forma que essa lib poderia facilmente substituir a OTAL sem grandes problemas (pelo menos se você utilizava apenas as funções básicas da otal)
Todas as funções que não tem -- nome do autor do lado dela foram feitas por mim, xWhiteWolf ou Night Wolf (NW). O restante delas são créditos dos devidos autores, apenas coloquei pois considero funções vitais no server de cada um. Crie um arquivo em data/lib chamado 075 - White Wolf Functions.lua e coloque o seguinte código dentro:
Agora eu vou explicar oque cada função faz porque de nada adianta lançar uma lib e não explicar oque ela faz não é mesmo? hahaha
Obs inicial: quando uma função tiver em seus parametros um [] significa que oque está dentro do colchetes não é um parâmetro obrigatório.
Como usar: doShowTimeByPos(cid, getCreaturePosition(cid), 20, 20)
Irá fazer uma contagem regressiva na posição que o player se encontra começando de 20 e mandando a mensagem na mesma cor da fala dos monstros.
Essa função é bem útil em actions/spells para fazer contagem de tempo em runas como a magic wall e ver quanto tempo falta pra magic wall sumir)
Obs: Espero que ajude bastante pessoas a entender sobre funções, eu utilizei cid como o principal uid das funções nos exemplos mas você pode muito bem utilizar outros uids, fica a critério seu.
Qualquer dúvida comentem abaixo que eu vou tentar ajudar da melhor maneira.
Ahhh, isso daí foi testado em 8.54 mas deve funcionar em quase todas as versões que tenham as funções básicas do TFS.
EDIT: Pessoal, agora é sério, essa lib tem fácil umas 600 linhas, das quais umas 500 eu devo ter codado sozinho (na mão, linha por linha). Eu tive todo o trabalho de testar cada uma delas e oque eu peço é o mínimo de gratidão e respeito. Se eu te ajudei clique em Gostei, se você tiver alguma dúvida eu to me colocando a disposição de responder qualquer coisa relacionada ao tópico, mesmo que você não saiba nem oque é uma lib apenas venha aqui e escreva sua dúvida.
EDIT 2: Duas novas funções adicionas, espero que gostem!
EDIT 3: Três novas funções adicionadas juntamente com suas respectivas explicações.
-
Henriquegb recebeu reputação de leonardosantos em {PEDIDO}Tentei fazer aqui, se funcionar...
pelo menos no script live, não apontou erros...
Obs: mecho a pouco tempo, grandes chances de estar não funcional.
-
Henriquegb recebeu reputação de pupukin em COMO ENTRAR NOS CODIGOS DO TIBIASe você estiver falando dos codigos internos
provavelmente estamos falando de Source,
dê uma pesquisada, acredito que existam bons tutoriais aqui no forum sobre descompilar e compilar.
mas se estiver falando do codigos do tibia (cliente), um editor Hex já consegue fazer o serviço.
boa sorte
-
Henriquegb recebeu reputação de arthurabreu em Adicionar vocaçõesNah, você disse que nenhuma vocação aparece??
verifique se nos eu config.lua tem esta linha
"newPlayerChooseVoc = true"
se por false, nenhuma vocation será escolhida,
se por true o player poderá escolher, as vocations que forem configuradas no vocations.xml
-
Henriquegb recebeu reputação de lucasromero em (Resolvido)[Dúvida] Como que funciona essas 3 funçõesif getPlayerLookDir(cid) == 0 then
se não me engano
0
1
2
3
provavelmente são as 4 direções, esperemos que um scripter mais experiente confirme.
Edit:
Segundo a Lib
-
Henriquegb deu reputação a Alencar123 em (Resolvido)exhaustion.check and exhaustion.setPara adicionar cooldown primeiramente adicione estes locais no script:
local tempo = 900 -- Tempo para usar novamente (em segundos) local storage = 23585 -- storage pra verificar se o player já pode usar novamente Depois disso, adicione isso a seguir depois da linha function:
if exhaustion.check(cid, storage) then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_RED, "Mensagem dizendo ao player que ele tem que esperar") return true end Agora você adiciona isso junto da função principal do script:
exhaustion.set(cid, storage, tempo) Exemplo:
function onSay(cid, words, param) local storage = 23585 local tempo = 3600 local cidade = getPlayerTown(cid) local pos = getTownTemplePosition(cidade) if exhaustion.check(cid, storage) then doPlayerSendTextMessage(cid, 22, "Você não tem dinheiro suficiente, espere passar o tempo de 1 hora depois da ultima vez que você usou para usar novamente!") return true end doTeleportThing(cid, pos) exhaustion.set(cid, storage, tempo) doSendAnimatedText(getThingPosWithDebug(cid), "Desbugado!", COLOR_BURN) doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_RED, "Voce sera kikado!") addEvent(doRemoveCreature, 2500, cid) end @Deu um erro aqui e publicou dois posts mals ai.
-
Henriquegb deu reputação a Killua em (Resolvido)Script não funcionalVocê cometeu muitos erros... Vou te ajudar
1 - Pra declarar uma variável local vc usa 'local' (não 'Local') seguido por um '=' e o valor que vc quer armazenar.
2 - Você usou a função getPlayerSlotItem(cid, slot) entre '', fazendo ela ser somente uma string e não uma função.
3 - A variável global 'RING' provavelmente não foi declarada em nenhum lugar, os servidores normalmente vem com a variável CONST_SLOT_RING, que se refere ao slot de id 9.
4 - getPlayerSlotItem(cid, slot) vai te retornar uma tabela com várias informações sobre o item, (exemplos: itemid, uid, itemtype). Quando você vai fazer a comparação em if isInArray({2207,2208,2209,2210,2211}, Ringbase) then você deve especificar quais das informações vc quer usar. No caso vc precisaria usar o id, portanto ficaria assim: if isInArray({2207,2208,2209,2210,2211}, Ringbase.itemid) then
5 - A função doPlayerRemoveItem(cid, item) precisa de um uniqueid (quase o mesmo caso do item 4), então você deveria usar: doPlayerRemoveItem(cid, Ringbase.uid, 1)
6 - elseif getPlayerSlotItem(cid, RING) == 2216 then Além de estar totalmente errada é desnecessária pq vc já guardou o valor de getPlayerSlotItem(cid, slot) em um variável. Além disso, vc está tentando comparar uma tabela com um número. O correto seria: elseif Ringbase.itemid == 2216 then
7 - Não há necessidade de ficar usando esses returns dentro do escopo, os ifs, elseifs e elses já estão fazendo esse trabalho
8 - Você não retornou true a function onSay(cid, words, param), por conta disso, sempre que o jogador usar o comando ele vai aparecer como fala.
Espero que vc leia tudo que eu falei e que isso te ajude a aprender.
Aqui está o script corrigido:
function onSay(cid, words, param) local Ringbase = getPlayerSlotItem(cid, CONST_SLOT_RING) if isInArray({2207,2208,2209,2210,2211}, Ringbase.itemid) then doPlayerRemoveItem(cid, Ringbase.uid, 1) doPlayerAddItem(cid, 2216, 1) elseif Ringbase.itemid == 2216 then doPlayerSendCancel(cid, "Você já esta nesta forma!") else doPlayerSendCancel(cid, "Você precisa do transformador equipado!") end return true end -
Henriquegb deu reputação a xWhiteWolf em (Resolvido)Element ArrowdoPlayerRemoveItem(cid, arrowice, 1) repete essa linha antes de cada return true mudando somente o arrowice
-
Henriquegb deu reputação a xWhiteWolf em (Resolvido)Element Arrowlocal arrowice = 7839 local arrowenergy = 7838 local arrowfire = 7840 local arrowearth = 7850 -- =============== COMBAT VARS =============== -- Areas/Combat for 100ms local combat1_Ice_Area_Hit = createCombatObject() setCombatParam(combat1_Ice_Area_Hit, COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) setCombatParam(combat1_Ice_Area_Hit, COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) setCombatArea(combat1_Ice_Area_Hit,createCombatArea({{0, 1, 0}, {1, 2, 1}})) setCombatFormula(combat1_Ice_Area_Hit, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 0ms local combat0_Ice_Arrow = createCombatObject() setCombatParam(combat0_Ice_Arrow, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SHIVERARROW) setCombatParam(combat0_Ice_Arrow, COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) setCombatArea(combat0_Ice_Arrow,createCombatArea({{1}, {0}, {0}, {0}, {2}})) setCombatFormula(combat0_Ice_Arrow, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) local dfcombat0_Ice_Arrow = {CONST_ANI_SHIVERARROW,0,5} -- Areas/Combat for 200ms local combat2_Ice_Area_Hit = createCombatObject() setCombatParam(combat2_Ice_Area_Hit, COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) setCombatParam(combat2_Ice_Area_Hit, COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) setCombatArea(combat2_Ice_Area_Hit,createCombatArea({{0, 1, 0}, {1, 1, 1}, {1, 0, 1}, {0, 2, 0}})) setCombatFormula(combat2_Ice_Area_Hit, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 300ms local combat3_Ice_Area_Hit = createCombatObject() setCombatParam(combat3_Ice_Area_Hit, COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) setCombatParam(combat3_Ice_Area_Hit, COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) setCombatArea(combat3_Ice_Area_Hit,createCombatArea({{1, 1, 1}, {1, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 2, 0}})) setCombatFormula(combat3_Ice_Area_Hit, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- =============== COMBAT VARS =============== -- Areas/Combat for 200ms local combat2_Fire_Area = createCombatObject() setCombatParam(combat2_Fire_Area, COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) setCombatParam(combat2_Fire_Area, COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) setCombatArea(combat2_Fire_Area,createCombatArea({{0, 1, 0}, {1, 1, 1}, {1, 0, 1}, {0, 2, 0}})) setCombatFormula(combat2_Fire_Area, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 100ms local combat1_Fire_Area = createCombatObject() setCombatParam(combat1_Fire_Area, COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) setCombatParam(combat1_Fire_Area, COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) setCombatArea(combat1_Fire_Area,createCombatArea({{0, 1, 0}, {1, 2, 1}})) setCombatFormula(combat1_Fire_Area, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 0ms local combat0_Fire_Arrow = createCombatObject() setCombatParam(combat0_Fire_Arrow, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FLAMMINGARROW) setCombatParam(combat0_Fire_Arrow, COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) setCombatArea(combat0_Fire_Arrow,createCombatArea({{1}, {0}, {0}, {0}, {2}})) setCombatFormula(combat0_Fire_Arrow, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) local dfcombat0_Fire_Arrow = {CONST_ANI_FLAMMINGARROW,0,5} -- Areas/Combat for 300ms local combat3_Fire_Area = createCombatObject() setCombatParam(combat3_Fire_Area, COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) setCombatParam(combat3_Fire_Area, COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) setCombatArea(combat3_Fire_Area,createCombatArea({{1, 1, 1}, {1, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 2, 0}})) setCombatFormula(combat3_Fire_Area, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- =============== COMBAT VARS =============== -- Areas/Combat for 200ms local combat2_Lightning_Area_Hit = createCombatObject() setCombatParam(combat2_Lightning_Area_Hit, COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) setCombatParam(combat2_Lightning_Area_Hit, COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) setCombatArea(combat2_Lightning_Area_Hit,createCombatArea({{0, 1, 0}, {1, 1, 1}, {1, 0, 1}, {0, 2, 0}})) setCombatFormula(combat2_Lightning_Area_Hit, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 100ms local combat1_Lightning_Area_Hit = createCombatObject() setCombatParam(combat1_Lightning_Area_Hit, COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) setCombatParam(combat1_Lightning_Area_Hit, COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) setCombatArea(combat1_Lightning_Area_Hit,createCombatArea({{0, 1, 0}, {1, 2, 1}})) setCombatFormula(combat1_Lightning_Area_Hit, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 0ms local combat0_Lightning_Arrow = createCombatObject() setCombatParam(combat0_Lightning_Arrow, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FLASHARROW) setCombatParam(combat0_Lightning_Arrow, COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) setCombatArea(combat0_Lightning_Arrow,createCombatArea({{1}, {0}, {0}, {0}, {2}})) setCombatFormula(combat0_Lightning_Arrow, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) local dfcombat0_Lightning_Arrow = {CONST_ANI_FLASHARROW,0,5} -- Areas/Combat for 300ms local combat3_Lightning_Area_Hit = createCombatObject() setCombatParam(combat3_Lightning_Area_Hit, COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) setCombatParam(combat3_Lightning_Area_Hit, COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) setCombatArea(combat3_Lightning_Area_Hit,createCombatArea({{1, 1, 1}, {1, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 2, 0}})) setCombatFormula(combat3_Lightning_Area_Hit, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- =============== COMBAT VARS =============== -- Areas/Combat for 200ms local combat2_Brush = createCombatObject() setCombatParam(combat2_Brush, COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) setCombatParam(combat2_Brush, COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) setCombatArea(combat2_Brush,createCombatArea({{0, 1, 0}, {1, 1, 1}, {1, 0, 1}, {0, 2, 0}})) setCombatFormula(combat2_Brush, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 0ms local combat0_Earth_Arrow = createCombatObject() setCombatParam(combat0_Earth_Arrow, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTHARROW) setCombatParam(combat0_Earth_Arrow, COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) setCombatArea(combat0_Earth_Arrow,createCombatArea({{1}, {0}, {0}, {0}, {2}})) setCombatFormula(combat0_Earth_Arrow, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) local dfcombat0_Earth_Arrow = {CONST_ANI_EARTHARROW,0,5}local combat0_Brush = createCombatObject() setCombatParam(combat0_Brush, COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) setCombatParam(combat0_Brush, COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) setCombatArea(combat0_Brush,createCombatArea({{0, 1, 0}, {1, 2, 1}})) setCombatFormula(combat0_Brush, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- Areas/Combat for 300ms local combat3_Brush = createCombatObject() setCombatParam(combat3_Brush, COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) setCombatParam(combat3_Brush, COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) setCombatArea(combat3_Brush,createCombatArea({{1, 1, 1}, {1, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 2, 0}})) setCombatFormula(combat3_Brush, COMBAT_FORMULA_LEVELMAGIC, -2, 60, -2, 60) -- =============== CORE FUNCTIONS =============== local function RunPart(c,cid,var,dirList,dirEmitPos,startDir) -- Part if (isCreature(cid)) then doCombat(cid, c, var) if (dirList ~= nil) then -- Emit distance effects local i = 2; while (i < #dirList) do if (startDir == 0) then -- N doSendDistanceShoot(dirEmitPos,{x=dirEmitPos.x-dirList[i],y=dirEmitPos.y-dirList[i+1],z=dirEmitPos.z},dirList[1]) elseif (startDir == 2) then -- S doSendDistanceShoot(dirEmitPos,{x=dirEmitPos.x+dirList[i],y=dirEmitPos.y+dirList[i+1],z=dirEmitPos.z},dirList[1]) elseif (startDir == 1) then -- E doSendDistanceShoot(dirEmitPos,{x=dirEmitPos.x+dirList[i+1],y=dirEmitPos.y+dirList[i],z=dirEmitPos.z},dirList[1]) else -- W / Something weird happened doSendDistanceShoot(dirEmitPos,{x=dirEmitPos.x-dirList[i+1],y=dirEmitPos.y-dirList[i],z=dirEmitPos.z},dirList[1]) end i = i + 2 end end end end function onCastSpell(cid, var) local startPos = getCreaturePosition(cid) local startDir = getCreatureLookDirection(cid) if isInArray({arrowice}, getPlayerSlotItem(cid, 10).itemid) then addEvent(RunPart,100,combat1_Ice_Area_Hit,cid,var) RunPart(combat0_Ice_Arrow,cid,var,dfcombat0_Ice_Arrow,startPos,startDir) addEvent(RunPart,200,combat2_Ice_Area_Hit,cid,var) addEvent(RunPart,300,combat3_Ice_Area_Hit,cid,var) return true elseif isInArray({arrowfire}, getPlayerSlotItem(cid, 10).itemid) then addEvent(RunPart,200,combat2_Fire_Area,cid,var) addEvent(RunPart,100,combat1_Fire_Area,cid,var) RunPart(combat0_Fire_Arrow,cid,var,dfcombat0_Fire_Arrow,startPos,startDir) addEvent(RunPart,300,combat3_Fire_Area,cid,var) return true elseif isInArray({arrowenergy}, getPlayerSlotItem(cid, 10).itemid) then addEvent(RunPart,200,combat2_Lightning_Area_Hit,cid,var) addEvent(RunPart,100,combat1_Lightning_Area_Hit,cid,var) RunPart(combat0_Lightning_Arrow,cid,var,dfcombat0_Lightning_Arrow,startPos,startDir) addEvent(RunPart,300,combat3_Lightning_Area_Hit,cid,var) return true elseif isInArray({arrowearth}, getPlayerSlotItem(cid, 10).itemid) then addEvent(RunPart,200,combat2_Brush,cid,var) RunPart(combat0_Earth_Arrow,cid,var,dfcombat0_Earth_Arrow,startPos,startDir) RunPart(combat0_Brush,cid,var) addEvent(RunPart,300,combat3_Brush,cid,var) return true else doSendMagicEffect(startPos, 2) doPlayerSendCancel(cid, "You need to have elemental arrows on your ammunition slot.") return false end end