How can I remove something from this table?

Hello so there’s something I had to update in my code due to a recent change I made however I can’t seem to do that and not sure what’s going on.

I have a table that essentially looks like this whenever a new battle is created I put it inside the activeBattles table and inside the battles table I have two tables one for holding all the players and then one for the enmies.

--[[
--[[
activeBattles = {
	battle1 = {
		playersInBattle = {
			player1 = {
				action = ""
			},
			player2 = {
				action = ""
			}
		},
		enemiesInBattle = {} --same thing as playersInBattle just with enemies
	},
	battle2 = {}
	etc
}
]]

When a player flees though I wanna remove that players table from the battle BUT if that’s the only player inside the battle then I need to remove the battle as there’s no players in it.

This is what I updated my old code to, but it still just didn’t work

	for battleName,battleData in pairs(battle) do
		for playerInBattle,playerData in pairs(battleData.playersInBattle) do
			if playerInBattle == player then
				workspace[player]:FindFirstChild("In Battle"):Destroy()
				battle.playersInBattle
			end
		end
		if #battleData.playersInBattle == 0 then
			print("testt")
			workspace:FindFirstChild(battleName):Destroy() --destroys the battle area
			for enemyInBattle,enemyData in pairs(battleData.enemiesInBattle) do
				local Count = 0
				Count += 1
				if game.Workspace.Enemies:FindFirstChild(enemyInBattle) then
					print("test")
					workspace.Enemies[enemyInBattle]:FindFirstChild("In Battle"):Destroy()
					table.remove(battleData.enemiesInBattle,Count)
				end				
			end
			return battle --returns the battle so that I can remove it from the activeBattles table or update it 
		end
	end

Basically though I’m just trying to figure out how I can remove the players table from the table they’re in and then if playersInBattle equals 0 then yeah.

edit: No matter what #battleData.playersInBattle always equals 0 even though there’s a table inside it? So yeah not sure what’s going on

1 Like

I believe you can just set it to nil:

activebattles.battle1 = nil -- removes the table
3 Likes

battle1 isn’t actually what it’s called the actual table looks like this

local activeBattles = {}

And then whenever I create a battle I do

		activeBattles[player.Name.."'s Battle"] = { --I name the battle after the player that started it because why not
			playersInBattle = {},
			enemiesInBattle = {},
		}

And then in another part of my code I put the player inside playersInBattle like this

				playersInBattle[v1.Name] = {
					action = ""
				}

So it would look like this (or it should)

activeBattles = {
["Player1's Battle"] = {
 playersInBattle = {
   Player1 = {
    action = ""
   }
  }
 {
}

So I don’t think that would work

This is simply because # does not work with the hash part/dictionaries, related topic.

print(#{a = 1, b = 2}) --0
print(#{1, 2}) --2

Each player’s table is stored under a key, so it’s a dictionary, which is why #playersInBattle is always 0. So best way to know how many players are in the battle is to keep track of that by yourself, keeping a key under each battle’s table, and when the match starts, set that to how many players are playing, when someone loses, subtract 1.

battle1 = {
    numOfPlayers = --something
    player1 = {

     }; --ect.
1 Like

Well I’m making a turn-based game and I kind of took a similar approach to how wizard 101 does things where you can have up to 4 players and 4 enemies in a battle and players are allowed to walk into and join any battle if there’s enough space for them. So I don’t think I’m able to set how many players are playing because it could change? I’m probably wrong though :s

although if I’m being honest this kind of looks confusing lmao.

1 Like

You just add 1 when the player joins the battle, and subtract them when they leave. You can listen to these events by using PlayerRemoving

local battle1 = {
	numOfPlayers = 0
}


game.Players.PlayerRemoving :Connect(function() -- only subtract if they were in the battle though
	battle1.numOfPlayers -= 1
end)

-- bla bla bla if player clicks a button or something

OnAButtonClickCausePlayerWantedToJoinTheBattle:Connect(function()
	if battle1.numOfPlayers == MAX_PLAYERS then
		script.Parent.TextLabel.Text = 'battle full'
		return
	end
	
	battle1.numOfPlayers += 1
end)

So I don’t think I’m able to set how many players are playing because it could change?

Well as I said, when it changes, you have to change it as well. Implementing this prerequires the player join and leave mechanic first, but you can just do this then come back to it when you have the join/leave system done and alter your code.

To clear the confusion, this might sound scary but it’s rather easy.
(Note that I’m using bindable just for the sake of visualization, so when something happens, you understand what you need to do, using something else instead of a bindable might be better design) (also obviously this code isn’t gonna work in a real scenario, I’m writing to the same key battle1 each time a battle starts).

battleStarted.Event:Connect(function(players) --players is a table of players that are starting this battle
    activeBattles.battle1 = {playersInBattle = {numOfPlayers = #players}}
    for i, v in pairs(players) do
       activeBattles.battle1.PlayersInBattle[v.Name] = {} --initialize a table for each player under his name
    end
end)

playerLeft.Event:Connect(function(player) --player that left
     activeBattles.battle1.playersInBattle.numOfPlayer -= 1
     if activeBattles.battle1.playersInBattle.numOfPlayer == 0 then --if no players
          activeBattles.battle1 = nil --clear the battle
     else
          activeBattles.battle1.playersInBattle[player.Name] = nil --or just remove the player that left
     end
end)

playerJoined.Event:Connect(function() --this part is surely easy
     activeBattles.battle1.playersInBattle.numOfPlayer += 1
end)

Ok so this essentially then looks like what I have, but much much shorter because I already have 2 functions for creating & joining battles however for fleeing (removing a player) it’s just a remote event where if the player selects the flee option then I use their name as a way to find them in the table.

anyways ok I think I understand what’s going on here so I’ll see if I can fix my thing lol

Although a queston I have is there’s also enemies so would I just include some kind of check to see if it’s a player or enemy I assume yeah right? So I had have

local battle1 = {
	numOfPlayers = 0
    numOfEnemies = 0
}

Yah you would.

I would also try to change the name of numOfPlayers makes it sound like everyone including the enemy team and the other team, but yah that’s your choice.

1 Like

Ok so I know you want a simple solution, but i’d suggest you create a unique class for battles, with descriptions of things like number of participants, and on each team, as well as players included, just for convenience.

That’s kind what I already do not sure what you mean about a unique class but I have my table activeBattles where I add new battles to which have that info

So for playerJoined would I put activeBattles.battle1.PlayersInBattle[v.Name] = {} again? Because Id need a new table for that player

this link describes a bit of class constructors; You know of some classes already. Vector3, Instance, CFrame. if you make it a new object that you can run functions on to check players and such it might tidy up your code in the long run. I don’t know if your issue is uh, you’re having issues removing the battle or checking if that’s the only player? but you could index the character from game.Players:GetPlayerFromCharacter() or just check if the Player.Parent == game.Players, to count players?