Marce Loko 18 Postado Outubro 6, 2016 Share Postado Outubro 6, 2016 Bom dia! Esse código faz a creature (NPC, monster ou player) andar até a posição desejada. Notas: Não use para longas distâncias. Crie um sistema de waypoints para isso. A creature não para exatamente na posição desejada. (caso alguém se interesse em corrigir, eu anexarei ao tópico) Utiliza grande poder de processamento. Use de forma sábia. Testado apenas em TFS 1.2 Coloque em luascript.cpp registerMethod("Creature", "moveTo", LuaScriptInterface::luaCreatureMoveTo); int32_t LuaScriptInterfaceluaCreatureMoveTo(lua_State* L){ //creature:moveTo(pos) Creature* creature = getUserdata<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } const Position& position = getPosition(L, 2); FindPathParams fpp; fpp.minTargetDist = getNumber<int32_t>(L, 3, 0); fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1); fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch); fpp.clearSight = getBoolean(L, 6, fpp.clearSight); fpp.maxSearchDist = getNumber<int32_t>(L, 7, 150); stdforward_list<Direction> dirList; if (creature->getPathTo(position, dirList, fpp)) { creature->hasFollowPath = true; creature->startAutoWalk(dirList); pushBoolean(L, true); } else { pushBoolean(L, false); } return 1;} Coloque em luascript.h static int luaCreatureMoveTo(lua_State* L); Substitua a função original em creature.cpp bool CreaturesetFollowCreature(Creature* creature){ if (creature) { if (followCreature == creature) { return true; } const Position& creaturePos = creature->getPosition(); FindPathParams fpp; fpp.minTargetDist = 0; fpp.maxTargetDist = 1; fpp.fullPathSearch = true; fpp.clearSight = true; fpp.maxSearchDist = 150; stdforward_list<Direction> dirList; if (creaturePos.z != getPosition().z || !canSee(creaturePos) || !getPathTo(creaturePos, dirList, fpp)) { followCreature = nullptr; return false; } if (!listWalkDir.empty()) { listWalkDir.clear(); onWalkAborted(); } hasFollowPath = false; forceUpdateFollowPath = false; followCreature = creature; isUpdatingPath = true; } else { isUpdatingPath = false; followCreature = nullptr; } onFollowCreature(creature); return true;} Substitua a função original em monster.cpp bool MonstergetNextStep(Direction& dir, uint32_t& flags){ if (getHealth() <= 0) { //we dont have anyone watching might aswell stop walking eventWalk = 0; return false; } bool result = false; if (hasFollowPath) return CreaturegetNextStep(dir, flags); else if ((!followCreature || !hasFollowPath) && !isSummon()) { if ((followCreature || getTimeSinceLastMove() > 1000) && !hasFollowPath && !isIdle) { //choose a random direction result = getRandomStep(getPosition(), dir); } } else if (isSummon() || followCreature) { result = CreaturegetNextStep(dir, flags); if (result) { flags |= FLAG_PATHFINDING; } else { //target dancing if (attackedCreature && attackedCreature == followCreature) { if (isFleeing()) { result = getDanceStep(getPosition(), dir, false, false); } else if (mType->staticAttackChance < static_cast<uint32_t>(uniform_random(1, 100))) { result = getDanceStep(getPosition(), dir); } } } } if (result && (canPushItems() || canPushCreatures())) { const Position& pos = SpellsgetCasterPosition(this, dir); Tile* tile = g_game.map.getTile(pos); if (tile) { if (canPushItems()) { MonsterpushItems(tile); } if (canPushCreatures()) { MonsterpushCreatures(tile); } } } return result;} Aproveitem! Abraço. Link para o comentário Compartilhar em outros sites More sharing options...
Visitante Postado Outubro 6, 2016 Share Postado Outubro 6, 2016 Muito bom o Código REP + Link para o comentário Compartilhar em outros sites More sharing options...
Administrador Administrador 1435 Postado Outubro 7, 2016 Administrador Share Postado Outubro 7, 2016 Esta é uma contribuição para a maratona de projetos Bom desempenho ao projeto! Link para o comentário Compartilhar em outros sites More sharing options...
Waterson 9 Postado Outubro 8, 2016 Share Postado Outubro 8, 2016 Interessante, você implementou em C++ uma função para movimentar o personagem com o smart walk, é uma boa jogada também apesar que é possível se fazer em LUA; Que tal agora um sistema parallel-thread para tais cálculos com alto-processamento ? Acho que seria bastante conveniente; Atualmente estou desenvolvendo algo do tipo para um projeto de faculdade, cujas ideias irão futuramente se transformar num servidor. REP+ Link para o comentário Compartilhar em outros sites More sharing options...
dalvorsn 268 Postado Outubro 8, 2016 Share Postado Outubro 8, 2016 12 minutos atrás, Waterson disse: Interessante, você implementou em C++ uma função para movimentar o personagem com o smart walk, é uma boa jogada também apesar que é possível se fazer em LUA; Que tal agora um sistema parallel-thread para tais cálculos com alto-processamento ? Acho que seria bastante conveniente; Atualmente estou desenvolvendo algo do tipo para um projeto de faculdade, cujas ideias irão futuramente se transformar num servidor. REP+ Sei la, acho que nem é um processamento muito pesado, a parada que é meio paia no otserv que seria bacana de mudar ate mesmo usando essa ideia ai é a divisao que tem mais interna, que é o um thread pro scheduler, um pro asio e um pro dispatcher, porém o pesado é o dispatcher, ele se fosse subdividido ai ia melhorar pra caralho o processamento sera que é muito complexo quebrar o dispatcher em threads e ainda assim manter a cronologia certa das execuções? #topic Muito boa implementação, meus parabéns. Link para o comentário Compartilhar em outros sites More sharing options...
Waterson 9 Postado Outubro 8, 2016 Share Postado Outubro 8, 2016 O problema é o seguinte, você precisará ter controle das variáveis, exemplo, quando trabalhamos em maneira assíncrona dois threads poderão querer alterar/ler a mesma variável no mesmo exato segundo, e isso irá com certeza crashar ! A solução é utilizar uma biblioteca chamada atomic, ela terá novos tipos de variáveis chamados atomic_int, atomic_float, atomic_char ... etc ... que são exatamente iguais as int, float ,... mas ela possui um controle para que quando trabalhado de maneira assíncrona dois threads não possam modificar ou ler uma mesma variável no mesmo instante (seria um modelo chave fechadura, se um está lendo está trancado para o outro não ler, quando este terminar de ler será destrancando e o outro poderá a ler ...), o grande problema é que não existe por exemplo um atomic_luaState, ou seja, seria impossível trabalhar com multi-thread em LUA com esta biblioteca atomic, o esquema seria criar este modelo na mão para poder ser usado em variáveis do tipo luaState também ! Link para o comentário Compartilhar em outros sites More sharing options...
dalvorsn 268 Postado Outubro 8, 2016 Share Postado Outubro 8, 2016 6 minutos atrás, Waterson disse: O problema é o seguinte, você precisará ter controle das variáveis, exemplo, quando trabalhamos em maneira assíncrona dois threads poderão querer alterar/ler a mesma variável no mesmo exato segundo, e isso irá com certeza crashar ! A solução é utilizar uma biblioteca chamada atomic, ela terá novos tipos de variáveis chamados atomic_int, atomic_float, atomic_char ... etc ... que são exatamente iguais as int, float ,... mas ela possui um controle para que quando trabalhado de maneira assíncrona dois threads não possam modificar ou ler uma mesma variável no mesmo instante (seria um modelo chave fechadura, se um está lendo está trancado para o outro não ler, quando este terminar de ler será destrancando e o outro poderá a ler ...), o grande problema é que não existe por exemplo um atomic_luaState, ou seja, seria impossível trabalhar com multi-thread em LUA com esta biblioteca atomic, o esquema seria criar este modelo na mão para poder ser usado em variáveis do tipo luaState também ! entendi, complexo isso e tipo tem que refatorar o codigo todo pra trabalhar com esses tipos do atomic tambem? Link para o comentário Compartilhar em outros sites More sharing options...
Waterson 9 Postado Outubro 8, 2016 Share Postado Outubro 8, 2016 Nos locais aonde haverá transições entre threads sim ! Eu já fiz isso, pelo menos algo do tipo, consegui otimizar esta função acima de moveTo que eu usava em 4 NPCs de inteligência artificial (800-1200ms de ping) para 70 NPCs (290-420ms), porém estou tendo problemas com alocação de memória... então está complicando ... Link para o comentário Compartilhar em outros sites More sharing options...
Marce Loko 18 Postado Outubro 8, 2016 Autor Share Postado Outubro 8, 2016 43 minutos atrás, Waterson disse: é uma boa jogada também apesar que é possível se fazer em LUA; eu já sugeri ter muito cuidado pra usar essa função... se fosse uma implementação Lua, eu então diria pra nem usá-la! hahhahahahha 43 minutos atrás, Waterson disse: Que tal agora um sistema parallel-thread para tais cálculos com alto-processamento ? Acho que seria bastante conveniente; Atualmente estou desenvolvendo algo do tipo para um projeto de faculdade, cujas ideias irão futuramente se transformar num servidor. REP+ 25 minutos atrás, dalvorsn disse: sera que é muito complexo quebrar o dispatcher em threads e ainda assim manter a cronologia certa das execuções? Infelizmente eu não sou designer de framework, apenas desenvolvo conteúdo em cima da plataforma. Então eu parto do pressuposto de que o servidor cumpre com maestria o que eu preciso. Afinal, nunca vi um OT que o gargalo seja o processamento. Em um OT que atingiu 2 mil jogadores, o computador não chegou a bater 50% de processamento... e nem era um dedicado tão possante. Além disso tudo, o meu projeto possui características que pode alterar como funciona o mapa, posso bufferizar todo o mapa no cliente. No que eu tenho conhecimento, essa parte do mapa é um dos grandes vilões do processamento. Link para o comentário Compartilhar em outros sites More sharing options...
dalvorsn 268 Postado Outubro 8, 2016 Share Postado Outubro 8, 2016 23 minutos atrás, Marce Loko disse: Infelizmente eu não sou designer de framework, apenas desenvolvo conteúdo em cima da plataforma. Então eu parto do pressuposto de que o servidor cumpre com maestria o que eu preciso. Afinal, nunca vi um OT que o gargalo seja o processamento. Em um OT que atingiu 2 mil jogadores, o computador não chegou a bater 50% de processamento... e nem era um dedicado tão possante. Além disso tudo, o meu projeto possui características que pode alterar como funciona o mapa, posso bufferizar todo o mapa no cliente. No que eu tenho conhecimento, essa parte do mapa é um dos grandes vilões do processamento. do processamento e da rede ne, um map descriptions full envia uma quantidade de dados ferrada xD essa parada de bufferizar o mapa é bacana, dai ficam apenas os things e uma eventual atualizaçao do mapa ne? Link para o comentário Compartilhar em outros sites More sharing options...
Marce Loko 18 Postado Outubro 8, 2016 Autor Share Postado Outubro 8, 2016 48 minutos atrás, dalvorsn disse: do processamento e da rede ne, um map descriptions full envia uma quantidade de dados ferrada xD essa parada de bufferizar o mapa é bacana, dai ficam apenas os things e uma eventual atualizaçao do mapa ne? sim, como o meu mapa é pequeno, dá certinho eu não cheguei a profilar, mas me disseram que considerável porcentagem do processamento é relativo ao map description Link para o comentário Compartilhar em outros sites More sharing options...
Waterson 9 Postado Dezembro 28, 2016 Share Postado Dezembro 28, 2016 No fim das contas o problema não era alocação de memória, era um simplesmente um crash no thread secundário ocasionado por um problema relacionado aos protocolos que eu havia utilizado para comunicação para averiguar a situação dos processamentos pelo cliente. O erro default para esse tipo de coisa era Memory Allocation Failed, porém esse erro é exibido sempre que ocorre um erro ou no MainThread ou em qualquer outro thread que não seja o Dispatcher. Sistema funcionando - Sistema é exibido no final do vídeo. [isto fora um trabalho da faculdade da matéria de Ciência, Tecnologia, Sociedade e Ambiente & Jogos, Games e Gameficação] Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados