Jump to content

[SOLVED] RemoveOnRotten lua script


Berdryn

Recommended Posts

RemoveOnRotten	=	{};

	function RemoveOnRotten.removeItems()
		local player 	= getSpecificPlayer(0);
		local inv		= player:getInventory();
		
		if inv:contains("Matter - Spiritual (Rotten)") == true then
			inv:Remove("Matter - Spiritual (Rotten)");
		end
	end
end

Event.OnPlayerUpdate.Add(RemoveOnRotten.removeItems);

I'm not sure if this is even set up, kinda writing in the dark as still new to lua.  I'm trying to get it so that as soon as the item rots, the script detects it and removes it from the player inventory. Thanks in advance!

Edited by Berdryn
Link to comment
Share on other sites

Here is what the console says when it causes the error on loading the game, where it loads all the lua files.

 

Loading: C:/Users/Master Berdryn/Zomboid/mods/iGod/media/lua/shared/iGod/iGod_RemoveOnRotten.lua
Oct 16, 2016 7:07:02 AM zombie.Lua.LuaManager RunLua
SEVERE: Error found in LUA file: C:/Users/Master Berdryn/Zomboid/mods/iGod/media/lua/shared/iGod/iGod_RemoveOnRotten.lua
se.krka.kahlua.vm.KahluaException: iGod_RemoveOnRotten.lua:11: '<eof>' expected near `end`
	at org.luaj.kahluafork.compiler.LexState.lexerror(LexState.java:280)
	at org.luaj.kahluafork.compiler.LexState.syntaxerror(LexState.java:291)
	at org.luaj.kahluafork.compiler.LexState.error_expected(LexState.java:686)
	at org.luaj.kahluafork.compiler.LexState.check(LexState.java:699)
	at org.luaj.kahluafork.compiler.LexState.compile(LexState.java:201)
	at se.krka.kahlua.luaj.compiler.LuaCompiler.loadis(LuaCompiler.java:132)
	at se.krka.kahlua.luaj.compiler.LuaCompiler.loadis(LuaCompiler.java:124)
	at zombie.Lua.LuaManager.RunLua(LuaManager.java:4598)
	at zombie.Lua.LuaManager.RunLua(LuaManager.java:4575)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:857)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:791)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:902)
	at zombie.GameWindow.init(GameWindow.java:1796)
	at zombie.GameWindow.maina(GameWindow.java:1014)
	at zombie.gameStates.MainScreenState.main(MainScreenState.java:177)

 

Link to comment
Share on other sites

Just now, Dr_Cox1911 said:

Looks like you have one "end" to much.  The first end closes the if, the second the function and the third is causing the error.

 

Thanks for responding. I've tried a few different ways of organizing the code, currently this is the code:

RemoveOnRotten	=	{};
	
	function RemoveOnRotten.addItems()
		local player 	= getSpecificPlayer(0);
		local inv		= player:getInventory();

		if inv:contains("Matter - Spiritual (Rotten)") == true then
			inv:Remove("Matter - Spiritual (Rotten)");
		end
		
	end


Event.OnPlayerUpdate.Add(RemoveOnRotten.addItems);

this is what the console says:

Loading: C:/Users/Master Berdryn/Zomboid/mods/iGod/media/lua/shared/iGod/iGod_RemoveOnRotten.lua
-------------------------------------------------------------
attempted index: OnPlayerUpdate of non-table: null
-----------------------------------------
STACK TRACE
-----------------------------------------
function: iGod_RemoveOnRotten.lua -- file: iGod_RemoveOnRotten.lua line # 14
java.lang.RuntimeException: attempted index: OnPlayerUpdate of non-table: null
	at se.krka.kahlua.vm.KahluaThread.tableget(KahluaThread.java:1549)
	at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:473)
	at se.krka.kahlua.vm.KahluaThread.call(KahluaThread.java:163)
	at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1727)
	at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1642)
	at se.krka.kahlua.integration.LuaCaller.pcall(LuaCaller.java:63)
	at se.krka.kahlua.integration.LuaCaller.protectedCall(LuaCaller.java:77)
	at zombie.Lua.LuaManager.RunLua(LuaManager.java:4611)
	at zombie.Lua.LuaManager.RunLua(LuaManager.java:4575)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:857)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:791)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:902)
	at zombie.GameWindow.init(GameWindow.java:1796)
	at zombie.GameWindow.maina(GameWindow.java:1014)
	at zombie.gameStates.MainScreenState.main(MainScreenState.java:177)
