-- base_fortball.lua

-- if you want base fortball with the default setup, 
-- include base_fortball_default.lua in your map's lua file 
-- and then include base_fortball.lua

-- precache (sounds)
function precache()
	PrecacheSound("misc.bizwarn")
	PrecacheSound("misc.bloop")
	PrecacheSound("misc.buzwarn")
	PrecacheSound("misc.dadeda")
	PrecacheSound("misc.deeoo")
	PrecacheSound("misc.doop")
	PrecacheSound("misc.woop")

	PrecacheSound("otherteam.flagstolen")
	PrecacheSound("yourteam.flagcap")
	PrecacheSound("otherteam.flagcap")

	-- Unagi Power!  Unagi!
	PrecacheSound("misc.unagi_spatial")

	-- goalie sounds
	--PrecacheSound( goalie_sound_loop )
	--PrecacheSound( goalie_sound_idle )
	--PrecacheSound( goalie_sound_pain )
	--PrecacheSound( goalie_sound_kill )
end

function startup()
	SetGameDescription( "Fortball" )

	-- disable certain teams
	for i,v in pairs(disabled_teams) do
		SetPlayerLimit( v, -1 )
	end

	-- set up team limits
	for i1,v1 in pairs(teams) do
		local team = GetTeam(v1)
		for i2,v2 in ipairs(team_info[team:GetTeamId()].class_limits) do
			team:SetClassLimit( i2, v2 )
		end
	end

	local ball = GetEntityByName( "ball" )
	for i,v in pairs(teams) do
		objective_entities[v] = ball
	end

	the_wall_reset()

end

function the_wall_reset()
	OutputEvent( "the_wall", "Enable" )
	OutputEvent( "the_wall_laser_blue", "TurnOn" )
	OutputEvent( "the_wall_laser_red", "TurnOn" )
	AddSchedule("the_wall_disable", THE_WALL_TIMER_DISABLE, the_wall_disable )
	AddSchedule("the_wall_10secwarn", THE_WALL_TIMER_WARN, the_wall_10secwarn )
end

function the_wall_disable()
	OutputEvent( "the_wall", "Disable" )
	OutputEvent( "the_wall_laser_blue", "TurnOff" )
	OutputEvent( "the_wall_laser_red", "TurnOff" )
	BroadCastMessage("#FF_ROUND_STARTED")
	BroadCastSound("otherteam.flagstolen")
end

function the_wall_10secwarn()
	BroadCastMessage("#FF_MAP_10SECWARN")
	AddSchedule("the_wall_9secwarn", 1, the_wall_9secwarn )
end

function the_wall_9secwarn()
	BroadCastMessage("#FF_MAP_9SECWARN")
	AddSchedule("the_wall_8secwarn", 1, the_wall_8secwarn )
end

function the_wall_8secwarn()
	BroadCastMessage("#FF_MAP_8SECWARN")
	AddSchedule("the_wall_7secwarn", 1, the_wall_7secwarn )
end

function the_wall_7secwarn()
	BroadCastMessage("#FF_MAP_7SECWARN")
	AddSchedule("the_wall_6secwarn", 1, the_wall_6secwarn )
end

function the_wall_6secwarn()
	BroadCastMessage("#FF_MAP_6SECWARN")
	AddSchedule("the_wall_5secwarn", 1, the_wall_5secwarn )
end

function the_wall_5secwarn()
	BroadCastMessage("#FF_MAP_5SECWARN")
	SpeakAll( "AD_5SEC" )
	AddSchedule("the_wall_4secwarn", 1, the_wall_4secwarn )
end

function the_wall_4secwarn()
	BroadCastMessage("#FF_MAP_4SECWARN")
	SpeakAll( "AD_4SEC" )
	AddSchedule("the_wall_3secwarn", 1, the_wall_3secwarn )
end

function the_wall_3secwarn()
	BroadCastMessage("#FF_MAP_3SECWARN")
	SpeakAll( "AD_3SEC" )
	AddSchedule("the_wall_2secwarn", 1, the_wall_2secwarn )
end

function the_wall_2secwarn()
	BroadCastMessage("#FF_MAP_2SECWARN")
	SpeakAll( "AD_2SEC" )
	AddSchedule("the_wall_1secwarn", 1, the_wall_1secwarn )
end

function the_wall_1secwarn()
	BroadCastMessage("#FF_MAP_1SECWARN")
	SpeakAll( "AD_1SEC" )
end

function goalie_bounds_notification(player)
	BroadCastSoundToPlayer( player, "misc.buzwarn" )
	BroadCastMessageToPlayer(player, "#FF_WATERPOLO_GOALIE_BOUNDS")
end

function reset_ball_carrier()
	if ball_carrier ~= nil and IsPlayer( ball_carrier ) then
		local player = CastToPlayer(ball_carrier)
		UpdateObjectiveIcon( player, objective_entities[player:GetTeamId()] )
		if not BALL_ALWAYS_ENEMY_OBJECTIVE then
			local enemy_team = team_info[player:GetTeamId()].enemy_team
			objective_entities[enemy_team] = GetEntityByName( "ball" )
			UpdateTeamObjectiveIcon( GetTeam(enemy_team), objective_entities[enemy_team] )
		end
	end
	ball_carrier = nil
end

-- Give everyone a full resupply, but strip grenades
function player_spawn( player_entity )
	local player = CastToPlayer( player_entity )

	player:AddHealth( 100 )
	player:AddArmor( 300 )

	player:AddAmmo( Ammo.kNails, 400 )
	player:AddAmmo( Ammo.kShells, 400 )
	player:AddAmmo( Ammo.kRockets, 400 )
	player:AddAmmo( Ammo.kCells, 400 )

	-- god damn right
	player:RemoveAmmo( Ammo.kDetpack, 1 )
	player:RemoveAmmo( Ammo.kManCannon, 1 )
	player:RemoveAmmo( Ammo.kGren1, 4 )
	player:RemoveAmmo( Ammo.kGren2, 4 )

	-- goalies run fast
	if player:GetClass() ~= Player.kCivilian then
		player:RemoveEffect( EF.kSpeedlua1 )
	else
		player:AddEffect( EF.kSpeedlua1, -1, 0, GOALIE_SPEED )

		-- stop the goalie loop sound
		--player:StopSound( goalie_sound_loop )

		-- play the goalie loop sound
		--player:EmitSound( goalie_sound_loop )
	end

	-- objective
	UpdateObjectiveIcon( player, objective_entities[player:GetTeamId()] )
end

function player_onkill( player )
	-- stop the goalie loop sound
	--if player:GetClass() == Player.kCivilian then
		--player:StopSound( goalie_sound_loop )
	--end

	return true
end

function player_killed( player )
	-- stop the goalie loop sound
	--if player:GetClass() == Player.kCivilian then
		--player:StopSound( goalie_sound_loop )
	--end
end

function player_switchteam( player, currentteam, desiredteam )

	-- stop the goalie loop sound
	--if player:GetClass() == Player.kCivilian then
		--player:StopSound( goalie_sound_loop )
	--end

	return true

end

function player_disconnected( player )

	if ball_carrier ~= nil then
		if ball_carrier:GetId() == player:GetId() then
			reset_ball_carrier()
		end
	end

	-- stop the goalie loop sound
	--if player:GetClass() == Player.kCivilian then
		--player:StopSound( goalie_sound_loop )
	--end

end

function remove_hud_items(ball, player)

	RemoveHudItem( player, ball:GetName() )

	local team = player:GetTeamId()

	if (team == TEAM1) then
		RemoveHudItemFromAll( "ball-icon-blue" )
	elseif (team == TEAM2) then
		RemoveHudItemFromAll( "ball-icon-red" )
	end

end

function player_ondamage( player, damageinfo )
	-- goalies have "UNAGI POWER, UNAGI!"
	local attacker = damageinfo:GetAttacker()
	if IsPlayer( attacker ) then
		attacker = CastToPlayer( attacker )
		if attacker:GetClass() == Player.kCivilian and attacker:GetTeamId() ~= player:GetTeamId() then
			ConsoleToAll( "Goalie, " .. attacker:GetName() .. ", has UNAGI POWER, UNAGI!" )
			--attacker:EmitSound("misc.unagi_spatial")
			attacker:AddFortPoints( POINTS_PER_GOALIE_ATTACK, "#FF_FORTPOINTS_GOALIE_ATTACK" )
			damageinfo:ScaleDamage(69)
			--attacker:EmitSound( goalie_sound_kill )
		elseif attacker:GetClass() == Player.kSniper and player:GetClass() ~= Player.kCivilian then
			-- snipers do less damage to non-goalies
			damageinfo:ScaleDamage(0.1)
		end
	end

	if player:GetClass() == Player.kCivilian then

		if player:GetTeamId() == player:GetLocationTeam() then

			-- goalies are invincible in their team's locations
			damageinfo:ScaleDamage(0)
			--player:EmitSound( goalie_sound_idle )

		else

			-- goalies take more damage outside their team's locations
			damageinfo:ScaleDamage(3)
			--player:EmitSound( goalie_sound_pain )

		end

	end
