Jump to content

Recommended Posts

My first post here, but I don't know where else to go for help. I have a modded character I've been working on, with one of his special abilities being that he can eat live critters in the inventory without having to "murder" them first. So far, I have code that works just fine for other mobs such as bees and rabbits, but for some reason, nothing I try for getting him to eat live fishes (pond fish or ocean fish) will work. I'm no good at coding, so if someone can help me out and find why it's not working, I'd really appreciate it!

Here's what the code I'm using looks like, for the mobs that DO actually work as intended:

local function OnGotNewItem(inst, data)
    if data.item ~= nil and data.item:HasTag("smallcreature") and data.item:HasTag("edible") == false and data.item.components.health ~= nil then
		if data.item.components.health.canmurder ~= nil then

			data.item.components.health.canmurder = false

			data.item:AddComponent("edible")
			data.item.components.edible.foodtype = FOODTYPE.REALLYGROSS
						
			if data.item:HasTag("bee") then
				data.item.components.edible.healthvalue = -1
				data.item.components.edible.hungervalue = 15
				data.item.components.edible.sanityvalue = -1
			elseif data.item:HasTag("bird") then
				data.item.components.edible.healthvalue = 0
				data.item.components.edible.hungervalue = 20
				data.item.components.edible.sanityvalue = -3

local function OnDropItem(inst, data)
	if data.item ~= nil and data.item:HasTag("smallcreature") and data.item.components.health ~= nil then
		if data.item.components.health.canmurder == false then		
			data.item.components.health.canmurder = true
			data.item:RemoveComponent("edible")
		end
	end
end

It works mostly fine, aside from bugging out in multiplayer if another non-modded character is given the critter first. I'm no good at coding, so I wouldn't know how to fix that part on my own.

I've tried changing HasTag("edible") to True since in the pondfish/oceanfish prefabs they're listed as edible, but it still doesn't work. Fish are still able to be murdered, too, which means it's probably not even picking up on that bit of code correctly. Someone with much better coding experience can hopefully help me out?

Welcome to the forums! I think fish don't have the smallcreature tag, so your code won't apply to them. You could either check for the prefab name:

-- Special case for fish:
if data.item ~= nil and (data.item:HasTag("smallcreature") or data.item.prefabname == "fish") and data.item:HasTag("edible") == false and data.item.components.health ~= nil then

-- Or check all prefabs individually:
  if data.item ~= nil and (data.item.prefabname == "bee" or data.item.prefabname == "rabbit" or data.item.prefabname == "fish") and data.item:HasTag("edible") == false and data.item.components.health ~= nil then

or add a new tag for your mod:

-- Add your tag to all relevant prefabs in your modmain.lua:
for i, prefab in ipairs({"rabbit", "bee", "fish"}) do
  AddPrefabPostInit(prefab, function(inst) inst.AddTag("edibleAlive") end)
end

-- Simplify the check in your character .lua file:
if data.item ~= nil and data.item:HasTag("edibleAlive") then

Disclaimers: untested and I'm a tad rusty in DS/DST. Happy modding!

9 hours ago, alainmcd said:

Welcome to the forums! I think fish don't have the smallcreature tag, so your code won't apply to them. You could either check for the prefab name:

-- Special case for fish:
if data.item ~= nil and (data.item:HasTag("smallcreature") or data.item.prefabname == "fish") and data.item:HasTag("edible") == false and data.item.components.health ~= nil then

-- Or check all prefabs individually:
  if data.item ~= nil and (data.item.prefabname == "bee" or data.item.prefabname == "rabbit" or data.item.prefabname == "fish") and data.item:HasTag("edible") == false and data.item.components.health ~= nil then

or add a new tag for your mod:

-- Add your tag to all relevant prefabs in your modmain.lua:
for i, prefab in ipairs({"rabbit", "bee", "fish"}) do
  AddPrefabPostInit(prefab, function(inst) inst.AddTag("edibleAlive") end)
end

-- Simplify the check in your character .lua file:
if data.item ~= nil and data.item:HasTag("edibleAlive") then

Disclaimers: untested and I'm a tad rusty in DS/DST. Happy modding!

Alright, so I've been messing with the code for a bit, I don't know how much progress I've made though. The new code (I'm using the first new option, having it detect the prefab name) is working good, my character can eat normal critters just fine using it! But there's still the issue of not being able to eat fish. I don't think the issue is the code itself, but because in the pondfish/pondeel/oceanfish prefabs, they're labeled as being FOODTYPE.MEAT.

