Offline training, with bar in-game
- show time left on 'bar' [9.6 client]
- use skill and mlvl rate from config.lua
- use vocations.xml config to:
- - calculate magic level [food mana regen of vocation] ^_^
- - calculate club/axe/sword/distance gain speed [attackSpeed of vocation] ^_^
Code tested on TFS 0.4, 9.6 (one of newest revisions). LUA scripts should work on most of TFSes (0.3.6 - 0.4), but only on 9.6 is 'bar' that show time left and RL tibia items to 'click' to select type of training. Script is designed to make it possible to start training other way then clicking on 'statue'.
How does it calculate skills/mlvl?
- sword, axe, club, distance: it uses multiplier from config.lua, it check attackSpeed of player vocation and 'attack' as fast he can
- shield: it uses multiplier from config.lua, it add one 'hit' per one offline second [like when you train with 2 Monks]
- magic level: it uses multiplier from config.lua, it adds as much 'mana spent' [mag level] as player could regenerate if he eat some food
At start of 'lib' you got basic config, here you can reduce/increase skill/mlvl, 100 = 100% of normal [described above]:
(below config are functions that you can modify to if you want make it start with other action then 'click on statue', example: start trainging if player logout in some area)
First LUA scripts:
../data/lib/103-offline-training.lua
../data/actions/actions.xml
../data/actions/scripts/offtrain_statue.lua
../data/creaturescripts/creaturescripts.xml
../data/creaturescripts/scripts/offtrain_login.lua
../data/creaturescripts/scripts/offtrain_logout.lua
../data/globalevents/globalevents.xml
If you use old TFS change interval 60000 to 60 [60 seconds].
../data/globalevents/scripts/offtrain_addMinutes.lua
C++ code for TFS 0.4, 9.6 version to show time left on 'bar' in client
In file protocolgame.cpp
Find:
[CPP]msg->put<uint16_t>(720);[/CPP]
and replace with:
[CPP]// offline training minutes
std::string strValue;
if(!player->getStorage("62666", strValue))
{
// no storage
msg->put<uint16_t>(0);
}
else
{
msg->put<uint16_t>((uint16_t) atoi(strValue.c_str()));
}[/CPP]
It will show value of storage '62666' on 'bar'. 0 = 0:00, 720 = 12:00 [12 hours, full] - time in minutes.
- show time left on 'bar' [9.6 client]
- use skill and mlvl rate from config.lua
- use vocations.xml config to:
- - calculate magic level [food mana regen of vocation] ^_^
- - calculate club/axe/sword/distance gain speed [attackSpeed of vocation] ^_^
Code tested on TFS 0.4, 9.6 (one of newest revisions). LUA scripts should work on most of TFSes (0.3.6 - 0.4), but only on 9.6 is 'bar' that show time left and RL tibia items to 'click' to select type of training. Script is designed to make it possible to start training other way then clicking on 'statue'.
How does it calculate skills/mlvl?
- sword, axe, club, distance: it uses multiplier from config.lua, it check attackSpeed of player vocation and 'attack' as fast he can
- shield: it uses multiplier from config.lua, it add one 'hit' per one offline second [like when you train with 2 Monks]
- magic level: it uses multiplier from config.lua, it adds as much 'mana spent' [mag level] as player could regenerate if he eat some food
At start of 'lib' you got basic config, here you can reduce/increase skill/mlvl, 100 = 100% of normal [described above]:
Lua:
-- config, in percent of normal training with 2 trainers and player vocation mana regeneration [by food]
OfflineTraining_rates = {
[SKILL_CLUB] = 100,
[SKILL_SWORD] = 100,
[SKILL_AXE] = 100,
[SKILL_DISTANCE] = 100,
[SKILL_SHIELD] = 100,
[SKILL__MAGLEVEL] = 100
}
First LUA scripts:
../data/lib/103-offline-training.lua
Lua:
-- config, in percent of normal training with 2 trainers and player vocation mana regeneration [by food]
OfflineTraining_rates = {
[SKILL_CLUB] = 100,
[SKILL_SWORD] = 100,
[SKILL_AXE] = 100,
[SKILL_DISTANCE] = 100,
[SKILL_SHIELD] = 100,
[SKILL__MAGLEVEL] = 100
}
-- function that you should edit to make it add other skill etc.
function OfflineTraining_canStartTraining(cid) -- return bool
return getCreatureStorage(cid, 62669) > 0
end
function OfflineTraining_onStartTraining(cid)
-- maybe someone will need
-- to save your time, this: doPlayerPopupFYI(cid, "You started offline training.")
-- NOT WORK :(
end
function OfflineTraining_onEndTraining(cid)
doCreatureSetStorage(cid, 62669, 0)
end
function OfflineTraining_addTrainedSkills(cid, trainTime) -- time in minutes!
local timeInSeconds = trainTime * 60
local vocInfo = getVocationInfo(getPlayerVocation(cid))
if(getCreatureStorage(cid, 62669) == SKILL_SWORD) then
doPlayerAddSkillTry(cid, SKILL_SWORD, ((timeInSeconds * 1000) / vocInfo["attackSpeed"]) * OfflineTraining_rates[SKILL_SWORD] / 100, true)
elseif(getCreatureStorage(cid, 62669) == SKILL_AXE) then
doPlayerAddSkillTry(cid, SKILL_AXE, ((timeInSeconds * 1000) / vocInfo["attackSpeed"]) * OfflineTraining_rates[SKILL_AXE] / 100, true)
elseif(getCreatureStorage(cid, 62669) == SKILL__MAGLEVEL) then
doPlayerAddSpentMana(cid, ((timeInSeconds / vocInfo["manaGainTicks"]) * vocInfo["manaGain"]) * OfflineTraining_rates[SKILL__MAGLEVEL] / 100, true)
elseif(getCreatureStorage(cid, 62669) == SKILL_CLUB) then
doPlayerAddSkillTry(cid, SKILL_CLUB, ((timeInSeconds * 1000) / vocInfo["attackSpeed"]) * OfflineTraining_rates[SKILL_CLUB] / 100, true)
elseif(getCreatureStorage(cid, 62669) == SKILL_DISTANCE) then
doPlayerAddSkillTry(cid, SKILL_DISTANCE, ((timeInSeconds * 1000) / vocInfo["attackSpeed"]) * OfflineTraining_rates[SKILL_DISTANCE] / 100, true)
end
doPlayerAddSkillTry(cid, SKILL_SHIELD, timeInSeconds * OfflineTraining_rates[SKILL_SHIELD] / 100, true)
end
-- 4 functions to show right values on 'bar' in Tibia 9.6
function OfflineTraining_getTime(cid)
return getCreatureStorage(cid, 62666)
end
function OfflineTraining_setTime(cid, newTime)
-- set values only between 0 - 720 [12 hours]
doCreatureSetStorage(cid, 62666, math.max(0, math.min(newTime, 720)))
-- now code to force server to send 'PlayerStats' (including Offline Time)
-- we must change any stat: hp,mana,stamina,cap,soul,exp,level
doPlayerAddSoul(cid, 1)
doPlayerAddSoul(cid, -1)
end
function OfflineTraining_addTime(cid, addTime)
OfflineTraining_setTime(cid, OfflineTraining_getTime(cid) + addTime)
end
function OfflineTraining_removeTime(cid, removeTime)
OfflineTraining_setTime(cid, OfflineTraining_getTime(cid) - removeTime)
end
-- functions for library to add skills/mlvl
function OfflineTraining_initialize(cid)
if(OfflineTraining_getTime(cid) == -1) then
OfflineTraining_setTime(cid, 720)
OfflineTraining_setLogoutTime(cid) -- block problem with first login 'add time'
end
end
function OfflineTraining_isTraining(cid)
return (getCreatureStorage(cid, 62667) > 0)
end
function OfflineTraining_turnOnTraining(cid)
doCreatureSetStorage(cid, 62667, 1)
end
function OfflineTraining_turnOffTraining(cid)
doCreatureSetStorage(cid, 62667, 0)
end
function OfflineTraining_getOfflineTime(cid)
return math.floor((os.time() - getCreatureStorage(cid, 62668)) / 60)
end
function OfflineTraining_setLogoutTime(cid)
return doCreatureSetStorage(cid, 62668, os.time())
end
../data/actions/actions.xml
XML:
<action itemid="18492" script="offtrain_statue.lua"/>
<action itemid="18491" script="offtrain_statue.lua"/>
<action itemid="18490" script="offtrain_statue.lua"/>
<action itemid="18489" script="offtrain_statue.lua"/>
<action itemid="18488" script="offtrain_statue.lua"/>
../data/actions/scripts/offtrain_statue.lua
Lua:
-- example 'action' when you click on statue:
function onUse(cid, item, fromPosition, itemEx, toPosition)
if(item.itemid == 18488) then -- sword
doCreatureSetStorage(cid, 62669, SKILL_SWORD)
elseif(item.itemid == 18489) then -- axe
doCreatureSetStorage(cid, 62669, SKILL_AXE)
elseif(item.itemid == 18492) then -- mlvl
doCreatureSetStorage(cid, 62669, SKILL__MAGLEVEL)
elseif(item.itemid == 18490) then -- club
doCreatureSetStorage(cid, 62669, SKILL_CLUB)
elseif(item.itemid == 18491) then -- distannce
doCreatureSetStorage(cid, 62669, SKILL_DISTANCE)
end
-- we remove player, so it will execute onLogout(cid) function and save time of training start
doRemoveCreature(cid)
end
../data/creaturescripts/creaturescripts.xml
XML:
<event type="login" name="offtrain_PlayerLogin" event="script" value="offtrain_login.lua"/>
<event type="logout" name="offtrain_PlayerLogout" event="script" value="offtrain_logout.lua"/>
../data/creaturescripts/scripts/offtrain_login.lua
Lua:
-- 0.4 - offline training - login.lua
function onLogin(cid)
OfflineTraining_initialize(cid)
if(OfflineTraining_isTraining(cid)) then
OfflineTraining_turnOffTraining(cid)
-- we add skill/mlvl, we select lower value: time that player was offline OR offline training time [bar in game - 9.6]
OfflineTraining_addTrainedSkills(cid, math.min(OfflineTraining_getTime(cid), OfflineTraining_getOfflineTime(cid)))
-- we remove offline training time [bar in game - 9.6],
-- if player was offline longer then his 'offline training time' it will add him time [like on RL tibia]
-- got '3 hours offline training time', stay logged off for 8 hours, you get skills for 3 hours and on login you got '5 hours offline training time'
OfflineTraining_setTime(cid, math.abs(OfflineTraining_getTime(cid) - OfflineTraining_getOfflineTime(cid)))
OfflineTraining_onEndTraining(cid)
else
-- offline training time also regenerate when you are offline, but NOT train
OfflineTraining_setTime(cid, OfflineTraining_getTime(cid) + OfflineTraining_getOfflineTime(cid))
end
return true
end
../data/creaturescripts/scripts/offtrain_logout.lua
Lua:
-- 0.4 - offline training - logout.lua
function onLogout(cid)
if(OfflineTraining_canStartTraining(cid)) then
OfflineTraining_turnOnTraining(cid)
OfflineTraining_onStartTraining(cid)
end
OfflineTraining_setLogoutTime(cid)
return true
end
../data/globalevents/globalevents.xml
XML:
<globalevent name="offtrain_add_minutes" interval="60000" event="script" value="offtrain_addMinutes.lua"/>
../data/globalevents/scripts/offtrain_addMinutes.lua
Lua:
function onThink(interval) -- run it with interval 60 seconds
for _, cid in pairs(getPlayersOnline()) do
OfflineTraining_addTime(cid, 1)
end
return true
end
C++ code for TFS 0.4, 9.6 version to show time left on 'bar' in client
In file protocolgame.cpp
Find:
[CPP]msg->put<uint16_t>(720);[/CPP]
and replace with:
[CPP]// offline training minutes
std::string strValue;
if(!player->getStorage("62666", strValue))
{
// no storage
msg->put<uint16_t>(0);
}
else
{
msg->put<uint16_t>((uint16_t) atoi(strValue.c_str()));
}[/CPP]
It will show value of storage '62666' on 'bar'. 0 = 0:00, 720 = 12:00 [12 hours, full] - time in minutes.