Skip to content

Commit

Permalink
Add outputting info to file and info about ticks gained
Browse files Browse the repository at this point in the history
- Now requires luafilesystem (lfs)
- Fixed negative number display in friendlyNumber/friendlyTime
  • Loading branch information
squeek502 committed Dec 12, 2017
1 parent fea6628 commit 280f9f2
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 37 deletions.
84 changes: 84 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
output

# Created by https://www.gitignore.io/api/lua,linux,windows

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### Lua ###
# Compiled Lua sources
luac.out

# luarocks build files
*.src.rock
*.zip
*.tar.gz

# Object files
*.o
*.os
*.ko
*.obj
*.elf

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex


### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# End of https://www.gitignore.io/api/lua,linux,windows
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ Simply grab the [latest .exe build from the releases page](https://github.com/sq

### Running using Lua

- Build [memreader](https://github.com/squeek502/memreader) and [sleep](https://github.com/squeek502/sleep) and make the resulting .dll's available to Lua's `package.cpath`.
- Build [memreader](https://github.com/squeek502/memreader), [sleep](https://github.com/squeek502/sleep), and [luafilesystem](https://github.com/keplerproject/luafilesystem) and make the resulting .dll's available to Lua's `package.cpath`.
- Run `lua d2info.lua`

## Sample Output
## Output

Currently, the information is just output to the console window. Soon, data will be (optionally?) put into files so that it can easily be added to stream overlays.
The information is output to both the console window and to individual text files (in the directory `output`, relative to d2info) to allow the info to be easily added to stream overlays.

Console output example:
```
CoolGuy
Expand All @@ -41,6 +42,14 @@ Est time until level 96:
11h (using game-time xp/min)
23h (using current game's xp/min)
8h22m (using last game's xp/min)
Exp gained (overall): 2.4m
Exp gained (current game): 179.8k
Exp gained (last game): 156.1k
Ticks gained (overall): 1.4
Ticks gained (current game): 0.1
Ticks gained (last game): 0.1
```

## Acknowledgements
Expand Down
39 changes: 19 additions & 20 deletions d2info.lua
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
local memreader = require('memreader')
local D2Reader = require('d2info.d2reader')
local sleep = require('sleep')
local friendlyNumber = require('d2info.utils').friendlyNumber
local friendlyTime = require('d2info.utils').friendlyTime
local Session = require('d2info.session')
local Output = require('d2info.output')

memreader.debugprivilege(true)
local reader = D2Reader.new()
local sessions = {}
local lastPlayer = nil
local output = Output.new()
local lastInfo = {}
local UPDATE_PERIOD = 1000

while true do
os.execute('cls')
local player = reader:getPlayerName()
if player then
local exp, lvl = reader:getExperience()
Expand All @@ -20,38 +20,37 @@ while true do
sessions[player] = {}
sessions[player].total = Session.new(exp, lvl)
end
if player ~= lastPlayer then
if sessions[player].current == nil then
sessions[player].current = Session.new(exp, lvl)
end

local current, total, last = sessions[player].current, sessions[player].total, sessions[player].last
current:update(exp, lvl)
total:update(exp, lvl)

print(string.format("%s\n", player))
print(string.format("Overall (real-time): %s xp/min", friendlyNumber(total:realTimeExpPerMin())))
print(string.format("Overall (game-time): %s xp/min", friendlyNumber(total:durationExpPerMin())))
print(string.format("Current game: %s xp/min", friendlyNumber(current:realTimeExpPerMin())))
print(string.format("Last game: %s xp/min", last and friendlyNumber(last:durationExpPerMin()) or "?"))
print(string.format("\nEst time until level %d:", lvl+1))
print(string.format(" %s (using real-time xp/min)", friendlyTime(total:realTimeToNextLevel())))
print(string.format(" %s (using game-time xp/min)", friendlyTime(total:gameTimeToNextLevel())))
print(string.format(" %s (using current game's xp/min)", friendlyTime(current:gameTimeToNextLevel())))
print(string.format(" %s (using last game's xp/min)", last and friendlyTime(last:gameTimeToNextLevel()) or "?"))
output:toScreen(player, lvl, total, current, last)
output:toFile(player, lvl, total, current, last)

current:incrementDuration()
total:incrementDuration()

lastPlayer = player
lastInfo.player = player
lastInfo.level = lvl
elseif reader.status ~= nil then
os.execute('cls')
print(reader.status)
else
os.execute('cls')
print("No player")

if lastPlayer ~= nil then
sessions[lastPlayer].last = sessions[lastPlayer].current
lastPlayer = nil
if lastInfo.player ~= nil and sessions[lastInfo.player].current ~= nil then
sessions[lastInfo.player].last = sessions[lastInfo.player].current
sessions[lastInfo.player].current = nil
end

-- need to update files here because otherwise they wouldn't update
-- while at the menu screen
output:toFile(lastInfo.player, lastInfo.level, sessions[lastInfo.player].total, sessions[lastInfo.player].current, sessions[lastInfo.player].last)
end
sleep(1000)
sleep(UPDATE_PERIOD)
end
6 changes: 6 additions & 0 deletions d2info/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ return {
exe = "Game.exe",
windowTitle = "Diablo II",

gui = {
expBar = {
ticks=120,
}
},

stats = {
strength = 0,
energy = 1,
Expand Down
51 changes: 51 additions & 0 deletions d2info/output.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
local utils = require('d2info.utils')
local lfs = require('lfs')
local printf, friendlyNumber, friendlyTime, toFile = utils.printf, utils.friendlyNumber, utils.friendlyTime, utils.toFile

local Output = {}
Output.__index = Output

function Output.new(outputDir)
local self = setmetatable({}, Output)
self.outputDir = outputDir or "output"
if not lfs.attributes(self.outputDir) then
assert(lfs.mkdir(self.outputDir))
end
return self
end

function Output:toScreen(player, level, total, current, last)
os.execute('cls')
printf("%s\n", player)
printf("Overall (real-time): %s xp/min", friendlyNumber(total:realTimeExpPerMin()))
printf("Overall (game-time): %s xp/min", friendlyNumber(total:durationExpPerMin()))
printf("Current game: %s xp/min", current and friendlyNumber(current:realTimeExpPerMin()) or "-")
printf("Last game: %s xp/min", last and friendlyNumber(last:durationExpPerMin()) or "-")
printf("\nEst time until level %d:", level+1)
printf(" %s (using real-time xp/min)", friendlyTime(total:realTimeToNextLevel()))
printf(" %s (using game-time xp/min)", friendlyTime(total:gameTimeToNextLevel()))
printf(" %s (using current game's xp/min)", current and friendlyTime(current:gameTimeToNextLevel()) or "-")
printf(" %s (using last game's xp/min)", last and friendlyTime(last:gameTimeToNextLevel()) or "-")
printf("\nExp gained (overall): %s", friendlyNumber(total:expGained()))
printf("Exp gained (current game): %s", current and friendlyNumber(current:expGained()) or "-")
printf("Exp gained (last game): %s", last and friendlyNumber(last:expGained()) or "-")
printf("\nTicks gained (overall): %0.1f", total:ticksGained())
printf("Ticks gained (current game): %0.1f", current and current:ticksGained() or 0)
printf("Ticks gained (last game): %0.1f", last and last:ticksGained() or 0)
end

function Output:toFile(player, level, total, current, last)
toFile(self.outputDir .. "/xpmin-realtime.txt", friendlyNumber(total:realTimeExpPerMin()))
toFile(self.outputDir .. "/xpmin-gametime.txt", friendlyNumber(total:durationExpPerMin()))
toFile(self.outputDir .. "/xpmin-currentgame.txt", current and friendlyNumber(current:realTimeExpPerMin()) or "-")
toFile(self.outputDir .. "/xpmin-lastgame.txt", last and friendlyNumber(last:durationExpPerMin()) or "-")
toFile(self.outputDir .. "/timetolevel-realtime.txt", friendlyTime(total:realTimeToNextLevel()))
toFile(self.outputDir .. "/timetolevel-gametime.txt", friendlyTime(total:gameTimeToNextLevel()))
toFile(self.outputDir .. "/timetolevel-currentgame.txt", current and friendlyTime(current:gameTimeToNextLevel()) or "-")
toFile(self.outputDir .. "/timetolevel-lastgame.txt", last and friendlyTime(last:gameTimeToNextLevel()) or "-")
toFile(self.outputDir .. "/ticksgained-overall.txt", string.format("%0.1f", total:ticksGained()))
toFile(self.outputDir .. "/ticksgained-currentgame.txt", current and string.format("%0.1f", current:ticksGained()) or "-")
toFile(self.outputDir .. "/ticksgained-lastgame.txt", last and string.format("%0.1f", last:ticksGained()) or "-")
end

return Output
18 changes: 14 additions & 4 deletions d2info/session.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local constants = require('d2info.constants')
local utils = require('d2info.utils')

local Session = {}
Session.__index = Session
Expand Down Expand Up @@ -32,18 +33,27 @@ function Session:incrementDuration(inc)
self.duration = self.duration + inc
end

function Session:expGained()
return self.exp - self.startExp
end

function Session:ticksGained()
local gainedIntoLevel = constants.experience[self.level] + self:expGained()
return utils.expToTicks(gainedIntoLevel, self.level)
end

local function expPerMin(expGained, duration)
local mins = duration / 60
if mins == 0 then return 0 end
return expGained / mins
end

function Session:realTimeExpPerMin()
return expPerMin(self.exp - self.startExp, os.time() - self.startTime)
return expPerMin(self:expGained(), os.time() - self.startTime)
end

function Session:durationExpPerMin()
return expPerMin(self.exp - self.startExp, self.duration)
return expPerMin(self:expGained(), self.duration)
end

local function secondsToNextLevel(exp, level, expGained, duration)
Expand All @@ -55,11 +65,11 @@ local function secondsToNextLevel(exp, level, expGained, duration)
end

function Session:realTimeToNextLevel()
return secondsToNextLevel(self.exp, self.level, self.exp - self.startExp, os.time() - self.startTime)
return secondsToNextLevel(self.exp, self.level, self:expGained(), os.time() - self.startTime)
end

function Session:gameTimeToNextLevel()
return secondsToNextLevel(self.exp, self.level, self.exp - self.startExp, self.duration)
return secondsToNextLevel(self.exp, self.level, self:expGained(), self.duration)
end

return Session
38 changes: 31 additions & 7 deletions d2info/utils.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local constants = require('d2info.constants')
local utils = {}

function utils.friendlyVersion(ver)
Expand All @@ -17,21 +18,24 @@ function utils.tableMerge(a, b)
end

function utils.friendlyNumber(num)
if num > 1000000 then
return string.format("%0.2fm", num / 1000000)
elseif num > 1000 then
local abs = math.abs(num)
if abs >= 1000000000 then
return string.format("%0.1fb", num / 1000000000)
elseif abs >= 1000000 then
return string.format("%0.1fm", num / 1000000)
elseif abs >= 1000 then
return string.format("%0.1fk", num / 1000)
end
return string.format("%u", num)
return string.format("%d", num)
end

local secondsPerMin = 60
local secondsPerHour = secondsPerMin * 60
local secondsPerDay = secondsPerHour * 24
function utils.friendlyTime(seconds, days)
if seconds == nil then
function utils.friendlyTime(seconds, showDays)
if seconds == nil or seconds < 0 then
return "-"
elseif days and seconds >= secondsPerDay then
elseif showDays and seconds >= secondsPerDay then
return string.format("%ud%02uh", math.floor(seconds / secondsPerDay), (seconds % secondsPerDay) / secondsPerHour)
elseif seconds >= secondsPerHour*10 then
return string.format("%uh", math.floor(seconds / secondsPerHour))
Expand All @@ -44,4 +48,24 @@ function utils.friendlyTime(seconds, days)
end
end

function utils.printf(...)
print(string.format(...))
end

function utils.toFile(filename, txt)
local f = assert(io.open(filename, "w"))
f:write(txt)
f:close()
end

-- Converts exp to GUI 'ticks' of the experience bar
function utils.expToTicks(exp, level)
if level == 99 then return 0 end
local maxTicks = constants.gui.expBar.ticks
local expRange = constants.experience[level+1] - constants.experience[level]
local expGotten = exp - constants.experience[level]
local percentLeveled = expGotten / expRange
return percentLeveled * maxTicks
end

return utils
Loading

0 comments on commit 280f9f2

Please sign in to comment.