Skip to content

Commit

Permalink
Merge pull request #1413 from ninjalulz/OfflineTraining
Browse files Browse the repository at this point in the history
Moved offline training snippet (from Player::onCreatureAppear) to Lua
  • Loading branch information
marksamman committed Aug 9, 2015
2 parents 6eb07a6 + 59242b9 commit 29b7cb4
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 114 deletions.
4 changes: 2 additions & 2 deletions data/actions/scripts/other/skilltrainer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
1 change: 1 addition & 0 deletions data/creaturescripts/creaturescripts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<event type="login" name="PlayerLogin" script="login.lua" />
<event type="logout" name="PlayerLogout" script="logout.lua" />
<event type="login" name="FirstItems" script="firstitems.lua" />
<event type="login" name="OfflineTraining" script="offlinetraining.lua" />
<event type="login" name="RegenerateStamina" script="regeneratestamina.lua" />
<event type="death" name="PlayerDeath" script="playerdeath.lua" />
<event type="death" name="DropLoot" script="droploot.lua" />
Expand Down
75 changes: 75 additions & 0 deletions data/creaturescripts/scripts/offlinetraining.lua
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions data/lib/compat/compat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
110 changes: 92 additions & 18 deletions src/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,9 +1000,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);

Expand Down Expand Up @@ -2124,6 +2121,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);

Expand Down Expand Up @@ -3695,21 +3701,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<uint32_t>(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)
Expand Down Expand Up @@ -7868,6 +7859,89 @@ int LuaScriptInterface::luaPlayerAddSkillTries(lua_State* L)
return 1;
}

int LuaScriptInterface::luaPlayerAddOfflineTrainingTime(lua_State* L)
{
// player:addOfflineTrainingTime(time)
Player* player = getUserdata<Player>(L, 1);
if (player) {
int32_t time = getNumber<int32_t>(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<Player>(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<Player>(L, 1);
if (player) {
int32_t time = getNumber<int32_t>(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<Player>(L, 1);
if (player) {
skills_t skillType = getNumber<skills_t>(L, 2);
uint64_t tries = getNumber<uint64_t>(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<Player>(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<Player>(L, 1);
if (player) {
uint32_t skillId = getNumber<uint32_t>(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])
Expand Down
10 changes: 9 additions & 1 deletion src/luascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down
97 changes: 4 additions & 93 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1173,99 +1173,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<int32_t>(0, std::min<int32_t>(offlineTime, std::min<int32_t>(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<skills_t>(offlineTrainingSkill), (trainingTime / modifier) / 2);
} else if (offlineTrainingSkill == SKILL_DISTANCE) {
float modifier = topVocation->getAttackSpeed() / 1000.f;
sendUpdateSkills = addOfflineTrainingTries(static_cast<skills_t>(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<double>(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);
}
Expand Down Expand Up @@ -4531,6 +4438,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());
Expand Down

0 comments on commit 29b7cb4

Please sign in to comment.