Go factory help

I’m using a go factory in order to create enemies for my game, I want each enemy to have 3 health and get deleted after taking all 3 health.
Currently, with my code, if i spawn in multiple instances of the enemy game object, they share the same 3 hp, so if i hit one enemy twice and then hit the other enemy once, that enemy dies (and gets deleted), how would i ensure each instance of the game object has a separate counter of 3 health

Data Storage file where i store health variables for use across multiple scripts

local M = {}

M.playerHealth = {}
M.playerHealth.my_value = 12

M.enemyHealth = {}
M.enemyHealth.enemy_value = 3

return M

Enemy collision script

local dataStorage = require("main.Data Storage") 
max_enemyHealth = dataStorage.enemyHealth.enemy_value -- creates a health variable
enemyHealth = max_enemyHealth
local TILE_SIZE = 16
print(enemyHealth)

function init(self)
	self.correction = vmath.vector3() -- correction vector
end

function update(self, dt)
	self.correction = vmath.vector3() -- correction vector
end

function on_message(self, message_id, message, sender)
	
	if message_id == hash("contact_point_response") then --checks for a collision message sent by the game
		if message.other_group == hash("objects") or message.other_group == hash("signs") then
			if message.distance > 0 then 
				local proj = vmath.project(self.correction, message.normal * message.distance) -- Combine the accumulated correction with the penetration vector
				if proj < 1 then
					local comp = (message.distance - message.distance * proj) * message.normal -- Calculate how much the player will have to be moved to compensate
					go.set_position(go.get_position() + comp) -- Add the compensation onto the player's position to put them in the right location
					self.correction = self.correction + comp -- Accumulate the correction applied
				end
			end
		end

		if message.other_group == hash("sword") and self.invulnerable ~= true then
			enemyHealthChange(-1)
			local pos = go.get_position()
			-- set a pushback direction based on the collision normal
			local to = pos + message.normal * 30
			-- knockback animation, then continue moving
			go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_OUTQUAD, 0.1, 0, move)
			self.invulnerable = true
			local j
			j = 0
			timer.delay(0.1, true, function(self,handle,time_elapsed)
				if j<5 or j == 5 then 
					go.animate("#sprite", "tint", go.PLAYBACK_ONCE_PINGPONG, vmath.vector4(1, 1, 1, 0), go.EASING_LINEAR, 0.05,0,anim_done)
					j = j+1
				elseif j > 5 then
					timer.cancel(handle)
				end
			end)
			timer.delay(1, false, function()
				--reset invulnerability
				self.invulnerable = false
			end)
		end
	end
end

function enemyHealthChange(hearts)
	enemyHealth = enemyHealth + hearts
	if enemyHealth == 0 then
		sound.play("sfx#Enemy_Death") -- plays the enemy death sfx
		sprite.play_flipbook("#sprite", hash("Poof"), function()
			go.delete()
		end)
		
	elseif enemyHealth > max_enemyHealth then
		enemyHealth = max_enemyHealth
		
	elseif enemyHealth < 0 then
		enemyHealth = 0
		
	end

end

Enemy.go
image

main.collection
image

Spawning script, being honest i’m not sure what everything in here does exactly cause i found it elsewhere on the forums while trying to make this work initially

function init(self)
	local p = go.get_position()
	p.y = vmath.lerp(math.random(), -1080, -920)
	local component = "#factory"
	factory.create(component, p)
	factory.create(component, p)
end

Let me know if i need anything else to try and get this working properly

HP can be a property of the game object, e.g. self.hp - this way you will create a separate self.hp for each instance of the enemy. This applies to every data to you want to be unique to each instance, not shared.

If you still want to store health points on enemies in a Lua table - you need to create a new entry for each enemy, e.g.

M.enemyHealth = {}
M.enemyHealth.enemy_value = 3

change to seomething like:

M.enemyHealth = {}
M.enemyHealth["instance1"] = 3
M.enemyHealth["instance2"] = 3

etc.

thanks, that should help

Hey, sorry for getting back after a few days, but I’ve just gotten to trying to implement this and it’s not working, where have i gone wrong?

Here is my collision code, i’ve changed it, I’ve tried changing the enemy health stuff, but no matter what

local max_enemyHealth = 3 -- creates a health variable
local TILE_SIZE = 16
print(enemyHealth)

function init(self)
	self.correction = vmath.vector3() -- correction vector
	self.enemyHealth = max_enemyHealth
end

function update(self, dt)
	self.correction = vmath.vector3() -- correction vector
end

function on_message(self, message_id, message, sender)
	
	if message_id == hash("contact_point_response") then --checks for a collision message sent by the game
		if message.other_group == hash("objects") or message.other_group == hash("signs") then
			if message.distance > 0 then 
				local proj = vmath.project(self.correction, message.normal * message.distance) -- Combine the accumulated correction with the penetration vector
				if proj < 1 then
					local comp = (message.distance - message.distance * proj) * message.normal -- Calculate how much the player will have to be moved to compensate
					go.set_position(go.get_position() + comp) -- Add the compensation onto the player's position to put them in the right location
					self.correction = self.correction + comp -- Accumulate the correction applied
				end
			end
		end

		if message.other_group == hash("sword") and self.invulnerable ~= true then
			enemyHealthChange(-1)
			local pos = go.get_position()
			-- set a pushback direction based on the collision normal
			local to = pos + message.normal * 30
			-- knockback animation, then continue moving
			go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_OUTQUAD, 0.1, 0, move)
			self.invulnerable = true
			local j
			j = 0
			timer.delay(0.1, true, function(self,handle,time_elapsed)
				if j<5 or j == 5 then 
					go.animate("#sprite", "tint", go.PLAYBACK_ONCE_PINGPONG, vmath.vector4(1, 1, 1, 0), go.EASING_LINEAR, 0.05,0,anim_done)
					j = j+1
				elseif j > 5 then
					timer.cancel(handle)
				end
			end)
			timer.delay(1, false, function()
				--reset invulnerability
				self.invulnerable = false
			end)
		end
	end
end

function enemyHealthChange(hearts)
	self.enemyHealth = self.enemyHealth + hearts
	if self.enemyHealth == 0 then
		sound.play("sfx#Enemy_Death") -- plays the enemy death sfx
		sprite.play_flipbook("#sprite", hash("Poof"), function()
			go.delete()
		end)
		
	elseif self.enemyHealth > max_enemyHealth then
		self.enemyHealth = max_enemyHealth
		
	elseif self.enemyHealth < 0 then
		self.enemyHealth = 0
		
	end

end

I just keep getting this error:

Line 55 is self.enemyHealth = self.enemyHealth + hearts btw

It seems you should pass self as a parameter of enemyHealthChange function. Something like

function enemyHealthChange(self, hearts)

And then you change this line enemyHealthChange(-1) to enemyHealthChange(self, -1)

1 Like

thanks, it works now!
after posting i did consider that I needed self in enemyHealthChange so I added self as a parameter, forgot to pass it as an argument