Jump to content

If entity has been touched by player(s)


Recommended Posts

I have been checking and writing different code to make this work for a couple of hours and still have not/can not solve it.

Is there any way I can check if an entity has ever been dropped by any player or if any player has ever had this entity in his inventory?

Edited by Dcrew
Link to comment
Share on other sites

Not unless you set a custom variable on that player. You can add a listener to all players for when they pick up something, and if that something is the right prefab, you can just do

inst.playerOnceHadAnAcorn = true

and then you can check for that whenever you need to. But if you want this to "stick" when the player leaves and rejoins the server, you also have to make sure to add that this variable is saved and loaded. You can do this by extending the inst.OnSave and inst.OnLoad functions on the player characters. There are many examples of how these functions work in the original game files, so you should be able to figure it out.

Link to comment
Share on other sites

Alright, in my prepare function I use:

local function on_pickup_ent(ent)
	ent.dcrew_wasplayerowned = true
	print("player picked up "..ent.prefab)
end
for _, ent in pairs(Ents) do
	ent:ListenForEvent("onpickup", on_pickup_ent)
end

and it works, but I have no idea how to save & load it or override said functions.

Link to comment
Share on other sites

I may have misunderstood what you wanted. I thought you wanted to know whether a player had ever had or dropped a certain entity/prefab, but from your code it seems like you want to know whether an entity has ever been in the inventory of a player. There's a big difference in where the code should go and which entity should save/load data about his, depending on what exactly you want to achieve. Can you spell out exactly what it is you want to achieve, so I know what you're going for? All the details.

I don't understand which entities you are adding these events to in the code you posted.

Link to comment
Share on other sites

Oh, wow, ok. Then what you have is right, assuming you have every single entity in your Ents, but you won't be getting any entities created during the game. You may want to instead set the pickup event in an AddComponentPostInit("inventoryitem", function(comp) bla bla end)

That way you only affect items which actually have an inventoryitem component.

An example of making things save and load can be found in several prefabs, like rock_flippable.

local function onsave(inst, data)
	if inst.flipped then
		data.flipped = true
	end
end

local function onload(inst, data)
	-- cut some extra code which wasn't important for showing how it works
	if data and data.flipped then
		inst.flipped = true
	end
end

and then in the fn() or master_postinit() of the component or prefab you set those functions to be the new OnSave and OnLoad functions of the inst, which are automatically called during saving and loading the server.

inst.OnSave = onsave
inst.OnLoad = onload

 

Make sure that you aren't overwriting existing OnSave or OnLoad functions. You can check if they exist, and if so, instead extend them with your code, instead of just setting them to your functions.

Edited by Ultroman
Link to comment
Share on other sites

is there a way to create a component post init within a component instead of modmain?

I've tried:

AddComponentPostInit
self:AddComponentPostInit
self.inst:AddComponentPostInit

but none of them work.

Link to comment
Share on other sites

How can I use ComponentPostInit on inventoryitem anyway, I need the entity itself not the component:

AddComponentPostInit("inventoryitem", function(inst)
		player_owned_ents[inst:GetGUID()] = true
		print("[Enhanced Biomes] Player picked up "..inst.prefab)
	end)

 

Link to comment
Share on other sites

For AddComponentPostInit you actually get the component passed as a parameter and not the inst, and all components have a reference to the inst they are on, so:

AddComponentPostInit("inventoryitem", function(component)
	player_owned_ents[component.inst:GetGUID()] = true
	print("[Enhanced Biomes] Player picked up "..component.inst.prefab)
end)
Link to comment
Share on other sites

That doesn't work:

AddComponentPostInit("inventoryitem", function(component)
		local ent = component.inst
		if ent and ent.prefab then
			print("[Enhanced Biomes] Player picked up "..ent.prefab)
		end
	end)

Nothing happens when picking up an entity.

Edited by Dcrew
Link to comment
Share on other sites

That's because at the point that a component is initialized, the prefab isn't done initializing yet, and for some stupid reason the "prefab" variable holding the name is one of the last things that happens for an instance of a prefab, so the "prefab" variable is not available to you on component.inst inside AddComponentPostInit. Also, you can't be sure that any OTHER components on the prefab have been applied yet, so almost anything you want to do concerning OTHER components or insts in AddComponentPostInit must be delayed with component.inst:DoTaskInTime(0, function(inst) bla bla end)

But, since you want to do this to every single item that has the inventoryitem component, and the inventoryitem component is the one with the onpickupfn, you can safely set that inside your AddComponentPostInit using component:SetOnPickupFn(fn), and all listeners and custom variables can still be added to component.inst.

Edited by Ultroman
Link to comment
Share on other sites

I didn't get that working fully so I did some things, and it works now:

local function ent_onpickup(ent)
	if TUNING.ENHANCEDBIOMES.PLAYER_OWNED_ENTS[ent.GUID] then
		print("T")
		TUNING.ENHANCEDBIOMES.PLAYER_OWNED_ENTS[ent.GUID] = nil
	end
end

local function ent_ondropped(ent)
	print("player dropped "..ent.prefab)
	TUNING.ENHANCEDBIOMES.PLAYER_OWNED_ENTS[ent.GUID] = true
end

