diff --git a/modules/corelib/ui/tooltip.lua b/modules/corelib/ui/tooltip.lua index 47cbbb25..b78058c1 100644 --- a/modules/corelib/ui/tooltip.lua +++ b/modules/corelib/ui/tooltip.lua @@ -92,6 +92,10 @@ function UIWidget:setTooltip(text) self.tooltip = text end +function UIWidget:removeTooltip() + self.tooltip = nil +end + function UIWidget:getTooltip() return self.tooltip end diff --git a/modules/game_market/market.lua b/modules/game_market/market.lua index 5e075117..909f3c55 100644 --- a/modules/game_market/market.lua +++ b/modules/game_market/market.lua @@ -467,7 +467,7 @@ local function onSelectSellOffer(table, selectedRow, previousSelectedRow) if offer then local price = offer:getPrice() if price > information.balance then - balanceLabel:setColor('#b22222') + balanceLabel:setColor('#b22222') -- red buyButton:setEnabled(false) else local slice = (information.balance / 2) @@ -751,7 +751,9 @@ function Market.reset() categoryList:setCurrentOption(getMarketCategoryName(MarketCategory.First)) searchEdit:setText('') clearFilters() - Market.updateCurrentItems() + if information and not table.empty(information) then + Market.updateCurrentItems() + end end function Market.clearSelectedItem() diff --git a/modules/game_skills/skills.lua b/modules/game_skills/skills.lua index a066541f..1e9cf2c3 100644 --- a/modules/game_skills/skills.lua +++ b/modules/game_skills/skills.lua @@ -10,8 +10,18 @@ function init() onSoulChange = onSoulChange, onFreeCapacityChange = onFreeCapacityChange, onStaminaChange = onStaminaChange, + onOfflineTrainingChange = onOfflineTrainingChange, + onRegenerationChange = onRegenerationChange, + onSpeedChange = onSpeedChange, + onBaseSpeedChange = onBaseSpeedChange, onMagicLevelChange = onMagicLevelChange, - onSkillChange = onSkillChange + onBaseMagicLevelChange = onBaseMagicLevelChange, + onSkillChange = onSkillChange, + onBaseSkillChange = onBaseSkillChange + }) + connect(g_game, { + onGameStart = update, + onGameEnd = update }) skillsWindow = g_ui.loadUI('skills.otui', modules.game_interface.getRightPanel()) @@ -31,8 +41,18 @@ function terminate() onSoulChange = onSoulChange, onFreeCapacityChange = onFreeCapacityChange, onStaminaChange = onStaminaChange, + onOfflineTrainingChange = onOfflineTrainingChange, + onRegenerationChange = onRegenerationChange, + onSpeedChange = onSpeedChange, + onBaseSpeedChange = onBaseSpeedChange, onMagicLevelChange = onMagicLevelChange, - onSkillChange = onSkillChange + onBaseMagicLevelChange = onBaseMagicLevelChange, + onSkillChange = onSkillChange, + onBaseSkillChange = onBaseSkillChange + }) + disconnect(g_game, { + onGameStart = update, + onGameEnd = update }) g_keyboard.unbindKeyDown('Ctrl+S') @@ -40,12 +60,40 @@ function terminate() skillsWindow:destroy() end +function setSkillBase(id, value, baseValue) + local skill = skillsWindow:recursiveGetChildById(id) + local widget = skill:getChildById('value') + + if value > baseValue then + widget:setColor('#008b00') + skill:setTooltip(baseValue .. ' + ' .. (value - baseValue)) + elseif value < baseValue then + widget:setColor('#008b00') + skill:setTooltip(baseValue .. ' - ' .. (value - baseValue)) + else + widget:setColor('#bbbbbb') + skill:removeTooltip() + end +end + function setSkillValue(id, value) local skill = skillsWindow:recursiveGetChildById(id) local widget = skill:getChildById('value') widget:setText(value) end +function setSkillColor(id, value) + local skill = skillsWindow:recursiveGetChildById(id) + local widget = skill:getChildById('value') + widget:setColor(value) +end + +function setSkillTooltip(id, value) + local skill = skillsWindow:recursiveGetChildById(id) + local widget = skill:getChildById('value') + widget:setTooltip(value) +end + function setSkillPercent(id, percent, tooltip) local skill = skillsWindow:recursiveGetChildById(id) local widget = skill:getChildById('percent') @@ -56,6 +104,22 @@ function setSkillPercent(id, percent, tooltip) end end +function update() + local offlineTraining = skillsWindow:recursiveGetChildById('offlineTraining') + if not g_game.getFeature(GameOfflineTrainingTime) then + offlineTraining:hide() + else + offlineTraining:show() + end + + local regenerationTime = skillsWindow:recursiveGetChildById('regenerationTime') + if not g_game.getFeature(GamePlayerRegenerationTime) then + regenerationTime:hide() + else + regenerationTime:show() + end +end + function refresh() local player = g_game.getLocalPlayer() if not player then return end @@ -68,9 +132,15 @@ function refresh() onFreeCapacityChange(player, player:getFreeCapacity()) onStaminaChange(player, player:getStamina()) onMagicLevelChange(player, player:getMagicLevel(), player:getMagicLevelPercent()) + onOfflineTrainingChange(player, player:getOfflineTrainingTime()) + onRegenerationChange(player, player:getRegenerationTime()) + onSpeedChange(player, player:getSpeed()) + onBaseSpeedChange(player, player:getBaseSpeed()) + onBaseMagicLevelChange(player, player:getBaseMagicLevel()) for i=0,6 do onSkillChange(player, i, player:getSkillLevel(i), player:getSkillLevelPercent(i)) + onBaseSkillChange(player, i, player:getSkillBaseLevel(i)) end end @@ -137,13 +207,74 @@ function onStaminaChange(localPlayer, stamina) setSkillPercent('stamina', percent, tr('You have %s percent', percent)) end -function onMagicLevelChange(localPlayer, value, percent) - setSkillValue('magiclevel', value) +function onOfflineTrainingChange(localPlayer, offlineTrainingTime) + local hours = math.floor(offlineTrainingTime / 60) + local minutes = offlineTrainingTime % 60 + if minutes < 10 then + minutes = '0' .. minutes + end + local percent = 100 * offlineTrainingTime / (12 * 60) -- max is 12 hours + + setSkillValue('offlineTraining', hours .. ":" .. minutes) + setSkillPercent('offlineTraining', percent, tr('You have %s percent', percent)) +end + +function onRegenerationChange(localPlayer, regenerationTime) + local hours = math.floor(regenerationTime / 60) + local minutes = regenerationTime % 60 + if minutes < 10 then + minutes = '0' .. minutes + end + + setSkillValue('regenerationTime', hours .. ":" .. minutes) +end + +function onSpeedChange(localPlayer, speed) + setSkillValue('speed', speed) + + setSkillBase('speed', speed, localPlayer:getBaseSpeed()) +end + +function onBaseSpeedChange(localPlayer, baseSpeed) + if baseSpeed < 1 then + return + end + local speed = localPlayer:getSpeed() + onSpeedChange(localPlayer, baseSpeed) + + setSkillBase('speed', speed, baseSpeed) +end + +function onMagicLevelChange(localPlayer, magiclevel, percent) + setSkillValue('magiclevel', magiclevel) setSkillPercent('magiclevel', percent, tr('You have %s percent to go', 100 - percent)) + + setSkillBase('magiclevel', magiclevel, localPlayer:getBaseMagicLevel()) +end + +function onBaseMagicLevelChange(localPlayer, baseMagicLevel) + if baseMagicLevel < 1 then + return + end + local magiclevel = localPlayer:getMagicLevel() + onMagicLevelChange(localPlayer, magiclevel, localPlayer:getMagicLevelPercent()) + + setSkillBase('magiclevel', magiclevel, baseMagicLevel) end function onSkillChange(localPlayer, id, level, percent) setSkillValue('skillId' .. id, level) setSkillPercent('skillId' .. id, percent, tr('You have %s percent to go', 100 - percent)) + + setSkillBase('skillId'..id, level, localPlayer:getSkillBaseLevel(id)) end +function onBaseSkillChange(localPlayer, id, baseLevel) + if baseLevel < 1 then + return + end + local level = localPlayer:getSkillLevel(id) + onSkillChange(localPlayer, id, level, localPlayer:getSkillLevelPercent(id)) + + setSkillBase('skillId'..id, level, baseLevel) +end \ No newline at end of file diff --git a/modules/game_skills/skills.otui b/modules/game_skills/skills.otui index 2c33b5f9..9adc6e8a 100644 --- a/modules/game_skills/skills.otui +++ b/modules/game_skills/skills.otui @@ -85,6 +85,19 @@ MiniWindow !text: tr('Capacity') SkillValueLabel + SkillButton + id: speed + height: 15 + SkillNameLabel + !text: tr('Speed') + SkillValueLabel + + SkillButton + id: regenerationTime + SkillNameLabel + !text: tr('Regeneration Time') + SkillValueLabel + SkillButton id: stamina SkillNameLabel @@ -92,6 +105,13 @@ MiniWindow SkillValueLabel SkillPercentPanel + SkillButton + id: offlineTraining + SkillNameLabel + !text: tr('Offline Training') + SkillValueLabel + SkillPercentPanel + SkillButton id: magiclevel SkillNameLabel @@ -116,7 +136,6 @@ MiniWindow SkillButton id: skillId2 - SkillNameLabel !text: tr('Sword Fighting') SkillValueLabel diff --git a/modules/gamelib/const.lua b/modules/gamelib/const.lua index 3e9d294e..9087dea3 100644 --- a/modules/gamelib/const.lua +++ b/modules/gamelib/const.lua @@ -41,30 +41,28 @@ FightDefensive = 3 DontChase = 0 ChaseOpponent = 1 -GameExtendedOpcode = 0 GameProtocolChecksum = 1 GameAccountNames = 2 GameChallangeOnLogin = 3 -GameStackposOnTileAddThing = 4 GamePenalityOnDeath = 5 GameNameOnNpcTrade = 6 GameDoubleFreeCapacity = 7 GameDoubleExperience = 8 GameTotalCapacity = 9 GameSkillsBase = 10 -GameAdditionalPlayerStats = 11 -GameIdOnCancelAttack = 12 +GamePlayerRegenerationTime = 11 GameChannelPlayerList = 13 GamePlayerMounts = 14 GameEnvironmentEffect = 15 -GameCreatureType = 16 GameCreatureEmblems = 17 -GameCreaturePassableInfo = 18 GameItemAnimationPhase = 19 -GameTrucatedPingOpcode = 20 -GameReverseCreatureStack = 21 GameMagicEffectU16 = 22 GamePlayerMarket = 23 +GameSpritesU32 = 24 +GameChargeableItems = 25 +GameOfflineTrainingTime = 26 +GamePurseSlot = 27 +GameFormatCreatureName = 28 TextColors = { red = '#f55e5e', --'#c83200' diff --git a/src/otclient/creature.cpp b/src/otclient/creature.cpp index 8a23f547..72e54c7d 100644 --- a/src/otclient/creature.cpp +++ b/src/otclient/creature.cpp @@ -514,11 +514,14 @@ void Creature::setOutfit(const Outfit& outfit) void Creature::setSpeed(uint16 speed) { + uint16 oldSpeed = m_speed; m_speed = speed; // speed can change while walking (utani hur, paralyze, etc..) if(m_walking) nextWalkUpdate(); + + callLuaField("onSpeedChange", speed, oldSpeed); } void Creature::setSkull(uint8 skull) diff --git a/src/otclient/localplayer.cpp b/src/otclient/localplayer.cpp index 813ab104..51bd6bed 100644 --- a/src/otclient/localplayer.cpp +++ b/src/otclient/localplayer.cpp @@ -39,6 +39,7 @@ LocalPlayer::LocalPlayer() m_walkLockExpiration = 0; m_skillsLevel.fill(-1); + m_skillsBaseLevel.fill(-1); m_skillsLevelPercent.fill(-1); m_health = -1; @@ -51,8 +52,13 @@ LocalPlayer::LocalPlayer() m_maxMana = -1; m_magicLevel = -1; m_magicLevelPercent = -1; + m_baseMagicLevel = -1; m_soul = -1; m_stamina = -1; + m_baseSpeed = -1; + m_regenerationTime = -1; + m_offlineTrainingTime = -1; + m_totalCapacity = -1; } void LocalPlayer::lockWalk(int millis) @@ -248,6 +254,21 @@ void LocalPlayer::setSkill(Otc::Skill skill, int level, int levelPercent) } } +void LocalPlayer::setBaseSkill(Otc::Skill skill, int baseLevel) +{ + if(skill >= Otc::LastSkill) { + g_logger.traceError("invalid skill"); + return; + } + + int oldBaseLevel = m_skillsBaseLevel[skill]; + if(baseLevel != oldBaseLevel) { + m_skillsBaseLevel[skill] = baseLevel; + + callLuaField("onBaseSkillChange", skill, baseLevel, oldBaseLevel); + } +} + void LocalPlayer::setHealth(double health, double maxHealth) { if(m_health != health || m_maxHealth != maxHealth) { @@ -277,6 +298,16 @@ void LocalPlayer::setFreeCapacity(double freeCapacity) } } +void LocalPlayer::setTotalCapacity(double totalCapacity) +{ + if(m_totalCapacity != totalCapacity) { + double oldTotalCapacity = m_totalCapacity; + m_totalCapacity = totalCapacity; + + callLuaField("onTotalCapacityChange", totalCapacity, oldTotalCapacity); + } +} + void LocalPlayer::setExperience(double experience) { if(m_experience != experience) { @@ -323,6 +354,16 @@ void LocalPlayer::setMagicLevel(double magicLevel, double magicLevelPercent) } } +void LocalPlayer::setBaseMagicLevel(double baseMagicLevel) +{ + if(m_baseMagicLevel != baseMagicLevel) { + double oldBaseMagicLevel = m_baseMagicLevel; + m_baseMagicLevel = baseMagicLevel; + + callLuaField("onBaseMagicLevelChange", baseMagicLevel, oldBaseMagicLevel); + } +} + void LocalPlayer::setSoul(double soul) { if(m_soul != soul) { @@ -377,6 +418,36 @@ void LocalPlayer::setPremium(bool premium) } } +void LocalPlayer::setBaseSpeed(double baseSpeed) +{ + if(m_baseSpeed != baseSpeed) { + double oldBaseSpeed = m_baseSpeed; + m_baseSpeed = baseSpeed; + + callLuaField("onBaseSpeedChange", baseSpeed, oldBaseSpeed); + } +} + +void LocalPlayer::setRegenerationTime(double regenerationTime) +{ + if(m_regenerationTime != regenerationTime) { + double oldRegenerationTime = m_regenerationTime; + m_regenerationTime = regenerationTime; + + callLuaField("onRegenerationChange", regenerationTime, oldRegenerationTime); + } +} + +void LocalPlayer::setOfflineTrainingTime(double offlineTrainingTime) +{ + if(m_offlineTrainingTime != offlineTrainingTime) { + double oldOfflineTrainingTime = m_offlineTrainingTime; + m_offlineTrainingTime = offlineTrainingTime; + + callLuaField("onOfflineTrainingChange", offlineTrainingTime, oldOfflineTrainingTime); + } +} + double LocalPlayer::getWalkPing() { if(m_lastWalkPings.empty()) diff --git a/src/otclient/localplayer.h b/src/otclient/localplayer.h index 165f229e..d1face12 100644 --- a/src/otclient/localplayer.h +++ b/src/otclient/localplayer.h @@ -41,27 +41,35 @@ public: void setStates(int states); void setSkill(Otc::Skill skill, int level, int levelPercent); + void setBaseSkill(Otc::Skill skill, int baseLevel); void setHealth(double health, double maxHealth); void setFreeCapacity(double freeCapacity); + void setTotalCapacity(double totalCapacity); void setExperience(double experience); void setLevel(double level, double levelPercent); void setMana(double mana, double maxMana); void setMagicLevel(double magicLevel, double magicLevelPercent); + void setBaseMagicLevel(double baseMagicLevel); void setSoul(double soul); void setStamina(double stamina); void setKnown(bool known) { m_known = known; } void setInventoryItem(Otc::InventorySlot inventory, const ItemPtr& item); void setVocation(int vocation); void setPremium(bool premium); + void setBaseSpeed(double baseSpeed); + void setRegenerationTime(double regenerationTime); + void setOfflineTrainingTime(double offlineTrainingTime); int getStates() { return m_states; } int getSkillLevel(Otc::Skill skill) { return m_skillsLevel[skill]; } + int getSkillBaseLevel(Otc::Skill skill) { return m_skillsBaseLevel[skill]; } int getSkillLevelPercent(Otc::Skill skill) { return m_skillsLevelPercent[skill]; } int getVocation() { return m_vocation; } double getWalkPing(); double getHealth() { return m_health; } double getMaxHealth() { return m_maxHealth; } double getFreeCapacity() { return m_freeCapacity; } + double getTotalCapacity() { return m_totalCapacity; } double getExperience() { return m_experience; } double getLevel() { return m_level; } double getLevelPercent() { return m_levelPercent; } @@ -69,8 +77,12 @@ public: double getMaxMana() { return m_maxMana; } double getMagicLevel() { return m_magicLevel; } double getMagicLevelPercent() { return m_magicLevelPercent; } + double getBaseMagicLevel() { return m_baseMagicLevel; } double getSoul() { return m_soul; } double getStamina() { return m_stamina; } + double getBaseSpeed() { return m_baseSpeed; } + double getRegenerationTime() { return m_regenerationTime; } + double getOfflineTrainingTime() { return m_offlineTrainingTime; } ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; } bool hasSight(const Position& pos); @@ -111,6 +123,7 @@ private: std::deque m_lastWalkPings; std::array m_skillsLevel; + std::array m_skillsBaseLevel; std::array m_skillsLevelPercent; bool m_known; @@ -121,6 +134,7 @@ private: double m_health; double m_maxHealth; double m_freeCapacity; + double m_totalCapacity; double m_experience; double m_level; double m_levelPercent; @@ -128,8 +142,12 @@ private: double m_maxMana; double m_magicLevel; double m_magicLevelPercent; + double m_baseMagicLevel; double m_soul; double m_stamina; + double m_baseSpeed; + double m_regenerationTime; + double m_offlineTrainingTime; }; #endif diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 26509972..a59c1eb8 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -383,6 +383,7 @@ void OTClient::registerLuaFunctions() g_lua.bindClassMemberFunction("setInventoryItem", &LocalPlayer::setInventoryItem); g_lua.bindClassMemberFunction("getStates", &LocalPlayer::getStates); g_lua.bindClassMemberFunction("getSkillLevel", &LocalPlayer::getSkillLevel); + g_lua.bindClassMemberFunction("getSkillBaseLevel", &LocalPlayer::getSkillBaseLevel); g_lua.bindClassMemberFunction("getSkillLevelPercent", &LocalPlayer::getSkillLevelPercent); g_lua.bindClassMemberFunction("getHealth", &LocalPlayer::getHealth); g_lua.bindClassMemberFunction("getMaxHealth", &LocalPlayer::getMaxHealth); @@ -396,6 +397,11 @@ void OTClient::registerLuaFunctions() g_lua.bindClassMemberFunction("getMagicLevelPercent", &LocalPlayer::getMagicLevelPercent); g_lua.bindClassMemberFunction("getSoul", &LocalPlayer::getSoul); g_lua.bindClassMemberFunction("getStamina", &LocalPlayer::getStamina); + g_lua.bindClassMemberFunction("getOfflineTrainingTime", &LocalPlayer::getOfflineTrainingTime); + g_lua.bindClassMemberFunction("getRegenerationTime", &LocalPlayer::getRegenerationTime); + g_lua.bindClassMemberFunction("getBaseSpeed", &LocalPlayer::getBaseSpeed); + g_lua.bindClassMemberFunction("getBaseMagicLevel", &LocalPlayer::getBaseMagicLevel); + g_lua.bindClassMemberFunction("getTotalCapacity", &LocalPlayer::getTotalCapacity); g_lua.bindClassMemberFunction("getInventoryItem", &LocalPlayer::getInventoryItem); g_lua.bindClassMemberFunction("getVocation", &LocalPlayer::getVocation); g_lua.bindClassMemberFunction("isPremium", &LocalPlayer::isPremium); diff --git a/src/otclient/protocolgameparse.cpp b/src/otclient/protocolgameparse.cpp index 42c063c2..8b1ca1b4 100644 --- a/src/otclient/protocolgameparse.cpp +++ b/src/otclient/protocolgameparse.cpp @@ -876,7 +876,7 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg) else freeCapacity = msg->getU16() / 100.0; - double totalCapacity; + double totalCapacity = 0; if(g_game.getFeature(Otc::GameTotalCapacity)) totalCapacity = msg->getU32() / 100.0; @@ -892,42 +892,57 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg) double maxMana = msg->getU16(); double magicLevel = msg->getU8(); + double baseMagicLevel; if(g_game.getFeature(Otc::GameSkillsBase)) - msg->getU8(); // base magic level + baseMagicLevel = msg->getU8(); + else + baseMagicLevel = magicLevel; double magicLevelPercent = msg->getU8(); double soul = msg->getU8(); double stamina = msg->getU16(); + double baseSpeed = 0; + if(g_game.getFeature(Otc::GameSkillsBase)) + baseSpeed = msg->getU16(); + + double regeneration = 0; + if(g_game.getFeature(Otc::GamePlayerRegenerationTime)) + regeneration = msg->getU16(); + + double training = 0; + if(g_game.getFeature(Otc::GameOfflineTrainingTime)) + training = msg->getU16(); + m_localPlayer->setHealth(health, maxHealth); m_localPlayer->setFreeCapacity(freeCapacity); + m_localPlayer->setTotalCapacity(totalCapacity); m_localPlayer->setExperience(experience); m_localPlayer->setLevel(level, levelPercent); m_localPlayer->setMana(mana, maxMana); m_localPlayer->setMagicLevel(magicLevel, magicLevelPercent); + m_localPlayer->setBaseMagicLevel(baseMagicLevel); m_localPlayer->setStamina(stamina); m_localPlayer->setSoul(soul); - - if(g_game.getFeature(Otc::GameSkillsBase)) - msg->getU16(); // base speed - - if(g_game.getFeature(Otc::GamePlayerRegenerationTime)) - msg->getU16(); - - if(g_game.getFeature(Otc::GameOfflineTrainingTime)) - msg->getU16(); + m_localPlayer->setBaseSpeed(baseSpeed); + m_localPlayer->setRegenerationTime(regeneration); + m_localPlayer->setOfflineTrainingTime(training); } void ProtocolGame::parsePlayerSkills(const InputMessagePtr& msg) { for(int skill = 0; skill < Otc::LastSkill; skill++) { int level = msg->getU8(); + int baseLevel; if(g_game.getFeature(Otc::GameSkillsBase)) - msg->getU8(); // base + baseLevel = msg->getU8(); // base + else + baseLevel = level; int levelPercent = msg->getU8(); m_localPlayer->setSkill((Otc::Skill)skill, level, levelPercent); + m_localPlayer->setBaseSkill((Otc::Skill)skill, baseLevel); } }