end


-----------------------------------------------------------------------------
-- ball information
-- status: 0 = home, 1 = carried, 2 = dropped
-----------------------------------------------------------------------------
base_ball = info_ff_script:new({
	name = "base ball",
	team = Team.kUnassigned,
	model = "models/items/ball/ball.mdl",
	modelskin = 0,
	tosssound = "Flag.toss",
	dropnotouchtime = 0,
	capnotouchtime = 2,
	hudicon = "hud_ball",
	hudx = 5,
	hudy = 210,
	hudwidth = 48,
	hudheight = 48,
	hudalign = 1, 
	hudstatusiconbluex = 60,
	hudstatusiconbluey = 5,
	hudstatusiconredx = 60,
	hudstatusiconredy = 5,
	hudstatusiconblue = "hud_ball.vtf",
	hudstatusiconred = "hud_ball.vtf",
	hudstatusiconw = 15,
	hudstatusiconh = 15,
	hudstatusiconbluealign = 2,
	hudstatusiconredalign = 3,
	touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed},
	botgoaltype = Bot.kFlag,
	status = 0
})

function base_ball:hasanimation() return false end
function base_ball:usephysics() return true end

function base_ball:touch( touch_entity )
	if IsPlayer( touch_entity ) then

		local player = CastToPlayer( touch_entity )
		if self.notouch[player:GetId()] then return end

		local ball = CastToInfoScript( entity )

		if player:GetClass() ~= Player.kCivilian then
			-- if the player is a spy, then force him to lose his disguise
			player:SetDisguisable( false )
			player:SetCloakable( false )

			ConsoleToAll( player:GetName() .. " has the ball!" )
			--SmartSound( player, "misc.bloop", "misc.bloop", "misc.bloop" )
			SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen")
			SmartSpeak(player, "CTF_YOUHAVEBALL", "CTF_TEAMHASBALL", "CTF_ENEMYHASBALL")
			SmartMessage( player, "#FF_WATERPOLO_YOU_PICKUP", "#FF_WATERPOLO_TEAM_PICKUP", "#FF_WATERPOLO_ENEMY_PICKUP", Color.kGreen, Color.kGreen, Color.kRed )
			ball:Pickup( player )

			AddHudIcon( player, self.hudicon, ball:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign )
			local team = player:GetTeamId()
			if (team == TEAM1) then
				AddHudIconToAll( self.hudstatusiconblue, "ball-icon-blue", self.hudstatusiconbluex, self.hudstatusiconbluey, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconbluealign )
			elseif (team == TEAM2) then
				AddHudIconToAll( self.hudstatusiconred, "ball-icon-red", self.hudstatusiconredx, self.hudstatusiconredy, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconredalign )
			end

			-- 100 points for initial touch on ball
			if self.status == 0 then player:AddFortPoints(POINTS_PER_INITIALTOUCH, "#FF_FORTPOINTS_INITIALTOUCH") end
			self.status = 1

			UpdateObjectiveIcon( player, goal_entities[player:GetTeamId()] )
			ball_carrier = player

			if not BALL_ALWAYS_ENEMY_OBJECTIVE then
				local enemy_team = team_info[player:GetTeamId()].enemy_team
				objective_entities[enemy_team] = nil
				UpdateTeamObjectiveIcon( GetTeam(enemy_team), objective_entities[enemy_team] )
			end

		-- goalies return the ball
		else
			if ball:IsDropped() then
				-- if pressing +use
				if player:IsInUse() then
					ConsoleToAll( "Goalie, " .. player:GetName() .. ", returned the ball!" )
					SmartSound( player, "misc.deeoo", "misc.deeoo", "misc.deeoo" )
					SmartMessage( player, "#FF_WATERPOLO_YOU_RETURN", "#FF_WATERPOLO_TEAM_GOALIE_RETURN", "#FF_WATERPOLO_ENEMY_GOALIE_RETURN" )
					player:AddFortPoints( POINTS_PER_GOALIE_RETURN, "#FF_FORTPOINTS_GOALIE_RETURN" )
					ball:Return()
					self.status = 0
				else
					BroadCastMessageToPlayer(player, "#FF_WATERPOLO_USE_RETURN")
				end
			end
		end
	end
