示例#1
0
void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin)
{
    m_null = false;
    m_id = clientId;
    m_category = category;

    int count = 0, attr = -1;
    bool done = false;
    for(int i = 0 ; i < ThingLastAttr;++i) {
        count++;
        attr = fin->getU8();
        if(attr == ThingLastAttr) {
            done = true;
            break;
        }

        if(g_game.getClientVersion() >= 1000) {
            /* In 10.10+ all attributes from 16 and up were
             * incremented by 1 to make space for 16 as
             * "No Movement Animation" flag.
             */
            if(attr == 16)
                attr = ThingAttrNoMoveAnimation;
            else if(attr > 16)
                attr -= 1;
        } else if(g_game.getClientVersion() >= 860) {
            /* Default attribute values follow
             * the format of 8.6-9.86.
             * Therefore no changes here.
             */
        } else if(g_game.getClientVersion() >= 780) {
            /* In 7.80-8.54 all attributes from 8 and higher were
             * incremented by 1 to make space for 8 as
             * "Item Charges" flag.
             */
            if(attr == 8) {
                m_attribs.set(ThingAttrChargeable, true);
                continue;
            } else if(attr > 8)
                attr -= 1;
        } else if(g_game.getClientVersion() >= 755) {
            /* In 7.55-7.72 attributes 23 is "Floor Change". */
            if(attr == 23)
                attr = ThingAttrFloorChange;
        } else if(g_game.getClientVersion() >= 740) {
            /* In 7.4-7.5 attribute "Ground Border" did not exist
             * attributes 1-15 have to be adjusted.
             * Several other changes in the format.
             */
            if(attr > 0 && attr <= 15)
                attr += 1;
            else if(attr == 16)
                attr = ThingAttrLight;
            else if(attr == 17)
                attr = ThingAttrFloorChange;
            else if(attr == 18)
                attr = ThingAttrFullGround;
            else if(attr == 19)
                attr = ThingAttrElevation;
            else if(attr == 20)
                attr = ThingAttrDisplacement;
            else if(attr == 22)
                attr = ThingAttrMinimapColor;
            else if(attr == 23)
                attr = ThingAttrRotateable;
            else if(attr == 24)
                attr = ThingAttrLyingCorpse;
            else if(attr == 25)
                attr = ThingAttrHangable;
            else if(attr == 26)
                attr = ThingAttrHookSouth;
            else if(attr == 27)
                attr = ThingAttrHookEast;
            else if(attr == 28)
                attr = ThingAttrAnimateAlways;

            /* "Multi Use" and "Force Use" are swapped */
            if(attr == ThingAttrMultiUse)
                attr = ThingAttrForceUse;
            else if(attr == ThingAttrForceUse)
                attr = ThingAttrMultiUse;
        }

        switch(attr) {
            case ThingAttrDisplacement: {
                if(g_game.getClientVersion() >= 755) {
                    m_displacement.x = fin->getU16();
                    m_displacement.y = fin->getU16();
                } else {
                    m_displacement.x = 8;
                    m_displacement.y = 8;
                }
                m_attribs.set(attr, true);
                break;
            }
            case ThingAttrLight: {
                Light light;
                light.intensity = fin->getU16();
                light.color = fin->getU16();
                m_attribs.set(attr, light);
                break;
            }
            case ThingAttrMarket: {
                MarketData market;
                market.category = fin->getU16();
                market.tradeAs = fin->getU16();
                market.showAs = fin->getU16();
                market.name = fin->getString();
                market.restrictVocation = fin->getU16();
                market.requiredLevel = fin->getU16();
                m_attribs.set(attr, market);
                break;
            }
            case ThingAttrElevation: {
                m_elevation = fin->getU16();
                m_attribs.set(attr, m_elevation);
                break;
            }
            case ThingAttrUsable:
            case ThingAttrGround:
            case ThingAttrWritable:
            case ThingAttrWritableOnce:
            case ThingAttrMinimapColor:
            case ThingAttrCloth:
            case ThingAttrLensHelp:
                m_attribs.set(attr, fin->getU16());
                break;
            default:
                m_attribs.set(attr, true);
                break;
        };
    }

    if(!done)
        stdext::throw_exception(stdext::format("corrupt data (id: %d, category: %d, count: %d, lastAttr: %d)",
            m_id, m_category, count, attr));

    bool hasFrameGroups = (category == ThingCategoryCreature && g_game.getFeature(Otc::GameIdleAnimations));
    uint8 groupCount = hasFrameGroups ? fin->getU8() : 1;

    for(int i = 0; i < groupCount; ++i) {
        uint8 frameGroupType = FrameGroupDefault;
        if(hasFrameGroups)
            frameGroupType = fin->getU8();

        uint8 width = fin->getU8();
        uint8 height = fin->getU8();
        m_size = Size(width, height);
        if(width > 1 || height > 1) {
            m_realSize = fin->getU8();
            m_exactSize = std::min<int>(m_realSize, std::max<int>(width * 32, height * 32));
        }
        else
            m_exactSize = 32;

        m_layers = fin->getU8();
        m_numPatternX = fin->getU8();
        m_numPatternY = fin->getU8();
        if(g_game.getClientVersion() >= 755)
            m_numPatternZ = fin->getU8();
        else
            m_numPatternZ = 1;
        m_animationPhases = fin->getU8();

        if(m_animationPhases > 1 && g_game.getFeature(Otc::GameEnhancedAnimations)) {
            m_animator = AnimatorPtr(new Animator);
            m_animator->unserialize(m_animationPhases, fin);
        }

        int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;

        if(totalSprites > 4096)
            stdext::throw_exception("a thing type has more than 4096 sprites");

        m_spritesIndex.resize(totalSprites);
        for(int i = 0; i < totalSprites; i++)
            m_spritesIndex[i] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();
    }

    m_textures.resize(m_animationPhases);
    m_texturesFramesRects.resize(m_animationPhases);
    m_texturesFramesOriginRects.resize(m_animationPhases);
    m_texturesFramesOffsets.resize(m_animationPhases);
}
示例#2
0
bool Map::loadOtcm(const std::string& fileName)
{
    try {
        FileStreamPtr fin = g_resources.openFile(fileName);
        if(!fin)
            stdext::throw_exception("unable to open file");

        stdext::timer loadTimer;
        fin->cache();

        uint32 signature = fin->getU32();
        if(signature != OTCM_SIGNATURE)
            stdext::throw_exception("invalid otcm file");

        uint16 start = fin->getU16();
        uint16 version = fin->getU16();
        fin->getU32(); // flags

        switch(version) {
            case 1: {
                fin->getString(); // description
                uint32 datSignature = fin->getU32();
                fin->getU16(); // protocol version
                fin->getString(); // world name

                if(datSignature != g_things.getDatSignature())
                    g_logger.warning("otcm map loaded was created with a different dat signature");

                break;
            }
            default:
                stdext::throw_exception("otcm version not supported");
        }

        fin->seek(start);

        while(true) {
            Position pos;

            pos.x = fin->getU16();
            pos.y = fin->getU16();
            pos.z = fin->getU8();

            // end of file
            if(!pos.isValid())
                break;

            const TilePtr& tile = g_map.createTile(pos);

            int stackPos = 0;
            while(true) {
                int id = fin->getU16();

                // end of tile
                if(id == 0xFFFF)
                    break;

                int countOrSubType = fin->getU8();

                ItemPtr item = Item::create(id);
                item->setCountOrSubType(countOrSubType);

                if(item->isValid())
                    tile->addThing(item, stackPos++);
            }
        }

        fin->close();

        g_logger.debug(stdext::format("Otcm load time: %.2f seconds", loadTimer.elapsed_seconds()));
        return true;
    } catch(stdext::exception& e) {
        g_logger.error(stdext::format("failed to load OTCM map: %s", e.what()));
        return false;
    }
}
示例#3
0
void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin)
{
    m_null = false;
    m_id = clientId;
    m_category = category;

    bool done = false;
    for(int i = 0 ; i < ThingLastAttr;++i) {
        int attr = fin->getU8();
        if(attr == ThingLastAttr) {
            done = true;
            break;
        }

        if(g_game.getFeature(Otc::GameChargeableItems)) {
            if(attr == ThingAttrWritable) {
                m_attribs.set(ThingAttrChargeable, true);
                continue;
            } else if(attr > ThingAttrWritable)
                attr -= 1;
        }

        if(g_game.getProtocolVersion() >= 1010) {
            /* In 10.10 all attributes from 16 and up were
             * incremented by 1 to make space for 16 as
             * "No Movement Animation" flag.
             */
            if(attr == 16)
                attr = ThingAttrNoMoveAnimation;
            else if(attr > 16)
                attr -= 1;
        }

        switch(attr) {
            case ThingAttrDisplacement: {
                m_displacement.x = fin->getU16();
                m_displacement.y = fin->getU16();
                m_attribs.set(attr, true);
                break;
            }
            case ThingAttrLight: {
                Light light;
                light.intensity = fin->getU16();
                light.color = fin->getU16();
                m_attribs.set(attr, light);
                break;
            }
            case ThingAttrMarket: {
                MarketData market;
                market.category = fin->getU16();
                market.tradeAs = fin->getU16();
                market.showAs = fin->getU16();
                market.name = fin->getString();
                market.restrictVocation = fin->getU16();
                market.requiredLevel = fin->getU16();
                m_attribs.set(attr, market);
                break;
            }
            case ThingAttrElevation: {
                m_elevation = fin->getU16();
                m_attribs.set(attr, m_elevation);
                break;
            }
            case ThingAttrGround:
            case ThingAttrWritable:
            case ThingAttrWritableOnce:
            case ThingAttrMinimapColor:
            case ThingAttrCloth:
            case ThingAttrLensHelp:
                m_attribs.set(attr, fin->getU16());
                break;
            default:
                m_attribs.set(attr, true);
                break;
        };
    }

    if(!done)
        stdext::throw_exception("corrupt data");

    uint8 width = fin->getU8();
    uint8 height = fin->getU8();
    m_size = Size(width, height);
    m_exactSize = (width > 1 || height > 1) ? std::min((int)fin->getU8(), std::max(width * 32, height * 32)) : 32;
    m_layers = fin->getU8();
    m_numPatternX = fin->getU8();
    m_numPatternY = fin->getU8();
    m_numPatternZ = fin->getU8();
    m_animationPhases = fin->getU8();

    int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;

    // if(totalSprites == 0)
    //     stdext::throw_exception("a thing type has no sprites");
    if(totalSprites > 4096)
        stdext::throw_exception("a thing type has more than 4096 sprites");

    m_spritesIndex.resize(totalSprites);
    for(int i = 0; i < totalSprites; i++)
        m_spritesIndex[i] = g_game.getFeature(Otc::GameSpritesU32) ? fin->getU32() : fin->getU16();

    m_textures.resize(m_animationPhases);
    m_texturesFramesRects.resize(m_animationPhases);
    m_texturesFramesOriginRects.resize(m_animationPhases);
    m_texturesFramesOffsets.resize(m_animationPhases);
}