-----------------------------------------
STACK TRACE
-----------------------------------------
function: iGod_RemoveOnRotten.lua -- file: iGod_RemoveOnRotten.lua line # 14
Oct 16, 2016 8:08:01 AM zombie.Lua.LuaManager RunLua
SEVERE: null
Oct 16, 2016 8:08:01 AM zombie.Lua.LuaManager RunLua
SEVERE: null
java.lang.RuntimeException: 
	at se.krka.kahlua.vm.KahluaUtil.fail(KahluaUtil.java:91)
	at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:1285)
	at se.krka.kahlua.vm.KahluaThread.call(KahluaThread.java:163)
	at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1727)
	at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1642)
	at se.krka.kahlua.integration.LuaCaller.pcall(LuaCaller.java:63)
	at se.krka.kahlua.integration.LuaCaller.protectedCall(LuaCaller.java:77)
	at zombie.Lua.LuaManager.RunLua(LuaManager.java:4611)
	at zombie.Lua.LuaManager.RunLua(LuaManager.java:4575)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:857)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:791)
	at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:902)
	at zombie.GameWindow.init(GameWindow.java:1796)
	at zombie.GameWindow.maina(GameWindow.java:1014)
	at zombie.gameStates.MainScreenState.main(MainScreenState.java:177)

Oct 16, 2016 8:08:01 AM zombie.Lua.LuaManager RunLua
SEVERE: null

 

Link to comment
Share on other sites

Didn´t catch it at first glimpse, but you´re missing an "s" on Events

The event you´ve chosen gives you the player as a return value, so your code could look like this:

RemoveOnRotten	=	{};
	
	function RemoveOnRotten.addItems(_player)
		local player 	= _player;
		local inv		= player:getInventory();

		if inv:contains("Matter - Spiritual (Rotten)") == true then
			inv:Remove("Matter - Spiritual (Rotten)");
		end
		
	end


Events.OnPlayerUpdate.Add(RemoveOnRotten.addItems);

This should throw no error, but I haven´t tested it.

Link to comment
Share on other sites

48 minutes ago, Dr_Cox1911 said:

Didn´t catch it at first glimpse, but you´re missing an "s" on Events

The event you´ve chosen gives you the player as a return value, so your code could look like this:


RemoveOnRotten	=	{};
	
	function RemoveOnRotten.addItems(_player)
		local player 	= _player;
		local inv		= player:getInventory();

		if inv:contains("Matter - Spiritual (Rotten)") == true then
			inv:Remove("Matter - Spiritual (Rotten)");
		end
		
	end


Events.OnPlayerUpdate.Add(RemoveOnRotten.addItems);

This should throw no error, but I haven´t tested it.


Thanks a lot. I don't know how many hours I have wasted recently due to little stuff like this, or the comma or the right bracket. 

It doesn't cause any scripting error but I don't see it removing the item. Gonna test more extensively. 

Do I need to use the item's name and not the display name? I couldn't figure out any other way to differentiate between fresh and rotten otherwise. 

Link to comment
Share on other sites

20 hours ago, Berdryn said:


Thanks a lot. I don't know how many hours I have wasted recently due to little stuff like this, or the comma or the right bracket. 

It doesn't cause any scripting error but I don't see it removing the item. Gonna test more extensively. 

Do I need to use the item's name and not the display name? I couldn't figure out any other way to differentiate between fresh and rotten otherwise. 

Sorry, my quoting got a little fucked up.

 

Your code:

RemoveOnRotten	=	{};
	
	function RemoveOnRotten.addItems(_player)
		local player 	= _player;
		local inv		= player:getInventory();

		if inv:contains("Matter - Spiritual (Rotten)") == true then
			inv:Remove("Matter - Spiritual (Rotten)");
		end
		
	end

It looks like this should work as long as "Matter - Spiritual (Rotten)" is the item name of the item you are trying to remove. Example:

    item Matter-Spiritual(Rotten)
    {
        Weight	=	0,
        Type	=	Container,
	Capacity	= 1,
        DisplayName	=	Matter - Spiritual (Rotten),
        Icon	=	default,
    }