end

function base_ball:onownerdie( owner_entity )
	if IsPlayer( owner_entity ) then
		local player = CastToPlayer( owner_entity )
		-- drop the ball
		ConsoleToAll( player:GetName() .. " died and dropped the ball!" )
		local ball = CastToInfoScript( entity )
		ball:Drop(BALL_RETURN_TIME, 0.0)
		remove_hud_items(ball, player)
		self.status = 2

		reset_ball_carrier()
	end
end

function base_ball:ownercloak( owner_entity )
	if IsPlayer( owner_entity ) then
		local player = CastToPlayer( owner_entity )
		-- drop the ball
		ConsoleToAll( player:GetName() .. " cloaked and dropped the ball!" )
		local ball = CastToInfoScript( entity )
		ball:Drop(BALL_RETURN_TIME, 0.0)
		remove_hud_items(ball, player)
		self.status = 2

		reset_ball_carrier()
	end
end

function base_ball:ownerfeign( owner_entity )
	if IsPlayer( owner_entity ) then
		local player = CastToPlayer( owner_entity )
		-- drop the ball
		ConsoleToAll( player:GetName() .. " feigned and dropped the ball!" )
		local ball = CastToInfoScript( entity )
		ball:Drop(BALL_RETURN_TIME, 0.0)
		remove_hud_items(ball, player)
		self.status = 2

		reset_ball_carrier()
	end
end

function base_ball:dropitemcmd( drop_entity )
	if IsPlayer( drop_entity ) then
		-- throw the ball
		local ball = CastToInfoScript( entity )

		local player = CastToPlayer( drop_entity )
		if not player:IsInUse() then
			ball:Drop(BALL_RETURN_TIME, BALL_THROW_SPEED)
		else
			ball:Drop(BALL_RETURN_TIME, BALL_THROW_SPEED * 0.333)
		end

		ConsoleToAll( player:GetName() .. " passed the ball!" )
		remove_hud_items(ball, player)
		self.status = 2

		reset_ball_carrier()
	
		SmartSound( player, "misc.woop", "misc.woop", "misc.woop" )
	
		-- Make it so the player can't touch the ball for 1 second
		-- (so it can't be thrown and not stick to the player)
		self:addnotouch(player:GetId(), 1)
	end
end

function base_ball:ondrop( owner_entity )
	if IsPlayer( owner_entity ) then
		local player = CastToPlayer( owner_entity )
		-- let the teams know that the flag was dropped
		SmartSound(player, "yourteam.drop", "yourteam.drop", "otherteam.drop")
		SmartMessage(player, "#FF_YOUBALLDROP", "#FF_TEAMBALLDROP", "#FF_ENEMYBALLDROP", Color.kYellow, Color.kYellow, Color.kYellow)
	end
	
	local ball = CastToInfoScript(entity)
	ball:EmitSound(self.tosssound)
end

function base_ball:onloseitem( owner_entity )
	if IsPlayer( owner_entity ) then
		-- let the player that lost the ball put on a disguise
		local player = CastToPlayer( owner_entity )
		player:SetDisguisable(true)
		player:SetCloakable( true )
	
		self:addnotouch(player:GetId(), self.capnotouchtime)
	end
end

function base_ball:spawn()
	self.notouch = { }
	info_ff_script.spawn(self)
	self.status = 0
end

function base_ball:addnotouch( player_id, duration )
	self.notouch[player_id] = duration
	AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id)
end

function base_ball.removenotouch(self, player_id)
	self.notouch[player_id] = nil
end

-- For when this object is carried, these offsets are used to place
-- the info_ff_script relative to the players feet
function base_ball:attachoffset()
	-- x = forward/backward
	-- y = left/right
	-- z = up/down
	local offset = Vector( 32, 0, 0 )
	return offset
end

function base_ball:precache()
	PrecacheSound(self.tosssound)
	info_ff_script.precache(self)
end

function base_ball:onreturn()
	ConsoleToAll( "The ball has returned!" )
	SpeakAll ( "CTF_BALLRETURN" )
	BroadCastMessage( "#FF_WATERPOLO_BALL_RETURN", Color.kYellow )
	self.status = 0

	reset_ball_carrier()
