Jump to content

Trying to create a Flashlight clone.


false_chicken

Recommended Posts

Hello. I am trying to create a clone of the flashlight except it uses radial light (Its a lantern) and I have created the object itself and have managed to spawn with it. It works except that it doesn't have the battery functionality the flashlight has. It is like any other drainable object. I assume there is some LUA involved giving the flashlight the ability to use batteries. I have been going through the Zomboid client LUA files looking for anything referencing the flashlight and batteries but have had no luck so far. Can someone be so kind as to point me in the right direction? Thanks!

Link to comment
Share on other sites

There are a few things that will need to be done if adding a new item. Though adding an item like this is easier than you think! The game code looks like it is already able to handle new light sources, just needs to have the item added to the game.

 

- Define the new item

- Add crafting recipies for adding fuel/batteries, and removing them

- Adding the item to the distribution lists.

- Maybe also add a texture!

 

In this example it would be easiest to copy the sections of the code for the existing flashlight item and modify to make it a lantern.

 I would hightly recommend looking at a few other mods to check how they handle new items and recipies, and the general mod structure, and especially how they handle adding new items to the suburbsdistribution table.

 

Key LUA files to look at are the media\scripts\items.txt  media\scripts\recipies.txt and media\lua\server\items\distribution.lua files

 

Key things to look at that will shape the light in the item definition:

 

TorchCone    =    TRUE,   - If set to false, will have the radial light (I think)

LightDistance    =    16, This will control the range of the light, may want to lower it a bit given that lanterns don't have quite the range that flashlights do

Link to comment
Share on other sites

There are a few things that will need to be done if adding a new item. Though adding an item like this is easier than you think! The game code looks like it is already able to handle new light sources, just needs to have the item added to the game.

 

- Define the new item

- Add crafting recipies for adding fuel/batteries, and removing them

- Adding the item to the distribution lists.

- Maybe also add a texture!

 

In this example it would be easiest to copy the sections of the code for the existing flashlight item and modify to make it a lantern.

 I would hightly recommend looking at a few other mods to check how they handle new items and recipies, and the general mod structure, and especially how they handle adding new items to the suburbsdistribution table.

 

Key LUA files to look at are the media\scripts\items.txt  media\scripts\recipies.txt and media\lua\server\items\distribution.lua files

 

Key things to look at that will shape the light in the item definition:

 

TorchCone    =    TRUE,   - If set to false, will have the radial light (I think)

LightDistance    =    16, This will control the range of the light, may want to lower it a bit given that lanterns don't have quite the range that flashlights do

Thanks for the info! Anon again to the rescue lol. But I have already made the item itself, defined its recipes and added it to the loot table. The issue comes in with adding and removing batteries. Right now I have it setup with two different items, Empty LED Lantern and LED Lantern with a recipe to turn the empty lantern into a "full" regular LED Lantern using a battery. The problem comes in when I want to remove the battery. Right now the battery is destroyed when crafting a new LED Lantern and the lantern just loses power and becomes an Empty LED Lantern when depleted. It doesnt "use" the battery like the flashlight does. Here are my scripts:

fc_ll_items.txt:

module Ledlantern{	item LEDLantern	{		LightDistance	=	5,		Weight	=	1.6,        ReplaceOnDeplete = emptyLEDLantern,		Type	=	Drainable,		TorchCone	=	FALSE,		UseDelta	=	0.0009,		LightStrength	=	0.8,		DisplayName	=	LED Lantern,		ActivatedItem	=	TRUE,		Icon	=	ledlantern,	}        item emptyLEDLantern    {		Weight	=	1,		Type	=	Normal,		DisplayName	=	Empty LED Lantern,		Icon	=	ledlantern,     }}

fc_ll_recipes.txt:

 

module Ledlantern{    recipe Insert Battery Into Lantern  	{   	   destroy Battery,       destroy emptyLEDLantern,   	   Result:LEDLantern,	   Time:30.0,  	}}

As opposed to the recipe for the adding and removing batteries from the vanilla flashlight which looks like this:

 

  recipe Remove Battery   {     keep Torch,     Result:Battery,     Time:30,     OnTest:TorchBatteryRemoval_TestIsValid,     OnCreate:TorchBatteryRemoval_OnCreate,   }   recipe Insert Battery   {     destroy Torch,     destroy Battery,     Result:Torch,     Time:30,     OnTest:TorchBatteryInsert_TestIsValid,     OnCreate:TorchBatteryInsert_OnCreate,   }

I see that those look like LUA functions at the bottom but do not know what they do or where they are or if I can reuse them for my own recipes.

 