So the item name in the example is Matter-Spiritual(Rotten) with no spaces (I don't think this can have spaces) and differs from the DisplayName which is "Matter - Spiritual (Rotten)" and is what the item would display when it is in the inventory. So I think you just need to change that and it should work. If it doesn't, I have an idea to get it working. Just let me know.

 

Also, you should be able to change the following line:

if inv:contains("Matter - Spiritual (Rotten)") == true then

 

...to:

if inv:contains("Matter - Spiritual (Rotten)") then

...because that alone should return either true or false without having to specify. But either way should work. Just an FYI.

 

Also, for debugging purposes you could add a print line like this:

RemoveOnRotten = {};
	
function RemoveOnRotten.addItems(_player)
    local player = _player;
    local inv = player:getInventory();

    if inv:contains("Matter - Spiritual (Rotten)") then
        print("Here there be something rotten");
        inv:Remove("Matter - Spiritual (Rotten)");
    else
	print("My item was not detected in the inventory");
    end		
end

Which would print one of those two lines to console. I use that shit all the time.

Edited by tommysticks
Link to comment
Share on other sites

I don't work today and I am bored. So here is a solution that I think may work, using an apple as an example:

 

RemoveOnRotten	=	{};

function RemoveOnRotten.addItems(_player)
    local player = _player;
    local inv = player:getInventory();
    local item = inv:FindAndReturn("Apple");

    if item then
    	if item:isRotten() then
        	inv:Remove(item);
	end
    end		
end

I'm not 100% this will work, but I am fairly confident.

Link to comment
Share on other sites

I'm not sure exactly what I am doing there with \n(Rotten) but my idea was that FindAndReturn searched for an item that had " (Rotten)" at the end, note the space. I figured this might be able to detect any rotten item, as I am wanting each of my iGod base level crafting items to eventually decay. It's a method of protecting unauthorized players from finding an iGod item and ruining whatever the admin's are doing. One spark gives you access to everything.

Is the problem detecting the item name versus the display name? 

 

Here is what I am testing with right now:


RemoveOnRotten	=	{};

function RemoveOnRotten.removeItems(_player)
    local player = _player;
    local inv = player:getInventory();
    local item = inv:FindAndReturn("\n(Rotten)");

    if item then
	print("If item then..")
    	if item:isRotten() then
        	inv:Remove(item);
			print("Rotten item removed")
		else
			print("Nothing was detected.Line34")
		end
    end		
end

Events.OnPlayerUpdate.Add(RemoveOnRotten.removeItems);

Here is the item info from my script:

 

		item iGod_Matter_Spiritual
		{
			DisplayName	=	Matter - Spiritual,
			Type		=	Food,
			Icon		=	MeatPatty,	
			Weight		=	0.0,
			
			DaysFresh = 1,
			DaysTotallyRotten = 1,

		}


 

Link to comment
Share on other sites

FINALLY! This actually works. I'm not sure if OnPlayerUpdate is right as I don't want to add to the lag as this is checking constantly. The print() debug lines really came in handy @tommysticks!

How do you suggest I make this work for like 40+ items? Is there a better way than copying the function over and over? Would it be in like a for loop? An array? My programming knowledge is mostly from C+ syntax but its been so long and it was never formal, just what I picked up for modding and some early life classes in college.
 

  • Could it be set up to require another file like say a txt file where I can define the possible items then in the code, check against this list so that any instance of an iGod item on that txt list is checked for isRotten() and replaces that local item variable?


I need some way to check so that it removes my iGod items or any items specified but leave other rotten things like food from the base game alone.

where it says iGod.iGod_Matter_Spiritual, its module.item where the module is defined in my item.txt file in my mod and item is the actual item name, not the display name. In case someone else was trying to figure it out for their own use.

Here is the current working RemoveOnRotten script:

 

RemoveOnRotten	=	{};

function RemoveOnRotten.removeItems(_player)
    local player = _player;
    local inv = player:getInventory();
    local item = inv:FindAndReturn("iGod.iGod_Matter_Spiritual");

    if item then
	print("If item then..")
    	if item:isRotten() then
        	inv:Remove(item);
			print("Rotten item removed")
		else
			print("Nothing was detected.Line34")
		end
    end		
end

Events.OnPlayerUpdate.Add(RemoveOnRotten.removeItems);

 

Edited by Berdryn
Link to comment
Share on other sites

I"m tryin to think of a simple way to do this without causing it to lag to shit, but I don't know if it can be done. I do think it would probably take a for loop and I don't know how well it would run with 40+ items running on OnPlayerUpdate. There is a way to make your own event trigger when the player's inventory is updated, which I think would be ideal, however I haven't fucked around with that in quite a while. It would require replacing the game's function that updates the player's inventory and adding the line... it was something like CreateEvent("Name of event"). I don't remember where I found that...

 

 

Link to comment
Share on other sites

I might just have to limit some of that or if I can figure out a way to call to a table and if anything on that table is in the player inventory and is rotten, its removed. Tho with that script, its possible to check for an item in a players inventory so I don't see why I couldn't just leave the stuff rotten but have it only viable for use when its fresh, I assume with isRotten() it has a isFresh() counterpart. 

The point is to just limit how long these items can last in the game, with my mod as it is, you can create all these things with no cost, infinitely. I just want to make it less of a cheat mod and more of a cheat mod with limits and a believable narrative as to why you can do what it does.  I'll play with it more and see if I can get it to track more items with as little code as possible then try the fresh detection method, I think you can place OnCreate:LUA SCRIPT NAME in an item recipe to have it trigger a script, maybe just a simple Is it fresh? If so then return true, else say "You need fresh materials to work with!" or something like that

 

Link to comment
Share on other sites

I wonder, is there any tutorials out there on getModData()? I think maybe it might be possible to create the item and on create, start like a timer so that it only exists for so long, as the timer runs out, it deletes itself, anywhere it is in the game world. I think a player could just make a ton of resources, throw them in a container and build stuff that way, that script would remove it should they add it back to the inventory but I think having it just vanish based on its own data would be better.

Link to comment
Share on other sites

1 minute ago, tommysticks said:

You are correct, there is an isFresh().

 

I use this to aide me in looking for these functions: link.

Thanks, I've been looking at this as well as the javadocs page too. I'm just now starting to get into the lua parts of all this, its slow going but stuff is slowly starting to make sense.

When I was doing gamemaker games, I had a script that poppped up my own hand made debug overlay with a keypress. It just displayed various global variables, my x, y, z, etc. I want to make that here but I don't know where to look to make pop up windows or to display text on the screen. I've looked at a few mods out there, such as Life after people and some others but I don't understand how to bring up a window. If I can do that, I can make my own gump artwork for it and set one up as a debug tool for further modding.

Link to comment
Share on other sites

2 minutes ago, Berdryn said:

Thanks, I've been looking at this as well as the javadocs page too. I'm just now starting to get into the lua parts of all this, its slow going but stuff is slowly starting to make sense.

When I was doing gamemaker games, I had a script that poppped up my own hand made debug overlay with a keypress. It just displayed various global variables, my x, y, z, etc. I want to make that here but I don't know where to look to make pop up windows or to display text on the screen. I've looked at a few mods out there, such as Life after people and some others but I don't understand how to bring up a window. If I can do that, I can make my own gump artwork for it and set one up as a debug tool for further modding.

I have a mod that does this, although kind of shittily because it is susceptible to a lot of errors which will break it. But here it is.

 

I don't know if that version still works, but it shouldg et you started.

Link to comment
Share on other sites

Yeah its alright, I do that also with a working file. I just --[[ ]]-- and quarantine different sections for testing, reference and so on. 

I really want to figure out how to make stuff you place in the world, such as building parts. I know how to do tilesets and with my graphics design background, I would love to try to make a building set with tiles, it just seems so complicated from what i've seen, I wish more of the code had comments with explanations. It helps a lot to learn how it works. 

Link to comment
Share on other sites

I started fuckin around with tilesets, they aren't the most user friendly tools out there. But I think they are the best way to get stuff like that added in. But the 2 x tools aren't in yet. So that kinda sucks.

 

From what I can tell, it would be relatively simple to add stuff after you have it loaded as a tileset.

Link to comment
Share on other sites

Any chance you know it well enough to put together a little tutorial to show how to make an iso object in the world? Say for example just a crate or a wall. I think I understand the tileset stuff well enough, its somewhat basic graphic manipulation, I think there is also a decent tutorial in the resources section about it but actually making use of it, it didn't touch on. If I can get the basics of it down, I want to try my hand at a space theme or maybe dark ages like art for map making later on but from what I understand making the tileset for the mapmaker isn't quite the same as making one for use in the build system in game. I could be wrong tho.

Link to comment
Share on other sites

Dark ages, dude that would be sick. I actually made a plate armor 3-D model set and started working on a castle tileset. Yeah, I can fuck around with it more.

medi bob.png

 

I just recently got into 3-D modelling, so it's not the best, especially my texturing. However, the way the models are rendered in-game kind of negates some of the shittiness.

Edited by tommysticks
Link to comment
Share on other sites

Yeah I know it would be pretty awesome, did you ever hear of a game called Ultima Online? It was a fantasy isometric mmo which is still going. There's a ton of artwork in it and available for examples. Using blender, I thought I could make some nice textured walls like stone, wood, sticks, etc. It would save a ton of time that way and look so much better in game than drawing pixel by pixel.

I wanted to include a section of my iGod mod with a small map not connected to the main map, which was sort of like a iGod only area, it would look like space but with dark age stone temple like stuff where you can hang out and rp as gods, using a teleport or portal system as part of the iGod miracles section. UO had a magic system, portals and gates and a ton of other stuff ripe for experimentation lol

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
×
×
  • Create New...