Jump to content

I want to make wooden spikes trap to the game. How to make them hurt zombies?


dred

Recommended Posts

Like in the title - how? I thought to copy wooden floor, change it properties to fit to my mod idea and add it to the game in the form of new building item. Is there a way to do this? I have no experience in this field, but I like to invent and contrive :)

post-3591-0-48305300-1384807002.png

Link to comment
Share on other sites

Hi. I'm working on my idea and i am making properties file for my item:

 

item SpikeTrap
{
display name = "Spike Trap",
type = "Weapon",
ShareDamage = true,
KnockBackOnNoDeath = true, 
KnockdownMod = 100,
MaxDamage = 50,
MinDamage = 10,
MaxHitCount = 17,
ConditionMax = 79,
CriticalChance = 10,
CanBarricade = true,
 
--i'm not sure on this one: --
ConditionLowerChanceOneIn = 15,
 
}
 
This is what i did so far (default values for testing purpose).
If anyone can give me a hint/opinion if this properties are correct i will be grateful.
Link to comment
Share on other sites

ConditionLowerChanceOneIn=15 means that there is 1/15 chance to lower ConditionMax by 1 when you hit someone with it.

 

But this will work as handweapon,if you put it on ground,nothing happens to zombies wandering through it.That will need different approach and lots of coding.I dont have any experiences here but when i looked at camping code.how many things i need for making tent...it will take many late evenings for newbie like me to create something like that. 

 

EDIT I was curious what item with KnockdownMod = 100 do to my heard of stupid zombies in sandbox,but it does nothing and i died horribly :(

Edited by Ramibuk
Link to comment
Share on other sites

Phew ... I'm afraid, that you will need more than a few lines of code to get this one done.

This is a rough outline of what you'll need (at least as far as I can tell):

  • New Inventory Item for the spikes
  • New World Context Menu
  • Timed Action for placing the spikes
  • WorldObject to represent the spikes (= Building Object in TIS terms^^)
  • Custom behaviour of how zombies interact with it (instead of bashing on it they should pass through)
So here is what code you should look at IMO.

media/lua/BuildingObjects => for how to place stuff in the game world

media/lua/ISUI/ISWorldObjectContextMenu.lua => for how to create a new context menu

media/lua/TimedActions => for the timed actions

Link to comment
Share on other sites

It'd be nice to be able to do simple things in the game without having to resort to learning Zomboid 101, Zomboid 102, and the extra Zomboid elective courses.

 

The key to making the spikes is the interaction portion of it.  The difficulty lies in making it work with the rest of the game.  There's really no plug'n'play style guide for the game due to the relative lack of interest in the game compared to how much content it has.

Link to comment
Share on other sites

 

 

can you upload that png file?

Is in the first post ;-)

Thank you guys for the hints and support in this one :mrgreen:

Situation looks like this so far:

 

 

  • New Inventory Item for the spikes done!
  • New World Context Menu
  • Timed Action for placing the spikes
  • WorldObject to represent the spikes (= Building Object in TIS terms^^)
  • Custom behaviour of how zombies interact with it (instead of bashing on it they should pass through)

 

I will continue my work and will see how far i go :D

Link to comment
Share on other sites

The key to making the spikes is the interaction portion of it.  The difficulty lies in making it work with the rest of the game.

It actually isn't that hard, if you know about coding - but then again that's the requirement for most mods. PZ is probably the easiest game to mod I've seen so far. If lua is too hard for you, you can already make custom item with via scripting.

I will continue my work and will see how far i go :D

You can always ask for help here ;)

Link to comment
Share on other sites

Hello. I wanted to make an update in the mod creation progress. Last week was a trial for me and i have concentrated my efforts on the scripts and i have made a tiny mod adding this post-3591-0-64814800-1386107629.gif little baby to the crafting list. Torch Mod can be found here http://pz-mods.net/weapons-items/Torch/

 

Spike Trap Mod is completed in 10% and i'm lack of modding knowledge to go forward. I post here files i managed to create following this http://www.theindiestone.com/community/viewtopic.php%3Ff=34&t=14783.html# tutorial and if anyone can look at them and gave me a little help i will be extremely grateful :rolleyes:

Thanks in advance!

 

TPM:http://www.mediafire.com/download/iiih2vmwq0cng6m/Spike%20Trap.zip

Link to comment
Share on other sites

