From 59242b9df8db134b749c25be02a201f2bb504560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Bj=C3=B6rkholm?= Date: Sat, 25 Jul 2015 15:53:03 +0200 Subject: [PATCH] Moved offline training snippet (from Player::onCreatureAppear) to Lua --- data/actions/scripts/other/skilltrainer.lua | 4 +- data/creaturescripts/creaturescripts.xml | 1 + .../scripts/offlinetraining.lua | 75 ++++++++++++ data/lib/compat/compat.lua | 1 + src/luascript.cpp | 110 +++++++++++++++--- src/luascript.h | 10 +- src/player.cpp | 97 +-------------- 7 files changed, 184 insertions(+), 114 deletions(-) create mode 100644 data/creaturescripts/scripts/offlinetraining.lua diff --git a/data/actions/scripts/other/skilltrainer.lua b/data/actions/scripts/other/skilltrainer.lua index 7f7a76c8e2..8ff872bca2 100644 --- a/data/actions/scripts/other/skilltrainer.lua +++ b/data/actions/scripts/other/skilltrainer.lua @@ -8,7 +8,7 @@ local statues = { function onUse(player, item, fromPosition, target, toPosition, isHotkey) local skill = statues[item:getId()] - if player:getPremiumDays() == 0 then + if not player:isPremium() then player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUNEEDPREMIUMACCOUNT)) return true end @@ -17,7 +17,7 @@ function onUse(player, item, fromPosition, target, toPosition, isHotkey) return false end - doPlayerSetOfflineTrainingSkill(player, skill) + player:setOfflineTrainingSkill(skill) player:remove() return true end diff --git a/data/creaturescripts/creaturescripts.xml b/data/creaturescripts/creaturescripts.xml index a5e7fd0f54..86e2c8c3a7 100644 --- a/data/creaturescripts/creaturescripts.xml +++ b/data/creaturescripts/creaturescripts.xml @@ -3,6 +3,7 @@ + diff --git a/data/creaturescripts/scripts/offlinetraining.lua b/data/creaturescripts/scripts/offlinetraining.lua new file mode 100644 index 0000000000..98e37aeaec --- /dev/null +++ b/data/creaturescripts/scripts/offlinetraining.lua @@ -0,0 +1,75 @@ +function onLogin(player) + local lastLogout = player:getLastLogout() + local offlineTime = lastLogout ~= 0 and math.min(os.time() - lastLogout, 86400 * 21) or 0 + local offlineTrainingSkill = player:getOfflineTrainingSkill() + if offlineTrainingSkill == -1 then + player:addOfflineTrainingTime(offlineTime * 1000) + return true + end + + player:setOfflineTrainingSkill(-1) + + if offlineTime < 600 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must be logged out for more than 10 minutes to start offline training.") + return true + end + + local trainingTime = math.max(0, math.min(offlineTime, math.min(43200, player:getOfflineTrainingTime() / 1000))) + player:removeOfflineTrainingTime(trainingTime * 1000) + + local remainder = offlineTime - trainingTime + if remainder > 0 then + player:addOfflineTrainingTime(remainder * 1000) + end + + if trainingTime < 60 then + return true + end + + local text = "During your absence you trained for" + local hours = math.floor(trainingTime / 3600) + if hours > 1 then + text = string.format("%s %d hours", text, hours) + elseif hours == 1 then + text = string.format("%s 1 hour", text) + end + + local minutes = math.floor((trainingTime % 3600) / 60) + if minutes ~= 0 then + if hours ~= 0 then + text = string.format("%s and", text) + end + + if minutes > 1 then + text = string.format("%s %d minutes", text, minutes) + else + text = string.format("%s 1 minute", text) + end + end + + text = string.format("%s.", text) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, text) + + local vocation = player:getVocation() + local promotion = vocation:getPromotion() + local topVocation = not promotion and vocation or promotion + + local updateSkills = false + if isInArray({SKILL_CLUB, SKILL_SWORD, SKILL_AXE, SKILL_DISTANCE}, offlineTrainingSkill) then + local modifier = topVocation:getAttackSpeed() / 1000 + updateSkills = player:addOfflineTrainingTries(offlineTrainingSkill, (trainingTime / modifier) / (offlineTrainingSkill == SKILL_DISTANCE and 4 or 2)) + elseif offlineTrainingSkill == SKILL_MAGLEVEL then + local gainTicks = topVocation:getManaGainTicks() * 2 + if gainTicks == 0 then + gainTicks = 1 + end + + updateSkills = player:addOfflineTrainingTries(SKILL_MAGLEVEL, trainingTime * (vocation:getManaGainAmount() / gainTicks)) + end + + if updateSkills then + player:addOfflineTrainingTries(SKILL_SHIELD, trainingTime / 4) + end + + return true +end diff --git a/data/lib/compat/compat.lua b/data/lib/compat/compat.lua index fb6e998cee..b97eded218 100644 --- a/data/lib/compat/compat.lua +++ b/data/lib/compat/compat.lua @@ -374,6 +374,7 @@ function setPlayerGroupId(cid, groupId) local p = Player(cid) return p ~= nil an function doPlayerSetSex(cid, sex) local p = Player(cid) return p ~= nil and p:setSex(sex) or false end function doPlayerSetGuildLevel(cid, level) local p = Player(cid) return p ~= nil and p:setGuildLevel(level) or false end function doPlayerSetGuildNick(cid, nick) local p = Player(cid) return p ~= nil and p:setGuildNick(nick) or false end +function doPlayerSetOfflineTrainingSkill(cid, skillId) local p = Player(cid) return p ~= nil and p:setOfflineTrainingSkill(skillId) or false end function doShowTextDialog(cid, itemId, text) local p = Player(cid) return p ~= nil and p:showTextDialog(itemId, text) or false end function doPlayerAddItemEx(cid, uid, ...) local p = Player(cid) return p ~= nil and p:addItemEx(Item(uid), ...) or false end function doPlayerRemoveItem(cid, itemid, count, ...) local p = Player(cid) return p ~= nil and p:removeItem(itemid, count, ...) or false end diff --git a/src/luascript.cpp b/src/luascript.cpp index b856a3f283..e376ec95d9 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -1012,9 +1012,6 @@ void LuaScriptInterface::registerFunctions() //isInWar(cid, target) lua_register(m_luaState, "isInWar", LuaScriptInterface::luaIsInWar); - //doPlayerSetOfflineTrainingSkill(cid, skill) - lua_register(m_luaState, "doPlayerSetOfflineTrainingSkill", LuaScriptInterface::luaDoPlayerSetOfflineTrainingSkill); - //getWaypointPosition(name) lua_register(m_luaState, "getWaypointPositionByName", LuaScriptInterface::luaGetWaypointPositionByName); @@ -2136,6 +2133,15 @@ void LuaScriptInterface::registerFunctions() registerMethod("Player", "getSkillTries", LuaScriptInterface::luaPlayerGetSkillTries); registerMethod("Player", "addSkillTries", LuaScriptInterface::luaPlayerAddSkillTries); + registerMethod("Player", "addOfflineTrainingTime", LuaScriptInterface::luaPlayerAddOfflineTrainingTime); + registerMethod("Player", "getOfflineTrainingTime", LuaScriptInterface::luaPlayerGetOfflineTrainingTime); + registerMethod("Player", "removeOfflineTrainingTime", LuaScriptInterface::luaPlayerRemoveOfflineTrainingTime); + + registerMethod("Player", "addOfflineTrainingTries", LuaScriptInterface::luaPlayerAddOfflineTrainingTries); + + registerMethod("Player", "getOfflineTrainingSkill", LuaScriptInterface::luaPlayerGetOfflineTrainingSkill); + registerMethod("Player", "setOfflineTrainingSkill", LuaScriptInterface::luaPlayerSetOfflineTrainingSkill); + registerMethod("Player", "getItemCount", LuaScriptInterface::luaPlayerGetItemCount); registerMethod("Player", "getItemById", LuaScriptInterface::luaPlayerGetItemById); @@ -3707,21 +3713,6 @@ int LuaScriptInterface::luaIsInWar(lua_State* L) return 1; } -int LuaScriptInterface::luaDoPlayerSetOfflineTrainingSkill(lua_State* L) -{ - //doPlayerSetOfflineTrainingSkill(cid, skillid) - Player* player = getPlayer(L, 1); - if (player) { - uint32_t skillid = getNumber(L, 2); - player->setOfflineTrainingSkill(skillid); - pushBoolean(L, true); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - int LuaScriptInterface::luaGetWaypointPositionByName(lua_State* L) { //getWaypointPositionByName(name) @@ -7880,6 +7871,89 @@ int LuaScriptInterface::luaPlayerAddSkillTries(lua_State* L) return 1; } +int LuaScriptInterface::luaPlayerAddOfflineTrainingTime(lua_State* L) +{ + // player:addOfflineTrainingTime(time) + Player* player = getUserdata(L, 1); + if (player) { + int32_t time = getNumber(L, 2); + player->addOfflineTrainingTime(time); + player->sendStats(); + pushBoolean(L, true); + } else { + lua_pushnil(L); + } + return 1; +} + + +int LuaScriptInterface::luaPlayerGetOfflineTrainingTime(lua_State* L) +{ + // player:getOfflineTrainingTime() + Player* player = getUserdata(L, 1); + if (player) { + lua_pushnumber(L, player->getOfflineTrainingTime()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerRemoveOfflineTrainingTime(lua_State* L) +{ + // player:removeOfflineTrainingTime(time) + Player* player = getUserdata(L, 1); + if (player) { + int32_t time = getNumber(L, 2); + player->removeOfflineTrainingTime(time); + player->sendStats(); + pushBoolean(L, true); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerAddOfflineTrainingTries(lua_State* L) +{ + // player:addOfflineTrainingTries(skillType, tries) + Player* player = getUserdata(L, 1); + if (player) { + skills_t skillType = getNumber(L, 2); + uint64_t tries = getNumber(L, 3); + pushBoolean(L, player->addOfflineTrainingTries(skillType, tries)); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerGetOfflineTrainingSkill(lua_State* L) +{ + // player:getOfflineTrainingSkill() + Player* player = getUserdata(L, 1); + if (player) { + lua_pushnumber(L, player->getOfflineTrainingSkill()); + } else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerSetOfflineTrainingSkill(lua_State* L) +{ + // player:setOfflineTrainingSkill(skillId) + Player* player = getUserdata(L, 1); + if (player) { + uint32_t skillId = getNumber(L, 2); + player->setOfflineTrainingSkill(skillId); + pushBoolean(L, true); + } else { + lua_pushnil(L); + } + return 1; +} + int LuaScriptInterface::luaPlayerGetItemCount(lua_State* L) { // player:getItemCount(itemId[, subType = -1]) diff --git a/src/luascript.h b/src/luascript.h index 3a8aad2902..3f50e639b2 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -491,7 +491,6 @@ class LuaScriptInterface static int luaCleanMap(lua_State* L); static int luaIsInWar(lua_State* L); - static int luaDoPlayerSetOfflineTrainingSkill(lua_State* L); static int luaGetWaypointPositionByName(lua_State* L); @@ -864,6 +863,15 @@ class LuaScriptInterface static int luaPlayerGetSkillTries(lua_State* L); static int luaPlayerAddSkillTries(lua_State* L); + static int luaPlayerAddOfflineTrainingTime(lua_State* L); + static int luaPlayerGetOfflineTrainingTime(lua_State* L); + static int luaPlayerRemoveOfflineTrainingTime(lua_State* L); + + static int luaPlayerAddOfflineTrainingTries(lua_State* L); + + static int luaPlayerGetOfflineTrainingSkill(lua_State* L); + static int luaPlayerSetOfflineTrainingSkill(lua_State* L); + static int luaPlayerGetItemCount(lua_State* L); static int luaPlayerGetItemById(lua_State* L); diff --git a/src/player.cpp b/src/player.cpp index 4c8c6304d9..e1a05f8623 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -1177,99 +1177,6 @@ void Player::onCreatureAppear(Creature* creature, bool isLogin) } } - bool sentStats = false; - - int16_t oldStaminaMinutes = getStaminaMinutes(); - - if (offlineTrainingSkill != -1) { - if (offlineTime >= 600) { - uint32_t trainingTime = std::max(0, std::min(offlineTime, std::min(43200, offlineTrainingTime / 1000))); - - removeOfflineTrainingTime(trainingTime * 1000); - - int32_t remainder = offlineTime - trainingTime; - if (remainder > 0) { - addOfflineTrainingTime(remainder * 1000); - } - - if (trainingTime >= 60) { - std::ostringstream ss; - ss << "During your absence you trained for "; - int32_t hours = trainingTime / 3600; - if (hours > 1) { - ss << hours << " hours"; - } else if (hours == 1) { - ss << "1 hour"; - } - - int32_t minutes = (trainingTime % 3600) / 60; - if (minutes != 0) { - if (hours != 0) { - ss << " and "; - } - - if (minutes > 1) { - ss << minutes << " minutes"; - } else { - ss << "1 minute"; - } - } - - ss << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - - Vocation* topVocation; - if (isPromoted()) { - topVocation = getVocation(); - } else { - int32_t promotedVocationId = g_vocations.getPromotedVocation(getVocationId()); - topVocation = g_vocations.getVocation(promotedVocationId); - if (!topVocation) { - topVocation = getVocation(); - } - } - - bool sendUpdateSkills = false; - if (offlineTrainingSkill == SKILL_CLUB || offlineTrainingSkill == SKILL_SWORD || offlineTrainingSkill == SKILL_AXE) { - float modifier = topVocation->getAttackSpeed() / 1000.f; - sendUpdateSkills = addOfflineTrainingTries(static_cast(offlineTrainingSkill), (trainingTime / modifier) / 2); - } else if (offlineTrainingSkill == SKILL_DISTANCE) { - float modifier = topVocation->getAttackSpeed() / 1000.f; - sendUpdateSkills = addOfflineTrainingTries(static_cast(offlineTrainingSkill), (trainingTime / modifier) / 4); - } else if (offlineTrainingSkill == SKILL_MAGLEVEL) { - int32_t gainTicks = topVocation->getManaGainTicks() * 2; - if (gainTicks == 0) { - gainTicks = 1; - } - - addOfflineTrainingTries(SKILL_MAGLEVEL, trainingTime * (static_cast(vocation->getManaGainAmount()) / gainTicks)); - } - - if (addOfflineTrainingTries(SKILL_SHIELD, trainingTime / 4) || sendUpdateSkills) { - sendSkills(); - } - } - - sendStats(); - sentStats = true; - } else { - sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must be logged out for more than 10 minutes to start offline training."); - } - setOfflineTrainingSkill(-1); - } else { - uint16_t oldMinutes = getOfflineTrainingTime() / 60 / 1000; - addOfflineTrainingTime(offlineTime * 1000); - uint16_t newMinutes = getOfflineTrainingTime() / 60 / 1000; - if (oldMinutes != newMinutes) { - sendStats(); - sentStats = true; - } - } - - if (!sentStats && getStaminaMinutes() != oldStaminaMinutes) { - sendStats(); - } - g_game.checkPlayersRecord(); IOLoginData::updateOnlineStatus(guid, true); } @@ -4535,6 +4442,10 @@ bool Player::addOfflineTrainingTries(skills_t skill, uint64_t tries) newSkillValue = skills[skill].level; } + if (sendUpdate) { + sendSkills(); + } + std::ostringstream ss; ss << std::fixed << std::setprecision(2) << "Your " << ucwords(getSkillName(skill)) << " skill changed from level " << oldSkillValue << " (with " << oldPercentToNextLevel << "% progress towards level " << (oldSkillValue + 1) << ") to level " << newSkillValue << " (with " << newPercentToNextLevel << "% progress towards level " << (newSkillValue + 1) << ')'; sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str());