local edible = inst:AddComponent("edible")
	if fish_def.edible_values ~= nil then
		edible.healthvalue = fish_def.edible_values.health or TUNING.HEALING_TINY
		edible.hungervalue = fish_def.edible_values.hunger or TUNING.CALORIES_SMALL
		edible.sanityvalue = fish_def.edible_values.sanity or 0
		edible.foodtype = fish_def.edible_values.foodtype or FOODTYPE.MEAT
	else
		edible.healthvalue = 0
		edible.hungervalue = 0
		edible.sanityvalue = 0
		edible.foodtype = FOODTYPE.MEAT
	end
	if edible.foodtype == FOODTYPE.MEAT then
		--edible.ismeat doesn't appear to actually be used anywhere, might not be necessary.
		edible.ismeat = true
	end

Probably so that certain mobs can eat fish as well, but I have a feeling it's conflicting with the code that's trying to change their FOODTYPE to REALLYGROSS, the one I've made. It might be possible to write code that adds the foodtype as a secondary foodtype, like some foods do, the problem is I'm having trouble writing code that does that; every time it just causes the game to bug out, no crash report, just either not loading or making the whole game freeze.

Here's the code right now, it works for other mobs but still not fish.

local function OnGotNewItem(inst, data)
    if data.item ~= nil and (data.item:HasTag("smallcreature") or data.item.prefabname == "pondfish") and data.item.components.health ~= nil then

		if data.item.components.health.canmurder ~= nil then
    
			data.item.components.health.canmurder = false

			data.item:AddComponent("edible")
			data.item.components.edible.foodtype = FOODTYPE.REALLYGROSS