I found on this forum a file i needed to complete my mod. It's from another mod adding basicaly the same item. The problem is that when i try to load the lua file i get this string repeating in cmd window:

at zombie.scripting.objects.ScriptModule.getItem(Script Module.java:1119)

Can any of you guys having a bit more experience look at this code and correct it if needed?

--***********************************************************--**                    ROBERT JOHNSON                     **--***********************************************************TrapSharpWood = ISBuildingObject:derive("TrapSharpWood");function TrapSharpWood:create(x, y, z, north, sprite)	self.sq = getCell():getGridSquare(x, y, z);	self.javaObject = IsoThumpable.new(cell, self.sq, sprite, north, self);    	buildUtil.setInfo(self.javaObject, self);	buildUtil.consumeMaterial(self);	self.javaObject:setMaxHealth(self:getHealth());	self.javaObject:setBreakSound("breakdoor");       self.sq:AddSpecialObject(self.javaObject);	buildUtil.addWoodXp();	self.sq:setSpeedMod(0.1);	self.sq:setHurtMod(0.01);		self.javaObject:setShowName("Thorn trap"); 	--print("add a Trap at : " .. x .. "," .. y);endfunction TrapSharpWood:new(player)	-- OOP stuff	-- we create an item (o), and return it	local o = {};	setmetatable(o, self);	self.__index = self;	o:init();	o:setSprite("trap_sharpwood");	o:setNorthSprite("trap_sharpwood");	o.name="sharp wood trap";	o.player = player;	o.dismantable = true;	o.canBarricade = false;       o.canPassThrough=true;	o.blockAllTheSquare = false;	return o;endfunction TrapSharpWood:getHealth()       return 100;endfunction TrapSharpWood:isValid(square, north)	return buildUtil.canBePlace(square, north);endfunction TrapSharpWood:render(x, y, z, square, north)	return true;endfunction TrapSharpWood.onDestroy(thump, square, modData)    square:getSpecialObjects():remove(thump);    square:getObjects():remove(thump);    square:setSpeedMod(1);    square:setHurtMod(0);end--[[function TrapSharpWood.load(square)                                  for i=0,square:getSpecialObjects():size() - 1 do       local obj=square:getSpecialObjects():get(i);            if obj:getName() == "sharp wood trap" then               obj:setShowName("Thorn trap");               --obj:setSprite("trap_sharpwood");               break;            end        endend]]--Events.LoadGridsquare.Add(TrapSharpWood.load);

Mod location: pan.baidu.com/s/1BXjbF

Link to comment
Share on other sites

 from  zombie.scripting.objects.ScriptModule:

  public Item getItem(String name)  {    if (name.contains("."))      return ScriptManager.instance.getItem(name);    if (!this.ItemMap.containsKey(name))    {      for (int n = 0; n < this.Imports.size(); n++)      {        Item inv = ScriptManager.instance.getModule((String)this.Imports.get(n)).getItem(name);        if (inv != null) {          return inv;        }      }      return null;    }    return (Item)this.ItemMap.get(name);  }

Looks like an issue with your script.... not your lua :)

Link to comment
Share on other sites

  • 2 weeks later...

Hello fellow survivors, this is my first post and I seek your knowledge !

I bought Project Zomboid two days ago after playing the demo (awesome game btw) and went into modding for the first time  :wub: !

 

So my 4 questions are related to this topic since I went with the same idea (I started from scratch since I didn't know lua ... I still don't :D  ). I have somewhat managed to create traps (and have them properly reloaded after a save reload ...), submenu and stuff and to detect collisions with zombies (using Events.OnObjectCollide : character, object) checking for my IsoThumpable object (a trap). However :(  :

 

1 : It seems only zombies are detected (character argument), never the player; is it expected behaviour ?

Note that both zombies and player can pass through.

 

2 : The zombie class inherit from the more general character class and could use the method say(string) inherited from

zombie.characters.IsoGameCharacter

but it seems zombies can't talk (nil table or something like that). It's the same with some other methods (splatBlood ...).

3 : Most important question : character.getHealth() returns 0 when used on a zombie (he's dead, somewhat logical), so how can my trap do damage to something that is dead ? :D

Ok the collision is detected multiple times (100 ?) in a second interval, so the zombie health quickly drops to 0. Although it doesn't kill it, I found a solution using Kill(player) when health reach 0. Funny thing the collision still trigger for a while after the zombie's death :)

 

4 : to remember deployed traps, i use a table. However to refresh the sprite after save load i use Events.OnIsoThumpableLoad while the table keeps the IsoThumpable object found themselves, checking if id already exists (not a save load case).

 

On many forums modders use Events.LoadGridsquare and a table with coordinates to detect an already existing Object in this table. But my traps are never found at the same place (by a few pixels ...) when doing so (i move far away and come back, 2 traps in the table ...), which result in a table linearly growing in size :o .

Is the png sprite too small to cover a square and therefor move within the square between reloads? :ph34r: And what's the height of the png ? My traps are huge, like walls, they're to kill elephants! It's stretched all the way up to the roof.

 

4bis : To delete a trap from the table after removing it from the ground, I use table.remove(mytable, mykey), mykey in this case is just an integer since i store only objects as value. I read on some lua forums that it's not good and should use mytable[mykey] = nil. But the size of the map does not change doing so, or does it ? maybe #mytable is the number of elements, but the size of the value associated to "mykey" is 0 (since it's nil) so the table memory size is lower ?

 

