Histórico de Curtidas
-
Milbradt deu reputação a Wise em math.percent {Cálculo Percentual}Eis que trago mais uma função à biblioteca matemática de Lua, a math.percent.
Sendo objetivo, ela calcula o percentual de um valor numérico, independentemente desse valor ser um inteiro ou decimal.
math.percent = function (value, percentage) -- Developed by Wise ~ TibiaKing.com return tonumber(value) and tonumber(percentage) and math.abs(tonumber(string.format('%.f', tostring(percentage * (value/100))))) or nil end
Exemplo de um cálculo:
Mensagem maldita
"Você atingiu 80% da sua franquia diária de 30MB. Ao atingir 100%, sua navegação será bloqueada."
E agora, brother? Quantos MB eu usei?
math.percent(30, 80) -- (valor númerico, %) 24
Enfim, se for disponibilizar este script em outro meio, deixe meu nick nos créditos.
;]
-
Milbradt deu reputação a Anuudek em [TFS 1.x] Compilando OTServ em Ubuntu/DebianCompilando OTServer em Linux
(Testado em Debian7 e Ubuntu14.04)
Olá TibiaKing! Venho trazendo um tutorial muito útil para aqueles que não faz a mínima ideia de como compilar um OT de uma forma simples! Funciona somente com sources de TFS 1.x
Primeiro de tudo, você tem que ter a Source e o OT que deseja compilar. Então 'LETS GO'!
Programas para instalar PuTTY para conectar via SSH. (aqui) FilleZila Client para ter acesso aos arquivos da máquina. (aqui)
Começando Ao instalar os programas, abra o Fillezila. Em Host, Nome de Usuário, Senha, Port (padrão 22), coloque oque te passaram pelo email quando comprou o Dedicado Ao logar, volte uma pasta, renomeie a pasta do seu ot para "otserv" e coloque a pasta "sources" dentro da pasta do seu ot, e mova para o Fillezila, ficando em /otserv Ao mover basta compilar, configurar e deixar online.
Abrindo o PuTTY Agora você precisará usar o PuTTY. Abra ele e siga as imagens abaixo:
----
----
----
-----
Instalando arquivos necessários Bom, depois que o Shell estiver aberto, vamos instalar os arquivos necessários para compilar, incluindo Apache e MySQL. Com o Shell aberto execute este comando para atualizar o sistema: apt-get update (OBS: NUNCA USE #apt-get upgrade)
Logo depois execute:
apt-get install cmake build-essential liblua5.2-dev libgmp3-dev libmysqlclient-dev libboost-system-dev apache2 php5 libapache2-mod-php5 php5-mysql mysql-server phpmyadmin Após carregar tudo, irá pedir abrir duas telas com caixas de seleção, a primeira você marque "apache2" e dê enter, na segunda você seleciona "yes", e coloque a senha do MYSQL.
Compilando seu OTServ Chegou a hora do tão esperando momento! Para compilar seu otserv navegue até a pasta das sources, executa o comando de compilar, e mova o arquivo "tfs" para a pasta do seu OT. Seguindo estes comandos: cd otserv/sources mkdir build cd build cmake .. make mv tfs /otserv
Pronto, OT compilado, fácil né? Para abrir certifique que seu config.lua está de acordo com a sua necessidade.
Deixando seu OTServ online Depois de compilar, configurar o seu OTServ do jeito que você quiser, é hora de deixar seu OT online! Para deixar o OT online, você precisa ir para pasta do seu otserv e executar o comando #./tfs Siga os comandos: cd /otserv ./tfs
Pronto! Só esperar carregar e SERVER ON!
Outros e dicas A pasta para colocar seu site fica em /var/www Se quiser deixar seu servidor online e com o Plutty fechado, antes de abrir execute este comando apt-get install screen
Logo depois, use este comando, depois só abrir o servidor normalmente!
screen -S tibia (OBS: o -S dessa palavra tem diferença, se você colocar o -S minúsculo (-s), haverá diferença de comando.
Se quiser fechar o servidor, só digitar este comando de depois apertar CTRL+C.
screen -x
Então galera, o tutorial foi esse! Eu também achava que era MUITO complicado, mas é só isso!
Se você gostou não esqueça de reputar, e até mais!
(Créditos pelas imagens: @Natanael Beckman)
-
Milbradt deu reputação a Bluetooth em Compilando TFS 1.x linux Debian 8Instale as lib
# apt-get install git cmake build-essential liblua5.2-dev libgmp3-dev libmysqlclient-dev libboost-system-dev execute os comandos
$ cd /pasta_do_tfs $ mkdir build && cd build $ cmake .. $ make
pronto sua distro esta na pasta build nomeada de tfs
-
Milbradt deu reputação a xWhiteWolf em All bugs OTSERV - REVELADO ! -testei todos após fazer as modificações que o pessoal orienta a fazer na source.
https://github.com/otland/forgottenserver/pull/1858/files/3fde26a3685711c45f6113f40d1a11a3adaccf87..138f3a0ee7b082717e13f077716d718a89ae758d
https://github.com/otland/forgottenserver/issues/1846#issuecomment-231544154
-
Milbradt recebeu reputação de eliasferro em [8.54] Naruto Online Shinobiuhauha, melhor nem comentar muita coisa..
mas já exite um tópico com o mesmo servidor postado aqui!
Ele também é uma versão acima dessa.
-
Milbradt deu reputação a Yugami em Susanoo Madarabem sei que não é susanoo la essas coisas,tambem sei q ele é feio e esta um tanto inacabado... só fis aqui só pra ver se ia fica bom ... peguei 1 spriter do madara 32x32 do meu client e comecei a desenha ao lado dele e deu nisso ai,quem quiser usar é só baixar o link ta abaixo,quem quiser deixa sua Opinião sobre como ela estar,oque precisa melhorar... deixa ai que eu vou ler :biggrin: .
ela não esta cortada só vocês colocarem o fundo roxo e corta em 32x32 e colocarem no client e editar a ordem dos efeitos vai fica mais ou menos igual acima :tongue: . Download
-
Milbradt deu reputação a Guilherme em [C++] Opcode versão 8.54+Por: BananaFight > DragonElement
Adaptação pra source 8.54+
LEMBRE-SE, ISSO É NA SOURCE DO SERVIDOR
Vamos ao código.
protocolgame.h
Embaixo de
void AddShopItem(NetworkMessage_ptr msg, const ShopInfo item); Adicione
void parseExtendedOpcode(NetworkMessage& msg); void sendExtendedOpcode(uint8_t opcode, const std::string& buffer); protocolgame.cpp
Embaixo de
uint32_t key[4] = {msg.GetU32(), msg.GetU32(), msg.GetU32(), msg.GetU32()}; enableXTEAEncryption(); setXTEAKey(key); Adicione
// notifies to otclient that this server can receive extended game protocol opcodes if(operatingSystem >= CLIENTOS_OTCLIENT_LINUX) sendExtendedOpcode(0x00, std::string()); Embaixo de
void ProtocolGame::AddShopItem(NetworkMessage_ptr msg, const ShopInfo item) { const ItemType& it = Item::items[item.itemId]; msg->AddU16(it.clientId); if(it.isSplash() || it.isFluidContainer()) msg->AddByte(fluidMap[item.subType % 8]); else if(it.stackable || it.charges) msg->AddByte(item.subType); else msg->AddByte(0x01); msg->AddString(item.itemName); msg->AddU32(uint32_t(it.weight * 100)); msg->AddU32(item.buyPrice); msg->AddU32(item.sellPrice); } Adicione
void ProtocolGame::parseExtendedOpcode(NetworkMessage& msg) { uint8_t opcode = msg.GetByte(); std::string buffer = msg.GetString(); // process additional opcodes via lua script event addGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer); } void ProtocolGame::sendExtendedOpcode(uint8_t opcode, const std::string& buffer) { // extended opcodes can only be send to players using otclient, cipsoft's tibia can't understand them NetworkMessage_ptr msg = getOutputBuffer(); if(msg) { TRACK_MESSAGE(msg); msg->AddByte(0x32); msg->AddByte(opcode); msg->AddString(buffer); } } Embaixo de
case 0x1E: // keep alive / ping response parseReceivePing(msg); break;
Adicione
case 0x32: // otclient extended opcode parseExtendedOpcode(msg); break; enums.h
Embaixo de
enum GuildLevel_t { GUILDLEVEL_NONE = 0, GUILDLEVEL_MEMBER, GUILDLEVEL_VICE, GUILDLEVEL_LEADER }; Substitua o OperatingSystem por este
enum OperatingSystem_t { CLIENTOS_LINUX = 0x01, CLIENTOS_WINDOWS = 0x02, CLIENTOS_OTCLIENT_LINUX = 0x0A, CLIENTOS_OTCLIENT_WINDOWS = 0x0B, CLIENTOS_OTCLIENT_MAC = 0x0C, };/
player.h
Embaixo de
void sendCreatureShield(const Creature* creature) Adicione
void sendExtendedOpcode(uint8_t opcode, const std::string& buffer) {if(client) client->sendExtendedOpcode(opcode, buffer);} luascript.cpp
Embaixo de
void LuaScriptInterface::registerFunctions() { Adicione
//doSendPlayerExtendedOpcode(cid, opcode, buffer) lua_register(m_luaState, "doSendPlayerExtendedOpcode", LuaScriptInterface::luaDoSendPlayerExtendedOpcode); Embaixo de
SHIFT_OPERATOR(int32_t, LeftShift, <<) SHIFT_OPERATOR(int32_t, RightShift, >>) SHIFT_OPERATOR(uint32_t, ULeftShift, <<) SHIFT_OPERATOR(uint32_t, URightShift, >>) #undef SHIFT_OPERATOR Adicione
int32_t LuaScriptInterface::luaDoSendPlayerExtendedOpcode(lua_State* L) { //doSendPlayerExtendedOpcode(cid, opcode, buffer) std::string buffer = popString(L); int opcode = popNumber(L); ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) { player->sendExtendedOpcode(opcode, buffer); lua_pushboolean(L, true); } lua_pushboolean(L, false); return 1; } luascript.h
Embaixo de
virtual void registerFunctions(); Adicione
static int32_t luaDoSendPlayerExtendedOpcode(lua_State* L); creatureevent.h
.
Substitua
CREATURE_EVENT_PREPAREDEATH Por isso
CREATURE_EVENT_PREPAREDEATH, CREATURE_EVENT_EXTENDED_OPCODE // otclient additional network opcodes Embaixo de
uint32_t executePrepareDeath(Creature* creature, DeathList deathList); Adicione
uint32_t executeExtendedOpcode(Creature* creature, uint8_t opcode, const std::string& buffer); creatureevent.cpp
Embaixo de
else if(tmpStr == "death") m_type = CREATURE_EVENT_DEATH; Adicione
else if(tmpStr == "extendedopcode") m_type = CREATURE_EVENT_EXTENDED_OPCODE; Embaixo de
case CREATURE_EVENT_DEATH: return "onDeath"; Adicione
case CREATURE_EVENT_EXTENDED_OPCODE: return "onExtendedOpcode"; Embaixo de
case CREATURE_EVENT_DEATH: return "cid, corpse, deathList"; Adicione
case CREATURE_EVENT_EXTENDED_OPCODE: return "cid, opcode, buffer"; Embaixo de
std::cout << "[Error - CreatureEvent::executeFollow] Call stack overflow." << std::endl; return 0; } } Adicione
uint32_t CreatureEvent::executeExtendedOpcode(Creature* creature, uint8_t opcode, const std::string& buffer) { //onExtendedOpcode(cid, opcode, buffer) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; scriptstream << "local opcode = " << (int)opcode << std::endl; scriptstream << "local buffer = " << buffer.c_str() << std::endl; scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[35]; sprintf(desc, "%s", player->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); lua_pushnumber(L, opcode); lua_pushlstring(L, buffer.c_str(), buffer.length()); bool result = m_interface->callFunction(3); m_interface->releaseEnv(); return result; } } else { std::cout << "[Error - CreatureEvent::executeRemoved] Call stack overflow." << std::endl; return 0; } } game.h
Embaixo de
int32_t getLightHour() {return lightHour;} void startDecay(Item* item); Adicione
void parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer);
game.cpp
Embaixo de
player->sendTextMessage(MSG_INFO_DESCR, buffer); }
Adicione
void Game::parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer) { Player* player = getPlayerByID(playerId); if(!player || player->isRemoved()) return; CreatureEventList extendedOpcodeEvents = player->getCreatureEvents(CREATURE_EVENT_EXTENDED_OPCODE); for(CreatureEventList::iterator it = extendedOpcodeEvents.begin(); it != extendedOpcodeEvents.end(); ++it) (*it)->executeExtendedOpcode(player, opcode, buffer); } /creaturescripts/creaturescrips.xml
<event type="extendedopcode" name="ExtendedOpcode" event="script" value="extendedopcode.lua"/>
/creaturescripts/extendedopcode.lua
OPCODE_LANGUAGE = 1 function onExtendedOpcode(cid, opcode, buffer) if opcode == OPCODE_LANGUAGE then -- otclient language if buffer == 'en' or buffer == 'pt' then -- example, setting player language, because otclient is multi-language... --doCreatureSetStorage(cid, CREATURE_STORAGE_LANGUAGE, buffer) end else -- other opcodes can be ignored, and the server will just work fine... end end Créditos : MaXwEllDeN 100% por adaptar o código
-
Milbradt deu reputação a Ryzor em "Math", a matemática por traz do scriptMath
A matemática por traz do script
introdução:
bem, antes de começar a explicar o math em si, acho melhor explicar que:
não é recomendado colocar variáveis como x ou y em uma equação
alem do exemplo acima, funções lua ou de otserv, não podem ser declaradas como nome de variáveis
"=" é diferente de "=="
para facilitar, de uma olhada nessa tabela com os simbulos matemáticos em lua :
+ ---------------------- adição - ------------------ subtração *---------------- multiplicação / ---------------------- divisão == ------------------ igualdade ~= -------------- desigualdade > ----------------- maior que >= -------- maior ou igual que < ----------------- menor que <= -------- menor ou igual que ^ ----------------- potenciação O math sozinho: O math, sozinho, serve somente para colocar equações e cálculos em geral. ficando assim : local var = getPlayerHealth(cid) local resultado = math((var-(var/2))) no caso, var é a vida do player, e na variavel resultado e math resolve a equação que está em seu parametro. math.random: O math.random, pode pegar um numero aleatorio entre um minimo e um maximo, pegar um numero de uma tabela, ou ate mesmo randomizar frases e etc... randomizando numeros por min/max : observe resultado = math.random(1,3) no caso ali, 1 é o numero minimo a ser sorteado, e 3 é o maximo. randomizando por meio de tabelas novamente com um codigo de base : tabela = {1, "eu sou de...mai...onese!", " tutorial by Eventide =D ", 2, 3, 5} Sorteio = math.random(1, table.getn(tabela)) resultado = tabela[Sorteio] primeiramente, foi feito uma tabela com o que seria sorteado. depois, declarei que ia sortear em uma variavel (sorteio), usando math.random, o primeiro numero de seu parametro, indica em qual valor da tabela ele começara a contar, o numero pode ser considerado ordinal, mas é escrito como cardinal, veja o exemplo: table = { "1° valor (ordinal), é representado por 1 ( cardinal )", "2° valor (ordinal), é representado por 2 (cardinal)" } outro modo: tab = {"sete", "mih", "exemplo" } R = math.random(1,table.maxn(tab)) rand = tab[R] assim, você cria uma tabela, randomiza normalmente pelo metodo min/max, sendo que o max é o numero de valores contidos na tabela, e depois na variavel rand, você pega a tabela randomizada, com esse metodo, da pra inserir novos valores na tabela futuramente, sendo que estes tambem serão randomizados... math.fmod(x, y) Retorna o resto da divisão de x por y, caso necessario o valor é arredondado para baixo. math.fmod(4,2) -- retornara 0 math.sqrt (x) Retorna a raiz quadrada de x. math.sqrt(9) -- retornara 3 math.pow (x, y) Retorna x elevado a y math.pow(x, 2) -- retornara x² math.abs( ) retorna o valor absoluto do valor contido em seu parametro, ou seja, os números negativos são automaticamente transformados em positivos. math.abs(-x) -- retornara x math.floor (x) transorma um numero decimal em inteiro, exemplo, se x for 1,3 depois de passar pelo floor ele se torna 1. math.floor(1,5) -- retornara 1
é sempre bom usar isto após uma divisão
creditos: (60%)Eventide (30%)Merdamen (10%) Dark( pelas dicas... ;p)
para saber mais, acesse :
Creditos :
Eventide
-
Milbradt deu reputação a skulls em [Spells] Checando Interferências na TrajetóriaBoa noite galera, tudo bem?
Venho compartilhar com vocês hoje um sisteminha que desenvolvi para as magias do tipo "shoot'. Foi feito inicialmente para funcionar com magias que usam a posição do mouse como referência e adaptei para cipclientes poderem usar em runas e magias de tiro.
O funcionamento do sistema é simples: Ao usar uma runa ou castar uma magia "shoot" com esse sistema criaturas e objetos no caminho irão interferir na trajetória, isto é, receberão o combate no lugar do alvo inicial.
Ilustrativo:
Bom, vamos ao que interessa.
Vá em data/lib/ e crie um novo arquivo chamado spellsLib.lua (pode-se utilizar também o arquivo spells.lua contido em data/spells/lib).
Dentro dele inclua as seguintes funções:
IsWalkable (by Nord)
GetPositionsAround (by Skulls)
CheckInterceptions (by Skulls)
SetSpellTarget (by Skulls)
Feito isso, está tudo configurado. Basta agora adicionar às magias que você queira.
Abra o .lua da magia, por exemplo death strike.lua.
Lá você terá, entre outras coisas, a função onCastSpell como abaixo:
function onCastSpell(cid, var) return doCombat(cid, combat, var) end Substitua isso por:
function onCastSpell(cid, var) return doCombat(cid, combat, setSpellTarget(cid, var)) end Pronto, a sua magia "Exori Mort" será parada por criaturas ou obstáculos (qualquer item que não seja móvel). Bom é isso, espero que gostem. Queria agradecer ao @xWhiteWolf e ao Caronte pelas ajudas tentando entender alguns parâmetros e me dando algumas luzes. Ao Lobo, fica ainda, um agradecimento especial pela maravilhosa lib dele *-*. Abraços, -
Milbradt deu reputação a psychonaut em removidoremovido
-
Milbradt deu reputação a AntigoLiberato em All bugs OTSERV - REVELADO ! -Pode ser alguma house do lado do npc, e quando ele compra os itens direto do npc, ele consegue burlar esse bloquei de 5 itens por tile. ai tem que configurar algo e arrumar isso, coisa que não sei fazer, porque não mexo nessa área.
pode ser também o bug de varias e varias backpacks com varios itens dentro estocados jogado nesse tile dentro da house...
Up~ se alguém puder ajudar o rapaz ai !
-
Milbradt deu reputação a xWhiteWolf em All bugs OTSERV - REVELADO ! -testei todos os bugs ditos no tfs 1.2 q tem na otland e nenhum deles resultou em alguma coisa, quanto à deathlist do 8.6, eu já passei por isso e o problema é q quem fez o schema da database não tinha o mínimo conhecimento de banco de dados e fez uma baita gambiarra danada. A query da deathlist é outra gambiarra maior ainda e isso explica por si só o crash. A solução q eu encontrei foi refazer o script de deathlist usando uma query q eu confiasse.
Quem tiver precisando só utilizar...
SELECT player_id, date, level, all_kills.name FROM ( SELECT kill_id, name FROM player_killers INNER JOIN players ON player_id = id UNION SELECT * FROM environment_killers ) AS all_kills INNER JOIN player_deaths ON player_deaths.id = all_kills.kill_id WHERE player_id = 1-- pegar por script -- ORDER BY player_id, level DESC; se quiser só as ultimas 10 mortes tira o ; ali do fim e coloca embaixo
LIMIT 10;
Ps: aqui tem um print sem o limit mostrando que a query é rapida (testei num banco altamente populado)
player_id é o id do char q eu quis verificar a deathlist, date é a data em unix time (os.time(), usando um os.date com esse numero vc retorna a data e hora em q ocorreu a morte) o level q ele estava e quem matou; Se não tiver "a ____" no all_kills.name então foi morte pra um player.
EDIT 2: Não usem cast system, saibam configurar maxpacket no config.lua (30~50), botem timeBetweenActions de 1 ou 2 segundos (1000 milisegundos no config.lua), constantemente chequem o git do forgotten server olhando os bugs, os commits e os prs, se possível se registre no git para receber notificações de tudo q rola por lá, duvido q seu server será explorado. Oque você não consegue resolver por source vc consegue resolver por script, então fiquem ligados e sempre testem tudo antes de abrir um sv só pra ganhar dinheiro.
-
Milbradt deu reputação a Hoad em [HELP-SPELL] Chuva de MeteorosEntão, eu só mudei os efeitos da spell criada pelo xWhiteWolf
Crie um arquivo .lua dentro de sua pasta spells/script/attack chamado meteor.lua e cole isso dentro dele:
E no arquivo spells.xml, cole isso:
Edit: Agora vi que era azul, vou tentar melhorar
Edit2: Pronto
-
Milbradt deu reputação a The Most Amazing em Tá difícil jogar otserverSobre a questão dos servidores hospedados no Canadá, acho que é falta de opção mesmo.
Hospedar um servidor no Brasil não é viável, o preço é ALTO e o serviço é precário, geralmente a banda é baixa e com isso qualquer um pode nukar o seu servidor.
Eu possuo um servidor e gostaria e MUITO de hospeda-lo no Brasil para meus jogadores terem um ping baixo, mas isso infelizmente é impossível nos dias de hoje.
Sobre os servidores estarem cada vez mais pay to win, eu digo que ninguém é obrigado a doar! Os servidores chegaram a esse ponto por um motivo chamado DEMANDA, os players querem tudo fácil e se podem pagar por isso que o façam.
-
Milbradt deu reputação a Skydangerous em [Programação] Magias Requerindo SkillTutorial: Soltando magia se tiver tanto de skill.
Nivél: Expert Avançado.
Esse sistema é perfeito para quem gosta de Dragon Ball, Naruto, Bleach e etc. Aplicação após a implementação do sistema na spells.xml: instant name="XXX" words="xxxx" clubpoints="XX" lvl="XX" mana="XX" aggressive=XX" selftarget="XX" exhaustion="XXX" event="script" value="XXX.lua"/> 1) Procure por player.cpp case RET_TILEISFULL: sendCancel("You cannot add more items on this tile."); break; e cola em cima do código case RET_NOTENOUGHSKILL: sendCancel("You do not have enough club fighting."); break; 2) Declare na linha (o qual será vericado) no spells.xml Procure por spells.cpp if(readXMLInteger(p, "maglv", intValue) || readXMLInteger(p, "magiclevel", intValue)) magLevel = intValue; e cola em cima do código if(readXMLInteger(p, "club", intValue) || readXMLInteger(p, "clubpoints", intValue)) clubpoints = intValue; 3) Adiciona na função principal Procure novamente spells.cpp if((int32_t)player->getMagicLevel() < magLevel) { player->sendCancelMessage(RET_NOTENOUGHMAGICLEVEL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } e cola em cima if((int32_t)player->getSkill(SKILL_CLUB, SKILL_LEVEL) < clubpoints) { player->sendCancelMessage(RET_NOTENOUGHSKILL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } 4) Procure spells.h Procure essa linha int32_t getMagicLevel() const {return magLevel;} cola em cima uint32_t getSkill() const {return clubpoints;} Procure novamente essa linha int32_t magLevel; cola em cima int32_t clubpoints; 5) Procure things.h E procure essa linha RET_TILEISFULL = 64, e cola em cima RET_NOTENOUGHTRAINPOINTS = 65 Para Configurar: Formula do spells: (ex. level*2 + clubpoints*2) Créditos SkyDangerous Fresh
-
Milbradt deu reputação a Absolute em [ANTI-CLONE] 100% NOVO [O MELHOR]Fala galera do TK!
Trago hoje a vocês um sistema que desenvolvi sob uma base de shop com meu parceiro Thales Valentim do pokemonbr.com.br a alguns meses, pós vários testes e visando que funcionou perfeitamente trago para vocês!
Como funciona?
Toda vez que um ItemVIP ou qualquer Item comprado no SHOP do seu site, quando ele for entregar ao player, irá ficar; COMPRADOR POR:, ou seja; irá adicionar uma "KEY" algo que realmente saiu direto do seu SHOP, pois quando o item é disparado para o player ele vai entregar normal com a função "doCreateItemEx" e então adicionar a descrição no mesmo com a função "doItemSetAttribute".
E como evitará os clones Absolute?
Você terá uma QUERY para executar no seu banco de dados, fazendo uma checagem dos items VIPS que não possuem esse SERIAL KEY (o script também já faz a checagem), ou seja; os que não tiverem a KEY foram clonados (não saíram do SHOP), e então vocês poderão deleta-los manualmente caso necessário.
É muito simples, apenas um script e a QUERY de checagem.
Vamos a instalação?
Em data/globalevents/scripts substitua o seu arquivo shop.lua por este:
-- ### CONFIG ### -- message send to player by script "type" (types you can check in "global.lua") SHOP_MSG_TYPE = 19 -- time (in seconds) between connections to SQL database by shop script SQL_interval = 30 -- ### END OF CONFIG ### function onThink(interval, lastExecution) local result_plr = db.getResult("SELECT * FROM z_ots_comunication WHERE `type` = 'login';") if(result_plr:getID() ~= -1) then while(true) do id = tonumber(result_plr:getDataInt("id")) action = tostring(result_plr:getDataString("action")) delete = tonumber(result_plr:getDataInt("delete_it")) cid = getCreatureByName(tostring(result_plr:getDataString("name"))) if isPlayer(cid) == TRUE then local itemtogive_id = tonumber(result_plr:getDataInt("param1")) local itemtogive_count = tonumber(result_plr:getDataInt("param2")) local container_id = tonumber(result_plr:getDataInt("param3")) local container_count = tonumber(result_plr:getDataInt("param4")) local add_item_type = tostring(result_plr:getDataString("param5")) local add_item_name = tostring(result_plr:getDataString("param6")) local received_item = 0 local full_weight = 0 if add_item_type == 'container' then container_weight = getItemWeightById(container_id, 1) if isItemRune(itemtogive_id) == TRUE then items_weight = container_count * getItemWeightById(itemtogive_id, 1) else items_weight = container_count * getItemWeightById(itemtogive_id, itemtogive_count) end full_weight = items_weight + container_weight else full_weight = getItemWeightById(itemtogive_id, itemtogive_count) if isItemRune(itemtogive_id) == TRUE then full_weight = getItemWeightById(itemtogive_id, 1) else full_weight = getItemWeightById(itemtogive_id, itemtogive_count) end end local free_cap = getPlayerFreeCap(cid) if full_weight <= free_cap then if add_item_type == 'container' then local new_container = doCreateItemEx(container_id, 1) doItemSetAttribute(new_container, "description", 'Bought by ' .. getCreatureName(cid) .. ' [ID:' .. id .. '].') local iter = 0 while iter ~= container_count do local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) doItemSetAttribute(new_item, "description", 'Bought by ' .. getCreatureName(cid) .. ' [ID:' .. id .. '].') doAddContainerItemEx(new_container, new_item) iter = iter + 1 end received_item = doPlayerAddItemEx(cid, new_container) else local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) doItemSetAttribute(new_item, "description", 'Bought by ' .. getCreatureName(cid) .. ' [ID:' .. id .. '].') received_item = doPlayerAddItemEx(cid, new_item) end if received_item == RETURNVALUE_NOERROR then doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, 'You received >> '.. add_item_name ..' << from OTS shop.') doPlayerSave(cid) db.executeQuery("DELETE FROM `z_ots_comunication` WHERE `id` = " .. id .. ";") db.executeQuery("UPDATE `z_shop_history_item` SET `trans_state`='realized', `trans_real`=" .. os.time() .. " WHERE id = " .. id .. ";") else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, '>> '.. add_item_name ..' << from OTS shop is waiting for you. Please make place for this item in your backpack/hands and wait about '.. SQL_interval ..' seconds to get it.') end else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, '>> '.. add_item_name ..' << from OTS shop is waiting for you. It weight is '.. full_weight ..' oz., you have only '.. free_cap ..' oz. free capacity. Put some items in depot and wait about '.. SQL_interval ..' seconds to get it.') end end if not(result_plr:next()) then break end end result_plr:free() end return TRUE end
Confira se no seu globalevents.xml já possui a tag:
<globalevent name="shop" interval="30000" script="shop.lua"/>
PRONTO, VOCÊ ESTÁ LIVRE DE CLONES! TÃO SIMPLES NÃO?
Para fazer a checagem se há items clonados, abra o seu phpmyadmin e execute a seguinte query:
------------------- COMANDO SQL BY ABSOLUTE PARA VERIFICAR A TABELA PLAYER_DEPOTITEMS---------------------- SELECT `player_id`,`pid`,`sid`,CONVERT( `attributes` USING latin1 ) FROM `player_depotitems` WHERE CONVERT( `attributes` USING latin1 ) LIKE '%description%' ------------------- COMANDO SQL BY ABSOLUTE PARA VERIFICAR A TABELA PLAYER_ITEMS---------------------- SELECT `player_id`,`pid`,`sid`,CONVERT( `attributes` USING latin1 ) FROM `player_items` WHERE CONVERT( `attributes` USING latin1 ) LIKE '%description%'
OBSERVAÇÃO IMPORTANTE: Caso seu servidor já esteja online e já possua vendas no seu SHOP, você terá que adicionar a "KEY" em todos os items ou reseta-los.
OUTRA OBSERVAÇÃO: Nunca crie items VIP com o ADMIN e de aos jogadores, pois eles ficaram sem a "KEY" e poderão ser deletados.
ESTE SCRIPT FUNCIONA PERFEITAMENTE NAS REVS 0.3.6 e 0_4, caso necessário passo para a 1.x. S
IMPLES, PRATICO E PERFEITO NÃO?
Quero vê-los usando, espero ter ajudado. :D
Até a próxima!
Absolute.
-
Milbradt 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.
-
Milbradt deu reputação a xWhiteWolf em TauntTaunt é uma magia bem simples que eu fiz me baseando na New Library, pra magia funcionar no seu servidor você vai precisar ter a New Lib instalada (veja esse tópico http://www.tibiaking.com/forum/topic/46015-new-library-v-10/)
A magia em si não tira dano, ela apenas provoca um inimigo fazendo ele andar até a sua direção mas ela possui uns efeitos bem legais e acho que vai ser ótima pra um servidor com bastante foco em RPG;
Aqui tem um pequeno GIF mostrando como a magia funciona.
Bom, dito isso vamos para o código da spell.. como a função taunt já existe na new lib tudo que vc vai precisar adicionar no script da spell é isso daqui:
local config = { walks = 4, -- qnts passos ele vai dar delay = 750, -- de qnts em qnts milisegundos ele dá cada passo speed = 100 -- velocidade que ele vai ficar enquanto estiver sob efeito do taunt } function onCastSpell(cid, var) Taunt(cid, variantToNumber(var), config.delay, config.walks) doChangeSpeed(variantToNumber(var), (config.speed - getCreatureBaseSpeed(variantToNumber(var)))) addEvent(function() if isCreature(variantToNumber(var)) then doChangeSpeed(variantToNumber(var), (-config.speed + getCreatureBaseSpeed(variantToNumber(var)))) end end, config.delay * (config.walks + 1)) return true end
e você configura ali no 300 que é o tempo em milisegundos entre cada passo e 4 é o número de passos que o monstro/player vai andar na sua direção.
Agora é só adicionar isso daqui no spells.xml:
<instant name="TK" words="taunt" lvl="8" mana="35" prem="0" exhaustion="1500" range="4" needtarget="1" needlearn="0" event="script" value="taunt.lua"> </instant> Espero que vocês gostem da spell e façam um bom proveito!
Edit: Deixei o efeito do taunt mais bonito, espero que tenham gostado
-
Milbradt deu reputação a skulls em [Show off] Galeria de SpellsTítulo auto explicativo.
-
Milbradt deu reputação a Lyu em getWinningRatio(win, lose)O que faz? : Retorna o percentual de um frag (vitórias & derrotas).
function getWinningRatio(win, lose) if(type(win) ~= "number" or type(lose) ~= "number") then return nil, error("You need to specify a number value.") end if(win == 0 and lose == 0) then return 0.0 end local ratio = win / (win + lose) * 100 local i = 4 if(math.floor(ratio) < 10) then i = 3 end ratio = tostring(ratio):sub(1, i) return tonumber(ratio) end Como usar? :
doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Seu percentual é "..getWinningRatio(230, 78).."%.") Resultado : Seu percentual é 74.6%.
Onde 230 pode ser uma storage de vitórias do player e 78 as derrotas.
Creio que será dificil esta função ser utilizada. Talvez seja útil para eventos!
créditos : Halls Santos
-
Milbradt deu reputação a GabrielSapient em Launcher AutoUpdate C#Galera sempre procurei um Launcher AutoUpdate para meu servidor, depois de muita pesquisa e pouco conhecimento consegui fazer um em C#, está ai:
1. Download:
• Download | • Scan
2. Oque ele faz:
• Verifica a existência da versão local na pasta do cliente; • Se a versão do arquivo não existir, ele assume que a versão é "1.0" e cria um arquivo de versão; • Verifica arquivo .xml no servidor de atualização; • Baixar atualizações para todas as versões maiores do que a versão atual do cliente (atualiza tudo em apenas formato de arquivo .zip); • Extrai os arquivos .zip; • Exclui os arquivos .zip após a extração; • Arquiva a versão atualizada na pasta do cliente; • E, finalmente, desbloqueia o botão "Start Game". 3. Como editar: • Abra o arquivo .sln na pasta "VS Project" com o Visual Studio: Procure por: string Server = "http://127.0.0.1/Updates/"; • Altere o http://127.0.0.1/Updates/ para qualquer URL que você estará hospedando suas atualizações.
• Agora vamos procurar por: Process.Start("OTClient PkR DX9.exe", "\\Pokémon Rusty"); • Modifique o OTClient PkR DX9.exe pelo nome do .exe do seu Client.
• \\Pokémon Rusty e a pasta que está seu .exe e vai ficar seu Launcher. (troque sem tirar os "\\")
• No Visual Studio, selecione o controle WebBrowser(Neste caso, o nome "patchNotes") e alterar a url do "http://127.0.0.1/"para o caminho do arquivo index.html, na pasta do host: OBS: Isto á opcional, é apenas um template em .html. Você pode remove-lo e editar da maneira deseja. • Agora apenas jogue o .exe, .dll e o arquivo version da pasta "Launcher\VS Project\Launcher v2\bin\Debug ou Release" para a pasta de seu Client: Pronto! Agora e com o Site. • No host do site, apos colarmos a pasta Updates, editamos o arquivo Updates.xml, para cada atualização adicionamos um <update> fechamos com </update> como no exemplo do arquivo. Colocamos o arquivo atualização em .zip nessa mesma pasta, editando a versão e o nome no arquivo: • No arquivo version.txt colocamos a versão da nova atualização: • Uma dica para o .zip de atualização é colocar em pastas o caminho no client desejado a fazer update. Exemplo: data/things/854 nesta pasta colocaremos os arquivos que será substituído, no exemplo foi Tibia.spr e .dat. Depois compactamos e deixamos na pasta Updates, sem esquecer de colocar o nome no arquivo Updates.xml. 4. Dica • Pronto! Agora e só criar um instalador com o launcher, com atalho na área de trabalho (o launcher é o .exe que você colocou no client). Você pode modificar o launcher do jeito que quiser, o arquivo index.html e etc. Quando abrir o arquivo ele irá atualizar, liberar o botão "Start Game", e quando você clicar vai fechar o Launcher e abrir o Client. 5. Créditos Eu - Pelo launcher e pelo tutorial. -
Milbradt deu reputação a Refe em Show-Off Client + Launcher Pokémon RubrumHoje eu vim mostrar o client/launcher do meu projeto, provavelmente eu irei liberar as sources do Launcher :)
Launcher:
Client:
-
Milbradt deu reputação a Nu77 em Null's Show OffFeito para um ATS inspirado em Naruto.
Autenticação totalmente server side, a única coisa que o Client faz é manipular o input do usuário.
Feedback's?
Postagem original: https://facebook.com/SpriteArtBrasil
-
Milbradt deu reputação a Wise em forceSetStorageValue(name, key, value)Serei breve enquanto a explicação.
Esta função serve para "forçar" o value de uma storage key a mudar, independentemente do player estar on ou offline.
Adicione o seguinte script à lib do seu servidor (data\lib):
forceSetStorageValue = function (name, key, value) if not tostring(name) or not tonumber(key) then return nil end local p = getPlayerByName(name) if p then setPlayerStorageValue(p, key, value) else local have = db.storeQuery("SELECT `key` FROM `player_storage` WHERE `player_id` = ".. getPlayerGUIDByName(name) .." and `key` = ".. key) if have then db.query("UPDATE `player_storage` SET `value` = '".. value .."' WHERE `player_id` = '".. getPlayerGUIDByName(name) .."' AND `key` = ".. key) else db.query("INSERT INTO `player_storage` (`player_id` ,`key` ,`value`) VALUES ('".. getPlayerGUIDByName(name) .."', '".. key .."', '".. value .."');") end end return true end
A seguir, preparei uma talkaction para o uso da função.
fstorage.lua (data\talkactions\scripts):
function onSay(cid, words, param) local w = string.explode(param, ",") if param == '' then return doPlayerSendCancel(cid, 'Enter the player name, the storage key and the storage value (number or string). Ex: /forcestorage Player, 1234, 5') elseif not tostring(w[1]) or not tonumber(w[2]) or not w[3] or w[4] then return doPlayerSendCancel(cid, 'Invalid parameter specified.') end forceSetStorageValue(w[1], w[2], w[3]) return true end
talkactions.xml (data\talkactions):
<talkaction log="yes" words="/forcestorage" access="5" event="script" value="fstorage.lua"/> (o formato da tag varia de acordo com a versão do servidor utilizado)
Uso da talkaction:
/forcestorage Player, key, value ~ /forcestorage Wise, 1234, 5 Enfim, na minha mente ela me parece bem eficaz.
Espero que gostem.
-
Milbradt deu reputação a MaXwEllDeN em (Resolvido)Falar saia e o npc desaparecerif msgcontains(message, 'saia') then local pos_npc = getThingPos(getNpcId()) doRemoveCreature(getNpcId()) addEvent(doCreateNpc, 4*1000, "Fulano", pos_npc) end