Jump to content

OnZombieDead add inventory


PizzaPepperoni

Recommended Posts

Hello all,

 

I'm new to modding and made some mods for myself that work by trial and error and some info from this site. However I'm stuck at this issue for some time now, and i was hoping to get some help here :)

I got a piece of code from "NamedWeapons" Mod, for the OnZombieDead function and counter.

Everything works, except the part where i should get an item in my inventory. i have tried different approaches like getPlayer():getInventory():Additem... and player:getInventory():.. all without result. Same goes for trying to say an ingame message with Say(".. ") function. Only the the "Print" messages show up in my console, but the effects don't ingame.

Help would be much appreciated!

 

pff sorry i can't even get the spoiler function to work .. frustrating :S

IsoPlayer:getPrimaryHandItemlocal function numberKills(items, result, player)	local player = getPlayer();	local inv = player:getInventory();	local primary = player:getPrimaryHandItem();	if primary ~= nil then	        local pModData = primary:getModData();		pModData.nKills = pModData.nKills + 1;				print("Zombies killed with this weapon " .. pModData.nKills);				if pModData.nKills >= 1 then		print("Zombie killed");    Gamble = ZombRand(4);    if Gamble == 3 then		print("Gamble3");        inv:AddItem("Base.Shotgun");    elseif Gamble == 2 then		print("Gamble2");        inv:AddItem("Base.Pistol");    elseif Gamble == 1 then		print("Gamble1");        inv:AddItem("Base.Saw");    elseif Gamble == 0 then		print("Gamble0");        inv:AddItem("Base.Hammer");else	return;	end						print("End");		end	endend	Events.OnZombieDead.Add(numberKills);
Link to comment
Share on other sites

Sorry, currently on my phone so can't read this very well to check for formatting and such.

Something I've noticed is when something isn't working correctly there is a capital letter or colon/semicolon missing somewhere. Another thing I do for troubleshooting is comment sections off to make sure others are working. It can be painstaking and time consuming but is a great way to debug.

Or you can just wait for RoboMat to come around :P

Link to comment
Share on other sites

Try this:

local function numberKills(items, result, player)    local player = getPlayer();    local inv = player:getInventory();    local primary = player:getPrimaryHandItem();    if primary then -- syntactic sugar for foo ~= nil                local pModData = primary:getModData();        pModData.nKills = pModData.nKills or 0; -- You'll need to initialise the variable if it doesn't exist yet.        pModData.nKills = pModData.nKills + 1;                print("Zombies killed with this weapon " .. pModData.nKills);                if pModData.nKills >= 1 then            print("Zombie killed");                        local Gamble = ZombRand(4);            if Gamble == 3 then                print("Gamble3");                inv:AddItem("Base.Shotgun");            elseif Gamble == 2 then                print("Gamble2");                inv:AddItem("Base.Pistol");            elseif Gamble == 1 then                print("Gamble1");                inv:AddItem("Base.Saw");            elseif Gamble == 0 then                print("Gamble0");                inv:AddItem("Base.Hammer");            else                return;            end            print("End");        end    endendEvents.OnZombieDead.Add(numberKills);
No guarantee that it'll work. Are you sure "getPlayer()" returns the correct player character? If not try:

local player = getSpecificPlayer(player);
Link to comment
Share on other sites

Thanks for the replies! I'm a big fan of both your mods!

 

yeah i tried to do zoning with the print option. The gamble function works because i get a different result with each kill (gamble0-3). Can't find the capital though :P

 

I tried the code you send RoboMat, but still no succes. With the code with getPlayer(), i get the exact same result as i got before: print does work but no items in inventory. With the local player, i get all kinds of error messages in the console.

 

Does it matter in which Lua folder the file is? I tried both shared and server folders.

Link to comment
Share on other sites

Tested with only Hydrocraft Mod active including this code in server folder.

Result i get in server console:


 

Zombies killed with this weapon 1
Zombie killed
Gamble1
End
Zombies killed with this weapon 2
Zombie killed
Gamble3
End
Zombies killed with this weapon 3
Zombie killed
Gamble1
End
Zombies killed with this weapon 4
Zombie killed
Gamble2
End
Zombies killed with this weapon 5
Zombie killed
Gamble1
End

Link to comment
Share on other sites

I think there must be something wrong with the accessing of the inventory.

I get this message after deletion of that line.

 

-------------------------------------------------------------
attempted index: getInventory of non-table: null
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 2
java.lang.RuntimeException: attempted index: getInventory 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:83)
        at zombie.characters.IsoZombie.Hit(IsoZombie.java:757)
        at zombie.network.GameServer.hitZombie(GameServer.java:3050)
        at zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:154
0)
        at zombie.network.GameServer.main(GameServer.java:353)
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 2

 

Link to comment
Share on other sites

