Moved everything to common.
This commit is contained in:
116
common/media/lua/client/TOC/UI/ConfirmationPanel.lua
Normal file
116
common/media/lua/client/TOC/UI/ConfirmationPanel.lua
Normal file
@@ -0,0 +1,116 @@
|
||||
---@class ConfirmationPanel : ISPanel
|
||||
local ConfirmationPanel = ISPanel:derive("ConfirmationPanel")
|
||||
|
||||
---Starts a new confirmation panel
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param width number
|
||||
---@param height number
|
||||
---@param alertText string
|
||||
---@param onConfirmFunc function
|
||||
---@return ConfirmationPanel
|
||||
function ConfirmationPanel:new(x, y, width, height, alertText, parentPanel, onConfirmFunc)
|
||||
local o = ISPanel:new(x, y, width, height)
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
|
||||
o:initialise()
|
||||
o.alertText = alertText
|
||||
o.onConfirmFunc = onConfirmFunc
|
||||
o.parentPanel = parentPanel
|
||||
ConfirmationPanel.instance = o
|
||||
|
||||
---@cast o ConfirmationPanel
|
||||
return o
|
||||
end
|
||||
|
||||
function ConfirmationPanel:createChildren()
|
||||
ISPanel.createChildren(self)
|
||||
self.borderColor = { r = 1, g = 0, b = 0, a = 1 }
|
||||
|
||||
self.textPanel = ISRichTextPanel:new(0, 0, self.width, self.height)
|
||||
self.textPanel:initialise()
|
||||
self:addChild(self.textPanel)
|
||||
self.textPanel.defaultFont = UIFont.Medium
|
||||
self.textPanel.anchorTop = true
|
||||
self.textPanel.anchorLeft = false
|
||||
self.textPanel.anchorBottom = true
|
||||
self.textPanel.anchorRight = false
|
||||
self.textPanel.marginLeft = 0
|
||||
self.textPanel.marginTop = 10
|
||||
self.textPanel.marginRight = 0
|
||||
self.textPanel.marginBottom = 0
|
||||
self.textPanel.autosetheight = false
|
||||
self.textPanel.background = false
|
||||
self.textPanel:setText(self.alertText)
|
||||
self.textPanel:paginate()
|
||||
|
||||
local yPadding = 10
|
||||
local xPadding = self:getWidth() / 4
|
||||
local btnWidth = 100
|
||||
local btnHeight = 25
|
||||
|
||||
|
||||
local yButton = self:getHeight() - yPadding - btnHeight
|
||||
|
||||
self.btnYes = ISButton:new(xPadding, yButton, btnWidth, btnHeight, getText("IGUI_Yes"), self, self.onClick)
|
||||
self.btnYes.internal = "YES"
|
||||
self.btnYes:initialise()
|
||||
self.btnYes.borderColor = { r = 1, g = 0, b = 0, a = 1 }
|
||||
self.btnYes:setEnable(true)
|
||||
self:addChild(self.btnYes)
|
||||
|
||||
self.btnNo = ISButton:new(self:getWidth() - xPadding - btnWidth, yButton, btnWidth, btnHeight, getText("IGUI_No"), self,
|
||||
self.onClick)
|
||||
self.btnNo.internal = "NO"
|
||||
self.btnNo:initialise()
|
||||
self.btnNo:setEnable(true)
|
||||
self:addChild(self.btnNo)
|
||||
end
|
||||
|
||||
function ConfirmationPanel:onClick(btn)
|
||||
if btn.internal == 'YES' then
|
||||
self.onConfirmFunc(self.parentPanel)
|
||||
self:close()
|
||||
elseif btn.internal == 'NO' then
|
||||
self:close()
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------
|
||||
|
||||
---@param alertText string
|
||||
---@param x any
|
||||
---@param y any
|
||||
---@param parentPanel any
|
||||
---@param onConfirmFunc any
|
||||
---@return ConfirmationPanel
|
||||
function ConfirmationPanel.Open(alertText, x, y, parentPanel, onConfirmFunc)
|
||||
local width = 500
|
||||
local height = 120
|
||||
|
||||
|
||||
local screenWidth = getCore():getScreenWidth()
|
||||
local screenHeight = getCore():getScreenHeight()
|
||||
|
||||
-- Check for oversize
|
||||
if x+width > screenWidth then
|
||||
x = screenWidth - width
|
||||
end
|
||||
|
||||
if y+height > screenHeight then
|
||||
y = screenHeight - height
|
||||
end
|
||||
|
||||
local panel = ConfirmationPanel:new(x, y, width, height, alertText, parentPanel, onConfirmFunc)
|
||||
panel:initialise()
|
||||
panel:addToUIManager()
|
||||
panel:bringToTop()
|
||||
return panel
|
||||
end
|
||||
|
||||
function ConfirmationPanel.Close()
|
||||
ConfirmationPanel.instance:close()
|
||||
end
|
||||
|
||||
return ConfirmationPanel
|
||||
282
common/media/lua/client/TOC/UI/HealthPanel.lua
Normal file
282
common/media/lua/client/TOC/UI/HealthPanel.lua
Normal file
@@ -0,0 +1,282 @@
|
||||
local StaticData = require("TOC/StaticData")
|
||||
local DataController = require("TOC/Controllers/DataController")
|
||||
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
|
||||
local Compat = require("TOC/Compat")
|
||||
|
||||
local CutLimbInteractionHandler = require("TOC/UI/Interactions/CutLimbInteractionHandler")
|
||||
local WoundCleaningInteractionHandler = require("TOC/UI/Interactions/WoundCleaningInteractionHandler")
|
||||
------------------------
|
||||
|
||||
|
||||
local isReady = false
|
||||
|
||||
function SetHealthPanelTOC()
|
||||
|
||||
-- depending on compatibility
|
||||
|
||||
isReady = true
|
||||
end
|
||||
|
||||
|
||||
-- We're overriding ISHealthPanel to add custom textures to the body panel.
|
||||
-- By doing so we can show the player which limbs have been cut without having to use another menu
|
||||
-- We can show prosthesis too this way
|
||||
-- We also manage the drag'n drop of items on the body to let the players use the saw this way too
|
||||
---@diagnostic disable: duplicate-set-field
|
||||
|
||||
--ISHealthBodyPartPanel = ISBodyPartPanel:derive("ISHealthBodyPartPanel")
|
||||
|
||||
--* Handling drag n drop of the saw *--
|
||||
|
||||
local og_ISHealthPanel_dropItemsOnBodyPart = ISHealthPanel.dropItemsOnBodyPart
|
||||
function ISHealthPanel:dropItemsOnBodyPart(bodyPart, items)
|
||||
og_ISHealthPanel_dropItemsOnBodyPart(self, bodyPart, items)
|
||||
|
||||
TOC_DEBUG.print("override to dropItemsOnBodyPart running")
|
||||
local cutLimbInteraction = CutLimbInteractionHandler:new(self, bodyPart)
|
||||
local woundCleaningInteraction = WoundCleaningInteractionHandler:new(self, bodyPart, self.character:getUsername())
|
||||
|
||||
for _,item in ipairs(items) do
|
||||
cutLimbInteraction:checkItem(item)
|
||||
woundCleaningInteraction:checkItem(item)
|
||||
end
|
||||
if cutLimbInteraction:dropItems(items) or woundCleaningInteraction:dropItems(items) then
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local og_ISHealthPanel_doBodyPartContextMenu = ISHealthPanel.doBodyPartContextMenu
|
||||
function ISHealthPanel:doBodyPartContextMenu(bodyPart, x, y)
|
||||
og_ISHealthPanel_doBodyPartContextMenu(self, bodyPart, x, y)
|
||||
local playerNum = self.otherPlayer and self.otherPlayer:getPlayerNum() or self.character:getPlayerNum()
|
||||
|
||||
-- To not recreate it but reuse the one that has been created in the original method
|
||||
|
||||
-- TODO This will work ONLY when an addOption has been already done in the og method.
|
||||
local context = getPlayerContextMenu(playerNum)
|
||||
context:bringToTop()
|
||||
context:setVisible(true)
|
||||
|
||||
|
||||
local cutLimbInteraction = CutLimbInteractionHandler:new(self, bodyPart)
|
||||
self:checkItems({cutLimbInteraction})
|
||||
cutLimbInteraction:addToMenu(context)
|
||||
|
||||
local woundCleaningInteraction = WoundCleaningInteractionHandler:new(self, bodyPart, self.character:getUsername())
|
||||
self:checkItems({woundCleaningInteraction})
|
||||
woundCleaningInteraction:addToMenu(context)
|
||||
end
|
||||
|
||||
|
||||
--* Modifications and additional methods to handle visible amputation on the health menu *--
|
||||
|
||||
---Get a value between 1 and 0.1 for the cicatrization time
|
||||
---@param cicTime integer
|
||||
---@return integer
|
||||
local function GetColorFromCicatrizationTime(cicTime, limbName)
|
||||
local defaultTime = StaticData.LIMBS_CICATRIZATION_TIME_IND_NUM[limbName]
|
||||
local delta = cicTime/defaultTime
|
||||
return math.max(0.15, math.min(delta, 1))
|
||||
end
|
||||
|
||||
---Try to draw the highest amputation in the health panel, based on the cicatrization time
|
||||
---@param side string L or R
|
||||
---@param username string
|
||||
function ISHealthPanel:tryDrawAmputation(highestAmputations, side, username)
|
||||
local redColor
|
||||
local texture
|
||||
|
||||
if TOC_DEBUG.enableHealthPanelDebug then
|
||||
redColor = 1
|
||||
texture = getTexture("media/ui/test_pattern.png")
|
||||
else
|
||||
if highestAmputations[side] == nil then return end
|
||||
local limbName = highestAmputations[side]
|
||||
--TOC_DEBUG.print("Drawing " .. tostring(limbName) .. " for " .. username)
|
||||
|
||||
local cicTime = DataController.GetInstance(username):getCicatrizationTime(limbName)
|
||||
redColor = GetColorFromCicatrizationTime(cicTime, limbName)
|
||||
|
||||
local sexPl = self.character:isFemale() and "Female" or "Male"
|
||||
texture = StaticData.HEALTH_PANEL_TEXTURES[sexPl][limbName]
|
||||
end
|
||||
|
||||
-- B42, for some reason the positioning of the texture changed. Realigned it manually with those fixed values
|
||||
self:drawTexture(texture, self.healthPanel.x - 5, self.healthPanel.y - 9, 1, redColor, 0, 0)
|
||||
end
|
||||
function ISHealthPanel:tryDrawProsthesis(highestAmputations, side, username)
|
||||
local dc = DataController.GetInstance(username) -- TODO CACHE PROSTHESIS!!! Don't use DC here
|
||||
local limbName = highestAmputations[side]
|
||||
if limbName and dc:getIsProstEquipped(limbName) then
|
||||
self:drawTexture(StaticData.HEALTH_PANEL_TEXTURES.ProstArm[side], self.healthPanel.x, self.healthPanel.y, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
local og_ISHealthPanel_render = ISHealthPanel.render
|
||||
function ISHealthPanel:render()
|
||||
og_ISHealthPanel_render(self)
|
||||
local username = self.character:getUsername()
|
||||
local highestAmputations = CachedDataHandler.GetHighestAmputatedLimbs(username)
|
||||
|
||||
if highestAmputations ~= nil then
|
||||
|
||||
-- Left Texture
|
||||
self:tryDrawAmputation(highestAmputations, "L", username)
|
||||
self:tryDrawProsthesis(highestAmputations, "L", username)
|
||||
|
||||
-- Right Texture
|
||||
self:tryDrawAmputation(highestAmputations, "R", username)
|
||||
self:tryDrawProsthesis(highestAmputations, "R", username)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- local og_ISHealthPanel_update = ISHealthPanel.update
|
||||
-- function ISHealthPanel:update()
|
||||
-- og_ISHealthPanel_update(self)
|
||||
-- -- TODO Listen for changes on other player side instead of looping this
|
||||
|
||||
|
||||
-- -- FIX Re-enable it, just for test
|
||||
-- if self.character then
|
||||
-- local locPlUsername = getPlayer():getUsername()
|
||||
-- local remPlUsername = self.character:getUsername()
|
||||
-- if locPlUsername ~= remPlUsername and self:isReallyVisible() then
|
||||
-- -- Request update for TOC DATA
|
||||
-- local key = CommandsData.GetKey(remPlUsername)
|
||||
-- --ModData.request(key)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
|
||||
|
||||
-- We need to override this to force the alpha to 1
|
||||
local og_ISCharacterInfoWindow_render = ISCharacterInfoWindow.prerender
|
||||
function ISCharacterInfoWindow:prerender()
|
||||
og_ISCharacterInfoWindow_render(self)
|
||||
self.backgroundColor.a = 1
|
||||
end
|
||||
|
||||
-- We need to override this to force the alpha to 1 for the Medical Check in particular
|
||||
local og_ISHealthPanel_prerender = ISHealthPanel.prerender
|
||||
function ISHealthPanel:prerender()
|
||||
og_ISHealthPanel_prerender(self)
|
||||
self.backgroundColor.a = 1
|
||||
end
|
||||
|
||||
--- The medical check wrap the health panel into this. We need to override its color
|
||||
local overrideBackgroundColor = true
|
||||
local og_ISUIElement_wrapInCollapsableWindow = ISUIElement.wrapInCollapsableWindow
|
||||
---@param title string
|
||||
---@param resizable any
|
||||
---@param subClass any
|
||||
---@return any
|
||||
function ISUIElement:wrapInCollapsableWindow(title, resizable, subClass)
|
||||
local panel = og_ISUIElement_wrapInCollapsableWindow(self, title, resizable, subClass)
|
||||
|
||||
if overrideBackgroundColor then
|
||||
TOC_DEBUG.print("Overriding color for panel - " .. title)
|
||||
self.backgroundColor.a = 1
|
||||
panel.backgroundColor.a = 1
|
||||
end
|
||||
|
||||
return panel
|
||||
end
|
||||
|
||||
-- This is run when a player is trying the Medical Check action on another player
|
||||
local og_ISMedicalCheckAction_perform = ISMedicalCheckAction.perform
|
||||
function ISMedicalCheckAction:perform()
|
||||
local username = self.otherPlayer:getUsername()
|
||||
TOC_DEBUG.print("Medical Action on " .. username )
|
||||
|
||||
-- We need to recalculate them here before we can create the highest amputations point
|
||||
CachedDataHandler.CalculateAmputatedLimbs(username)
|
||||
og_ISMedicalCheckAction_perform(self)
|
||||
end
|
||||
|
||||
local og_ISHealthBodyPartListBox_doDrawItem = ISHealthBodyPartListBox.doDrawItem
|
||||
function ISHealthBodyPartListBox:doDrawItem(y, item, alt)
|
||||
y = og_ISHealthBodyPartListBox_doDrawItem(self, y, item, alt)
|
||||
y = y - 5
|
||||
local x = 15
|
||||
local fontHgt = getTextManager():getFontHeight(UIFont.Small)
|
||||
|
||||
local username = self.parent.character:getUsername()
|
||||
--local amputatedLimbs = CachedDataHandler.GetIndexedAmputatedLimbs(username)
|
||||
|
||||
---@type BodyPart
|
||||
local bodyPart = item.item.bodyPart
|
||||
|
||||
local bodyPartTypeStr = BodyPartType.ToString(bodyPart:getType())
|
||||
local limbName = StaticData.LIMBS_IND_STR[bodyPartTypeStr]
|
||||
|
||||
|
||||
-- We should cache a lot of other stuff to have this working with CacheDataHandler :(
|
||||
if limbName then
|
||||
local dcInst = DataController.GetInstance(username)
|
||||
if dcInst:getIsCut(limbName) and dcInst:getIsVisible(limbName) then
|
||||
if dcInst:getIsCicatrized(limbName) then
|
||||
if dcInst:getIsCauterized(limbName) then
|
||||
self:drawText("- " .. getText("IGUI_HealthPanel_Cauterized"), x, y, 0.58, 0.75, 0.28, 1, UIFont.Small)
|
||||
else
|
||||
self:drawText("- " .. getText("IGUI_HealthPanel_Cicatrized"), x, y, 0.28, 0.89, 0.28, 1, UIFont.Small)
|
||||
end
|
||||
|
||||
y = y + fontHgt
|
||||
else
|
||||
local cicaTime = dcInst:getCicatrizationTime(limbName)
|
||||
|
||||
-- Show it in percentage
|
||||
local maxCicaTime = StaticData.LIMBS_CICATRIZATION_TIME_IND_NUM[limbName]
|
||||
local percentage = (1 - cicaTime/maxCicaTime) * 100
|
||||
self:drawText("- " .. getText("IGUI_HealthPanel_Cicatrization") .. string.format(" %.2f", percentage) .. "%", x, y, 0.89, 0.28, 0.28, 1, UIFont.Small)
|
||||
y = y + fontHgt
|
||||
|
||||
local scaledDirtyness = math.floor(dcInst:getWoundDirtyness(limbName) * 100)
|
||||
self:drawText("- " .. getText("IGUI_HealthPanel_WoundDirtyness") .. string.format(" %d", scaledDirtyness) .. "%", x, y, 0.89, 0.28, 0.28, 1, UIFont.Small)
|
||||
y = y + fontHgt
|
||||
|
||||
end
|
||||
|
||||
if dcInst:getIsProstEquipped(limbName) then
|
||||
self:drawText("- " .. getText("IGUI_HealthPanel_ProstEquipped"), x, y, 0.28, 0.89, 0.28, 1, UIFont.Small)
|
||||
y = y + fontHgt
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
y = y + 5
|
||||
return y
|
||||
end
|
||||
|
||||
local og_ISHealthPanel_getDamagedParts = ISHealthPanel.getDamagedParts
|
||||
function ISHealthPanel:getDamagedParts()
|
||||
-- check for imeds or if TOC is ready to display its stuff on the health panel
|
||||
if isReady == false or Compat.handlers['iMeds'].isActive or Compat.handlers['iMedsFixed'].isActive then
|
||||
return og_ISHealthPanel_getDamagedParts(self)
|
||||
elseif isReady then
|
||||
local result = {}
|
||||
local bodyParts = self:getPatient():getBodyDamage():getBodyParts()
|
||||
if isClient() and not self:getPatient():isLocalPlayer() then
|
||||
bodyParts = self:getPatient():getBodyDamageRemote():getBodyParts()
|
||||
end
|
||||
|
||||
local patientUsername = self:getPatient():getUsername()
|
||||
local mdh = DataController.GetInstance(patientUsername)
|
||||
for i=1,bodyParts:size() do
|
||||
local bodyPart = bodyParts:get(i-1)
|
||||
local bodyPartTypeStr = BodyPartType.ToString(bodyPart:getType())
|
||||
local limbName = StaticData.LIMBS_IND_STR[bodyPartTypeStr]
|
||||
|
||||
if ISHealthPanel.cheat or bodyPart:HasInjury() or bodyPart:bandaged() or bodyPart:stitched() or bodyPart:getSplintFactor() > 0 or bodyPart:getAdditionalPain() > 10 or bodyPart:getStiffness() > 5 or (mdh:getIsCut(limbName) and mdh:getIsVisible(limbName)) then
|
||||
table.insert(result, bodyPart)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,287 @@
|
||||
local BaseHandler = require("TOC/UI/Interactions/HealthPanelBaseHandler")
|
||||
local StaticData = require("TOC/StaticData")
|
||||
local DataController = require("TOC/Controllers/DataController")
|
||||
local ConfirmationPanel = require("TOC/UI/ConfirmationPanel")
|
||||
|
||||
local CutLimbAction = require("TOC/TimedActions/CutLimbAction")
|
||||
---------------------
|
||||
|
||||
|
||||
|
||||
|
||||
--* Various functions to help during these pesky checks
|
||||
|
||||
---Check if the item type corresponds to a compatible saw
|
||||
---@param itemType string
|
||||
local function CheckIfSaw(itemType)
|
||||
return itemType == StaticData.SAWS_TYPES_IND_STR.saw
|
||||
or itemType == StaticData.SAWS_TYPES_IND_STR.gardenSaw
|
||||
end
|
||||
|
||||
---Return a compatible bandage
|
||||
---@param player IsoPlayer
|
||||
---@return InventoryItem?
|
||||
local function GetBandageItem(player)
|
||||
local plInv = player:getInventory()
|
||||
local bandageItem = plInv:FindAndReturn("Base.Bandage") or plInv:FindAndReturn("Base.RippedSheets")
|
||||
|
||||
---@cast bandageItem InventoryItem
|
||||
|
||||
return bandageItem
|
||||
end
|
||||
|
||||
---Return a suture needle or thread (only if the player has a needle too)
|
||||
---@param player IsoPlayer
|
||||
---@return InventoryItem?
|
||||
local function GetStitchesConsumableItem(player)
|
||||
local plInv = player:getInventory()
|
||||
|
||||
-- Suture needle has priority
|
||||
|
||||
local sutureNeedle = plInv:FindAndReturn("Base.SutureNeedle")
|
||||
|
||||
if sutureNeedle then
|
||||
return sutureNeedle
|
||||
else
|
||||
-- Didn't find the suture one, so let's search for the normal one + thread
|
||||
|
||||
local needleItem = plInv:FindAndReturn("Base.Needle")
|
||||
|
||||
if needleItem == nil then return nil end
|
||||
|
||||
-- Found the normal one, searching for thread
|
||||
|
||||
local threadItem = plInv:FindAndReturn("Base.Thread")
|
||||
---@cast threadItem DrainableComboItem
|
||||
|
||||
if threadItem and threadItem:getUsedDelta() > 0 then
|
||||
return threadItem
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
local textConfirmAmp = getText("IGUI_Confirmation_Amputate")
|
||||
local textAmp = getText("ContextMenu_Amputate")
|
||||
local textAmpBandage = getText("ContextMenu_Amputate_Bandage")
|
||||
local textAmpStitch = getText("ContextMenu_Amputate_Stitch")
|
||||
local textAmpStitchBandage = getText("ContextMenu_Amputate_Stitch_Bandage")
|
||||
|
||||
---Add the action to the queue
|
||||
---@param limbName string
|
||||
---@param surgeon IsoPlayer
|
||||
---@param patient IsoPlayer
|
||||
---@param sawItem InventoryItem
|
||||
---@param stitchesItem InventoryItem?
|
||||
---@param bandageItem InventoryItem?
|
||||
local function PerformAction(surgeon, patient, limbName, sawItem, stitchesItem, bandageItem)
|
||||
|
||||
|
||||
local x = (getCore():getScreenWidth() - 500) / 2
|
||||
local y = getCore():getScreenHeight() / 2
|
||||
|
||||
|
||||
ConfirmationPanel.Open(textConfirmAmp, x, y, nil, function()
|
||||
|
||||
-- get saw in hand
|
||||
-- todo primary or secondary depending on amputation status of surgeon
|
||||
ISTimedActionQueue.add(ISEquipWeaponAction:new(surgeon, sawItem, 50, true, false))
|
||||
|
||||
local lHandItem = surgeon:getSecondaryHandItem()
|
||||
if lHandItem then
|
||||
ISTimedActionQueue.add(ISUnequipAction:new(surgeon, lHandItem, 50))
|
||||
end
|
||||
|
||||
|
||||
ISTimedActionQueue.add(CutLimbAction:new(surgeon, patient, limbName, sawItem, stitchesItem, bandageItem))
|
||||
|
||||
end)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
---Adds the actions to the inventory context menu
|
||||
---@param player IsoPlayer
|
||||
---@param context ISContextMenu
|
||||
---@param sawItem InventoryItem
|
||||
---@param stitchesItem InventoryItem?
|
||||
---@param bandageItem InventoryItem?
|
||||
local function AddInvAmputationOptions(player, context, sawItem, stitchesItem, bandageItem)
|
||||
local text
|
||||
|
||||
-- Set the correct text option
|
||||
if stitchesItem and bandageItem then
|
||||
--TOC_DEBUG.print("stitches and bandage")
|
||||
text = textAmpStitchBandage
|
||||
elseif not bandageItem and stitchesItem then
|
||||
--TOC_DEBUG.print("only stitches")
|
||||
text = textAmpStitch
|
||||
elseif not stitchesItem and bandageItem then
|
||||
--TOC_DEBUG.print("only bandages")
|
||||
text = textAmpBandage
|
||||
else
|
||||
text = textAmp
|
||||
end
|
||||
|
||||
TOC_DEBUG.print("Current text " .. tostring(text))
|
||||
local option = context:addOption(text, nil)
|
||||
local subMenu = context:getNew(context)
|
||||
context:addSubMenu(option, subMenu)
|
||||
|
||||
|
||||
|
||||
-- TODO Separate into groups
|
||||
|
||||
|
||||
-- Amputate -> Top/Bottom - > Left/Right - > Limb
|
||||
-- for i=1, #StaticData.PROSTHESES_GROUPS_STR do
|
||||
-- local group = StaticData.PROSTHESES_GROUPS_STR[i]
|
||||
|
||||
-- for j=1, #StaticData.SIDES_IND_STR do
|
||||
|
||||
-- end
|
||||
|
||||
-- end
|
||||
|
||||
-- for k,v in pairs(StaticData.LIMBS_TO_PROST_GROUP_MATCH_IND_STR) do
|
||||
-- TOC_DEBUG.print(k)
|
||||
|
||||
-- end
|
||||
|
||||
|
||||
local dc = DataController.GetInstance()
|
||||
for i = 1, #StaticData.LIMBS_STR do
|
||||
local limbName = StaticData.LIMBS_STR[i]
|
||||
if not dc:getIsCut(limbName) then
|
||||
local limbTranslatedName = getText("ContextMenu_Limb_" .. limbName)
|
||||
subMenu:addOption(limbTranslatedName, player, PerformAction, player, limbName, sawItem, stitchesItem, bandageItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Handler for OnFillInventoryObjectContextMenu
|
||||
---@param playerNum number
|
||||
---@param context ISContextMenu
|
||||
---@param items table
|
||||
local function AddInventoryAmputationMenu(playerNum, context, items)
|
||||
local item
|
||||
|
||||
-- We can't access the item if we don't create the loop and start ipairs.
|
||||
for _, v in ipairs(items) do
|
||||
item = v
|
||||
if not instanceof(v, "InventoryItem") then
|
||||
item = v.items[1]
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
local itemType = item:getType()
|
||||
if CheckIfSaw(itemType) then
|
||||
local player = getSpecificPlayer(playerNum)
|
||||
local sawItem = item
|
||||
local stitchesItem = GetStitchesConsumableItem(player)
|
||||
local bandageItem = GetBandageItem(player)
|
||||
|
||||
TOC_DEBUG.print("Stitches item: " .. tostring(stitchesItem))
|
||||
TOC_DEBUG.print("Bandage item: " .. tostring(bandageItem))
|
||||
|
||||
AddInvAmputationOptions(player, context, sawItem, stitchesItem, bandageItem)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Events.OnFillInventoryObjectContextMenu.Add(AddInventoryAmputationMenu)
|
||||
|
||||
-------------------------------------
|
||||
|
||||
---@class CutLimbInteractionHandler : BaseHandler
|
||||
---@field items table
|
||||
---@field limbName string
|
||||
---@field itemType string temporary
|
||||
local CutLimbInteractionHandler = BaseHandler:derive("CutLimbInteractionHandler")
|
||||
|
||||
|
||||
---Creates new CutLimbInteractionHandler
|
||||
---@param panel ISUIElement
|
||||
---@param bodyPart BodyPart
|
||||
---@return CutLimbInteractionHandler
|
||||
function CutLimbInteractionHandler:new(panel, bodyPart)
|
||||
local o = BaseHandler.new(self, panel, bodyPart)
|
||||
o.items.ITEMS = {}
|
||||
o.limbName = BodyPartType.ToString(bodyPart:getType())
|
||||
o.itemType = "Saw"
|
||||
--TOC_DEBUG.print("init CutLimbInteractionHandler")
|
||||
return o
|
||||
end
|
||||
|
||||
---@param item InventoryItem
|
||||
function CutLimbInteractionHandler:checkItem(item)
|
||||
--TOC_DEBUG.print("CutLimbInteractionHandler checkItem")
|
||||
local itemType = item:getType()
|
||||
|
||||
if CheckIfSaw(itemType) then
|
||||
TOC_DEBUG.print("added to list -> " .. itemType)
|
||||
self:addItem(self.items.ITEMS, item)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param type any
|
||||
function CutLimbInteractionHandler:openConfirmation(x, y, type)
|
||||
ConfirmationPanel.Open(textConfirmAmp, x, y, nil, function()
|
||||
self.onMenuOptionSelected(self, type)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param context ISContextMenu
|
||||
function CutLimbInteractionHandler:addToMenu(context)
|
||||
--TOC_DEBUG.print("CutLimbInteractionHandler addToMenu")
|
||||
local types = self:getAllItemTypes(self.items.ITEMS)
|
||||
local patientUsername = self:getPatient():getUsername()
|
||||
if #types > 0 and StaticData.LIMBS_TO_BODYLOCS_IND_BPT[self.limbName] and not DataController.GetInstance(patientUsername):getIsCut(self.limbName) then
|
||||
TOC_DEBUG.print("addToMenu, types > 0")
|
||||
|
||||
local x = (getCore():getScreenWidth() - 500) / 2
|
||||
local y = getCore():getScreenHeight() / 2
|
||||
|
||||
for i=1, #types do
|
||||
context:addOption(getText("ContextMenu_Amputate"), self, self.openConfirmation, x, y, types[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CutLimbInteractionHandler:dropItems(items)
|
||||
local types = self:getAllItemTypes(items)
|
||||
if #self.items.ITEMS > 0 and #types == 1 and StaticData.LIMBS_TO_BODYLOCS_IND_BPT[self.limbName] then
|
||||
self:onMenuOptionSelected(types[1])
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---Check if CutLimbInteractionHandler is valid, the limb must not be cut to be valid
|
||||
---@return boolean
|
||||
function CutLimbInteractionHandler:isValid()
|
||||
--TOC_DEBUG.print("CutLimbInteractionHandler isValid")
|
||||
self:checkItems()
|
||||
local patientUsername = self:getPatient():getUsername()
|
||||
return not DataController.GetInstance(patientUsername):getIsCut(self.limbName)
|
||||
end
|
||||
|
||||
function CutLimbInteractionHandler:perform(previousAction, itemType)
|
||||
local item = self:getItemOfType(self.items.ITEMS, itemType)
|
||||
previousAction = self:toPlayerInventory(item, previousAction)
|
||||
TOC_DEBUG.print("Perform CutLimbInteractionHandler on " .. self.limbName)
|
||||
local action = CutLimbAction:new(self:getDoctor(),self:getPatient(), self.limbName, item)
|
||||
ISTimedActionQueue.addAfter(previousAction, action)
|
||||
end
|
||||
|
||||
return CutLimbInteractionHandler
|
||||
@@ -0,0 +1,139 @@
|
||||
-- Had to copy and paste this stuff from the base game since this is a local only class. Kinda shit, but eh
|
||||
|
||||
---@class BaseHandler : ISBaseObject
|
||||
---@field panel ISUIElement
|
||||
---@field bodyPart BodyPart
|
||||
---@field items table
|
||||
local BaseHandler = ISBaseObject:derive("BaseHandler")
|
||||
|
||||
---@param panel ISUIElement
|
||||
---@param bodyPart BodyPart
|
||||
---@return table
|
||||
function BaseHandler:new(panel, bodyPart)
|
||||
local o = {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
o.panel = panel
|
||||
o.bodyPart = bodyPart
|
||||
o.items = {}
|
||||
return o
|
||||
end
|
||||
|
||||
function BaseHandler:isInjured()
|
||||
TOC_DEBUG.print("Running isInjured")
|
||||
local bodyPart = self.bodyPart
|
||||
return (bodyPart:HasInjury() or bodyPart:stitched() or bodyPart:getSplintFactor() > 0) and not bodyPart:bandaged()
|
||||
end
|
||||
|
||||
function BaseHandler:checkItems()
|
||||
for k,v in pairs(self.items) do
|
||||
table.wipe(v)
|
||||
end
|
||||
|
||||
local containers = ISInventoryPaneContextMenu.getContainers(self:getDoctor())
|
||||
local done = {}
|
||||
local childContainers = {}
|
||||
for i=1,containers:size() do
|
||||
local container = containers:get(i-1)
|
||||
done[container] = true
|
||||
table.wipe(childContainers)
|
||||
self:checkContainerItems(container, childContainers)
|
||||
for _,container2 in ipairs(childContainers) do
|
||||
if not done[container2] then
|
||||
done[container2] = true
|
||||
self:checkContainerItems(container2, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BaseHandler:checkContainerItems(container, childContainers)
|
||||
local containerItems = container:getItems()
|
||||
for i=1,containerItems:size() do
|
||||
local item = containerItems:get(i-1)
|
||||
if item:IsInventoryContainer() then
|
||||
if childContainers then
|
||||
table.insert(childContainers, item:getInventory())
|
||||
end
|
||||
else
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
self:checkItem(item) -- This is in inherited classes, we never use this class by itself
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BaseHandler:dropItems(items)
|
||||
return false
|
||||
end
|
||||
|
||||
function BaseHandler:addItem(items, item)
|
||||
table.insert(items, item)
|
||||
end
|
||||
|
||||
function BaseHandler:getAllItemTypes(items)
|
||||
local done = {}
|
||||
local types = {}
|
||||
for _,item in ipairs(items) do
|
||||
if not done[item:getFullType()] then
|
||||
table.insert(types, item:getFullType())
|
||||
done[item:getFullType()] = true
|
||||
end
|
||||
end
|
||||
return types
|
||||
end
|
||||
|
||||
function BaseHandler:getItemOfType(items, type)
|
||||
for _,item in ipairs(items) do
|
||||
if item:getFullType() == type then
|
||||
return item
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function BaseHandler:getItemOfTag(items, type)
|
||||
for _,item in ipairs(items) do
|
||||
if item:hasTag(type) then
|
||||
return item
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function BaseHandler:getAllItemsOfType(items, type)
|
||||
local items = {}
|
||||
for _,item in ipairs(items) do
|
||||
if item:getFullType() == type then
|
||||
table.insert(items, item)
|
||||
end
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
function BaseHandler:onMenuOptionSelected(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
||||
ISTimedActionQueue.add(HealthPanelAction:new(self:getDoctor(), self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8))
|
||||
end
|
||||
|
||||
function BaseHandler:toPlayerInventory(item, previousAction)
|
||||
if item:getContainer() ~= self:getDoctor():getInventory() then
|
||||
local action = ISInventoryTransferAction:new(self:getDoctor(), item, item:getContainer(), self:getDoctor():getInventory())
|
||||
ISTimedActionQueue.addAfter(previousAction, action)
|
||||
-- FIXME: ISHealthPanel.actions never gets cleared
|
||||
self.panel.actions = self.panel.actions or {}
|
||||
self.panel.actions[action] = self.bodyPart
|
||||
return action
|
||||
end
|
||||
return previousAction
|
||||
end
|
||||
|
||||
---@return IsoPlayer
|
||||
function BaseHandler:getDoctor()
|
||||
return self.panel.otherPlayer or self.panel.character
|
||||
end
|
||||
|
||||
---@return IsoPlayer
|
||||
function BaseHandler:getPatient()
|
||||
return self.panel.character
|
||||
end
|
||||
|
||||
return BaseHandler
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
local BaseHandler = require("TOC/UI/Interactions/HealthPanelBaseHandler")
|
||||
local CommonMethods = require("TOC/CommonMethods")
|
||||
local DataController = require("TOC/Controllers/DataController")
|
||||
|
||||
local CleanWoundAction = require("TOC/TimedActions/CleanWoundAction")
|
||||
-------------------------
|
||||
---@class WoundCleaningInteractionHandler : BaseHandler
|
||||
---@field username string
|
||||
---@field limbName string
|
||||
local WoundCleaningInteractionHandler = BaseHandler:derive("WoundCleaningInteractionHandler")
|
||||
|
||||
---@param panel any
|
||||
---@param bodyPart any
|
||||
---@param username string
|
||||
---@return table
|
||||
function WoundCleaningInteractionHandler:new(panel, bodyPart, username)
|
||||
local o = BaseHandler.new(self, panel, bodyPart)
|
||||
o.items.ITEMS = {}
|
||||
o.username = username
|
||||
|
||||
o.limbName = CommonMethods.GetLimbNameFromBodyPart(bodyPart)
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
function WoundCleaningInteractionHandler:checkItem(item)
|
||||
-- Disinfected rag or bandage
|
||||
--TOC_DEBUG.print("WoundCleaningInteractionHandler checkItem")
|
||||
if item:getBandagePower() >=2 and item:isAlcoholic() then
|
||||
--TOC_DEBUG.print("Adding " .. item:getName())
|
||||
self:addItem(self.items.ITEMS, item)
|
||||
end
|
||||
end
|
||||
|
||||
function WoundCleaningInteractionHandler:addToMenu(context)
|
||||
--TOC_DEBUG.print("WoundCleaningInteraction addToMenu")
|
||||
|
||||
local types = self:getAllItemTypes(self.items.ITEMS)
|
||||
if #types > 0 and self:isValid() then
|
||||
TOC_DEBUG.print("WoundCleaningInteraction inside addToMenu")
|
||||
local option = context:addOption(getText("ContextMenu_CleanWound"), nil)
|
||||
local subMenu = context:getNew(context)
|
||||
context:addSubMenu(option, subMenu)
|
||||
for i=1, #types do
|
||||
local item = self:getItemOfType(self.items.ITEMS, types[i])
|
||||
subMenu:addOption(item:getName(), self, self.onMenuOptionSelected, item:getFullType())
|
||||
TOC_DEBUG.print(item:getName())
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function WoundCleaningInteractionHandler:dropItems(items)
|
||||
local types = self:getAllItemTypes(items)
|
||||
if #self.items.ITEMS > 0 and #types == 1 and self:isActionValid() then
|
||||
self:onMenuOptionSelected(types[1])
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function WoundCleaningInteractionHandler:isValid()
|
||||
self:checkItems()
|
||||
return self:isActionValid()
|
||||
end
|
||||
|
||||
function WoundCleaningInteractionHandler:isActionValid()
|
||||
if self.limbName == nil then return false end
|
||||
local dcInst = DataController.GetInstance(self.username)
|
||||
local check = dcInst:getIsCut(self.limbName) and not dcInst:getIsCicatrized(self.limbName) and dcInst:getWoundDirtyness(self.limbName) > 0
|
||||
--TOC_DEBUG.print("WoundCleaningInteraction isValid: " .. tostring(check))
|
||||
return check
|
||||
end
|
||||
|
||||
function WoundCleaningInteractionHandler:perform(previousAction, itemType)
|
||||
local item = self:getItemOfType(self.items.ITEMS, itemType)
|
||||
previousAction = self:toPlayerInventory(item, previousAction)
|
||||
local action = CleanWoundAction:new(self:getDoctor(), self:getPatient(), item, self.bodyPart)
|
||||
ISTimedActionQueue.addAfter(previousAction, action)
|
||||
end
|
||||
|
||||
|
||||
return WoundCleaningInteractionHandler
|
||||
98
common/media/lua/client/TOC/UI/SurgeryInteractions.lua
Normal file
98
common/media/lua/client/TOC/UI/SurgeryInteractions.lua
Normal file
@@ -0,0 +1,98 @@
|
||||
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
|
||||
local DataController = require("TOC/Controllers/DataController")
|
||||
local CauterizeAction = require("TOC/TimedActions/CauterizeAction")
|
||||
---------------
|
||||
|
||||
|
||||
---@param tooltip ISToolTip
|
||||
---@param desc string
|
||||
local function AppendToDescription(tooltip, desc)
|
||||
if tooltip.description == "" then
|
||||
desc = string.upper(string.sub(desc, 1, 1)) .. string.sub(desc, 2)
|
||||
tooltip.description = desc
|
||||
else
|
||||
desc = string.lower(string.sub(desc, 1, 1)) .. string.sub(desc, 2)
|
||||
tooltip.description = tooltip.description .. getText("Tooltip_Surgery_And") .. desc
|
||||
end
|
||||
end
|
||||
|
||||
---@param playerNum number
|
||||
---@param context ISContextMenu
|
||||
---@param worldObjects any
|
||||
---@param test any
|
||||
local function AddStoveContextMenu(playerNum, context, worldObjects, test)
|
||||
if test then return true end
|
||||
|
||||
local pl = getSpecificPlayer(playerNum)
|
||||
|
||||
local dcInst = DataController.GetInstance()
|
||||
if not dcInst:getIsAnyLimbCut() then return end
|
||||
local amputatedLimbs = CachedDataHandler.GetAmputatedLimbs(pl:getUsername())
|
||||
|
||||
---@type IsoStove?
|
||||
local stoveObj = nil
|
||||
for _, obj in pairs(worldObjects) do
|
||||
if instanceof(obj, "IsoStove") then
|
||||
stoveObj = obj
|
||||
break
|
||||
end
|
||||
end
|
||||
if stoveObj == nil then return end
|
||||
local tempTooltip = ISToolTip:new()
|
||||
tempTooltip:initialise()
|
||||
tempTooltip.description = ""
|
||||
tempTooltip:setVisible(false)
|
||||
|
||||
local addMainOption = false
|
||||
local subMenu
|
||||
|
||||
for k, _ in pairs(amputatedLimbs) do
|
||||
|
||||
-- We need to let the player cauterize ONLY the visible one!
|
||||
---@type string
|
||||
local limbName = k
|
||||
if dcInst:getIsVisible(limbName) and not dcInst:getIsCicatrized(limbName) then
|
||||
if addMainOption == false then
|
||||
-- Adds the cauterize option ONLY when it's needed
|
||||
local optionMain = context:addOption(getText("ContextMenu_Cauterize"), nil)
|
||||
subMenu = context:getNew(context)
|
||||
context:addSubMenu(optionMain, subMenu)
|
||||
addMainOption = true
|
||||
end
|
||||
|
||||
local option = subMenu:addOption(getText("ContextMenu_Limb_" .. limbName), nil, function()
|
||||
local adjacent = AdjacentFreeTileFinder.Find(stoveObj:getSquare(), pl)
|
||||
ISTimedActionQueue.add(ISWalkToTimedAction:new(pl, adjacent))
|
||||
ISTimedActionQueue.add(CauterizeAction:new(pl, limbName, stoveObj))
|
||||
end)
|
||||
|
||||
|
||||
-- Notifications, in case the player can't do the action
|
||||
local isPlayerCourageous = pl:HasTrait("Brave") or pl:getPerkLevel(Perks.Strength) > 5
|
||||
local isTempHighEnough = stoveObj:getCurrentTemperature() >= 250
|
||||
local isLimbFree = not dcInst:getIsProstEquipped(limbName)
|
||||
|
||||
option.notAvailable = not(isPlayerCourageous and isTempHighEnough and isLimbFree)
|
||||
if not isTempHighEnough then
|
||||
AppendToDescription(tempTooltip, getText("Tooltip_Surgery_TempTooLow"))
|
||||
end
|
||||
|
||||
if not isPlayerCourageous then
|
||||
AppendToDescription(tempTooltip, getText("Tooltip_Surgery_Coward"))
|
||||
end
|
||||
|
||||
if not isLimbFree then
|
||||
AppendToDescription(tempTooltip, getText("Tooltip_Surgery_LimbNotFree"))
|
||||
end
|
||||
|
||||
if option.notAvailable then
|
||||
tempTooltip:setName(getText("Tooltip_Surgery_CantCauterize"))
|
||||
option.toolTip = tempTooltip
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Events.OnFillWorldObjectContextMenu.Add(AddStoveContextMenu)
|
||||
Reference in New Issue
Block a user