diff --git a/.vscode/settings.json b/.vscode/settings.json index d59bef0..206a0e1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -53,6 +53,7 @@ "FHSwapHandsAction", "getClassFieldVal", "SandboxVars", - "getClassField" + "getClassField", + "ISWearClothing" ] } \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index 2c4d610..e613ae7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +0.9.15 +- Hotfix to sound not stopping when performing an amputation on another player + 0.9.14 - Optimizations - New icon for the mod diff --git a/media/AnimSets/player/aim/aim_default.xml b/media/AnimSets/player/aim/aim_default.xml new file mode 100644 index 0000000..5806066 --- /dev/null +++ b/media/AnimSets/player/aim/aim_default.xml @@ -0,0 +1,37 @@ + + + aim_default + Bob_Sit_FishingIdle + 4 + Y + false + IdleSpeed + 0.30 + 70.0 + + IsCrawling + BOOL + true + + + Idle + Bob_Sit_FishingIdle + 0.3 + 0.3 + 1.2 + + + sneakIdle + Bob_Sit_FishingIdle + 0.3 + 0.3 + 1.2 + + + sneakIdleLow + Bob_Sit_FishingIdle + 0.3 + 0.3 + 1.2 + + \ No newline at end of file diff --git a/media/AnimSets/player/idle/NoLegs_Idle.xml b/media/AnimSets/player/idle/NoLegs_Idle.xml new file mode 100644 index 0000000..af32f14 --- /dev/null +++ b/media/AnimSets/player/idle/NoLegs_Idle.xml @@ -0,0 +1,24 @@ + + + NoLegs_Idle + Bob_Sit_FishingIdle + Translation_Data + Y + true + 0.8 + 0.20 + + IsCrawling + BOOL + true + + + NoLegs_IdleSneak + 0.1 + + + NoLegs_Idle + 0.35 + 0.35 + + diff --git a/media/AnimSets/player/idle/NoLegs_IdleSneak.xml b/media/AnimSets/player/idle/NoLegs_IdleSneak.xml new file mode 100644 index 0000000..9816218 --- /dev/null +++ b/media/AnimSets/player/idle/NoLegs_IdleSneak.xml @@ -0,0 +1,21 @@ + + + NoLegs_IdleSneak + Bob_ScrambleFloorIdle + true + Y + false + true + 0.8 + 0.20 + + IsCrawling + BOOL + true + + + sneaking + BOOL + true + + \ No newline at end of file diff --git a/media/AnimSets/player/movement/NoLegs_Walk.xml b/media/AnimSets/player/movement/NoLegs_Walk.xml new file mode 100644 index 0000000..d976510 --- /dev/null +++ b/media/AnimSets/player/movement/NoLegs_Walk.xml @@ -0,0 +1,24 @@ + + + NoLegs_Walk + Bob_Crawl + Y + true + 1.5 + 0.20 + + IsCrawling + BOOL + true + + + Footstep + 0.15 + walk + + + Footstep + 0.6 + walk + + diff --git a/media/AnimSets/player/movement/NoLegs_WalkSneak.xml b/media/AnimSets/player/movement/NoLegs_WalkSneak.xml new file mode 100644 index 0000000..f87d216 --- /dev/null +++ b/media/AnimSets/player/movement/NoLegs_WalkSneak.xml @@ -0,0 +1,34 @@ + + + NoLegs_WalkSneak + Zombie_CrawlUnder + Translation_Data + true + 1.5 + 0.20 + + IsCrawling + BOOL + true + + + sneaking + BOOL + true + + + inTrees + BOOL + false + + + Footstep + 0.15 + sneak_walk + + + Footstep + 0.6 + sneak_walk + + diff --git a/media/AnimSets/player/turning/NoLegs_Turn.xml b/media/AnimSets/player/turning/NoLegs_Turn.xml new file mode 100644 index 0000000..85c6024 --- /dev/null +++ b/media/AnimSets/player/turning/NoLegs_Turn.xml @@ -0,0 +1,61 @@ + + + NoLegs_Turn + Bip01 + Y + true + 0.80 + 0.10 + 0.20 + + IsCrawling + BOOL + true + + + + + isTurning + BOOL + true + + + Bip01_Pelvis + false + + + Bip01_Spine + false + + + Bip01_BackPack + + + Bip01_DressFront + + + Bip01_DressBack + + + Bip01_L_Thigh + + + Bip01_R_Thigh + + + Bip01 + false + + + Translation_Data + false + + + Bip01_Prop1 + 0.00 + + + Bip01_Prop2 + 0.00 + + \ No newline at end of file diff --git a/media/AnimSets/player/turning/NoLegs_TurnIdle.xml b/media/AnimSets/player/turning/NoLegs_TurnIdle.xml new file mode 100644 index 0000000..ebbe1ce --- /dev/null +++ b/media/AnimSets/player/turning/NoLegs_TurnIdle.xml @@ -0,0 +1,45 @@ + + + NoLegs_TurnIdle + false + true + 0.10 + + + IsCrawling + BOOL + true + + + + isMoving + BOOL + false + + + + + Aim + BOOL + false + + + Idle + 0.1 + + + + 0.25 + + + 0.20 + + + + + + + + + + \ No newline at end of file diff --git a/media/AnimSets/player/turning/NoLegs_TurnIdle180.xml b/media/AnimSets/player/turning/NoLegs_TurnIdle180.xml new file mode 100644 index 0000000..6515cb2 --- /dev/null +++ b/media/AnimSets/player/turning/NoLegs_TurnIdle180.xml @@ -0,0 +1,28 @@ + + + NoLegs_TurnIdle180 + + + + IsCrawling + BOOL + true + + + + isTurningAround + BOOL + true + + + + 0.00 + + + + + + + + + \ No newline at end of file diff --git a/media/AnimSets/player/turning/NoLegs_TurnIdle180L.xml b/media/AnimSets/player/turning/NoLegs_TurnIdle180L.xml new file mode 100644 index 0000000..6370623 --- /dev/null +++ b/media/AnimSets/player/turning/NoLegs_TurnIdle180L.xml @@ -0,0 +1,15 @@ + + + NoLegs_turnIdle180L + Bob_Crawl + + IsCrawling + BOOL + true + + + twist + LESS + 0 + + \ No newline at end of file diff --git a/media/AnimSets/player/turning/NoLegs_TurnIdle180R.xml b/media/AnimSets/player/turning/NoLegs_TurnIdle180R.xml new file mode 100644 index 0000000..d219ba7 --- /dev/null +++ b/media/AnimSets/player/turning/NoLegs_TurnIdle180R.xml @@ -0,0 +1,18 @@ + + + NoLegs_TurnIdle180R + Bob_EmoteWaveBye + + + + + IsCrawling + BOOL + true + + + twist + GTR + 0 + + \ No newline at end of file diff --git a/media/clothing/clothingItems/Amputation_Left_Foot.xml b/media/clothing/clothingItems/Amputation_Left_Foot.xml new file mode 100644 index 0000000..a1d237b --- /dev/null +++ b/media/clothing/clothingItems/Amputation_Left_Foot.xml @@ -0,0 +1,35 @@ + + + Amputation\Amputation_GenericModel + Amputation\Amputation_GenericModel + 506c0fc0-b50c-4667-bafa-ae22e3c2c0dc + false + false + false + 8 + none + + Amputations\Forearm\skin01_b + Amputations\Forearm\skin02_b + Amputations\Forearm\skin03_b + Amputations\Forearm\skin04_b + Amputations\Forearm\skin05_b + + Amputations\Forearm\skin01_hairy_b + Amputations\Forearm\skin02_hairy_b + Amputations\Forearm\skin03_hairy_b + Amputations\Forearm\skin04_hairy_b + Amputations\Forearm\skin05_hairy_b + + Body\MaleBody01 + Body\MaleBody02 + Body\MaleBody03 + Body\MaleBody04 + Body\MaleBody05 + + Body\MaleBody01a + Body\MaleBody02a + Body\MaleBody03a + Body\MaleBody04 + Body\MaleBody05a + \ No newline at end of file diff --git a/media/clothing/clothingItems/Amputation_Right_Foot.xml b/media/clothing/clothingItems/Amputation_Right_Foot.xml new file mode 100644 index 0000000..af3f9dc --- /dev/null +++ b/media/clothing/clothingItems/Amputation_Right_Foot.xml @@ -0,0 +1,35 @@ + + + Amputation\Amputation_GenericModel + Amputation\Amputation_GenericModel + 2600c2ab-bfeb-49c3-b0b5-e21c6d83d5c2 + false + false + false + 10 + none + + Amputations\Forearm\skin01_b + Amputations\Forearm\skin02_b + Amputations\Forearm\skin03_b + Amputations\Forearm\skin04_b + Amputations\Forearm\skin05_b + + Amputations\Forearm\skin01_hairy_b + Amputations\Forearm\skin02_hairy_b + Amputations\Forearm\skin03_hairy_b + Amputations\Forearm\skin04_hairy_b + Amputations\Forearm\skin05_hairy_b + + Body\MaleBody01 + Body\MaleBody02 + Body\MaleBody03 + Body\MaleBody04 + Body\MaleBody05 + + Body\MaleBody01a + Body\MaleBody02a + Body\MaleBody03a + Body\MaleBody04 + Body\MaleBody05a + \ No newline at end of file diff --git a/media/fileGuidTable.xml b/media/fileGuidTable.xml index c5a3932..a829229 100644 --- a/media/fileGuidTable.xml +++ b/media/fileGuidTable.xml @@ -85,4 +85,15 @@ media/clothing/clothingItems/Surgery_Right_Tourniquet.xml 9a5fe063-63c7-4e6f-81ca-ee77c6678e0d + + + media/clothing/clothingItems/Amputation_Left_Foot.xml + 506c0fc0-b50c-4667-bafa-ae22e3c2c0dc + + + + media/clothing/clothingItems/Amputation_Right_Foot.xml + 2600c2ab-bfeb-49c3-b0b5-e21c6d83d5c2 + + \ No newline at end of file diff --git a/media/lua/client/ActionsMethods/TOC_CutLimb.lua b/media/lua/client/ActionsMethods/TOC_CutLimb.lua index b90ed93..0d07300 100644 --- a/media/lua/client/ActionsMethods/TOC_CutLimb.lua +++ b/media/lua/client/ActionsMethods/TOC_CutLimb.lua @@ -11,7 +11,7 @@ local function TocCheckIfStillInfected(limbs_data) local check = false - for _, v in ipairs(GetBodyParts()) do + for _, v in pairs(GetBodyParts()) do if limbs_data[v].is_infected then check = true end @@ -37,8 +37,8 @@ local function TocCureInfection(body_damage, part_name) -- TODO I think this is enough... we should just cycle if with everything instead of that crap up there for i = body_part_types:size() - 1, 0, -1 do - local bodyPart = body_part_types:get(i); - bodyPart:SetInfected(false); + local bodyPart = body_part_types:get(i) + bodyPart:SetInfected(false) end if body_part_type:scratched() then body_part_type:setScratched(false, false) end @@ -104,7 +104,7 @@ local function FindTourniquetInWornItems(patient, side) for i = 1, worn_items:size() - 1 do -- Maybe wornItems:size()-1 local item = worn_items:get(i):getItem() local item_full_type = item:getFullType() - if string.find(item_full_type, "Test_Tourniquet_" .. side) then + if string.find(item_full_type, "Surgery_" .. side .. "_Tourniquet") then return item end end @@ -151,7 +151,7 @@ function TocCutLimb(part_name, surgeon_factor, bandage_table, painkiller_table) local base_damage_value = 100 if tourniquet_item ~= nil then - base_damage_value = 50 + base_damage_value = 50 -- TODO Decrease mostly blood and damage, add pain, not everything else if part_name == "Left_UpperArm" or part_name == "Right_UpperArm" then player:removeWornItem(tourniquet_item) @@ -240,13 +240,20 @@ function TocCutLimb(part_name, surgeon_factor, bandage_table, painkiller_table) TocDeleteOtherAmputatedLimbs(side) --Equip new model for amputation - local amputation_clothing_item = player:getInventory():AddItem(TocFindAmputatedClothingFromPartName(part_name)) + local amputation_clothing_item_name = TocFindAmputatedClothingFromPartName(part_name) + print(amputation_clothing_item_name) + + local amputation_clothing_item = player:getInventory():AddItem(amputation_clothing_item_name) TocSetCorrectTextureForAmputation(amputation_clothing_item, player, false) player:setWornItem(amputation_clothing_item:getBodyLocation(), amputation_clothing_item) -- Set blood on the amputated limb TocSetBloodOnAmputation(getPlayer(), adiacent_body_part) + + if part_name == "Left_Foot" or part_name == "Right_Foot" then + SetMissingFootAnimation(true) + end end end diff --git a/media/lua/client/ActionsMethods/TOC_OperateLimb.lua b/media/lua/client/ActionsMethods/TOC_OperateLimb.lua index 5379e83..8bd2e66 100644 --- a/media/lua/client/ActionsMethods/TOC_OperateLimb.lua +++ b/media/lua/client/ActionsMethods/TOC_OperateLimb.lua @@ -20,13 +20,10 @@ local function FixSingleBodyPartType(body_part_type, use_oven) end local function SetBodyPartsStatusAfterOperation(player, limbs_data, part_name, use_oven) - --for _, v in ipairs(GetBodyParts()) do - - local body_part_type = player:getBodyDamage():getBodyPart(TocGetAdiacentBodyPartFromPartName(part_name)) FixSingleBodyPartType(body_part_type, use_oven) - for _, v in ipairs(limbs_data[part_name].depends_on) do + for _, v in pairs(limbs_data[part_name].depends_on) do local depended_body_part_type = player:getBodyDamage():getBodyPart(TocGetAdiacentBodyPartFromPartName(v)) FixSingleBodyPartType(depended_body_part_type, use_oven) diff --git a/media/lua/client/ActionsMethods/TOC_ProsthesisMethods.lua b/media/lua/client/ActionsMethods/TOC_ProsthesisMethods.lua index 56c4d81..da3ee96 100644 --- a/media/lua/client/ActionsMethods/TOC_ProsthesisMethods.lua +++ b/media/lua/client/ActionsMethods/TOC_ProsthesisMethods.lua @@ -6,15 +6,47 @@ ---Equip a prosthesis transforming a normal item into a clothing item ---@param part_name string +---@param prosthesis_item any the prosthesis item ---@param prosthesis_base_name string -function TocEquipProsthesis(part_name, prosthesis_base_name) +function TocEquipProsthesis(part_name, prosthesis_item, prosthesis_base_name) + + -- TODO probably will have to move this from the TOC menu to classic equip to have dynamic durability + -- TODO We need to pass the original item so we can get its data! + local player = getPlayer() local toc_data = player:getModData().TOC + + + local item_mod_data = prosthesis_item:getModData() + + if item_mod_data.TOC == nil then + GenerateEquippedProsthesis(prosthesis_item, "Test") -- TODO Change it with the limb + item_mod_data = prosthesis_item:getModData() -- Updates it + end + + + --print("TOC: Test durability normal item " .. item_mod_data.TOC.durability) + + local prosthesis_name = TocFindCorrectClothingProsthesis(prosthesis_base_name, part_name) local added_prosthesis = player:getInventory():AddItem(prosthesis_name) + + -- Add parameters to added_prosthesis + local added_prosthesis_mod_data = added_prosthesis:getModData() + + added_prosthesis_mod_data.TOC = { + durability = item_mod_data.TOC.durability, + speed = item_mod_data.TOC.speed, + } + + + --print("TOC: Test durability new item " .. added_prosthesis_mod_data.TOC.durability) + + + if part_name ~= nil then if added_prosthesis ~= nil then @@ -40,6 +72,8 @@ end function TocUnequipProsthesis(patient, part_name, equipped_prosthesis) + -- TODO Pass the parameters generated from EquipProsthesis to the re-generated normal item + local toc_data = patient:getModData().TOC toc_data.Limbs[part_name].is_prosthesis_equipped = false @@ -50,14 +84,21 @@ function TocUnequipProsthesis(patient, part_name, equipped_prosthesis) for _, prost_v in ipairs(GetProsthesisList()) do local prosthesis_name = string.match(equipped_prosthesis_full_type, prost_v) if prosthesis_name then - patient:getInventory():AddItem("TOC." .. prosthesis_name) + + -- Get mod data from equipped prosthesis so we can get its parameters + local equipped_prosthesis_mod_data = equipped_prosthesis:getModData() + + + local base_prosthesis_item = patient:getInventory():AddItem("TOC." .. prosthesis_name) + local base_prosthesis_item_mod_data = base_prosthesis_item.getModData() + base_prosthesis_item_mod_data.TOC = { + durability = equipped_prosthesis_mod_data.TOC.durability, + speed = equipped_prosthesis_mod_data.TOC.speed + } + patient:setWornItem(equipped_prosthesis:getBodyLocation(), nil) patient:getInventory():Remove(equipped_prosthesis) toc_data.Limbs[part_name].equipped_prosthesis = nil end - end - - -end - +end \ No newline at end of file diff --git a/media/lua/client/Interface/TOC_ContextMenus.lua b/media/lua/client/Interface/TOC_ContextMenus.lua index f2bec76..fc6c519 100644 --- a/media/lua/client/Interface/TOC_ContextMenus.lua +++ b/media/lua/client/Interface/TOC_ContextMenus.lua @@ -16,7 +16,7 @@ TocContextMenus.CreateMenus = function(player, context, worldObjects, test) local local_player = getSpecificPlayer(player) --local players = getOnlinePlayers() - for k, v in ipairs(worldObjects) do + for k, v in pairs(worldObjects) do -- help detecting a player by checking nearby squares for x = v:getSquare():getX() - 1, v:getSquare():getX() + 1 do for y = v:getSquare():getY() - 1, v:getSquare():getY() + 1 do @@ -79,6 +79,7 @@ TocContextMenus.CreateOperateWithOvenMenu = function(player, context, worldObjec -- Check temperature if v_stove:getCurrentTemperature() > 250 then + -- ipairs here to keep the order for _, v_bodypart in ipairs(GetBodyParts()) do if part_data[v_bodypart].is_cut and part_data[v_bodypart].is_amputation_shown and not part_data[v_bodypart].is_operated then diff --git a/media/lua/client/Interface/TOC_UI.lua b/media/lua/client/Interface/TOC_UI.lua index c18070a..426dc18 100644 --- a/media/lua/client/Interface/TOC_UI.lua +++ b/media/lua/client/Interface/TOC_UI.lua @@ -154,6 +154,9 @@ local function SetupTocMainUI(surgeon, patient, limbs_data) main_ui["b31"]:setPath(GetImageName("Right_Hand", limbs_data)) main_ui["b32"]:setPath(GetImageName("Left_Hand", limbs_data)) + main_ui["b41"]:setPath(GetImageName("Right_Foot", limbs_data)) + main_ui["b42"]:setPath(GetImageName("Left_Foot", limbs_data)) + end @@ -435,6 +438,15 @@ local function CreateTocMainUI() main_ui:addImageButton("b32", "", OnClickTocMainUI) main_ui["b32"]:addArg("part_name", "Left_Hand") + + main_ui:nextLine() + + main_ui:addImageButton("b41", "", OnClickTocMainUI) + main_ui["b41"]:addArg("part_name", "Right_Foot") + + main_ui:addImageButton("b42", "", OnClickTocMainUI) + main_ui["b42"]:addArg("part_name", "Left_Foot") + main_ui:saveLayout() diff --git a/media/lua/client/TOC_Animations.lua b/media/lua/client/TOC_Animations.lua new file mode 100644 index 0000000..766d32a --- /dev/null +++ b/media/lua/client/TOC_Animations.lua @@ -0,0 +1,18 @@ +-- Thanks to Glytcher and Matías N. Salas for helping out with this + +function SetMissingFootAnimation(check) + + + local player = getPlayer() + player:setVariable("IsCrawling", tostring(check)) + + if not isServer() and not isClient() then + print("SP, so it's fine") + else + + sendClientCommand(player, "TOC", "NotifyNewCrawlAnimation", {id = player:getOnlineID(), check = check}) + end + +end + + diff --git a/media/lua/client/TOC_Checks.lua b/media/lua/client/TOC_Checks.lua index 4086d77..0d7d51b 100644 --- a/media/lua/client/TOC_Checks.lua +++ b/media/lua/client/TOC_Checks.lua @@ -4,6 +4,10 @@ if TheOnlyCure == nil then TheOnlyCure = {} end + +local pairs = pairs + + ----------------------------------------- -- MP HANDLING CHECKS function CheckIfCanBeCut(part_name, limbs_data) @@ -60,9 +64,8 @@ end function CheckIfItemIsProsthesis(item) - -- TODO find a cleaner way local item_full_type = item:getFullType() - local prosthesis_list = GetProsthesisList() + local prosthesis_list = GetProsthesisList() -- TODO this isn't gonna work after the modular prost rewrite for _, v in pairs(prosthesis_list) do if v == item_full_type then @@ -88,7 +91,7 @@ end function CheckIfProsthesisAlreadyInstalled(limbs_data, part_name) - for _, side in ipairs(TOC_sides) do + for _, side in pairs(TOC_sides) do if string.find(part_name, side) then return (limbs_data[side .. "_Hand"].is_prosthesis_equipped or limbs_data[side .. "_LowerArm"].is_prosthesis_equipped) end diff --git a/media/lua/client/TOC_ClientCommands.lua b/media/lua/client/TOC_ClientCommands.lua index b7ecd81..7e06f68 100644 --- a/media/lua/client/TOC_ClientCommands.lua +++ b/media/lua/client/TOC_ClientCommands.lua @@ -1,8 +1,11 @@ --- Synchronization and MP related stuff +------------------------------------------ +-------- THE ONLY CURE BUT BETTER -------- +------------------------------------------ +------------ CLIENT COMMANDS ------------- -local Commands = {} +local ServerCommands = {} -Commands["ResponseCanAct"] = function(arg) +ServerCommands.ResponseCanAct = function(arg) print("TOC: ResponseCanAct") @@ -17,6 +20,162 @@ Commands["ResponseCanAct"] = function(arg) end + +ServerCommands.CanCutLimb = function(arg) + local part_name = arg["toSend"] + + arg["To"] = arg["From"] + arg["From"] = getPlayer():getOnlineID() + arg["command"] = "ResponseCanAct" + arg["toSend"] = { part_name, "Cut", CheckIfCanBeCut(part_name) } + sendClientCommand("TOC", "SendServer", arg) +end + +ServerCommands.CutLimb = function(arg) + local data = arg["toSend"] + TocCutLimb(data[1], data[2], data[3], data[4]) +end + + + +ServerCommands.CanOperateLimb = function(arg) + local part_name = arg["toSend"] + + arg["To"] = arg["From"] + arg["From"] = getPlayer():getOnlineID() + arg["command"] = "ResponseCanAct" + arg["toSend"] = { part_name, "Operate", CheckIfCanBeOperated(part_name) } + sendClientCommand("TOC", "SendServer", arg) +end +ServerCommands.OperateLimb = function(arg) + + local data = arg["toSend"] + TocOperateLimb(data[1], data[2], data[3]) +end + + +ServerCommands.CanEquipProsthesis = function(arg) + local part_name = arg["toSend"] + --local item = arg["toSend"][2] -- TODO Add item prosth here + + arg["To"] = arg["From"] + arg["From"] = getPlayer():getOnlineID() + arg["command"] = "ResponseCanAct" + arg["toSend"] = {part_name, "Equip", CheckIfProsthesisCanBeEquipped(part_name) } + sendClientCommand("TOC", "SendServer", arg) + +end +ServerCommands.EquipProsthesis = function(arg) + + -- part_name = arg[1] + -- prosthesis_item = arg[2] + -- prosthesis_name = arg[3] + + local data = arg["toSend"] + TocEquipProsthesis(data[1], data[2], data[3]) + +end + + +ServerCommands.CanUnequipProsthesis = function(arg) + local part_name = arg["toSend"] + arg["To"] = arg["From"] + arg["From"] = getPlayer():getOnlineID() + arg["command"] = "ResponseCanAct" + arg["toSend"] = { part_name, "Unequip", CheckIfProsthesisCanBeUnequipped(part_name)} + sendClientCommand("TOC", "SendServer", arg) +end +ServerCommands.UnequipProsthesis = function(arg) + + -- part_name = arg[1] + + local data = arg["toSend"] + TheOnlyCure.TocUnequipProsthesis(data[1], data[2]) + +end + + + +ServerCommands.CanResetEverything = function(arg) + local part_name = "RightHand" --useless + + arg["To"] = arg["From"] + arg["From"] = getPlayer():getOnlineID() + arg["command"] = "ResponseCanAct" + arg["toSend"] = { part_name, "Cut", true } + sendClientCommand("TOC", "SendServer", arg) +end +ServerCommands.ResetEverything = function(_) + TocResetEverything() +end + + +-- Used when amputating the limb of another player +ServerCommands.AcceptDamageOtherPlayer = function(arg) + local patient = getPlayerByOnlineID(arg[1]) + local part_name = arg[2] + TocDamagePlayerDuringAmputation(patient, part_name) +end + +-- Used to propagate animation changes after amputating a foot +ServerCommands.SetCrawlAnimation = function(args) + + local player = getPlayerByOnlineID(args.id) + local check = args.check + + player:setVariable('IsCrawling', tostring(check)) + +end + +-- Used to propagate the stop of the sound of amputation +ServerCommands.StopAmputationSound = function(args) + + local player = getPlayerByOnlineID(args.surgeon_id) + player:getEmitter():stopSoundByName("Amputation_Sound") + +end + + + +local function OnTocServerCommand(module, command, args) + if module == 'TOC' then + print("TOC: On Toc Server Command " .. command) + if ServerCommands[command] then + print("Found command, executing it now") + args = args or {} + ServerCommands[command](args) + + end + end +end + +Events.OnServerCommand.Add(OnTocServerCommand) + + +---------------------------------- Global Mod Data ----------------------------- + + +function TOC_OnReceiveGlobalModData(key, modData) + if modData then + ModData.remove(key) + ModData.add(key, modData) + end +end + + +Events.OnReceiveGlobalModData.Add(TOC_OnReceiveGlobalModData) + +function TOC_OnConnected() + ModData.request("TOC_PLAYER_DATA") +end + + +Events.OnConnected.Add(TOC_OnConnected) + + +-------------------------------------------------------- + + function SendCutLimb(player, part_name, surgeon_factor, bandage_table, painkiller_table) local arg = {} arg["From"] = getPlayer():getOnlineID() @@ -25,7 +184,7 @@ function SendCutLimb(player, part_name, surgeon_factor, bandage_table, painkille -- TODO Hotfix for sound, fix this later - arg["toSend"] = {part_name, surgeon_factor, bandage_table, painkiller_table, getPlayer():getOnlineID()} + arg["toSend"] = {part_name, surgeon_factor, bandage_table, painkiller_table} @@ -41,12 +200,12 @@ function SendOperateLimb(player, part_name, surgeon_factor, use_oven) sendClientCommand("TOC", "SendServer", arg) end -function SendEquipProsthesis(player, part_name, prosthesis_base_name) +function SendEquipProsthesis(player, part_name, item, prosthesis_base_name) local arg = {} arg["From"] = getPlayer():getOnlineID() arg["To"] = player:getOnlineID() arg["command"] = "EquipProsthesis" - arg["toSend"] = { part_name, prosthesis_base_name} + arg["toSend"] = { part_name, item, prosthesis_base_name} sendClientCommand("TOC", "SendServer", arg) end @@ -90,7 +249,6 @@ function AskCanEquipProsthesis(player, part_name) sendClientCommand("TOC", "SendServer", arg) end - function AskCanUnequipProsthesis(player, part_name) GetConfirmUIMP().responseReceive = false local arg = {} @@ -101,165 +259,3 @@ function AskCanUnequipProsthesis(player, part_name) sendClientCommand("TOC", "SendServer", arg) end - - --- Patient (receive) -Commands["CutLimb"] = function(arg) - local arg = arg["toSend"] - local surgeon_id = arg[5] - - -- Disable the sound coming from the surgeon - getPlayerByOnlineID(surgeon_id):getEmitter():stopSoundByName("Amputation_Sound") - - - - TocCutLimb(arg[1], arg[2], arg[3], arg[4]) -end - -Commands["OperateLimb"] = function(arg) - local arg = arg["toSend"] - TocOperateLimb(arg[1], arg[2], arg[3]) -end - - -Commands["EquipProsthesis"] = function(arg) - - -- part_name = arg[1] - -- prosthesis = arg[2] - - local arg = arg["toSend"] - - TocEquipProsthesis(arg[1], arg[2]) - -end - -Commands["UnequipProsthesis"] = function(arg) - - -- part_name = arg[1] - - local arg = arg["toSend"] - - TheOnlyCure.TocUnequipProsthesis(arg[1], arg[2]) - -end - -Commands["CanCutLimb"] = function(arg) - local part_name = arg["toSend"] - - arg["To"] = arg["From"] - arg["From"] = getPlayer():getOnlineID() - arg["command"] = "ResponseCanAct" - arg["toSend"] = { part_name, "Cut", CheckIfCanBeCut(part_name) } - sendClientCommand("TOC", "SendServer", arg) -end - -Commands["CanOperateLimb"] = function(arg) - local part_name = arg["toSend"] - - arg["To"] = arg["From"] - arg["From"] = getPlayer():getOnlineID() - arg["command"] = "ResponseCanAct" - arg["toSend"] = { part_name, "Operate", CheckIfCanBeOperated(part_name) } - sendClientCommand("TOC", "SendServer", arg) -end - -Commands["CanEquipProsthesis"] = function(arg) - local part_name = arg["toSend"] - --local item = arg["toSend"][2] -- TODO Add item prosth here - - arg["To"] = arg["From"] - arg["From"] = getPlayer():getOnlineID() - arg["command"] = "ResponseCanAct" - arg["toSend"] = {part_name, "Equip", CheckIfProsthesisCanBeEquipped(part_name) } - sendClientCommand("TOC", "SendServer", arg) - -end - -Commands["CanUnequipProsthesis"] = function(arg) - local part_name = arg["toSend"] - arg["To"] = arg["From"] - arg["From"] = getPlayer():getOnlineID() - arg["command"] = "ResponseCanAct" - arg["toSend"] = { part_name, "Unequip", CheckIfProsthesisCanBeUnequipped(part_name)} - sendClientCommand("TOC", "SendServer", arg) - -end - -Commands["CanResetEverything"] = function(arg) - local part_name = "RightHand" --useless - - arg["To"] = arg["From"] - arg["From"] = getPlayer():getOnlineID() - arg["command"] = "ResponseCanAct" - arg["toSend"] = { part_name, "Cut", true } - sendClientCommand("TOC", "SendServer", arg) -end - -Commands["ResetEverything"] = function(arg) - local arg = arg["toSend"] - TocResetEverything() -end - --- Cheating stuff -Commands["AcceptResetEverything"] = function(arg) - - local clicked_player = getPlayerByOnlineID(arg[1]) -- TODO delete this - TocResetEverything() -end - - - - --- Cut Limb stuff -Commands["AcceptDamageOtherPlayer"] = function(arg) - - local patient_id = arg[1] - local patient = getPlayerByOnlineID(arg[1]) - local part_name = arg[2] - TocDamagePlayerDuringAmputation(patient, part_name) -end - - - - --- Base stuff -local function OnTocServerCommand(module, command, args) - if module == 'TOC' then - print("TOC: On Toc Server Command " .. command) - if Commands[command] then - print("Found command, executing it now") - args = args or {} - Commands[command](args) - - end - end -end - -Events.OnServerCommand.Add(OnTocServerCommand) - - - - - - - ----------------------------------- TEST ----------------------------- - - -function TOC_OnReceiveGlobalModData(key, modData) - if modData then - ModData.remove(key) - ModData.add(key, modData) - end -end - - -Events.OnReceiveGlobalModData.Add(TOC_OnReceiveGlobalModData) - -function TOC_OnConnected() - ModData.request("TOC_PLAYER_DATA") -end - - -Events.OnConnected.Add(TOC_OnConnected) - diff --git a/media/lua/client/TOC_CommonFunctions.lua b/media/lua/client/TOC_CommonFunctions.lua index 21356ec..cd3fe32 100644 --- a/media/lua/client/TOC_CommonFunctions.lua +++ b/media/lua/client/TOC_CommonFunctions.lua @@ -74,6 +74,11 @@ function TocGetBodyPartFromPartName(part_name) if part_name == "Left_Hand" then return BodyPartType.Hand_L end if part_name == "Left_LowerArm" then return BodyPartType.ForeArm_L end if part_name == "Left_UpperArm" then return BodyPartType.UpperArm_L end + + -- New Legs stuff + if part_name == "Right_Foot" then return BodyPartType.Foot_R end + if part_name == "Left_Foot" then return BodyPartType.Foot_L end + end -- Custom mapping to make more sense when cutting a limb @@ -85,6 +90,11 @@ function TocGetAdiacentBodyPartFromPartName(part_name) if part_name == "Left_Hand" then return BodyPartType.ForeArm_L end if part_name == "Left_LowerArm" then return BodyPartType.UpperArm_L end if part_name == "Left_UpperArm" then return BodyPartType.Torso_Upper end + + if part_name == "Right_Foot" then return BodyPartType.LowerLeg_R end + if part_name == "Left_Foot" then return BodyPartType.LowerLeg_L end + + end function TocFindCorrectClothingProsthesis(item_name, part_name) diff --git a/media/lua/client/TOC_Compatibility.lua b/media/lua/client/TOC_Compatibility.lua index ad22d43..58a04d6 100644 --- a/media/lua/client/TOC_Compatibility.lua +++ b/media/lua/client/TOC_Compatibility.lua @@ -1,3 +1,8 @@ + + + + + local function TocReapplyAmputationClothingItem(mod_data) local player = getPlayer() local player_inv = player:getInventory() @@ -6,16 +11,22 @@ local function TocReapplyAmputationClothingItem(mod_data) for _, limb in ipairs(TOC_limbs) do local part_name = side .. "_" .. limb - if mod_data.TOC.Limbs[part_name].is_cut and mod_data.TOC.Limbs[part_name].is_amputation_shown then - local amputated_clothing_name = "TOC.Amputation_" .. part_name - if player_inv:FindAndReturn(amputated_clothing_name) == nil then - local amputation_clothing_item = player:getInventory():AddItem(TocFindAmputatedClothingFromPartName(part_name)) - TocSetCorrectTextureForAmputation(amputation_clothing_item, player, mod_data.TOC.Limbs[part_name].is_cicatrized) - player:setWornItem(amputation_clothing_item:getBodyLocation(), amputation_clothing_item) - + -- Check this before since we could have changed some stuff about part names before fixing them. Could break things + local part_data = mod_data.TOC.Limbs[part_name] + if part_data then + if part_data.is_cut and part_data.is_amputation_shown then + local amputated_clothing_name = "TOC.Amputation_" .. part_name + if player_inv:FindAndReturn(amputated_clothing_name) == nil then + local amputation_clothing_item = player:getInventory():AddItem(TocFindAmputatedClothingFromPartName(part_name)) + TocSetCorrectTextureForAmputation(amputation_clothing_item, player, part_data.is_cicatrized) + player:setWornItem(amputation_clothing_item:getBodyLocation(), amputation_clothing_item) + + end end end + + TocResetClothingItemBodyLocation(player, side, limb) end end @@ -34,8 +45,9 @@ function TocCheckCompatibilityWithOlderVersions(mod_data) print("TOC: Something was wrongly initiliazed before. Resetting parameters") TocResetEverything() else - print("TOC: Found compatible data, correcting models in case of errors") - TocReapplyAmputationClothingItem(mod_data) + print("TOC: Bypassing reapplying of amputations, assuming that everything is correct") + --print("TOC: Found compatible data, correcting models in case of errors and adding limbs") + --TocReapplyAmputationClothingItem(mod_data) end end diff --git a/media/lua/client/TOC_Debug.lua b/media/lua/client/TOC_Debug.lua index c44c920..cebf84d 100644 --- a/media/lua/client/TOC_Debug.lua +++ b/media/lua/client/TOC_Debug.lua @@ -45,32 +45,40 @@ function TocResetEverything() TheOnlyCure.InitTheOnlyCure(_, player) -- Destroy the amputation or prosthesis item - for _, v in ipairs(GetBodyParts()) do - -- TODO This is incredibly shitty, but we can't use worn items since we need to consider the case that the item wasn't applied - local amputation_item_name = TocFindAmputationOrProsthesisName(v, player, "Amputation") - local prosthesis_item_name = TocFindAmputationOrProsthesisName(v, player, "Prosthesis") - if amputation_item_name ~= nil then - local amputation_item = player_inventory:FindAndReturn(amputation_item_name) - if amputation_item ~= nil then - print("Resetting " .. amputation_item:getName()) - player:removeWornItem(amputation_item) - player:getInventory():Remove(amputation_item) + for _, side in pairs(TOC_sides) do + for _, limb in pairs(TOC_limbs) do + + local part_name = side .. "_" .. limb + local amputation_item_name = TocFindAmputationOrProsthesisName(part_name, player, "Amputation") + local prosthesis_item_name = TocFindAmputationOrProsthesisName(part_name, player, "Prosthesis") + if amputation_item_name ~= nil then + local amputation_item = player_inventory:FindAndReturn(amputation_item_name) + if amputation_item ~= nil then + print("Resetting " .. amputation_item:getName()) + player:removeWornItem(amputation_item) + player:getInventory():Remove(amputation_item) + end + amputation_item = nil -- reset it end - amputation_item = nil -- reset it - end - if prosthesis_item_name ~= nil then - local prosthesis_item = player_inventory:FindAndReturn(prosthesis_item_name) - if prosthesis_item ~= nil then - print("Resetting " .. prosthesis_item:getName()) - player:removeWornItem(prosthesis_item) - player:getInventory():Remove(prosthesis_item) + if prosthesis_item_name ~= nil then + local prosthesis_item = player_inventory:FindAndReturn(prosthesis_item_name) + if prosthesis_item ~= nil then + print("Resetting " .. prosthesis_item:getName()) + player:removeWornItem(prosthesis_item) + player:getInventory():Remove(prosthesis_item) + end + prosthesis_item = nil -- reset it end - prosthesis_item = nil -- reset it + + end - - end + + + -- Reset special flag for legs amputations + SetMissingFootAnimation(false) + end @@ -129,4 +137,16 @@ function TocTestBodyLocations() print(list:get(i -1):getId()) end +end + +function TocTestItem() + local player = getPlayer() + local player_inventory = player:getInventory() + local item_name = "TOC.Amputation_" .. "Right" .. "_" .. "Hand" + local found_item = player_inventory:FindAndReturn(item_name) + + print(found_item:getID()) + print("_______________") + found_item:setID(12334) + print(found_item:getID()) end \ No newline at end of file diff --git a/media/lua/client/TOC_HelperFunctions.lua b/media/lua/client/TOC_HelperFunctions.lua index d369004..6793d07 100644 --- a/media/lua/client/TOC_HelperFunctions.lua +++ b/media/lua/client/TOC_HelperFunctions.lua @@ -25,6 +25,9 @@ local function PartNameToBodyLocationAmputation(name) if name == "Left_Hand" then return "TOC_ArmLeft" end if name == "Left_LowerArm" then return "TOC_ArmLeft" end if name == "Left_UpperArm" then return "TOC_ArmLeft" end + + if name == "Left_Foot" then return "TOC_LegLeft" end + if name == "Right_Foot" then return "TOC_LegRight" end end function TocFindItemInProstBodyLocation(part_name, patient) @@ -71,7 +74,7 @@ end -- Override and mod compat helper function TocPopulateCanBeHeldTable(can_be_held, limbs_data) - for _, side in ipairs(TOC_sides) do + for _, side in pairs(TOC_sides) do can_be_held[side] = true if limbs_data[side .. "_Hand"].is_cut then @@ -85,4 +88,18 @@ function TocPopulateCanBeHeldTable(can_be_held, limbs_data) end end +end + + + + + +----------------------------------------- +function TocCheckLegsAmputations(mod_data) + + if mod_data.TOC.Limbs["Left_Foot"].is_cut or mod_data.TOC.Limbs["Right_Foot"].is_cut then + SetMissingFootAnimation(true) + end + + end \ No newline at end of file diff --git a/media/lua/client/TOC_Init.lua b/media/lua/client/TOC_Init.lua index 147b180..eb43a18 100644 --- a/media/lua/client/TOC_Init.lua +++ b/media/lua/client/TOC_Init.lua @@ -8,7 +8,7 @@ if not TheOnlyCure then end TOC_sides = { "Left", "Right" } -TOC_limbs = { "Hand", "LowerArm", "UpperArm" } +TOC_limbs = { "Hand", "LowerArm", "UpperArm", "Foot"} local function TocCutLimbForTrait(player, limbs_data, part_name) local amputation_clothing_item = player:getInventory():AddItem("TOC.Amputation_" .. part_name) @@ -27,6 +27,33 @@ local function TocCutLimbForTrait(player, limbs_data, part_name) limbs_data[v].is_cicatrized = true end end + +local function InitSpecificPart(mod_data, part_name) + + if mod_data.TOC.Limbs[part_name] == nil then + mod_data.TOC.Limbs[part_name] = {} + end + + + mod_data.TOC.Limbs[part_name].is_cut = false + mod_data.TOC.Limbs[part_name].is_infected = false + mod_data.TOC.Limbs[part_name].is_operated = false + mod_data.TOC.Limbs[part_name].is_cicatrized = false + mod_data.TOC.Limbs[part_name].is_cauterized = false + mod_data.TOC.Limbs[part_name].is_amputation_shown = false + + mod_data.TOC.Limbs[part_name].cicatrization_time = 0 + + + mod_data.TOC.Limbs[part_name].is_prosthesis_equipped = false + mod_data.TOC.Limbs[part_name].equipped_prosthesis = {} + + + +end + + + local function TocUpdateBaseData(mod_data) -- TODO The prosthetic knife needs to be a weapon first and foremost, so other than a @@ -37,12 +64,20 @@ local function TocUpdateBaseData(mod_data) local accepted_prosthesis_hand = { "WoodenHook", "MetalHook", "MetalHand", "ProstheticKnife" } local accepted_prosthesis_lowerarm = { "WoodenHook", "MetalHook", "MetalHand", "ProstheticKnife" } local accepted_prosthesis_upperarm = {} -- For future stuff + local accepted_prosthesis_foot = {} - for _, side in ipairs(TOC_sides) do - for _, limb in ipairs(TOC_limbs) do + for _, side in pairs(TOC_sides) do + for _, limb in pairs(TOC_limbs) do local part_name = side .. "_" .. limb + + -- Check if part was initialized + if mod_data.TOC.Limbs[part_name] == nil then + InitSpecificPart(mod_data, part_name) + end + + if limb == "Hand" then mod_data.TOC.Limbs[part_name].cicatrization_base_time = 1700 mod_data.TOC.Limbs[part_name].depends_on = {} @@ -69,6 +104,11 @@ local function TocUpdateBaseData(mod_data) mod_data.TOC.Limbs[part_name].cicatrization_base_time = 2000 mod_data.TOC.Limbs[part_name].depends_on = { side .. "_Hand", side .. "_LowerArm", } mod_data.TOC.Prosthesis.Accepted_Prosthesis[part_name] = accepted_prosthesis_upperarm + elseif limb == "Foot" then + mod_data.TOC.Limbs[part_name].cicatrization_base_time = 1700 + mod_data.TOC.Limbs[part_name].depends_on = {} + mod_data.TOC.Prosthesis.Accepted_Prosthesis[part_name] = accepted_prosthesis_foot + end end @@ -102,6 +142,10 @@ local function TocSetInitData(mod_data, player) Left_Hand = {}, Left_LowerArm = {}, Left_UpperArm = {}, + + Left_Foot = {}, + Right_Foot = {}, + is_other_bodypart_infected = false }, Prosthesis = { @@ -161,8 +205,8 @@ local function TocSetInitData(mod_data, player) - for _, side in ipairs(TOC_sides) do - for _, limb in ipairs(TOC_limbs) do + for _, side in pairs(TOC_sides) do + for _, limb in pairs(TOC_limbs) do local part_name = side .. "_" .. limb @@ -207,7 +251,8 @@ function TheOnlyCure.InitTheOnlyCure(_, player) TocSetInitData(mod_data, player) else TocCheckCompatibilityWithOlderVersions(mod_data) - TocUpdateBaseData(mod_data) -- Since it's gonna be common to update stuff + TocUpdateBaseData(mod_data) -- Since it's gonna be common to update stuff + TocCheckLegsAmputations(mod_data) end end @@ -216,14 +261,20 @@ local function TocDeclareTraits() local amp1 = TraitFactory.addTrait("Amputee_Hand", getText("UI_trait_Amputee_Hand"), -8, getText("UI_trait_Amputee_Hand_desc"), false, false) amp1:addXPBoost(Perks.Left_Hand, 4) + amp1:addXPBoost(Perks.Fitness, -1) + amp1:addXPBoost(Perks.Strength, -1) local amp2 = TraitFactory.addTrait("Amputee_LowerArm", getText("UI_trait_Amputee_LowerArm"), -10, getText("UI_trait_Amputee_LowerArm_desc"), false, false) amp2:addXPBoost(Perks.Left_Hand, 4) + amp2:addXPBoost(Perks.Fitness, -1) + amp2:addXPBoost(Perks.Strength, -1) local amp3 = TraitFactory.addTrait("Amputee_UpperArm", getText("UI_trait_Amputee_UpperArm"), -20, getText("UI_trait_Amputee_UpperArm_desc"), false, false) amp3:addXPBoost(Perks.Left_Hand, 4) + amp3:addXPBoost(Perks.Fitness, -1) + amp3:addXPBoost(Perks.Strength, -1) TraitFactory.addTrait("Insensitive", getText("UI_trait_Insensitive"), 6, getText("UI_trait_Insensitivedesc"), false, false) diff --git a/media/lua/client/TOC_OverridenFunctions.lua b/media/lua/client/TOC_OverridenFunctions.lua index 0e6bf6e..fd8fe8d 100644 --- a/media/lua/client/TOC_OverridenFunctions.lua +++ b/media/lua/client/TOC_OverridenFunctions.lua @@ -3,9 +3,8 @@ require "TimedActions/ISEquipWeaponAction" require "TimedActions/ISUnequipAction" require "ISUI/ISInventoryPaneContextMenu" + local og_ISBaseTimedActionAdjustMaxTime = ISBaseTimedAction.adjustMaxTime - - function ISBaseTimedAction:adjustMaxTime(maxTime) local original_max_time = og_ISBaseTimedActionAdjustMaxTime(self, maxTime) @@ -73,14 +72,15 @@ function ISInventoryPane:onMouseDoubleClick(x, y) local item_to_check = self.items[self.mouseOverOption] local player_inventory = getPlayerInventory(self.player).inventory + + if instanceof(item_to_check, "InventoryItem") then og_ISInventoryPaneOnMouseDoubleClick(self, x, y) elseif CheckIfItemIsAmputatedLimb(item_to_check.items[1]) or CheckIfItemIsInstalledProsthesis(item_to_check.items[1]) then --print("TOC: Can't double click this item") - else - og_ISInventoryPaneOnMouseDoubleClick(self, x, y) end + og_ISInventoryPaneOnMouseDoubleClick(self, x, y) @@ -93,7 +93,6 @@ function ISInventoryPane.getActualItems(items) local ret = og_ISInventoryPaneGetActualItems(items) -- This is gonna be slower than just overriding the function but hey it's more compatible - for i = 1, #ret do local item_full_type = ret[i]:getFullType() if string.find(item_full_type, "Amputation_") or string.find(item_full_type, "Prost_") then @@ -120,7 +119,6 @@ end local og_ISEquipWeaponActionPerform = ISEquipWeaponAction.perform function ISEquipWeaponAction:perform() - -- TODO this is only for weapons, not items. Won't work for everything I think --TODO Block it before even performing -- TODO in the inventory menu there is something broken, even though this works @@ -153,7 +151,7 @@ function ISEquipWeaponAction:perform() if self.item then local item_name = self.item:getFullType() - for _, prost_v in ipairs(GetProsthesisList()) do + for _, prost_v in pairs(GetProsthesisList()) do local prosthesis_name = string.match(item_name, prost_v) if prosthesis_name then self.character:Say("This isn't the right way to equip this...") diff --git a/media/lua/client/TOC_ProsthesisHandler.lua b/media/lua/client/TOC_ProsthesisHandler.lua new file mode 100644 index 0000000..d5dc025 --- /dev/null +++ b/media/lua/client/TOC_ProsthesisHandler.lua @@ -0,0 +1,89 @@ +local BaseStats = { + LeatherBase = { + durability = 25, + speed = 15 + }, + WoodenBase = { + durability = 10, + speed = 5, + }, + MetalBase = { + durability = 75, + speed = 7, + } + + + + +} + + +local TopStats = { + +} + + + + + + + +function GenerateEquippedProsthesis(prosthesis_item, limb) + -- TODO Durability should be decided from the clothing item xml. Same thing for disassembling stuff + + -- TODO some stuff should be defined by the limb, like -10 if forearm in speed +-- -- when we equip a prosthesis, we're gonna pass these parameters to the newly generated clothing item +-- -- when we unequip it, we regen the normal item with the parameters from the clothing item + + local durability = 0 + local speed = 0 + + local prosthesis_name = prosthesis_item:getFullType() + + for base_name, base_values in pairs(BaseStats) do + -- Check the name of the prosthesis item, set the correct values + if string.find(prosthesis_name, base_name) then + durability = base_values.durability + speed = base_values.speed + end + end + + + + for top_name, top_values in pairs(TopStats) do + -- Check the name of the prosthesis item, set the correct values + if string.find(prosthesis_name, top_name) then + durability = durability + top_values.durability + speed = speed + top_values.speed + end + end + + local item_mod_data = prosthesis_item:getModData() + + -------------------- + -- TEST STUFF + durability = 12 + speed = 51 + + ------------------- + + + item_mod_data.TOC = { + durability = durability, + speed = speed, + } +end + +--local ProsthesisRecipe = {} + + +-- function ProsthesisRecipe.OnCreate.Hook(items, result, player, selectedItem) + +-- -- Set mod data for item with durability and all that crap + + + +-- end + + + diff --git a/media/lua/client/TOC_Update.lua b/media/lua/client/TOC_Update.lua index cc8240e..254faf8 100644 --- a/media/lua/client/TOC_Update.lua +++ b/media/lua/client/TOC_Update.lua @@ -19,7 +19,7 @@ local function CheckIfPlayerIsInfected(player, toc_data) end -- Check for everything else - for _, v in ipairs(GetOtherBodyPartTypes()) do + for _, v in pairs(GetOtherBodyPartTypes()) do if body_damage:getBodyPart(v):bitten() then toc_data.Limbs.is_other_bodypart_infected = true -- Even one is enough, stop cycling if we find it break @@ -171,12 +171,14 @@ end -- MAIN UPDATE FUNCTIONS + local function TocUpdateOnTick() local player = getPlayer() if player == nil then return end + local toc_data = player:getModData().TOC if toc_data ~= nil then CheckIfPlayerIsInfected(player, toc_data) @@ -196,7 +198,7 @@ local function TocUpdateEveryTenMinutes() local part_data = player:getModData().TOC.Limbs --Experience for prosthesis user - for _, side in ipairs(TOC_sides) do + for _, side in pairs(TOC_sides) do if part_data[side .. "_Hand"].is_prosthesis_equipped or part_data[side .. "_LowerArm"].is_prosthesis_equipped then player:getXp():AddXP(Perks[side .. "_Hand"], 4) end @@ -247,6 +249,7 @@ local function TocUpdateEveryOneMinute() -- Sends only Limbs since the other stuff is mostly static if toc_data ~= nil then -- FIXME Send little packets instead of the whole thing? + -- TODO we shouldn't run this if we're in SP I guess? sendClientCommand(player, 'TOC', 'ChangePlayerState', { toc_data.Limbs } ) end diff --git a/media/lua/client/TimedActions/ISCutLimb.lua b/media/lua/client/TimedActions/ISCutLimb.lua index 16f1064..8ad4203 100644 --- a/media/lua/client/TimedActions/ISCutLimb.lua +++ b/media/lua/client/TimedActions/ISCutLimb.lua @@ -23,7 +23,12 @@ end function ISCutLimb:stop() + print("Stopping ISCutLimb") self.surgeon:getEmitter():stopSoundByName("Amputation_Sound") + sendClientCommand(self.surgeon, "TOC", "AskStopAmputationSound", {surgeon_id = self.surgeon:getOnlineID()}) + + -- TODO test this with more than 2 players + -- TODO this gets bugged when player dies while amputating end @@ -115,6 +120,7 @@ function ISCutLimb:perform() if self.patient ~= self.surgeon and isClient() then SendCutLimb(self.patient, self.part_name, surgeon_factor, bandage_table, painkiller_table) + sendClientCommand(self.surgeon, "TOC", "AskStopAmputationSound", {surgeon_id = self.surgeon:getOnlineID()}) else TocCutLimb(self.part_name, surgeon_factor, bandage_table, painkiller_table) end diff --git a/media/lua/client/TimedActions/ISInstallProsthesis.lua b/media/lua/client/TimedActions/ISInstallProsthesis.lua index 30ecbdb..11a30b2 100644 --- a/media/lua/client/TimedActions/ISInstallProsthesis.lua +++ b/media/lua/client/TimedActions/ISInstallProsthesis.lua @@ -3,6 +3,9 @@ require "TimedActions/ISBaseTimedAction" ISInstallProsthesis = ISBaseTimedAction:derive("ISInstallProsthesis"); function ISInstallProsthesis:isValid() + + -- TODO add here conditions if the action can be performed or not, so if thing is in inventory + -- TODO 'not sure about multiplayer, maybe an overriding check? return true end @@ -49,17 +52,19 @@ function ISInstallProsthesis:perform() return end - self.surgeon:getInventory():Remove(prosthesis_base_name) -- Removes the base item and substitute it with the part one if self.patient ~= self.surgeon and isClient() then - SendEquipProsthesis(self.patient, self.part_name, prosthesis_base_name) + SendEquipProsthesis(self.patient, self.part_name, self.item, prosthesis_base_name) else - TocEquipProsthesis(self.part_name, prosthesis_base_name) + TocEquipProsthesis(self.part_name, self.item, prosthesis_base_name) end + + self.surgeon:getInventory():Remove(prosthesis_base_name) -- Removes the base item after we transferred everything + -- needed to remove from queue / start next. ISBaseTimedAction.perform(self) end diff --git a/media/lua/server/TOC_MP_server.lua b/media/lua/server/TOC_MP_server.lua index a0587df..fc2ddc4 100644 --- a/media/lua/server/TOC_MP_server.lua +++ b/media/lua/server/TOC_MP_server.lua @@ -1,19 +1,18 @@ ---- A rly big thx to Fenris_Wolf and Chuck to help me with that. Love you guy ----Server side -local TOC_Commands = {} +local ClientCommands = {} -TOC_Commands["SendServer"] = function(player, arg) +-- Main handler of base functions for TOC, not changed till now 'cause it works +ClientCommands.SendServer = function(player, arg) local otherPlayer = getPlayerByOnlineID(arg["To"]) sendServerCommand(otherPlayer, "TOC", arg["command"], arg) + end - --- Cut Limb stuff -TOC_Commands["AskDamageOtherPlayer"] = function(_, arg) +-- Cutting Limbs +ClientCommands.AskDamageOtherPlayer = function(_, arg) local patient = getPlayerByOnlineID(arg[1]) local patient_id = arg[1] @@ -23,24 +22,38 @@ TOC_Commands["AskDamageOtherPlayer"] = function(_, arg) end +ClientCommands.AskStopAmputationSound = function(_, args) + + print("TOC: We're in AskStopAmputationSound") + sendServerCommand("TOC", "StopAmputationSound", {surgeon_id = args.surgeon_id}) +end +-- Animations +ClientCommands.NotifyNewCrawlAnimation = function(player, args) - --- CHEATING STUFF -TOC_Commands["AskToResetEverything"] = function(_, arg) - local clicked_player = getPlayerByOnlineID(arg[1]) - local clicked_player_id = arg[1] - - - sendServerCommand(clicked_player, "TOC", "AcceptResetEverything", { clicked_player_id }) + sendServerCommand("TOC", "SetCrawlAnimation", {id = args.id, check = args.check}) end +-- Cheats +ClientCommands.AskToResetEverything = function(_, arg) + local clicked_player = getPlayerByOnlineID(arg[1]) + sendServerCommand(clicked_player, "TOC", "ResetEverything", {}) +end + + +-- Global Mod Data data handler +ClientCommands.ChangePlayerState = function(playerObj, args) + ModData.get("TOC_PLAYER_DATA")[playerObj:getUsername()] = args + ModData.transmit("TOC_PLAYER_DATA") +end + + ------ Global Mod Data ----------- function TOC_OnInitGlobalModData() @@ -49,18 +62,15 @@ end Events.OnInitGlobalModData.Add(TOC_OnInitGlobalModData) -TOC_Commands.OnClientCommand = function(module, command, playerObj, args) - if module == 'TOC' and TOC_Commands[command] then - TOC_Commands[command](playerObj, args) +------------------------------------------------------ + +local function OnClientCommand(module, command, playerObj, args) + if module == 'TOC' and ClientCommands[command] then + ClientCommands[command](playerObj, args) end end - -Events.OnClientCommand.Add(TOC_Commands.OnClientCommand) +Events.OnClientCommand.Add(OnClientCommand) -TOC_Commands.ChangePlayerState = function(playerObj, args) - ModData.get("TOC_PLAYER_DATA")[playerObj:getUsername()] = args - ModData.transmit("TOC_PLAYER_DATA") -end \ No newline at end of file diff --git a/media/lua/shared/NPCs/ExtraBodyLocations.lua b/media/lua/shared/NPCs/ExtraBodyLocations.lua index 69729e6..78beefb 100644 --- a/media/lua/shared/NPCs/ExtraBodyLocations.lua +++ b/media/lua/shared/NPCs/ExtraBodyLocations.lua @@ -1,20 +1,26 @@ -local function addBodyLocationBefore(new_location, move_to_location) - -- FIXME This doesn't really move a body location, it just re-adds it to another index. Find a way to remove it entirely (maybe setExclusive?) - +local function AddBodyLocationBefore(new_location, move_to_location) local group = BodyLocations.getGroup("Human") local list = getClassFieldVal(group, getClassField(group, 1)) group:getOrCreateLocation(new_location) - local newItem = list:get(list:size()-1) - print("TOC: Created new body location" .. newItem:getId()) - - list:remove(newItem) -- We can't use the Index, it works if we pass the item though! + local new_item = list:get(list:size()-1) + print("TOC: Created new body location" .. new_item:getId()) + list:remove(new_item) -- We can't use the Index, it works if we pass the item though! local i = group:indexOf(move_to_location) - list:add(i, newItem) + list:add(i, new_item) end +AddBodyLocationBefore("TOC_ArmRight", "Shoes") +AddBodyLocationBefore("TOC_ArmLeft", "Shoes") -addBodyLocationBefore("TOC_ArmRight", "Shoes") -addBodyLocationBefore("TOC_ArmLeft", "Shoes") -addBodyLocationBefore("TOC_ArmRightProsthesis", "Shoes") -addBodyLocationBefore("TOC_ArmLeftProsthesis", "Shoes") + + +AddBodyLocationBefore("TOC_ArmRightProsthesis", "Shoes") +AddBodyLocationBefore("TOC_ArmLeftProsthesis", "Shoes") + +AddBodyLocationBefore("TOC_LegRight", "FannyPackFront") +AddBodyLocationBefore("TOC_LegLeft", "FannyPackFront") + + +AddBodyLocationBefore("TOC_LegRightProsthesis", "FannyPackFront") +AddBodyLocationBefore("TOC_LegLeftProsthesis", "FannyPackFront") diff --git a/media/models_X/Amputation/Amputation_GenericModel.fbx b/media/models_X/Amputation/Amputation_GenericModel.fbx new file mode 100644 index 0000000..9c315ef Binary files /dev/null and b/media/models_X/Amputation/Amputation_GenericModel.fbx differ diff --git a/media/scripts/TOC_items.txt b/media/scripts/TOC_items.txt index 54f56ad..cbc76e9 100644 --- a/media/scripts/TOC_items.txt +++ b/media/scripts/TOC_items.txt @@ -478,6 +478,45 @@ item Surgery_Right_Tourniquet Tooltip = Test, CanHaveHoles = false, } + +item Amputation_Left_Foot + { + Type = Clothing, + DisplayName = Amputated Left Foot, + + ClothingItem = Amputation_Left_Foot, + BodyLocation = TOC_LegLeft, + + Weight = 0, + CombatSpeedModifier = 0.9, + BloodLocation = Hands;LowerArms, + + Insulation = 1.0, + WindResistance = 1.0, + WaterResistance = 1.0, + Icon = genericAmputation, + CanHaveHoles = false, + } + +item Amputation_Right_Foot + { + Type = Clothing, + DisplayName = Amputated Right Foot, + + ClothingItem = Amputation_Right_Foot, + BodyLocation = TOC_LegRight, + + Weight = 0, + CombatSpeedModifier = 0.9, + BloodLocation = Hands;LowerArms, + + Insulation = 1.0, + WindResistance = 1.0, + WaterResistance = 1.0, + Icon = genericAmputation, + CanHaveHoles = false, + } + } diff --git a/media/scripts/TOC_recipes.txt b/media/scripts/TOC_recipes.txt index 25a94d7..8790bff 100644 --- a/media/scripts/TOC_recipes.txt +++ b/media/scripts/TOC_recipes.txt @@ -82,6 +82,7 @@ recipe Make wooden hook Category: Surgeon, Tooltip: Recipe_Tooltip_Wooden_hook, NeedToBeLearn: true, + } recipe Make metal hook diff --git a/media/ui/TOC/Left_Foot/Base.png b/media/ui/TOC/Left_Foot/Base.png new file mode 100644 index 0000000..373ca17 Binary files /dev/null and b/media/ui/TOC/Left_Foot/Base.png differ diff --git a/media/ui/TOC/Left_Foot/Bite.png b/media/ui/TOC/Left_Foot/Bite.png new file mode 100644 index 0000000..3ec6837 Binary files /dev/null and b/media/ui/TOC/Left_Foot/Bite.png differ diff --git a/media/ui/TOC/Left_Foot/Bleed.png b/media/ui/TOC/Left_Foot/Bleed.png new file mode 100644 index 0000000..639d9b7 Binary files /dev/null and b/media/ui/TOC/Left_Foot/Bleed.png differ diff --git a/media/ui/TOC/Left_Foot/Cut.png b/media/ui/TOC/Left_Foot/Cut.png new file mode 100644 index 0000000..0d0ad48 Binary files /dev/null and b/media/ui/TOC/Left_Foot/Cut.png differ diff --git a/media/ui/TOC/Left_Foot/Hook.png b/media/ui/TOC/Left_Foot/Hook.png new file mode 100644 index 0000000..e9d0df4 Binary files /dev/null and b/media/ui/TOC/Left_Foot/Hook.png differ diff --git a/media/ui/TOC/Left_Foot/MetalHand.png b/media/ui/TOC/Left_Foot/MetalHand.png new file mode 100644 index 0000000..3094308 Binary files /dev/null and b/media/ui/TOC/Left_Foot/MetalHand.png differ diff --git a/media/ui/TOC/Left_Foot/Operate.png b/media/ui/TOC/Left_Foot/Operate.png new file mode 100644 index 0000000..e6209ad Binary files /dev/null and b/media/ui/TOC/Left_Foot/Operate.png differ diff --git a/media/ui/TOC/Right_Foot/Base.png b/media/ui/TOC/Right_Foot/Base.png new file mode 100644 index 0000000..b89e95b Binary files /dev/null and b/media/ui/TOC/Right_Foot/Base.png differ diff --git a/media/ui/TOC/Right_Foot/Bite.png b/media/ui/TOC/Right_Foot/Bite.png new file mode 100644 index 0000000..3ec6837 Binary files /dev/null and b/media/ui/TOC/Right_Foot/Bite.png differ diff --git a/media/ui/TOC/Right_Foot/Bleed.png b/media/ui/TOC/Right_Foot/Bleed.png new file mode 100644 index 0000000..2961263 Binary files /dev/null and b/media/ui/TOC/Right_Foot/Bleed.png differ diff --git a/media/ui/TOC/Right_Foot/Cut.png b/media/ui/TOC/Right_Foot/Cut.png new file mode 100644 index 0000000..9240f93 Binary files /dev/null and b/media/ui/TOC/Right_Foot/Cut.png differ diff --git a/media/ui/TOC/Right_Foot/Hook.png b/media/ui/TOC/Right_Foot/Hook.png new file mode 100644 index 0000000..e9d0df4 Binary files /dev/null and b/media/ui/TOC/Right_Foot/Hook.png differ diff --git a/media/ui/TOC/Right_Foot/MetalHand.png b/media/ui/TOC/Right_Foot/MetalHand.png new file mode 100644 index 0000000..3094308 Binary files /dev/null and b/media/ui/TOC/Right_Foot/MetalHand.png differ diff --git a/media/ui/TOC/Right_Foot/Operate.png b/media/ui/TOC/Right_Foot/Operate.png new file mode 100644 index 0000000..6f3eead Binary files /dev/null and b/media/ui/TOC/Right_Foot/Operate.png differ diff --git a/models_stuff/Modular_prost.psd b/python_helpers/Modular_prost.psd similarity index 86% rename from models_stuff/Modular_prost.psd rename to python_helpers/Modular_prost.psd index d0d97c3..10abaff 100644 Binary files a/models_stuff/Modular_prost.psd and b/python_helpers/Modular_prost.psd differ diff --git a/python_helpers/main.py b/python_helpers/main.py new file mode 100644 index 0000000..ab242ff --- /dev/null +++ b/python_helpers/main.py @@ -0,0 +1,198 @@ +import lxml.etree as gfg +import pandas as pd +import numpy as np +import openpyxl + + +def generate_clothing_item(name, model, texture_choices, guid = None): + root = gfg.Element("clothingItem") + + m_MaleModel = gfg.Element("m_MaleModel") + m_MaleModel.text = f"{model}_Male" + root.append(m_MaleModel) + + m_FemaleModel = gfg.Element("m_FemaleModel") + m_FemaleModel.text = f"{model}_Female" + root.append(m_FemaleModel) + + m_GUID = gfg.Element("m_GUID") + if guid: + m_GUID.text = guid + else: + m_GUID.text = "get guid from func" + + root.append(m_GUID) + + m_Static = gfg.Element("m_Static") + m_Static.text = "false" + root.append(m_Static) + + m_AllowRandomTint = gfg.Element("m_AllowRandomTint") + m_AllowRandomTint.text = "false" + root.append(m_AllowRandomTint) + + # Defined by the amount of textures that we're gonna pass + for tex in texture_choices: + textureChoices = gfg.Element("textureChoices") + textureChoices.text = tex + root.append(textureChoices) + + tree = gfg.ElementTree(root) + + path = r'python_helpers/outputs/output_clothing/' + name + ".xml" + + with open(path, "wb") as file: + tree.write(file, encoding='utf-8', xml_declaration=True, pretty_print=True ) + +def generate_recipe(recipe_name, recipe_items, result_name, time, skill_required, tooltip): + root_element = f"recipe {recipe_name}\n" + root_element += "\t{\n" + + for item in recipe_items: + root_element += f"\t\t{item},\n" + + root_element += f"\n\n\t\tResult: {result_name},\n" + root_element += f"\t\tTime: {time:.2f},\n" + root_element += "\t\tNeedToBeLearn: true,\n" + root_element += "\t\tCanBeDoneFromFloor: false,\n" + root_element += "\t\tOnGiveXP: NoXP_OnGiveXP,\n" + root_element += f"\t\tSkillRequired: {skill_required[0]}={skill_required[1]},\n" + root_element += "\t\tCategory: Surgeon,\n" + root_element += f"\t\tTooltip: {tooltip},\n" + + root_element += "\t}" + + + with open("Test_recipe.txt", "wt") as file: + file.write(root_element) + file.close() + +def generate_item(item_name, weight, item_type, display_category, display_name, icon, tooltip, can_have_holes, clothing_item=None, body_location = None, blood_location = None): + root_element = f"item {item_name}\n" + root_element += "\t{\n" + + root_element += f"\t\tWeight = {weight},\n" + root_element += f"\t\tType = {item_type},\n" + root_element += f"\t\tDisplayCategory = {display_category},\n" + root_element += f"\t\tDisplayName = {display_name},\n" + + if item_type == "Clothing": + root_element += f"\t\tClothingItem = {clothing_item},\n" + root_element += f"\t\tBodyLocation = {body_location},\n" + root_element += f"\t\tBloodLocation = {blood_location},\n" + + root_element += f"\t\tIcon = {icon},\n" + root_element += f"\t\tTooltip = {tooltip},\n" + root_element += f"\t\tCanHaveHoles = {can_have_holes.lower()},\n" + + root_element += "\t}\n" + + + path = r'python_helpers/outputs/output_item/script.txt' + + with open(path, "at") as file: + file.write(root_element) + file.close() + + +########################################################################################### +def read_table(file_name: str, table_name: str) -> pd.DataFrame: + wb = openpyxl.load_workbook(file_name, read_only= False, data_only = True) # openpyxl does not have table info if read_only is True; data_only means any functions will pull the last saved value instead of the formula + for sheetname in wb.sheetnames: # pulls as strings + sheet = wb[sheetname] # get the sheet object instead of string + if table_name in sheet.tables: # tables are stored within sheets, not within the workbook, although table names are unique in a workbook + tbl = sheet.tables[table_name] # get table object instead of string + tbl_range = tbl.ref #something like 'C4:F9' + break # we've got our table, bail from for-loop + data = sheet[tbl_range] # returns a tuple that contains rows, where each row is a tuple containing cells + content = [[cell.value for cell in row] for row in data] # loop through those row/cell tuples + header = content[0] # first row is column headers + rest = content[1:] # every row that isn't the first is data + df = pd.DataFrame(rest, columns = header) + wb.close() + return df + +########################################################################################### + +excel_path = r'python_helpers/modules_prost.xlsx' +df_base = read_table(excel_path, "BaseTable") +df_top = read_table(excel_path, "TopTable") + + +# CLOTHING GENERATION PASS + +limbs = ["Hand", "LowerArm"] +sides = ["Left", "Right"] +prost_bodylocations = ["TOC_ArmRightProsthesis", "TOC_ArmLeftProsthesis"] + + + +for base_row in df_base.iterrows(): + for top_row in df_top.iterrows(): + base_name = base_row[1][0] + top_name = top_row[1][0] + + for limb in limbs: + for side in sides: + current_name = "Prost_" + side + "_" + limb + "_" + base_name + "_" + top_name + generate_clothing_item(current_name, "test", {"test1", "test2"}, "123") + + + + + + +# ITEM GENERATION PASS - ASSEMBLED +for base_row in df_base.iterrows(): + for top_row in df_top.iterrows(): + base_id = base_row[1]["Base"] + top_id = top_row[1]["Top"] + + item_id = base_id + "_" + top_id + item_type = "Clothing" + weight = "{0:.2f}".format(float(base_row[1]["Weight"]) + float(top_row[1]["Weight"])) + display_category = "Prosthesis" + display_name = "Prosthesis - " + base_row[1]["Display Name"] + " and " + top_row[1]["Display Name"] + + for limb in limbs: + for side in sides: + clothing_item_name = "Prost_" + side + "_" + limb + "_" + base_id + "_" + top_id + bl = prost_bodylocations[0] if side == "Right" else prost_bodylocations[1] + generate_item(item_id, weight, item_type, display_category, display_name, "TempIcon", "TempTooltip", "false", clothing_item_name, bl, "TestBloodLocation") + + +# ITEM GENERATION PASS - Single item to assemble stuff +def generate_normal_items(df, type): + for row in df.iterrows(): + item_id = "ProsthPart_" + row[1][type] + item_type = "Normal" + weight = "{0:.2f}".format(float(row[1]["Weight"])) + display_category = "Prosthesis" + display_name = row[1]["Display Name"] + generate_item(item_id, weight, item_type, display_category, display_name, "TempIcon", "TempTooltip", "false") + +generate_normal_items(df_base, "Base") +generate_normal_items(df_top, "Top") + + +######################################################################################### + +recipe_name = "Test Recipe" +recipe_items = ["Ass", "Penis", "Shit=3"] +result_name = "Cum sock" +time = 10 +skill_required = ["Carpentry", "4"] +tooltip = "tooltip_test" + +#generate_recipe(recipe_name, recipe_items, result_name, time, skill_required, tooltip) + + +item_name = "Ass Ass Ass" +weight = 100 +item_type = "Clothing" +display_category = "Prosthesis" +display_name = "Ass cock" +clothing_item = "ClothingItemSomethingProst" +body_location = "TOC_ArmRightProsthesis" + +#generate_item(item_name, weight, item_type, display_category, display_name, "test_icon", "test_tooltip", "false", clothing_item, body_location, "Hands") \ No newline at end of file diff --git a/python_helpers/modules_prost.xlsx b/python_helpers/modules_prost.xlsx new file mode 100644 index 0000000..94d004e Binary files /dev/null and b/python_helpers/modules_prost.xlsx differ