blubuild Posted October 20, 2016 Share Posted October 20, 2016 Like some other things... the functions and tables related to tumbleweed loot and grave mounds loot are all defined as local, and therefore are inaccessible to the outside/mods. So there's no way to merely add/remove/change a loot item, mods must duplicate at least some of the existing code of the prefab's functions, including the whole existing loot list, to affect the loot, which isn't so good for compatibility and robustness, as that will has to be re-done every time that part of the game was updated (as just happened in the latest update) and the mod re-released, otherwise the official update will be overwritten or worse, something may be broken in some way (due to "partially updated" code), and multiple mods using this method will also generally completely overwrite each other. So this is a suggestion to change tumbleweed.lua and mound.lua to make the loot generation functions and loot lists available to the outside in some fashion. Ideally for other modding interests the same would be the case for any other general loot lists that aren't changable in a good way which I'm not aware of (random chests? ruins chests?). There's a global PickRandomTrinket() in trinkets.lua used for grave mounds which is a good start, but the rest of the loot and logic are still local in mound.lua. For example, the relevant parts of tumbleweed.lua look like this (seems to me like there's a bit of unused stuff in that file, by the way): Spoiler ... ... ... local prefabs = { "splash_ocean", "tumbleweedbreakfx", "ash", "cutgrass", "twigs", "petals", "foliage", "silk", "rope", "seeds", "purplegem", "bluegem", "redgem", "orangegem", "yellowgem", "greengem", "seeds", "trinket_6", "cutreeds", "feather_crow", "feather_robin", "feather_robin_winter", "feather_canary", "trinket_3", "beefalowool", "rabbit", "mole", "butterflywings", "fireflies", "beardhair", "berries", "TOOLS_blueprint", "LIGHT_blueprint", "SURVIVAL_blueprint", "FARM_blueprint", "SCIENCE_blueprint", "WAR_blueprint", "TOWN_blueprint", "REFINE_blueprint", "MAGIC_blueprint", "DRESS_blueprint", "petals_evil", "trinket_8", "houndstooth", "stinger", "gears", "spider", "frog", "bee", "mosquito", "boneshard", } local CHESS_LOOT = { "chesspiece_pawn_sketch", "chesspiece_muse_sketch", "chesspiece_formal_sketch", "trinket_15", --bishop "trinket_16", --bishop "trinket_28", --rook "trinket_29", --rook "trinket_30", --knight "trinket_31", --knight } for k, v in ipairs(CHESS_LOOT) do table.insert(prefabs, v) end ... ... ... local function MakeLoot(inst) local possible_loot = { {chance = 40, item = "cutgrass"}, {chance = 40, item = "twigs"}, {chance = 1, item = "petals"}, {chance = 1, item = "foliage"}, {chance = 1, item = "silk"}, {chance = 1, item = "rope"}, {chance = 1, item = "seeds"}, {chance = 0.01, item = "purplegem"}, {chance = 0.04, item = "bluegem"}, {chance = 0.02, item = "redgem"}, {chance = 0.02, item = "orangegem"}, {chance = 0.01, item = "yellowgem"}, {chance = 0.02, item = "greengem"}, {chance = 1, item = "seeds"}, {chance = 0.5, item = "trinket_6"}, {chance = 0.5, item = "trinket_4"}, {chance = 1, item = "cutreeds"}, {chance = 0.33, item = "feather_crow"}, {chance = 0.33, item = "feather_robin"}, {chance = 0.33, item = "feather_robin_winter"}, {chance = 0.33, item = "feather_canary"}, {chance = 1, item = "trinket_3"}, {chance = 1, item = "beefalowool"}, {chance = 0.1, item = "rabbit"}, {chance = 0.1, item = "mole"}, {chance = 0.1, item = "spider", aggro = true}, {chance = 0.1, item = "frog", aggro = true}, {chance = 0.1, item = "bee", aggro = true}, {chance = 0.1, item = "mosquito", aggro = true}, {chance = 1, item = "butterflywings"}, {chance = .02, item = "beardhair"}, {chance = 1, item = "berries"}, {chance = 0.1, item = "TOOLS_blueprint"}, {chance = 0.1, item = "LIGHT_blueprint"}, {chance = 0.1, item = "SURVIVAL_blueprint"}, {chance = 0.1, item = "FARM_blueprint"}, {chance = 0.1, item = "SCIENCE_blueprint"}, {chance = 0.1, item = "WAR_blueprint"}, {chance = 0.1, item = "TOWN_blueprint"}, {chance = 0.1, item = "REFINE_blueprint"}, {chance = 0.1, item = "MAGIC_blueprint"}, {chance = 0.1, item = "DRESS_blueprint"}, {chance = 1, item = "petals_evil"}, {chance = 1, item = "trinket_8"}, {chance = 1, item = "houndstooth"}, {chance = 1, item = "stinger"}, {chance = 1, item = "gears"}, {chance = 0.1, item = "boneshard"}, } local chessunlocks = TheWorld.components.chessunlocks if chessunlocks ~= nil then for i, v in ipairs(CHESS_LOOT) do if not chessunlocks:IsLocked(v) then table.insert(possible_loot, { chance = .1, item = v }) end end end local totalchance = 0 for m, n in ipairs(possible_loot) do totalchance = totalchance + n.chance end inst.loot = {} inst.lootaggro = {} local next_loot = nil local next_aggro = nil local next_chance = nil local num_loots = 3 while num_loots > 0 do next_chance = math.random()*totalchance next_loot = nil next_aggro = nil for m, n in ipairs(possible_loot) do next_chance = next_chance - n.chance if next_chance <= 0 then next_loot = n.item if n.aggro then next_aggro = true end break end end if next_loot ~= nil then table.insert(inst.loot, next_loot) if next_aggro then table.insert(inst.lootaggro, true) else table.insert(inst.lootaggro, false) end num_loots = num_loots - 1 end end end ... ... ... local function fn() local inst = CreateEntity() ... MakeLoot(inst) ... return inst end They could be reconstructed to something more extensible, along these lines (don't know if it's totally right as directly working code): Spoiler ... ... ... local prefabs = { "splash_ocean", "tumbleweedbreakfx", } TUNING.TUMBLEWEED_CHESS_LOOT = TUNING.TUMBLEWEED_CHESS_LOOT or { "chesspiece_pawn_sketch", "chesspiece_muse_sketch", "chesspiece_formal_sketch", "trinket_15", --bishop "trinket_16", --bishop "trinket_28", --rook "trinket_29", --rook "trinket_30", --knight "trinket_31", --knight } for k, v in pairs(TUNING.TUMBLEWEED_CHESS_LOOT) do table.insert(prefabs, v) end TUNING.TUMBLEWEED_BASE_LOOT = TUNING.TUMBLEWEED_BASE_LOOT or { {chance = 40, item = "cutgrass"}, {chance = 40, item = "twigs"}, {chance = 1, item = "petals"}, {chance = 1, item = "foliage"}, {chance = 1, item = "silk"}, {chance = 1, item = "rope"}, {chance = 1, item = "seeds"}, {chance = 0.01, item = "purplegem"}, {chance = 0.04, item = "bluegem"}, {chance = 0.02, item = "redgem"}, {chance = 0.02, item = "orangegem"}, {chance = 0.01, item = "yellowgem"}, {chance = 0.02, item = "greengem"}, {chance = 1, item = "seeds"}, {chance = 0.5, item = "trinket_6"}, {chance = 0.5, item = "trinket_4"}, {chance = 1, item = "cutreeds"}, {chance = 0.33, item = "feather_crow"}, {chance = 0.33, item = "feather_robin"}, {chance = 0.33, item = "feather_robin_winter"}, {chance = 0.33, item = "feather_canary"}, {chance = 1, item = "trinket_3"}, {chance = 1, item = "beefalowool"}, {chance = 0.1, item = "rabbit"}, {chance = 0.1, item = "mole"}, {chance = 0.1, item = "spider", aggro = true}, {chance = 0.1, item = "frog", aggro = true}, {chance = 0.1, item = "bee", aggro = true}, {chance = 0.1, item = "mosquito", aggro = true}, {chance = 1, item = "butterflywings"}, {chance = .02, item = "beardhair"}, {chance = 1, item = "berries"}, {chance = 0.1, item = "TOOLS_blueprint"}, {chance = 0.1, item = "LIGHT_blueprint"}, {chance = 0.1, item = "SURVIVAL_blueprint"}, {chance = 0.1, item = "FARM_blueprint"}, {chance = 0.1, item = "SCIENCE_blueprint"}, {chance = 0.1, item = "WAR_blueprint"}, {chance = 0.1, item = "TOWN_blueprint"}, {chance = 0.1, item = "REFINE_blueprint"}, {chance = 0.1, item = "MAGIC_blueprint"}, {chance = 0.1, item = "DRESS_blueprint"}, {chance = 1, item = "petals_evil"}, {chance = 1, item = "trinket_8"}, {chance = 1, item = "houndstooth"}, {chance = 1, item = "stinger"}, {chance = 1, item = "gears"}, {chance = 0.1, item = "boneshard"}, } for k,v in pairs(TUNING.TUMBLEWEED_BASE_LOOT) do table.insert(prefabs, t.item) end TUNING.TUMBLEWEED_NUM_LOOTS = TUNING.TUMBLEWEED_NUM_LOOTS or 3 ... ... ... function ConstructTumbleweedLoot(baseloot) local loot = deepcopy(baseloot) local chessunlocks = TheWorld.components.chessunlocks if chessunlocks ~= nil then for k, v in pairs(TUNING.TUMBLEWEED_CHESS_LOOT) do if not chessunlocks:IsLocked(v) then table.insert(loot, { chance = .1, item = v }) end end end return loot end function PickTumbleweedLoot(inst,possible_loot) local totalchance = 0 for m, n in pairs(possible_loot) do totalchance = totalchance + n.chance end local next_loot = nil local next_aggro = nil local next_chance = nil local num_loots = TUNING.TUMBLEWEED_NUM_LOOTS while num_loots > 0 do next_chance = math.random()*totalchance next_loot = nil next_aggro = nil for m, n in pairs(possible_loot) do next_chance = next_chance - n.chance if next_chance <= 0 then next_loot = n.item if n.aggro then next_aggro = true end break end end if next_loot ~= nil then table.insert(inst.loot, next_loot) if next_aggro then table.insert(inst.lootaggro, true) else table.insert(inst.lootaggro, false) end num_loots = num_loots - 1 end end end function MakeTumbleweedLoot(inst,baseloot) local possible_loot = ConstructTumbleweedLoot(baseloot) inst.loot = {} inst.lootaggro = {} PickTumbleweedLoot(inst,possible_loot) end ... ... ... local function fn() local inst = CreateEntity() ... MakeTumbleweedLoot(inst,TUNING.TUMBLEWEED_BASE_LOOT) ... return inst end I guess I also I think it'd be better if the loot list would be transformed to a simpler {prefabname = chance} table instead (aggro flag could be kept track of elsewhere, like in another table {prefabwithaggroname = true} ,or in a general prefabs flags list if more flags like aggro are planned {prefabwithflagsname = {aggro = true, otherflag = 3} } ) and the tumbleweed's loot was determined on pickup rather than on creation. But ignoring that, with the current way of things and with the above code changes as an example, mods could then robustly modify the loot like so: AddSimPostInit(function() --tumbleweed.lua is loaded after modmain.lua, postinit won't be needed if TUNING lines and function definitions are moved to an earlier loaded file like tuning.lua local loot = TUNING.TUMBLEWEED_BASE_LOOT local remove_items = table.invert{"cutgrass", "twigs", "petals"} -- tumbleweeds don't give these items anymore local function strends(String,End) return End=='' or string.sub(String,-string.len(End))==End end for k,v in pairs(loot) do if remove_items[v.item] then table.remove(loot,k) -- remove the item's entry from the loot table elseif strends(v.item,"gem") v.chance = 5 -- change the relative chance of all gems to 5%, instead of the original end end table.insert( loot, {item = "butter", chance = 10} ) -- add butter as possible loot, with 10% relative chance -- conditional/more complex loot modification: -- override the original function local orig_construct = GLOBAL.ConstructTumbleweedLoot GLOBAL.ConstructTumbleweedLoot = function(...) local ret = orig_construct(...) if GLOBAL.TheWorld.state.season == "winter" then table.insert(ret, {item = "ice", chance = 20} ) -- tumblweed may drop ice in winter only elseif GLOBAL.TheWorld.state.season == "summer" then table.insert(ret, {item = "cactus_flower", chance = 10} ) -- tumblweed may drop cactus flower in summer only end return ret end end) Of course, it doesn't have to look exactly like that, the important thing is that the code is set up in some extensible fashion that makes the base loot list, loot list construction function and loot picking function (which are currently in the same, local function, ideally they'd be separated, like above) accessible and overridable. So, stored in some kind of global var or member var attached to the tumbleweed (in that case) prefab, which makes it at least changable with AddPrefabPostInit (kind of an inefficient way to make the same change to every single created prefab instance, but at least it works well). Link to comment https://forums.kleientertainment.com/forums/topic/70997-exposed-for-proper-modding-loot-for-tumbleweeds-and-graves/ Share on other sites More sharing options...
blubuild Posted November 10, 2016 Author Share Posted November 10, 2016 So, it appears that there's no interest by the game devs to improve the moddability of things. Is something to this extent planned to ever be done at all? Link to comment https://forums.kleientertainment.com/forums/topic/70997-exposed-for-proper-modding-loot-for-tumbleweeds-and-graves/#findComment-835860 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.
Please be aware that the content of this thread may be outdated and no longer applicable.