I added an item in the list that doesn't exist in the zomboid folder (removed the mod for testing).

I think this must mean that it does look up the item, right? it only doesn't execute it in game for some reason. No other errors pop up.

 

Zombies killed with this weapon 5
Zombie killed
gamble2
End

 

Zombies killed with this weapon 6
Zombie killed
ERROR: ItemContainer.AddItem: can't find tommyguns_items.weapon_1911
gamble5
End

Link to comment
Share on other sites

Ah I just remembered. I think you need to refresh the inventory for the items to show up.

    -- Make sure we refresh the inventory so the items show up.    local pdata = getPlayerData(player:getPlayerNum());    if pdata then        pdata.playerInventory:refreshBackpacks();        pdata.lootInventory:refreshBackpacks();    end
Link to comment
Share on other sites

I get an error regarding the line:  local pdata = getPlayerData(player:getPlayerNum());

tried some alterations but still no succes :(

details below:

 

 

Zombies killed with this weapon 1
Zombie killed
Gamble3
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 34
java.lang.RuntimeException: Object tried to call nil in numberKills
        at se.krka.kahlua.vm.KahluaUtil.fail(KahluaUtil.java:91)
        at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:947)
        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:83)
        at zombie.characters.IsoZombie.Hit(IsoZombie.java:757)
        at zombie.network.GameServer.hitZombie(GameServer.java:3050)
        at zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:154
0)
        at zombie.network.GameServer.main(GameServer.java:353)
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 34

 

Link to comment
Share on other sites

So according to the event reference the only parameter for methods called by the OnZombieDead event is the zombie. I'm at work so I can't check it right now.

But that would mean that your second and third parameter (result, player) are in fact nil.

 

So you'd have to add back the line you removed:

local function numberKills(zombie) --Change params here   local player = getPlayer(); -- This worked because if it didnt you would not see the prints   -- add stuff to inv  end 

Another thing regarding OnZombieDead (in case you do this in order to add loot to the zed):

 

You can add items to the zombies inventory but when you loot the corpse they won't be there. The reason is: When the zombie dies it is removed and an container is added to the grid square where the zombie died. When a player comes close to that grid square, the container is populated with loot. So if you want to add stuff to the corpse you'll have to use OnFillContainer

Link to comment
Share on other sites

Testing your mod right now, will let you know what I come up with.

 

Here is how I changed it and got results:

 

local function numberKills()	local player = getPlayer();	local inv = player:getInventory();	local primary = player:getPrimaryHandItem();		if primary ~= nil then	                local pModData = primary:getModData();		pModData.nKills = pModData.nKills or 0; 		pModData.nKills = pModData.nKills + 1;				print("Zombies killed with this weapon " .. pModData.nKills);				if pModData.nKills >= 1 then			print("Zombie killed");			Gamble = ZombRand(4);			if Gamble == 3 then				print("Gamble3");				inv:AddItem('Base.Shotgun');				elseif Gamble == 2 then				print("Gamble2");				inv:AddItem('Base.Pistol');				elseif Gamble == 1 then				print("Gamble1");				inv:AddItem('Base.Saw');				elseif Gamble == 0 then				print("Gamble0");				inv:AddItem('Base.Hammer');				else				return;			end						print("End");		end	endend	Events.OnZombieDead.Add(numberKills);

 

It's formatted to my liking. Honestly, I don't understand how parameters work. I've read up on them, but I know next to nothing when it comes to programming.

 

With the above code gamble was rolled with each kill I got and weapons spawned as they should.

Link to comment
Share on other sites

Thanks for the effort! It works in Singleplayer mode! I had been testing it on my server everytime. But on multiplayer it still doesn't work.. Tried it with a clean server and copied new game files into the folder.. maybe that was the problem all along for me. Is there a difference in coding for multiplayer and singleplayer?

Link to comment
Share on other sites

I've never tried modding anything on multiplayer. I assume it has something to do with the getPlayer line. I believe getPlayer():getSpecificPlayer(0); tells it to only affect the player controlling their player... if that makes sense. I believe getPlayer(); could potentially affect other players in the area such as in multiplayer, whereas in single player there is only one possible player so you don't have to specify. I could be completely wrong though...

Link to comment
Share on other sites

I tried to implement the getSpecificPlayer() into the code. But now a new error shows up:

Object tried to call nil in numberKills, regarding the primary weapon, i guess.

Don't know what it means haha

 

local function numberKills()
    local player = getSpecificPlayer(0);
    print(" got specific player");
    local inv = getInventory();
    local primary = getPrimaryHandItem();

    if primary ~= nil then    
                local pModData = primary:getModData();
        pModData.nKills = pModData.nKills or 0;
        pModData.nKills = pModData.nKills + 1;        
        print("Zombies killed with this weapon " .. pModData.nKills);
        
        if pModData.nKills >= 1 then ........