EDIT: I could have just done exactly what the vanilla flashlight does and just spawn a battery when removing it from the light but then you would just get a full battery. That's exploitable. You could use the lantern until its about dead then get a fresh battery from it. An obvious problem lol. I am unclear about how the flashlight actually gets and sets the battery state.

Link to comment
Share on other sites

It looks like the TorchBatteryRemoval_OnCreate and TorchBatteryRemoval_TestIsValid and other related functions are in the Media\Lua\Server\recipecode.lua file.

 

Looking at the code, it is able to check the "Used Delta"  of the Torch item, and when it creates the battery back in the inventory, sets its usage to the same.

It looks like in the vanilla game there is no "Empty Battery" and will just assume the Torch has no battery if completely used up.

 

You will likely need to create a new function that mimics this, specifically for the added lantern. Should be easy enough to copy/paste and tweak for use with your LED Lantern. 

function TorchBatteryRemoval_OnCreate(items, result, player)  for i=0, items:size()-1 do	-- we found the battery, we change his used delta according to the battery	if items:get(i):getType() == "Torch" then		result:setUsedDelta(items:get(i):getUsedDelta());		-- then we empty the torch used delta (his energy)		items:get(i):setUsedDelta(0);	end  endend
Link to comment
Share on other sites

 

It looks like the TorchBatteryRemoval_OnCreate and TorchBatteryRemoval_TestIsValid and other related functions are in the Media\Lua\Server\recipecode.lua file.

 

Looking at the code, it is able to check the "Used Delta"  of the Torch item, and when it creates the battery back in the inventory, sets its usage to the same.

It looks like in the vanilla game there is no "Empty Battery" and will just assume the Torch has no battery if completely used up.

 

You will likely need to create a new function that mimics this, specifically for the added lantern. Should be easy enough to copy/paste and tweak for use with your LED Lantern. 

function TorchBatteryRemoval_OnCreate(items, result, player)  for i=0, items:size()-1 do	-- we found the battery, we change his used delta according to the battery	if items:get(i):getType() == "Torch" then		result:setUsedDelta(items:get(i):getUsedDelta());		-- then we empty the torch used delta (his energy)		items:get(i):setUsedDelta(0);	end  endend

Hmmm.. That looks odd to me. I notice that TorchBatteryRemoval_OnCreate accepts some parameters it looks like? (items, result, and player) At least that's what my Java knowledge tells me. But when it is called from the recipe script it doesn't provide any input. Do you happen to know why that is? Where are those values being passed in coming from?

Link to comment
Share on other sites

Hmm. I appear to be causing an exception somewhere. I copied the required methods from recipecode.lua and added them to my own lanternUtils.lua and simply renamed the occurrences of "Torch" to "Lantern". Here is my recipe file:

module Ledlantern{    recipe Insert Battery Into Lantern  	{   	    destroy LEDLantern,        destroy Battery,        Result:LEDLantern,        Time:30,        OnTest:LanternBatteryInsert_TestIsValid,        OnCreate:LanternBatteryInsert_OnCreate,  	}        recipe Remove Battery From Lantern    {        keep LEDLantern,        Result:Battery,        Time:30,        OnTest:LanternBatteryRemoval_TestIsValid,        OnCreate:LanternBatteryRemoval_OnCreate,    }}

And here is my lanternUtils.lua:

-- Return true if recipe is valid, false otherwisefunction LanternBatteryRemoval_TestIsValid (sourceItem, result)      print("Battery Removal Test Entered");	return sourceItem:getUsedDelta() > 0;end-- When creating item in result box of crafting panel.function LanternBatteryRemoval_OnCreate(items, result, player)  print("Battery Removal OnCreate Entered");  for i=0, items:size()-1 do	-- we found the battery, we change his used delta according to the battery	if items:get(i):getType() == "Torch" then		result:setUsedDelta(items:get(i):getUsedDelta());		-- then we empty the torch used delta (his energy)		items:get(i):setUsedDelta(0);	end  endend-- Return true if recipe is valid, false otherwisefunction LanternBatteryInsert_TestIsValid (sourceItem, result)	return sourceItem:getUsedDelta() == 0; -- Only allow the battery inserting if the flashlight has battery left in it.end-- When creating item in result box of crafting panel.function LanternBatteryInsert_OnCreate(items, result, player)  for i=0, items:size()-1 do	-- we found the battery, we change his used delta according to the battery	if items:get(i):getType() == "Battery" then		result:setUsedDelta(items:get(i):getUsedDelta());	end  endend

And here is the resulting stack trace when I click "Remove Battery From Lantern":