(I removed the if for items being non-edible, thought that might've been causing it to exclude fishes but I guess not. Not terribly important anyways, I think fish are literally the only critters the game considers edible for some ungodly reason.)

Mostly I don't really know WHERE to stick new code in for fishes exclusively that wouldn't cause it to crash. If you need, I can send the character's full prefab file so you can take a look.

But thanks for the help so far, it's helped me out quite a bit! Even if I'm still rubbish at writing code I feel like I understand it just a tiny bit better now.

7 hours ago, emsterthecat said:

a secondary foodtype

That should work. Something like:

data.item.components.edible.secondaryfoodtype = FOODTYPE.REALLYGROSS

--

7 hours ago, emsterthecat said:

causes the game to bug out

Sorry, no idea.

--

7 hours ago, emsterthecat said:
if data.item ~= nil and (data.item:HasTag("smallcreature") or data.item.prefabname == "pondfish") and data.item.components.health ~= nil then

Pondfish don't seem to have health, if I'm seeing it correctly?

--

7 hours ago, emsterthecat said:

I think fish are literally the only critters the game considers edible for some ungodly reason.

Might be so they can be put in crockpots, but I'm just guessing. Especially when you stumble upon this:

7 hours ago, emsterthecat said:
--edible.ismeat doesn't appear to actually be used anywhere, might not be necessary.

:grin:

Good luck!

Quote
4 hours ago, alainmcd said:

That should work. Something like:

data.item.components.edible.secondaryfoodtype = FOODTYPE.REALLYGROSS

--

Sorry, no idea.

--

Pondfish don't seem to have health, if I'm seeing it correctly?

--

Might be so they can be put in crockpots, but I'm just guessing. Especially when you stumble upon this:

:grin:

Good luck!

 

Okay, I'm trying to add the secondary food type to fish now. The only problem is, I think I'm getting the code wrong when trying to separate fish from normal critters. See, here's the code I'm trying to use:

local function OnGotNewItem(inst, data)
    if data.item ~= nil and data.item:HasTag("smallcreature") and data.item.components.health ~= nil then

		if data.item.components.health.canmurder ~= nil then
    
			data.item.components.health.canmurder = false

			data.item:AddComponent("edible")
			data.item.components.edible.foodtype = FOODTYPE.REALLYGROSS

    		if data.item ~= nil and data.item:HasTag("fish") then
     			
			data.item.components.edible.secondaryfoodtype = FOODTYPE.REALLYGROSS

But, this causes the server to crash before it launches, it works fine if it's just the top half (without the fish part). I have a feeling I need to code it differently, maybe putting an elseif somewhere, but I'm not really experienced enough to know where it's going wrong. If you know how to write it correctly I'd be very grateful!

Guh... I never would've guessed that trying to code in such a dumb little feature would've been this troublesome!

You're missing an end before checking for the fish. Or with an elseif:

local function OnGotNewItem(inst, data)
	if data.item ~= nil and data.item:HasTag("smallcreature") then
		if data.item.components.health ~= nil and data.item.components.health.canmurder ~= nil then
			data.item.components.health.canmurder = false

			data.item:AddComponent("edible")
			data.item.components.edible.foodtype = FOODTYPE.REALLYGROSS
		elseif data.item:HasTag("fish") then
			data.item.components.edible.secondaryfoodtype = FOODTYPE.REALLYGROSS
		end
	end
end

 

12 hours ago, emsterthecat said:

Guh... I never would've guessed that trying to code in such a dumb little feature would've been this troublesome!

That's exactly how programming works. :grin: You're doing fine. :friendly_wink:

Geez, neither of those are working for me, I'm starting to wonder if something else in the prefab is messing it up...

Here, I have the character's prefab file for you, do you think you can look through and see if anything else might be wrong? Sorry to keep asking so much, it's just bothering me a lot now that I just can't get this code to work right :grumpy:

fakey.lua

Don't worry. Was isn't working? If it's only that your character still can't eat fish: there's no check for fish in the file you linked. Also, fish don't have a health component as far as I can tell, so data.item.components.health ~= nil in line 37 and the check in line 38 will always return false.

Is it something else? I don't see anything wrong with the code. Does the game crash? If so, please do post the stack trace.

A couple of syntax errors: an end too many at the end of OnGotNewItem and a sneaky if in the middle of a boolean expression:

		if data.item.components.health ~= nil and 
		if data.item.components.health.canmurder == false then		

If your editor allows it, consider using a syntax checking extension. I use VSCode with this extension which pointed me directly to the issues, with an explanation.

I've also made it so the secondary food type is removed on dropping the fish and fixed the indentation, which is a pet peeve of mine. Again: untested.

fakey.lua

Alright, the good news! It's loading ingame again and the critter code works! Bad news... it's STILL not letting him eat fish.

But I might know where the problem is.... so, in the code, the prompt to "murder" a critter takes priority over being able to eat it. Which is why it has to be made "un-murderable" in the first place. But adding "data.item.components.health.canmurder = false" back in makes the game crash upon picking up a fish... here's what the server log says.

[00:04:59]: [string "../mods/fakeywakey/scripts/prefabs/fakey.lu..."]:46: attempt to index field 'health' (a nil value)
LUA ERROR stack traceback:
../mods/fakeywakey/scripts/prefabs/fakey.lua:46 in (local) fn (Lua) <38-132>
   inst = 116201 - fakey (valid:true)
   data = table: 000000003F93F940
scripts/entityscript.lua:1208 in (method) PushEvent (Lua) <1195-1222>
   self (valid:true) =
      _PostActivateHandshakeState_Client = 0
      EnableLoadingProtection = function - scripts/prefabs/player_common.lua:1058
      inlimbo = false
      GetMoistureRateScale = function - scripts/prefabs/player_common.lua:254
      SetCameraDistance = function - scripts/prefabs/player_common.lua:1489
      ScreenFlash = function - scripts/prefabs/player_common.lua:1567
      skeleton_prefab = skeleton_player
      player_classified = 116202 - player_classified (valid:true)
      playercolour = table: 0000000034DEDE10
      MakeGenericCommander = function - scripts/prefabs/player_common_extensions.lua:898
      IsOverheating = function - scripts/prefabs/player_common.lua:224
      IsActing = function - scripts/prefabs/player_common_extensions.lua:939
      SetClientAuthoritativeSetting = function - scripts/prefabs/player_common_extensions.lua:967
      _isrezattuned = false
      OnRemoveEntity = function - scripts/prefabs/player_common.lua:1099
      pendingtasks = table: 000000003F706130
      ShowHUD = function - scripts/prefabs/player_common.lua:1461
      ResetMinimapOffset = function - scripts/prefabs/player_common.lua:1473
      sg = sg="wilson", state="doshortaction", time=0.17, tags = "doing,keepchannelcasting,"
      IsHUDVisible = function - scripts/prefabs/player_common.lua:1451
      ApplyScale = function - scripts/prefabs/player_common.lua:1584
      entity = Entity (00000000458854E0)
      SetGhostMode = function - scripts/prefabs/player_common.lua:913
      ShowActions = function - scripts/prefabs/player_common.lua:1455
      Light = Light (0000000017775A50)
      OnWakeUp = function - scripts/prefabs/player_common.lua:1319
      IsInAnyStormOrCloud = function - scripts/prefabs/player_common.lua:275
      killtask = PERIODIC 116201: 3.000000
      DynamicShadow = DynamicShadow (0000000017775120)
      actionreplica = table: 000000003F705DC0
      event_listening = table: 000000003F7059B0
      _lunarportalmax = table: 000000003F717340
      SynchronizeOneClientAuthoritativeSetting = function - scripts/prefabs/player_common_extensions.lua:955
      CanSeePointOnMiniMap = function - scripts/prefabs/player_common_extensions.lua:887
      _hermit_music = table: 000000003F717C00
      GetMaxMoisture = function - scripts/prefabs/player_common.lua:244
      OnPostActivateHandshake_Server = function - scripts/prefabs/player_common_extensions.lua:1007
      RemoveCameraExtraDistance = function - scripts/prefabs/player_common.lua:1503
      EnableBoatCamera = function - scripts/prefabs/player_common.lua:904
      CanUseTouchStone = function - scripts/prefabs/player_common.lua:194
      updatecomponents = table: 000000003F7097E0
      YOTB_issetunlocked = function - scripts/prefabs/player_common.lua:85
      ShakeCamera = function - scripts/prefabs/player_common.lua:1525
      OnPostActivateHandshake_Client = function - scripts/prefabs/player_common_extensions.lua:988
      YOTB_isskinunlocked = function - scripts/prefabs/player_common.lua:92
      Physics = Physics (0000000017775B40)
      MiniMapEntity = MiniMapEntity (00000000177751B0)
      event_listeners = table: 000000003F7058C0
      wallupdatecomponents = table: 000000003A3B4ED0
      _OnLoad = function - ../mods/fakeywakey/scripts/prefabs/fakey.lua:27
      AnimState = AnimState (0000000017775510)
      children = table: 000000003A3B09C0
      SetGymStopState = function - scripts/prefabs/player_common.lua:64
      _serverpauseddirtyfn = function - scripts/prefabs/player_common.lua:977
      name = Marclef
      GetTemperature = function - scripts/prefabs/player_common.lua:204
      GUID = 116201
      ApplySkinOverrides = function - scripts/prefabs/player_common.lua:1646
  
[00:04:59]: [string "../mods/fakeywakey/scripts/prefabs/fakey.lu..."]:46: attempt to index field 'health' (a nil value)
LUA ERROR stack traceback:
    ../mods/fakeywakey/scripts/prefabs/fakey.lua:46 in (local) fn (Lua) <38-132>
    scripts/entityscript.lua:1208 in (method) PushEvent (Lua) <1195-1222>
    scripts/components/inventory.lua:951 in (method) GiveItem (Lua) <881-1037>
    scripts/actions.lua:733 in (field) fn (Lua) <672-736>
    scripts/bufferedaction.lua:26 in (method) Do (Lua) <22-36>
    scripts/entityscript.lua:1552 in (method) PerformBufferedAction (Lua) <1534-1567>
    scripts/stategraphs/SGwilson.lua:6321 in (field) fn (Lua) <6314-6323>
    scripts/stategraph.lua:665 in (method) UpdateState (Lua) <633-677>
    scripts/stategraph.lua:703 in (method) Update (Lua) <696-722>
    scripts/stategraph.lua:128 in (method) Update (Lua) <109-146>
    scripts/update.lua:288 in () ? (Lua) <224-298>

It still has problems with the fish item technically not having health. Do you know how to make it so it removes the ability to "murder", without referencing the item's health?

I'VE DONE IT!!!!!!!!!!!

I found the code that lets fish be murderable without health inside the pondfish file! It's a component, so I set it to be removed whenever he picks up a fish/added back when he drops it, and...

AAAAAAAAAAAAAA.JPG.4f56f66a5a770e49d9436cc3f9c759bf.JPG

There it is!!!!!!!

You have no idea how happy I am over such a dumb little thing right now :grin: but thank you sososososososososo much for helping me out!! I don't know if I could've figured out all the things I had wrong without your help!

You don't mind if I mention you on the mod's page for helping, do you? Either way, once again thank you so much!!!

  • Big Ups 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...