Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1735 lines (1338 sloc) 46.2 KB
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Saturday, June 30, 2007, 10:48 -->
<!-- MuClient version 4.13 -->
<muclient>
<plugin
name="Aardwolf_Inventory_V3"
author="Nick Gammon"
id="bd5f6df4728a85a9036ec355"
language="Lua"
purpose="Redirects Aardwolf inventory to another world"
date_written="2008-08-28"
requires="4.36"
version="1.0"
save_state="y"
>
<description trim="y">
Displays the inventory in a tabbed mini-window.
</description>
</plugin>
<!-- Triggers -->
<triggers>
<trigger
enabled="y"
match="{invdata}"
script="inventory_redirect"
omit_from_output="y"
name="inventory_start"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="{invdata *}"
script="inventory_redirect"
omit_from_output="y"
name="container_start"
sequence="100"
>
</trigger>
<trigger
enabled="n"
match="*"
script="inventory_redirect"
name="multi_line_inventory"
omit_from_output="y"
sequence="10"
>
</trigger>
<trigger
enabled="y"
match="{invdetails}"
script="invdetails_redirect"
omit_from_output="y"
name="invdetails_start"
sequence="100"
>
</trigger>
<trigger
enabled="n"
match="*"
script="invdetails_redirect"
name="multi_line_invdetails"
omit_from_output="y"
sequence="10"
>
</trigger>
<trigger
enabled="y"
match="^You drop an? "
regexp="y"
sequence="100"
script="inventory_changed"
>
</trigger>
<trigger
enabled="y"
match="^You get an? "
regexp="y"
sequence="100"
script="inventory_changed"
>
</trigger>
<trigger
enabled="y"
match="You stop holding *"
sequence="100"
script="inventory_changed"
>
</trigger>
<trigger
enabled="y"
match="You hold *"
sequence="100"
script="inventory_changed"
>
</trigger>
<trigger
enabled="y"
match="^You receive an? .+ from "
regexp="y"
sequence="100"
script="inventory_changed"
>
</trigger>
<trigger
enabled="y"
match="{spellheaders noprompt}"
script="spellheaders_redirect"
omit_from_output="y"
name="start_spellheaders"
sequence="100"
>
</trigger>
<trigger
enabled="n"
match="*"
script="spellheaders_redirect"
name="multi_line_spellheaders"
omit_from_output="y"
sequence="10"
>
</trigger>
<trigger
enabled="y"
match="{recoveries noprompt}"
script="recoveries_redirect"
omit_from_output="y"
name="start_recoveries"
sequence="100"
>
</trigger>
<trigger
enabled="n"
match="*"
script="recoveries_redirect"
name="multi_line_recoveries"
omit_from_output="y"
sequence="10"
>
</trigger>
<trigger
enabled="y"
omit_from_output="y"
match="^\{skillgain\}(?<sn>\d+)\,(?<percent>\d+)$"
script="skillgain"
regexp="y"
sequence="100"
>
</trigger>
</triggers>
<timers>
<timer enabled="n"
minute="1"
second="0.00"
offset_second="0.00"
omit_from_output="y"
name="inventory_timer"
>
<send>invdata</send>
</timer>
</timers>
<!-- Script -->
<script>
<![CDATA[
--background_colour = ColourNameToRGB "antiquewhite"
background_colour = ColourNameToRGB "black"
tab_text_colour = ColourNameToRGB "maroon"
tab_colour = ColourNameToRGB "saddlebrown"
title_colour = ColourNameToRGB "maroon"
hyperlink_colour = 0x00DFDF
invdata = {}
-- store each container here
inventories = { [false] = {} }
container_id = false
wanted_container = false
spells = {} -- spells that exist
-- cross-reference for spells - given a name, returns a number
spells_xref = {}
require "checkplugin"
require "commas"
require "tprint"
require "getlines"
require "serialize"
require "pairsbykeys"
require "mw"
require "movewindow"
function capitalize (s)
return string.sub (s, 1, 1):upper () .. string.sub (s, 2):lower ()
end -- capitalize
function plural (count)
if count ~= 1 then
return "s"
else
return ""
end -- if
end -- function plural
flags_table = {
H = "@c(Hum)@w",
G = "@W(Glow)@w",
K = "Kept",
I = "Invis",
M = "Magic",
} -- flags_table
-- see: http://www.aardwolf.com/builders/index.php?option=content&task=view&id=210&Itemid=134
avg_weapon_points = {
3.0, 3.0, 3.0, 4.5, 4.5, 6.0, 6.0, 6.0, 6.0, 8.0, -- 1 to 10
8.0, 10.0, 10.0, 10.0, 10.0, 10.0, 12.0, 12.5, 12.5, 14.0, -- 11 to 20
14.0, 14.0, 15.0, 16.0, 16.0, 16.0, 16.0, 18.0, 18.0, 20.0, -- 21 to 30
21.0, 22.5, 24.5, 27.0, 28.0, 28.0, 28.0, 32.0, 32.0, 35.0, -- 31 to 40
35.0, 36.0, 36.0, 38.5, 40.5, 40.0, 39.0, 42.0, 42.0, 45.0, -- 41 to 50
45.0, 48.0, 48.0, 49.5, 49.5, 50.0, 52.0, 52.0, 52.0, 52.0, -- 51 to 60
55.0, 55.0, 58.5, 58.5, 58.5, 58.5, 60.5, 60.5, 63.0, 63.0, -- 61 to 70
63.0, 65.0, 66.0, 66.0, 67.5, 70.0, 75.0, 77.0, 76.5, 80.0, -- 71 to 80
84.5, 90.0, 96.0, 96.0, 98.0, 102.0, 110.5, 120.0, 120.0, 128.0, -- 81 to 90
135.0, 144.0, 144.5, 160.0, 165.0, 162.0, 171.0, 180.0, 190.0, 190.0, -- 91 to 100
192.5, 192.5, 200.0, 200.0, 207.0, 207.0, 211.5, 211.5, 214.5, 214.5, -- 101 to 110
220.0, 220.0, 222.0, 222.0, 220.5, 220.5, 245.0, 245.0, 231.0, 231.0, -- 111 to 120
238.5, 238.5, 242.0, 242.0, 242.0, 242.0, 253.0, 253.0, 255.0, 255.0, -- 121 to 130
253.0, 253.0, 259.0, 259.0, 266.5, 266.5, 272.0, 272.0, 276.0, 276.0, -- 131 to 140
280.0, 280.0, 280.0, 280.0, 285.0, 285.0, 288.0, 288.0, 294.5, 294.5, -- 141 to 150
297.0, 297.0, 304.0, 304.0, 308.0, 308.0, 313.5, 313.5, 315.0, 315.0, -- 151 to 160
320.0, 320.0, 323.0, 323.0, 324.0, 324.0, 325.0, 325.0, 330.0, 330.0, -- 161 to 170
332.5, 332.5, 333.5, 333.5, 336.0, 336.0, 338.0, 338.0, 330.0, 330.0, -- 171 to 180
346.5, 346.5, 350.0, 350.0, 351.0, 351.0, 356.5, 356.5, 360.0, 360.0, -- 181 to 199
362.5, 362.5, 368.0, 368.0, 372.0, 372.0, 377.0, 377.0, 384.0, 384.0, -- 191 to 200
390.0, -- 201
} -- end of avg_weapon_points
local CANNOT_USE_COLOUR = "#E60E00" -- red
local obvious_wear_locs = {
[""] = true,
hold = true,
light = true,
["hold, portal"] = true,
}
local function popup_window (x, y, heading, f, arg)
local info = {}
local function infoline (text, colour)
table.insert (info, { text = text, colour = colour } )
end -- infoline
local font_height = WindowFontInfo (infowin, font_id, 1)
-- this function populates the window
if not f (arg, infoline) then
return
end -- did not want to proceed
-- find text width - minus colour codes
local infowidth = 5 + WindowTextWidth (infowin, font_id_large, mw.strip_colours (heading))
for k, v in ipairs (info) do
infowidth = math.max (infowidth, 5 + WindowTextWidth (infowin, font_id, mw.strip_colours (v.text)))
end -- for
x = x - infowidth
WindowCreate (infowin, x, y, infowidth + 10,
WindowFontInfo (infowin, font_id_large, 1) +
WindowFontInfo (infowin, font_id, 1) * #info + 12,
5, 2 + 4, 0x080808)
WindowCircleOp (infowin, 3, 2, 2, -3, -3, -- round rectangle
title_colour, 0, 2, 0x141414, 0, 5, 5)
local x = 6
local y = 5
-- name
mw.colourtext (infowin, font_id_large, heading, x, y, 0, 0, ColourNameToRGB "lime")
y = y + WindowFontInfo (infowin, font_id_large, 1)
for k, v in ipairs (info) do
mw.colourtext (infowin, font_id, v.text, x, y, 0, 0, ColourNameToRGB (v.colour))
y = y + font_height
end -- for
WindowShow (infowin, true)
end -- popup_window
local function showmods (modifies, t, infoline, default_colour)
for k, v in ipairs (t) do
-- show red for negative mod
if v.by < 0 then
colour = "@r"
else
colour = default_colour
end -- if
infoline (string.format ("%s%s %s%s by %+i",
default_colour, modifies, colour, v.type, v.by), default_colour)
modifies = string.rep (" ", #modifies)
end -- for
end -- showmods
function detailed_item (hotspot_id, infoline)
local item = invdata [hotspot_id]
current_mouseover = hotspot_id
local colour
-- level
if item.level > stats.level then
colour = CANNOT_USE_COLOUR -- red
else
colour = "white"
end -- if
if item.level > 0 then
infoline ("Level " .. item.level, colour)
end -- has a level
-- flags
--[[ -- skip for now, they don't come out the same as extended
if item.flags and item.flags ~= "" then
local t = {}
string.gsub (item.flags, "%a", function (s)
table.insert (t, flags_table [s] or "Unknown")
end )
infoline ("Flags: " .. table.concat (t, ", "), "white")
end -- flags
--]]
-- extended information?
if not item.type then
if not IsConnected () then
infoline ("(Cannot get more details when not connected.)", "darkgray")
elseif AFK then
infoline ("(Cannot get more details when AFK.)", "darkgray")
else
SendNoEcho ("invdetails " .. (container_id or "") .. " " .. hotspot_id)
infoline ("Loading details ...", "darkgray")
end -- not AFK
else
-- type
if obvious_wear_locs [item.wear] then
infoline (string.format ("%s", item.type), "white")
else
infoline (string.format ("%s (%s)", item.type, item.wear), "white")
end -- if
if item.spells and next (item.spells) then
for k, v in ipairs (item.spells) do
local count = ""
if v.count > 1 then
count = v.count .. " x "
end -- if
if v.uses > 1 then
infoline (string.format ("%i use%s of %slevel %i '%s'",
v.uses, plural (v.uses), count, v.level, v.name),
"deepskyblue")
else
infoline (string.format ("%sLevel %i '%s'",
count, v.level, v.name),
"deepskyblue")
end -- if
end -- for
end -- spells
if item.drink and item.drink.servings then
infoline (string.format ("%i serving%s of %s",
item.drink.servings, plural (item.drink.servings), item.drink.name),
"dodgerblue")
end -- drink
if item.food and item.food.hunger then
infoline (string.format ("Will replenish hunger by %i%%",
item.food.hunger),
"chocolate")
end -- food
if item.light and item.light.duration then
infoline (string.format ("Duration %s",
convert_time (item.light.duration * 60)),
"white")
end -- light
if item.furniture and item.furniture.health then
infoline (string.format ("Sleep: Health by %i%%, mana by %i%%",
item.furniture.health, item.furniture.mana),
"lime")
infoline (string.format ("Maximum users: %i",
item.furniture.users),
"white")
end -- furniture
if item.portal and item.portal.uses then
infoline (string.format ("Uses left: %i",
item.portal.uses),
"lime")
end -- portal
if item.container and item.container.capacity then
if item.container.items > 0 then
infoline (string.format ("Holding: %s item%s, weight: %i.",
commas (item.container.items), plural (item.container.items),
commas (item.container.holding)),
"khaki")
else
infoline ("Empty.", "khaki")
end -- if
infoline (string.format ("Capacity: %s, heaviest: %i.",
commas (item.container.capacity), item.container.heaviest),
"khaki")
if item.container.burden > 1 then
infoline (string.format ("Burden: %i, multiplier: %i%%",
item.container.burden, item.container.multiplier),
"khaki")
else
infoline (string.format ("Multiplier: %i%%",
item.container.multiplier),
"khaki")
end -- if
local totweight = item.container.holding * item.container.multiplier / 100 + item.weight
infoline (string.format ("Total weight: %.0f.",
math.ceil (totweight)),
"yellow")
end -- container
if item.type == "Weapon" then
-- see if they know how to use it
local sn = spells_xref [item.weapon.weapontype]
colour = CANNOT_USE_COLOUR
if spells [sn] and spells [sn].percent > 1 then
colour = "white"
end -- if
infoline (string.format ("%s (%i damage)",
capitalize (item.weapon.weapontype), item.weapon.avgdamage), colour)
local avg_damage = avg_weapon_points [item.level] or 1
local rating = 0
local L = item.level
local new_points
if item.weapon.avgdamage > avg_damage then
repeat
L = L + 1
if L > #avg_weapon_points then
break
end -- if
if avg_weapon_points [L] > item.weapon.avgdamage then
break
end -- if
new_points = avg_weapon_points [L]
rating = rating + 1
until false
-- drop back to first weapon that had this rating
if new_points then
rating = rating + 1
while avg_weapon_points [L - 1] == new_points do
L = L - 1
rating = rating - 1
end -- while
end -- if
elseif item.weapon.avgdamage < avg_damage then
repeat
L = L - 1
if L < 1 then
break
end -- if
if avg_weapon_points [L] < item.weapon.avgdamage then
break
end -- if
new_points = avg_weapon_points [L]
rating = rating - 1
until false
-- go forwards to first weapon that had this rating
if new_points then
rating = rating - 1
while avg_weapon_points [L + 1] == new_points do
L = L + 1
rating = rating + 1
end -- while
end -- if
end -- if
if rating > 0 then
infoline (string.format ("Rating: +%i", rating), "lime")
elseif rating < 0 then
infoline (string.format ("Rating: %i", rating), "slategray")
end -- if
end -- if weapon
local svalue = "No sale price."
local sweight = ""
if item.value > 0 then
svalue = string.format ("Worth: %s gold.", commas (item.value))
end -- if
if item.weight ~= 0 then
sweight = string.format (" Weight: %i.", commas (item.weight))
end -- if
infoline (string.format ("%s%s", svalue, sweight), "white")
showmods ("Stats:", item.statmod, infoline, "@g")
showmods ("Resists:", item.resistmod, infoline, "@y")
showmods ("Skills:", item.skillmod, infoline, "@m")
if item.skilleffects > 0 then
infoline (string.format ("Item has %i skill effect%s.",
item.skilleffects, plural (item.skilleffects)), "deepskyblue")
end -- if
if item.resisteffects > 0 then
infoline (string.format ("Item has %i resistance effect%s.",
item.resisteffects, plural (item.resisteffects)), "deepskyblue")
end -- if
if item.objflags ~= "" then
local flaglist = utils.split (string.gsub (item.objflags, ",%s+", ","), ",")
table.sort (flaglist)
local flagline = "Flags:"
for i, v in ipairs (flaglist) do
if #flagline > 25 then
infoline (flagline, "teal")
flagline = " "
end
flagline = flagline .. " " .. capitalize (v)
if i < #flaglist then
flagline = flagline .. ","
end -- not end of list
end -- for
-- last line
infoline (flagline, "teal")
end -- if flags
if item.owner ~= "" then
infoline (string.format ("Owner: %s", item.owner), "cyan")
end -- owner
if item.clan ~= "" then
infoline (string.format ("Clan: From %s", item.clan), "yellow")
end -- clan
end -- if extended information
infoline (string.format ("Id: %s", hotspot_id), "#424200")
return true
end -- detailed_item
function itemmouseover (flags, hotspot_id)
item = invdata [hotspot_id]
if not item then return end
-- work out coordinates
local x = WindowHotspotInfo (win, hotspot_id, 1) + WindowInfo (win, 10) - 45
local y = WindowHotspotInfo (win, hotspot_id, 2) + WindowInfo (win, 11)
popup_window (x, y, item.name, detailed_item, hotspot_id)
end -- itemmouseover
function inventory_info (hotspot_id, infoline)
current_mouseover = hotspot_id
categories = {}
weight = 0
infoline (string.format ("Contains %i item%s.", #inventory, plural (#inventory)), "yellow")
for _, v in ipairs (inventory) do
categories [v.typecode] = (categories [v.typecode] or 0) + 1
end -- for
for k, v in pairsByKeys (categories, function (a, b)
return code_descriptions [a] < code_descriptions [b] end) do
if v > 0 then
infoline (string.format ("%10s: %3s item%s.",
code_descriptions [k], commas (v), plural (v)), "white")
end -- have some
end -- for
if container_id then
item = invdata [container_id]
infoline (string.format ("Bag weight: %s.",
commas (item.weight)),
"khaki")
if item.container.capacity > 0 then
infoline (string.format ("Item weight: %s / %s.",
commas (item.container.holding), commas (item.container.capacity)),
"khaki")
infoline (string.format ("Usage: %.1f%% full.",
item.container.holding / item.container.capacity * 100),
"khaki")
end -- if
infoline (string.format ("Heaviest: %i.", item.container.heaviest),
"khaki")
if item.container.burden > 1 then
infoline (string.format ("Burden: %i.", item.container.burden),
"khaki")
end -- burden
infoline (string.format ("Multiplier: %i%%.",
item.container.multiplier),
"khaki")
local totweight = item.container.holding * item.container.multiplier / 100 + item.weight
infoline (string.format ("Total weight: %.0f.",
math.ceil (totweight)),
"yellow")
end -- container
return true
end -- inventory_info
function headingmouseover (flags, hotspot_id)
-- work out coordinates
local x = WindowHotspotInfo (win, hotspot_id, 1) + WindowInfo (win, 10) - 45
local y = WindowHotspotInfo (win, hotspot_id, 2) + WindowInfo (win, 11)
popup_window (x, y, headingtitle, inventory_info, hotspot_id)
end -- headingmouseover
function cancelmouseover (flags, hotspot_id)
WindowShow (infowin, false)
end -- cancelmouseover
function mouse_down_tab (flags, hotspot_id)
if active_tab ~= hotspot_id then
start = 1
end -- different tab
active_tab = hotspot_id
Display_Inventory ()
end -- mouse_down_tab
function itemmousedown (flags, hotspot_id)
ouch_count = (ouch_count or 0) + 1
print ("ouch!", hotspot_id)
if ouch_count % 10 == 0 then
print "Are you crazy? Stop doing that!"
end -- if
end -- itemmousedown
function itemmouseup (flags, hotspot_id)
if invdata [hotspot_id].typecode == 11 then
wanted_container = hotspot_id
if inventories [hotspot_id] then
container_id = hotspot_id
start = 1
Display_Inventory ()
else
SendNoEcho ("invdata " .. hotspot_id)
end -- if not loaded
else -- if container
local result = WindowMenu (win, WindowInfo (win, 14),
WindowInfo (win, 15), "^" .. mw.strip_colours (invdata [hotspot_id].name) ..
"|-|Wield|Drop|Wear")
print (result)
if result ~= "" then
Send (result:lower () .. " " .. string.match (hotspot_id, "%d+"))
end -- if
end -- if not container
end -- itemmouseup
function display_inventory_item (y, item)
local x = 2
local text = item.name
local count
if item.count > 1 then
count = string.format ("%3i x ", item.count)
else
count = string.format (" ")
end -- if
x = x + WindowText (win, font_id, count, x, y, 0, 0, 0xC0C0C0)
if item.level > 0 then
if item.level > stats.level then
text = text .. " @R(" .. item.level .. ")@w"
else
text = text .. " (" .. item.level .. ")"
end -- if
end -- if has a level
mw.colourtext (win, font_id, text, x, y, 0, 0, 0xC0C0C0)
local height = WindowFontInfo (win, font_id, 1)
local right = x + WindowTextWidth (win, font_id, text)
local bottom = y + height
WindowAddHotspot(win, item.id,
x, y, right, bottom,
"itemmouseover",
"cancelmouseover",
"itemmousedown",
"", -- cancelmousedown
"itemmouseup",
"",
1, 0)
end -- display_inventory_item
local function make_table (t1)
local t2 = {}
for _, v in ipairs (t1) do
t2 [v] = true
end
return t2
end -- make_table
local equipcodes = make_table {
3, -- wand
4, -- staff
5, -- weapon
7, -- armor
} -- end equipcodes
local bagcodes = make_table {
11, -- container
} -- end bagcodes
local magiccodes = make_table {
2, -- scroll
8, -- potion
19, -- pill
} -- end magiccodes
local travelcodes = make_table {
13, -- key
15, -- boat
20, -- portal
} -- end travelcodes
local othercodes = make_table {
1, -- light
6, -- treasure
9, -- furniture
10, -- trash
12, -- drink
14, -- food
16, -- mobcorpse
17, -- corpse
18, -- fountain
21, -- beacon
22, -- giftcard
23, -- gold
24, -- raw material
} -- end othercodes
code_descriptions = {
"Light", -- 1
"Scroll",
"Wand",
"Staff",
"Weapon",
"Treasure",
"Armor",
"Potion",
"Furniture",
"Trash", -- 10
"Container",
"Drink",
"Key",
"Food",
"Boat",
"Mobcorpse",
"Corpse",
"Fountain",
"Pill",
"Portal", -- 20
"Beacon",
"Giftcard",
"Gold",
"Raw material", -- 24
} -- end code_descriptions
function make_hyperlink (text, left, top, action, hint, colour)
local height = WindowFontInfo (win, font_id, 1)
local right = left + WindowTextWidth (win, font_id, text)
local bottom = top + height
WindowAddHotspot(win, text,
left, top, right, bottom,
"", -- mouseover
"", -- cancelmouseover
"mousedown",
"", -- cancelmousedown
"", -- mouseup
hint,
1, 0)
WindowText (win, font_id, text, left, top, right, bottom, colour or hyperlink_colour)
hyperlink_functions [text] = action
return right
end -- make_hyperlink
function hyperlink_first ()
start = 1
Display_Inventory ()
end -- hyperlink_first
function hyperlink_next ()
start = last_line_shown + 1
Display_Inventory ()
end -- hyperlink_next
function hyperlink_previous ()
start = start - max_lines_to_show
Display_Inventory ()
end -- hyperlink_previous
function hyperlink_combine ()
combine = true
start = 1 -- may end up with page 2 of 1
Display_Inventory ()
end -- hyperlink_combine
function hyperlink_expand ()
combine = false
Display_Inventory ()
end -- hyperlink_expand
function hyperlink_close ()
if container_id then
container_id = false
wanted_container = false
WindowShow (infowin, false)
Display_Inventory ()
return
end -- if
WindowShow (win, false)
WindowShow (infowin, false)
EnablePlugin (GetPluginID (), false)
end -- hyperlink_close
function display_generic (code_table)
code_table = code_table or last_code_table
last_code_table = code_table
local t = {}
local keys = {}
local left = (width - WindowTextWidth (win, font_id, "[x]", false)) - 2
if container_id then
make_hyperlink ("[x]", left, 2, hyperlink_close, "Close bag", ColourNameToRGB "white")
else
make_hyperlink ("[x]", left, 2, hyperlink_close, "Close inventory", ColourNameToRGB "white")
end -- if
for k, v in ipairs (inventory) do
if code_table [v.typecode] then
if combine then
local key = string.format ("%s|%i|%i", v.name, v.level, v.typecode)
local item = keys [key] -- already have an item of this name/level/type?
if item and
v.unique == 0 and -- don't combine unique items
v.typecode ~= 11 then -- nor containers
item.count = item.count + 1 -- yes
else
keys [key] = v -- no, make one
v.count = 1 -- first one
table.insert (t, v)
end -- if
else -- combine not wanted
v.count = 1
table.insert (t, v)
end -- if
end -- if type wanted
end -- for
y = font_height * 3 + 2
local right = 10
if #t == 0 then
WindowText (win, font_id,"No items in this category.",
right, y, 0, 0, 0x808080)
return
end -- if
table.sort (t, function (a, b)
if a.typecode ~= b.typecode then
return a.typecode < b.typecode
end -- if
if a.level ~= b.level then
return a.level > b.level
end -- if
return a.name > b.name
end )
local count = 0
if start < 1 then
start = 1
end -- too low
for i = start, start + max_lines_to_show - 1 do
if i > #t then
break
end
display_inventory_item (y, t [i])
last_line_shown = i
y = y + font_height
end -- for
local top = font_height * (max_lines_to_show + 3) + 3
if math.ceil (#t / max_lines_to_show) > 1 then
right = make_hyperlink ("[First]", right + 10, top, hyperlink_first, "First page")
else
right = right + WindowTextWidth (win, font_id, "[First]") + 10
end -- if
if start > 1 then
right = make_hyperlink ("[Previous]", right + 10, top, hyperlink_previous, "Previous page")
else
right = right + WindowTextWidth (win, font_id, "[Previous]") + 10
end -- if
if last_line_shown < #t then
right = make_hyperlink ("[Next]", right + 10, top, hyperlink_next, "Next page")
else
right = right + WindowTextWidth (win, font_id, "[Next]") + 10
end -- if
right = right + 10
if combine then
right = make_hyperlink ("[Expand]", right + 10, top, hyperlink_expand, "Show each item")
else
right = make_hyperlink ("[Combine]", right + 10, top, hyperlink_combine, "Combine like items")
end
local pageinfo = string.format ("(Page %i of %i)",
math.ceil (start / max_lines_to_show), math.ceil (#t / max_lines_to_show))
local left = (width - WindowTextWidth (win, font_id, pageinfo, false)) - 10
WindowText (win, font_id, pageinfo, left, font_height + 10, 0, 0, ColourNameToRGB "white")
end -- display_generic
function display_equipment ()
display_generic (equipcodes)
end -- display_equipment
function display_bags ()
display_generic (bagcodes)
end -- display_bags
function display_magic ()
display_generic (magiccodes)
end -- display_magic
function display_travel ()
display_generic (travelcodes)
end -- display_travel
function display_other ()
display_generic (othercodes)
end -- display_other
tabs = {
{ name = "Bags", display_func = display_bags, heading = "Bags / Containers", },
{ name = "Equip", display_func = display_equipment, heading = "Armor / Weapons", },
{ name = "Magic", display_func = display_magic, heading = "Magical Items", },
{ name = "Travel", display_func = display_travel, heading = "Travel", },
{ name = "Other", display_func = display_other, heading = "Other", },
}
active_tab = "Equip"
start = 1
function mousedown (flags, hotspotid)
local f = hyperlink_functions [hotspotid]
if f then
f (flags, hotspotid)
end -- function found
end -- mousedown
hyperlink_functions = {}
function drawtab (x, y, tabwidth, colour, width, text, active, hint)
if tabwidth == 0 then
tabwidth = WindowTextWidth (win, font_id_bold, text, false) + 15
end -- if
local points = {
0, 2, -- start (top left) 1 .. 2
10, 2, 10, 2, 10, 2, -- top of tab, before curve 3 .. 8
10, 22, 10, 22, 30, 22, -- bottom of tab - left side 9 .. 14
10, 22, 10, 22, 10, 22, -- bottom of tab - right side 15 .. 20
20, 22, 20, 22, 20, 2, -- top of tab, after curve 21 .. 26
22, 2, 22, 2, 22, 2, -- finishing horizontal line 27 .. 32
} -- end points table
-- add width
for i = 15, #points, 2 do
points [i] = points [i] + tabwidth - 10
end -- for
WindowCreate (tabwin, 0, 0, tabwidth + 200, 30, 0, 0, background_colour)
WindowBezier (tabwin, table.concat (points, ","), colour, 0, width)
WindowLine (tabwin, tabwidth + 20, 2, tabwidth + 200, 2, colour, 0, width)
if active then
WindowLine (tabwin, tabwidth + 10, 2, tabwidth + 20, 2, colour, 0, width)
else
WindowLine (tabwin, 0, 2, tabwidth + 20, 2, colour, 0, width)
end -- not active
WindowFilter (tabwin, 0, 0, 0, 0, 25, 0) -- blur
WindowImageFromWindow (win, "tab", tabwin)
--WindowBlendImage (win, "tab", x, y, 0, 0, 6, 1)
WindowDrawImage (win, "tab", x, y, 0, 0, 1, 2, 0, 0, 0)
-- tab text
local left, top, right, bottom
left = x + 9 + (tabwidth - WindowTextWidth (win, font_id_bold, text, false) + width) / 2
top = y + 6
WindowText (win, font_id_bold, text, left, top, 0, 0, tab_text_colour)
WindowAddHotspot(win, text,
x, y, x + tabwidth + 10, y + 25,
"", -- mouseover
"", -- cancelmouseover
"mousedown",
"", -- cancelmousedown
"", -- mouseup
"Show " .. hint,
1, 0)
hyperlink_functions [text] = mouse_down_tab
return x + tabwidth + 10 -- where it ends
end -- drawtab
function Display_Inventory ()
width = 310
height = 400
-- once we know our level
if not stats then
return
end
inventory = inventories [container_id]
if not inventory then
return
end
-- recreate the window the correct size
check (WindowCreate (win,
windowinfo.window_left,
windowinfo.window_top,
width,
height,
windowinfo.window_mode,
windowinfo.window_flags,
background_colour) )
max_lines_to_show = math.floor ((height - (font_height * 6)) / font_height)
WindowFilter (win, 0, 0, 0, 0, 2, 25) -- monochrome noise in whole window - level 100
WindowDeleteAllHotspots (win)
movewindow.add_drag_handler (win, 0, 0, 0, font_height, 1)
-- title rectangle
check (WindowRectOp (win, 2, 2, 2, -2, font_height * 3, title_colour))
taby = height - 30
tabx = 0
local display_func
local heading
for k, v in ipairs (tabs) do
local active = v.name == active_tab
if active then
display_func = v.display_func
heading = v.heading
end -- if
tabx = drawtab (tabx, taby, 0, tab_colour, 2, v.name, active, v.heading)
end -- for each tab
-- main inventory or container
headingtitle = "- Inventory -"
if container_id then
headingtitle = mw.strip_colours (invdata [container_id].name)
headingtitle = headingtitle:sub (1, 1):upper () .. headingtitle:sub (2)
end -- this is a container
local left = (width - WindowTextWidth (win, font_id_bold, headingtitle, false)) / 2
local top = 5
WindowText (win, font_id_bold, headingtitle, left, top, 0, 0, ColourNameToRGB "white")
do
local height = WindowFontInfo (win, font_id_bold, 1)
local right = left + WindowTextWidth (win, font_id_bold, headingtitle)
local bottom = top + height
WindowAddHotspot(win, "<title>",
left, top, right, bottom,
"headingmouseover",
"cancelmouseover",
"",
"", -- cancelmousedown
"", -- mouseup
"",
1, 0)
end
-- which tab
WindowText (win, font_id_bold, heading, 10, font_height + 10, 0, 0, ColourNameToRGB "white")
if display_func then
display_func ()
end -- if
-- show it now (or refresh)
WindowShow (win, true)
-- DrawEdge rectangle
check (WindowRectOp (win, 5, 0, 0, 0, 0, 10, 15))
end -- Display_Inventory
function inventory_changed (name, line, wildcards, styles)
SendNoEcho "invdata"
end -- inventory_changed
-- inventory redirector
function inventory_redirect (name, line, wildcards, styles)
if line == "{/invdata}" then
EnableTrigger ("multi_line_inventory", false) -- no more lines to go
-- save as the container inventory or the main inventory
inventories [new_inventory.container_id] = new_inventory
if (not new_inventory.container_id and not container_id) or
(new_inventory.container_id == wanted_container) then
container_id = wanted_container
WindowShow (infowin, false)
start = 1
Display_Inventory ()
end -- updated main inventory
return
end -- if inventory done
EnableTrigger ("multi_line_inventory", true) -- capture subsequent lines
if name == "inventory_start" then
new_inventory = { container_id = false }
return
end -- if start
if name == "container_start" then
new_inventory = { container_id = wildcards [1] .. "/0" }
return
end -- if start
local data = utils.split (trim (line), ",")
local id = data [1]
if not string.find (id, "^%d+") then
return
end -- not an ID
local t = {
id = id,
flags = data [2],
name = data [3],
level = tonumber (data [4]),
typecode = tonumber (data [5]),
unique = tonumber (data [6]),
wear_loc = tonumber (data [7]),
}
table.insert (new_inventory, t)
-- save for caching
invdata [id] = invdata [id] or t
end -- function inventory_redirect
-- invdetails redirector
function invdetails_redirect (name, line, wildcards, styles)
if line == "{/invdetails}" then
EnableTrigger ("multi_line_invdetails", false) -- no more lines to go
--tprint (new_invdetails)
if new_invdetails.id then
new_invdetails.name = invdata [new_invdetails.id].name
new_invdetails.typecode = invdata [new_invdetails.id].typecode
invdata [new_invdetails.id] = new_invdetails
if WindowInfo (infowin, 5) and current_mouseover == new_invdetails.id then
itemmouseover (0, current_mouseover)
end -- if
end -- if have id
return
end -- if invdetails done
EnableTrigger ("multi_line_invdetails", true) -- capture subsequent lines
if name == "invdetails_start" then
new_invdetails = {}
new_invdetails.statmod = {}
new_invdetails.resistmod = {}
new_invdetails.skillmod = {}
return
end -- if start
local type, details = string.match (line, "^{(%a-)}(.+)$")
if not type then
return
end
local data = utils.split (details, "|")
if type == "invheader" then
new_invdetails.id = data [1]
new_invdetails.level = tonumber (data [2])
new_invdetails.type = data [3]
new_invdetails.value = tonumber (data [4])
new_invdetails.weight = tonumber (data [5])
new_invdetails.wear = data [6]
new_invdetails.objflags = data [7]
new_invdetails.owner = data [8]
new_invdetails.clan = data [9]
new_invdetails.timer = data [10]
new_invdetails.resisteffects = tonumber (data [11]) or 0
new_invdetails.skilleffects = tonumber (data [12]) or 0
elseif type == "weapon" then
local t = {}
new_invdetails.weapon = t
t.weapontype = data [1]
t.avgdamage = tonumber (data [2])
t.dmgnoun = data [3]
t.dmgtype = data [4]
t.weaponflags = data [5]
elseif type == "spells" then -- {spells}uses|level|sn0..sn4
local t = {}
new_invdetails.spells = t
local level = tonumber (data [2])
local uses = tonumber (data [1])
local sns = {}
for i = 3, 7 do
local sn = tonumber (data [i])
if sn and sn ~= 0 and spells [sn] then
sns [sn] = (sns [sn] or 0) + 1
end -- if
end -- if
for k, v in pairs (sns) do
table.insert (t, { name = capitalize (spells [k].name), count = v, level = level, uses = uses } )
end -- for
elseif type == "drink" then -- {drink}5|water|100|100|30|0|0
local t = {}
new_invdetails.drink = t
t.servings = tonumber (data [1])
t.name = data [2]
t.capacity = tonumber (data [3])
t.remaining = tonumber (data [4])
t.thirst = tonumber (data [5])
t.hunger = tonumber (data [6])
t.proof = tonumber (data [7])
elseif type == "food" then -- {food}2
local t = {}
new_invdetails.food = t
t.hunger = tonumber (data [1])
elseif type == "light" then -- {light}50
local t = {}
new_invdetails.light = t
t.duration = tonumber (data [1])
elseif type == "portal" then -- {portal}4
local t = {}
new_invdetails.portal = t
t.uses = tonumber (data [1])
elseif type == "furniture" then -- {furniture}health regen%|mana regen%|max users
local t = {}
new_invdetails.furniture = t
t.health = tonumber (data [1])
t.mana = tonumber (data [2])
t.users = tonumber (data [3])
elseif type == "container" then
-- {container}capacity|heaviest item allowed|currently holding|number of items|tot weight|item burden|multiplier
local t = {}
new_invdetails.container = t
t.capacity = tonumber (data [1])
t.heaviest = tonumber (data [2])
t.holding = tonumber (data [3])
t.items = tonumber (data [4])
t.tot_weight = tonumber (data [5])
t.burden = tonumber (data [6])
t.multiplier = tonumber (data [7])
end -- if
-- stats modifiers
if type == "statmod" then
table.insert (new_invdetails.statmod, {
type = data [1],
by = tonumber (data [2]),
})
end -- statmod
table.sort (new_invdetails.statmod, function (a, b) return a.type < b.type end)
-- resistance modifiers
if type == "resistmod" then
table.insert (new_invdetails.resistmod, {
type = data [1],
by = tonumber (data [2]),
})
end -- resistmod
table.sort (new_invdetails.resistmod, function (a, b) return a.type < b.type end)
-- skill modifiers
if type == "skillmod" then
local sn = tonumber (data [1])
if spells [sn] then
table.insert (new_invdetails.skillmod, {
type = capitalize (spells [sn].name),
by = tonumber (data [2]),
})
end -- skill exists
end -- skillmod
table.sort (new_invdetails.skillmod, function (a, b) return a.type < b.type end)
end -- function invdetails_redirect
-- parse spellheaders line, break into pieces
function parse_spell_line (line)
local sn, name, target, duration, percent, recovery, skilltype =
string.match (line, "^(%d+)%,([A-Za-z0-9 ]+)%,(%d+)%,(%d+)%,(%d+),(-?%d+),(%d+)$")
if not sn then
ColourNote ("white", "red", "Invalid spellheaders line: " .. line)
return nil
end -- not a valid spell name
return tonumber (sn),
trim (name:lower()),
tonumber (target),
tonumber (duration),
tonumber (percent),
tonumber (recovery),
tonumber (skilltype)
end -- parse_spell_line
-- make tables that let us convert spell name to spell number
function make_xrefs ()
spells_xref = {}
for k, v in pairs (spells) do
spells_xref [v.name] = k
end -- for each spell
end -- make_xrefs
-- we gained a skill
function skillgain (name, line, wildcards)
local sn = tonumber (wildcards.sn)
local percent = tonumber (wildcards.percent)
if spells [sn] then
spells [sn].percent = percent
end -- if exists
end -- skillgain
-- spells redirector
function spellheaders_redirect (name, line, wildcards, styles)
-- start of spells list? remove old ones
if name == "start_spellheaders" then
spells = {}
spells_count = 0
EnableTrigger ("multi_line_spellheaders", true) -- capture subsequent lines
return
end -- if
if line == "{/spellheaders}" then
EnableTrigger ("multi_line_spellheaders", false) -- no more lines to go
ColourNote ("green", "", "Loaded information about " .. spells_count .. " spells.")
make_xrefs ()
SaveState ()
return
end -- if
local sn, name, target, duration, percent, recovery, skilltype = parse_spell_line (line)
if not sn then return end
spells [sn] = {
name = name:lower (), -- name of spell
target = target, -- target code
percent = percent, -- percent known for this character
recovery = recovery, -- depends on which recovery
skilltype = skilltype, -- 1 = spell, 2 = skill
} -- end spells table item
spells_count = spells_count + 1
end -- function spellheaders_redirect
-- cooldowns redirector
function recoveries_redirect (name, line, wildcards, styles)
-- start of recoveries list? remove old ones
if name == "start_recoveries" then
EnableTrigger ("multi_line_recoveries", true) -- capture subsequent lines
return
end -- if
if line == "{/recoveries}" then
EnableTrigger ("multi_line_recoveries", false) -- no more lines to go
return
end -- if
end -- function recoveries_redirect
function OnPluginBroadcast (msg, id, name, text)
if msg == 1 and id == "0e191dc7829ff2ac2433c2d8" then
AFK = text == "y"
if playing and not AFK and just_connected then
SendNoEcho ("invdata")
just_connected = false
end -- if
-- our stats
elseif id == "8a710e0783b431c06d61a54c" then
stats = GetPluginVariableList ("8a710e0783b431c06d61a54c")
stats.level = tonumber (stats.level)
-- playing status
elseif id == "f5b05e8826711cdb0d141939" then
playing = text == "y"
if playing and not AFK and just_connected then
SendNoEcho ("invdata")
just_connected = false
end -- if
end -- if
-- if we are AFK, don't send message
EnableTimer ("inventory_timer", playing and not AFK)
end
function OnPluginInstall ()
assert (loadstring (GetVariable ("spells") or "")) ()
combine = GetVariable ("combine") == "true"
make_xrefs ()
win = GetPluginID ()
tabwin = win .. ":tab"
infowin = win .. ":info"
local fonts = utils.getfontfamilies ()
if fonts.Dina then
font_size = 8
font_name = "Dina" -- the actual font
else
font_size = 10
font_name = "Courier"
end -- if
font_id = "inventory_font" -- our internal name
font_id_bold = "inventory_font_bold" -- our internal name
font_id_large = "inventory_font_large" -- our internal name
windowinfo = movewindow.install (win, 6)
-- make miniwindow so I can grab the font info
WindowCreate (win,
0, 0, 1, 1,
6, -- top right
0,
background_colour)
WindowFont (win, font_id, font_name, font_size, false, false, false, false, 0, 49) -- normal
WindowFont (win, font_id_bold, font_name, font_size, true, false, false, false, 0, 49) -- bold
-- load fonts - mouseover window
WindowCreate (infowin, 0, 0, 1, 1, 0, 0, 0)
WindowFont (infowin, font_id, font_name, font_size, false, false, false, false, 0, 49) -- normal
WindowFont (infowin, font_id_bold, font_name, font_size, true, false, false, false, 0, 49) -- bold
WindowFont (infowin, font_id_large, font_name, font_size + 2, false, false, false, false, 0, 49) -- larger
font_height = WindowFontInfo (win, font_id, 1) -- - WindowFontInfo (win, font_id, 4) + 1 -- height
font_width = WindowFontInfo (win, font_id, 6) -- avg width
if GetVariable ("enabled") == "false" then
ColourNote ("yellow", "", "Warning: Plugin " .. GetPluginName ().. " is currently disabled.")
check (EnablePlugin(GetPluginID (), false))
return
end -- they didn't enable us last time
OnPluginEnable () -- do initialization stuff
end -- OnPluginInstall
-- pull in telnet option handling
dofile (GetPluginInfo (GetPluginID (), 20) .. "telnet_options.lua")
function OnPluginConnect ()
TelnetOptionOn (TELOPT_INVENTORY)
just_connected = true
if next (spells) == nil then
SendNoEcho "slist noprompt"
end -- if no spells known
SendNoEcho "invdata"
end -- function OnPluginConnect
function OnPluginClose ()
-- if enabled
if GetPluginInfo (GetPluginID (), 17) then
TelnetOptionOff (TELOPT_INVENTORY)
end -- if enabled
end -- OnPluginClose
function OnPluginEnable ()
checkplugin ("0e191dc7829ff2ac2433c2d8", "AFK_Detector.xml")
checkplugin ("f5b05e8826711cdb0d141939", "Playing_Detector.xml")
-- if we are connected when the plugin loads, it must have been reloaded whilst playing
if IsConnected () then
OnPluginConnect ()
end -- if already connected
-- see if we are playing at install time
playing = GetPluginVariable ("f5b05e8826711cdb0d141939", "playing") == "y"
end -- OnPluginEnable
function OnPluginDisable ()
TelnetOptionOff (TELOPT_INVENTORY)
end -- OnPluginDisable
function OnPluginSaveState ()
SetVariable ("enabled", tostring (GetPluginInfo (GetPluginID (), 17)))
SetVariable ("combine", tostring (combine))
SetVariable ("spells",
"spells = " .. serialize.save_simple (spells))
movewindow.save_state (win)
end -- OnPluginSaveState
--[[
probably weapons/armor containers(incl. drink) pills/junk/trophies/pies potions/scrolls/wands/staves'
then:
equipment / food / magic / travel / containers / other
you have to consider that items load with level variability +-3 levels'
http://www.aardwolf.com/builders/index.php?option=content&task=view&id=210&Itemid=134
- The inventory view has item types at the end.
invdetails 2067752/0
{invdetails}
{invheader}2067752|0|3|Weapon|3|2wield|v3|||||1|
{weapon}spear|5|pierce|Pierce|
{statmod}Dexterity|1
{/invdetails}
--]]
]]>
</script>
</muclient>