5 : Am I going the wrong way ? :D

 

Thank you for any input you may have and all the tutorials I found ! 

 

PS : i'm on build 21, the "iwillbackupmysave" branch.

Link to comment
Share on other sites

Its going to be hard to answer specifically without code snippets but

 

2.... Sounds like your character return isn't correct... was it object tried T call nill in NULL?

I know for a fact that the say method will work with zombies because I used it in NecroForge

zombie = getVirtualZombieManager():createRealZombieNow(X, Y, Z);zombie:say("..ONE....OF....US!..");

this would, in turn, answer 1 & 3.... A zombie IS dead, fictionally speaking, but in in terms of the code it should have a value associated with its health. The fact that the methods wont work, your getting no health & cant detect player characters implies that your event isn't returning the IsoGameCharacter Object

 

4.... Really cant answer this without an example showing how your going about it. I don't understand why you have to load your trap into a lua table when your object should be stored in a Java HashTable once added to a gridsquare, but that's based upon the way I would do it.

sprites shouldn't stretch unless you use the drawTextureScaled() method

 

4bis.... Your over thinking it, the devs remove objects from lua tables using MyTable[MyKey] = nil

 

Sorry I couldn't be of more help :)

Link to comment
Share on other sites

Thanks you for your answer. Yes that's exactly object tried T call nill in NULL.

 

Here's the function associated with a collision trigger so you can see what I'm doing :

function Trap.SpikeTrapDmg(character, object)	print("collision with " .. character:toString() .. " and " .. object:toString());	if object:getModData()['isTrap'] == 'true' and object:getModData()['trapId'] == "SpikeTrap" then		local charstr = character:toString();		local str = "zombie.characters.IsoZombie";		local pstr = "zombie.characters.IsoGameCharacter ";		-- zed		if charstr:sub(1, str:len()) == str then			--print(character:getHealth());			--character:setHealth(0);			--if character:getHealth() == 0 then				--character:setOnFloor(true);				character:say("HAAAAA");				character:Kill(nil); -- getSpecificPlayer does not increase kill count				--local weapon_effect = HandWeapon.new("Base", "Hammer", "Weapon", "Hammer");				--character:Hit(weapon_effect, getSpecificPlayer(0), 0,0,0);								getSpecificPlayer(0):setZombieKills(getSpecificPlayer(0):getZombieKills() + 1); -- what happens is 2 zombies die at the same time ? need a lock								Trap.destroyed(object);			--end		--- player does not trigger collision like zeds ?		elseif charstr:sub(1, pstr:len()) == pstr then			print("collision perso");			character:Say("Collision !");			--print("with player");		end	endendEvents.OnObjectCollide.Add(Trap.SpikeTrapDmg);

character:say("HAAAAA");

character:Hit(...)

 

Don't work but Kill does. I have the same problem with destroying the trap (to make a sound like with a hammer, a hit fails, but the remove of the object works, and I use the playsound(breakdoor) ...).

 

The first print (who collide with what) does not appear when it's me walking on the trap (it doesn't block all the square and i can go through it).

 

 

The way I store stuff when creating any trap, in the parent file Trap.lua (each trap derives it) :

