LS
poketibia

Função onSpawn(cid) para TFS 0.3.6

Por lSainty, 28 de fev. de 2014 em Linguagens de Programação

onspawn
tfs 036
funçao
tibia
script
otserv
22
7.3k
lSaintyL
28 de fevereiro de 2014 às 01:28

Eae galera, estava passando aqui por essa seção e vi que só havia a função onSpawn para TFS 0.4, então resolvi trazer para 0.3.6 :)

 

Primeiramente, va em Creatureevent.h e procure por:

uint32_t executePrepareDeath(Creature* creature, DeathList deathList);

E cole embaixo:

uint32_t executeOnSpawn(Creature* creature);

Procure por:

CREATURE_EVENT_DEATH,

E cole isso por cima da linha de baixo:

CREATURE_EVENT_PREPAREDEATH,
CREATURE_EVENT_SPAWN

Agora va em creatureevent.cpp e procure por:

else if(tmpStr == "preparedeath")
m_type = CREATURE_EVENT_PREPAREDEATH;

E cole embaixo:

else if(tmpStr == "spawn")
m_type = CREATURE_EVENT_SPAWN; 

Procure por:

case CREATURE_EVENT_PREPAREDEATH:
return "onPrepareDeath";

E cole embaixo:

case CREATURE_EVENT_SPAWN:
return "onSpawn";

Procure por:

case CREATURE_EVENT_PREPAREDEATH:
return "cid, deathList";

E cole embaixo:

case CREATURE_EVENT_SPAWN:
return "cid";

Va ao fim do arquivo e cole isso:

uint32_t CreatureEvent::executeOnSpawn(Creature* creature)
{

    //onSpawn(cid)
    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 << 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__
            std::stringstream desc;
            desc << creature->getName();
            env->setEvent(desc.str());
            #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));


            bool result = m_interface->callFunction(1);
            m_interface->releaseEnv();
            return result;
        }
    }
    else
    {
        std::clog << "[Error - CreatureEvent::executeCast] Call stack overflow." << std::endl;
        return 0;
    }
}

Va em monster.cpp e procure por:

