Post by nebula on Dec 21, 2005 4:58:52 GMT -5
There my version of ExpWatch
Alittle about it. the exp/hr and time til level are based on how long you've been fighting, so its a losing battle to keep it exp/hr stable. it'll gradually keep falling, boost back up if you kill a mob quick or such *shrug* it works enough that'll you can get an idea of how well you're doing
download
open up ExpMon.lua if you want to use it and look in the settings area, whats shown on the bar is customizable and if you don't want messages about binds existing or what not, set BindKey = "". if you have issues with it not picking the right resolution (thanks to sdphantom for pointing out that its in the ini that windower uses), you can put it as a cmdline argument, otherwise, on error it will default to 600
Alittle about it. the exp/hr and time til level are based on how long you've been fighting, so its a losing battle to keep it exp/hr stable. it'll gradually keep falling, boost back up if you kill a mob quick or such *shrug* it works enough that'll you can get an idea of how well you're doing
download
open up ExpMon.lua if you want to use it and look in the settings area, whats shown on the bar is customizable and if you don't want messages about binds existing or what not, set BindKey = "". if you have issues with it not picking the right resolution (thanks to sdphantom for pointing out that its in the ini that windower uses), you can put it as a cmdline argument, otherwise, on error it will default to 600
-------------------------------------------------------------------
-- ExpMonitor by Nebula
-- Version 1.0.1
-- Copyright (C) 2005 Kyle Buller
--
-- Based on StarHawk's ExpWatch FFXI Windower plugin.
--
-- You will need TinyTerror's Lunar plugin for Windower for
-- this script to work.
--
-- Load by typing this in console or adding it to your init.txt:
-- .Lunar load ExpMon.lua [BindKey] [Y-Resolution]
-- where BindKey is an optional argument for setting a default
-- bind key
--
-- Aliases/Commands after loading:
--
-- exp_show : .Lunar command ExpMon.lua show
-- Show the exp stats
--
-- exp_hide : .Lunar command ExpMon.lua hide
-- Hide the exp stats
--
-- exp_toggle : .Lunar command ExpMon.lua toggle
-- Toggle the visibility of the exp stats
--
-- exp_reset : .Lunar command ExpMon.lua reset
-- Reset the exp stats and counters
--
-- forcebind : .Lunar command ExpMon.lua bind
-- If the key specified by BindKey is already bound, overwrite
-- the existing bind.
--
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-------------------------------------------------------------------
-- Settings --
--------------
-- The ini file windower loads from (don't change if you're unsure)
INIFile = "windower.ini"
-- Key to bind for toggling (BindKey) and to reset (Ctrl+BindKey)
-- (See KeyCodes.txt for valid keys)
BindKey = "LBRACKET"
-- Stat display preferences:
-- Font used
DisplayFont = "Century Gothic Bold"
-- Show current job/subjob and levels
DisplayJobLevel = false
-- Total exp gained
DisplayGain = true
-- Average exp gained
DisplayAverage = true
-- Exp/Hr
DisplayExpHr = true
-- Time before next level
DisplayTTL = true
-- Mobs before next level
DisplayMTL = true
-------------------------------------------------------------------
-- Don't touch anything below this line ---------------------------
-------------------------------------------------------------------
Windower.script_SetVersion("1.0.1")
Windower.script_SetAuthor("nebula")
Windower.script_SetContact("nebula@the-syn.com")
--force it to be named ExpMon.lua so the aliases work
if not Windower.script_SetName("ExpMon.lua") then
Windower.console_Write("Error: Unable to name script.")
return
end
Windower.console_Write(" ")
Windower.console_Write("ExpMonitor by Nebula.")
Windower.console_Write("Idea copied from StarHawk.")
Windower.console_Write(" ")
-- Try reading windower.ini for the Y Res
resY = 600 --value incase unable to load from ini and not in the cmdline
function loadcfg ()
local cfg = assert(io.open("../../../"..INIFile,"r"))
for line in cfg:lines() do
if string.find(line,"Y Resolution") then
resY = tonumber(string.sub(line,string.find(line,"%d+")))
break
end
end
end
pcall(loadcfg) --don't hang on not being able to open the config
-- Get Args
if Windower.script_GetArgCount() > 2 then
BindKey = Windower.script_GetArg(2)
if Windower.script_GetArgCount() > 3 then
resY = tonumber(Windower.script_GetArg(3))
end
end
-- Text objects
ExpTextShadow = Graphics.text_CreateObject()
Graphics.text_SetPosition(21,resY-17,ExpTextShadow)
Graphics.text_SetColor(255,0,0,0,ExpTextShadow)
Graphics.text_SetFont(DisplayFont,11,ExpTextShadow)
Graphics.text_SetBold(true,ExpTextShadow)
ExpText = Graphics.text_CreateObject()
Graphics.text_SetPosition(20,resY-18,ExpText)
Graphics.text_SetColor(255,255,255,255,ExpText)
Graphics.text_SetFont(DisplayFont,11,ExpText)
Graphics.text_SetBold(true,ExpText)
Graphics.text_SetText("Loading...",ExpText)
Graphics.text_SetText("Loading...",ExpTextShadow)
-- Init globals
Exp = FFXI.player_GetCurrentXP()
ExpD = 0
ExpMax = 0
ExpTnl = 0
ExpTotal= 0
ExpHr = 0
ExpTime = 0
tStart = 0
MobCnt = 0
ExpAvg = 0
ExpMTL = 0
ExpTTL = 0
Job = FFXI.player_GetMainJob()
Level = FFXI.player_GetMainJobLevel()
Dead = false
Visible = 1
Bound = 0
------------
-- Functions
-- Returns the short job name based on the id
-- (1-15), order corresponding with the order in the job select list, heh
function GetJobName(id)
local name, id = "", tonumber(id)
if id == 1 then name="WAR"
elseif id == 2 then name="MNK"
elseif id == 3 then name="WHM"
elseif id == 4 then name="BLM"
elseif id == 5 then name="RDM"
elseif id == 6 then name="THF"
elseif id == 7 then name="PLD"
elseif id == 8 then name="DRK"
elseif id == 9 then name="BST"
elseif id == 10 then name="BRD"
elseif id == 11 then name="RNG"
elseif id == 12 then name="SAM"
elseif id == 13 then name="NIN"
elseif id == 14 then name="DRG"
elseif id == 15 then name="SMN"
else name="???"
end
return name
end
function FFXI.player_GetMainJobName()
return GetJobName(FFXI.player_GetMainJob())
end
function FFXI.player_GetSubJobName()
return GetJobName(FFXI.player_GetSubJob())
end
-- Reset counters
function reset ()
Exp = FFXI.player_GetCurrentXP()
ExpD = 0
ExpMax = 0
ExpTnl = 0
ExpTotal = 0
ExpHr = 0
ExpTime = 0
tStart = 0
MobCnt = 0
ExpAvg = 0
ExpMTL = 0
ExpTTL = 0
Job = FFXI.player_GetMainJob()
Level = FFXI.player_GetMainJobLevel()
Dead = false
show()
end
-- Triggered from user, displays 'Resetting..'
function user_reset()
reset()
Output = "Resetting ExpMon..."
Graphics.text_SetText(Output,ExpText)
Graphics.text_SetText(Output,ExpTextShadow)
Windower.script_Sleep(2000)
return true
end
-- Hide/show/toggle the text
function hide ()
Visible = 0
return Graphics.text_HideAll()
end
function show ()
Visible = 1
return Graphics.text_ShowAll()
end
function toggle ()
Visible = 1-Visible
if Visible == 1 then return show()
else return hide()
end
end
-- Bind for toggle and reset
function bind ()
if Control.control_BindKey(BindKey,true,false,false,".Lunar command ExpMon.lua toggle") and
Control.control_BindKey(BindKey,true,false,true,".Lunar command ExpMon.lua reset") then
Windower.console_Write(""..BindKey.." set.")
Bound=1
else
Windower.console_Write("Error: "..BindKey.." was not bound.")
end
end
-- Formatting functions
-- Returns a string in date("H:i:s") format
function format_time(seconds)
return string.format('%02d:%02d:%02d',math.floor(seconds/3600),math.mod(math.floor(seconds/60),60),math.mod(seconds,60))
end
-- Returns a string of an int with place seperated by commas
function format_number(num)
local len, tmp = string.len(num), ""
for i=len,1,-1 do
if math.mod(len-(i-1)-1,3)==0 and i ~= len then
tmp = string.char(string.byte(num,i))..","..tmp;
else
tmp = string.char(string.byte(num,i))..tmp;
end
end
return tmp;
end
-- .Lunar command processing
function ProcessCommand (Command)
if Command == "show" then show()
elseif Command == "hide" then hide()
elseif Command == "toggle" then toggle()
elseif Command == "reset" then user_reset()
elseif Command == "bind" then bind()
end
end
function ProcessCommands ()
for i=1, Windower.script_GetCommandCount(), 1 do
ProcessCommand(Windower.script_GetCommand())
end
end
-- Aliases
Windower.console_Exec("ExpMon-Aliases.txt",false)
--[[
Control.control_SendString("/console alias exp_show .Lunar command ExpMon.lua show")
Control.control_SendString("/console alias exp_hide .Lunar command ExpMon.lua hide")
Control.control_SendString("/console alias exp_toggle .Lunar command ExpMon.lua toggle")
Control.control_SendString("/console alias exp_reset .Lunar command ExpMon.lua reset")
Control.control_SendString("/console alias forcebind .Lunar command ExpMon.lua bind")
]]
-- Bind toggle and reset if key is set (otherwise can bind to aliases)
if BindKey ~= "" then
if Control.control_IsKeyBound(BindKey,false,false) or Control.control_IsKeyBound(BindKey,false,true) then
Windower.console_Write("Warning: "..BindKey.." is already bound.")
Windower.console_Write("Type \"forcebind\" to overwrite the existing bind(s).")
else
bind()
end
end
---------------
-- Main loop --
---------------
while true do
ProcessCommands()
if FFXI.player_GetStatus() == 2 then
Dead = true
end
-- Zoning
if FFXI.player_GetLevelXP() == 0 then
Output = "Waiting..."
reset() --hmm, perhaps check zone id, if possible, then reset only if in a city or on region change
else
ExpD = FFXI.player_GetCurrentXP()
--switch jobs
if Job ~= FFXI.player_GetMainJob() then
reset()
end
--level
if Level ~= FFXI.player_GetMainJobLevel() and tStart ~= 0 and Exp ~= ExpD then
local LevelD = FFXI.player_GetMainJobLevel()
if LevelD > Level then --level up
ExpTotal = ExpTotal + ExpTnl
Exp = 0
else --level down
ExpTotal = ExpTotal - (FFXI.player_GetRemainingXP() + Exp)
Exp = FFXI.player_GetCurrentXP()
end
Level = LevelD
end
-- Exp values changed
if Exp ~= ExpD then
-- Gained exp
if ExpD > Exp then
--first exp gained after dead will be from a raise, skip counting it as a kill
if not Dead then
-- First kill? start the clock
if tStart == 0 then
tStart = os.clock()
ExpTime = 0
end
-- i realize exp scrolls will trigger this
-- but i don't wanna use chatlines to get exp ;;
MobCnt = MobCnt + 1
else
Dead = false
end
-- So random deaths don't change ExpTotal while not exping
if tStart ~= 0 then
ExpTotal = ExpTotal + (ExpD-Exp)
ExpAvg = math.floor( ExpTotal/MobCnt )
end
end
end
Exp = FFXI.player_GetCurrentXP()
ExpTnl = FFXI.player_GetRemainingXP()
ExpMax = FFXI.player_GetLevelXP()
-- Killing mobs
if tStart ~= 0 then
ExpTime = os.difftime(os.clock(),tStart)
ExpMTL = math.ceil( ExpTnl/ExpAvg )
ExpHr = math.floor( (ExpTotal/((ExpTime/3600)+1)) * (3600/ExpTime) )
ExpTTL = (ExpTnl/ExpHr) * 3600
-- If Exp/Hr drops to 0, assume they stopped killing things and reset counters
if ExpHr == 0 then reset() end
end
Output = ""
if DisplayJobLevel then
JobLevel = string.format("%s%i",FFXI.player_GetMainJobName(),Level)
if FFXI.player_GetSubJobLevel() > 0 then JobLevel = JobLevel .. string.format("/%s%i",FFXI.player_GetSubJobName(),FFXI.player_GetSubJobLevel()) end
Output = Output .. string.format("%s: ",JobLevel)
end
Output = Output .. string.format("%s/%s @%s ",format_number(Exp),format_number(ExpMax),format_number(ExpTnl))
if (tStart ~= 0 and MobCnt > 1) then
if DisplayGain then Output = Output .. string.format("Gain: %s ",format_number(ExpTotal)) end
if DisplayAverage then Output = Output .. string.format("Avg: %s ",format_number(ExpAvg)) end
if DisplayExpHr then Output = Output .. string.format("Exp/Hr: %s ",format_number(ExpHr)) end
if DisplayTTL then Output = Output .. string.format("TTL: %s ",format_time(ExpTTL)) end
if DisplayMTL then Output = Output .. string.format("Mobs/Lvl: %s ",format_number(ExpMTL)) end
end
end
Graphics.text_SetText(Output,ExpText)
Graphics.text_SetText(Output,ExpTextShadow)
Windower.script_Sleep(100)
end