• 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!

Solved Change from chase mode to Stand While Fighting mode

ralke

(҂ ͠❛ ෴ ͡❛)ᕤ
Joined
Dec 17, 2011
Messages
1,541
Solutions
28
Reaction score
875
Location
Santiago - Chile
GitHub
ralke23
Twitch
ralke23
Using TFS 1.5, mehah otclient and A* algorythm from @Itutorial

Testing with mehah's otclient, when you attack while you're with chasing mode enabled, then you move, it start to hesitate between following or leaving the target. It should change from chase mode to Stand While Fighting mode. I also tested the same thing on Tibia 8.6 client and it works good, this is why I think is a client-side thing.

OTClient logs sent me this:
Code:
Codicia 3.x rev 0.000 (desenv) built on Dec 31 2023 for arch x64
Exiting application..
== aplicación iniciada el Apr 25 2024 20:12:31
== sistema operativo: Windows
Codicia 3.x rev 0.000 (desenv) built on Dec 31 2023 for arch x64
2
1
2
1
2
1
2
Exiting application..
== aplicación iniciada el Apr 25 2024 22:09:42
== sistema operativo: Windows
Codicia 3.x rev 0.000 (desenv) built on Dec 31 2023 for arch x64
Exiting application..

Here's the video evidence.

Anyways, any idea of where can I start fixing this? I'm going to have to update my mehah client sources to see if i'm missing something but I would like to know specifically why it is happening. Any help is appreciated!

Regards.
Post automatically merged:

Here's also my game_inventory/inventory.lua based on what I saw here:

Lua:
Icons = {}
Icons[PlayerStates.Poison] = {
    tooltip = tr('Estás envenenado'),
    path = '/images/game/states/poisoned',
    id = 'condition_poisoned'
}
Icons[PlayerStates.Burn] = {
    tooltip = tr('Estás ardiendo'),
    path = '/images/game/states/burning',
    id = 'condition_burning'
}
Icons[PlayerStates.Energy] = {
    tooltip = tr('Estás electrificado'),
    path = '/images/game/states/electrified',
    id = 'condition_electrified'
}
Icons[PlayerStates.Drunk] = {
    tooltip = tr('Estás ebrio'),
    path = '/images/game/states/drunk',
    id = 'condition_drunk'
}
Icons[PlayerStates.ManaShield] = {
    tooltip = tr('Estás protegido por un escudo mágico'),
    path = '/images/game/states/magic_shield',
    id = 'condition_magic_shield'
}
Icons[PlayerStates.Paralyze] = {
    tooltip = tr('Estás paralizado'),
    path = '/images/game/states/slowed',
    id = 'condition_slowed'
}
Icons[PlayerStates.Haste] = {
    tooltip = tr('Estás acelerado'),
    path = '/images/game/states/haste',
    id = 'condition_haste'
}
Icons[PlayerStates.Swords] = {
    tooltip = tr('No puedes cerrar sesión durante una pelea'),
    path = '/images/game/states/logout_block',
    id = 'condition_logout_block'
}
Icons[PlayerStates.Drowning] = {
    tooltip = tr('Te Estás ahogando'),
    path = '/images/game/states/drowning',
    id = 'condition_drowning'
}
Icons[PlayerStates.Freezing] = {
    tooltip = tr('Te Estás congelando'),
    path = '/images/game/states/freezing',
    id = 'condition_freezing'
}
Icons[PlayerStates.Dazzled] = {
    tooltip = tr('Estás deslumbrado'),
    path = '/images/game/states/dazzled',
    id = 'condition_dazzled'
}
Icons[PlayerStates.Cursed] = {
    tooltip = tr('Estás maldito'),
    path = '/images/game/states/cursed',
    id = 'condition_cursed'
}
Icons[PlayerStates.PartyBuff] = {
    tooltip = tr('Estás fortalecido'),
    path = '/images/game/states/strengthened',
    id = 'condition_strengthened'
}
Icons[PlayerStates.PzBlock] = {
    tooltip = tr('No puedes cerrar sesión ni ingresar a una zona de protección'),
    path = '/images/game/states/protection_zone_block',
    id = 'condition_protection_zone_block'
}
Icons[PlayerStates.Pz] = {
    tooltip = tr('Estás dentro de una zona de protección'),
    path = '/images/game/states/protection_zone',
    id = 'condition_protection_zone'
}
Icons[PlayerStates.Bleeding] = {
    tooltip = tr('Estás sangrando'),
    path = '/images/game/states/bleeding',
    id = 'condition_bleeding'
}
Icons[PlayerStates.Hungry] = {
    tooltip = tr('Estás hambriento'),
    path = '/images/game/states/hungry',
    id = 'condition_hungry'
}