Battery Removal Test Entered <- Debug print statement.-------------------------------------------------------------attempted index: getTexture of non-table: null-----------------------------------------STACK TRACE-----------------------------------------function: addDynamicalContextMenu -- file: ISInventoryPaneContextMenu.lua line # 906function: createMenu -- file: ISInventoryPaneContextMenu.lua line # 459function: doContextOnJoypadSelected -- file: ISInventoryPane.lua line # 912function: onJoypadDown -- file: ISInventoryPage.lua line # 302function: onJoypadPressButton -- file: JoyPadSetup.lua line # 220function: onJoypadRenderTick -- file: JoyPadSetup.lua line # 477java.lang.RuntimeException: attempted index: getTexture of non-table: null	at se.krka.kahlua.vm.KahluaThread.tableget(KahluaThread.java:1544)	at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:621)	at se.krka.kahlua.vm.KahluaThread.call(KahluaThread.java:162)	at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1722)	at se.krka.kahlua.vm.KahluaThread.pcallvoid(KahluaThread.java:1667)	at se.krka.kahlua.integration.LuaCaller.pcallvoid(LuaCaller.java:53)	at se.krka.kahlua.integration.LuaCaller.protectedCallVoid(LuaCaller.java:81)	at zombie.Lua.Event.trigger(Event.java:37)	at zombie.Lua.LuaEventManager.triggerEvent(LuaEventManager.java:64)	at zombie.GameWindow.run(GameWindow.java:1184)	at zombie.GameWindow.maina(GameWindow.java:999)	at zombie.gameStates.MainScreenState.main(MainScreenState.java:150)	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)	at java.lang.reflect.Method.invoke(Method.java:606)	at com.exe4j.runtime.LauncherEngine.launch(Unknown Source)	at com.exe4j.runtime.WinLauncher.main(Unknown Source)

Any suggestions? Thanks for all your help! 

Link to comment
Share on other sites

You are welcome! I am new to LUA modding, and the PZ codebase. Learning as I go, and best way is to help people figure out stuff while I brainstorm a few ideas. ( I have no clue what I am doing). I *think* that the params for the function are passed by the EventHandler java code, likely a table of items from the recipie, the result item type/data? and the current player.

 

But it looks like you may need to add the base items as a import. It gave me an error for the battery removal recipe in the startup console.
 

 

module Ledlantern
{
imports
    {
        Base
    }

recipe Insert Battery Into Lantern
    {

 

This should fix the crashing, checking out the other stuff now

 

Edit: Found another issue that would allow infinite batteries to be created in your lanternUtils.lua, correction in bold, it looks like the original function was specifically looking for the "Torch" item.

 

 

-- When creating item in result box of crafting panel.
function LanternBatteryRemoval_OnCreate(items, result, player)

print("Battery Removal OnCreate Entered");

for i=0, items:size()-1 do
    -- we found the battery, we change his used delta according to the battery
    
if items:get(i):getType() == "LEDLantern" then
        result:setUsedDelta(items:get(i):getUsedDelta());
        -- then we empty the torch used delta (his energy)
        items:get(i):setUsedDelta(0);
    end
end
end

Though you will run into one issue with the addition of the Empty LED Lantern, you can't add batteries to it currently. When the battery is removed from the full lantern, it stays just as an "LED Lantern" and doesn't get emptied. In the vanilla code there is no "Empty Flashlight" and adding one to the LED lamp is definitly possible but will take some tweaking to the lanternUtils and recipie script.

Link to comment
Share on other sites

You are welcome! I am new to LUA modding, and the PZ codebase. Learning as I go, and best way is to help people figure out stuff while I brainstorm a few ideas. ( I have no clue what I am doing)

 

But it looks like you may need to add the base items as a import. It gave me an error for the battery removal recipe in the startup console.

 

 

module Ledlantern

{

imports

    {

        Base

    }

recipe Insert Battery Into Lantern

    {

 

This should fix the crashing, checking out the other stuff now

 

Thanks again! Yep this did stop the crashing. And I can confirm that the infinite battery issue is present. I am trying to see what the Flashlight does differently. It seems to set its "Used Delta" to 0. I am trying to replicate this with the lantern but the code looks pretty much the same. I am a bit puzzled as to why its not operating in the same way.

 

EDIT: Wait I think I found it!  "if items:get(i):getType() == "Torch" then"

Torch should totally be the lantern lol. Copy/Paste oversight.

 

Link to comment
Share on other sites

And after that change it is now working perfectly :). Thanks again AnonPrime! Your help has been invaluable! I am going to clean this up a little and post it in the mod forum. Ill shoot you a link and if you want you can check it out. After all its pretty much entirely because of your help that I have been able to complete the mod. I walk away knowing quite a bit more than when I started.

EDIT: Looks like we found the issue independently at about the same time xD. I simply removed the empty lantern. Its no longer necessary as it was a work around until I could get the batteries actually working as intended.

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...