Example #1
0
bool Tile::removeThing(ThingPtr thing)
{
    if(!thing)
        return false;

    bool removed = false;

    if(thing->isEffect()) {
        EffectPtr effect = thing->static_self_cast<Effect>();
        auto it = std::find(m_effects.begin(), m_effects.end(), effect);
        if(it != m_effects.end()) {
            m_effects.erase(it);
            removed = true;
        }
    } else {
        auto it = std::find(m_things.begin(), m_things.end(), thing);
        if(it != m_things.end()) {
            m_things.erase(it);
            removed = true;
        }
    }

    thing->onDisappear();

    if(thing->isTranslucent())
        checkTranslucentLight();

    return removed;
}
Example #2
0
void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
{
    if(!thing)
        return;

    if(thing->isItem() || thing->isCreature() || thing->isEffect()) {
        const TilePtr& tile = getOrCreateTile(pos);
        if(tile)
            tile->addThing(thing, stackPos);
    } else {
        if(thing->isMissile()) {
            m_floorMissiles[pos.z].push_back(thing->static_self_cast<Missile>());
            thing->onAppear();
        } else if(thing->isAnimatedText()) {
            // this code will stack animated texts of the same color
            AnimatedTextPtr animatedText = thing->static_self_cast<AnimatedText>();
            AnimatedTextPtr prevAnimatedText;
            bool merged = false;
            for(auto other : m_animatedTexts) {
                if(other->getPosition() == pos) {
                    prevAnimatedText = other;
                    if(other->merge(animatedText)) {
                        merged = true;
                        break;
                    }
                }
            }
            if(!merged) {
                if(prevAnimatedText) {
                    Point offset = prevAnimatedText->getOffset();
                    float t = prevAnimatedText->getTimer().ticksElapsed();
                    if(t < Otc::ANIMATED_TEXT_DURATION / 4.0) { // didnt move 12 pixels
                        int y = 12 - 48 * t / (float)Otc::ANIMATED_TEXT_DURATION;
                        offset += Point(0, y);
                    }
                    offset.y = std::min<int>(offset.y, 12);
                    animatedText->setOffset(offset);
                }
                m_animatedTexts.push_back(animatedText);
            }
        } else if(thing->isStaticText()) {
            StaticTextPtr staticText = thing->static_self_cast<StaticText>();
            bool mustAdd = true;
            for(auto other : m_staticTexts) {
                // try to combine messages
                if(other->getPosition() == pos && other->addMessage(staticText->getName(), staticText->getMessageMode(), staticText->getFirstMessage())) {
                    mustAdd = false;
                    break;
                }
            }

            if(mustAdd)
                m_staticTexts.push_back(staticText);
            else
                return;
        }

        thing->setPosition(pos);
        thing->onAppear();
    }

    notificateTileUpdate(pos);
}
Example #3
0
void Tile::addThing(const ThingPtr& thing, int stackPos)
{
    if(!thing)
        return;

    if(thing->isEffect()) {
        m_effects.push_back(thing->static_self_cast<Effect>());
    } else {
        // priority                                    854
        // 0 - ground,                        -->      -->
        // 1 - ground borders                 -->      -->
        // 2 - bottom (walls),                -->      -->
        // 3 - on top (doors)                 -->      -->
        // 4 - creatures, from top to bottom  <--      -->
        // 5 - items, from top to bottom      <--      <--
        if(stackPos < 0 || stackPos == 255) {
            int priority = thing->getStackPriority();

            // -1 or 255 => auto detect position
            // -2        => append

            bool append;
            if(stackPos == -2)
                append = true;
            else {
                append = (priority <= 3);

                // newer protocols does not store creatures in reverse order
                if(g_game.getProtocolVersion() >= 854 && priority == 4)
                    append = !append;
            }


            for(stackPos = 0; stackPos < (int)m_things.size(); ++stackPos) {
                int otherPriority = m_things[stackPos]->getStackPriority();
                if((append && otherPriority > priority) || (!append && otherPriority >= priority))
                    break;
            }
        } else if(stackPos > (int)m_things.size())
            stackPos = m_things.size();

        m_things.insert(m_things.begin() + stackPos, thing);

        if(m_things.size() > MAX_THINGS)
            removeThing(m_things[MAX_THINGS]);

        /*
        // check stack priorities
        // this code exists to find stackpos bugs faster
        int lastPriority = 0;
        for(const ThingPtr& thing : m_things) {
            int priority = thing->getStackPriority();
            assert(lastPriority <= priority);
            lastPriority = priority;
        }
        */
    }

    thing->setPosition(m_position);
    thing->onAppear();

    if(thing->isTranslucent())
        checkTranslucentLight();
}