InventorySlotStyles = {
    [InventorySlotHead] = 'HeadSlot',
    [InventorySlotNeck] = 'NeckSlot',
    [InventorySlotBack] = 'BackSlot',
    [InventorySlotBody] = 'BodySlot',
    [InventorySlotRight] = 'RightSlot',
    [InventorySlotLeft] = 'LeftSlot',
    [InventorySlotLeg] = 'LegSlot',
    [InventorySlotFeet] = 'FeetSlot',
    [InventorySlotFinger] = 'FingerSlot',
    [InventorySlotAmmo] = 'AmmoSlot'
}

inventoryWindow = nil
inventoryPanel = nil
inventoryButton = nil
purseButton = nil
-- improve inventory soul / cap / states
soulLabel = nil
capLabel = nil

fightOffensiveBox = nil
fightBalancedBox = nil
fightDefensiveBox = nil
chaseModeButton = nil
safeFightButton = nil

fightModeRadioGroup = nil

function init()
    connect(LocalPlayer, {
        onInventoryChange = onInventoryChange,
        onBlessingsChange = onBlessingsChange,
        onSoulChange = onSoulChange,
        onFreeCapacityChange = onFreeCapacityChange,
        onStatesChange = onStatesChange
    })


    g_keyboard.bindKeyDown('Ctrl+I', toggle)

    inventoryButton = modules.client_topmenu.addRightGameToggleButton('inventoryButton', tr('Inventario') .. ' (Ctrl+I)',
        '/images/topbuttons/inventory', toggle)
    inventoryButton:setOn(true)

    inventoryWindow = g_ui.loadUI('inventory')
    inventoryWindow:disableResize()
    inventoryPanel = inventoryWindow:getChildById('contentsPanel'):getChildById('inventoryPanel')

    purseButton = inventoryPanel:getChildById('purseButton')

    -- improve inventory soul / cap / states
    soulLabel = inventoryWindow:recursiveGetChildById('soulLabel')
    capLabel = inventoryWindow:recursiveGetChildById('capLabel')

    for k, v in pairs(Icons) do
        g_textures.preload(v.path)
    end

    -- Combat Controls
    fightOffensiveBox = inventoryWindow:recursiveGetChildById('fightOffensiveBox')
    fightBalancedBox = inventoryWindow:recursiveGetChildById('fightBalancedBox')
    fightDefensiveBox = inventoryWindow:recursiveGetChildById('fightDefensiveBox')


    chaseModeButton = inventoryWindow:recursiveGetChildById('chaseModeBox')
    safeFightButton = inventoryWindow:recursiveGetChildById('safeFightBox')

    fightModeRadioGroup = UIRadioGroup.create()
    fightModeRadioGroup:addWidget(fightOffensiveBox)
    fightModeRadioGroup:addWidget(fightBalancedBox)
    fightModeRadioGroup:addWidget(fightDefensiveBox)



    connect(fightModeRadioGroup, {
        onSelectionChange = onSetFightMode
    })
    connect(pvpModeRadioGroup, {
        onSelectionChange = onSetPVPMode
    })
    connect(chaseModeButton, {
        onCheckChange = onSetChaseMode
    })
    connect(safeFightButton, {
        onCheckChange = onSetSafeFight
    })

    local function purseFunction()
        local purse = g_game.getLocalPlayer():getInventoryItem(InventorySlotPurse)
        if purse then
            g_game.use(purse)
        end
    end
    purseButton.onClick = purseFunction
    connect(g_game, {
        onGameStart = online,
        onGameEnd = offline,
        onFightModeChange = update,
        onChaseModeChange = update,
        onSafeFightChange = update,

        onWalk = check,
        onAutoWalk = check
    })
    refresh()
    inventoryWindow:setup()
    if g_game.isOnline() then
        local localPlayer = g_game.getLocalPlayer()
        onStatesChange(localPlayer, localPlayer:getStates(), 0)
        inventoryWindow:setupOnStart()
        online()
    end
