Postado 12 horas12 hs Salve.Quero compartilhar com vocês um Height adjustment.Ajuste de nome em cima do monstro/player: barra de hp/nome ficam estáticos e centralizados um pouco acima da cabeça player/pokémon, mais precisamente no centro da sprite.Instalação: a alteração é apenas na source (C++), compile o OTclient depois.Primeiro, abre o arquivo src\client\thingtype.h no otc e procure por:getExactSizeencontrará essa linha:int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);cole essa linha em baixo (e salve: ctrl + s):bool getSpriteBounds(int& left, int& top, int& width, int& height, int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);Agora abra o arquivo src\client\thingtype.cpp no otc e procure por:getExactHeightdesce um pouquinho até achar essa:return m_exactHeight = size.height();antes do 'ThingFlagAttr', cole isso aqui (e salve também):bool ThingType::getSpriteBounds(int& left, int& top, int& width, int& height, int layer, int xPattern, int yPattern, int zPattern, int animationPhase){ if (m_null) return false; // pokemon parado caso o quadro seja invalido if (animationPhase < 0 || animationPhase >= m_animationPhases) animationPhase = 0; if (!getTexture(animationPhase)) return false; const auto& pos = m_textureData[animationPhase].pos; if (pos.empty()) return false; const int frameIndex = getTextureIndex(layer, xPattern, yPattern, zPattern); if (frameIndex < 0 || frameIndex >= static_cast<int>(pos.size())) return false; const auto& frame = pos[frameIndex]; if (frame.rects.isEmpty()) return false; // nao vai contar a transparencia by nort0n const int spriteSize = g_gameConfig.getSpriteSize(); left = frame.offsets.x - m_displacement.x - (m_size.width() - 1) * spriteSize; top = frame.offsets.y - m_displacement.y - (m_size.height() - 1) * spriteSize; width = frame.rects.width(); height = frame.rects.height(); return width > 0 && height > 0;}Bom, finalizando essa parte vamos pra src\client\creature.cpp, no otc procure por:calculate main rectslogo abaixo tem essas 3 linhas:const auto& nameSize = m_name.getTextSize();const int cropSizeText = getExactSize();const int cropSizeBackGround = cropSizeText - nameSize.height();apague as 3 linhas e no lugar coloque (e salve tudo):const auto& nameSize = m_name.getTextSize();const int barHeight = 4;const int spriteGap = 8; // quanto maior o número, mais distante da cabeça do player/pokeint cropSizeText = getExactSize();// nome, level, genero e barra estáticos// se usar quadro de caminhada o nome pula enquanto o player andaif (auto* thingType = getThingType()) { const int spriteSize = g_gameConfig.getSpriteSize(); const int numX = std::max(1, thingType->getNumPatternX()); const int numY = std::max(1, getNumPatternY()); int dirX = m_numPatternX; if (dirX < 0) dirX = 0; if (dirX >= numX) dirX = numX - 1; // vai ler só o quadro parado auto sampleStanding = [&](int xPattern, int yPattern, int& left, int& top, int& right) -> bool { int width = 0; int height = 0; if (!thingType->getSpriteBounds(left, top, width, height, 0, xPattern, yPattern, m_numPatternZ, 0)) return false; right = left + width; (void)height; return width > 0; }; // onde a cabeça costuma ficar std::vector<int> idleTops; idleTops.reserve(static_cast<size_t>(numX)); for (int xPattern = 0; xPattern < numX; ++xPattern) { int sampleLeft = 0; int sampleTop = 0; int sampleRight = 0; if (sampleStanding(xPattern, 0, sampleLeft, sampleTop, sampleRight)) idleTops.push_back(sampleTop); } // direção em que ele está virado int spriteLeft = 0; int spriteTop = 0; int spriteRight = 0; bool hasBody = sampleStanding(dirX, 0, spriteLeft, spriteTop, spriteRight); if (!hasBody) { for (int xPattern = 0; xPattern < numX && !hasBody; ++xPattern) hasBody = sampleStanding(xPattern, 0, spriteLeft, spriteTop, spriteRight); } if (hasBody) { // se uma direção estiver esticada demais pra cima, usa a cabeçaa normal if (!idleTops.empty()) { std::sort(idleTops.begin(), idleTops.end()); const int typicalTop = idleTops[idleTops.size() / 2]; if (typicalTop - spriteTop > spriteSize) spriteTop = typicalTop; } // addon que encosta na cabeça entra normal e addon muito alto fica de fora for (int yPattern = 1; yPattern < numY; ++yPattern) { if (!(m_outfit.getAddons() & (1 << (yPattern - 1)))) continue; int addonLeft = 0; int addonTop = 0; int addonRight = 0; if (!sampleStanding(dirX, yPattern, addonLeft, addonTop, addonRight)) continue; if (spriteTop - addonTop > spriteSize) continue; if (addonTop < spriteTop) spriteTop = addonTop; } const bool negativeOffset = g_game.getFeature(Otc::GameNegativeOffset); const int dispInfoX = negativeOffset ? 0 : getDisplacementX(); const int dispInfoY = negativeOffset ? 0 : getDisplacementY(); const float scaleX = mapRect.scaleFactor * mapRect.horizontalStretchFactor; const float scaleY = mapRect.scaleFactor * mapRect.verticalStretchFactor; // centraliza o nome pro meio do corpo const float spriteCenterX = spriteLeft + (spriteRight - spriteLeft) / 2.f; p.x += (spriteCenterX - (16 - dispInfoX)) * scaleX; cropSizeText = static_cast<int>(std::lround( nameSize.height() + barHeight + scaleY * (spriteGap - spriteTop - dispInfoY - 2))); }}const int cropSizeBackGround = cropSizeText - nameSize.height();Agora basta compilar o otclient e fazer o teste.ANTESnomes desajustados das spritesDEPOISnomes ajustados no centro da sprite😈 Editamento: em src\client\creature.cpp, alterando o número você aproxima ou afasta a barra e o nome. Ao editar, salva e compila o otClient novamente.const int spriteGap = 8; // quanto maior o número, mais distante da cabeça do player/pokeEu ainda acho que aproximar mais deixa mais bonito. Fica a dica.Esta adaptação é apenas visual, dentro do OTCLIENT (com source) e totalmente funcional.Créditos:Eu por adaptar do 0 e trazer aqui.Não dou suporte, somente freela. Faça bom uso.
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.