Jump to content

DarkXero

Registered Users
  • Posts

    3016
  • Joined

  • Last visited

Reputation

2897 Excellent

Badges

  • Don't Starve Together
    Contributor
  • Oxygen Not Included
    Alpha Contributor

Recent Profile Visitors

16682 profile views
  1. Yeah, you're right. Fair enough. local function EpicFilter(ret) local newret = {} for i, e in ipairs(ret) do if not e:HasTag("structure") then newret[i] = e end end return newret end -- absolute madman stuff local hax = GLOBAL.debug.getlocal AddPrefabPostInit("world", function(world) if world.ismastersim then local t = GLOBAL.getmetatable(GLOBAL.TheSim).__index local fe = t.FindEntities t.FindEntities = function(...) local ret = fe(...) if ret then local i = 1 while true do local name, value = hax(2, i) if not name then break end if name == "inst" then if value:HasTag("epic") then ret = EpicFilter(ret) else break end end if name == "self" then if value.inst and value.inst:HasTag("epic") then ret = EpicFilter(ret) else break end end i = i + 1 end end return ret end end end) -- special bearger collision edge case local _work = GLOBAL.require("components/workable") local _destroy = _work.Destroy _work.Destroy = function(self, destroyer) if destroyer and destroyer:HasTag("epic") then return end return _destroy(destroyer) end This one is server side too.
  2. if not GLOBAL.TheNet:GetIsServer() then return end local _HammerFn = GLOBAL.ACTIONS.HAMMER.fn GLOBAL.ACTIONS.HAMMER.fn = function(act) act.target.components.workable = act.target.components.hammerworkable local ret = _HammerFn(act) act.target.components.workable = nil return ret end local function AntiWork(inst) inst.components.hammerworkable = inst.components.workable inst.components.workable = nil end local function HammerFix(inst) if inst:HasTag("structure") and inst.components.workable and inst.components.workable.action == GLOBAL.ACTIONS.HAMMER then inst:DoTaskInTime(0, AntiWork) end end AddPrefabPostInitAny(HammerFix) Should be good as a server mod?
  3. It would help if you posted the mod or more data. AnimState should propagate correctly to clients when changing (using "Show"). As an example, here's the correct usage: -- prefab file local function PlayerFix(inst) if not inst:HasTag("depleted") then inst.extractor.AnimState:Show("salt") end end local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() -- ... inst.entity:AddNetwork() -- here inst:ListenForEvent("ms_playerjoined", function(world, player) PlayerFix(inst) end, TheWorld) -- ... inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end -- ... return inst end More interesting would be to see the extractor prefab. It's probably missing a AddNetwork that would solve this without hassle.
  4. I was going to write it but then I realized that I ****** up and I was the one generating the new herds with my debug lines. So yeah, domestication it is. The other way was my fault. My bad for raising hopes. If I figure something out I will post new results.
  5. It's not the only way but it is a valid way. A domesticated beefalo abandons its herd and when it goes feral it creates a new one.
  6. TUNING is a global table from where the server fetches values. If your character exists and edits that table, all other characters benefit. This isn't an issue in Don't Starve single-player because your character doesn't exist with others in the same world instance. Which means that you either have to make a mechanic unique to the character (give him a special mechanic that replaces fertilize with values unique to him), or to intercept the fertilization at a point where you can define who's doing the fertilizing. Where to do the interception only comes with experience and creativity. Lets go step by step. TUNING.POOP_FERTILIZE = TUNING.POOP_FERTILIZE * 1.5 TUNING.POOP_SOILCYCLES = TUNING.POOP_SOILCYCLES * 1.5 TUNING.GUANO_FERTILIZE = TUNING.GUANO_FERTILIZE * 1.5 TUNING.GUANO_SOILCYCLES = TUNING.GUANO_SOILCYCLES * 1.5 These values get attached to fertilizer when the fertilizer is spawned in the world. We want to edit items in particular. -- reference to global table local TUNING = GLOBAL.TUNING local bonuses = { poop = { value = 1.5, soil = 1.5, }, guano = { value = 1.5, soil = 1.5, }, } local function improveFertilizer(doer, item) -- see if it's our character if doer and doer.prefab == "eliyth" then -- see if item is fertilizer if item and item.components.fertilizer then -- get value or empty table if there's no value local bonus = bonuses[item.prefab] or {} -- get value or value that changes nothing local bonus1 = bonus.value or 1 local bonus2 = bonus.soil or 1 item.components.fertilizer.fertilizervalue = item.components.fertilizer.fertilizervalue * bonus1 item.components.fertilizer.soil_cycles = item.components.fertilizer.soil_cycles * bonus2 end end end local function restoreFertilizer(doer, item) if doer and doer.prefab == "eliyth" then -- item did what it had to do, now time to go back to normal -- check if it's valid, it may have been one single poop (removed) instead of a stack of it (still valid) if item and item.components.fertilizer and item:IsValid() then local bonus = bonuses[item.prefab] or {} local bonus1 = bonus.value or 1 local bonus2 = bonus.soil or 1 -- division instead of multiplication item.components.fertilizer.fertilizervalue = item.components.fertilizer.fertilizervalue / bonus1 item.components.fertilizer.soil_cycles = item.components.fertilizer.soil_cycles / bonus2 end end end -- save old action function local old_FERTILIZE_fn = GLOBAL.ACTIONS.FERTILIZE.fn GLOBAL.ACTIONS.FERTILIZE.fn = function(act) -- improve item if it deserves it improveFertilizer(act.doer, act.invobject) -- do the action of fertilizing local ret = old_FERTILIZE_fn(act) -- restore item if it needs it restoreFertilizer(act.doer, act.invobject) -- return if action went well return ret end This in modmain should do the trick. What did those values do? Edit the effectiveness of fertilizer. The higher the bonus, the less items you use to fertilize. One poop equals two. ... now here's an interesting problem. TUNING.SEEDS_GROW_TIME = TUNING.SEEDS_GROW_TIME * (4 / 6) TUNING.FARM1_GROW_BONUS = TUNING.FARM1_GROW_BONUS / 2 TUNING.FARM2_GROW_BONUS = TUNING.FARM1_GROW_BONUS / 2 TUNING.FARM3_GROW_BONUS = TUNING.FARM1_GROW_BONUS / 2 These values alter not only the effectiveness of fertilizer, but the effectiveness of farm plot and the speed of seed growth. Those are unrelated values to fertilizing. Those are also applied globally. The question is: how does our character relate to those values? Food grows faster, but what did our character do about it? Did he make the farmplot? Did he fertilize the farmplot? Does the bonus apply forever after our character interacts with the farmplot? Many questions to ask... yet useless, because what you want is just to be more efficient fertilizing. You should only touch the fertilizing values. Instead of making fertilizer more efficient by making the crops requiring less time, make fertilizer more efficient by making it more potent. So instead of implementing the TUNING modification, editing the bonuses is enough. local bonuses = { poop = { value = 3, soil = 1.5, }, guano = { value = 3, soil = 1.5, }, } Value is for how much time they skip. Soil is for how much soil they renew (you can't plant forever in farms unless you put poop in the dirt). Of course, if you want faster farms, then you've a design issue to tackle more than a code issue. For the flower planting, you can do it like this. In modmain.lua, we do the deployable stuff: -- this table loads files in scripts/prefabs inside your mod folder -- this way you can include prefab files for yourself PrefabFiles = { "petals_evil_placer", } -- function from the butterfly file local function OnDeploy(inst, pt, deployer) -- if our character deploys, spawn; otherwise just complain if deployer.prefab == "eliyth" then -- spawn flower local flower = GLOBAL.SpawnPrefab("flower_evil") -- set flower position to deployed position flower.Transform:SetPosition(pt:Get()) -- remove the petal deployed inst.components.stackable:Get():Remove() else -- complain deployer.components.talker:Say("I should find Eliyth for this!") -- return petal to inventory deployer.components.inventory:GiveItem(inst.components.stackable:Get()) end end -- for evil petal entities AddPrefabPostInit("petals_evil", function(inst) -- if instance is server, the deployable component exists, edit it then if GLOBAL.TheWorld.ismastersim then -- make it deployable inst:AddComponent("deployable") inst.components.deployable.ondeploy = OnDeploy inst.components.deployable:SetDeployMode(GLOBAL.DEPLOYMODE.PLANT) end end) And in your scripts/prefabs folder you will have a petals_evil_placer.lua file that will contain this: return MakePlacer("petals_evil_placer", "flower_petals_evil", "flower_petals_evil", "anim") (Just like how butterfly has a butterfly_placer inside the file, but we don't have one of those for petals.)
  7. To test code, I always do it with caves enabled. The game makes a dedicated instance and then connects me to it. This way the game loads server side mods on the server instance, client side mods on the client instance, and the rest on both. all_clients_require_mod = false // client_only_mod = false => server side only all_clients_require_mod = true // client_only_mod = false => server and client side loaded all_clients_require_mod = false // client_only_mod = true => client side only all_clients_require_mod = true // client_only_mod = true => nonsense I don't have to use the workshop at all, I just go to the world tab, enable caves, go to the mod tab, enable mods. When you don't have caves enabled, all mods are loaded (because the instance you see is both server and client, you are the server, your interactions with the world instance are the same like in Don't Starve, lag never bothers you). To debug, I read the relevant logs (client_log.txt on DoNotStarveTogether with no caves or with caves and client crashes, or server_log.txt on the Cluster_X/Master or Caves folder with caves and server crashes). When the server crashes, clients just disconnect. I do admit it is cumbersome to have to reload each log when I'm looking for sequences of messages. What I also use is the c_announce console command instead of print, to make the clients see messages on top of the screen.
  8. local function hello(inst) GLOBAL.print("hey") end AddPrefabPostInit("world", function(inst) if inst.ismastersim then inst:DoPeriodicTask(3, hello) end end)
  9. They behave like goats now (kind of). No more exponential growth. No more servers with 40 herds and over 300 beefalo. Or phantom herds. Kill all but one, and lure it with feeding or saddle and ride it to displace the herd. Beefalo herd updates every 8 seconds for members within a 20 units radius (about 3 and a half tiles). Important to not fully domesticate the lone beef, or the herd won't be able to find a feral parent inside the herd to attach the baby. Another way would be the following: 1) Wait until there's baby beefalo. 2) Kill everything but 1 baby beefalo. 3) Relocate the lone baby beefalo with teleportation. When the baby grows, the baby will be deleted. The herd will be empty and removed. The herd will no longer be valid. A new grown beefalo will spawn on its place. Since the herd is no longer valid, a new herd will spawn there. A problem may arise where you teleport the baby, but the beefalo herd was on the mood and spawning babies, so a new baby spawns next to your baby. If your baby grows, the herd will still be valid. Now you will have your grown baby, and the new baby, running against the wall trying to return to the herd that's far away. To avoid this problem you would need to do the herd relocation outside Spring or if they're in the mood. All of this because the herd only updates positions for the members that are nearby. It is truly a conundrum. What's the difference between a herd with a member that's 10 units away from the update range versus a herd with a member that's 50 units away from the update range? Maybe the telelocator staff should make teleported units leave the herd and make their own? But then we could make new herds from a single herd: teleport one goat and one beefalo from a herd to duplicate herds... Would it be balanced to make gigantic meat farms with telelocator staffs and bases? We could also make it so if you have 1 member only, the herd position updates no matter what. This would fix the telelocation issue. But then this means that any herds with 1 single member will wander to zones of the map where they shouldn't be. Beefalo would wander way outside the savannah, since the herd point would keep moving with them. We could also apply the goat treatment: if you have one beefalo, you push it to where you want the herd. -- babybeefalo.lua local function SetFullyGrown(inst) local herd = inst.components.herdmember ~= nil and inst.components.herdmember:GetHerd() or nil local count = herd ~= nil and herd.components.herd ~= nil and herd.components.herd.membercount or nil local grown = SpawnPrefab("beefalo") grown.Transform:SetPosition(inst.Transform:GetWorldPosition()) grown.Transform:SetRotation(inst.Transform:GetRotation()) grown.sg:GoToState("grow_up_pop") if count ~= nil and count == 1 then -- add before removing or herd will be destroyed if herd ~= nil and herd.components.herd ~= nil and herd:IsValid() then herd.components.herd:AddMember(grown) end inst:Remove() else inst:Remove() if herd ~= nil and herd.components.herd ~= nil and herd:IsValid() then herd.components.herd:AddMember(grown) end end end This would turn the beefalo herds into goat herds. So yeah, if you have any ideas or feedback, discuss it.
  10. @Ozzey_Lee @fimmatek Bug is ancient and rare. Back from when domestication appeared. Both client and server logs are useless here. Any chance any of you can provide a cluster_x folder with the world with the bugged beef?
  11. @myxal Thank you very much for the world. I have been tinkering with it. It allowed me to see: Unfortunately, those bugs are the cause of beefalo overpopulation, not the cause for the empty beefaloherds growing. Upon closer inspection of the empty beefaloherds, you can rest assured they do nothing, because they can only spawn a baby beefalo when there's a parent to attach it (which must be a member of the herd). I found half of the cause of the empty beefaloherds. There are special beefalo in your world that have no herd (herd in herdmember component is set to nil), BUT have a herd location saved on the knownlocations component. So basically, every time you log out and log in, more herds appear, because it creates one for itself (it doesn't have one) but it doesn't join it (it fails because it remembers it has one). Also, because of the fail everytime (and how the code works), it creates 3 new empty herds each time. As for why exactly some beefalo could have herd set to nil, but have a herd knownlocation memorized: it's a mystery to me. Technically, this in particular, should be impossible. But I don't know if you may have used any console commands that caused this, or mods that might have interfered, or maybe the bug comes from older versions. Another tidbit, is that the beefalo also remembered a "loiteranchor" knownlocation, which means it was fed or was ridden (presumably to domesticate it). When I pulled all the herdless beefalo to me, I got 2. One that was feral. And one that was domesticated. Both with loiteranchor and herd locations, and both without herd assigned in herdmember. Here are some commands to repair the world: -- 1) clean buggy beef for k, v in pairs(Ents) do if v.prefab == "beefalo" and v.components.herdmember.herd == nil then v:Remove() end end -- 2) clean empty herds for k, v in pairs(Ents) do if v.prefab == "beefaloherd" and v.components.herd.membercount == 0 then v:Remove() end end -- extra) pull buggy beef for inspection for k, v in pairs(Ents) do if v.prefab == "beefalo" and v.components.herdmember.herd == nil then v.Transform:SetPosition(ThePlayer.Transform:GetWorldPosition()) end end Here is a command to spawn a domesticated beef: c_spawn("beefalo"); c_sel().components.hunger:DoDelta(400); c_sel().components.domesticatable:DeltaDomestication(1); c_sel().components.domesticatable:TryBecomeDomesticated(); After that, no more herd spawning on log in. Of course, you still have a massive population to clean. You can kill them all and spawn a lone beefalo every 10 seconds to make herds of size 1 wherever you please. Overpopulation still has to be fixed, of course.
  12. -- babybeefalo.lua local function SetFullyGrown(inst) local grown = SpawnPrefab("beefalo") grown.Transform:SetPosition(inst.Transform:GetWorldPosition() ) grown.Transform:SetRotation(inst.Transform:GetRotation() ) grown.sg:GoToState("grow_up_pop") inst:Remove() end -- herd.lua self.task = self.inst:DoPeriodicTask(math.random() * 2 + 6, _OnUpdate, nil, self) -- herdmember.lua self.task = self.inst:DoTaskInTime(5, OnInit) Assuming that herds never merge, consider the following situation: You have a herd of 1 beefalo, 1 baby beefalo spawns. The baby beefalo is added to the herd. Now you have a herd of 2. The baby beefalo grows until he's fully grown. He gets removed from the herd. Now you got a herd of 1. A beefalo spawns on the baby place. But it isn't linked to the herd. What happens next? The beefalo in 5 seconds will get a herd, if it doesn't have one. Either the herd picks up the beefalo via GatherNearbyMembers, or the beefalo makes its own. If the beefalo makes its own, since herds don't merge, you will end up with a herd of 1 and another herd of 1, and both will grow. And the same might happen to them. This causes beefalo overpopulation. NOTE: This applies to single player Don't Starve as well; I will mention it next patch time comes.
×
  • Create New...