void ThingType::serialize(const FileStreamPtr& fin) { for(int i = 0; i < ThingLastAttr; ++i) { if(!hasAttr((ThingAttr)i)) continue; int attr = i; if(g_game.getClientVersion() >= 780) { if(attr == ThingAttrChargeable) attr = ThingAttrWritable; else if(attr >= ThingAttrWritable) attr += 1; } else if(g_game.getClientVersion() >= 1010) { if(attr == ThingAttrNoMoveAnimation) attr = 16; else if(attr >= ThingAttrPickupable) attr += 1; } fin->addU8(attr); switch(attr) { case ThingAttrDisplacement: { fin->addU16(m_displacement.x); fin->addU16(m_displacement.y); break; } case ThingAttrLight: { Light light = m_attribs.get<Light>(attr); fin->addU16(light.intensity); fin->addU16(light.color); break; } case ThingAttrMarket: { MarketData market = m_attribs.get<MarketData>(attr); fin->addU16(market.category); fin->addU16(market.tradeAs); fin->addU16(market.showAs); fin->addString(market.name); fin->addU16(market.restrictVocation); fin->addU16(market.requiredLevel); break; } case ThingAttrUsable: case ThingAttrElevation: case ThingAttrGround: case ThingAttrWritable: case ThingAttrWritableOnce: case ThingAttrMinimapColor: case ThingAttrCloth: case ThingAttrLensHelp: fin->addU16(m_attribs.get<uint16>(attr)); break; default: break; }; } fin->addU8(ThingLastAttr); fin->addU8(m_size.width()); fin->addU8(m_size.height()); if(m_size.width() > 1 || m_size.height() > 1) fin->addU8(m_realSize); fin->addU8(m_layers); fin->addU8(m_numPatternX); fin->addU8(m_numPatternY); fin->addU8(m_numPatternZ); fin->addU8(m_animationPhases); if(g_game.getFeature(Otc::GameEnhancedAnimations)) { if(m_animationPhases > 1) { fin->addU8(m_animation.async ? 0 : 1); fin->add32(m_animation.loopCount); fin->addU8(m_animation.startIndex); for(std::tuple<int, int> frame : m_animation.frames) { fin->addU32(std::get<0>(frame)); fin->addU32(std::get<1>(frame)); } } } for(uint i = 0; i < m_spritesIndex.size(); i++) { if(g_game.getFeature(Otc::GameSpritesU32)) fin->addU32(m_spritesIndex[i]); else fin->addU16(m_spritesIndex[i]); } }