Link to comment
Share on other sites

You could always do something like this to loop through nearby players:

local function doGetPlayers()
    local players         = IsoPlayer.getPlayers();
    local array_size     = players:size();
    for i=0, array_size-1, 1 do
        local player = players:get(i);
        print(player:getUsername().." X: "..tostring(player:getX()).." Y: "..tostring(player:getY()))
    end
end  

 

In the games java code, when you call IsoPlayer.getPlayers() it does a check to determine if it's the server calling it or a client calling it. If it detects the game client is the server itself, it'll return ALL characters on the server. If it's a normal game client it'll just return the nearby players.

I think that if you installed the mod on the server, it'd pass the server check. I'm not sure though, as I'm not very experienced with multiplayer modding.

 

Edit: Not too sure if that's what you want, though.

Btw, numberKills is calling nill because you never called player

 

Should be like this:


    local player = getSpecificPlayer(0);
    print(" got specific player");
    local inv = player:getInventory();
    local primary = player:getPrimaryHandItem();

Link to comment
Share on other sites

I removed the player: because if i didn´t i got an error in that line#. I know next to nothing about lua. I was trying to get it working by trial and error, but when that failed i was hoping to get a quick solution on this forum, since i found a lot of information on here. And not to spam it with codes. So I don't know what to do with your reply either.

 

The thing I had in mind was exactly what the now working single player variant is doing: Spawn 1 item in player inventory after a zombie has been killed through ZombRand. I have made something simillar using an item instead of a zombiekill to get a weapon in inventory and it worked in MP right away. I thought it would be easier to accomplish this modification.

Link to comment
Share on other sites

I removed the player.  because if i didn´t i got an error in that line#. I know next to nothing about lua. I was trying to get it working by trial and error, but when that failed i was hoping to get a quick solution on this forum, since i found a lot of information on here. And not to spam it with codes. So I don't know what to do with your reply either.

 

The thing I had in mind was exactly what the now working single player variant is doing: Spawn 1 item in player inventory after a zombie has been killed through ZombRand. I have made something simillar using an item instead of a zombiekill to get a weapon in inventory and it worked in MP right away. I thought it would be easier to accomplish this modification.

Odd... What's the error that you get when you re-add the player bit of the code? It's calling nil on local inv and local primary because you never called getSpecificPlayer(0), local player = getSpecificPlayer(0) is basically a shortcut so that you don't have to type the same thing over again.

 

As far as I know, the ":" (without the quotes) acts like a chain. The first function gets called, then the one after the ":", and if you add another ":" at the end of the "chain" it'll call that one afterwards, and so on. It's kind of hard to explain, so here's an example:

 

local player = getPlayer()

 

local primary = player:getPrimaryHandItem() -- putting a : at the end of the function tells lua that whatever's afterwards is a function to be called immediately after. As I said before, it's like linking a chain

 

local maxCondition = primary:getConditionMax() -- so the "link" stored in primary is called here, and links getConditionMax()

 

primary:setCondition( maxCondition ) -- returns the "chain saved in the primary variable, and the "chain" saved in the maxCondition variable.

 

 

Think of "chains" like shortcuts, you link a chain with the primary and player variables, and instead of having to type getPlayer():getPrimaryHandItem():setCondition( getPlayer():getPrimaryHandItem():getConditionMax()), you could save the "getPlayer():getPrimaryHandItem" bit into a chain.

 

So this:

 

local player = getPlayer():getDescriptor()

 

print(player:getForeName())

 

Is equivalent to this:

 

getPlayer():getDescriptor():getForeName()

 

The main reason for saving a specific function call to a variable to "chain" is for efficiency. If you have something that calls getPlayer():getDescriptor() alot, you could save that in a variable and "chain" it.

 

 

 

Also, just curious, could you please post the code of your current mod, and the code of the similar one you mentioned that worked?

 

Would help to check and contrast what worked and what didn't.

 

 

"I know next to nothing about lua" Neither did anyone when they started. We all have to learn somehow :)

Link to comment
Share on other sites

Thanks for the advice! But I was aware of the chain story :) I think I just don't know the different functions I can use and such.

The code is all in here haha it ain't that much. just what is below + the zombrand function.

And the one similar was just based on RoboMat's Hydrocraft mod, combination of a recipe and use OnCreate: to activate a function which i added in the HCExtra.lua file in the same way the others are in that file.

 

code:

 

 

local function numberKills()
    local player = getSpecificPlayer(0);
    print(" got specific player");
    local primary = player:getPrimaryHandItem(); -- line #4

 

    if primary ~= nil then    
                local pModData = primary:getModData();

Console:

 got specific player
