Initial Commit
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
require "ISUI/ISCollapsableWindow"
|
||||
require "ISUI/ISScrollingListBox"
|
||||
require "ISUI/ISButton"
|
||||
require "Vehicles/TimedActions/ISPathFindAction"
|
||||
require "PaintMyKI5/PaintRequirements"
|
||||
require "PaintMyKI5/PaintInventory"
|
||||
require "PaintMyKI5/TimedActions/ISPaintMyKI5Vehicle"
|
||||
|
||||
ISPaintMyKI5UI = ISCollapsableWindow:derive("ISPaintMyKI5UI")
|
||||
ISPaintMyKI5UI.instances = ISPaintMyKI5UI.instances or {}
|
||||
|
||||
local FONT_SMALL = UIFont.Small
|
||||
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
|
||||
end
|
||||
|
||||
local function getPaletteColor(itemType)
|
||||
for _, paint in ipairs(PaintMyKI5.VehiclePaintData.paintCans or {}) do
|
||||
if paint.item == itemType and paint.rgb then
|
||||
return paint.rgb[1], paint.rgb[2], paint.rgb[3]
|
||||
end
|
||||
end
|
||||
return 0.5, 0.5, 0.5
|
||||
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)
|
||||
elseif alt then
|
||||
list:drawRect(0, y, list:getWidth(), item.height, 0.08, 1, 1, 1)
|
||||
end
|
||||
list:drawText(item.text, 8, y + 3, 1, 1, 1, 1, FONT_SMALL)
|
||||
return y + item.height
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:createChildren()
|
||||
ISCollapsableWindow.createChildren(self)
|
||||
local top = self:titleBarHeight() + 10
|
||||
self.skinList = ISScrollingListBox:new(10, top, 275, self.height - top - 52)
|
||||
self.skinList:initialise()
|
||||
self.skinList:instantiate()
|
||||
self.skinList.itemheight = SMALL_HEIGHT + 8
|
||||
self.skinList.doDrawItem = ISPaintMyKI5UI.drawSkinItem
|
||||
self.skinList.drawBorder = true
|
||||
self:addChild(self.skinList)
|
||||
|
||||
for _, textureData in ipairs(self.vehicleData.textures or {}) do
|
||||
self.skinList:addItem(textureLabel(textureData), textureData)
|
||||
end
|
||||
local currentIndex = self.vehicle:getSkinIndex()
|
||||
for index, row in ipairs(self.skinList.items) do
|
||||
if row.item.skinIndex == currentIndex then self.skinList.selected = index end
|
||||
end
|
||||
if self.skinList.selected <= 0 and #self.skinList.items > 0 then self.skinList.selected = 1 end
|
||||
|
||||
self.paintButton = ISButton:new(
|
||||
self.width - 210, self.height - 38, 95, 28,
|
||||
getText("IGUI_PaintMyKI5_Paint"), self, ISPaintMyKI5UI.onPaint
|
||||
)
|
||||
self.paintButton:initialise()
|
||||
self.paintButton:instantiate()
|
||||
self:addChild(self.paintButton)
|
||||
|
||||
self.cancelButton = ISButton:new(
|
||||
self.width - 105, self.height - 38, 95, 28,
|
||||
getText("UI_btn_close"), self, ISPaintMyKI5UI.close
|
||||
)
|
||||
self.cancelButton:initialise()
|
||||
self.cancelButton:instantiate()
|
||||
self:addChild(self.cancelButton)
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:getSelectedTexture()
|
||||
local row = self.skinList and self.skinList.items[self.skinList.selected] or nil
|
||||
return row and row.item or nil
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:prerender()
|
||||
ISCollapsableWindow.prerender(self)
|
||||
local textureData = self:getSelectedTexture()
|
||||
local enabled = false
|
||||
if textureData then
|
||||
local area = PaintMyKI5.PaintRequirements.findInteractionArea(
|
||||
self.vehicle, self.character
|
||||
)
|
||||
local requirements = PaintMyKI5.PaintRequirements.getRequirements(
|
||||
self.vehicle, textureData.skinIndex
|
||||
)
|
||||
enabled = requirements ~= nil
|
||||
and PaintMyKI5.PaintRequirements.isValidTarget(
|
||||
self.character, self.vehicle, textureData.skinIndex, area
|
||||
)
|
||||
and PaintMyKI5.PaintInventory.checkRequirements(self.character, requirements)
|
||||
end
|
||||
self.paintButton:setEnable(enabled)
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:render()
|
||||
ISCollapsableWindow.render(self)
|
||||
local textureData = self:getSelectedTexture()
|
||||
if not textureData then return end
|
||||
|
||||
local rightX = 300
|
||||
local contentWidth = self.width - rightX - 10
|
||||
local previewY = self:titleBarHeight() + 10
|
||||
local requirements = PaintMyKI5.PaintRequirements.getRequirements(
|
||||
self.vehicle, textureData.skinIndex
|
||||
) or {}
|
||||
local requirementHeight = #requirements * (SMALL_HEIGHT + 5)
|
||||
local availablePreviewHeight = self.height - previewY - requirementHeight - 110
|
||||
local previewHeight = math.max(120, math.min(245, availablePreviewHeight))
|
||||
self:drawRectBorder(rightX, previewY, contentWidth, previewHeight, 0.7, 0.6, 0.6, 0.6)
|
||||
local preview = getTexture("media/textures/" .. textureData.texture .. ".png")
|
||||
or getTexture(textureData.texture)
|
||||
if preview then
|
||||
self:drawTextureScaledAspect(preview, rightX + 5, previewY + 5, contentWidth - 10, previewHeight - 10, 1, 1, 1, 1)
|
||||
else
|
||||
self:drawTextCentre(
|
||||
getText("IGUI_PaintMyKI5_PreviewMissing"),
|
||||
rightX + contentWidth / 2, previewY + previewHeight / 2,
|
||||
0.8, 0.8, 0.8, 1, FONT_SMALL
|
||||
)
|
||||
end
|
||||
|
||||
local y = previewY + previewHeight + 12
|
||||
self:drawText(getText("IGUI_PaintMyKI5_Requirements"), rightX, y, 1, 1, 1, 1, FONT_MEDIUM)
|
||||
y = y + MEDIUM_HEIGHT + 6
|
||||
for _, requirement in ipairs(requirements) do
|
||||
local available = PaintMyKI5.PaintInventory.countUses(self.character, requirement.item)
|
||||
local enough = available + 0.0001 >= requirement.uses
|
||||
local red, green, blue = getPaletteColor(requirement.item)
|
||||
self:drawRect(rightX, y + 2, 14, 14, 1, red, green, blue)
|
||||
self:drawRectBorder(rightX, y + 2, 14, 14, 1, 0.9, 0.9, 0.9)
|
||||
local itemName = getItemNameFromFullType(requirement.item)
|
||||
available = math.floor(available * 100 + 0.5) / 100
|
||||
local text = getText(
|
||||
"IGUI_PaintMyKI5_RequirementLine",
|
||||
itemName, requirement.percent, requirement.uses, available
|
||||
)
|
||||
if enough then
|
||||
self:drawText(text, rightX + 22, y, 0.7, 1, 0.7, 1, FONT_SMALL)
|
||||
else
|
||||
self:drawText(text, rightX + 22, y, 1, 0.4, 0.4, 1, FONT_SMALL)
|
||||
end
|
||||
y = y + SMALL_HEIGHT + 5
|
||||
end
|
||||
self:drawText(
|
||||
getText("IGUI_PaintMyKI5_OneBucket", PaintMyKI5.PaintRequirements.getBucketUses()),
|
||||
rightX, y + 4, 1, 1, 1, 1, FONT_SMALL
|
||||
)
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:onPaint()
|
||||
local textureData = self:getSelectedTexture()
|
||||
if not textureData then return end
|
||||
local requirements = PaintMyKI5.PaintRequirements.getRequirements(
|
||||
self.vehicle, textureData.skinIndex
|
||||
)
|
||||
if not requirements then return end
|
||||
local enough = PaintMyKI5.PaintInventory.checkRequirements(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
|
||||
) then return end
|
||||
|
||||
ISTimedActionQueue.add(ISPathFindAction:pathToVehicleArea(self.character, self.vehicle, area))
|
||||
ISTimedActionQueue.add(ISPaintMyKI5Vehicle:new(
|
||||
self.character, self.vehicle, textureData.skinIndex, area
|
||||
))
|
||||
self:close()
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:close()
|
||||
ISPaintMyKI5UI.instances[self.playerNum] = nil
|
||||
self:setVisible(false)
|
||||
self:removeFromUIManager()
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI.open(playerNum, vehicle)
|
||||
local existing = ISPaintMyKI5UI.instances[playerNum]
|
||||
if existing then existing:close() end
|
||||
local character = getSpecificPlayer(playerNum)
|
||||
local window = ISPaintMyKI5UI:new(character, vehicle, playerNum)
|
||||
window:initialise()
|
||||
window:addToUIManager()
|
||||
ISPaintMyKI5UI.instances[playerNum] = window
|
||||
end
|
||||
|
||||
function ISPaintMyKI5UI:new(character, vehicle, playerNum)
|
||||
local width = math.min(800, getCore():getScreenWidth() - 40)
|
||||
local height = math.min(600, getCore():getScreenHeight() - 40)
|
||||
local x = (getCore():getScreenWidth() - width) / 2
|
||||
local y = (getCore():getScreenHeight() - height) / 2
|
||||
local window = ISCollapsableWindow:new(x, y, width, height)
|
||||
setmetatable(window, self)
|
||||
self.__index = self
|
||||
window.title = getText("IGUI_PaintMyKI5_Title")
|
||||
window.resizable = false
|
||||
window.character = character
|
||||
window.vehicle = vehicle
|
||||
window.vehicleData = PaintMyKI5.PaintRequirements.getVehicleData(vehicle)
|
||||
window.playerNum = playerNum
|
||||
return window
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
require "Vehicles/ISUI/ISVehicleMenu"
|
||||
require "PaintMyKI5/PaintRequirements"
|
||||
require "PaintMyKI5/ISPaintMyKI5UI"
|
||||
|
||||
PaintMyKI5 = PaintMyKI5 or {}
|
||||
PaintMyKI5.PaintVehicleContextMenu = PaintMyKI5.PaintVehicleContextMenu or {}
|
||||
|
||||
local PaintVehicleContextMenu = PaintMyKI5.PaintVehicleContextMenu
|
||||
|
||||
local function getTargetVehicle(playerObj)
|
||||
if JoypadState.players[playerObj:getPlayerNum() + 1] then
|
||||
return ISVehicleMenu.getVehicleToInteractWith(playerObj)
|
||||
end
|
||||
return IsoObjectPicker.Instance:PickVehicle(getMouseXScaled(), getMouseYScaled())
|
||||
end
|
||||
|
||||
function PaintVehicleContextMenu.open(playerObj, vehicle)
|
||||
ISPaintMyKI5UI.open(playerObj:getPlayerNum(), vehicle)
|
||||
end
|
||||
|
||||
function PaintVehicleContextMenu.onFillWorldObjectContextMenu(player, context, worldobjects, test)
|
||||
if test and ISWorldObjectContextMenu.Test then return true end
|
||||
local playerObj = getSpecificPlayer(player)
|
||||
if not playerObj or playerObj:getVehicle() then return false end
|
||||
local vehicle = getTargetVehicle(playerObj)
|
||||
local script = vehicle and vehicle:getScript() or nil
|
||||
local vehicleId = script and script:getFullName() or nil
|
||||
local vehicles = PaintMyKI5.VehiclePaintData and PaintMyKI5.VehiclePaintData.vehicles
|
||||
local shortId = vehicleId and string.match(vehicleId, "[^.]+$") or nil
|
||||
if not shortId or string.match(string.lower(shortId), "^trailer") then return false end
|
||||
if not vehicles or not vehicles[vehicleId] then return false end
|
||||
if math.abs(vehicle:getCurrentSpeedKmHour()) > 0.8 then return false end
|
||||
if test then return ISWorldObjectContextMenu.setTest() end
|
||||
|
||||
local option = context:addOption(
|
||||
getText("ContextMenu_PaintMyKI5"),
|
||||
playerObj,
|
||||
PaintVehicleContextMenu.open,
|
||||
vehicle
|
||||
)
|
||||
option.iconTexture = getTexture("media/textures/PaintBrush.png")
|
||||
return true
|
||||
end
|
||||
|
||||
Events.OnFillWorldObjectContextMenu.Add(PaintVehicleContextMenu.onFillWorldObjectContextMenu)
|
||||
@@ -0,0 +1,131 @@
|
||||
PaintMyKI5 = PaintMyKI5 or {}
|
||||
PaintMyKI5.PaintInventory = PaintMyKI5.PaintInventory or {}
|
||||
|
||||
local PaintInventory = PaintMyKI5.PaintInventory
|
||||
local EPSILON = 0.0001
|
||||
local EMPTY_BUCKET = "Base.PaintbucketEmpty"
|
||||
|
||||
local function getItems(character, itemType)
|
||||
if not character or not character:getInventory() then return nil end
|
||||
return character:getInventory():getAllTypeRecurse(itemType)
|
||||
end
|
||||
|
||||
local function getUses(item)
|
||||
local useDelta = item:getUseDelta()
|
||||
if not useDelta or useDelta <= 0 then return 0 end
|
||||
return item:getCurrentUsesFloat() / useDelta
|
||||
end
|
||||
|
||||
function PaintInventory.countUses(character, itemType)
|
||||
local items = getItems(character, itemType)
|
||||
if not items then return 0 end
|
||||
local total = 0
|
||||
for index = 0, items:size() - 1 do
|
||||
total = total + getUses(items:get(index))
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
function PaintInventory.checkRequirements(character, requirements)
|
||||
local missing = {}
|
||||
for _, requirement in ipairs(requirements or {}) do
|
||||
local available = PaintInventory.countUses(character, requirement.item)
|
||||
if available + EPSILON < requirement.uses then
|
||||
table.insert(missing, {
|
||||
item = requirement.item,
|
||||
required = requirement.uses,
|
||||
available = available,
|
||||
})
|
||||
end
|
||||
end
|
||||
return #missing == 0, missing
|
||||
end
|
||||
|
||||
local function buildPlan(character, requirements)
|
||||
local enough = PaintInventory.checkRequirements(character, requirements)
|
||||
if not enough then return nil end
|
||||
local plan = {}
|
||||
for _, requirement in ipairs(requirements) do
|
||||
local remaining = requirement.uses
|
||||
local items = getItems(character, requirement.item)
|
||||
for index = 0, items:size() - 1 do
|
||||
if remaining <= EPSILON then break end
|
||||
local item = items:get(index)
|
||||
local oldDelta = item:getCurrentUsesFloat()
|
||||
local consumed = math.min(remaining, getUses(item))
|
||||
local newDelta = oldDelta - consumed * item:getUseDelta()
|
||||
local mutation = {
|
||||
item = item,
|
||||
container = item:getContainer(),
|
||||
oldDelta = oldDelta,
|
||||
newDelta = newDelta,
|
||||
}
|
||||
if not mutation.container then return nil end
|
||||
if newDelta <= EPSILON then
|
||||
mutation.replacement = instanceItem(EMPTY_BUCKET)
|
||||
if not mutation.replacement then return nil end
|
||||
end
|
||||
table.insert(plan, mutation)
|
||||
remaining = remaining - consumed
|
||||
end
|
||||
if remaining > EPSILON then return nil end
|
||||
end
|
||||
return plan
|
||||
end
|
||||
|
||||
local function applyMutation(character, mutation)
|
||||
if not mutation.replacement then
|
||||
mutation.item:setUsedDelta(mutation.newDelta)
|
||||
mutation.deltaApplied = true
|
||||
sendItemStats(mutation.item)
|
||||
return
|
||||
end
|
||||
local added = mutation.container:AddItem(mutation.replacement)
|
||||
if not added then error("could not add empty paint bucket") end
|
||||
mutation.replacementAdded = true
|
||||
sendAddItemToContainer(mutation.container, mutation.replacement)
|
||||
character:removeFromHands(mutation.item)
|
||||
mutation.container:DoRemoveItem(mutation.item)
|
||||
mutation.originalRemoved = true
|
||||
sendRemoveItemFromContainer(mutation.container, mutation.item)
|
||||
end
|
||||
|
||||
local function rollBackMutation(mutation)
|
||||
if mutation.replacement then
|
||||
if mutation.originalRemoved then
|
||||
mutation.item:setUsedDelta(mutation.oldDelta)
|
||||
local restored = mutation.container:AddItem(mutation.item)
|
||||
if not restored then return false end
|
||||
sendAddItemToContainer(mutation.container, mutation.item)
|
||||
mutation.originalRemoved = false
|
||||
end
|
||||
if mutation.replacementAdded then
|
||||
mutation.container:DoRemoveItem(mutation.replacement)
|
||||
sendRemoveItemFromContainer(mutation.container, mutation.replacement)
|
||||
mutation.replacementAdded = false
|
||||
end
|
||||
elseif mutation.deltaApplied then
|
||||
mutation.item:setUsedDelta(mutation.oldDelta)
|
||||
sendItemStats(mutation.item)
|
||||
mutation.deltaApplied = false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function PaintInventory.consumeRequirements(character, requirements)
|
||||
local plan = buildPlan(character, requirements)
|
||||
if not plan then return false end
|
||||
local applied = {}
|
||||
for _, mutation in ipairs(plan) do
|
||||
local ok = pcall(applyMutation, character, mutation)
|
||||
if not ok then
|
||||
pcall(rollBackMutation, mutation)
|
||||
for index = #applied, 1, -1 do
|
||||
pcall(rollBackMutation, applied[index])
|
||||
end
|
||||
return false
|
||||
end
|
||||
table.insert(applied, mutation)
|
||||
end
|
||||
return true
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
||||
require "PaintMyKI5/PaintMyKI5VehiclePaintData"
|
||||
|
||||
PaintMyKI5 = PaintMyKI5 or {}
|
||||
PaintMyKI5.PaintRequirements = PaintMyKI5.PaintRequirements or {}
|
||||
|
||||
local PaintRequirements = PaintMyKI5.PaintRequirements
|
||||
local INTERACTION_AREAS = {
|
||||
"Engine", "TruckBed", "SeatFrontLeft", "SeatLeft", "SeatFrontRight", "SeatRight"
|
||||
}
|
||||
|
||||
local function getVehicleId(vehicle)
|
||||
if not vehicle or not vehicle.getScript then return nil end
|
||||
local script = vehicle:getScript()
|
||||
return script and script:getFullName() or nil
|
||||
end
|
||||
|
||||
local function isCarId(vehicleId)
|
||||
local shortId = vehicleId and string.match(vehicleId, "[^.]+$") or nil
|
||||
return shortId and not string.match(string.lower(shortId), "^trailer")
|
||||
end
|
||||
|
||||
function PaintRequirements.getVehicleData(vehicle)
|
||||
local data = PaintMyKI5.VehiclePaintData
|
||||
local vehicleId = getVehicleId(vehicle)
|
||||
if not data or not data.vehicles or not isCarId(vehicleId) then return nil end
|
||||
return data.vehicles[vehicleId]
|
||||
end
|
||||
|
||||
function PaintRequirements.getTextureData(vehicle, skinIndex)
|
||||
local vehicleData = PaintRequirements.getVehicleData(vehicle)
|
||||
if not vehicleData or type(skinIndex) ~= "number" or skinIndex % 1 ~= 0 then return nil end
|
||||
for _, textureData in ipairs(vehicleData.textures or {}) do
|
||||
if textureData.skinIndex == skinIndex then return textureData end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function PaintRequirements.getBucketUses()
|
||||
local data = PaintMyKI5.VehiclePaintData
|
||||
local uses = data and tonumber(data.bucketUses) or nil
|
||||
if not uses or uses <= 0 then return nil end
|
||||
return uses
|
||||
end
|
||||
|
||||
function PaintRequirements.getRequirements(vehicle, skinIndex)
|
||||
local textureData = PaintRequirements.getTextureData(vehicle, skinIndex)
|
||||
local bucketUses = PaintRequirements.getBucketUses()
|
||||
if not textureData or not bucketUses then return nil end
|
||||
|
||||
local requirements = {}
|
||||
local total = 0
|
||||
for _, paint in ipairs(textureData.paints or {}) do
|
||||
local uses = tonumber(paint.uses)
|
||||
if type(paint.item) ~= "string" or not uses or uses <= 0 then return nil end
|
||||
table.insert(requirements, {
|
||||
item = paint.item,
|
||||
percent = tonumber(paint.percent) or 0,
|
||||
uses = uses,
|
||||
})
|
||||
total = total + uses
|
||||
end
|
||||
if math.abs(total - bucketUses) > 0.001 then return nil end
|
||||
return requirements, textureData
|
||||
end
|
||||
|
||||
function PaintRequirements.isSupported(vehicle)
|
||||
return PaintRequirements.getVehicleData(vehicle) ~= nil
|
||||
end
|
||||
|
||||
function PaintRequirements.findInteractionArea(vehicle, character)
|
||||
if not vehicle or not character then return nil end
|
||||
local part = vehicle:getUseablePart(character)
|
||||
if part and part:getArea() then return part:getArea() end
|
||||
local script = vehicle:getScript()
|
||||
if not script then return nil end
|
||||
for _, area in ipairs(INTERACTION_AREAS) do
|
||||
if script:getAreaById(area) then return area end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function PaintRequirements.isValidTarget(character, vehicle, skinIndex, area)
|
||||
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
|
||||
if type(skinIndex) ~= "number" or skinIndex % 1 ~= 0 then return false end
|
||||
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
|
||||
if not area or not vehicle:isInArea(area, character) then return false end
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,115 @@
|
||||
require "TimedActions/ISBaseTimedAction"
|
||||
require "PaintMyKI5/PaintRequirements"
|
||||
require "PaintMyKI5/PaintInventory"
|
||||
|
||||
ISPaintMyKI5Vehicle = ISBaseTimedAction:derive("ISPaintMyKI5Vehicle")
|
||||
|
||||
function ISPaintMyKI5Vehicle:isValid()
|
||||
local area = PaintMyKI5.PaintRequirements.findInteractionArea(
|
||||
self.vehicle, self.character
|
||||
)
|
||||
if not PaintMyKI5.PaintRequirements.isValidTarget(
|
||||
self.character, self.vehicle, self.skinIndex, area
|
||||
) then
|
||||
return false
|
||||
end
|
||||
local requirements = PaintMyKI5.PaintRequirements.getRequirements(
|
||||
self.vehicle, self.skinIndex
|
||||
)
|
||||
if not requirements then return false end
|
||||
return PaintMyKI5.PaintInventory.checkRequirements(self.character, requirements)
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:waitToStart()
|
||||
self.character:faceThisObject(self.vehicle)
|
||||
return self.character:shouldBeTurning()
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:update()
|
||||
self.character:faceThisObject(self.vehicle)
|
||||
self.character:setMetabolicTarget(Metabolics.MediumWork)
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:start()
|
||||
self.originalSkinIndex = self.vehicle:getSkinIndex()
|
||||
self:setActionAnim(CharacterActionAnims.Paint)
|
||||
self:setOverrideHandModels("PaintBrush", nil)
|
||||
self.sound = self.character:playSound("Painting")
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:serverStart()
|
||||
self.originalSkinIndex = self.vehicle and self.vehicle:getSkinIndex() or nil
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:stop()
|
||||
if self.sound then self.character:stopOrTriggerSound(self.sound) end
|
||||
ISBaseTimedAction.stop(self)
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:perform()
|
||||
if self.sound then self.character:stopOrTriggerSound(self.sound) end
|
||||
ISBaseTimedAction.perform(self)
|
||||
end
|
||||
|
||||
local function applySkin(vehicle, skinIndex)
|
||||
vehicle:setSkinIndex(skinIndex)
|
||||
if isServer() then
|
||||
vehicle:transmitSkinIndex()
|
||||
else
|
||||
vehicle:updateSkin()
|
||||
end
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:complete()
|
||||
if isClient() then return true end
|
||||
local area = PaintMyKI5.PaintRequirements.findInteractionArea(
|
||||
self.vehicle, self.character
|
||||
)
|
||||
if not PaintMyKI5.PaintRequirements.isValidTarget(
|
||||
self.character, self.vehicle, self.skinIndex, area
|
||||
) then
|
||||
return false
|
||||
end
|
||||
if self.originalSkinIndex == nil
|
||||
or self.vehicle:getSkinIndex() ~= self.originalSkinIndex then
|
||||
return false
|
||||
end
|
||||
local requirements = PaintMyKI5.PaintRequirements.getRequirements(
|
||||
self.vehicle, self.skinIndex
|
||||
)
|
||||
if not requirements then return false end
|
||||
local enough = PaintMyKI5.PaintInventory.checkRequirements(
|
||||
self.character, requirements
|
||||
)
|
||||
if not enough then return false end
|
||||
|
||||
local vehicle = self.vehicle
|
||||
local changed = pcall(applySkin, vehicle, self.skinIndex)
|
||||
if not changed then
|
||||
pcall(applySkin, vehicle, self.originalSkinIndex)
|
||||
return false
|
||||
end
|
||||
if not PaintMyKI5.PaintInventory.consumeRequirements(self.character, requirements) then
|
||||
pcall(applySkin, vehicle, self.originalSkinIndex)
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:getDuration()
|
||||
if self.character:isTimedActionInstant() then return 1 end
|
||||
return 500
|
||||
end
|
||||
|
||||
function ISPaintMyKI5Vehicle:new(character, vehicle, skinIndex, area)
|
||||
local action = ISBaseTimedAction.new(self, character)
|
||||
action.vehicle = vehicle
|
||||
action.skinIndex = skinIndex
|
||||
action.area = area
|
||||
action.originalSkinIndex = vehicle and vehicle:getSkinIndex() or nil
|
||||
action.maxTime = action:getDuration()
|
||||
action.stopOnWalk = true
|
||||
action.stopOnRun = true
|
||||
action.caloriesModifier = 4
|
||||
return action
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"ContextMenu_PaintMyKI5": "Paint vehicle"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"IGUI_PaintMyKI5_Title": "Paint KI5 Vehicle",
|
||||
"IGUI_PaintMyKI5_Skin": "Skin %1",
|
||||
"IGUI_PaintMyKI5_Paint": "Paint",
|
||||
"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"
|
||||
}
|
||||
Reference in New Issue
Block a user