Ir para conteúdo

creature:moveTo(pos)


Posts Recomendados

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

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

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

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

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

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

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

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

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

  • 2 months later...

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

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...