• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ Slowly dying monsters (OTHire 0.0.3) [Solved]

jakub742

Member
Joined
May 1, 2010
Messages
144
Solutions
2
Reaction score
20
Location
Slovakia
Hi. If i kill a creature its dying very slowly till the corpse is created. If im using spell that is attacking the monsters at screen, sometimes its also targeting a dying monsters and it looks weird. Also they dont die at the same time.

Using OTHire 0.0.3 distro.

bXqxlK8AtP.gif
 
Solution
Had a quick look at it, and if I am not mistaken, it has to do with the EVENT_CHECK_CREATURE_INTERVAL, which is used as a delay in Game::checkCreatures()

If it doesn't hurt you that much you can let it be, else you can try reduce EVENT_CREATURE_THINK_INTERVAL. It is currently defined at 1000 in creature.h. But I don't recomend it because it might affect other parts of the code.

And note: I might be fully wrong.
In sources somewhere, there's something similar to "addevent" for the function that make the monster die.
Normally it's a random function that decide how long it will take before the creature falls.
 
I see addevent only with addeventWalk
Creature.cpp
Code:
void Creature::onDie()
{
    DeathList killers = getKillers(g_config.getNumber(ConfigManager::DEATH_ASSIST_COUNT));

    for(DeathList::const_iterator it = killers.begin(); it != killers.end(); ++it){
        if(it->isCreatureKill()){
            Creature* attacker = it->getKillerCreature();
            if(attacker){
                attacker->onKilledCreature(this, (it == killers.begin()));
            }
        }
    }
   
    std::map<Creature*, uint64_t> experienceMap;

    for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it){
        if(Creature* attacker = g_game.getCreatureByID((*it).first)){
            if (attacker != this) {
                uint64_t gainExp = getGainedExperience(attacker);
                if (Player* player = attacker->getPlayer()) {
                    Party* party = player->getParty();
                    if (party && party->getLeader() && party->isSharedExperienceActive() && party->isSharedExperienceEnabled()) {
                        attacker = party->getLeader();
                    }
                }

                std::map<Creature*, uint64_t>::iterator it = experienceMap.find(attacker);
                if (it == experienceMap.end()) {
                    experienceMap[attacker] = gainExp;
                } else {
                    it->second += gainExp;
                }
            }
        }
    }

    dropCorpse();
    die();
   
    bool fromMonster = false;
    if (this->getMonster()) {
        fromMonster = true;
    }
   
    for (std::map<Creature*, uint64_t>::iterator it = experienceMap.begin(); it != experienceMap.end(); it++) {
        it->first->onGainExperience(it->second, fromMonster);
    }

    if(getMaster()){
        getMaster()->removeSummon(this);
    }
}


void Creature::die()
{
    g_game.removeCreature(this, false);
}

monster.cpp
Code:
void Monster::die()
{
    setAttackedCreature(NULL);
    destroySummons();
    clearTargetList();
    clearFriendList();
    onIdleStatus();
    Creature::die();
}

Item* Monster::createCorpse()
{
    Item* corpse = Creature::createCorpse();
    return corpse;
}
 
Had a quick look at it, and if I am not mistaken, it has to do with the EVENT_CHECK_CREATURE_INTERVAL, which is used as a delay in Game::checkCreatures()

If it doesn't hurt you that much you can let it be, else you can try reduce EVENT_CREATURE_THINK_INTERVAL. It is currently defined at 1000 in creature.h. But I don't recomend it because it might affect other parts of the code.

And note: I might be fully wrong.
 
Solution
Lol. I was around when otserv began and it was the exact opposite. Now ppl want that? oh well..

For the record, having all die the exact moment they are killed was way more weird :)
 
Last edited:
I changed the #define EVENT_CREATURE_THINK_INTERVAL to 500. The delay is smaller and everythink looks OK. They still dont die at the exact same time but thats ok. I check the game.cpp and found this
Code:
void Game::checkCreatures()
{
    g_scheduler.addEvent(createSchedulerTask(
        EVENT_CHECK_CREATURE_INTERVAL, boost::bind(&Game::checkCreatures, this)));

    Creature* creature;
    std::vector<Creature*>::iterator it;

    //add any new creatures
    for(it = toAddCheckCreatureVector.begin(); it != toAddCheckCreatureVector.end(); ++it){
        creature = (*it);
        checkCreatureVectors[creature->checkCreatureVectorIndex].push_back(creature);
    }
    toAddCheckCreatureVector.clear();

    checkCreatureLastIndex++;
    if(checkCreatureLastIndex == EVENT_CREATURECOUNT){
        checkCreatureLastIndex = 0;
    }

    std::vector<Creature*>& checkCreatureVector = checkCreatureVectors[checkCreatureLastIndex];

    for(it = checkCreatureVector.begin(); it != checkCreatureVector.end();){
        creature = (*it);

        if(creature->creatureCheck){
            if(creature->getHealth() > 0){
                creature->onThink(EVENT_CREATURE_THINK_INTERVAL);
            }
            else{
                creature->onDie();
            }
            ++it;
        }
        else{
            creature->checkCreatureVectorIndex = -1;
            it = checkCreatureVector.erase(it);
            FreeThing(creature);
        }
    }

    cleanup();
}

So i guess thats okay because its checking one creature per iteration.
 
They don't drop at the same time since they were not spawned at the exact same time (again speculation)
 
So it should not be a problem with setting #define EVENT_CREATURE_THINK_INTERVAL to 500 right ?. I checked some distros and some of them had 500 too.
 
So it should not be a problem with setting #define EVENT_CREATURE_THINK_INTERVAL to 500 right ?. I checked some distros and some of them had 500 too.
Well it depends on what you want to achieve. Do you want the monsters to die and become corpses instantly or do you just want them to drop at the same time? Because the latter is probably not so tricky, to make newly created monsters fit the onThink interval simultaneously with current, alive, creatures.

As the code is created now, we need to constantly check the creatures being "alive" and that is what the checkCreatures function does. However, I don't think it's impossible to make it so you check creature health (if creature should be alive or not) when damage has ben dealt to it, which means you can make the corpse drop in an instance.

But to me it seems like a lot of work for basically nothing more than aesthetics
 
Well it depends on what you want to achieve. Do you want the monsters to die and become corpses instantly or do you just want them to drop at the same time? Because the latter is probably not so tricky, to make newly created monsters fit the onThink interval simultaneously with current, alive, creatures.

As the code is created now, we need to constantly check the creatures being "alive" and that is what the checkCreatures function does. However, I don't think it's impossible to make it so you check creature health (if creature should be alive or not) when damage has ben dealt to it, which means you can make the corpse drop in an instance.

But to me it seems like a lot of work for basically nothing more than aesthetics
Yea i dont care about dropping the corpse at the same time. I just wanted to lower the interval from die() to dropCorpse() and i achieved that. Thanks for your help ;)
 
This is due to addevent being called in a loop. I have no idea why the hell it need addevent as checkCreatures

You could probably just call onDie in drainHealth / changeHealth Creature methods when new health < 1. But AFAIK creatures, sometimes, lagged to drop corpse in old times, not sure about now.
 
You could probably just call onDie in drainHealth / changeHealth Creature methods when new health < 1. But AFAIK creatures, sometimes, lagged to drop corpse in old times, not sure about now.
I need the delay as my server is 7.6. But I need the monsters to die together, not one by one. I tried c++ 1 second "sleep function" but doesnt work
 
Back
Top