I'm trying to make it so that a number is one or two. Then it will affect the corresponding team and select a random team member. The selected team member's team will be changed to a different team. Right now, it's not changing the person's team AFAIK and if there is no one on the chosen team it dies. I'm not sure how to check if there's no value at all. Here's the snipped that needs work:
Hidden/Spoiler:
[code]
local nume = math.floor(ScriptCB_random()+1)
print("Today's lucky number is", nume)
SetReinforcementCount(4, 1)
OnTimerElapse(
function(timer)
if (GetNumTeamMembersAlive(2) + GetNumTeamMembersAlive(1)) >= 2 then
if GetNumTeamMembersAlive(num) == nil then
if GetNumTeamMembersAlive(2) > 0 then
nume = 2
print("Lucky number changed to ", nume)
end
if GetNumTeamMembersAlive(1) > 0 then
nume = 1
print("Lucky number changed to ", nume)
end
end
SetProperty("cp1", "Team", "0")
SetProperty("cp2", "Team", "0")
SetProperty("cp3", "Team", "0")
SetProperty("cp6", "Team", "0")
SetProperty("cp7", "Team", "0")
SetProperty("cp8", "Team", "0")
SelectCharacterTeam(GetTeamMember(nume, (math.floor(ScriptCB_random()*GetNumTeamMembersAlive(nume))-1)), 4)
print("Someone selected from team ", nume)
print("Team member selected: ", (math.floor(ScriptCB_random()*GetNumTeamMembersAlive(nume))-1))
ShowMessageText("level.0TT.begin")
StartTimer(win)
StartTimer(check)
StartTimer(checker)
ShowTimer(win)
DestroyTimer(timer)
end
if (GetNumTeamMembersAlive(2) + GetNumTeamMembersAlive(1)) <= 1 then
ShowMessageText("level.0TT.nope")
SetTimerValue(grace, 30)
StartTimer(grace)
end
end,
grace
)[/code]
The two ifs within if GetNumTeamMembersAlive(num) are relatively new (along with the if GetNumTeamMembersAlive(num)). I'm trying to make them check if there is anyone on the team that was selected. If there isn't anyone on the team, then it sets it to the other team so someone can actually be chosen. I'm pretty much out of ideas on how to do this. As per usual, help is greatly appreciated.
Re: More Scripting Help Needed
Posted: Sat May 31, 2014 8:35 pm
by razac920
OK, first of all I would use 0 instead of nil.
Mostly, your problem is with this line of code:
SelectCharacterTeam(GetTeamMember(nume, (math.floor(ScriptCB_random()*GetNumTeamMembersAlive(nume))-1)), 4)
You aren't checking if GetTeamMember returns a player at all, and if it does, is the player alive, and you also aren't randomly picking a team member, either. The team members are not indexed to have the alive ones first. Here's what you should do instead:
local alive = false
local player = nil
while not alive do
local index = math.floor(ScriptCB_random()*GetTeamSize(nume))) // not GetNumTeamMembersAlive and not -1
player = GetTeamMember(nume, index)
if player and GetCharacterUnit(player) and IsObjectAlive(player) then
SelectCharacterTeam(player,4)
alive = true
end
end
Re: More Scripting Help Needed
Posted: Sat May 31, 2014 11:03 pm
by Noobasaurus
So I messed around with what you put, and I finally arrived here. When the function goes off, the game freezes and spams the log indefinitely. Here's what it says:
Message Severity: 2
C:\Battlefront2\main\Battlefront2\Source\LuaCallbacks_Mission.cpp(635)
Entity "1" not found
I'm not sure why it can't find people. It's searching both teams from the amount of people alive on each team. The variable changes each time it doesn't work so it keeps searching. Here's what I have currently:
while not alive do
print("Testing random character for selection...")
nume = math.floor(ScriptCB_random()*2)+1
print("RANDOM NUMBER:", nume)
index = math.floor(ScriptCB_random()*GetNumTeamMembersAlive(nume)) --// not GetNumTeamMembersAlive and not -1
player = GetTeamMember(nume, index)
if player and GetCharacterUnit(player) and IsObjectAlive(player) then
SelectCharacterTeam(player,4)
alive = true
end
end
nume always returns either 1 or 2. I just don't know why it can't find people when there are obviously people running around.
I also have the variables first set up before this.
Re: More Scripting Help Needed
Posted: Sun Jun 01, 2014 4:07 am
by razac920
Noobasaurus wrote:It's searching both teams from the amount of people alive on each team.
This is your problem! Suppose there is a team of 2 players, the first one dead and the second alive, as follows:
GetTeamMember(nume,0) is dead and GetTeamMember(nume,1) is alive. If you use what you had:
index = math.floor(ScriptCB_random()*GetNumTeamMembersAlive(nume)), you will do math.floor([num from 0 to 1]*1) = 0 every time, and you will NEVER find the alive player. If instead you use GetTeamSize, like I originally told you, you will do math.floor([num from 0 to 1]*2), which half the time will give 1, the index for the ALIVE player. There is NO way to directly search for alive players (unless you make a list of them and continually update it as players spawn and die), so it's much easier and better to just randomly pick players (alive or dead) repeatedly until you find an alive one.
Also, I forgot that while loops don't always work right, so switch to a for loop like so:
Hidden/Spoiler:
[code]
for i=1,10000 do -- probability of not picking the 1 alive player out of 200 in 10000 trials is (199/200)^10000~10^-22, so safe
print("Testing random character for selection...")
nume = math.floor(ScriptCB_random()*2)+1
print("RANDOM NUMBER:", nume)
index = math.floor(ScriptCB_random()*GetTeamSize(nume))
player = GetTeamMember(nume, index)
if player and GetCharacterUnit(player) and IsObjectAlive(player) then
SelectCharacterTeam(player,4)
i=10000
end
end
[/code]
Re: More Scripting Help Needed
Posted: Mon Jun 23, 2014 11:38 pm
by Noobasaurus
I did some stuff with that and it works pretty well. However, my continuous timers that check if there are people alive on team 4 don't seem to be working properly. You said that there is no way to get the number of alive people on a team, so how would I do this? Here's what I have:
for i=1,10000 do -- probability of not picking the 1 alive player out of 200 in 10000 trials is (199/200)^10000~10^-22, so safe
print("Testing random character for selection...")
nume = math.floor(ScriptCB_random()*2)+1
print("TEAM:", nume)
index = math.floor(ScriptCB_random()*GetTeamSize(nume))
print("MEMBER:", index)
player = GetCharacterUnit(GetTeamMember(nume, index))
if player and IsObjectAlive(player) then
SetObjectTeam(player, 4)
i=10000
end
end
OnTimerElapse(
function(timer)
if (GetNumTeamMembersAlive(1) + GetNumTeamMembersAlive(2)) < 1 then
MissionDefeat(1)
MissionDefeat(2)
MissionDefeat(3)
MissionVictory(4)
DestroyTimer(timer)
end
if GetNumTeamMembersAlive(4) < 1 then
MissionVictory(1)
MissionVictory(2)
MissionVictory(3)
MissionDefeat(4)
DestroyTimer(timer)
end
SetTimerValue(checker, 0.1)
StartTimer(checker)
end,
checker
)
Re: More Scripting Help Needed
Posted: Mon Jun 23, 2014 11:48 pm
by razac920
Oh a nonstop timer going? That could be messy and slow things down, much easier and better to check GetNumTeamMembersAlive only after someone dies, so use OnCharacterDeath instead (check name for accuracy). And sorry I didn't say there isn't a way to get the number of alive people, there IS, that is what the function GetNumTeamMembersAlive does, HOWEVER, you won't know the indices of the alive players on the team (meaning which character is returned from GetTeamMember(teamnum,index)), so you must choose random numbers at least in the range from 0 to GetTeamSize(teamnum)-1 to be guaranteed of eventually choosing a living player.
CharacterTeam = [] --tracks which team each characters' unit is supposed to be on
CheckVictory = function()
--game over check. You need to make sure at least one player spawns on team 4 before any players die else the game will end
if NumPlayersAlive[1] <= 0 and NumPlayersAlice[2] <= 0 then
MissionDefeat({1,2,3})
else if NumPlayersAlive[4] <= 0 then
MissionVictory({1,2,3})
end
end
Shuffle = function(list)
local size = #list
while size >= 2 do
local index = math.random(n) --1 <= index <= n
list[size], list[index] = list[index], list[size]
end
--Find the first random player that's alive
--We don't continually loop or continually pick random numbers because there's a chance all the players are dead. We only need to go through them all once. Anything more is wasting CPU time.
--pick a random team
local team = 1
if (ScriptCB_random() > 0.5) then
team = 2
--building a list of all valid ids for this team
local size = GetTeamSize(team)
local teamMembers = []
local m
for m = 0, size-1 do
teamMemberIds.append(m)
end
--randomize player order
teamMemberIds = Shuffle(teamMemberIds)
--find the first living player
local allDead = true
for m = 0, size-1 do
local player = GetTeamMember(team, teamMemberIds[m+1])
local unit = GetCharacterUnit(player)
if unit ~= nil then
allDead = false
--move this player onto team 4
SetProperty(unit, 'Team', 4)
SetProperty(unit, 'PerceivedTeam' 4)
CharacterTeam[character] = 4
NumPlayersAlive[4] += 1
NumPlayersAlive[team] -= 1
CheckVictory()
break --stops the loop
end
end
if allDead then
--no one was alive on the team. If you trying them all again now, they'll probably still all be dead. Best to wait 15 seconds before trying again, or better yet, loop through CharacterTeam and change one of the team numbers. When that player respawns he'll be on the new team.
end
--tracking the amount of spawned players on each team
OnCharacterSpawn(function(character)
local unit = GetCharacterUnit(character)
local expectedTeam = CharacterTeam[character] or GetObjectTeam(unit)
--make sure swapped characters stay on their new team
SetProperty(unit, 'Team', expectedTeam)
SetProperty(unit, 'PerceivedTeam' expectedTeam)
I'm not sure what your end goal is so I'm not sure if this is what you wanted or not. It also probably has a typo or two as I can't test it.
Re: More Scripting Help Needed
Posted: Thu Jun 26, 2014 8:05 pm
by Noobasaurus
Thank you so much for writing this code for me Zerted. I'm trying to make it work but some things written I thought looked like SWBF2 functions so I changed those. The munger was spitting out an error at the first line and I didn't know what was wrong so I commented it out. When it got to the line with #list, it spat out another error. Now I'm really confused because it doesn't look wrong at all.
--CharacterTeam = () --tracks which team each characters' unit is supposed to be on
CheckVictory = function()
--game over check. You need to make sure at least one player spawns on team 4 before any players die else the game will end
if GetNumTeamMembersAlive(1) <= 0 and GetNumTeamMembersAlive(2) <= 0 then
MissionDefeat({1,2,3})
else if GetNumTeamMembersAlive(4) <= 0 then
MissionVictory({1,2,3})
end
end
Shuffle = function(list)
local size = #list
while size >= 2 do
local index = math.random(n) --1 <= index <= n
list(size), list(index) = list(index), list(size)
end
--Find the first random player that's alive
--We don't continually loop or continually pick random numbers because there's a chance all the players are dead. We only need to go through them all once. Anything more is wasting CPU time.
--pick a random team
local team = 1
if (ScriptCB_random() > 0.5) then
team = 2
--building a list of all valid ids for this team
local size = GetTeamSize(team)
local teamMembers = ()
local m
for m = 0, size-1 do
teamMemberIds.append(m)
end
--randomize player order
teamMemberIds = Shuffle(teamMemberIds)
--find the first living player
local allDead = true
for m = 0, size-1 do
local player = GetTeamMember(team, teamMemberIds(m+1))
local unit = GetCharacterUnit(player)
if unit ~= nil then
allDead = false
--move this player onto team 4
SetProperty(unit, 'Team', 4)
SetProperty(unit, 'PerceivedTeam' 4)
GetCharacterTeam(character) = 4
GetNumTeamMembersAlive(4) += 1
GetNumTeamMembersAlive(team) -= 1
CheckVictory()
break --stops the loop
end
end
if allDead then
--no one was alive on the team. If you trying them all again now, they'll probably still all be dead. Best to wait 15 seconds before trying again, or better yet, loop through CharacterTeam and change one of the team numbers. When that player respawns he'll be on the new team.
end
--tracking the amount of spawned players on each team
OnCharacterSpawn(function(character)
local unit = GetCharacterUnit(character)
local expectedTeam = GetCharacterTeam(character) or GetObjectTeam(unit)
--make sure swapped characters stay on their new team
SetProperty(unit, 'Team', expectedTeam)
SetProperty(unit, 'PerceivedTeam' expectedTeam)
Sorry, but change them back. NumPlayersAlive and CharacterTeam are supposed to be global array variables (technically dictionaries in Lua). You use brackets to access elements like: array[2] to get the 2nd item stored in the array. () are used for functions, not for arrays.
However I should have used curly brackets to create the arrays. It should be {0, 0, 0, 0} and {} compared to using () or [] for those first two lines. Sorry about that. I've been programming in Python all week and Python and Lua are too similar. Also change local teamMembers = () to use curly braces: local teamMembers = {}. Everywhere else where I used [] should have stayed as [].
# is a shortcut for table.getn(), but maybe SWBF2's version of Lua is too old to have it. Change that line to: local size = table.getn(list)
GetNumTeamMembersAlive/NumPlayersAlive, CharacterTeam, CheckVictory, and Shuffle should be put at the top of your Lua file. You should probably put the middle section (random player selection) into it's own function which will be before ScriptPostLoad. It'll be called by something in ScriptPostLoad. Inside ScriptPostLoad put the OnCharacterDeath/Spawn code.
Re: More Scripting Help Needed
Posted: Fri Jun 27, 2014 12:29 am
by Noobasaurus
I reverted everything back and made all of the changed you listed. It still doesn't like NumPlayersAlive = [0, 0, 0, 0] line. It says that there is an unexpected symbol next to the bracket. Now the brackets aren't the problem because the shuffle part is loaded before that now. I figured something out yay
I have the things below before ScriptPostLoad.
Hidden/Spoiler:
[code]
Shuffle = function(list)
local size = table.getn(list)
while size >= 2 do
local index = math.random(n) --1 <= index <= n
list[size], list[index] = list[index], list[size]
end
CharacterTeam = [] --tracks which team each characters' unit is supposed to be on
CheckVictory = function()
--game over check. You need to make sure at least one player spawns on team 4 before any players die else the game will end
if NumPlayersAlive[1] <= 0 and NumPlayersAlive[2] <= 0 then
MissionDefeat({1,2,3})
else if NumPlayersAlive[4] <= 0 then
MissionVictory({1,2,3})
end
end
--pick a random team
local team = 1
if (ScriptCB_random() > 0.5) then
team = 2
--building a list of all valid ids for this team
local size = GetTeamSize(team)
local teamMembers = {}
local m
for m = 0, size-1 do
teamMemberIds.append(m)
end
--randomize player order
teamMemberIds = Shuffle(teamMemberIds)
[/code]
NumPlayersAlive = {0, 0, 0, 0} --4 spots for 4 teams, tracks alive counts
CharacterTeam ={} --tracks which team each characters' unit is supposed to be on
You'll probably want all the code starting with line "--pick a random team" and afterwards somewhere else. Likely in a timer or something inside ScriptPostLoad.