How do I fix my sword_factory

I have been developing a dungeon crawler and I am developing a system of attack from the war battles tutorial however using my own assets, I have used the code, whilst removing the explosion function as that would not be neccessary in my game. However, when I am pressing space, no swords are spawned. I have ensured that the z value of player is 1 whilst the sword is 0. Any ideas on how to fix this would be greatly appreciated, here is my code:

player
sword
player - continued

Only thing I can see is that self.dir is reset before being passed to the new sword object. Could the sword be spawning underneath the player?

I think it could be, though I have set my player sprite to z: 1
Screenshot 2024-04-08 214343

Update: I added a sword.go to the collection to see if it would disappear on space. I ran a test and when space was pressed, the sword did not disappear until the self.life flag was at 0, therefore I can confirm that the code may be faulty for factory.create. Any suggestions?

here is some more of my code

local speed=100
function init(self)
	msg.post(".", "acquire_input_focus") -- tells object to listen for inputs
	self.input=vmath.vector3()
	self.dir=vmath.vector3(0, 1, 0)
	self.current_anim=nil -- stores current animation
	self.health=40 -- tracks health
	self.max_health=100 -- tracks max_health
	self.speed=100
	self.throwing=false -- sets attack to false, can be turned true with a space input
end

function final(self)
	msg.post(".", "release_input_focus")
end

function update(self, dt) -- allows player position to be updated
	player_pos = go.get_position()
	if vmath.length_sqr(self.dir) > 1 then
		self.dir = vmath.normalize(self.dir) -- normalises direction vector - allows for diagonal movement
	end
	local pos = go.get_position() -- fetches the new position
	go.set_position(pos + self.dir * speed * dt) -- sets new position

	local anim=hash("knight_idle")

	if self.dir.x ~= 0 then -- check if vectors are not 0
		anim=hash("knight_run")
	elseif self.dir.y ~= 0 then
		anim=hash("knight_run")
	end

	if anim ~= self.current_anim then -- checks if animation is the same
		msg.post("#sprite", "play_animation", { id = anim }) -- plays new animation
		self.current_anim=anim -- changes id to new animation id
	end

	self.throwing = false -- sets flag to false - changed each time space is pressed in inputs

	if self.throwing then
		local angle = math.atan2(self.dir.y, self.dir.x) -- computes angle of player
		local rot = vmath.quat_rotation_z(angle) -- Creates a quaternion for angular rotation around Z.
		local props = { dir = self.dir } -- creates a table to pass onto
		factory.create("#swordfactory", nil, rot, props) -- creates sword when input is pressed
	end

	self.dir = vmath.vector3() -- holds direction vector

	if self.health <= 0 then -- checks if health goes to 0
		go.delete()
	end
end


function on_input(self, action_id, action)
	if action_id == hash("up") then
		self.dir.y = 1 -- Up movement
	elseif action_id == hash("down") then
		self.dir.y = -1 -- Down movement
	elseif action_id == hash("right") then
		self.dir.x = 1 -- right movement
	elseif action_id == hash("left") then
		self.dir.x = -1 -- left movement
	elseif action_id == hash("throw") and action.pressed then
		self.throwing = true -- sets flag to true
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash ("remove_health") then -- listens for damage
		self.health=self.health - message.amount -- subtracts health by amount
		health_lost=message.amount -- Determines damage taken
		msg.post("/UI#main", "remove_health", {amount=health_lost}) -- sends message to gui telling it to subtract from health
	end
	if message_id == hash ("add_health_small") then -- listens for on_message
		self.health=self.health+40 -- adds health
		if self.health > self.max_health then -- checks if health goes over max health
			health_calc = self.health-self.max_health -- calculates health that needs to be subtracted
			self.health=self.health-health_calc -- subtracts health by the calculation
			msg.post("/UI#main", "fix_health", {amount=health_calc}) -- communicates change to UI
		end
		if self.health <= self.max_health then -- checks if health is below max health
			msg.post("/UI#main", "add_health_small") -- sends message to UI telling it to add health
		end
	end
	if message_id == hash ("add_health_large") then -- listens for on_message
		self.health=health+80 -- adds health
		if self.health > self.max_health then -- checks if health goes over max health
			health_calc = self.health-self.max_health -- calculates subtraction required
			self.health=self.health-health_calc -- subtracts health by max calculation
			msg.post("/UI#main", "fix_health", {amount=health_calc}) -- communicates change to UI
		end
		if self.health <= self.max_health then -- checks if health is below max health
			msg.post("/UI#main", "add_health_large") -- sends message to UI telling it to add health
		end
	end
	if message_id==hash("contact_point_response") then -- detects contact
		go.set_position(player_pos+message.normal*message.distance) -- corrects position
	end
	if message_id==hash("add_speed") then -- listens for collision from speed_potion
		self.speed=speed + message.amount -- adds potion's value to speed
	end
end
local damage=15 -- damage value to be sent to a target

go.property("dir", vmath.vector3()) -- defines dir and initialises default empty vector

function init(self)
	self.speed = 200 -- speed value of sword
	self.life=1 -- sets time until sword will disappear
end

function update(self, dt)
	local pos = go.get_position() -- get current position
	pos = pos + self.dir * self.speed * dt -- calculate new position based on old position + direction and speed
	go.set_position(pos) -- sets position

	self.life = self.life - dt -- decreases life by delta time (per 1 second)
	if self.life < 0 then -- runs if life = 0
		go.delete()
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash("contact_point_response") then -- if contact with enemy or walls is detected
		msg.post(message.other_id, "remove_health", {amount=damage}) -- sends damage to collided object
		go.delete() -- deletes object
	end
end

I know that the issue is with the spawning in of the sword, the sword itself works fine

The second argument, which is nil, is the position of the sword. Since you are not providing a position, the sword will get the same position as the game object containing the factory. Is this what you want? Is it ok for the sword to be at this position?

That is my intention, yes.

Ok, then I have no idea what’s wrong based on what I’ve seen. Can you create a minimal example project and share it here?

This if statement in the player script will never trigger, since self.throwing is set to false immediately before it.

2 Likes

I changed the position of the false statement to the bottom of update, changed the z value and it works perfectly, thanks for the help.

1 Like