[code]--
-- Copyright (c) 2006 GameToast Modder [RDH]Zerted,
--
-- Feel free to edit and distrubute this, but give me credit for what I have done.
-- No making/gaining money off of any part of this for any reason, without consent of [RDH]Zerted.
--
--Version: Sept. 22th, 2006
--
--[[
----------------------
-- Tips for modders --
----------------------
> In your map's main Lua, include: ScriptCB_DoFile("ObjectiveKOH")
> Don't forget to update .req files.
> Here is an example ScriptPostLoad() function:
<<<<<<<<<<<<<<
function ScriptPostLoad()
--create a new KOH game mode objective
koh = ObjectiveKOH:New{
--hills that can be captured
hills = { "cp1", "cp2", "cp3", "cp4", },
--paths where the teamATT players will spawn
pathsATT = {
{ name = "cp1_spawn", nodes = 4 },
{ name = "cp4_spawn", nodes = 4 },
},
--paths where the teamDEF players will spawn
pathsDEF = {
{ name = "cp2_spawn", nodes = 4 },
{ name = "cp3_spawn", nodes = 4 },
},
--true for MP rules
multiplayerRules = true,
}
--start the objective which koh represents
koh:Start()
end
<<<<<<<<<<<<<<
--]]
ScriptCB_DoFile("Objective")
ObjectiveKOH = Objective:New{
------------------------------
-- Required External values --
------------------------------
--This is a table of all the hill names which represent CP objects.
--All but one of these Hills/CPs will be disabled at any given time.
hills = {}, --={
-- "cp1",
-- "cp2",
-- "cp3",
-- "cp4",
--}
--This is a table consisting of the paths and their max nodes on which players
-- will be randomly forced spawned.
--Note: pathsATT is for the spawning ATT team members
--Note: pathsDEF is for the spawning DEF team members
pathsATT = nil,
pathsDEF = nil, --= {
--{ name = "cp1_spawn", nodes = 4},
--{ name = "cp3_spawn", nodes = 4},
--}
--not required, but highly recommended to be set to true
multiplayerRules = true,
------------------------------
-- Optional values --
------------------------------
--The marker that will be displayed on the ingame map over
-- the CP which needs to be captured.
--A marker will not be displayed if this is nil.
hillMarker = "hud_objective_icon",
--The amount of scaling done to the size of the hillMarker.
hillMarkerScale = 4,
--The color the hill marker will be on the ingame map.
--Know color values: "YELLOW"
hillMarkerColor = "YELLOW",
--The amount of points a team gets for each hill capture.
capturePoints = 1,
--The amount of team points a team needs to complete the objective.
captureLimit = 5,
--The AI goal scale for this objective.
AIGoalWeight = 1,
--This is the amount of seconds between each forced spawn
spawnTime = 15,
------------------------------
-- Non-User Editable values --
------------------------------
--holds the AI goals used by this objective
goals = {},
--Used to keep track of the currently enabled hill.
hill = nil,
}
--Modders: uncomment the following line to get extensive debug output if you are having problems with you map
--debug = true
--
-- Starts the given KOH objective.
--
function ObjectiveKOH:Start()
show("Start()")
--=============================
-- local functions
--=============================
--
-- Returns a random path and a random node on that path
--
local getPathAndNode = function( team )
--show("getPathAndNode()")
--Note: will just test for one team, then just use else for the rest
--assert( team, "Error: No team given.")
--determine which spawn path to use
local paths = nil
if team == self.teamATT then
paths = self.pathsATT
else
paths = self.pathsDEF
end
--get the amount of possible paths
local maxPaths = table.getn(paths)
--get a random path
local pathNumber = math.random(maxPaths)
--get the picked path's name
local path = paths[pathNumber].name
--get the path's amount of nodes
local maxNodes = paths[pathNumber].nodes
--get a random node
local node = math.random(maxNodes)
--return values
show( "Path = " .. path .. " Node = " .. node )
return path, node
end --end of getPathAndNode()
--
-- Spawns all dead units from the given team onto random paths
--
local spawnUnits = function( team )
show("spawnUnits()")
--check input
if not team then show("Warning: No team given.") return end
--get the amount of players on the given team
local size = GetTeamSize(team)
--for each team member,
local a
for a = 0, size do
--get the unit of the next team member
local character = GetTeamMember(team, a)
local unit = GetCharacterUnit( character )
--if there is not a unit the character is dead, so spawn a new unit for the character
if not unit then
--get a random path and path node
local path, node = getPathAndNode( team )
--spawn the given player at the generated path point
SpawnCharacter(character, GetPathPoint(path, node))
end--if unit
end--for each team member
end--end of spawnUnits()
--
-- Returns a random Hill from the table of Hill names.
--
local pickRandomHill = function()
show("pickRandomHill()")
--get the amount of possible hills
local maxHills = table.getn(self.hills)
--get the index for a random Hill
local hillIndex = math.random(maxHills)
--get the name of the CP at the generated index
local newHill = self.hills[hillIndex]
--return values
show("Returning Hill = " .. newHill .. " Hill Index: " .. hillIndex .. " of " .. maxHills )
return newHill
end --end of pickRandomHill()
--
-- Toggles on/off a marker for the given Hill
--
-- 'givenHill' is the name of a hill/CP.
-- 'enableMarker' is true to enable a ingame map marker for the hill/CP, anything else disables the marker.
-- 'marker' is the object which will be displayed over the hill/CP in the ingame map.
--
local toggleMarker = function( givenHill, enableMarker )
show("toggleMarker()")
--if objective is complete, then return
if self.isComplete then return end
--can't do anything if given no CP, so return
if not givenHill then show("Warning: No hill given.") return end
--if enabling a marker,
if enableMarker then
--can't display a marker if there isn't one, so return
if not self.hillMarker then show("Warning: No given marker.") return end
--enable a marker for both teams
MapAddEntityMarker( givenHill, self.hillMarker, self.hillMarkerScale, self.teamATT, self.hillMarkerColor, true, false, true, true)
MapAddEntityMarker( givenHill, self.hillMarker, self.hillMarkerScale, self.teamDEF, self.hillMarkerColor, true, false, true, true)
else
--disable the existing marker
MapRemoveEntityMarker( givenHill )
end
end--end of toggleMarker()
--
-- Does things to the given 'hill' depending on the given 'id'.
--
-- id "off": Removes the ingame map marker from the CP and kills the CP.
-- id "set as hill": Sets the CP to nutural, Enables the CP, Puts marker on the CP in the ingame map.
--
local toggleHill = function( givenHill, id )
show("toggleHill()")
--if objective is complete, then return
if self.isComplete then return end
--can't toggle what isn't given, so return
if not givenHill then show("Warning: No given hill. Id: " .. id) return end
if id == "off" then
--remove any hill/CP marker
toggleMarker( givenHill, false )
--kill the hill/CP, so it can't be captured and so it dosn't show up anywhere
KillObject( givenHill )
elseif id == "set as hill" then
--make sure the hill/CP starts as netural
SetProperty( givenHill, "Team", 0 )
SetProperty( givenHill, "PerceivedTeam", 0 )
--make sure the hill/CP is enabled by recreating it
RespawnObject( givenHill )
--put a marker on the ingame map for the new hill/CP
toggleMarker( givenHill, true )
else
show("Warning: Unknown toggleHill command: " .. id )
end
end --end of toggleHill()
--
-- Disables all CPs, Enables a random CP/Hill for capture, Updates AI goals
--
local setupHill = function()
show("setupHill()")
--if objective is complete, then return
if self.isComplete then return end
--for each old AI goal, remove it
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
self.goals = {}
--turn all the Hills/CPs off
local b
for b = 1, table.getn(self.hills) do
toggleHill( self.hills, "off" )
end
--pick a random CP for the new hill
self.hill = pickRandomHill()
--enable the new hill
toggleHill( self.hill, "set as hill" )
--tell the AI to attempt to capture the new hill
table.insert( self.goals, AddAIGoal(self.teamATT, "Conquest", self.AIGoalWeight*70) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Conquest", self.AIGoalWeight*70) )
--tell a few AI bots to stand around and fight
table.insert( self.goals, AddAIGoal(self.teamATT, "Deathmatch", self.AIGoalWeight*10) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Deathmatch", self.AIGoalWeight*10) )
--[[Note: got the following errer, so will remove the AI 'hill camping'
Message Severity: 3
.\Source\AIGoalManager.cpp(285)
Error too many AI Goals at one time! (20)
--]]
--tell a very few AI bots to goto the other CP locations and wait for them to become active hills
--for a = 1, table.getn(self.hills) do
-- table.insert( self.goals, AddAIGoal(self.teamATT, "Defend", self.AIGoalWeight*5, self.hills[a]) )
-- table.insert( self.goals, AddAIGoal(self.teamDEF, "Defend", self.AIGoalWeight*5, self.hills[a]) )
--end
end --end of setupHill()
--===============================
-- Var checks
--===============================
show("Starting var checks.")
--check starting values for errors, and fix any if discovered
assert(self.hills, "Error: A table of hills is required for KOH. (If you think you gave a table of hills, check the spelling of your variable names.)" )
assert(table.getn(self.hills) > 0, "Error: KOH requires at least one hill.")
--check the path table for findable errors
assert(self.pathsATT, "Error: A table of ATT paths is required for KOH. (If you think you gave a table of ATT paths, check the spelling of your variable names.)" )
assert( table.getn(self.pathsATT) > 0, "Error: KOH requires at least one ATT path with at least one node." )
local i
for i = 1, table.getn(self.pathsATT) do
assert(self.pathsATT.name, "Error: KOH requires each path to have a name. ATT Path: " .. i .. " has no know name.")
assert(self.pathsATT.nodes > 0, "Error: KOH requires that its paths have at least 1 node. ATT Path: " .. self.pathsATT.name .. " has " .. self.pathsATT.nodes .. ".")
end
assert(self.pathsDEF, "Error: A table of DEF paths is required for KOH. (If you think you gave a table of paths, check the spelling of your variable names.)" )
assert( table.getn(self.pathsDEF) > 0, "Error: KOH requires at least one DEF path with at least one node." )
local i
for i = 1, table.getn(self.pathsDEF) do
assert(self.pathsDEF.name, "Error: KOH requires each path to have a name. DEF Path: " .. i .. " has no know name.")
assert(self.pathsDEF.nodes > 0, "Error: KOH requires that its paths have at least 1 node. DEF Path: " .. self.pathsDEF.name .. " has " .. self.pathsDEF.nodes .. ".")
end
self.hillMarker = self.hillMarker or "hud_objective_icon"
self.hillMarkerScale = self.hillMarkerScale or 3
self.hillMarkerColor = self.hillMarkerColor or "YELLOW"
self.capturePoints = self.capturePoints or 1
self.captureLimit = self.captureLimit or 5
self.AIGoalWeight = self.AIGoalWeight or 1
self.teamATT = self.teamATT or 1
self.teamDEF = self.teamDEF or 2
self.spawnTime = self.spawnTime or 20
--make sure players have a chance to pick a new unit before respawning, as there are no CPs to sawp units at.
if self.spawnTime < 5 then
self.spawnTime = 20
end
self.goals = {}
print("Passed var checks.")
--===============================
--
--===============================
--set the number of bots in the level to the number in the game options for CTF
ScriptCB_SetNumBots( ScriptCB_GetCTFNumBots() )
--use CTF time limit
self.timeLimit = ScriptCB_GetCTFMaxTimeLimit()
--===============================
-- Initialization logic
--===============================
show("Starting Objective setup.")
--initialize the base objective data first--
Objective.Start(self)
--if multiplayer rules, then
if self.multiplayerRules then
--use GUI capture limit
self.captureLimit = ScriptCB_GetCTFCaptureLimit()
--set to unlimited reinforcments
SetReinforcementCount(self.teamATT, -1)
SetReinforcementCount(self.teamDEF, -1)
end
--make sure the teams start out a 0 points
SetTeamPoints( self.teamATT, 0 )
SetTeamPoints( self.teamDEF, 0 )
--display the team points at the top of the screen
ShowTeamPoints(self.teamATT, true)
ShowTeamPoints(self.teamDEF, true)
----give the AI a starting low level goal
--table.insert( self.goals, AddAIGoal(self.teamATT, "Deathmatch", self.AIGoalWeight*20) )
--table.insert( self.goals, AddAIGoal(self.teamDEF, "Deathmatch", self.AIGoalWeight*20) )
show("Passed Objective setup.")
--===============================
-- Timers
--===============================
show("Setting up timers.")
CreateTimer("spawnTimer")
SetTimerValue("spawnTimer", self.spawnTime)
ShowTimer("spawnTimer")
StartTimer("spawnTimer")
--when the spawn timer ends, spawn all units, and restart the timer.
local KOH_timerSpawn = OnTimerElapse(
function( timer )
show("KOH_timerSpawn OnTimerElapse()")
--spawn new units
spawnUnits( self.teamATT )
spawnUnits( self.teamDEF )
--reset and restart the timer
SetTimerValue( "spawnTimer", self.spawnTime )
ShowTimer( "spawnTimer" )
StartTimer( "spawnTimer" )
end, "spawnTimer"
)
show("Finished setting up timers.")
--===============================
-- Events
--===============================
show("Starting setting up event responses.")
--when a CP (thus hill) is captured, give the capturing team a point, then setup a new hill.
local KOH_eventCapture = OnFinishCapture(
function( post, characters )
show("KOH_eventCapture OnFinishCapture()")
--make sure its the Hill CP that has been captured
--Note: don't think this can be changed to an event filter because self.hill is a changing variable, but I haven't tested it.
if post ~= self.hill then show("Info: Captured a CP not in the hills table.") return end
--get the capture team by checking the post's team
local team = GetCommandPostTeam(post)
--add team point to the team for the capture
AddTeamPoints( team, self.capturePoints )
show("Info: Team: " .. team .. " made a hill capture." )
--setup a new hill to capture
setupHill()
end
)
--when a team's points change
local KOH_eventPoints = OnTeamPointsChange(
function (team, points)
show("KOH_eventPoints OnTeamPointsChange()")
--if objective is complete, then return
if self.isComplete then return end
--if capture limit has been reached, then the objective has finished
if points >= self.captureLimit then
show("KOH_eventPoints: Starting KOH cleanup.")
--release any KOH event responses
ReleaseFinishCapture(KOH_eventCapture)
ReleaseTimerElapse(KOH_timerSpawn)
ReleaseTeamPointsChange(KOH_eventPoints)
--clean up any KOH timers
StopTimer("spawnTimer")
ShowTimer(nil)
DestroyTimer("spawnTimer")
show("KOH_eventPoints: Finished KOH cleanup.")
--set objective as finished
self:Complete(team)
end
end
)
show("Finished setting up event responses.")
--Note: this basically starts the objective
--setup the first hill
setupHill()
show("KOH has started")
end--end of Start()
--
-- Displays debug output
--
function show( string )
--only display if debug messages are enabled
if not debug then return end
--cannot print nil messages (may also filter out messages of only 'false' )
if not string then return end
--output the message
print( string )
end --end of show()
--
-- Get game time limit as set in game options menu
--
function ObjectiveKOH:GetGameTimeLimit()
return ScriptCB_GetCTFMaxTimeLimit()
end --end of GetGameTimeLimit()
--
-- Determines who wins when the map's time limit is up.
--
function ObjectiveKOH:GameOptionsTimeLimitUp()
show("GameOptionsTimeLimitUp()")
local team1pts = GetTeamPoints(1)
local team2pts = GetTeamPoints(2)
if ( team1pts > team2pts ) then
MissionVictory(1)
elseif ( team1pts < team2pts ) then
MissionVictory(2)
else
--map tied, so victory for both teams
MissionVictory({1,2})
end
end--end of GameOptionsTimeLimitUp()[/code]