end

function terminate()
    if g_game.isOnline() then
        offline()
    end
    disconnect(LocalPlayer, {
        onInventoryChange = onInventoryChange,
        onBlessingsChange = onBlessingsChange,
        onSoulChange = onSoulChange,
        onFreeCapacityChange = onFreeCapacityChange,
        onStatesChange = onStatesChange
    })
    disconnect(g_game, {
        onGameStart = online,
        onGameEnd = offline,
        onFightModeChange = update,
        onChaseModeChange = update,
        onSafeFightChange = update,

        onWalk = check,
    onAutoWalk = check
    })

    g_keyboard.unbindKeyDown('Ctrl+I')

    inventoryWindow:destroy()
    inventoryButton:destroy()

    fightModeRadioGroup:destroy()

    inventoryWindow = nil
    inventoryPanel = nil
    inventoryButton = nil
    purseButton = nil
    soulLabel = nil
    capLabel = nil

    fightOffensiveBox = nil
    fightBalancedBox = nil
    fightDefensiveBox = nil
    chaseModeButton = nil
    safeFightButton = nil

    fightModeRadioGroup = nil

end

function toggleAdventurerStyle(hasBlessing)
    for slot = InventorySlotFirst, InventorySlotLast do
        local itemWidget = inventoryPanel:getChildById('slot' .. slot)
        if itemWidget then
            itemWidget:setOn(hasBlessing)
        end
    end
end

function online()
    inventoryWindow:setupOnStart() -- load character window configuration
    local player = g_game.getLocalPlayer()
    if player then
        local char = g_game.getCharacterName()

        local lastCombatControls = g_settings.getNode('LastCombatControls')

        if not table.empty(lastCombatControls) then
            if lastCombatControls[char] then
                g_game.setFightMode(lastCombatControls[char].fightMode)
                g_game.setChaseMode(lastCombatControls[char].chaseMode)
                g_game.setSafeFight(lastCombatControls[char].safeFight)
                if lastCombatControls[char].pvpMode then
                    g_game.setPVPMode(lastCombatControls[char].pvpMode)
                end
            end
        end

     --[[   if g_game.getFeature(GamePlayerMounts) then
            mountButton:setVisible(true)
            mountButton:setChecked(player:isMounted())
        else
            mountButton:setVisible(false)
        end ]]

     --[[     if g_game.getFeature(GamePVPMode) then
            pvpModesPanel:setVisible(true)
            combatControlsWindow:setHeight(combatControlsWindow.extendedControlsHeight)
        else
            pvpModesPanel:setVisible(false)
            combatControlsWindow:setHeight(combatControlsWindow.simpleControlsHeight)
        end ]]
    end

 
    update()
    refresh()

end