end

ball = base_ball:new({
	touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed},
	botgoaltype = Bot.kFlag
})




-- generic goal
base_goal = trigger_ff_script:new({
	health = 100,
	armor = 300,
	grenades = 200,
	nails = 200,
	shells = 200,
	rockets = 200,
	cells = 200,
	detpacks = 0,
	mancannons = 0,
	gren1 = 0,
	gren2 = 0,
	item = "",
	team = 0,
	botgoaltype = Bot.kFlagCap
})

function base_goal:spawn()
	if self.team ~= Team.kUnassigned then
		goal_entities[self.team] = entity
	end
end

function base_goal:allowed ( allowed_entity )
	if IsPlayer( allowed_entity ) then		
		-- player has to be carrying the item
		local player = CastToPlayer( allowed_entity )
		return player:HasItem( self.item )
	end

	return EVENT_DISALLOWED
end

function base_goal:ontrigger ( trigger_entity )
	if IsPlayer( trigger_entity ) then

		-- player should capture now
		local player = CastToPlayer( trigger_entity )
		if player:HasItem( self.item ) then
			local team = GetTeam( self.team )
			team:AddScore( POINTS_PER_CAPTURE )
			ConsoleToAll( team:GetName() .. " team scores!" )

			local ball = GetInfoScriptByName( self.item )
			ball:Return()

			remove_hud_items(ball, player)

			if player:GetTeamId() == self.team then
				ConsoleToAll( player:GetName() .. " scored a goal!" )
				-- show on the deathnotice board
				ObjectiveNotice( player, "scored a goal" )
				SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap")
				SmartSpeak(player, "CTF_YOUSCORE", "CTF_TEAMSCORE", "CTF_THEYSCORE")
				SmartMessage( player, "#FF_WATERPOLO_YOU_GOAL", "#FF_WATERPOLO_TEAM_GOAL", "#FF_WATERPOLO_ENEMY_GOAL", Color.kGreen, Color.kGreen, Color.kRed)
				player:AddFortPoints( POINTS_PER_CAPTURE * 100, "#FF_FORTPOINTS_GOAL" )
			else
				ConsoleToAll( player:GetName() .. " scored an own goal!\nWait, what?!  Kill him like that Columbian a few years ago!  OWN GOAL!  OWN GOAL!" )
				-- show on the deathnotice board
				ObjectiveNotice( player, "scored an own goal" )
				SmartSound(player, "otherteam.flagcap", "otherteam.flagcap", "yourteam.flagcap")
				SmartSpeak(player, "CTF_THEYSCORE", "CTF_THEYSCORE", "CTF_TEAMSCORE")
				SmartMessage( player, "#FF_WATERPOLO_YOU_OWN_GOAL", "#FF_WATERPOLO_TEAM_OWN_GOAL", "#FF_WATERPOLO_ENEMY_OWN_GOAL", Color.kRed, Color.kRed, Color.kGreen)
				player:AddFortPoints( -POINTS_PER_CAPTURE * 100, "#FF_FORTPOINTS_OWN_GOAL" )
			end

			ApplyToAll({ AT.kRespawnPlayers, AT.kReloadClips })

			the_wall_reset()
		end
	end
end

-- on blue's side of map, but points go to red
blue_goal = base_goal:new({ item = "ball", team = TEAM2 })

-- on red's side of map, but points go to blue
red_goal = base_goal:new({ item = "ball", team = TEAM1 })




-- respawns a goalie
base_goalie_respawner = trigger_ff_script:new({ team = Team.kUnassigned })

function base_goalie_respawner:ontouch( trigger_entity )

	if IsPlayer( trigger_entity ) then
		local player = CastToPlayer( trigger_entity )
		if player:GetClass() == Player.kCivilian and player:GetTeamId() == self.team then
			-- respawn the goalie
			ApplyToPlayer(player, { AT.kRespawnPlayers })
			AddSchedule("goalie_bounds_notification_" .. player:GetId(), 0.1, goalie_bounds_notification, player )
		end
	end

end

-- goalie respawner
blue_goalie_respawner = base_goalie_respawner:new({ team = TEAM1 })
red_goalie_respawner = base_goalie_respawner:new({ team = TEAM2 })




-- returns the item
base_item_returner = trigger_ff_script:new({ item = "", message = "" })