-------------------------------------------------------------
attempted index: getPrimaryHandItem of non-table: null
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 4
java.lang.RuntimeException: attempted index: getPrimaryHandItem of non-table: nu
ll
        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:83)
        at zombie.characters.IsoZombie.Hit(IsoZombie.java:757)
        at zombie.network.GameServer.hitZombie(GameServer.java:3050)
        at zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:154
0)
        at zombie.network.GameServer.main(GameServer.java:353)
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 4

 

 

 

local function numberKills()
    local player = getSpecificPlayer(0);
    print(" got specific player");
    local primary = getPrimaryHandItem();
    
    if primary ~= nil then    
                local pModData = primary:getModData();

 

 

Console:

 

 

 got specific player
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 4
java.lang.RuntimeException: Object tried to call nil in numberKills
        at se.krka.kahlua.vm.KahluaUtil.fail(KahluaUtil.java:91)
        at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:947)
        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:83)
        at zombie.characters.IsoZombie.Hit(IsoZombie.java:757)
        at zombie.network.GameServer.hitZombie(GameServer.java:3050)
        at zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:154
0)
        at zombie.network.GameServer.main(GameServer.java:353)
-----------------------------------------
STACK TRACE
-----------------------------------------
function: numberKills -- file: ZombieKills.lua line # 4

Link to comment
Share on other sites

Thanks for the advice! But I was aware of the chain story :) I think I just don't know the different functions I can use and such.

The code is all in here haha it ain't that much. just what is below + the zombrand function.

And the one similar was just based on RoboMat's Hydrocraft mod, combination of a recipe and use OnCreate: to activate a function which i added in the HCExtra.lua file in the same way the others are in that file.

 

code:

 

 

local function numberKills()

    local player = getSpecificPlayer(0);

    print(" got specific player");

    local primary = player:getPrimaryHandItem(); -- line #4

 

    if primary ~= nil then    

                local pModData = primary:getModData();

Console:

 got specific player

-------------------------------------------------------------

attempted index: getPrimaryHandItem of non-table: null

-----------------------------------------

STACK TRACE

-----------------------------------------

function: numberKills -- file: ZombieKills.lua line # 4

java.lang.RuntimeException: attempted index: getPrimaryHandItem of non-table: nu

ll

        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:83)

        at zombie.characters.IsoZombie.Hit(IsoZombie.java:757)

        at zombie.network.GameServer.hitZombie(GameServer.java:3050)

        at zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:154

0)

        at zombie.network.GameServer.main(GameServer.java:353)

-----------------------------------------

STACK TRACE

-----------------------------------------

function: numberKills -- file: ZombieKills.lua line # 4

 

 

 

local function numberKills()

    local player = getSpecificPlayer(0);

    print(" got specific player");

    local primary = getPrimaryHandItem();

    

    if primary ~= nil then    

                local pModData = primary:getModData();

 

 

Console:

 

 

 got specific player

-----------------------------------------

STACK TRACE

-----------------------------------------

function: numberKills -- file: ZombieKills.lua line # 4

java.lang.RuntimeException: Object tried to call nil in numberKills

        at se.krka.kahlua.vm.KahluaUtil.fail(KahluaUtil.java:91)

        at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:947)

        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:83)

        at zombie.characters.IsoZombie.Hit(IsoZombie.java:757)

        at zombie.network.GameServer.hitZombie(GameServer.java:3050)

        at zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:154

0)

        at zombie.network.GameServer.main(GameServer.java:353)

-----------------------------------------

STACK TRACE

-----------------------------------------

function: numberKills -- file: ZombieKills.lua line # 4

Ah ok, wasn't sure if you knew.

 

Anyways, I find it kind of odd that line #4 is calling nil. The player in question already has something equipped, right?

 

That's the only thing I can think of. It shouldn't be calling nil, and your code looks like it should work, yet it doesn't. Very strange.

Link to comment
Share on other sites

Yeah the primary is equiped with the weapon I killed with. There must be a problem converting it from single player to multiplayer. Tried adding:     if primary then        
                local pModData = primary:getModData();

without the ~= nil, it still gives the error object tried to call nill in numberKills, which makes no sense to me after removing that line.

Link to comment
Share on other sites

Hey PizzaPepperoni,

If you want to make your logic MP compatible (Add items when you kill zombie) you will have to do some additional work.

 

In Multiplayer OnZombieDead is executed on the server while your characters inventory is maintained on the client.

 

So you will have to write some client server logic. I recently worked on a similar issue for my mod and wrote up a little 'Lessons Learned' on multiplayer coding.

 

The reason getSpecificPlayer(0) might not work for you, might be because I think this function is only working client side (for split screen). This is a theory.

 

I used getPlayer() in my mod on server side and it worked: Example. This class handles commands that were sent from client to server. In my case it changes the moddata of the weapon to add the used ammotype (switchAmmo).

 

In essence you will have to send a server command to the client when the zombie dies, and on the client side receive the server command and add the item to the players inventory.

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