function offline()
    inventoryWindow:setParent(nil, true)
    local lastCombatControls = g_settings.getNode('LastCombatControls')
    if not lastCombatControls then
        lastCombatControls = {}
    end

    local player = g_game.getLocalPlayer()
    if player then
        local char = g_game.getCharacterName()
        lastCombatControls[char] = {
            fightMode = g_game.getFightMode(),
            chaseMode = g_game.getChaseMode(),
            safeFight = g_game.isSafeFight()
        }

        if g_game.getFeature(GamePVPMode) then
            lastCombatControls[char].pvpMode = g_game.getPVPMode()
        end

        -- save last combat control settings
        g_settings.setNode('LastCombatControls', lastCombatControls)
    end
end

function refresh()
    local player = g_game.getLocalPlayer()
    for i = InventorySlotFirst, InventorySlotPurse do
        if g_game.isOnline() then
            onInventoryChange(player, i, player:getInventoryItem(i))
        else
            onInventoryChange(player, i, nil)
        end
        toggleAdventurerStyle(player and Bit.hasBit(player:getBlessings(), Blessings.Adventurer) or false)
    end

    purseButton:setVisible(g_game.getFeature(GamePurseSlot))
end

function toggle()
    if inventoryButton:isOn() then
        inventoryWindow:close()
        inventoryButton:setOn(false)
    else
        inventoryWindow:open()
        inventoryButton:setOn(true)
    end
end

function onMiniWindowOpen()
    inventoryButton:setOn(true)
end

function onMiniWindowClose()
    inventoryButton:setOn(false)
end

-- hooked events
function onInventoryChange(player, slot, item, oldItem)
    if slot > InventorySlotPurse then
        return
    end

    if slot == InventorySlotPurse then
        if g_game.getFeature(GamePurseSlot) then
            purseButton:setEnabled(item and true or false)
        end
        return
    end

    local itemWidget = inventoryPanel:getChildById('slot' .. slot)
    if item then
        itemWidget:setStyle('InventoryItem')
        itemWidget:setItem(item)
    else
        itemWidget:setStyle(InventorySlotStyles[slot])
        itemWidget:setItem(nil)
    end
end

function onBlessingsChange(player, blessings, oldBlessings)
    local hasAdventurerBlessing = Bit.hasBit(blessings, Blessings.Adventurer)
    if hasAdventurerBlessing ~= Bit.hasBit(oldBlessings, Blessings.Adventurer) then
        toggleAdventurerStyle(hasAdventurerBlessing)
    end
end

-- improve inventory soul / cap / states

function onSoulChange(localPlayer, soul)
    soulLabel:setText(tr('Alma') .. ':\n ' .. soul)
end

function onFreeCapacityChange(player, freeCapacity)
    if not freeCapacity then
        return
    end
    if freeCapacity > 99 then
        freeCapacity = math.floor(freeCapacity * 10) / 10
    end
    if freeCapacity > 999 then
        freeCapacity = math.floor(freeCapacity)
    end
    if freeCapacity > 99999 then
        freeCapacity = math.min(9999, math.floor(freeCapacity / 1000)) .. "k"
    end
    capLabel:setText(tr('Cap') .. ':\n' .. freeCapacity)
end

function toggleIcon(bitChanged)
    local content = inventoryWindow:recursiveGetChildById('conditionPanel')

    local icon = content:getChildById(Icons[bitChanged].id)
    if icon then
        icon:destroy()
    else
        icon = loadIcon(bitChanged)
        icon:setParent(content)
    end
end

function loadIcon(bitChanged)
    local icon = g_ui.createWidget('ConditionWidget', content)
    icon:setId(Icons[bitChanged].id)
    icon:setImageSource(Icons[bitChanged].path)
    icon:setTooltip(Icons[bitChanged].tooltip)
    return icon
end

function onStatesChange(localPlayer, now, old)
    if now == old then
        return
    end

    local bitsChanged = bit.bxor(now, old)
    for i = 1, 32 do
        local pow = math.pow(2, i - 1)
        if pow > bitsChanged then
            break
        end
        local bitChanged = bit.band(bitsChanged, pow)
        if bitChanged ~= 0 then
            toggleIcon(bitChanged)
        end
    end
end