function base_item_returner:allowed ( allowed_entity )

	if IsPlayer( allowed_entity ) then
		-- player has to be carrying the item or be a goalie
		local player = CastToPlayer( allowed_entity )
		if player:HasItem( self.item ) or player:GetClass() == Player.kCivilian then
			return EVENT_ALLOWED
		end
	end

	return EVENT_DISALLOWED

end

function base_item_returner:ontrigger ( trigger_entity )

	if IsPlayer( trigger_entity ) then
		local player = CastToPlayer( trigger_entity )

		if player:GetClass() ~= Player.kCivilian then
			-- return the item
			local item = GetInfoScriptByName( self.item )
			item:Return()
			remove_hud_items(item, player)
			ConsoleToAll( player:GetName() .. self.message )
			SpeakAll ( "CTF_BALLRETURN" )
			SmartMessage( player, "#FF_WATERPOLO_YOU_BOUNDS", "#FF_WATERPOLO_TEAM_BOUNDS", "#FF_WATERPOLO_ENEMY_BOUNDS", Color.kYellow, Color.kYellow, Color.kYellow )
		else
			-- respawn the goalie
			ApplyToPlayer(player, { AT.kRespawnPlayers })
			AddSchedule("goalie_bounds_notification_" .. player:GetId(), 0.1, goalie_bounds_notification, player )
		end
	end

end

-- ball stripper
ball_stripper = base_item_returner:new({ item = "ball", message = " took the ball out of bounds!" })

-- spawn ammo packs
waterpolo_pack_spawn_blue = blue_ammobackpack
waterpolo_pack_spawn_red = red_ammobackpack

fortball_pack_spawn_blue = blue_ammobackpack
fortball_pack_spawn_red = red_ammobackpack

-- unique fortball spawns (goalies spawn on top of the goal)
bluespawn = { validspawn = function(self,player) return player:GetTeamId() == TEAM1 and player:GetClass() ~= Player.kCivilian and player:GetClass() ~= Player.kSniper end }
redspawn = { validspawn = function(self,player) return player:GetTeamId() == TEAM2 and player:GetClass() ~= Player.kCivilian and player:GetClass() ~= Player.kSniper end }
bluespawn_goalie = { validspawn = function(self,player) return player:GetTeamId() == TEAM1 and player:GetClass() == Player.kCivilian end }
redspawn_goalie = { validspawn = function(self,player) return player:GetTeamId() == TEAM2 and player:GetClass() == Player.kCivilian end }
bluespawn_sniper = { validspawn = function(self,player) return player:GetTeamId() == TEAM1 and player:GetClass() == Player.kSniper end }
redspawn_sniper = { validspawn = function(self,player) return player:GetTeamId() == TEAM2 and player:GetClass() == Player.kSniper end }


-----------------------------------------------------------------------------
-- unique fortball locations
-----------------------------------------------------------------------------
location_ballsonia = location_info:new({ text = "Ballsonia", team = Team.kUnassigned })
location_midfield = location_info:new({ text = "Midfield", team = Team.kUnassigned })
location_blue_side = location_info:new({ text = "Blue Side", team = TEAM1 })
location_red_side = location_info:new({ text = "Red Side", team = TEAM2 })
location_blue_goal = location_info:new({ text = "Blue Goal", team = TEAM1 })
location_red_goal = location_info:new({ text = "Red Goal", team = TEAM2 })
location_upper_deck = location_info:new({ text = "Upper Deck", team = Team.kUnassigned })
location_blue_upper_deck = location_info:new({ text = "Blue Upper Deck", team = TEAM1 })
location_red_upper_deck = location_info:new({ text = "Red Upper Deck", team = TEAM2 })
location_nose_bleeds = location_info:new({ text = "Nose Bleeds", team = Team.kUnassigned })
location_blue_nose_bleeds = location_info:new({ text = "Blue Nose Bleeds", team = TEAM1 })
location_red_nose_bleeds = location_info:new({ text = "Red Nose Bleeds", team = TEAM2 })
location_rainy_sky = location_info:new({ text = "Rainy Sky", team = Team.kUnassigned })
location_death_hills = location_info:new({ text = "Death Hills", team = Team.kUnassigned })
location_sideroom1 = location_info:new({ text = "Side Room 1", team = Team.kUnassigned })
location_sideroom2 = location_info:new({ text = "Side Room 2", team = Team.kUnassigned })