• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

OTClient Module center outfit and up offset information bar

Michcol94

Member
Joined
Sep 2, 2021
Messages
105
Reaction score
18
Client: Otclient mehah latest current version,
Hello and welcome. I wanted to make a module that would center the character and raise information to the player when the graphics were too large and it looked bad. and it worked out for me to either raise the graphics or center the item. I added one or two functions to the sources in otclient mehah, because I don't know if such or similar ones exist, and I modified one of the client functions by adding my functions. I wrote something like this:
Module
name: game_creatureoffset
description: Changes the position of the informations point to correctly draw names and creature bars and outfit.
author: Michcol
autoload: true
reloadable: true
sandboxed: true
version: 1.0
scripts: [ game_creatureoffset ]
@onLoad: init()
@onUnload: terminate()
module/game_outfitoffset/game_outfitoffset.lua
Lua:
local CreatureOutfitOffsets = {
  [401] = { -- Outfit do pierwszego gif
      [North] = {x = -30, y = 0},
      [East] = {x = -30, y = 0},
      [South] = {x = -30, y = 0},
      [West] = {x = -30, y = 0},
  },

}


local PlayerInfoOffsets = {
  [401] = {x = 0, y = -20},
 
}

local function translateDir(dir)
  if dir == NorthEast or dir == SouthEast then
      return East
  elseif dir == NorthWest or dir == SouthWest then
      return West
  end
  return dir
end

local function getCreatureOutfitOffset(outfit, dir)
  if CreatureOutfitOffsets[outfit] then
      return CreatureOutfitOffsets[outfit][translateDir(dir)] or {x = 0, y = 0}
  end
  return {x = 0, y = 0}
end

local function getPlayerInfoOffset(outfit)
  return PlayerInfoOffsets[outfit] or {x = 0, y = 0}
end

local function onCreatureAppear(creature)
  local outfitOffset = getCreatureOutfitOffset(creature:getOutfit().type, creature:getDirection())
  local infoOffset = getPlayerInfoOffset(creature:getOutfit().type)

  if creature.setOutfitOffset then
      creature:setOutfitOffset(outfitOffset.x, outfitOffset.y)
  else
      print("Obiekt stworzenia nie posiada metody setOutfitOffset.")
  end
 
  if creature.setInformationOffset then
      creature:setInformationOffset(infoOffset.x, infoOffset.y)
  else
      print("Obiekt stworzenia nie posiada metody setInformationOffset.")
  end
end

local function onCreatureDirectionChange(creature, oldDirection, newDirection)
  local outfitOffset = getCreatureOutfitOffset(creature:getOutfit().type, newDirection)
  local infoOffset = getPlayerInfoOffset(creature:getOutfit().type)

  creature:setInformationOffset(infoOffset.x, infoOffset.y)
  creature:setOutfitOffset(outfitOffset.x, outfitOffset.y)
end

local function onCreatureOutfitChange(creature, newOutfit, oldOutfit)
  local outfitOffset = getCreatureOutfitOffset(newOutfit.type, creature:getDirection())
  local infoOffset = getPlayerInfoOffset(newOutfit.type)

  creature:setInformationOffset(infoOffset.x, infoOffset.y)
  creature:setOutfitOffset(outfitOffset.x, outfitOffset.y)
end

function init()
  connect(LocalPlayer, { onOutfitChange = onCreatureOutfitChange })
  connect(Creature, {
      onAppear = onCreatureAppear,
      onDirectionChange = onCreatureDirectionChange,
      onOutfitChange = onCreatureOutfitChange
  })
end

function terminate()
  disconnect(LocalPlayer, { onOutfitChange = onCreatureOutfitChange })
  disconnect(Creature, {
      onAppear = onCreatureAppear,
      onDirectionChange = onCreatureDirectionChange,
      onOutfitChange = onCreatureOutfitChange
  })
end
creature.cpp
Source otclient:

