Redoing user experience
This commit is contained in:
0
media/lua/client/TOC_Debug.lua
Normal file
0
media/lua/client/TOC_Debug.lua
Normal file
128
media/lua/client/TOC_HealthPanelBaseHandler.lua
Normal file
128
media/lua/client/TOC_HealthPanelBaseHandler.lua
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
-- Had to cop and paste this stuff from the base game since this is a local only class. Kinda shit, but eh
|
||||||
|
|
||||||
|
local BaseHandler = ISBaseObject:derive("BaseHandler")
|
||||||
|
|
||||||
|
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()
|
||||||
|
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
|
||||||
|
self:checkItem(item)
|
||||||
|
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
|
||||||
|
|
||||||
|
function BaseHandler:getDoctor()
|
||||||
|
return self.panel.otherPlayer or self.panel.character
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseHandler:getPatient()
|
||||||
|
return self.panel.character
|
||||||
|
end
|
||||||
|
|
||||||
|
return BaseHandler
|
||||||
@@ -22,6 +22,7 @@ function Main.SetupTraits()
|
|||||||
|
|
||||||
for i=1, #traitsTable do
|
for i=1, #traitsTable do
|
||||||
local t = traitsTable[i]
|
local t = traitsTable[i]
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
t:addXPBoost(Perks.Left_Hand, 4)
|
t:addXPBoost(Perks.Left_Hand, 4)
|
||||||
t:addXPBoost(Perks.Fitness, -1)
|
t:addXPBoost(Perks.Fitness, -1)
|
||||||
t:addXPBoost(Perks.Strength, -1)
|
t:addXPBoost(Perks.Strength, -1)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ function ModDataHandler:new(playerObj)
|
|||||||
self.__index = self
|
self.__index = self
|
||||||
|
|
||||||
o.playerObj = playerObj
|
o.playerObj = playerObj
|
||||||
|
|
||||||
ModDataHandler.instance = o
|
ModDataHandler.instance = o
|
||||||
|
|
||||||
return o
|
return o
|
||||||
@@ -25,7 +26,8 @@ end
|
|||||||
|
|
||||||
---Setup a newly instanced ModDataHandler
|
---Setup a newly instanced ModDataHandler
|
||||||
function ModDataHandler:setup()
|
function ModDataHandler:setup()
|
||||||
if self.modData == nil then self:createData() end
|
local modData = self.playerObj:getModData()[StaticData.MOD_NAME]
|
||||||
|
if modData == nil then self:createData() end
|
||||||
-- TODO Check compatibility or do we just skip it at this point?
|
-- TODO Check compatibility or do we just skip it at this point?
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -35,27 +37,62 @@ function ModDataHandler:createData()
|
|||||||
|
|
||||||
self.playerObj:getModData()[StaticData.MOD_NAME] = {}
|
self.playerObj:getModData()[StaticData.MOD_NAME] = {}
|
||||||
|
|
||||||
|
---@type amputationTable
|
||||||
|
local defaultParams = {isCut = false, isInfected = false, isOperated = false, isCicatrized = false, isCauterized = false, isDependant = false}
|
||||||
|
|
||||||
-- Initialize limbs
|
-- Initialize limbs
|
||||||
for i=1, #StaticData.LIMBS_STRINGS do
|
for i=1, #StaticData.LIMBS_STRINGS do
|
||||||
self:setLimbParams(StaticData.LIMBS_STRINGS[i], false, false, false, false, false, false)
|
self:setLimbParams(StaticData.LIMBS_STRINGS[i], defaultParams, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
--* Setters *--
|
||||||
|
|
||||||
|
---Set isCut
|
||||||
|
---@param limbName string
|
||||||
|
---@param isCut boolean
|
||||||
|
function ModDataHandler:setIsCut(limbName, isCut)
|
||||||
|
self.playerObj:getModData()[StaticData.MOD_NAME][limbName].isCut = isCut
|
||||||
|
end
|
||||||
|
|
||||||
|
---Set isInfected
|
||||||
|
---@param limbName string
|
||||||
|
---@param isInfected boolean
|
||||||
|
function ModDataHandler:setIsInfected(limbName, isInfected)
|
||||||
|
self.playerObj:getModData()[StaticData.MOD_NAME][limbName].isInfected = isInfected
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
--* Getters *--
|
||||||
|
---Get isCut
|
||||||
|
---@param limbName string
|
||||||
|
---@return boolean
|
||||||
|
function ModDataHandler:getIsCut(limbName)
|
||||||
|
return self.playerObj:getModData()[StaticData.MOD_NAME][limbName].isCut
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--* Limbs data handling *--
|
--* Limbs data handling *--
|
||||||
|
|
||||||
---Set a limb and its dependend limbs as cut
|
---Set a limb and its dependend limbs as cut
|
||||||
---@param limbName string
|
---@param limbName string
|
||||||
---@param ampStatus amputationTable {isOperated, isCicatrized, isCauterized}
|
---@param isOperated boolean
|
||||||
---@param surgeonFactor number
|
---@param isCicatrized boolean
|
||||||
function ModDataHandler:setCutLimb(limbName, ampStatus, surgeonFactor)
|
---@param isCauterized boolean
|
||||||
local cicatrizationTime = -1
|
---@param surgeonFactor number?
|
||||||
if ampStatus.isCicatrized == false or ampStatus.isCauterized == false then
|
function ModDataHandler:setCutLimb(limbName, isOperated, isCicatrized, isCauterized, surgeonFactor)
|
||||||
|
local cicatrizationTime = 0
|
||||||
|
if isCicatrized == false or isCauterized == false then
|
||||||
cicatrizationTime = StaticData.LIMBS_CICATRIZATION_TIME[limbName] - surgeonFactor
|
cicatrizationTime = StaticData.LIMBS_CICATRIZATION_TIME[limbName] - surgeonFactor
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type amputationTable
|
---@type amputationTable
|
||||||
local params = {isCut = true, isInfected = false, isOperated = ampStatus.isOperated, isCicatrized = ampStatus.isCicatrized, isCauterized = ampStatus.isCauterized, isDependant = false}
|
local params = {isCut = true, isInfected = false, isOperated = isOperated, isCicatrized = isCicatrized, isCauterized = isCauterized, isDependant = false}
|
||||||
self:setLimbParams(limbName, params, cicatrizationTime)
|
self:setLimbParams(limbName, params, cicatrizationTime)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ function PlayerHandler.CutLimb(patient, surgeon, limbName, surgeryHelpItems)
|
|||||||
|
|
||||||
-- TODO Get surgeon ability from his aid skill
|
-- TODO Get surgeon ability from his aid skill
|
||||||
local surgeonSkill = 50
|
local surgeonSkill = 50
|
||||||
|
local surgeonFactor = surgeonSkill - 1 -- TODO Should be decided by surgeryHelpItems
|
||||||
|
|
||||||
local bd = patient:getBodyDamage()
|
local bd = patient:getBodyDamage()
|
||||||
local bodyPart = bd:getBodyPart(BodyPartType[limbName])
|
local bodyPart = bd:getBodyPart(BodyPartType[limbName])
|
||||||
@@ -56,9 +57,7 @@ function PlayerHandler.CutLimb(patient, surgeon, limbName, surgeryHelpItems)
|
|||||||
patientStats:setEndurance(surgeonSkill)
|
patientStats:setEndurance(surgeonSkill)
|
||||||
patientStats:setStress(baseDamage - surgeonSkill)
|
patientStats:setStress(baseDamage - surgeonSkill)
|
||||||
|
|
||||||
---@type amputationTable
|
PlayerHandler.modDataHandler:setCutLimb(limbName, false, false, false, surgeonFactor)
|
||||||
local amputationValues = {isOperated = false, isCicatrized = false, isCauterized = false}
|
|
||||||
PlayerHandler.modDataHandler:setCutLimb(limbName, amputationValues)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -70,4 +69,36 @@ function PlayerHandler.ForceCutLimb(limbName)
|
|||||||
-- TODO Spawn amputation item
|
-- TODO Spawn amputation item
|
||||||
end
|
end
|
||||||
|
|
||||||
return PlayerHandler
|
|
||||||
|
|
||||||
|
--* Events *--
|
||||||
|
|
||||||
|
---Check if the player has an infected (as in, zombie infection) body part
|
||||||
|
---@param character IsoGameCharacter
|
||||||
|
---@param damageType string
|
||||||
|
---@param damage number
|
||||||
|
function PlayerHandler.CheckInfection(character, damageType, damage)
|
||||||
|
|
||||||
|
-- This fucking event barely works. Bleeding seems to be the only thing that triggers it
|
||||||
|
-- TODO Check other body parts that are not included in the mod, if there's a bite there then the player is fucked
|
||||||
|
local bd = character:getBodyDamage()
|
||||||
|
|
||||||
|
for i=1, #StaticData.LIMBS_STRINGS do
|
||||||
|
local limbName = StaticData.LIMBS_STRINGS[i]
|
||||||
|
local bptEnum = StaticData.BODYPARTSTYPES_ENUM[limbName]
|
||||||
|
local bodyPart = bd:getBodyPart(bptEnum)
|
||||||
|
|
||||||
|
if bodyPart:bitten() then
|
||||||
|
if PlayerHandler.modDataHandler:getIsCut(limbName) then
|
||||||
|
bodyPart:SetBitten(false)
|
||||||
|
else
|
||||||
|
PlayerHandler.modDataHandler:setIsInfected(limbName, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
Events.OnPlayerGetDamage.Add(PlayerHandler.CheckInfection)
|
||||||
|
|
||||||
|
return PlayerHandler
|
||||||
@@ -16,6 +16,7 @@ StaticData.SIDES_STRINGS = {
|
|||||||
-- Assembled BodyParts string
|
-- Assembled BodyParts string
|
||||||
---@enum
|
---@enum
|
||||||
StaticData.LIMBS_STRINGS = {}
|
StaticData.LIMBS_STRINGS = {}
|
||||||
|
StaticData.BODYPARTSTYPES_ENUM = {}
|
||||||
StaticData.LIMBS_DEPENDENCIES = {}
|
StaticData.LIMBS_DEPENDENCIES = {}
|
||||||
StaticData.LIMBS_CICATRIZATION_TIME = {}
|
StaticData.LIMBS_CICATRIZATION_TIME = {}
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ for i = 1, #StaticData.SIDES_STRINGS do
|
|||||||
|
|
||||||
-- Assembled strings
|
-- Assembled strings
|
||||||
StaticData.LIMBS_STRINGS[assembledName] = assembledName
|
StaticData.LIMBS_STRINGS[assembledName] = assembledName
|
||||||
|
StaticData.BODYPARTSTYPES_ENUM[assembledName] = BodyPartType[assembledName]
|
||||||
|
|
||||||
-- Dependencies and cicatrization time
|
-- Dependencies and cicatrization time
|
||||||
if part == StaticData.PARTS_STRINGS.Hand then
|
if part == StaticData.PARTS_STRINGS.Hand then
|
||||||
|
|||||||
56
media/lua/client/TOC_UI.lua
Normal file
56
media/lua/client/TOC_UI.lua
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
local CutLimbHandler = require("TOC_UIHandler")
|
||||||
|
|
||||||
|
-- TODO Use this to replace the sprites once a limb is cut
|
||||||
|
ISHealthBodyPartPanel = ISBodyPartPanel:derive("ISHealthBodyPartPanel")
|
||||||
|
|
||||||
|
function ISHealthBodyPartPanel:onMouseUp(x, y)
|
||||||
|
if self.selectedBp then
|
||||||
|
local dragging = ISInventoryPane.getActualItems(ISMouseDrag.dragging)
|
||||||
|
self.parent:dropItemsOnBodyPart(self.selectedBp.bodyPart, dragging)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ISHealthBodyPartPanel:prerender()
|
||||||
|
self.nodeAlpha = 0.0
|
||||||
|
self.selectedAlpha = 0.1
|
||||||
|
if self.selectedBp then
|
||||||
|
for index,item in ipairs(self.parent.listbox.items) do
|
||||||
|
if item.item.bodyPart == self.selectedBp.bodyPart then
|
||||||
|
self.nodeAlpha = 1.0
|
||||||
|
self.selectedAlpha = 0.5
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ISBodyPartPanel.prerender(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ISHealthBodyPartPanel:cbSetSelected(bp)
|
||||||
|
if bp == nil then
|
||||||
|
self.parent.listbox.selected = 0
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for index,item in ipairs(self.parent.listbox.items) do
|
||||||
|
if item.item.bodyPart == bp.bodyPart then
|
||||||
|
self.parent.listbox.selected = index
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local og_ISHealthPanel_dropItemsOnBodyPart = ISHealthPanel.dropItemsOnBodyPart
|
||||||
|
|
||||||
|
function ISHealthPanel:dropItemsOnBodyPart(bodyPart, items)
|
||||||
|
og_ISHealthPanel_dropItemsOnBodyPart(self, bodyPart, items)
|
||||||
|
local cutLimbHandler = CutLimbHandler:new(self, bodyPart)
|
||||||
|
|
||||||
|
for _,item in ipairs(items) do
|
||||||
|
cutLimbHandler:checkItem(item)
|
||||||
|
end
|
||||||
|
|
||||||
|
if cutLimbHandler:dropItems(items) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
62
media/lua/client/TOC_UIHandler.lua
Normal file
62
media/lua/client/TOC_UIHandler.lua
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
local BaseHandler = require("TOC_HealthPanelBaseHandler")
|
||||||
|
local CutLimbAction = require("TOC_CutLimbAction")
|
||||||
|
|
||||||
|
---@class CutLimbHandler
|
||||||
|
local CutLimbHandler = BaseHandler:derive("CutLimbHandler")
|
||||||
|
|
||||||
|
|
||||||
|
local contextMenuCutLimb = "Cut"
|
||||||
|
|
||||||
|
---Creates new CutLimbHandler
|
||||||
|
---@param panel any
|
||||||
|
---@param bodyPart any
|
||||||
|
---@return CutLimbHandler
|
||||||
|
function CutLimbHandler:new(panel, bodyPart)
|
||||||
|
local o = BaseHandler.new(self, panel, bodyPart)
|
||||||
|
o.items.ITEMS = {}
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function CutLimbHandler:checkItem(item)
|
||||||
|
local itemType = item:getType()
|
||||||
|
if itemType == "Saw" or itemType == "GardenSaw" or itemType == "Chainsaw" then
|
||||||
|
self:addItem(self.items.ITEMS, item)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function CutLimbHandler:addToMenu(context)
|
||||||
|
local types = self:getAllItemTypes(self.items.ITEMS)
|
||||||
|
if #types > 0 then
|
||||||
|
local option = context:addOption(contextMenuCutLimb, 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())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function CutLimbHandler:dropItems(items)
|
||||||
|
local types = self:getAllItemTypes(items)
|
||||||
|
if #self.items.ITEMS > 0 and #types == 1 then
|
||||||
|
self:onMenuOptionSelected(types[1])
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function CutLimbHandler:isValid(itemType)
|
||||||
|
return self:isInjured() and self:getItemOfType(self.items.ITEMS, itemType)
|
||||||
|
end
|
||||||
|
|
||||||
|
function CutLimbHandler:perform(previousAction, itemType)
|
||||||
|
local item = self:getItemOfType(self.items.ITEMS, itemType)
|
||||||
|
previousAction = self:toPlayerInventory(item, previousAction)
|
||||||
|
|
||||||
|
local action = CutLimbAction:new(self:getPatient(), self:getDoctor(), self.bodyPart)
|
||||||
|
ISTimedActionQueue.addAfter(previousAction, action)
|
||||||
|
end
|
||||||
|
|
||||||
|
return CutLimbHandler
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
require "TimedActions/ISBaseTimedAction"
|
||||||
|
|
||||||
|
local CutLimbAction = ISBaseTimedAction:derive("CutLimbAction")
|
||||||
|
|
||||||
|
function CutLimbAction:new(patient, surgeon, partName)
|
||||||
|
|
||||||
|
end
|
||||||
|
return CutLimbAction
|
||||||
Reference in New Issue
Block a user