Feature Complete Shipping V1.0
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
@@ -4,6 +4,7 @@ require "ISUI/ISButton"
|
||||
require "Vehicles/TimedActions/ISPathFindAction"
|
||||
require "PaintMyKI5/PaintRequirements"
|
||||
require "PaintMyKI5/PaintInventory"
|
||||
require "PaintMyKI5/TextureName"
|
||||
require "PaintMyKI5/TimedActions/ISPaintMyKI5Vehicle"
|
||||
|
||||
ISPaintMyKI5UI = ISCollapsableWindow:derive("ISPaintMyKI5UI")
|
||||
@@ -14,9 +15,9 @@ local FONT_MEDIUM = UIFont.Medium
|
||||
local SMALL_HEIGHT = getTextManager():getFontHeight(FONT_SMALL)
|
||||
local MEDIUM_HEIGHT = getTextManager():getFontHeight(FONT_MEDIUM)
|
||||
|
||||
local function textureLabel(textureData)
|
||||
local name = string.match(textureData.texture or "", "([^/]+)$") or ""
|
||||
return getText("IGUI_PaintMyKI5_Skin", textureData.skinIndex + 1) .. " - " .. name
|
||||
local function textureLabel(textureData, displayName)
|
||||
return getText("IGUI_PaintMyKI5_Skin", textureData.skinIndex + 1)
|
||||
.. " - " .. displayName
|
||||
end
|
||||
|
||||
local function getPaletteColor(itemType)
|
||||
@@ -28,6 +29,24 @@ local function getPaletteColor(itemType)
|
||||
return 0.5, 0.5, 0.5
|
||||
end
|
||||
|
||||
local function buildMissingTooltip(missingPaint, missingTools)
|
||||
local lines = { getText("IGUI_PaintMyKI5_MissingRequirements") }
|
||||
for _, missing in ipairs(missingTools or {}) do
|
||||
table.insert(lines, getText(
|
||||
"IGUI_PaintMyKI5_MissingTool",
|
||||
getItemNameFromFullType(missing.item)
|
||||
))
|
||||
end
|
||||
for _, missing in ipairs(missingPaint or {}) do
|
||||
local available = math.floor(missing.available * 100 + 0.5) / 100
|
||||
table.insert(lines, getText(
|
||||
"IGUI_PaintMyKI5_MissingPaint",
|
||||
getItemNameFromFullType(missing.item), missing.required, available
|
||||
))
|
||||
end
|
||||
return table.concat(lines, "\n")
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI.drawSkinItem(list, y, item, alt)
|
||||
if item.itemindex == list.selected then
|
||||
list:drawRect(0, y, list:getWidth(), item.height, 0.25, 0.3, 0.7, 1.0)
|
||||
@@ -49,8 +68,10 @@ function ISPaintMyKI5UI:createChildren()
|
||||
self.skinList.drawBorder = true
|
||||
self:addChild(self.skinList)
|
||||
|
||||
for _, textureData in ipairs(self.vehicleData.textures or {}) do
|
||||
self.skinList:addItem(textureLabel(textureData), textureData)
|
||||
local textures = self.vehicleData.textures or {}
|
||||
local textureNames = PaintMyKI5.TextureName.buildLabels(textures)
|
||||
for index, textureData in ipairs(textures) do
|
||||
self.skinList:addItem(textureLabel(textureData, textureNames[index]), textureData)
|
||||
end
|
||||
local currentIndex = self.vehicle:getSkinIndex()
|
||||
for index, row in ipairs(self.skinList.items) do
|
||||
@@ -84,6 +105,8 @@ function ISPaintMyKI5UI:prerender()
|
||||
ISCollapsableWindow.prerender(self)
|
||||
local textureData = self:getSelectedTexture()
|
||||
local enabled = false
|
||||
local missingPaint = {}
|
||||
local missingTools = {}
|
||||
if textureData then
|
||||
local area = PaintMyKI5.PaintRequirements.findInteractionArea(
|
||||
self.vehicle, self.character
|
||||
@@ -91,13 +114,26 @@ function ISPaintMyKI5UI:prerender()
|
||||
local requirements = PaintMyKI5.PaintRequirements.getRequirements(
|
||||
self.vehicle, textureData.skinIndex
|
||||
)
|
||||
enabled = requirements ~= nil
|
||||
and PaintMyKI5.PaintRequirements.isValidTarget(
|
||||
self.character, self.vehicle, textureData.skinIndex, area
|
||||
local ready = false
|
||||
if requirements then
|
||||
ready, missingPaint, missingTools =
|
||||
PaintMyKI5.PaintInventory.checkPaintingRequirements(
|
||||
self.character, requirements
|
||||
)
|
||||
end
|
||||
enabled = ready and area ~= nil
|
||||
and PaintMyKI5.PaintRequirements.isValidSelection(
|
||||
self.character, self.vehicle, textureData.skinIndex
|
||||
)
|
||||
and PaintMyKI5.PaintInventory.checkRequirements(self.character, requirements)
|
||||
end
|
||||
self.paintButton:setEnable(enabled)
|
||||
if enabled then
|
||||
self.paintButton:setTooltip(nil)
|
||||
elseif #missingPaint > 0 or #missingTools > 0 then
|
||||
self.paintButton:setTooltip(buildMissingTooltip(missingPaint, missingTools))
|
||||
else
|
||||
self.paintButton:setTooltip(getText("IGUI_PaintMyKI5_Unavailable"))
|
||||
end
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:render()
|
||||
@@ -162,12 +198,14 @@ function ISPaintMyKI5UI:onPaint()
|
||||
self.vehicle, textureData.skinIndex
|
||||
)
|
||||
if not requirements then return end
|
||||
local enough = PaintMyKI5.PaintInventory.checkRequirements(self.character, requirements)
|
||||
local enough = PaintMyKI5.PaintInventory.checkPaintingRequirements(
|
||||
self.character, requirements
|
||||
)
|
||||
if not enough then return end
|
||||
local area = PaintMyKI5.PaintRequirements.findInteractionArea(self.vehicle, self.character)
|
||||
if not area then return end
|
||||
if not PaintMyKI5.PaintRequirements.isValidTarget(
|
||||
self.character, self.vehicle, textureData.skinIndex, area
|
||||
if not PaintMyKI5.PaintRequirements.isValidSelection(
|
||||
self.character, self.vehicle, textureData.skinIndex
|
||||
) then return end
|
||||
|
||||
ISTimedActionQueue.add(ISPathFindAction:pathToVehicleArea(self.character, self.vehicle, area))
|
||||
|
||||
@@ -38,7 +38,7 @@ function PaintVehicleContextMenu.onFillWorldObjectContextMenu(player, context, w
|
||||
PaintVehicleContextMenu.open,
|
||||
vehicle
|
||||
)
|
||||
option.iconTexture = getTexture("media/textures/PaintBrush.png")
|
||||
option.iconTexture = getTexture("media/textures/PaintMyKI5_ContextMenu.png")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
PaintMyKI5 = PaintMyKI5 or {}
|
||||
PaintMyKI5.SandpaperDistribution = PaintMyKI5.SandpaperDistribution or {}
|
||||
|
||||
local SandpaperDistribution = PaintMyKI5.SandpaperDistribution
|
||||
local SANDPAPER_ITEM = "PaintMyKI5.Sandpaper"
|
||||
local SANDPAPER_WEIGHT = 0.1
|
||||
local FULL_PAINT_CANS = {
|
||||
PaintBlack = true,
|
||||
PaintBlue = true,
|
||||
PaintBrown = true,
|
||||
PaintCyan = true,
|
||||
PaintGreen = true,
|
||||
PaintGrey = true,
|
||||
PaintLightBlue = true,
|
||||
PaintLightBrown = true,
|
||||
PaintOrange = true,
|
||||
PaintPink = true,
|
||||
PaintPurple = true,
|
||||
PaintRed = true,
|
||||
PaintTurquoise = true,
|
||||
PaintWhite = true,
|
||||
PaintYellow = true,
|
||||
}
|
||||
|
||||
local function isFullPaintCan(itemType)
|
||||
if type(itemType) ~= "string" then return false end
|
||||
if FULL_PAINT_CANS[itemType] then return true end
|
||||
local moduleName, shortType = string.match(itemType, "^([^.]+)%.([^.]+)$")
|
||||
return moduleName == "Base" and FULL_PAINT_CANS[shortType] == true
|
||||
end
|
||||
|
||||
local function inspectItems(items)
|
||||
local hasPaint = false
|
||||
local hasSandpaper = false
|
||||
if type(items) ~= "table" then return hasPaint, hasSandpaper end
|
||||
|
||||
for index = 1, #items, 2 do
|
||||
local itemType = items[index]
|
||||
if itemType == SANDPAPER_ITEM then
|
||||
hasSandpaper = true
|
||||
elseif isFullPaintCan(itemType) then
|
||||
hasPaint = true
|
||||
end
|
||||
end
|
||||
return hasPaint, hasSandpaper
|
||||
end
|
||||
|
||||
local function injectIntoItems(items)
|
||||
local hasPaint, hasSandpaper = inspectItems(items)
|
||||
if not hasPaint or hasSandpaper then return 0 end
|
||||
table.insert(items, SANDPAPER_ITEM)
|
||||
table.insert(items, SANDPAPER_WEIGHT)
|
||||
return 1
|
||||
end
|
||||
|
||||
function SandpaperDistribution.inject(distributions, clutterTables)
|
||||
local list = distributions and distributions.list
|
||||
local added = 0
|
||||
if type(list) == "table" then
|
||||
for _, distribution in pairs(list) do
|
||||
if type(distribution) == "table" then
|
||||
added = added + injectIntoItems(distribution.items)
|
||||
if type(distribution.junk) == "table" then
|
||||
added = added + injectIntoItems(distribution.junk.items)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if type(clutterTables) == "table" then
|
||||
added = added + injectIntoItems(clutterTables.ClosetItems)
|
||||
end
|
||||
return added
|
||||
end
|
||||
|
||||
SandpaperDistribution.inject(ProceduralDistributions, ClutterTables)
|
||||
@@ -4,6 +4,16 @@ PaintMyKI5.PaintInventory = PaintMyKI5.PaintInventory or {}
|
||||
local PaintInventory = PaintMyKI5.PaintInventory
|
||||
local EPSILON = 0.0001
|
||||
local EMPTY_BUCKET = "Base.PaintbucketEmpty"
|
||||
local TOOL_REQUIREMENTS = {
|
||||
{
|
||||
item = "PaintMyKI5.Sandpaper",
|
||||
alternatives = { "PaintMyKI5.Sandpaper" },
|
||||
},
|
||||
{
|
||||
item = "Base.Paintbrush",
|
||||
alternatives = { "Base.Paintbrush", "Base.PaintbrushCrafted" },
|
||||
},
|
||||
}
|
||||
|
||||
local function getItems(character, itemType)
|
||||
if not character or not character:getInventory() then return nil end
|
||||
@@ -41,6 +51,27 @@ function PaintInventory.checkRequirements(character, requirements)
|
||||
return #missing == 0, missing
|
||||
end
|
||||
|
||||
local function hasAnyItem(character, itemTypes)
|
||||
for _, itemType in ipairs(itemTypes) do
|
||||
local items = getItems(character, itemType)
|
||||
if items and items:size() > 0 then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function PaintInventory.checkPaintingRequirements(character, requirements)
|
||||
local hasPaint, missingPaint = PaintInventory.checkRequirements(
|
||||
character, requirements
|
||||
)
|
||||
local missingTools = {}
|
||||
for _, tool in ipairs(TOOL_REQUIREMENTS) do
|
||||
if not hasAnyItem(character, tool.alternatives) then
|
||||
table.insert(missingTools, { item = tool.item })
|
||||
end
|
||||
end
|
||||
return hasPaint and #missingTools == 0, missingPaint, missingTools
|
||||
end
|
||||
|
||||
local function buildPlan(character, requirements)
|
||||
local enough = PaintInventory.checkRequirements(character, requirements)
|
||||
if not enough then return nil end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -79,7 +79,7 @@ function PaintRequirements.findInteractionArea(vehicle, character)
|
||||
return nil
|
||||
end
|
||||
|
||||
function PaintRequirements.isValidTarget(character, vehicle, skinIndex, area)
|
||||
function PaintRequirements.isValidSelection(character, vehicle, skinIndex)
|
||||
if not character or not vehicle or vehicle:isRemovedFromWorld() then return false end
|
||||
if character:getVehicle() then return false end
|
||||
if math.abs(vehicle:getCurrentSpeedKmHour()) > 0.8 then return false end
|
||||
@@ -87,6 +87,13 @@ function PaintRequirements.isValidTarget(character, vehicle, skinIndex, area)
|
||||
if skinIndex < 0 or skinIndex >= vehicle:getSkinCount() then return false end
|
||||
if vehicle:getSkinIndex() == skinIndex then return false end
|
||||
if not PaintRequirements.getTextureData(vehicle, skinIndex) then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
function PaintRequirements.isValidTarget(character, vehicle, skinIndex, area)
|
||||
if not PaintRequirements.isValidSelection(character, vehicle, skinIndex) then
|
||||
return false
|
||||
end
|
||||
if not area or not vehicle:isInArea(area, character) then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
PaintMyKI5 = PaintMyKI5 or {}
|
||||
PaintMyKI5.TextureName = PaintMyKI5.TextureName or {}
|
||||
|
||||
local TextureName = PaintMyKI5.TextureName
|
||||
|
||||
local function filename(textureData)
|
||||
local reference = textureData and textureData.texture or ""
|
||||
if type(reference) ~= "string" then return "" end
|
||||
local name = string.match(reference, "([^/\\]+)$") or reference
|
||||
if string.lower(string.sub(name, -4)) == ".png" then
|
||||
name = string.sub(name, 1, -5)
|
||||
end
|
||||
return name
|
||||
end
|
||||
|
||||
local function commonPrefix(names)
|
||||
local prefix = names[1] or ""
|
||||
for index = 2, #names do
|
||||
local other = names[index]
|
||||
local length = math.min(#prefix, #other)
|
||||
local matching = 0
|
||||
for character = 1, length do
|
||||
if string.lower(string.sub(prefix, character, character))
|
||||
~= string.lower(string.sub(other, character, character)) then
|
||||
break
|
||||
end
|
||||
matching = character
|
||||
end
|
||||
prefix = string.sub(prefix, 1, matching)
|
||||
if prefix == "" then break end
|
||||
end
|
||||
return prefix
|
||||
end
|
||||
|
||||
local function shortenedLabels(names)
|
||||
if #names < 2 then return nil end
|
||||
local prefix = commonPrefix(names)
|
||||
local separator = string.match(prefix, "^.*()[_%- ]")
|
||||
if not separator then return nil end
|
||||
prefix = string.sub(prefix, 1, separator)
|
||||
|
||||
local labels = {}
|
||||
local distinct = {}
|
||||
local distinctCount = 0
|
||||
for index, name in ipairs(names) do
|
||||
local label = string.sub(name, #prefix + 1)
|
||||
if label == "" or #label > 32 then return nil end
|
||||
label = string.gsub(label, "[_%-]+", " ")
|
||||
if not distinct[string.lower(label)] then
|
||||
distinct[string.lower(label)] = true
|
||||
distinctCount = distinctCount + 1
|
||||
end
|
||||
labels[index] = label
|
||||
end
|
||||
return distinctCount > 1 and labels or nil
|
||||
end
|
||||
|
||||
function TextureName.buildLabels(textures)
|
||||
local names = {}
|
||||
for index, textureData in ipairs(textures or {}) do
|
||||
names[index] = filename(textureData)
|
||||
end
|
||||
return shortenedLabels(names) or names
|
||||
end
|
||||
|
||||
@@ -17,7 +17,10 @@ function ISPaintMyKI5Vehicle:isValid()
|
||||
self.vehicle, self.skinIndex
|
||||
)
|
||||
if not requirements then return false end
|
||||
return PaintMyKI5.PaintInventory.checkRequirements(self.character, requirements)
|
||||
local ready = PaintMyKI5.PaintInventory.checkPaintingRequirements(
|
||||
self.character, requirements
|
||||
)
|
||||
return ready
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:waitToStart()
|
||||
@@ -78,7 +81,7 @@ function ISPaintMyKI5Vehicle:complete()
|
||||
self.vehicle, self.skinIndex
|
||||
)
|
||||
if not requirements then return false end
|
||||
local enough = PaintMyKI5.PaintInventory.checkRequirements(
|
||||
local enough = PaintMyKI5.PaintInventory.checkPaintingRequirements(
|
||||
self.character, requirements
|
||||
)
|
||||
if not enough then return false end
|
||||
|
||||
@@ -5,5 +5,9 @@
|
||||
"IGUI_PaintMyKI5_Requirements": "Paint requirements",
|
||||
"IGUI_PaintMyKI5_RequirementLine": "%1: %2%%, %3 uses needed, %4 available",
|
||||
"IGUI_PaintMyKI5_OneBucket": "Total: %1 uses — one full bucket",
|
||||
"IGUI_PaintMyKI5_PreviewMissing": "Texture preview unavailable"
|
||||
"IGUI_PaintMyKI5_PreviewMissing": "Texture preview unavailable",
|
||||
"IGUI_PaintMyKI5_MissingRequirements": "Missing requirements:",
|
||||
"IGUI_PaintMyKI5_MissingTool": "Missing %1",
|
||||
"IGUI_PaintMyKI5_MissingPaint": "Missing %1 (%2 uses needed, %3 available)",
|
||||
"IGUI_PaintMyKI5_Unavailable": "The vehicle must be parked and a different skin selected."
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"PaintMyKI5.Sandpaper": "Sandpaper"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
module PaintMyKI5
|
||||
{
|
||||
item Sandpaper
|
||||
{
|
||||
DisplayCategory = Tool,
|
||||
ItemType = base:normal,
|
||||
Weight = 0.1,
|
||||
Icon = Sandpaper,
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
+2
-2
@@ -1,11 +1,11 @@
|
||||
name=Paint my KI5
|
||||
id=hrsys_paint_my_ki5
|
||||
poster=../common/media/textures/preview.png
|
||||
poster=preview.png
|
||||
description=A mod allowing for painting of KI5 vehicles.
|
||||
author=Riggs0
|
||||
category=vehicle
|
||||
require=damnlib
|
||||
icon=../common/media/textures/paint_my_ki5_icon.png
|
||||
icon=icon.png
|
||||
url=https://hudsonriggs.systems
|
||||
modversion=1.1.0
|
||||
versionMin=42.20
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 265 KiB |
Reference in New Issue
Block a user