mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-20 10:23:16 -05:00
100 emulator names the two platforms run had no profile, so their packs carried nothing for them. Each was read from the platform's own launcher or scriptmodule: the same program as an existing profile takes the name in cores:, a different build gets its own profile read from that version, a launcher or self-contained game goes to remove_cores, and the rest are new profiles written from their source or shipped binary. The files they need that the collection lacked are collected from the upstream distributions. Bungie and splitwolf trees are read by path and stay out of dedup.
993 lines
30 KiB
Lua
993 lines
30 KiB
Lua
-- Basic HUD 1.0, by treellama
|
|
-- based on M2 Default HUD by Hopper
|
|
-- from work by Bungie and the Aleph One developers
|
|
|
|
Triggers = {}
|
|
function Triggers.draw()
|
|
if TexturePalette.draw() then return end
|
|
|
|
if Player.motion_sensor.active then
|
|
local sidelen = globals.motion_sensor_side_length
|
|
|
|
local r = rects["motion sensor"]
|
|
local fg = InterfaceColors["inventory text"]
|
|
|
|
clip_motion_sensor(r.x, r.y, sidelen, sidelen)
|
|
imgs["motion sensor virgin mount"]:draw(r.x, r.y)
|
|
|
|
local comp36 = globals.network_compass_36
|
|
local comp61 = globals.network_compass_61
|
|
|
|
if Player.compass.nw then
|
|
imgs["network compass nw"]:draw(r.x + comp36, r.y + comp36)
|
|
end
|
|
if Player.compass.ne then
|
|
imgs["network compass ne"]:draw(r.x + comp61, r.y + comp36)
|
|
end
|
|
if Player.compass.se then
|
|
imgs["network compass se"]:draw(r.x + comp61, r.y + comp61)
|
|
end
|
|
if Player.compass.sw then
|
|
imgs["network compass sw"]:draw(r.x + comp36, r.y + comp61)
|
|
end
|
|
|
|
for i = 1,#Player.motion_sensor.blips do
|
|
local blip = Player.motion_sensor.blips[i - 1]
|
|
local img = imgs["motion sensor " .. blip.type.mnemonic .. " " .. blip.intensity]
|
|
|
|
local mult = (blip.distance/globals.motion_sensor_range) * (globals.motion_sensor_scale)
|
|
local rad = math.rad(blip.direction)
|
|
local xoff = r.x + (sidelen / 2) + (math.cos(rad) * mult)
|
|
local yoff = r.y + (sidelen / 2) + (math.sin(rad) * mult)
|
|
|
|
img:draw(xoff - (img.width / 2), yoff - (img.height / 2))
|
|
end
|
|
unclip_motion_sensor()
|
|
|
|
end
|
|
|
|
if true then
|
|
local x = rects["inventory"].x
|
|
local y = rects["inventory"].y
|
|
local w = Screen.width - x
|
|
local h = Screen.height - y
|
|
local fg = InterfaceColors["inventory text"]
|
|
local bg = InterfaceColors["inventory background"]
|
|
|
|
Screen.fill_rect(x - adj(2), y - adj(2), w + adj(2), h, bg)
|
|
Screen.fill_rect(x - adj(2), y, w, h, bg)
|
|
end
|
|
|
|
-- inventory
|
|
if true then
|
|
local r = rects["inventory"]
|
|
local f = int_fonts["interface"]
|
|
local rowh = f.line_height
|
|
local sec = Player.inventory_sections.current
|
|
|
|
-- header
|
|
Screen.fill_rect(r.x, r.y, r.width, rowh, InterfaceColors["inventory header background"]);
|
|
draw_text_trunc(f, sec.name, r.x + globals.text_inset, r.y, r.width - globals.text_inset, InterfaceColors["inventory text"])
|
|
|
|
-- content
|
|
Screen.fill_rect(r.x, r.y + rowh, r.width, r.height - rowh, InterfaceColors["inventory background"])
|
|
if sec.type == InventorySections["network statistics"] then
|
|
network_stats_draw()
|
|
else
|
|
inventory_items_draw()
|
|
end
|
|
end
|
|
|
|
-- weapons
|
|
if true then
|
|
local r = rects["weapon display"]
|
|
Screen.fill_rect(r.x, r.y, r.width, r.height, InterfaceColors["inventory background"])
|
|
|
|
local wep = Player.weapons.desired
|
|
if wep then
|
|
-- weapon shapes
|
|
local shpinfo = wep_shapes[wep.type]
|
|
if shpinfo.unusable then
|
|
weapon_shape_draw(shpinfo.single)
|
|
if Player.items[wep.type.mnemonic].count > 1 then
|
|
weapon_shape_draw(shpinfo.multiple)
|
|
else
|
|
weapon_shape_draw(shpinfo.unusable)
|
|
end
|
|
elseif shpinfo.multiple then
|
|
if Player.items[wep.type.mnemonic].count > 1 then
|
|
weapon_shape_draw(shpinfo.multiple)
|
|
else
|
|
weapon_shape_draw(shpinfo.single)
|
|
end
|
|
else
|
|
weapon_shape_draw(shpinfo.single)
|
|
end
|
|
|
|
-- name
|
|
weapon_name_draw(wep.name, wep_nrects[wep.type], true)
|
|
|
|
-- ammo
|
|
if wep.primary then
|
|
if wep.primary.bullet_display then
|
|
weapon_bullet_draw(wep.primary)
|
|
elseif wep.primary.energy_display then
|
|
weapon_energy_draw(wep.primary)
|
|
end
|
|
end
|
|
if wep.secondary then
|
|
if wep.secondary.bullet_display then
|
|
weapon_bullet_draw(wep.secondary)
|
|
elseif wep.secondary.energy_display then
|
|
weapon_energy_draw(wep.secondary)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- frame health and O2
|
|
if false then
|
|
local r = rects["shield"]
|
|
local s = rects["oxygen"]
|
|
Screen.fill_rect(r.x - 1, r.y - 1, r.width + 2, 1, InterfaceColors["inventory text"])
|
|
Screen.fill_rect(r.x + r.width + 1, r.y - 1, 1, r.height + s.height + 4, InterfaceColors["inventory text"])
|
|
end
|
|
|
|
-- health
|
|
if true then
|
|
local r = rects["shield"]
|
|
local nrg = globals.player_maximum_suit_energy
|
|
if Player.energy > 2*nrg then
|
|
draw_bar(r, (Player.energy - 2*nrg) / nrg,
|
|
imgs["triple energy bar right"],
|
|
imgs["triple energy bar"],
|
|
imgs["double energy bar"])
|
|
elseif Player.energy > nrg then
|
|
draw_bar(r, (Player.energy - nrg) / nrg,
|
|
imgs["double energy bar right"],
|
|
imgs["double energy bar"],
|
|
imgs["energy bar"])
|
|
else
|
|
draw_bar(r, math.max(Player.energy, 0) / nrg,
|
|
imgs["energy bar right"],
|
|
imgs["energy bar"],
|
|
imgs["empty energy bar"])
|
|
end
|
|
end
|
|
|
|
-- O2
|
|
if true then
|
|
local r = rects["oxygen"]
|
|
-- oxygen
|
|
draw_bar(r, Player.oxygen / globals.player_maximum_suit_oxygen,
|
|
imgs["oxygen bar right"],
|
|
imgs["oxygen bar"],
|
|
imgs["empty oxygen bar"])
|
|
end
|
|
|
|
-- player name
|
|
if #Game.players > 1 then
|
|
local r = rects["player name"]
|
|
|
|
draw_text_center(int_fonts["player name"],
|
|
Player.name,
|
|
r.x + 1, r.y + 1, r.width,
|
|
{ 0, 0, 0, 1})
|
|
draw_text_center(int_fonts["player name"],
|
|
Player.name,
|
|
r.x, r.y, r.width,
|
|
InterfaceColors[Player.color.mnemonic .. " player"])
|
|
end
|
|
|
|
end
|
|
|
|
function Triggers.resize()
|
|
if TexturePalette.resize() then return end
|
|
|
|
Screen.clip_rect.width = Screen.width
|
|
Screen.clip_rect.x = 0
|
|
Screen.clip_rect.height = Screen.height
|
|
Screen.clip_rect.y = 0
|
|
|
|
Screen.map_rect.width = Screen.width
|
|
Screen.map_rect.x = 0
|
|
Screen.map_rect.height = Screen.height
|
|
Screen.map_rect.y = 0
|
|
|
|
-- local min_aspect_ratio = 1.6
|
|
-- local max_aspect_ratio = 2.4
|
|
-- local h = math.min(Screen.height, Screen.width / min_aspect_ratio)
|
|
-- local w = math.min(Screen.width, h*max_aspect_ratio)
|
|
local h = Screen.height
|
|
local w = Screen.width
|
|
Screen.world_rect.width = w
|
|
Screen.world_rect.x = (Screen.width - w)/2
|
|
Screen.world_rect.height = h
|
|
Screen.world_rect.y = (Screen.height - h)/2
|
|
|
|
if Screen.map_overlay_active then
|
|
Screen.map_rect.x = Screen.world_rect.x
|
|
Screen.map_rect.y = Screen.world_rect.y
|
|
Screen.map_rect.width = Screen.world_rect.width
|
|
Screen.map_rect.height = Screen.world_rect.height
|
|
end
|
|
|
|
local ww = Screen.width
|
|
local wh = Screen.height
|
|
|
|
-- calculate HUD area
|
|
hud_rect = {}
|
|
local hudsize = Screen.hud_size_preference
|
|
hud_rect.width = 640
|
|
if hudsize == SizePreferences["double"] then
|
|
if ww >= 2560 then
|
|
hud_rect.width = 1280
|
|
end
|
|
elseif hudsize == SizePreferences["largest"] then
|
|
hud_rect.width = ww / 2
|
|
end
|
|
|
|
hud_rect.height = hud_rect.width / 4
|
|
-- hud_rect.x = math.floor((ww - hud_rect.width) / 2)
|
|
-- hud_rect.y = math.floor(wh - hud_rect.height)
|
|
|
|
hud_rect.scale = hud_rect.width / 640
|
|
|
|
hud_rect.x = ww - hud_rect.width
|
|
hud_rect.y = wh - hud_rect.height
|
|
|
|
-- hud_rect.x = hud_rect.x + hud_rect.width - adj(InterfaceRects["inventory"].width) - adj(InterfaceRects["inventory"].x) - adj(InterfaceRects["weapon display"].width)
|
|
|
|
local iw_right = math.max(InterfaceRects["inventory"].x + InterfaceRects["inventory"].width, InterfaceRects["weapon display"].x + InterfaceRects["weapon display"].width)
|
|
local iw_bottom = math.max(InterfaceRects["inventory"].y - 320 + InterfaceRects["inventory"].height, InterfaceRects["weapon display"].y - 320 + InterfaceRects["weapon display"].height)
|
|
|
|
hud_rect.x = ww - adj(iw_right)
|
|
hud_rect.y = wh - adj(iw_bottom)
|
|
|
|
local sidelen = adj(123)
|
|
|
|
-- calculate terminal area
|
|
local termsize = Screen.term_size_preference
|
|
if termsize == SizePreferences["normal"] then
|
|
Screen.term_rect.width = 640
|
|
elseif termsize == SizePreferences["double"] then
|
|
if (wh - sidelen * 2) >= 640 and ww >= 1280 then
|
|
Screen.term_rect.width = 1280
|
|
end
|
|
elseif termsize == SizePreferences["largest"] then
|
|
Screen.term_rect.width = math.min(ww, math.max(640, 2 * (wh - sidelen * 2)))
|
|
end
|
|
|
|
Screen.term_rect.height = Screen.term_rect.width / 2
|
|
Screen.term_rect.x = math.floor((ww - Screen.term_rect.width) / 2)
|
|
Screen.term_rect.y = math.floor((wh - Screen.term_rect.height) / 2)
|
|
|
|
-- recalculate screen fonts
|
|
for k, v in pairs(int_fonts) do
|
|
v.scale = hud_rect.scale
|
|
end
|
|
|
|
-- recalculate interface rectangles
|
|
rects = {}
|
|
for r in InterfaceRects() do
|
|
rects[r.mnemonic] = adj_rect(r)
|
|
end
|
|
|
|
-- scale images
|
|
for k, v in pairs(imgs) do
|
|
v:rescale(adj(v.unscaled_width), adj(v.unscaled_height))
|
|
end
|
|
|
|
-- scale weapon shapes
|
|
for k, v in pairs(wep_shapes) do
|
|
for kk, vv in pairs(v) do
|
|
if vv.shp then
|
|
vv.shp:rescale(adj(vv.shp.unscaled_width), adj(vv.shp.unscaled_height))
|
|
end
|
|
vv.x = adj_x(vv.orig_x)
|
|
vv.y = adj_y(vv.orig_y)
|
|
end
|
|
end
|
|
|
|
-- scale bullet shapes
|
|
for k, v in pairs(ammo_shapes) do
|
|
v:rescale(adj(v.unscaled_width), adj(v.unscaled_height))
|
|
end
|
|
|
|
-- recalculate weapon name rects
|
|
wep_nrects = {}
|
|
for wt in WeaponTypes() do
|
|
wep_nrects[wt] = adj_rect(Player.weapons[wt].name_rect)
|
|
end
|
|
|
|
-- recalculate globals
|
|
globals = {
|
|
message_area_x_offset = adj(-9),
|
|
message_area_y_offset = adj(-5),
|
|
text_inset = adj(2),
|
|
name_offset = adj(23),
|
|
top_of_bar_width = adj(8),
|
|
motion_sensor_side_length = adj(123),
|
|
motion_sensor_scale = adj(64),
|
|
network_compass_36 = adj(36),
|
|
network_compass_61 = adj(61),
|
|
player_maximum_suit_energy = 150,
|
|
player_maximum_suit_oxygen = 6*30*60,
|
|
motion_sensor_range = 8
|
|
}
|
|
|
|
-- move the motion sensor and health to the bottom left
|
|
rects["motion sensor"].x = Screen.world_rect.x
|
|
rects["motion sensor"].y = Screen.world_rect.y + Screen.world_rect.height - globals.motion_sensor_side_length
|
|
|
|
rects["shield"].x = Screen.world_rect.x + globals.motion_sensor_side_length + 5
|
|
rects["shield"].y = Screen.world_rect.y + Screen.world_rect.height - rects["shield"].height - rects["oxygen"].height - 3
|
|
|
|
rects["oxygen"].x = Screen.world_rect.x + globals.motion_sensor_side_length + 5
|
|
rects["oxygen"].y = Screen.world_rect.y + Screen.world_rect.height - rects["oxygen"].height - 1
|
|
|
|
Screen.text_margins.bottom = globals.motion_sensor_side_length + 1;
|
|
|
|
end
|
|
|
|
function Triggers.init()
|
|
if not (WeaponTypes["fist"] == nil) then WeaponTypes["fist"].mnemonic = "knife" end
|
|
|
|
int_fonts = {}
|
|
for ftype in InterfaceFonts() do
|
|
int_fonts[ftype.mnemonic] = Fonts.new{ interface = ftype }
|
|
end
|
|
|
|
imgs = {}
|
|
imgs["motion sensor mask"] = Images.new { path = "resources/motion_sensor_mask.png" }
|
|
imgs["interface panel"] = Images.new{ resource = 1700 }
|
|
|
|
for idx, name in ipairs({
|
|
"empty energy bar",
|
|
"energy bar",
|
|
"energy bar right",
|
|
"double energy bar",
|
|
"double energy bar right",
|
|
"triple energy bar",
|
|
"triple energy bar right",
|
|
"empty oxygen bar",
|
|
"oxygen bar",
|
|
"oxygen bar right",
|
|
"motion sensor mount",
|
|
"motion sensor virgin mount",
|
|
"motion sensor alien 0",
|
|
"motion sensor alien 1",
|
|
"motion sensor alien 2",
|
|
"motion sensor alien 3",
|
|
"motion sensor alien 4",
|
|
"motion sensor alien 5",
|
|
"motion sensor friend 0",
|
|
"motion sensor friend 1",
|
|
"motion sensor friend 2",
|
|
"motion sensor friend 3",
|
|
"motion sensor friend 4",
|
|
"motion sensor friend 5",
|
|
"motion sensor hostile player 0",
|
|
"motion sensor hostile player 1",
|
|
"motion sensor hostile player 2",
|
|
"motion sensor hostile player 3",
|
|
"motion sensor hostile player 4",
|
|
"motion sensor hostile player 5",
|
|
"network panel" }) do
|
|
imgs[name] = Shapes.new{ collection = 0, texture_index = idx - 1, type = TextureTypes["interface"] }
|
|
end
|
|
|
|
for idx, name in ipairs({
|
|
"network compass nw",
|
|
"network compass ne",
|
|
"network compass sw",
|
|
"network compass se" }) do
|
|
imgs[name] = Shapes.new{ collection = 0, texture_index = idx + 50, type = TextureTypes["interface"] }
|
|
end
|
|
|
|
wep_shapes = {}
|
|
ammo_shapes = {}
|
|
for wt in WeaponTypes() do
|
|
local wep = Player.weapons[wt]
|
|
wep_shapes[wt] = {}
|
|
if wep.shape then
|
|
local s = wep.shape
|
|
wep_shapes[wt].single = {
|
|
shp = Shapes.new{ collection = 0, type = TextureTypes["interface"],
|
|
texture_index = s.texture_index },
|
|
orig_x = s.x,
|
|
orig_y = s.y }
|
|
end
|
|
if wep.multiple_shape then
|
|
local s = wep.multiple_shape
|
|
wep_shapes[wt].multiple = {
|
|
shp = Shapes.new{ collection = 0, type = TextureTypes["interface"],
|
|
texture_index = s.texture_index },
|
|
orig_x = s.x,
|
|
orig_y = s.y }
|
|
end
|
|
if wep.multiple_unusable_shape then
|
|
local s = wep.multiple_unusable_shape
|
|
wep_shapes[wt].unusable = {
|
|
shp = Shapes.new{ collection = 0, type = TextureTypes["interface"],
|
|
texture_index = s.texture_index },
|
|
orig_x = s.x,
|
|
orig_y = s.y }
|
|
end
|
|
|
|
if wep.primary and wep.primary.bullet_display then
|
|
local disp = wep.primary.bullet_display
|
|
if not ammo_shapes[disp.texture_index] then
|
|
ammo_shapes[disp.texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.texture_index }
|
|
end
|
|
if not ammo_shapes[disp.empty_texture_index] then
|
|
ammo_shapes[disp.empty_texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.empty_texture_index }
|
|
end
|
|
end
|
|
if wep.secondary and wep.secondary.bullet_display then
|
|
local disp = wep.secondary.bullet_display
|
|
if disp.texture_index then
|
|
if not ammo_shapes[disp.texture_index] then
|
|
ammo_shapes[disp.texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.texture_index }
|
|
end
|
|
end
|
|
if disp.empty_texture_index then
|
|
if not ammo_shapes[disp.empty_texture_index] then
|
|
ammo_shapes[disp.empty_texture_index] = Shapes.new{ collection = 0, type = TextureTypes["interface"], texture_index = disp.empty_texture_index }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Triggers.resize()
|
|
end
|
|
|
|
function adj(len)
|
|
return len * hud_rect.scale
|
|
end
|
|
function adj_x(x)
|
|
return hud_rect.x + adj(x)
|
|
end
|
|
function adj_y(y)
|
|
return hud_rect.y + adj(y - 320)
|
|
end
|
|
function adj_rect(r)
|
|
return { x = adj_x(r.x),
|
|
y = adj_y(r.y),
|
|
width = adj(r.width),
|
|
height = adj(r.height) }
|
|
end
|
|
|
|
function draw_bar(r, frac, cap, full, empty)
|
|
empty.crop_rect.width = empty.width
|
|
empty:draw(r.x, r.y)
|
|
|
|
local width = r.width * frac
|
|
local capw = globals.top_of_bar_width
|
|
|
|
if width > 2 * capw then
|
|
cap.crop_rect.width = cap.width
|
|
cap.crop_rect.x = 0
|
|
cap:draw(r.x + width - capw, r.y)
|
|
|
|
full.crop_rect.width = width - capw
|
|
full:draw(r.x, r.y)
|
|
else
|
|
cap.crop_rect.width = width/2
|
|
cap.crop_rect.x = capw - width/2
|
|
cap:draw(r.x + width/2, r.y)
|
|
|
|
full.crop_rect.width = width/2
|
|
full:draw(r.x, r.y)
|
|
end
|
|
end
|
|
|
|
function trunc_text(font, text, w)
|
|
local tw, th = font:measure_text(text)
|
|
local trunc = false
|
|
while tw > w do
|
|
text = string.sub(text, 1, -2)
|
|
tw, th = font:measure_text(text .. string.char(201))
|
|
trunc = true
|
|
end
|
|
if trunc then text = text .. string.char(201) end
|
|
return text, tw
|
|
end
|
|
|
|
function draw_text_trunc(font, text, x, y, w, color)
|
|
local tt, tw = trunc_text(font, text, w)
|
|
font:draw_text(tt, x, y, color)
|
|
end
|
|
|
|
function draw_text_center(font, text, x, y, w, color)
|
|
local tt, tw = trunc_text(font, text, w)
|
|
font:draw_text(tt, x + sfloor((w - tw)/2), y, color)
|
|
end
|
|
|
|
function draw_text_right(font, text, x, y, color)
|
|
local tw, th = font:measure_text(text)
|
|
font:draw_text(text, x - tw, y, color)
|
|
end
|
|
|
|
function clip(x, y, w, h)
|
|
local rect = Screen.clip_rect
|
|
rect.x = x
|
|
rect.y = y
|
|
rect.width = w
|
|
rect.height = h
|
|
end
|
|
|
|
function cliprect(r)
|
|
local rect = Screen.clip_rect
|
|
rect.x = r.x
|
|
rect.y = r.y
|
|
rect.width = r.width
|
|
rect.height = r.height
|
|
end
|
|
|
|
function unclip()
|
|
local rect = Screen.clip_rect
|
|
rect.x = 0
|
|
rect.y = 0
|
|
rect.width = Screen.width
|
|
rect.height = Screen.height
|
|
end
|
|
|
|
function clip_motion_sensor(x, y, w, h)
|
|
if Screen.renderer == "software" then
|
|
clip(x, y, w, h)
|
|
else
|
|
unclip()
|
|
Screen.clear_mask()
|
|
Screen.masking_mode = MaskingModes["drawing"]
|
|
imgs["motion sensor mask"]:draw(x, y)
|
|
Screen.masking_mode = MaskingModes["enabled"]
|
|
end
|
|
end
|
|
|
|
function unclip_motion_sensor()
|
|
if Screen.renderer == "software" then
|
|
unclip()
|
|
else
|
|
Screen.masking_mode = MaskingModes["disabled"]
|
|
end
|
|
end
|
|
|
|
function sfloor(num)
|
|
return num - (num % hud_rect.scale)
|
|
end
|
|
|
|
function format_time(ticks)
|
|
local secs = math.floor(ticks / 30)
|
|
return string.format("%d:%02d", math.floor(secs / 60), secs % 60)
|
|
end
|
|
|
|
function player_ranking_text(gametype, ranking)
|
|
if gametype == "kill monsters" or
|
|
gametype == "capture the flag" or
|
|
gametype == "rugby" or
|
|
gametype == "most points" then
|
|
return string.format("%d", ranking)
|
|
elseif gametype == "least points" then
|
|
return string.format("%d", -ranking)
|
|
elseif gametype == "cooperative play" then
|
|
return string.format("%d%%", ranking)
|
|
elseif gametype == "most time" or
|
|
gametype == "least time" or
|
|
gametype == "king of the hill" or
|
|
gametype == "kill the man with the ball" or
|
|
gametype == "defense" or
|
|
gametype == "tag" then
|
|
return format_time(math.abs(ranking))
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function sorted_players()
|
|
local sort_tbl = {}
|
|
for i = 1,#Game.players do
|
|
table.insert(sort_tbl, { rank = Game.players[i - 1].ranking, idx = i - 1 })
|
|
end
|
|
local sortfunc = function(a, b)
|
|
if a.rank ~= b.rank then return a.rank > b.rank end
|
|
return a.idx < b.idx
|
|
end
|
|
table.sort(sort_tbl, sortfunc)
|
|
|
|
local splayers = {}
|
|
for i = 1,#sort_tbl do
|
|
table.insert(splayers, Game.players[sort_tbl[i].idx])
|
|
end
|
|
return splayers
|
|
end
|
|
|
|
function inventory_item_draw(item, y)
|
|
local r = rects["inventory"]
|
|
local clr = InterfaceColors["inventory text"]
|
|
if not item.valid then clr = InterfaceColors["invalid weapon"] end
|
|
|
|
local iname = item.plural
|
|
if item.count == 1 then iname = item.singular end
|
|
draw_text_trunc(
|
|
int_fonts["interface"],
|
|
iname,
|
|
r.x + globals.name_offset + globals.text_inset,
|
|
y,
|
|
r.width - globals.name_offset - globals.text_inset,
|
|
clr)
|
|
|
|
draw_text_trunc(
|
|
int_fonts["interface item count"],
|
|
string.format("%3d", item.count),
|
|
r.x + globals.text_inset,
|
|
y,
|
|
globals.name_offset + globals.text_inset,
|
|
clr)
|
|
end
|
|
|
|
function inventory_items_draw()
|
|
local r = rects["inventory"]
|
|
local rowh = int_fonts["interface"].line_height
|
|
local maxrows = r.height / rowh
|
|
local currow = 1
|
|
local section = Player.inventory_sections.current.type
|
|
|
|
for itype in ItemTypes() do
|
|
if currow < maxrows and itype ~= ItemTypes["knife"] then
|
|
local item = Player.items[itype]
|
|
if item.inventory_section == section and item.count > 0 then
|
|
inventory_item_draw(item, r.y + (currow * rowh))
|
|
currow = currow + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function inventory_right_draw(text, currow)
|
|
local r = rects["inventory"]
|
|
local f = int_fonts["interface"]
|
|
draw_text_right(f, text, r.x + r.width - globals.text_inset, r.y + (currow * f.line_height), InterfaceColors["inventory text"])
|
|
end
|
|
|
|
function inventory_right_draw(text, currow)
|
|
local r = rects["inventory"]
|
|
local f = int_fonts["interface"]
|
|
draw_text_right(f, text, r.x + r.width - globals.text_inset, r.y + (currow * f.line_height), InterfaceColors["inventory text"])
|
|
end
|
|
|
|
function network_stats_draw()
|
|
local r = { xl = rects["inventory"].x + globals.text_inset,
|
|
xr = rects["inventory"].x + rects["inventory"].width - globals.text_inset,
|
|
y = rects["inventory"].y,
|
|
width = rects["inventory"].width - (2*globals.text_inset) }
|
|
local f = int_fonts["interface"]
|
|
local rowh = f.line_height
|
|
|
|
-- time/score display in header
|
|
if Game.time_remaining and Game.time_remaining <= 30*60*999 then
|
|
draw_text_right(f, format_time(Game.time_remaining),
|
|
r.xr, r.y, InterfaceColors["inventory text"])
|
|
|
|
elseif Game.kill_limit then
|
|
local lim = Game.kill_limit
|
|
local gt = Game.type.mnemonic
|
|
if gt == "kill monsters" or
|
|
gt == "cooperative play" or
|
|
gt == "king of the hill" or
|
|
gt == "kill the man with the ball" or
|
|
gt == "tag" then
|
|
local leastleft = nil
|
|
for p = 1,#Game.players do
|
|
local thisleft = lim - Game.players[p - 1].kills
|
|
if (not leastleft) or thisleft < leastleft then
|
|
leastleft = thisleft
|
|
end
|
|
end
|
|
|
|
draw_text_right(f, string.format("%d", leastleft),
|
|
r.xr, r.y, InterfaceColors["inventory text"])
|
|
end
|
|
end
|
|
|
|
-- player listing
|
|
for idx, p in ipairs(sorted_players()) do
|
|
r.y = r.y + rowh
|
|
local clr = InterfaceColors[p.color.mnemonic .. " player"]
|
|
|
|
draw_text_trunc(f, p.name, r.xl, r.y, r.width, clr)
|
|
|
|
draw_text_right(f, player_ranking_text(Game.type, p.ranking),
|
|
r.xr, r.y, clr)
|
|
end
|
|
end
|
|
|
|
function weapon_name_draw(txt, nr, vertical)
|
|
local f = int_fonts["weapon name"]
|
|
local fh = f.line_height
|
|
local w, h = f:measure_text(txt)
|
|
|
|
local draw_single = function(singleline, vert)
|
|
local y = nr.y
|
|
if vert then
|
|
if fh > nr.height then
|
|
y = nr.y - fh + adj(2)
|
|
else
|
|
local off = nr.height - fh
|
|
y = nr.y + nr.height - fh - sfloor(off/2) - adj(1)
|
|
end
|
|
else
|
|
if fh > nr.height then
|
|
y = nr.y + nr.height - fh
|
|
else
|
|
y = nr.y
|
|
end
|
|
end
|
|
draw_text_center(f, singleline, nr.x, y, nr.width, InterfaceColors["inventory text"])
|
|
end
|
|
|
|
-- will we fit on one line?
|
|
if w <= nr.width then
|
|
draw_single(txt, vertical)
|
|
return
|
|
end
|
|
|
|
-- no more words?
|
|
local spos, epos = string.find(txt, " ")
|
|
if not spos then
|
|
draw_single(txt, vertical)
|
|
return
|
|
end
|
|
|
|
-- if we get here, we need to split
|
|
local lineend = spos
|
|
w, h = f:measure_text(string.sub(txt, 1, spos - 1))
|
|
while w < nr.width do
|
|
spos, epos = string.find(txt, " ", lineend + 1)
|
|
if not spos then
|
|
w = nr.width
|
|
else
|
|
w, h = f:measure_text(string.sub(txt, 1, spos - 1))
|
|
if w < nr.width then lineend = spos end
|
|
end
|
|
end
|
|
|
|
draw_single(string.sub(txt, 1, lineend - 1), false)
|
|
weapon_name_draw(string.sub(txt, lineend + 1, -1), { x = nr.x, width = nr.width, y = nr.y + f.line_height, height = nr.height - f.line_height }, false)
|
|
end
|
|
|
|
function weapon_shape_draw(shpinfo)
|
|
if shpinfo and shpinfo.shp then
|
|
shpinfo.shp:draw(shpinfo.x, shpinfo.y)
|
|
end
|
|
end
|
|
|
|
function weapon_bullet_draw(trigger)
|
|
local disp = trigger.bullet_display
|
|
local rounds = trigger.rounds
|
|
if rounds < 0 then return end
|
|
local max = disp.across * disp.down
|
|
if rounds > max then rounds = max end
|
|
local dr = adj_rect(disp)
|
|
|
|
local full = ammo_shapes[disp.texture_index]
|
|
if not full then return end
|
|
local empty = ammo_shapes[disp.empty_texture_index]
|
|
if not empty then return end
|
|
|
|
local row = 0
|
|
full.crop_rect.x = 0
|
|
full.crop_rect.width = full.width
|
|
while row < math.floor(rounds / disp.across) do
|
|
full:draw(dr.x, dr.y)
|
|
dr.y = dr.y + dr.height
|
|
row = row + 1
|
|
end
|
|
|
|
local partial = rounds % disp.across
|
|
if partial > 0 then
|
|
full.crop_rect.width = partial * dr.width
|
|
empty.crop_rect.width = (disp.across - partial) * dr.width
|
|
if disp.right_to_left then
|
|
full.crop_rect.x = 0
|
|
full:draw(dr.x, dr.y)
|
|
empty.crop_rect.x = full.crop_rect.width
|
|
empty:draw(dr.x + empty.crop_rect.x, dr.y)
|
|
else
|
|
empty.crop_rect.x = 0
|
|
empty:draw(dr.x, dr.y)
|
|
full.crop_rect.x = empty.crop_rect.width
|
|
full:draw(dr.x + full.crop_rect.x, dr.y)
|
|
end
|
|
dr.y = dr.y + dr.height
|
|
end
|
|
|
|
row = 0
|
|
empty.crop_rect.x = 0
|
|
empty.crop_rect.width = empty.width
|
|
while row < math.floor((max - rounds) / disp.across) do
|
|
empty:draw(dr.x, dr.y)
|
|
dr.y = dr.y + dr.height
|
|
row = row + 1
|
|
end
|
|
end
|
|
|
|
function weapon_energy_draw(trigger)
|
|
local disp = trigger.energy_display
|
|
local rounds = trigger.rounds
|
|
if rounds < 0 then return end
|
|
if rounds > disp.maximum then rounds = disp.maximum end
|
|
|
|
local dr = adj_rect(disp)
|
|
Screen.fill_rect(dr.x, dr.y, dr.width, dr.height, disp.color)
|
|
dr.x = dr.x + adj(1)
|
|
dr.y = dr.y + adj(1)
|
|
dr.width = dr.width - adj(2)
|
|
dr.height = dr.height - adj(2)
|
|
|
|
local fill_height = sfloor((rounds * dr.height) / disp.maximum)
|
|
Screen.fill_rect(dr.x, dr.y, dr.width, dr.height - fill_height, disp.empty_color)
|
|
end
|
|
|
|
|
|
-- BEGIN texture palette utility
|
|
--
|
|
-- Use: in Triggers.draw: "if TexturePalette.draw() then return end"
|
|
-- in Triggers.resize: "if TexturePalette.resize() then return end"
|
|
|
|
TexturePalette = {}
|
|
TexturePalette.active = false
|
|
|
|
function TexturePalette.check_active()
|
|
local old_active = TexturePalette.active
|
|
local new_active = false
|
|
if Player.texture_palette.size > 0 then new_active = true end
|
|
TexturePalette.active = new_active
|
|
|
|
if old_active and not new_active then
|
|
Screen.crosshairs.lua_hud = TexturePalette.saved_crosshairs_lua_hud
|
|
Triggers.resize()
|
|
elseif new_active and not old_active then
|
|
TexturePalette.palette_cache = {}
|
|
TexturePalette.saved_crosshairs_lua_hud = Screen.crosshairs.lua_hud
|
|
Screen.crosshairs.lua_hud = false
|
|
TexturePalette.resize()
|
|
end
|
|
return TexturePalette.active
|
|
end
|
|
|
|
function TexturePalette.get_shape(slot)
|
|
local key = string.format("%d %d", slot.collection, slot.texture_index)
|
|
local shp = TexturePalette.palette_cache[key]
|
|
if not shp then
|
|
shp = Shapes.new{collection = slot.collection, texture_index = slot.texture_index, type = slot.type}
|
|
TexturePalette.palette_cache[key] = shp
|
|
end
|
|
return shp
|
|
end
|
|
|
|
function TexturePalette.draw_shape(slot, x, y, size)
|
|
local shp = TexturePalette.get_shape(slot)
|
|
if not shp then return end
|
|
if shp.width > shp.height then
|
|
shp:rescale(size, shp.unscaled_height * size / shp.unscaled_width)
|
|
shp:draw(x, y + (size - shp.height)/2)
|
|
else
|
|
shp:rescale(shp.unscaled_width * size / shp.unscaled_height, size)
|
|
shp:draw(x + (size - shp.width)/2, y)
|
|
end
|
|
end
|
|
|
|
function TexturePalette.draw(hr)
|
|
if not TexturePalette.check_active() then return false end
|
|
|
|
local hr = TexturePalette.hud_rect
|
|
local tcount = Player.texture_palette.size
|
|
local size
|
|
if tcount <= 5 then size = 128
|
|
elseif tcount <= 16 then size = 80
|
|
elseif tcount <= 36 then size = 53
|
|
elseif tcount <= 64 then size = 40
|
|
elseif tcount <= 100 then size = 32
|
|
elseif tcount <= 144 then size = 26
|
|
else size = 20
|
|
end
|
|
size = size * hr.scale
|
|
|
|
local rows = math.floor(hr.height/size)
|
|
local cols = math.floor(hr.width/size)
|
|
local x_offset = hr.x + (hr.width - cols * size)/2
|
|
local y_offset = hr.y + (hr.height - rows * size)/2
|
|
|
|
for i = 0,tcount - 1 do
|
|
TexturePalette.draw_shape(
|
|
Player.texture_palette.slots[i],
|
|
(i % cols) * size + x_offset + hr.scale/2,
|
|
math.floor(i / cols) * size + y_offset + hr.scale/2,
|
|
size - hr.scale)
|
|
end
|
|
|
|
if Player.texture_palette.highlight then
|
|
local i = Player.texture_palette.highlight
|
|
Screen.frame_rect(
|
|
(i % cols) * size + x_offset,
|
|
math.floor(i / cols) * size + y_offset,
|
|
size, size,
|
|
InterfaceColors["inventory text"],
|
|
hr.scale)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function TexturePalette.resize()
|
|
if not TexturePalette.check_active() then return false end
|
|
|
|
local ww = Screen.width
|
|
local wh = Screen.height
|
|
|
|
-- calculate HUD area
|
|
TexturePalette.hud_rect = {}
|
|
local hudsize = Screen.hud_size_preference
|
|
TexturePalette.hud_rect.width = 640
|
|
if hudsize == SizePreferences["double"] then
|
|
if wh >= 960 and ww >= 1280 then
|
|
TexturePalette.hud_rect.width = 1280
|
|
end
|
|
elseif hudsize == SizePreferences["largest"] then
|
|
TexturePalette.hud_rect.width = math.min(ww, math.max(640, (4 * wh) / 3));
|
|
end
|
|
|
|
TexturePalette.hud_rect.height = TexturePalette.hud_rect.width / 4
|
|
TexturePalette.hud_rect.x = math.floor((ww - TexturePalette.hud_rect.width) / 2)
|
|
TexturePalette.hud_rect.y = math.floor(wh - TexturePalette.hud_rect.height)
|
|
|
|
TexturePalette.hud_rect.scale = TexturePalette.hud_rect.width / 640
|
|
|
|
-- remove HUD height from rest of calculations
|
|
wh = TexturePalette.hud_rect.y
|
|
|
|
-- calculate terminal area
|
|
local termsize = Screen.term_size_preference
|
|
Screen.term_rect.width = 640
|
|
if termsize == SizePreferences["double"] then
|
|
if wh >= 640 and ww >= 1280 then
|
|
Screen.term_rect.width = 1280
|
|
end
|
|
elseif termsize == SizePreferences["largest"] then
|
|
Screen.term_rect.width = math.min(ww, math.max(640, 2 * wh))
|
|
end
|
|
|
|
Screen.term_rect.height = Screen.term_rect.width / 2
|
|
Screen.term_rect.x = math.floor((ww - Screen.term_rect.width) / 2)
|
|
Screen.term_rect.y = math.floor((wh - Screen.term_rect.height) / 2)
|
|
|
|
-- calculate world-view area
|
|
Screen.world_rect.width = math.min(ww, math.max(640, 2 * wh))
|
|
Screen.world_rect.height = Screen.world_rect.width / 2
|
|
Screen.world_rect.x = math.floor((ww - Screen.world_rect.width) / 2)
|
|
Screen.world_rect.y = math.floor((wh - Screen.world_rect.height) / 2)
|
|
|
|
-- calculate map area
|
|
if Screen.map_overlay_active then
|
|
-- overlay just matches world-view
|
|
Screen.map_rect.width = Screen.world_rect.width
|
|
Screen.map_rect.height = Screen.world_rect.height
|
|
Screen.map_rect.x = Screen.world_rect.x
|
|
Screen.map_rect.y = Screen.world_rect.y
|
|
else
|
|
Screen.map_rect.width = ww
|
|
Screen.map_rect.height = wh
|
|
Screen.map_rect.x = 0
|
|
Screen.map_rect.y = 0
|
|
end
|
|
|
|
Screen.clip_rect.width = Screen.width
|
|
Screen.clip_rect.height = Screen.height
|
|
Screen.clip_rect.x = 0
|
|
Screen.clip_rect.y = 0
|
|
|
|
return true
|
|
end
|
|
|
|
-- END texture palette utility
|