C++:
void Creature::drawInformation(const MapPosInfo& mapRect, const Point& dest, bool useGray, int drawFlags)
{
    static const Color
        DEFAULT_COLOR(96, 96, 96),
        NPC_COLOR(0x66, 0xcc, 0xff);

    if (isDead() || !canBeSeen() || !(drawFlags & Otc::DrawCreatureInfo) || !mapRect.isInRange(m_position))
        return;

    const auto& jumpOffset = m_jumpOffset * g_drawPool.getScaleFactor();
    const auto& parentRect = mapRect.rect;
    const auto& creatureOffset = Point(16 - getDisplacementX(), -getDisplacementY() - 2) + m_walkOffset;

    Point p = dest - mapRect.drawOffset;
    p += creatureOffset * g_drawPool.getScaleFactor() - Point(std::round(jumpOffset.x), std::round(jumpOffset.y));
    p += getInformationOffset(); // U�ycie getInformationOffset
    p.x *= mapRect.horizontalStretchFactor;
    p.y *= mapRect.verticalStretchFactor;
    p += parentRect.topLeft();

    auto fillColor = DEFAULT_COLOR;

    if (!useGray) {
        if (g_game.getFeature(Otc::GameBlueNpcNameColor) && isNpc() && isFullHealth())
            fillColor = NPC_COLOR;
        else
            fillColor = m_informationColor;
    }

    // calculate main rects

    const auto& nameSize = m_name.getTextSize();
    const int cropSizeText = g_gameConfig.isAdjustCreatureInformationBasedCropSize() ? getExactSize() : 12;
    const int cropSizeBackGround = g_gameConfig.isAdjustCreatureInformationBasedCropSize() ? cropSizeText - nameSize.height() : 0;

    g_drawPool.select(DrawPoolType::CREATURE_INFORMATION);
    {
        bool isScaled = g_app.getCreatureInformationScale() != PlatformWindow::DEFAULT_DISPLAY_DENSITY;
        if (isScaled) {
            g_drawPool.scale(g_app.getCreatureInformationScale());
            p.scale(g_app.getCreatureInformationScale());
        }

        auto backgroundRect = Rect(p.x - (13.5), p.y - cropSizeBackGround, 27, 4);
        auto textRect = Rect(p.x - nameSize.width() / 2.0, p.y - cropSizeText, nameSize);

        if (!isScaled) {
            backgroundRect.bind(parentRect);
            textRect.bind(parentRect);
        }

        // distance them
        uint8_t offset = 12 * g_drawPool.getScaleFactor();
        if (isLocalPlayer()) {
            offset *= 2 * g_drawPool.getScaleFactor();
        }

        if (textRect.top() == parentRect.top())
            backgroundRect.moveTop(textRect.top() + offset);
        if (backgroundRect.bottom() == parentRect.bottom())
            textRect.moveTop(backgroundRect.top() - offset);

        // health rect is based on background rect, so no worries
        Rect healthRect = backgroundRect.expanded(-1);
        healthRect.setWidth((m_healthPercent / 100.0) * 25);

        if (drawFlags & Otc::DrawBars) {
            g_drawPool.addFilledRect(backgroundRect, Color::black);
            g_drawPool.addFilledRect(healthRect, fillColor);

            if (drawFlags & Otc::DrawManaBar && isLocalPlayer()) {
                if (const auto& player = g_game.getLocalPlayer()) {
                    backgroundRect.moveTop(backgroundRect.bottom());

                    g_drawPool.addFilledRect(backgroundRect, Color::black);

                    Rect manaRect = backgroundRect.expanded(-1);
                    const double maxMana = player->getMaxMana();
                    manaRect.setWidth((maxMana ? player->getMana() / maxMana : 1) * 25);

                    g_drawPool.addFilledRect(manaRect, Color::blue);
                }
            }
        }

        if (drawFlags & Otc::DrawNames) {
            m_name.draw(textRect, fillColor);

#ifndef BOT_PROTECTION
            if (m_text) {
                auto extraTextSize = m_text->getTextSize();
                Rect extraTextRect = Rect(p.x - extraTextSize.width() / 2.0, p.y + 15, extraTextSize);
                m_text->drawText(extraTextRect.center(), extraTextRect);
            }
#endif
        }

        if (m_skull != Otc::SkullNone && m_skullTexture)
            g_drawPool.addTexturedPos(m_skullTexture, backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 5);

        if (m_shield != Otc::ShieldNone && m_shieldTexture && m_showShieldTexture)
            g_drawPool.addTexturedPos(m_shieldTexture, backgroundRect.x() + 13.5, backgroundRect.y() + 5);

        if (m_emblem != Otc::EmblemNone && m_emblemTexture)
            g_drawPool.addTexturedPos(m_emblemTexture, backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 16);

        if (m_type != Proto::CreatureTypeUnknown && m_typeTexture)
            g_drawPool.addTexturedPos(m_typeTexture, backgroundRect.x() + 13.5 + 12 + 12, backgroundRect.y() + 16);

        if (m_icon != Otc::NpcIconNone && m_iconTexture)
            g_drawPool.addTexturedPos(m_iconTexture, backgroundRect.x() + 13.5 + 12, backgroundRect.y() + 5);
    }
    // Go back to use map pool
    g_drawPool.select(DrawPoolType::MAP);
}
creature.h

C++:
public:   
    Point getInformationOffset() { return m_informationOffset; }
    void setInformationOffset(int x, int y) { m_informationOffset = Point(x, y); }

    Point getOutfitOffset() { return m_outfitOffset; }
    void setOutfitOffset(int x, int y) { m_outfitOffset = Point(x, y); }
private:
    Point m_informationOffset;
    Point m_outfitOffset;

I tried to change the code in various ways and didn't achieve anything, but either raising the information bar or centering the outfit worked. the offsets given in the table are examples and the code is also a sketch of what I want to do. Please help.
 
if I use negative offset in objectbuilder, I get the effect that a figure appears in the upper left corner of the window, at least the information bar appears there



screen object builder:Zrzut ekranu 2023-12-18 104947.pngZrzut ekranu 2023-12-18 104937.png
I remember that when I tried to move the outfit and center it, I changed the source client, will this be the fault of my changes?

Zrzut ekranu 2023-12-18 104655.png
 
Back
Top