void Monster::onCreatureAppear(const Creature* creature)
{
Creature::onCreatureAppear(creature);
if(creature == this)
{
//We just spawned lets look around to see who is there.
if(isSummon())

isMasterInRange = canSee(master->getPosition());

Embaixo pressione enter 2x e cole:

CreatureEventList spawn = getCreatureEvents(CREATURE_EVENT_SPAWN);
for(CreatureEventList::iterator it = spawn.begin(); it != spawn.end(); ++it)

(*it)->executeOnSpawn(this);

E pronto, basta compilar agora :D

 

Exemplos de como usar essa função:

 

 

Em um servidor de tibia, você pode usa-la para quando um boss der respawn, exemplo:

function onSpawn(cid)
doBroadcastMessage("Monster ".. getCreatureName(cid).." was created.")
return true

end

E até mesmo em um servidor de poketibia você pode fazer com que tenha uma chanse de o pokemon nascer shiny :b, resumindo, é possivel fazer varias coisas com essa função xD (Lembrando que ela só funciona quando o monstro da respawn, e não quando abre o servidor).

 

 

 

-- EDIT --

Para fazer com que o evento seja iniciado junto com o servidor ao invés de somente quando o monstro der RESPAWN, va em spawn.cpp e procure por:

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

e apague essa parte:

    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }
    else

Pronto, agora a função é executada assim que o servidor inicia :D

 

Se os monstros pararem de dar respawn, ao invés de apagarem a parte que citei acima, troquem isso:

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

Por isso:

 

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
        else
        {
           monster->onCreatureAppear(monster);
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

 

 

Créditos: Doggynub por fazer a função (OTIlha)

ArkSeyonet por adaptar para 0.3.6 (OTIlha)

Eu por pequenas edições :3

Slicer

Editado Março 21 por ElderZard

BeekiB
28 de fevereiro de 2014 às 03:12

ótimo conteúdo, tem como explicar/exemplificar de como usa-lo?

caoticC
28 de fevereiro de 2014 às 09:39

Opa colega so ta faltando o registro do evento.

 

Sendo assim o creatureevent nunca sera chamado.

lSaintyL
28 de fevereiro de 2014 às 10:42

ótimo conteúdo, tem como explicar/exemplificar de como usa-lo?

Essa função é executada sempre que o monstro da respawn, em um poketibia por exemplo ela pode ser usada para ter uma chanse de o pokemon nascer shiny, ou até mesmo mandar uma mensagem quando o monstro nascer:

 

function onSpawn(cid)
doBroadcastMessage("Monster ".. getCreatureName(cid).." was created.")
return true

end

Entendeu? :D

Opa colega so ta faltando o registro do evento.

 

Sendo assim o creatureevent nunca sera chamado.

Corrigido, eu tinha esquecido uma parte do código :/

StigalS
28 de fevereiro de 2014 às 10:54

Estou comentando em algo relacionado a tibia, então nem preciso dizer o que achei.

Parabéns!

Editado Fevereiro 28 por Stigal

lSaintyL
28 de fevereiro de 2014 às 11:08

Estou comentando em algo relacionado a tibia, então nem preciso dizer o que achei.

Parabéns!

vqz7.jpgi536.jpg20e1.jpg

1 mês depois...
StrogmanS
17 de março de 2014 às 20:56

lol parou de nascer respaw quando mata o monstro ele não nasce mais por que?

SlicerS
17 de março de 2014 às 21:59

/\ provavelmente tu fez 'caca' ali na hora de apagar a parte do spawn.cpp... na real, apagar aquela parte n eh a melhor opçao... eu colocaria um else ali.. ;p

StrogmanS
17 de março de 2014 às 22:11

como assim um else?

Editado Março 17 por gristony

nociamN
18 de março de 2014 às 18:53

como assim um else?

Queria saber tb como?

SlicerS
18 de março de 2014 às 19:33

eu tinha feito aki no serv q eu tinha começado do zero, mas parece q quando formatei o pc eu acabei salvando uma versao antiga das sources e dai n tenhu mais essa ediçao aki... mas se n me engano eu fiz assim...

 

 

 

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
        else
        {
           monster->onCreatureAppear(monster);
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

 

 

 

realmente n eh preciso checar se tem player por perto pra mandar os eventos quando o serv ta iniciando... entao o melhor jeito de fazer essa ediçao eh esse ae, pelo menos pra mim, executando soh o evento no proprio monstro... com isso, vai disparar o onSpawn... -em tese, n lembro se foi assim q fiz antes...-

Editado Março 18 por Slicer

StrogmanS
18 de março de 2014 às 21:51

eu tinha feito aki no serv q eu tinha começado do zero, mas parece q quando formatei o pc eu acabei salvando uma versao antiga das sources e dai n tenhu mais essa ediçao aki... mas se n me engano eu fiz assim...

 

 

 

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
        else
        {
           monster->onCreatureAppear(monster);
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

 

 

 

realmente n eh preciso checar se tem player por perto pra mandar os eventos quando o serv ta iniciando... entao o melhor jeito de fazer essa ediçao eh esse ae, pelo menos pra mim, executando soh o evento no proprio monstro... com isso, vai disparar o onSpawn... -em tese, n lembro se foi assim q fiz antes...-

 

vlw deu certo

Editado Março 18 por gristony

lSaintyL
21 de março de 2014 às 19:13

Tópico atualizado :b

nociamN
22 de março de 2014 às 09:55

eu tinha feito aki no serv q eu tinha começado do zero, mas parece q quando formatei o pc eu acabei salvando uma versao antiga das sources e dai n tenhu mais essa ediçao aki... mas se n me engano eu fiz assim...

 

 

 

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
        else
        {
           monster->onCreatureAppear(monster);
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

 

 

 

realmente n eh preciso checar se tem player por perto pra mandar os eventos quando o serv ta iniciando... entao o melhor jeito de fazer essa ediçao eh esse ae, pelo menos pra mim, executando soh o evento no proprio monstro... com isso, vai disparar o onSpawn... -em tese, n lembro se foi assim q fiz antes...-

No meu servidor quanto o servidor inicia nao funciona vai saber.

lSaintyL
24 de março de 2014 às 15:32

 

eu tinha feito aki no serv q eu tinha começado do zero, mas parece q quando formatei o pc eu acabei salvando uma versao antiga das sources e dai n tenhu mais essa ediçao aki... mas se n me engano eu fiz assim...

 

 

 

bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/)
{
    Monster* monster = Monster::createMonster(mType);
    if(!monster)
        return false;

    if(startup)
    {
        //No need to send out events to the surrounding since there is no one out there to listen!
        if(!g_game.internalPlaceCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
        else
        {
           monster->onCreatureAppear(monster);
        }
    }
    else
    {
        if(!g_game.placeCreature(monster, pos, false, true))
        {
            delete monster;
            return false;
        }
    }

    monster->setSpawn(this);
    monster->addRef();

    monster->setMasterPosition(pos, radius);
    monster->setDirection(dir);

    spawnedMap.insert(SpawnedPair(spawnId, monster));
    spawnMap[spawnId].lastSpawn = OTSYS_TIME();
    return true;
}

 

 

 

realmente n eh preciso checar se tem player por perto pra mandar os eventos quando o serv ta iniciando... entao o melhor jeito de fazer essa ediçao eh esse ae, pelo menos pra mim, executando soh o evento no proprio monstro... com isso, vai disparar o onSpawn... -em tese, n lembro se foi assim q fiz antes...-

No meu servidor quanto o servidor inicia nao funciona vai saber.

 

Tentou das duas formas? Comigo as duas funcionaram o.O