• 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++ Crash sending animatedText in monsters.cpp

Acubens

Old Penguin
Joined
May 6, 2008
Messages
1,261
Solutions
13
Reaction score
184
Location
Venezuela
Its me again with a new question ;D well im triying to use g_game.addAnimatedText using item position when is created in createLootItem method inside monsters.cpp but im getting crash when monster generates the loot and touch this part of the code.

In monsters.cpp i added

C++:
extern Game g_game;

Then in method

C++:
std::list<Item*> MonsterType::createLootItem(const LootBlock& lootBlock)

I try use

C++:
g_game.addAnimatedText(tmpItem->getItem()->getPosition(), 66, "Item looted");

and

C++:
g_game.addAnimatedText(tmpItem->getPosition(), 66, "Item looted");

and

C++:
g_game.addAnimatedText(tmpItem->getTile()->getPosition(), 66, "Item looted");

But server crash, any idea why this is happen?, my skills in c++ is low but im trying do new thigs to learn haha xD
 
Last edited:
Solution
The object was barely created and it certainly doesn't have any position set as of yet. On top of that calling it inside createLootItem of Monsters class is not a correct approach.

However, moving up a bit in the same file you probably have something like this:

C++:
void MonsterType::createLoot(Container* corpse)
{

for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && (corpse->capacity() - corpse->size() > 0); ++it){

    std::list<Item*> itemList = createLootItem(*it);

    if(!itemList.empty()){

        for(std::list<Item*>::iterator iit = itemList.begin(); iit != itemList.end(); ++iit){

            Item* tmpItem = *iit;

...

In this function corpse should have a set position, since before calling...
How about you copy the whole function of MonsterType::createLootItem for us to actually see how it looks like after your changes? It will be much easier this way.
 
@Iryont For example im looking to notify is a item with attack has been drop by monster, i think im getting crash because i can't find a position, maybe getPosition() isn't return the item position in the world? or i need the position of the corpse?

C++:
std::list<Item*> MonsterType::createLootItem(const LootBlock& lootBlock)
{
    Item* tmpItem = NULL;
    int32_t itemCount = 0;

    uint32_t randvalue = Monsters::getLootRandom();
    if(randvalue < lootBlock.chance){
        if(Item::items[lootBlock.id].stackable){
            itemCount = randvalue % lootBlock.countmax + 1;
        }
        else{
            itemCount = 1;
        }
    }

    std::list<Item*> itemList;


  
    while(itemCount > 0){
        uint16_t n = (uint16_t)std::min(itemCount, (int32_t)100);
        itemCount -= n;
      


        if((tmpItem = Item::CreateItem(lootBlock.id, n))){
            if(lootBlock.subType != -1){
                tmpItem->setSubType(lootBlock.subType);
            }

            if(lootBlock.actionId != -1)
            {
                tmpItem->setActionId(lootBlock.actionId);
            }
            // here

            if(tmpItem->getAttack() != 0)
                g_game.addAnimatedText(tmpItem->getPosition(), 66, "Item with attack dropped.");

            if(lootBlock.text != ""){
                tmpItem->setText(lootBlock.text);
            }

            itemList.push_back(tmpItem);
        }
    }

    return itemList;
}
 
The object was barely created and it certainly doesn't have any position set as of yet. On top of that calling it inside createLootItem of Monsters class is not a correct approach.

However, moving up a bit in the same file you probably have something like this:

C++:
void MonsterType::createLoot(Container* corpse)
{

for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && (corpse->capacity() - corpse->size() > 0); ++it){

    std::list<Item*> itemList = createLootItem(*it);

    if(!itemList.empty()){

        for(std::list<Item*>::iterator iit = itemList.begin(); iit != itemList.end(); ++iit){

            Item* tmpItem = *iit;

...

In this function corpse should have a set position, since before calling dropLoot (which then calls createLoot) the corpse is assigned to a tile, so it has a parent.

So, I assume the simplest way would be to do something like this in that void MonsterType::createLoot(Container* corpse) function:

C++:
if(tmpItem->getAttack() != 0)

    g_game.addAnimatedText(corpse->getPosition(), 66, "Item with attack dropped.");

Notice the position is taken from corpse and not tmpItem.

This is still not a proper approach, but at least should work for you. I cannot be sure about that though as it appears people do use a lot of different distributions (I did take a look at OTServ Legacy code since it was the only one similar enough to your functions, TFS has loot generation set in lua).
 
Solution
Back
Top