Simplify Team Checking Logic

I want to check 2 players to see if they can damage each other. I have 3 teams, Civilian, Criminal, and Police.

Each player on each team have a PVP tag. Players on Criminal and Police teams have the PVP tag always set to true. Players on the Civilian team can toggle the PVP tag to true or false.

Requirements:
-Civilian can never damage Civilian
-Police can never damage Police
-Criminal can always damage Criminal
-Police and Civilian can never damage each other
-Police and Criminal can always damage each other
-Civilian and Criminal can damage each other if and only if the Civilian has the PVP tag set to true

This is what I have so far. This works.

local function checkCanDamage(player, otherPlayer)
    local playerInPvp = GetPvp(player)
	local otherPlayerInPvp = GetPvp(otherPlayer)
	
	--not allowed to pvp
	if not (playerInPvp and otherPlayerInPvp) then
		print("player is not allowed to pvp")
		return false
	end
	
	--both are civilians
	if (player.Team == civilianTeam) and (otherPlayer.Team == civilianTeam) then
		print(player, otherPlayer, "are on the same team")
		return false
	end
	
	--both are police
	if (player.Team == policeTeam) and (otherPlayer.Team == policeTeam) then
		print(player, otherPlayer, "are on the same team")
		return false
	end
	
	--if either is civilian or police
	if (player.Team == civilianTeam and otherPlayer.Team == policeTeam) or (player.Team == policeTeam and otherPlayer.Team == civilianTeam) then
		print(player, otherPlayer, "are allied")
		return false
	end
	
	--both are criminals
	if (player.Team == criminalTeam) and (otherPlayer.Team == criminalTeam) then
		print("both are criminals")
		return true
	end
	
	--if either is police or criminal
	if (player.Team == policeTeam and otherPlayer.Team == criminalTeam) or (player.Team == criminalTeam and otherPlayer.Team == policeTeam) then
		print(player, otherPlayer, "are enemies")
		return true
	end
	
	--civiians and criminals can damage each other if civilian has pvp
	if otherPlayer.Team == criminalTeam and playerInPvp then
		print(player, "a civilian wants to help")
		return true
	end
	if otherPlayer.Team == civilianTeam and player.Team == criminalTeam and otherPlayerInPvp then
		print(player, "is killing civilians")
		return true
	end
	
	print("should not happen")
end

Is there a way to simplify the team checking? My boolean algebra is not that great.

I think I have cut it down a little.

local function checkCanDamage(player, otherPlayer)
	if not (PlayerInPvp and otherPlayerInPvp) then 
		return false
	elseif (player.Team == otherPlayer.Team) then
		return false
	elseif ((player.Team == criminalTeam) and (otherPlayerInPvp or otherPlayer.Team == policeTeam) then
		return true
	elseif ((player.Team == policeTeam) and (otherPlayer.Team == criminalTeam) then
		return true
    else 
        return false
	end
end
1 Like

This does not satisfy OP’s requirements because anyone with PVP enabled can fight anyone else with PVP enabled. Making logic (and the result) the opposite to what it is doesn’t always work.

1 Like

Overlooked that while writing it, some minor edits should work though.

1 Like

There are definitely multiple ways to write this, but here’s what I came up with.

local function checkCanDamage(player, otherPlayer)
	local playerInPvp = GetPvp(player)
	local otherPlayerInPvp = GetPvp(otherPlayer)
	
	if playerInPvp and otherPlayerInPvp then
		if player.Team == otherPlayer.Team then
			if player.Team == criminalTeam then
				return true -- Both players are criminals
			end
		elseif player.Team ~= civilianTeam and otherPlayer.Team ~= civilianTeam then
			return true -- Neither player is a civilian
		elseif player.Team == criminalTeam or otherPlayer.Team == criminalTeam then
			return true -- One player is a civilian, and the other is a criminal
		end
	end
	
	return false -- None of the conditions were met
end

You can use ternary operators and have the whole thing on one line if you want. For example:

return 
-- Check if civ + police
(player.Team == civilianTeam and otherPlayer.Team == policeTeam) or (player.Team == policeTeam and other player.Team == civilianTeam) or
-- Check if criminal + criminal
(player.Team == crinimalTeam and otherPlayer.Team == crinimalTeam) or
-- Check if pvp + civ + crinimal
(playerInPvp and otherPlayerInPvp) and
(player.Team == civilianTeam and otherPlayer.Team == crinimalTeam) or (player.Team == crinimalTeam and other player.Team == civilianTeam)

This still doesn’t meet OP’s requirements since some team combinations should be allowed to damage eachother even with PVP disabled.

Edit: nvm only civilians can set their PVP.

Similarly to ThousandDegreeKnife’s solution, this doesn’t meet OP’s requirements since some team combinations should be allowed to damage eachother even with PVP disabled.

Edit: nvm only civilians can set PVP.

Only civilians have the option to set their PVP status. Can you elaborate?

Apologies. Didn’t see this. Will edit my replies.

Your first code, before you edited it, allows two Civilians to damage each other if they both have PVP set to true.

The current one allows Criminals to damage Civilians if the Civilian has PVP set to true, but not the other way around. It also does not allow two Criminals to damage each other.