Ir para conteúdo

Featured Replies

Postado

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:

getExactSize

encontrará 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:

getExactHeight

desce 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 rects

logo 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/poke

int cropSizeText = getExactSize();

// nome, level, genero e barra estáticos

// se usar quadro de caminhada o nome pula enquanto o player anda

if (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.

ANTES

nomes desajustados das sprites

06-pidgeot-fearow-antes.png

01-nightain-antes.png

DEPOIS

nomes ajustados no centro da sprite

image.png

image.png



😈 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/poke


Eu 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.

Visitante
Responder

Quem Está Navegando 0

  • Nenhum usuário registrado visualizando esta página.

Estatísticas dos Fóruns

  • Tópicos 96.1k
  • Posts 512.6k

Informação Importante

Confirmação de Termo