Logic error in my turn based combat system

  1. What do you want to achieve?
    I am setting up a turn based combat system, where it is one player’s turn and once they attack it becomes the other player’s turn. Once a player’s HP reaches 0 the game ends and a victor is congratulated.

  2. What is the issue?
    Everything works fine, except that once a player’s HP reaches 0 another turn is allowed by the now dead player. The turns then stop after that, there’s only one extra turn after the game should have ended. I need help as I don’t know how to fix this, I don’t even know why it’s happening, but I assume it has something to do with my logic as there are no errors displayed.

I have one localscript that is in starterplayer and I have one server script which handles most of the turn based system.

Server script:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
Players.PlayerAdded:Connect(function(player)
	local statsFolder = Instance.new("Folder")
	statsFolder.Name = "Stats"


	local strength = Instance.new("IntValue")
	strength.Value = 10
	strength.Name = "Strength"

	local agility = Instance.new("IntValue")
	agility.Value = 10
	agility.Name = "Agility"

	local defense = Instance.new("IntValue")
	defense.Value = 10
	defense.Name = "Defense"

	local speed = Instance.new("IntValue")
	speed.Value = math.random(5,10)
	speed.Name = "Speed"

	local hp = Instance.new("IntValue")
	hp.Value = 10
	hp.Name = "HP"

	local mana = Instance.new("IntValue")
	mana.Value = 10
	mana.Name = "Mana"

	local level = Instance.new("IntValue")
	level.Value = 1
	level.Name = "Level"

	local xp = Instance.new("IntValue")
	xp.Value = 0
	xp.Name = "XP"

	local gold = Instance.new("IntValue")
	gold.Value = 0
	gold.Name = "Gold"

	local gems = Instance.new("IntValue")
	gems.Value = 0
	gems.Name = "Gems"

	local weapon = Instance.new("IntValue")
	weapon.Value = "sword"
	weapon.Name = "Weapon"

	strength.Parent = statsFolder
	agility.Parent = statsFolder
	defense.Parent = statsFolder
	speed.Parent = statsFolder
	hp.Parent = statsFolder
	mana.Parent = statsFolder
	level.Parent = statsFolder
	xp.Parent = statsFolder
	gold.Parent = statsFolder
	gems.Parent = statsFolder
	weapon.Parent = statsFolder

	statsFolder.Parent = player
end)
local weapons = {
	sword = {
		minDamage = 10,
		maxDamage = 20,
		speedMod = 0

	}
}


local turnStartEvent = Instance.new("RemoteEvent")
turnStartEvent.Name = "TurnStartEvent"
turnStartEvent.Parent = ReplicatedStorage

local attackEvent = Instance.new("RemoteEvent")
attackEvent.Name = "AttackEvent"
attackEvent.Parent = ReplicatedStorage

--Wait for two players to join the match
print("Wait started")
repeat
	task.wait()
until #Players:GetChildren() == 2
print("Wait complete")
local pList = Players:GetChildren()
local player1 = pList[1]
local player2 = pList[2]
local player1Init = player1:WaitForChild("Stats"):WaitForChild("Speed").Value
local player2Init = player2:WaitForChild("Stats"):WaitForChild("Speed").Value
local gameOver = Instance.new("BoolValue")
gameOver.Name = "GameOver"
gameOver.Parent = ReplicatedStorage
gameOver.Value = false
local function gameOverFunction(winner, loser)
	print(winner," wins!")
	gameOver = true
	-- execute victory screen and send player back to menu
end

local function turnHandler()
	--decide whose turn it is
	local turn
	
	if player1Init > player2Init then
		turn = player1
		player1Init = player1Init*0.5
		player2Init = player2Init*1.5
	elseif player1Init < player2Init then
		turn = player2
		player2Init = player2Init*0.5
		player1Init = player1Init*1.5
	elseif player1Init == player2Init then
		local random = math.random(1,2)
		if random == 1 then
			turn = player1
			player1Init = player1Init*0.5
			player2Init = player2Init*1.5
		else
			turn = player2
			player2Init = player2Init*0.5
			player1Init = player1Init*1.5
		end
	end
	--remote event to receive player input
	
	turnStartEvent:FireClient(turn)
	
	--wait until turn finished to end function
	attackEvent.OnServerEvent:Wait()
	--
end
--receive player input
	--attack function
local function attackFunction(attacker)
	local target
	if attacker == pList[1] then
		target = pList[2]
	elseif attacker == pList[2] then
		target = pList[1]
	else
		print("attack function target assignment error")
	end
	local weaponDamage = math.random(weapons["sword"]["minDamage"], weapons["sword"]["maxDamage"])
	local attackerStr = attacker.Stats.Strength.Value
	local damageOutput = math.round(weaponDamage*(1+(attackerStr/100)))
	local damageNegated = target.Stats.Defense.Value
	local damageDealt = damageOutput - damageNegated
	print(attacker," attacks ",target)
	print(damageOutput," dmg output, ",damageNegated," dmg negated, ",damageDealt," total dmg dealt.")
	print(target," HP Before attack: ",target.Stats.HP.Value)
	target.Stats.HP.Value -= damageDealt
	print(target," HP: ",target.Stats.HP.Value)
	if target.Stats.HP.Value <= 0 then
		gameOverFunction(attacker, target)
	end
	
end
--wrap it all in a loop that ends when a player dies
attackEvent.OnServerEvent:Connect(attackFunction)

while gameOver.Value == false do
	print("Turn start!")
	turnHandler()
	
end

LocalScript

local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local attackButton = player.PlayerGui.ScreenGui.AttackButton
humanoid.WalkSpeed = 0
humanoid.JumpHeight = 0
local turnStartEvent = ReplicatedStorage:WaitForChild("TurnStartEvent")
local attackEvent = ReplicatedStorage:WaitForChild("AttackEvent")
local turnActive = false
local gameOver = ReplicatedStorage:WaitForChild("GameOver")
local function turnFunction()
	if gameOver.Value == false then
		print(player,"'s turn")
		turnActive = true
	end
end

local function attackButtonClicked()
	if turnActive == true then
		print("Attack!")
		attackEvent:FireServer(player)
		turnActive = false
	else
		print("It is not your turn.")
	end
	
end
attackButton.MouseButton1Click:Connect(attackButtonClicked)
turnStartEvent.OnClientEvent:Connect(turnFunction)
1 Like