function Trap:create(x, y, z, north, sprite)		local cell = getWorld():getCell();   	self.sq = cell:getGridSquare(x, y, z);   	self.javaObject = IsoThumpable.new(cell, self.sq, sprite, north, self);   	buildUtil.setInfo(self.javaObject, self);	buildUtil.consumeMaterial(self);			   	self.javaObject:setMaxHealth(self:getHealth());   	self.javaObject:setBreakSound("breakdoor");		self.sq:AddSpecialObject(self.javaObject);		if self.javaObject:getModData()["trapId"] == "SpikeTrap" then		self.javaObject:getModData()['id'] = #trapping.spikeTrapsList + 1;		table.insert(trapping.spikeTrapsList, self.javaObject);	else		self.javaObject:getModData()['id'] = #trapping.trapsList + 1;		table.insert(trapping.trapsList, self.javaObject);	endend

And trapping.trapsList and spikeTrapList are in a trapping.lua file (used to load textures, loading on save load etc) :

trapping = {};trapping.trapsList = {};trapping.spikeTrapsList = {};

One more question :

I remove the IsoThumpable trap using :

local square = trap:getSquare();square:RemoveTileObject(trap);

And not the method from the super class :

ISBuildingObject.removeFromGround(square);

Since the super look through all objects and maybe it can remove something else ? (on top of being slower ?)

 

Well for now it kills zombies, produces a breakdoor sound, and an attract zombie sound of radius 10. Id's like to do small damages instead - but the collision trigger 100 times per second - and kill myself walking on it too.

Link to comment
Share on other sites

OK..... So.....

 

It seems your right, there is no event trigger for collide in IsoPlayer & it overwrites collideWith() in IsoMovingObject

Maybe your best bet, for that, would be a Event.OnPlayerMove. Get the players gridsquare & check your ModData against the objects in that square until you find (or dont find) your trap.

 

As for why Kill() will work for you & no other methods..... Thats a head head fuck :huh:

Your aware that your Say() in your zombie condition above is a syntax error?

Based on the error, it still sounds like your not getting the object correctly.... Maybe try iterating over the objects in the gridsquare until you find the zombie, though you really SHOULDN'T have to do that  <_<

 

I still dont see why you need your traps lists, once the JavaObject is created with IsoThumpable.new() the Java should handle all of the loading/rendering 

Link to comment
Share on other sites

OK..... So.....

 

It seems your right, there is no event trigger for collide in IsoPlayer & it overwrites collideWith() in IsoMovingObject

Maybe your best bet, for that, would be a Event.OnPlayerMove. Get the players gridsquare & check your ModData against the objects in that square until you find (or dont find) your trap.

You were right, the OnPlayerMove trick did it. I can check my traps until I find (or don't) a trap on the square I am. I now die if I walk on one of my traps. :D (setHealth doesn't change my health, I think we'd need to make the object behave as a weapon swing)

As for why Kill() will work for you & no other methods..... Thats a head head fuck :huh:

Your aware that your Say() in your zombie condition above is a syntax error?

Based on the error, it still sounds like your not getting the object correctly.... Maybe try iterating over the objects in the gridsquare until you find the zombie, though you really SHOULDN'T have to do that  <_<

Thanks you for spotting the syntax error ... :ph34r: Although I still don't understand why I can't call some methods.

I still dont see why you need your traps lists, once the JavaObject is created with IsoThumpable.new() the Java should handle all of the loading/rendering

Some sprites need changing according to their object status, I also planned to make bloody spikes once a zombie stepped on it, with durability etc ... but since I can't do anything else than kill the zombie straight, it will wait.

 

I think it answers the OP (although not at best) on how to damage (kill) zombies with spikes (and the player). Use Events.OnObjectCollide and/or Event.OnPlayerMove to check if a zombie/player collide with one of your traps. Then do the work.

Link to comment
Share on other sites

Nice :)

Glad I could help, if your still having problems with loading too many traps into your lua table, you could try removing he thumpable then adding a new object with a different sprite when the trap is triggered.... 

 

I should have read up beforehand, but did you try the square:setHurtMod() that was in the example that the OP found? looks like the usual modifier setup, use a decimal value where 1 will kill you instantly & 0 will do no damage.

If that works, then you could just use your events for trap status

Link to comment
Share on other sites

I should have read up beforehand, but did you try the square:setHurtMod() that was in the example that the OP found? looks like the usual modifier setup, use a decimal value where 1 will kill you instantly & 0 will do no damage.

If that works, then you could just use your events for trap status

 

Hehe that's the first thing I looked at, although I didn't found setHurtMod in the documentation, so I think it wont work :D

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