From 898e8ec6535757f4c69e10bd29870f9d4ed4b51b Mon Sep 17 00:00:00 2001 From: ZioPao Date: Thu, 8 Jan 2026 01:23:53 +0100 Subject: [PATCH] refactor: restored new bodylocs --- 42/media/lua/shared/TOC/BodyLocations.lua | 163 +++++++++++------- 42/media/scripts/TOC_amputation_items.txt | 12 +- 42/media/scripts/TOC_prosthesis_items.txt | 8 +- 42/media/scripts/TOC_surgery_items.txt | 4 +- .../media/shared/TOC/BodyLocationsInit.lua | 12 +- 5 files changed, 117 insertions(+), 82 deletions(-) diff --git a/42/media/lua/shared/TOC/BodyLocations.lua b/42/media/lua/shared/TOC/BodyLocations.lua index 9add0bc..15c71ca 100644 --- a/42/media/lua/shared/TOC/BodyLocations.lua +++ b/42/media/lua/shared/TOC/BodyLocations.lua @@ -1,74 +1,109 @@ -require("TOC/Debug") -require("NPCs/BodyLocations") -local TOC = require("TOC/Registries") -local StaticData = require("TOC/StaticData") +--Based on RabenRabo's bodylocation solution from their mod "Fantasy Bodyparts" and "Fantasy Legs" sub-mod. +--Modified by GanydeBielovzki with permission for batch use for the Frockin' Splendor franchise and spin-offs. +--To copy, further modify or otherwise use this code the original creator and the modifier must be credited. -local BodyLocationsAPI = {} -local function customGetVal(obj, int) return getClassFieldVal(obj, getClassField(obj, int)) end -local group = BodyLocations.getGroup("Human") - ----@type ArrayList -local list = customGetVal(group, 1) - ----@param bodyLoc string -function BodyLocationsAPI.New(bodyLoc) - curItem = group:getOrCreateLocation(bodyLoc) -- get current item - or create - return curItem +local function copyBodyLocationProperties(oldGroup, oldLocID, newGroup) + for k = 0, oldGroup:size()-1 do + local otherLocID = oldGroup:getLocationByIndex(k):getId() + if oldGroup:isExclusive(oldLocID, otherLocID) + then + newGroup:setExclusive(oldLocID, otherLocID) + end + if oldGroup:isHideModel(oldLocID, otherLocID) + then + newGroup:setHideModel(oldLocID, otherLocID) + end + if oldGroup:isAltModel(oldLocID, otherLocID) + then + newGroup:setAltModel(oldLocID, otherLocID) + end + end end --- TODO Not sure if this method actually works as intende with b42, but for our use case it's fine... ----@param toRelocateOrCreate string ----@param locationElement string ----@param afterBoolean boolean ----@return BodyLocation -function BodyLocationsAPI.MoveOrCreateBeforeOrAfter(toRelocateOrCreate, locationElement, afterBoolean) - -- Check type of arg 2 == string - if not error out. - if type(locationElement) ~= "string" then error("Argument 2 is not of type string. Please re-check!", 2) end - local itemToMoveTo = group:getLocation(locationElement) -- get location to move to - if itemToMoveTo ~= nil then - -- Check type of arg 1 == string - if not, error out. - if type(toRelocateOrCreate) ~= "string" then error("Argument 1 is not of type string. Please re-check!", 2) end +local function addBodyLocationsAt(groupName, locationList) + local results = {} - local curItem = BodyLocationsAPI.New(toRelocateOrCreate) - list:remove(curItem) -- remove from the list - local index = group:indexOf(locationElement) -- get current index after removal of the location to move to - if afterBoolean then index = index + 1 end -- if we want it after it, we increase the index to move to by one - list:add(index, curItem) -- we add the item again + -- get list (!!actually a view!!) of all groups and copy to array (BodyLocations.reset() will also clear the view) + local allGroupsList = BodyLocations.getAllGroups() + local allGroups = {} + for i = 0, allGroupsList:size()-1 do + allGroups[i + 1] = allGroupsList:get(i) + end + BodyLocations.reset() - return curItem - else -- we did not find the location to move to, so we throw an error. - error("Could not find the BodyLocation [".. tostring(locationElement) .."] - please check the passed arguments!", 2) - end + -- recreate all groups/bodylocations and insert new bodylocations + for i = 1, #allGroups do + local oldGroup = allGroups[i] + local newGroup = BodyLocations.getGroup(oldGroup:getId()) + + -- FIRST: Process all original locations AND insert new ones at correct positions + for j = 0, oldGroup:size()-1 do + local oldLoc = oldGroup:getLocationByIndex(j) + local oldLocID = oldLoc:getId() + + -- For each location definition, check if it should be inserted here + for _, locDef in ipairs(locationList) do + if oldGroup:getId() == groupName then + local newLocID = type(locDef.name) ~= "string" and locDef.name or + ItemBodyLocation.get(ResourceLocation.of(locDef.name)) + + local refLocID = type(locDef.reference) ~= "string" and locDef.reference or + ResourceLocation.of(locDef.reference) + + local isTargetGroupAndLoc = refLocID == oldLocID + + if isTargetGroupAndLoc and locDef.before then + results[locDef.name] = newGroup:getOrCreateLocation(newLocID) + end + end + end + + -- Add the original location + newGroup:getOrCreateLocation(oldLocID) + + -- Check for "after" insertions + for _, locDef in ipairs(locationList) do + if oldGroup:getId() == groupName then + local newLocID = type(locDef.name) ~= "string" and locDef.name or + ItemBodyLocation.get(ResourceLocation.of(locDef.name)) + + local refLocID = type(locDef.reference) ~= "string" and locDef.reference or + ResourceLocation.of(locDef.reference) + + local isTargetGroupAndLoc = refLocID == oldLocID + + if isTargetGroupAndLoc and not locDef.before then + results[locDef.name] = newGroup:getOrCreateLocation(newLocID) + end + end + end + end + + -- SECOND: copy bodylocation properties from old groups to new groups + for j = 0, oldGroup:size()-1 do + local oldLocID = oldGroup:getLocationByIndex(j):getId() + newGroup:setMultiItem(oldLocID, oldGroup:isMultiItem(oldLocID)) + copyBodyLocationProperties(oldGroup, oldLocID, newGroup) + end + end + + return results end +local results = addBodyLocationsAt("Human", { + {name = "toc:Arm_L", reference = ItemBodyLocation.FULL_TOP, before = false}, + {name = "toc:Arm_R", reference = ItemBodyLocation.FULL_TOP, before = false}, + {name = "toc:ArmProst_L", reference = ItemBodyLocation.FULL_TOP, before = false}, + {name = "toc:ArmProst_R", reference = ItemBodyLocation.FULL_TOP, before = false}, + {name = "toc:ArmAccessory_L", reference = ItemBodyLocation.FULL_TOP, before = false}, + {name = "toc:ArmAccessory_R", reference = ItemBodyLocation.FULL_TOP, before = false}, +}) --- function TestBodyLocations() --- local group = BodyLocations.getGroup("Human") --- local x = group:getAllLocations() - --- for i=0, x:size() -1 do - --- ---@type BodyLocation --- local bl = x:get(i) - --- print(bl:getId()) --- end --- end - --- MultiItem causes a ton of issues... fucking hell - --- local curItem = BodyLocation.new(group, "TOC_Arm_L") --- group:getAllLocations():add(curItem) - --- local curItem = BodyLocation.new(group, "TOC_Arm_R") --- group:getAllLocations():add(curItem) - - -BodyLocationsAPI.New(TOC.bodylocations.TOC_Arm_L) -BodyLocationsAPI.New(TOC.bodylocations.TOC_Arm_R) -BodyLocationsAPI.New(TOC.bodylocations.TOC_ArmProst_L) -BodyLocationsAPI.New(TOC.bodylocations.TOC_ArmProst_R) -BodyLocationsAPI.New(TOC.bodylocations.TOC_ArmAccessory_L) -BodyLocationsAPI.New(TOC.bodylocations.TOC_ArmAccessory_R) +results['toc:Arm_L']:setMultiItem(true) +results['toc:Arm_R']:setMultiItem(true) +results['toc:ArmProst_L']:setMultiItem(true) +results['toc:ArmProst_R']:setMultiItem(true) +results['toc:ArmAccessory_L']:setMultiItem(true) +results['toc:ArmAccessory_R']:setMultiItem(true) diff --git a/42/media/scripts/TOC_amputation_items.txt b/42/media/scripts/TOC_amputation_items.txt index 98ee59a..cc8995b 100644 --- a/42/media/scripts/TOC_amputation_items.txt +++ b/42/media/scripts/TOC_amputation_items.txt @@ -12,7 +12,7 @@ module TOC hidden = true, ClothingItem = Amputation_Hand_R, - BodyLocation = toc:TOC_Arm_R, + BodyLocation = toc:Arm_R, Weight = 0, CombatSpeedModifier = 0.9, @@ -31,7 +31,7 @@ module TOC hidden = true, ClothingItem = Amputation_ForeArm_R, - BodyLocation = toc:TOC_Arm_R, + BodyLocation = toc:Arm_R, Weight = 0, CombatSpeedModifier = 0.8, @@ -49,7 +49,7 @@ module TOC hidden = true, ClothingItem = Amputation_UpperArm_R, - BodyLocation = toc:TOC_Arm_R, + BodyLocation = toc:Arm_R, BloodLocation = UpperArms;UpperBody, Weight = 0, CombatSpeedModifier = 0.7, @@ -66,7 +66,7 @@ module TOC hidden = true, ClothingItem = Amputation_Hand_L, - BodyLocation = toc:TOC_Arm_L, + BodyLocation = toc:Arm_L, Weight = 0, CombatSpeedModifier = 0.9, @@ -85,7 +85,7 @@ module TOC hidden = true, ClothingItem = Amputation_ForeArm_L, - BodyLocation = toc:TOC_Arm_L, + BodyLocation = toc:Arm_L, Weight = 0, CombatSpeedModifier = 0.8, @@ -104,7 +104,7 @@ module TOC hidden = true, ClothingItem = Amputation_UpperArm_L, - BodyLocation = toc:TOC_Arm_L, + BodyLocation = toc:Arm_L, Weight = 0, CombatSpeedModifier = 0.7, diff --git a/42/media/scripts/TOC_prosthesis_items.txt b/42/media/scripts/TOC_prosthesis_items.txt index 97acd9e..2f288a0 100644 --- a/42/media/scripts/TOC_prosthesis_items.txt +++ b/42/media/scripts/TOC_prosthesis_items.txt @@ -16,7 +16,7 @@ module TOC ClothingItemExtra = Prost_HookArm_R, ClothingItemExtraOption = InstallProstRight, clothingExtraSubmenu = InstallProstLeft, - BodyLocation = toc:TOC_ArmProst_L, + BodyLocation = toc:ArmProst_L, Weight = 1.5, CombatSpeedModifier = 1.05, BloodLocation = UpperArms;UpperBody, @@ -38,7 +38,7 @@ module TOC ClothingItemExtra = Prost_HookArm_L, ClothingItemExtraOption = InstallProstLeft, clothingExtraSubmenu = InstallProstRight, - BodyLocation = toc:TOC_ArmProst_R, + BodyLocation = toc:ArmProst_R, Weight = 1.5, CombatSpeedModifier = 1.05, BloodLocation = UpperArms;UpperBody, @@ -60,7 +60,7 @@ module TOC ClothingItemExtra = Prost_NormalArm_R, ClothingItemExtraOption = InstallProstRight, clothingExtraSubmenu = InstallProstLeft, - BodyLocation = toc:TOC_ArmProst_L, + BodyLocation = toc:ArmProst_L, Weight = 2, CombatSpeedModifier = 1.1, BloodLocation = UpperArms;UpperBody, @@ -82,7 +82,7 @@ module TOC ClothingItemExtra = Prost_NormalArm_L, ClothingItemExtraOption = InstallProstLeft, clothingExtraSubmenu = InstallProstRight, - BodyLocation = toc:TOC_ArmProst_R, + BodyLocation = toc:ArmProst_R, Weight = 2, CombatSpeedModifier = 1.1, BloodLocation = UpperArms;UpperBody, diff --git a/42/media/scripts/TOC_surgery_items.txt b/42/media/scripts/TOC_surgery_items.txt index a93b8a8..0d2d954 100644 --- a/42/media/scripts/TOC_surgery_items.txt +++ b/42/media/scripts/TOC_surgery_items.txt @@ -15,7 +15,7 @@ module TOC ClothingItemExtra = Surg_Arm_Tourniquet_R, ClothingItemExtraOption = PutTourniquetArmRight, clothingExtraSubmenu = PutTourniquetArmLeft, - BodyLocation = toc:TOC_ArmAccessory_L, + BodyLocation = toc:ArmAccessory_L, BloodLocation = UpperArms;UpperBody, Weight = 0.25, @@ -35,7 +35,7 @@ module TOC ClothingItemExtra = Surg_Arm_Tourniquet_L, ClothingItemExtraOption = PutTourniquetArmLeft, clothingExtraSubmenu = PutTourniquetArmRight, - BodyLocation = toc:TOC_ArmAccessory_R, + BodyLocation = toc:ArmAccessory_R, BloodLocation = UpperArms;UpperBody, Weight = 0.25, diff --git a/test/42.12/media/shared/TOC/BodyLocationsInit.lua b/test/42.12/media/shared/TOC/BodyLocationsInit.lua index 3cc757c..08a9f90 100644 --- a/test/42.12/media/shared/TOC/BodyLocationsInit.lua +++ b/test/42.12/media/shared/TOC/BodyLocationsInit.lua @@ -1,8 +1,8 @@ local BodyLocationsAPI = require("TOC/BodyLocations") -BodyLocationsAPI.New("TOC_Arm_L") -BodyLocationsAPI.New("TOC_Arm_R") -BodyLocationsAPI.New("TOC_ArmProst_L") -BodyLocationsAPI.New("TOC_ArmProst_R") -BodyLocationsAPI.New("TOC_ArmAccessory_L") -BodyLocationsAPI.New("TOC_ArmAccessory_R") \ No newline at end of file +BodyLocationsAPI.New("Arm_L") +BodyLocationsAPI.New("Arm_R") +BodyLocationsAPI.New("ArmProst_L") +BodyLocationsAPI.New("ArmProst_R") +BodyLocationsAPI.New("ArmAccessory_L") +BodyLocationsAPI.New("ArmAccessory_R") \ No newline at end of file