function update()
    local fightMode = g_game.getFightMode()
    if fightMode == FightOffensive then
        fightModeRadioGroup:selectWidget(fightOffensiveBox)
    elseif fightMode == FightBalanced then
        fightModeRadioGroup:selectWidget(fightBalancedBox)
    else
        fightModeRadioGroup:selectWidget(fightDefensiveBox)
    end

    local chaseMode = g_game.getChaseMode()
    chaseModeButton:setChecked(chaseMode == ChaseOpponent)

    local safeFight = g_game.isSafeFight()
    safeFightButton:setChecked(not safeFight)

    if g_game.getFeature(GamePVPMode) then
        local pvpMode = g_game.getPVPMode()
        local pvpWidget = getPVPBoxByMode(pvpMode)
        if pvpWidget then
            pvpModeRadioGroup:selectWidget(pvpWidget)
        end
    end
end



function check()
    if modules.client_options.getOption('autoChaseOverride') then
        if g_game.isAttacking() and g_game.getChaseMode() == ChaseOpponent then
            g_game.setChaseMode(DontChase)
        end
    end
end

function onSetFightMode(self, selectedFightButton)
    if selectedFightButton == nil then
        return
    end
    local buttonId = selectedFightButton:getId()
    local fightMode
    if buttonId == 'fightOffensiveBox' then
        fightMode = FightOffensive
    elseif buttonId == 'fightBalancedBox' then
        fightMode = FightBalanced
    else
        fightMode = FightDefensive
    end
    g_game.setFightMode(fightMode)
end

function onSetChaseMode(self, checked)
    local chaseMode
    if checked then
      chaseMode = ChaseOpponent
    else
      chaseMode = DontChase
    end
    g_game.setChaseMode(chaseMode)
  end

function onSetSafeFight(self, checked)
    g_game.setSafeFight(not checked)
end

function offline()
    inventoryWindow:setParent(nil, true)
    inventoryWindow:recursiveGetChildById('conditionPanel'):destroyChildren()
end

--[[ function onSetPVPMode(self, selectedPVPButton)
    if selectedPVPButton == nil then
        return
    end

    local buttonId = selectedPVPButton:getId()
    local pvpMode = PVPWhiteDove
    if buttonId == 'whiteDoveBox' then
        pvpMode = PVPWhiteDove
    elseif buttonId == 'whiteHandBox' then
        pvpMode = PVPWhiteHand
    elseif buttonId == 'yellowHandBox' then
        pvpMode = PVPYellowHand
    elseif buttonId == 'redFistBox' then
        pvpMode = PVPRedFist
    end

    g_game.setPVPMode(pvpMode)
end

function getPVPBoxByMode(mode)
    local widget = nil
    if mode == PVPWhiteDove then
        widget = whiteDoveBox
    elseif mode == PVPWhiteHand then
        widget = whiteHandBox
    elseif mode == PVPYellowHand then
        widget = yellowHandBox
    elseif mode == PVPRedFist then
        widget = redFistBox
    end
    return widget
end
 ]]
Post automatically merged:

Solved. Changed the following line to commented:
-- if modules.client_options.getOption('autoChaseOverride') then

At little advice, don't use autoChaseOverride -.-

I still need a help with the following log:
Code:
ERROR: caught a lua call to a bot protected game function, the call was cancelled
stack traceback:
    [builtin#142]: at 0x7ff776c3d2c0
    [C]: in function 'setChaseMode'
    /game_inventory/inventory.lua:476: in function </game_inventory/inventory.lua:473>

This one is after turning the line into comment.
Is it related to Auto walker update must be done from C++ not lua due to bot protection. · edubart/otclient@a1a8d28 (https://github.com/edubart/otclient/commit/a1a8d28f5cc3e3ee73258bebca74a1a9cc13adb4 ? This is a 2013 commit I don't think it's going to be usefull.

Regards :)
 
Last edited:
Back
Top