AddComponentPostInit("inventoryitem", function(component)
		local ent = component.inst
		ent:ListenForEvent("ondropped", ent_ondropped)
		ent:ListenForEvent("onpickup", ent_onpickup)
	end)

Except, ent.GUID may be unique within the session but when I reload that game session it doesn't stick, I am saving & loading:

function EnhancedBiomes:OnSave()
	local data = {}
	data["last_seg_used"] = last_seg_used
	data["ent"] = {}
	for k, v in pairs(TUNING.ENHANCEDBIOMES.PLAYER_OWNED_ENTS) do
		data["ent"][k] = v
	end
	return data
end

function EnhancedBiomes:OnLoad(data)
	if data then
		last_seg_used = data["last_seg_used"] or 0
		if data["ent"] then
			for k, v in pairs(data["ent"]) do
				TUNING.ENHANCEDBIOMES.PLAYER_OWNED_ENTS[k] = v
			end
		end
	end
end

So each entity's GUID isn't sufficient since I want it to load used entitys from past sessions too, I'm not sure what to do here.

Link to comment
Share on other sites

First time the object runs throught your code, you save its GUID in your own variable on its instance, and make sure to save/load that variable. Then that variable will always be the same between sessions. Then you can save the GUIDs instead of saving the entire entity (which btw is not a good idea).

Link to comment
Share on other sites

If you want to have an easier time modding, I highly recommend that you go through the Lua Crash Course, possibly some more "Getting started with Lua" things, and check out the newcomer post if you haven't already. Modding is gonna be really annoying if you have to wait for other people to answer questions about syntax and basic functionality. Just a friendly suggestion.

Function extension/chaining is essentially piggybacking off of an existing function, while keeping the original functionality of the function intact, so as to not break the game. One huge benefit of this, is that several mods can take turns extending/chaining a function, and so they will all have a much better chance to keep working, i.e., be compatible with each other.

This is an example of extending/chaining a function which is declared with a : like this Container:RemoveItem(item, wholestack)
Notice that we add the first parameter 'self' because we're beclaring the function with . instead of : and functions declared with a : automatically get the self parameter passed into them as a hidden first parameter.

local oldRemoveItem = inst.components.container.RemoveItem

inst.components.container.RemoveItem = function(self, item, wholestack)
	local returnedItem = oldRemoveItem(self, item, wholestack)
	-- do whatever you want with the item, which MIGHT have been removed from the container.
end

If the function is declared as a normal function, i.e.

local myFunction = function(parameter1)
	-- code
end
-- or
local function myFunction(parameter1)
	-- code
end

you omit the self parameter

local oldSomeFunction = inst.components.container.SomeFunction

inst.components.container.SomeFunction = function(parameter1)
	-- Do something before the original function is called, perhaps changing parameter1.
	local returnValue = oldSomeFunction(parameter1)
	-- Do something after the function is called, perhaps altering the return value.
	return returnValue
end

You only need to save and return the return value if the original function returns something. Otherwise you can just do

local oldSomeFunction = inst.components.container.SomeFunction

inst.components.container.SomeFunction = function(parameter1)
	-- Do something before the original function is called, perhaps changing parameter1.
	oldSomeFunction(parameter1)
	-- Do something after the function is called, perhaps altering the return value.
end

 

Link to comment
Share on other sites

How can I check if a item is picked up? Using the 'onpickup' inventoryitem event triggers even when you just click an item in your inventory, I want to only trigger it if it's picked up off of the ground, I thought inventoryitem.owner would be the answer, but it sets to nil.

Link to comment
Share on other sites

If an item is in an inventory, must it not have been picked up at some point already? If so, you can rely on your variable already being set for this item, and thus not do anything.I don't know if it helps, but any prefab that is being instantiated always starts out not having an owner and being placed on the ground at 0, 0, 0. Then they are usually repositioned, or put into an inventory or container immediately, or something similar. There isn't really something that tells you whether the item was laying on the floor. There is only the owner variable, which is a player if it is in their itemslots or equipslots, or a container (backpack or chest) as long as the item is in there. Not sure which owner it has when it is in the mouse-slot. You can extend the original PickUp functions and such and simply print the name of the function and which owner it has before the original function is called and which owner it has after. That should tell you a lot.

Link to comment
Share on other sites

Nevermind I solved that one, I still have no idea how to save data with ents though, I browsed around many DST script files including the entity script, and just couldn't figure much out, is there any mods you know that save & load custom data to/from ents? So I can gain the knowledge and insight from it/them because doing this all day for 2 days straight is stressing me out a very lot D:

Link to comment
Share on other sites

From what I posted here which parts are you unsure about? All ents may or may not have an OnSave and OnLoad function on their inst, so if there is one you extend it and call your save-function alongside the original one, and if there isn't one, you just set it to be your save-function. Your save function should just have and use the same parameters as in the code snippet I posted.

Edited by Ultroman
Link to comment
Share on other sites

Well it has GetSaveRecord() to which I have no idea even after reading its contents, how to use it, other than that it seems it saves entity data through the components it has, to which I'd like to not have to attach a new component to every entity just to save some custom data to it.

Edited by Dcrew
Link to comment
Share on other sites

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
 Share

×
  • Create New...