Hidden/Spoiler:
Changing character properties via Lua
In this forum you will find and post information regarding the modding of Star Wars Battlefront 2. DO NOT POST MOD IDEAS/REQUESTS.
Moderator: Moderators
-
LRKfm946
- Master Sergeant

- Posts: 163
- Joined: Sun Feb 02, 2014 6:13 pm
- Projects :: Battlefront II Hunger Games
- Games I'm Playing :: SWBF2 BF3
- Contact:
Changing character properties via Lua
I'm trying to change some player properties via Lua, particularly speed, energy restore, and health regen. What I've tried so far hasn't worked:
PS: Will any of this affect online compatibility?
- Anakin
- Master of the Force

- Posts: 4817
- Joined: Sat Sep 19, 2009 11:37 am
- Projects :: RC Side Mod - Remastered - SWBF3 Legacy
- Location: Mos Espa (germany)
Re: Changing character properties via Lua
what is the charPtr = GetCharacterUnit(character) function about?? can you show us the code of it??
- Nedarb7
- Lieutenant General

- Posts: 676
- Joined: Sat Sep 22, 2012 3:41 pm
Re: Changing character properties via Lua
Could explain how and what is supposed to happen? Is there an event that causes it?
As for affecting online compatibility it depends. If this is something you want to occur right at the start (or when the map is loading) then it will work. If it is supposed to happen on some kind of event then all I can say is yes and maybe no. I've worked with SetClassProperty (change all classes) and it worked however it crashed after a third wave of changes (maybe there is a minimum value to the stats in multiplayer?). You'll have to try it and see what happens.
As for affecting online compatibility it depends. If this is something you want to occur right at the start (or when the map is loading) then it will work. If it is supposed to happen on some kind of event then all I can say is yes and maybe no. I've worked with SetClassProperty (change all classes) and it worked however it crashed after a third wave of changes (maybe there is a minimum value to the stats in multiplayer?). You'll have to try it and see what happens.
- [RDH]Zerted
- Gametoast Staff

- Posts: 2982
- Joined: Sun Feb 26, 2006 7:36 am
- Projects :: Bos Wars AI - a RTS game
- Games I'm Playing :: SWBF2 and Bos Wars
- xbox live or psn: No gamertag set
- Location: USA
- Contact:
Re: Changing character properties via Lua
Post by [RDH]Zerted »
GetCharacterUnit() is an available function that's part of the game.
You can't change class properties on individual units, you have to change them at the class level. Only a couple properties, like AddHealth, work at the unit level. All of the properties have min and max values that you shouldn't go below or above. I'd also recommend sticking to whole numbers unless an existing ODF value already had decimals.
v1.3 added some helpful functions if you want to change multiple properties. Example:
You can't change class properties on individual units, you have to change them at the class level. Only a couple properties, like AddHealth, work at the unit level. All of the properties have min and max values that you shouldn't go below or above. I'd also recommend sticking to whole numbers unless an existing ODF value already had decimals.
v1.3 added some helpful functions if you want to change multiple properties. Example:
Code: Select all
local classes = {
"all_inf_engineer",
"imp_inf_engineer",
}
local properties = {
{name = "JumpHeight", value = "15"},
{name = "EnergyRestore", value = "10"},
}
uf_changeClassProperties( classes, properties ) --changes JumpHeight and EngeryRestore for all the classes in classes
-
LRKfm946
- Master Sergeant

- Posts: 163
- Joined: Sun Feb 02, 2014 6:13 pm
- Projects :: Battlefront II Hunger Games
- Games I'm Playing :: SWBF2 BF3
- Contact:
Re: Changing character properties via Lua
These changes are to be triggered when a player picks up a "flag" (its classlabel is a flag but functionally, it's a powerup that makes you go faster for a certain amount of time).
One idea I had was to have a duplicate of each unit that had those properties already changed, and when the player picked up the powerup, it would respawn them as the duplicate class (in the same position) and when their time was up, it would switch them back. Would something like that work?
One idea I had was to have a duplicate of each unit that had those properties already changed, and when the player picked up the powerup, it would respawn them as the duplicate class (in the same position) and when their time was up, it would switch them back. Would something like that work?
- [RDH]Zerted
- Gametoast Staff

- Posts: 2982
- Joined: Sun Feb 26, 2006 7:36 am
- Projects :: Bos Wars AI - a RTS game
- Games I'm Playing :: SWBF2 and Bos Wars
- xbox live or psn: No gamertag set
- Location: USA
- Contact:
Re: Changing character properties via Lua
Post by [RDH]Zerted »
The duplicate classes would work (you can't duplicate the unit), but then you'll have those classes in the unit selection menu. I don't remember if you can get around that but adding those other classes to a 3rd or 4th team and respawning the player as a unit on those other teams. I'm including a version of the Holocron game mode if you want to see how I did it:
Hidden/Spoiler:
[code]--
-- Partly based on ObjectiveOneFlagCTF.lua released with the SWBF2 Mode Tools.
-- Copyright (c) 2006 GameToast Modder [RDH]Zerted, Auguest 27th, 2006
--
-- Feel free to edit and distrubute this, but give [RDH]Zerted credit for what he has done.
-- No making/gaining money off of any part of this for any reason.
--
--Version: Sept. 22th, 2006
--[[
----------------------
-- Tips for modders --
----------------------
> In your map's main Lua, include: ScriptCB_DoFile("ObjectiveHolocron")
> Here is an example ScriptPostLoad() function:
<<<<<<<<<<<<<<
function ScriptPostLoad()
SoundEvent_SetupTeams( ALL, 'all', IMP, 'imp' )
--create a Holocron objective
hm = ObjectiveHolocron:New{
--team numbers
teamATT = 1,
teamDEF = 2,
--game mode text
textATT = "game.modes.1flag",
textDEF = "game.modes.1flag2",
--these are the paths the holocron may spawn on
--the holocron will randomly spawn on one of these
paths = {
{name = "1flag_cp1_spawn", nodes = 4,},
{name = "1flag_cp2_spawn", nodes = 4,},
{name = "1flag_cp3_spawn", nodes = 4,},
{name = "1flag_cp4_spawn", nodes = 4,},
{name = "holocron_path", nodes = 20,},
},
--
multiplayerRules = true,
--hides the CPs from the ingame map
hideCPs = true,
--total captures a team needs to win the map
captureLimit = 3,
--the amount of seconds required to hold the flag until a capture is scored
captureTime = 20,
--the object that will be spawned as the capturable item
--Note: this object should be of type "flag"
holocronObject = "com_item_holocron",
}
--start the holocron objective
hm:Start()
end
<<<<<<<<<<<<<<
> Don't forget to add a memory pool for the shield effects: SetMemoryPoolSize("ShieldEffect", 10)
> If your map is having problems, uncomment all the 'print()' statement. Next
>> time you attempt to run your map, look at the error log, and follow the output
>> through your code it see what was going on at the time of the problem/crash.
>The Holocrons game mode and heros do not mix. Do not include heros in your map.
--]]
ScriptCB_DoFile("Objective")
ScriptCB_DoFile("SoundEvent_ctf")
--=============================
-- ObjectiveHolocron
-- Handles the logic for a capture the flag game
--=============================
ObjectiveHolocron = Objective:New
{
------------------------------
-- Required External values --
------------------------------
--a table of paths of which the holocron will randomly spawn on
--format:
--paths = {
-- { name = "[path name]", nodes = [max amount of nides on the path] },
--},
paths = nil,
--the number the attacking team uses
teamATT = 1,
--the number the defending team uses
teamDEF = 2,
------------------------------
-- Shell Changable values --
------------------------------
--amount of seconds until the first Holocron spawns
delayStart = 18,
--total amount of captures per team until game ends. Uses CTFCaptureLimit if nil.
captureLimit = 3,
--about of AI bots per team. Uses CTFNumBots if nil, so value can be set through batch file starting a server.
botsPerTeam = nil,
--global time limit until the map ends in minutes. Uses CTFMaxTimeLimit if nil. Use 0 for unlimited time.
timeLimit = nil,
------------------------------
-- Optional values --
------------------------------
--
multiplayerRules = true,
--the amount of seconds required to hold the flag until a capture is scored
captureTime = 120,
--icon to display the flag on the ingame map
flagIcon = "hud_target_flag_onscreen",
--size of the ingame flag icon
flagIconScale = 3.0,
--message for when the enemy picks up the flag
--Note "captured", "taken", or "dropped" is appended to this message variable
enemyFlagMessage = "game.oneflag.enemy.",
--message for when a friendly team member picks up the flag
--Note "captured", "taken", or "dropped" is appended to this message variable
friendFlagMessage = "game.oneflag.friend.",
--True to display the flag to the carrier's enemy team's map
displayEnemyHolocron = false,
--True to display the flag to the carrier team's map
displayFriendlyHolocron = false,
--True to display the flag on the map when it is not being carried
displayWhenDropped = true,
--name of the flag object
flag = "anyRandomName",
--the odf for the object which will represent the holocron
--Note: this object should be of type "flag"
holocronObject = "com_item_holocron",
--used to hold the AI goals which change depending on the status of the Holocron
goals = {},
------------------------------
-- Optional Power-Up values --
------------------------------
--The max shield for the flag carrier.
maxShield = 900,
--The flag carrier's shield regeneration rate.
addShield = 160,
--The flag carrier's health regeneration rate.
addHealth = 50,
--The flag carrier's energy regeneration rate.
energyRestore = 9,
------------------------------
-- WIP values --
------------------------------
--Uncomment to display extra debug output if your map keeps crashing
debug = true,
}
--
-- If debug output is on, will output the given string.
--
function show( string )
--test for debug var
if not debug then return end
--check input
if not string then return end
--display the given string
print( string )
end--end of show()
--used to determine when setupClasses() has been called. Nil when called.
setupClasses = false
--
-- Can be overwritten by map developer
--
function ObjectiveHolocron:OnCapture(flag, carrier)
end
--
-- Can be overwritten by map developer
--
function ObjectiveHolocron:OnTaken(flag, carrier)
end
--
-- Get game time limit as set in game options menu, if any. 0 if none.
--
function ObjectiveHolocron:GetGameTimeLimit()
return ScriptCB_GetCTFMaxTimeLimit()
end --end of GetGameTimeLimit()
--
-- Determines who wins when the map's time limit is up.
--
function ObjectiveHolocron:GameOptionsTimeLimitUp()
show("")
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()
--
-- Adds a shield variable to all the classes so the game's net code know to update each unit's shield values
--
-- The table parameter needs to have the following format:
-- units = { "[class name]", "[class name]", "[class name]", "[class name...]", }--
--
function setupClasses( units )
show("")
show("setupClasses()" )
--check input
if not units then return end
--for each unit class,
local a
for a = 1, table.getn(units) do
--give it a starting shield value
--NOTE: this is needed to prevent the game from crashing in MP when any unit gets the shield powerup.
SetClassProperty(units[a], "MaxShield", 1 )
end
--set the setupClasses var so that other functions know the shields are ready for use
setupClasses = nil
show("")
show("setupClasses() completed" )
end--end of setupClasses()
--
-- Initialize the capture objective
--
function ObjectiveHolocron:Start()
show("")
show("A Holocron objective is starting.")
--check user vars for errors
assert( self.holocronObject, "Error: No given holocron object. Map will crash. May cause more errors. " )
assert( self.paths, "Error: No given paths. Map will crash. May cause more errors. " )
assert( self.flag, "Error: No given holocron entity name. Map will crash. May cause more errors. " )
--check to see if setupClasses() has been called
if setupClasses then
show("You need to run Holocron's setupClasses() or the map would crash when someone picks up the Holocron. Stopping Holocron mode.")
return --stop loading the Holocron mode to prevent crashes.
end
local firstRun = true
--=============================
-- local functions
--=============================
--
-- Returns a random path and a random node on that path
--
local getPathAndNode = function()
show("")
show("getPathAndNode()")
--get the amount of possible paths
local maxPaths = table.getn(self.paths)
--get a random path
local pathNumber = math.random(maxPaths)
--get the picked path's name
local path = self.paths[pathNumber].name
--get the path's amount of nodes
local maxNodes = self.paths[pathNumber].nodes
--get a random node
local node = math.random(maxNodes)
--return values
show("")
show("Returning path = " .. path .. " node = " .. node )
return path, node
end --end of getPathAndNode()
--
-- Spawns a new holocron at a random spot on the given paths.
-- Resets the AI's goals to make them go after the Holocron.
--
local spawnNewFlag = function()
show("")
show("spawnNewFlag()")
--if objective is complete, then return
if self.isComplete then return end
--make sure there is a Holocron goal table
self.goals = self.goals or {}
--for each Holocron mode AI goal, remove it
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
--remove all the goal handlers
self.goals = {}
--skip DeleteEntity if the holocron hasn't been created yet
if not firstRun then
--delete the current flag object
DeleteEntity( self.flag )
show("The last Holocron has been deleted.")
else
show("The first Holocron will soon spawn.")
firstRun = nil
end
--get a spawn point for the new holocron
local pathName, nodeNumber = getPathAndNode()
spawnPoint = GetPathPoint( pathName, nodeNumber)
assert( spawnPoint, "Error: A path point was not generated. Holocron cannot spawn.")
--spawn a new holocron
CreateEntity( self.holocronObject, spawnPoint, self.flag)
--get the holocron object
local holoPtr = GetObjectPtr(self.flag)
assert(holoPtr, "Error: Flag was not spawned. Map will crash. May cause more errors. ")
--tell the AI to protect the Holocron, and it hunt down when it stolen
--Note: can't tell teh AI to take the Holocron because that would require a region to return the flag to
--TODO: try with a nil region
-- --crashes
-- table.insert( self.goals or {}, AddAIGoal(self.teamATT, "CTFDefense", self.AIGoalWeight or 1, holoPtr) )
-- table.insert( self.goals or {}, AddAIGoal(self.teamDEF, "CTFDefense", self.AIGoalWeight or 1, holoPtr) )
--tell 40% of the AI to go after the Holocron. Hopefully, one of them will run over it and pick it up.
table.insert( self.goals, AddAIGoal(self.teamATT, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
--tell 20% of the AI to attack any enemies coming near the Holocron
table.insert( self.goals, AddAIGoal(self.teamATT, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
--tell 10% of the AI go go to the enemy bases and attack
--this is to send troops to slow down the enemy from reaching the Holocron.
table.insert( self.goals, AddAIGoal(self.teamATT, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
-- --doesn't crash, but AI just stands around
-- table.insert( self.goals or {}, AddAIGoal(self.teamATT, "CTFDefense", self.AIGoalWeight or 1) )
-- table.insert( self.goals or {}, AddAIGoal(self.teamDEF, "CTFDefense", self.AIGoalWeight or 1) )
end--end of spawnNewFlag()
--
-- Returns the opposing team
--
local GetOpposingTeam = function(team)
if team == self.teamATT then
return self.teamDEF
else
return self.teamATT
end
end--end of GetOpposingTeam(team)
--
-- Show a given flag message to the given team
--
local FlagMessage = function(friendTeam, message)
show("")
show("FlagMessage()")
--if objective is complete, then return
if self.isComplete then return end
--show a firendly message
if self.friendFlagMessage then
ShowMessageText(self.friendFlagMessage .. message, friendTeam)
end
local opposingTeam = GetOpposingTeam(friendTeam)
--show a message to the enemy
if self.enemyFlagMessage then
ShowMessageText(self.enemyFlagMessage .. message, opposingTeam)
end
local missionTime = ScriptCB_GetMissionTime()
local timeSinceLastPlayed = missionTime - self.lastVOPlayTime
--Sound voice over for message if haven't happened within the last 3 seconds already
if timeSinceLastPlayed > 3.0 then
SoundEvent_BroadcastVO( message, friendTeam, opposingTeam )
self.lastVOPlayTime = missionTime
end
end--end of FlagMessage()
--
-- Adds/Removes the flag marker for the given team
--
local AddMarkers = function(team, bPulseFlag)
show("")
show("AddMarkers()")
--if objective is complete, then return
if self.isComplete then return end
if bPulseFlag then
--show an in-hud marker for the flag
MapAddEntityMarker(self.flag, self.flagIcon, self.flagIconScale, team, "YELLOW", true, false, true, true)
else
--remove the in-hud marker which represents the flag
MapRemoveEntityMarker(self.flag)
end
end--end of AddMarkers()
--
-- Updates the map markers
--
local UpdateMarkerPulses = function()
show("")
show("UpdateMarkerPulses()")
--if objective is complete, then return
if self.isComplete then return end
--if no flag icon, return
if not self.flagIcon then return end
--if the flag is being carried,
if self.carrier then
--get team numbers
local carrierTeam = GetCharacterTeam(self.carrier)
local otherTeam = GetOpposingTeam(carrierTeam)
--for the carrier team, turn map marker on/off for the flag
AddMarkers( carrierTeam, self.displayFriendlyHolocron )
--for the other team, turn map marker on/off for the flag
AddMarkers( otherTeam, self.displayEnemyHolocron )
else
--the flag is not being carried, so show both teams where it is
AddMarkers( self.teamATT, self.displayWhenDropped )
AddMarkers( self.teamDEF, self.displayWhenDropped )
end
end--end of UpdateMarkerPulses()
--
-- What happens when the flag is captured
--
local CaptureFlag = function(carrierTeam)
show("")
show("CaptureFlag()")
--if objective is complete, then return
if self.isComplete then return end
--say flag captured message
FlagMessage(carrierTeam, "captured")
--give points to flag carrier
AddFlagCapturePoints(GetFlagCarrier(self.flag))
--give points to flag carrier's team
AddTeamPoints(carrierTeam, 1)
--double check to make sure carrier is not nil. May cause crash if was nil and not checked.
if self.carrier == nil then
--remove the carrier's unit powerups
local unit = GetCharacterUnit(self.carrier)
RemovePowerUps(unit)
end
--foward capture event and holocron no longer has a carrier
self:OnCapture(self.flag, self.carrier)
self.carrier = nil
--destroy the current holocron, randomly spawn a new one, and rests AI goals
spawnNewFlag()
end--end of CaptureFlag()
--
-- Gives the given unit extra powers
--
local GivePowerUps = function(unit)
show("")
show("GivePowerUps()")
--if objective is complete, then return
if self.isComplete then return end
--[[
Possible powerups:
BuffDefenseMult = "0.5"
BuffOffenseMult = "1.5"
BuffHealthRate = "20"
SoldierEnergy = 150
SoldierHealth = 200
SoldierAmmo = 2
EnergyRestore = 12.0
Shield
Health
Ammo
--]]
--check input
if not unit then return end
--SetProperty(unit, "CurShield", 0 )
--set the max shield value
--Note: this may be a problem for any normally shielded units
SetProperty(unit, "MaxShield", self.maxShield or 900 )
--set the shield regeneration rate
SetProperty(unit, "AddShield", self.addShield or 160 )
--set the health regeneration rate
SetProperty(unit, "AddHealth", self.addHealth or 50 )
--set the energy regeneration rate, common to both MP and SP
SetProperty(unit, "EnergyRestore", self.energyRestore or 9 )
end--end of GivePowerUps()
--
-- Removes the extra powers from the given player
--
local RemovePowerUps = function(unit)
show("")
show("RemovePowerUps()")
--if objective is complete, then return
if self.isComplete then return end
--check input
if not unit then return end
--'removes' the shield
--Note: decided to let the player keep the shield until it runs out
--SetProperty(unit, "CurShield", 0 )
--remove the shield regeneration rate
--Note: this may be a problem for any normally shielded units
SetProperty(unit, "AddShield", 0 )
--remove the health regeneration rate
SetProperty(unit, "AddHealth", 0 )
--remove the energy regeneration rate
SetProperty(unit, "EnergyRestore", 0 )
end--end of RemovePowerUps()
--==========
-- Set the number of guys in the level to the number in game options
--==========
ScriptCB_SetNumBots( botsPerTeam or ScriptCB_GetCTFNumBots() or 10)
--use CTF time limit if current limit is nil
self.timeLimit = self.timeLimit or ScriptCB_GetCTFMaxTimeLimit() or 11
--===============================
-- Initialization logic
--===============================
--initialize the base objective data first--
Objective.Start(self)
-- initialize internal values---------------
self.lastVOPlayTime = -100000.0
--if multiplayer rules, then
if self.multiplayerRules then
--use GUI capture limit
self.captureLimit = self.captureLimit or ScriptCB_GetCTFCaptureLimit() or 3
--set to unlimited reinforcments
SetReinforcementCount(self.teamATT, -1)
SetReinforcementCount(self.teamDEF, -1)
--let C++ know what type of flag mode
--the flag mode changes the flag images displayed by the game code
SetFlagGameplayType("1flag")
else
SetFlagGameplayType("campaign")
end
--display the team points at the top of the screen
ShowTeamPoints(self.teamATT, true)
ShowTeamPoints(self.teamDEF, true)
--give the AI a starting goal
self.goals = self.goals or {}
table.insert( self.goals, AddAIGoal(self.teamATT, "Deathmatch", self.AIGoalWeight or 1) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Deathmatch", self.AIGoalWeight or 1) )
------------
-- Timers --
------------
--create, set and start the startDelayTimer.
CreateTimer("startDelayTimer")
SetTimerValue("startDelayTimer", startDelay or 17)
ShowTimer("startDelayTimer")
StartTimer("startDelayTimer")
--when the startDelayTimer is up, spawn the first holocron and let the games begin.
OnTimerElapse(
function(timer)
--stop displaying the start timer
ShowTimer(nil)
--no longer needed, so destroy startDelay timer to free up some memory
DestroyTimer("startDelayTimer")
--spawn the starting holocron in a random spot
spawnNewFlag()
--just in case a player is already standing right where the flag spawns in...
self.carrier = GetFlagCarrier(self.flag)
if self.carrier then
UpdateMarkerPulses()
FlagMessage(GetCharacterTeam(self.carrier), "taken")
self:OnTaken(self.flag, self.carrier)
end
UpdateMarkerPulses(self.flag)
----------------------
-- Core.lvl strings --
----------------------
--I'm not sure where in the language files these should go.
--You can put (and rename) them where you feel is right. Let me know where.
--Here is what I think their values should be:
--modeName = Holocron
--objectiveDescription = Mode Holocron. Hold the Holocron to score points for your team.
--hint1 = The Holocron carrier is protected by a shield. Attack the carrier in groups.
--hint2 = If you team kill, you will start to randomly die.
--hint3 = The carrier keeps the remaining sheild strength after he or she scores.
--for each team, set the mission objective
AddMissionObjective(self.teamATT, "holo.modeName", "holo.objective")
AddMissionObjective(self.teamDEF, "holo.modeName2", "holo.objective2")
--add mission hints
AddMissionHint("holo.hint1")
AddMissionHint("holo.hint2")
AddMissionHint("holo.hint3")
--activate objective so it shows up on the ingame map screen
ActivateObjective("holo.modeName")
ActivateObjective("holo.modeName2")
end, "startDelayTimer"
)
CreateTimer("captureTimer")
SetTimerValue("captureTimer", self.captureTime or 120 )
--when the captureTimer is up, the player with the flag scores a capture
OnTimerElapse(
function(timer)
--if objective is complete, then return
if self.isComplete then return end
--if there is no flag carrier, return
if self.carrier == nil then return end
show("Holocron captured.")
--get the carrier's team
local carrierTeam = GetCharacterTeam(self.carrier)
--remove the carrier's unit powerups
local unit = GetCharacterUnit(self.carrier)
RemovePowerUps(unit)
--the carrier has scored a capture
CaptureFlag(carrierTeam)
--reset and hide this timer
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer(nil)
end, "captureTimer"
)
--=======================================
-- Event responses
--=======================================
--when flag resets to starting position
OnFlagReset(
function (holoPtr)
show("")
show("OnFlagReset")
--if objective is complete, then return
if self.isComplete then return end
--get the flag name
local flagName = GetEntityName(holoPtr)
--map sure the resetting flag is the given objective flag
if self.flag ~= flagName then return end
--check to make sure carrier is not nil
--NOTE: need to have this here incase unit carries flag too long?
if self.carrier ~= nil then
--remove the carrier's unit powerups
local unit = GetCharacterUnit(self.carrier)
RemovePowerUps(unit)
end
--set as not moved
self.carrier = nil
--stop, reset, and hide the flag capture timer
StopTimer("captureTimer")
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer(nil)
--spawn a new Holocron if the current one gets reset
spawnNewFlag()
--update flag's ingame map marker
UpdateMarkerPulses(self.flag)
end
)
--when a player pickups the flag
OnFlagPickUp(
function(holoPtr, carrierObj)
show("")
show("OnFlagPickUp")
--if objective is complete, then return
if self.isComplete then return end
--get the flag name
local flagName = GetEntityName(holoPtr)
--make sure its the objective flag. Not sure what the assert is doing.
if self.flag ~= flagName then
assert("self.flag:", self.flag, " does not equal flagName:", flagName, " (don't forget flags cant have capitals in their names!)")
end
--get the carrier's team
local carrierTeam = GetCharacterTeam(carrierObj)
--set the flag's carrier
self.carrier = carrierObj
--send flag taken message out to players
FlagMessage(carrierTeam, "taken")
--IDEA: If the carrier's team is on its last capture, start the victory count down?
--NOTE: Holocron might not be the only objective so this is a bad idea.
--stop, reset, display, then start the flag capture timer
StopTimer("captureTimer") --NOTE: not sure if this is needed
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer("captureTimer")
StartTimer("captureTimer")
--give the carrier's unit powerups
local unit = GetCharacterUnit(carrierObj)
GivePowerUps(unit)
--update flag's ingame map marker
UpdateMarkerPulses(self.flag)
--get the holocron object
local flagPtr = GetObjectPtr(self.flag)
assert(flagPtr, "ERROR: flag "..self.flag.." does not exist in the map")
--clear the Holocron AI goals
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
--clear the old goal handlers
self.goals = {}
--TODO: make sure the AI goals changes from holoPtr to carrier work ingame.
--if the holocron carrier is human have the AI defend, else have the AI run around
if IsCharacterHuman(self.carrier) then
--tell AI to defend the human player
table.insert( self.goals, AddAIGoal(carrierTeam, "Defend", self.AIGoalWeight*60 or 60, self.carrier) )
--don't want the human covered with bots
table.insert( self.goals, AddAIGoal(carrierTeam, "Deathmatch", self.AIGoalWeight*10 or 10, self.carrier) )
else
--AI pickuped flag, so tell holocron holder to randomly run around the map
table.insert( self.goals, AddAIGoal(carrierTeam, "Follow", self.AIGoalWeight*60 or 60, self.carrier) )
--tell others to defent the carrier
table.insert( self.goals, AddAIGoal(carrierTeam, "Defend", self.AIGoalWeight*30 or 30, self.carrier) )
--tell a few AI to attack the enemy anywhere
table.insert( self.goals, AddAIGoal(carrierTeam, "Deathmatch", self.AIGoalWeight*10 or 10) )
end
--tell the enemy AI to follow and destroy the holocron carrier
local enemyTeam = GetOpposingTeam(carrierTeam)
table.insert( self.goals, AddAIGoal(enemyTeam, "Destroy", self.AIGoalWeight*70 or 70, self.carrier) )
table.insert( self.goals, AddAIGoal(enemyTeam, "Follow", self.AIGoalWeight*20 or 20, self.carrier) )
--keep a few bots spread around the map to catch the next spawning Holocron
table.insert( self.goals, AddAIGoal(enemyTeam, "Deathmatch", self.AIGoalWeight*10 or 10) )
end
)
--when a player drops the flag
OnFlagDrop(
function(holoPtr, carrierObj)
show("")
show("OnFlagDrop")
--if objective is complete, then return
if self.isComplete then return end
local flagName = GetEntityName(holoPtr)
--make sure its the objective flag
if self.flag ~= flagName then return end
--stop, reset, and hide the flag capture timer
StopTimer("captureTimer")
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer(nil)
--Note: unit is dead, so no need to remove the powerups
--remove the carrier's unit powerups
local unit = GetCharacterUnit(carrierObj)
RemovePowerUps(unit)
--store the last carrier incase the carrier was TKed
self.lastCarrier = self.carrier
--no more flag carrier
self.carrier = nil
--send out flag dropped text and voice message
FlagMessage(GetCharacterTeam(carrierObj), "dropped")
--update flag's ingame map marker
UpdateMarkerPulses(self.flag)
--get the holocron object
local flagPtr = GetObjectPtr(self.flag)
assert(flagPtr, "ERROR: flag does not exist in the map")
--clear the current AI Holocron goals
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
--clear the old goal handlers
self.goals = {}
--tell 40% of the AI to go after the Holocron. Hopefully, one of them will run over it and pick it up.
table.insert( self.goals, AddAIGoal(self.teamATT, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
--tell 20% of the AI to attack any enemies coming near the Holocron
table.insert( self.goals, AddAIGoal(self.teamATT, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
--tell 10% of the AI go go to the enemy bases and attack
--this is to send troops to slow down the enemy from reaching the Holocron.
table.insert( self.goals, AddAIGoal(self.teamATT, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
end
)
--when the a team's points change
OnTeamPointsChange(
function (team, points)
show("")
show("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
self:Complete(team)
end
end
)
--kill a unit if he/she TKs the holocron carrier
OnCharacterDeath(
function( dead, killer )
--if the dead player did not have the holocron, leave the event
--Note: most units will fail this test, so it is put first
if dead ~= self.lastCarrier then return end
show("OnCharacterDeath, last carrier killed")
--if not on same team, leave event
if GetCharacterTeam(dead) ~= GetCharacterTeam(killer) then return end
--Note: it may be possible to trick this TK carrier killer function. See the commented out OnCharacterSpawn()
--the played who died was the last flag carrier and he/was Tked, so kill the killer
ScriptCB_PlayerSuicide(killer)
end
)
--Note: this is needed to prevent the a Tker from dying when he/she kills the player
-- who last held the flag (that player has since respawned and no longer carriers the flag).
-- There is a risk that the game may be busy and the last carrier player
-- respawns before the Tker can be killed. In which case, the Tker
-- will get away with murder.
--Note2: On second thought, this will just slow the game even more. Why not
-- let the Tker die? He/she shouldn't be Tking players anyway. Some
-- Tkers are in for surprising sudden deaths
.
--Note3: Modders, if you want to prevent this little glitch and enable an even
-- smaller glitch, uncomment the following OnCharacterSpawn()
--if the player who was holding the flag has respawned, clear last holocron carrier var.
--OnCharacterSpawn(
-- function( player )
-- if player == self.lastCarrier then
-- self.lastCarrier = nil
-- end
-- end
--)
end
-----------------------------------------------------
-- Sound cues for events
gSoundEventsCTF_src = {
all = {
returned_att = "all_allFlag_returned",
returned_def = "all_impFlag_returned",
captured_att = "all_allFlag_score",
captured_def = "all_impFlag_score",
taken_att = "all_1Flag_take_all",
taken_def = "all_1Flag_take_imp",
dropped_att = "all_1Flag_drop_all",
dropped_def = "all_1Flag_drop_imp",
},
imp = {
returned_att = "imp_impFlag_returned",
returned_def = "imp_allFlag_returned",
captured_att = "imp_impFlag_score",
captured_def = "imp_allFlag_score",
taken_att = "imp_1Flag_take_imp",
taken_def = "imp_1Flag_take_all",
dropped_att = "imp_1Flag_drop_imp",
dropped_def = "imp_1Flag_drop_all",
},
rep = {
returned_att = "rep_repFlag_returned",
returned_def = "rep_cisFlag_returned",
captured_att = "rep_repFlag_score",
captured_def = "rep_cisFlag_score",
taken_att = "rep_1Flag_take_rep",
taken_def = "rep_1Flag_take_cis",
dropped_att = "rep_1Flag_drop_rep",
dropped_def = "rep_1Flag_drop_cis",
},
cis = {
returned_att = "cis_cisFlag_returned",
returned_def = "cis_repFlag_returned",
captured_att = "cis_cisFlag_score",
captured_def = "cis_repFlag_score",
taken_att = "cis_1Flag_take_cis",
taken_def = "cis_1Flag_take_rep",
dropped_att = "cis_1Flag_drop_cis",
dropped_def = "cis_1Flag_drop_rep",
},
}[/code]
-- Partly based on ObjectiveOneFlagCTF.lua released with the SWBF2 Mode Tools.
-- Copyright (c) 2006 GameToast Modder [RDH]Zerted, Auguest 27th, 2006
--
-- Feel free to edit and distrubute this, but give [RDH]Zerted credit for what he has done.
-- No making/gaining money off of any part of this for any reason.
--
--Version: Sept. 22th, 2006
--[[
----------------------
-- Tips for modders --
----------------------
> In your map's main Lua, include: ScriptCB_DoFile("ObjectiveHolocron")
> Here is an example ScriptPostLoad() function:
<<<<<<<<<<<<<<
function ScriptPostLoad()
SoundEvent_SetupTeams( ALL, 'all', IMP, 'imp' )
--create a Holocron objective
hm = ObjectiveHolocron:New{
--team numbers
teamATT = 1,
teamDEF = 2,
--game mode text
textATT = "game.modes.1flag",
textDEF = "game.modes.1flag2",
--these are the paths the holocron may spawn on
--the holocron will randomly spawn on one of these
paths = {
{name = "1flag_cp1_spawn", nodes = 4,},
{name = "1flag_cp2_spawn", nodes = 4,},
{name = "1flag_cp3_spawn", nodes = 4,},
{name = "1flag_cp4_spawn", nodes = 4,},
{name = "holocron_path", nodes = 20,},
},
--
multiplayerRules = true,
--hides the CPs from the ingame map
hideCPs = true,
--total captures a team needs to win the map
captureLimit = 3,
--the amount of seconds required to hold the flag until a capture is scored
captureTime = 20,
--the object that will be spawned as the capturable item
--Note: this object should be of type "flag"
holocronObject = "com_item_holocron",
}
--start the holocron objective
hm:Start()
end
<<<<<<<<<<<<<<
> Don't forget to add a memory pool for the shield effects: SetMemoryPoolSize("ShieldEffect", 10)
> If your map is having problems, uncomment all the 'print()' statement. Next
>> time you attempt to run your map, look at the error log, and follow the output
>> through your code it see what was going on at the time of the problem/crash.
>The Holocrons game mode and heros do not mix. Do not include heros in your map.
--]]
ScriptCB_DoFile("Objective")
ScriptCB_DoFile("SoundEvent_ctf")
--=============================
-- ObjectiveHolocron
-- Handles the logic for a capture the flag game
--=============================
ObjectiveHolocron = Objective:New
{
------------------------------
-- Required External values --
------------------------------
--a table of paths of which the holocron will randomly spawn on
--format:
--paths = {
-- { name = "[path name]", nodes = [max amount of nides on the path] },
--},
paths = nil,
--the number the attacking team uses
teamATT = 1,
--the number the defending team uses
teamDEF = 2,
------------------------------
-- Shell Changable values --
------------------------------
--amount of seconds until the first Holocron spawns
delayStart = 18,
--total amount of captures per team until game ends. Uses CTFCaptureLimit if nil.
captureLimit = 3,
--about of AI bots per team. Uses CTFNumBots if nil, so value can be set through batch file starting a server.
botsPerTeam = nil,
--global time limit until the map ends in minutes. Uses CTFMaxTimeLimit if nil. Use 0 for unlimited time.
timeLimit = nil,
------------------------------
-- Optional values --
------------------------------
--
multiplayerRules = true,
--the amount of seconds required to hold the flag until a capture is scored
captureTime = 120,
--icon to display the flag on the ingame map
flagIcon = "hud_target_flag_onscreen",
--size of the ingame flag icon
flagIconScale = 3.0,
--message for when the enemy picks up the flag
--Note "captured", "taken", or "dropped" is appended to this message variable
enemyFlagMessage = "game.oneflag.enemy.",
--message for when a friendly team member picks up the flag
--Note "captured", "taken", or "dropped" is appended to this message variable
friendFlagMessage = "game.oneflag.friend.",
--True to display the flag to the carrier's enemy team's map
displayEnemyHolocron = false,
--True to display the flag to the carrier team's map
displayFriendlyHolocron = false,
--True to display the flag on the map when it is not being carried
displayWhenDropped = true,
--name of the flag object
flag = "anyRandomName",
--the odf for the object which will represent the holocron
--Note: this object should be of type "flag"
holocronObject = "com_item_holocron",
--used to hold the AI goals which change depending on the status of the Holocron
goals = {},
------------------------------
-- Optional Power-Up values --
------------------------------
--The max shield for the flag carrier.
maxShield = 900,
--The flag carrier's shield regeneration rate.
addShield = 160,
--The flag carrier's health regeneration rate.
addHealth = 50,
--The flag carrier's energy regeneration rate.
energyRestore = 9,
------------------------------
-- WIP values --
------------------------------
--Uncomment to display extra debug output if your map keeps crashing
debug = true,
}
--
-- If debug output is on, will output the given string.
--
function show( string )
--test for debug var
if not debug then return end
--check input
if not string then return end
--display the given string
print( string )
end--end of show()
--used to determine when setupClasses() has been called. Nil when called.
setupClasses = false
--
-- Can be overwritten by map developer
--
function ObjectiveHolocron:OnCapture(flag, carrier)
end
--
-- Can be overwritten by map developer
--
function ObjectiveHolocron:OnTaken(flag, carrier)
end
--
-- Get game time limit as set in game options menu, if any. 0 if none.
--
function ObjectiveHolocron:GetGameTimeLimit()
return ScriptCB_GetCTFMaxTimeLimit()
end --end of GetGameTimeLimit()
--
-- Determines who wins when the map's time limit is up.
--
function ObjectiveHolocron:GameOptionsTimeLimitUp()
show("")
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()
--
-- Adds a shield variable to all the classes so the game's net code know to update each unit's shield values
--
-- The table parameter needs to have the following format:
-- units = { "[class name]", "[class name]", "[class name]", "[class name...]", }--
--
function setupClasses( units )
show("")
show("setupClasses()" )
--check input
if not units then return end
--for each unit class,
local a
for a = 1, table.getn(units) do
--give it a starting shield value
--NOTE: this is needed to prevent the game from crashing in MP when any unit gets the shield powerup.
SetClassProperty(units[a], "MaxShield", 1 )
end
--set the setupClasses var so that other functions know the shields are ready for use
setupClasses = nil
show("")
show("setupClasses() completed" )
end--end of setupClasses()
--
-- Initialize the capture objective
--
function ObjectiveHolocron:Start()
show("")
show("A Holocron objective is starting.")
--check user vars for errors
assert( self.holocronObject, "Error: No given holocron object. Map will crash. May cause more errors. " )
assert( self.paths, "Error: No given paths. Map will crash. May cause more errors. " )
assert( self.flag, "Error: No given holocron entity name. Map will crash. May cause more errors. " )
--check to see if setupClasses() has been called
if setupClasses then
show("You need to run Holocron's setupClasses() or the map would crash when someone picks up the Holocron. Stopping Holocron mode.")
return --stop loading the Holocron mode to prevent crashes.
end
local firstRun = true
--=============================
-- local functions
--=============================
--
-- Returns a random path and a random node on that path
--
local getPathAndNode = function()
show("")
show("getPathAndNode()")
--get the amount of possible paths
local maxPaths = table.getn(self.paths)
--get a random path
local pathNumber = math.random(maxPaths)
--get the picked path's name
local path = self.paths[pathNumber].name
--get the path's amount of nodes
local maxNodes = self.paths[pathNumber].nodes
--get a random node
local node = math.random(maxNodes)
--return values
show("")
show("Returning path = " .. path .. " node = " .. node )
return path, node
end --end of getPathAndNode()
--
-- Spawns a new holocron at a random spot on the given paths.
-- Resets the AI's goals to make them go after the Holocron.
--
local spawnNewFlag = function()
show("")
show("spawnNewFlag()")
--if objective is complete, then return
if self.isComplete then return end
--make sure there is a Holocron goal table
self.goals = self.goals or {}
--for each Holocron mode AI goal, remove it
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
--remove all the goal handlers
self.goals = {}
--skip DeleteEntity if the holocron hasn't been created yet
if not firstRun then
--delete the current flag object
DeleteEntity( self.flag )
show("The last Holocron has been deleted.")
else
show("The first Holocron will soon spawn.")
firstRun = nil
end
--get a spawn point for the new holocron
local pathName, nodeNumber = getPathAndNode()
spawnPoint = GetPathPoint( pathName, nodeNumber)
assert( spawnPoint, "Error: A path point was not generated. Holocron cannot spawn.")
--spawn a new holocron
CreateEntity( self.holocronObject, spawnPoint, self.flag)
--get the holocron object
local holoPtr = GetObjectPtr(self.flag)
assert(holoPtr, "Error: Flag was not spawned. Map will crash. May cause more errors. ")
--tell the AI to protect the Holocron, and it hunt down when it stolen
--Note: can't tell teh AI to take the Holocron because that would require a region to return the flag to
--TODO: try with a nil region
-- --crashes
-- table.insert( self.goals or {}, AddAIGoal(self.teamATT, "CTFDefense", self.AIGoalWeight or 1, holoPtr) )
-- table.insert( self.goals or {}, AddAIGoal(self.teamDEF, "CTFDefense", self.AIGoalWeight or 1, holoPtr) )
--tell 40% of the AI to go after the Holocron. Hopefully, one of them will run over it and pick it up.
table.insert( self.goals, AddAIGoal(self.teamATT, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
--tell 20% of the AI to attack any enemies coming near the Holocron
table.insert( self.goals, AddAIGoal(self.teamATT, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
--tell 10% of the AI go go to the enemy bases and attack
--this is to send troops to slow down the enemy from reaching the Holocron.
table.insert( self.goals, AddAIGoal(self.teamATT, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
-- --doesn't crash, but AI just stands around
-- table.insert( self.goals or {}, AddAIGoal(self.teamATT, "CTFDefense", self.AIGoalWeight or 1) )
-- table.insert( self.goals or {}, AddAIGoal(self.teamDEF, "CTFDefense", self.AIGoalWeight or 1) )
end--end of spawnNewFlag()
--
-- Returns the opposing team
--
local GetOpposingTeam = function(team)
if team == self.teamATT then
return self.teamDEF
else
return self.teamATT
end
end--end of GetOpposingTeam(team)
--
-- Show a given flag message to the given team
--
local FlagMessage = function(friendTeam, message)
show("")
show("FlagMessage()")
--if objective is complete, then return
if self.isComplete then return end
--show a firendly message
if self.friendFlagMessage then
ShowMessageText(self.friendFlagMessage .. message, friendTeam)
end
local opposingTeam = GetOpposingTeam(friendTeam)
--show a message to the enemy
if self.enemyFlagMessage then
ShowMessageText(self.enemyFlagMessage .. message, opposingTeam)
end
local missionTime = ScriptCB_GetMissionTime()
local timeSinceLastPlayed = missionTime - self.lastVOPlayTime
--Sound voice over for message if haven't happened within the last 3 seconds already
if timeSinceLastPlayed > 3.0 then
SoundEvent_BroadcastVO( message, friendTeam, opposingTeam )
self.lastVOPlayTime = missionTime
end
end--end of FlagMessage()
--
-- Adds/Removes the flag marker for the given team
--
local AddMarkers = function(team, bPulseFlag)
show("")
show("AddMarkers()")
--if objective is complete, then return
if self.isComplete then return end
if bPulseFlag then
--show an in-hud marker for the flag
MapAddEntityMarker(self.flag, self.flagIcon, self.flagIconScale, team, "YELLOW", true, false, true, true)
else
--remove the in-hud marker which represents the flag
MapRemoveEntityMarker(self.flag)
end
end--end of AddMarkers()
--
-- Updates the map markers
--
local UpdateMarkerPulses = function()
show("")
show("UpdateMarkerPulses()")
--if objective is complete, then return
if self.isComplete then return end
--if no flag icon, return
if not self.flagIcon then return end
--if the flag is being carried,
if self.carrier then
--get team numbers
local carrierTeam = GetCharacterTeam(self.carrier)
local otherTeam = GetOpposingTeam(carrierTeam)
--for the carrier team, turn map marker on/off for the flag
AddMarkers( carrierTeam, self.displayFriendlyHolocron )
--for the other team, turn map marker on/off for the flag
AddMarkers( otherTeam, self.displayEnemyHolocron )
else
--the flag is not being carried, so show both teams where it is
AddMarkers( self.teamATT, self.displayWhenDropped )
AddMarkers( self.teamDEF, self.displayWhenDropped )
end
end--end of UpdateMarkerPulses()
--
-- What happens when the flag is captured
--
local CaptureFlag = function(carrierTeam)
show("")
show("CaptureFlag()")
--if objective is complete, then return
if self.isComplete then return end
--say flag captured message
FlagMessage(carrierTeam, "captured")
--give points to flag carrier
AddFlagCapturePoints(GetFlagCarrier(self.flag))
--give points to flag carrier's team
AddTeamPoints(carrierTeam, 1)
--double check to make sure carrier is not nil. May cause crash if was nil and not checked.
if self.carrier == nil then
--remove the carrier's unit powerups
local unit = GetCharacterUnit(self.carrier)
RemovePowerUps(unit)
end
--foward capture event and holocron no longer has a carrier
self:OnCapture(self.flag, self.carrier)
self.carrier = nil
--destroy the current holocron, randomly spawn a new one, and rests AI goals
spawnNewFlag()
end--end of CaptureFlag()
--
-- Gives the given unit extra powers
--
local GivePowerUps = function(unit)
show("")
show("GivePowerUps()")
--if objective is complete, then return
if self.isComplete then return end
--[[
Possible powerups:
BuffDefenseMult = "0.5"
BuffOffenseMult = "1.5"
BuffHealthRate = "20"
SoldierEnergy = 150
SoldierHealth = 200
SoldierAmmo = 2
EnergyRestore = 12.0
Shield
Health
Ammo
--]]
--check input
if not unit then return end
--SetProperty(unit, "CurShield", 0 )
--set the max shield value
--Note: this may be a problem for any normally shielded units
SetProperty(unit, "MaxShield", self.maxShield or 900 )
--set the shield regeneration rate
SetProperty(unit, "AddShield", self.addShield or 160 )
--set the health regeneration rate
SetProperty(unit, "AddHealth", self.addHealth or 50 )
--set the energy regeneration rate, common to both MP and SP
SetProperty(unit, "EnergyRestore", self.energyRestore or 9 )
end--end of GivePowerUps()
--
-- Removes the extra powers from the given player
--
local RemovePowerUps = function(unit)
show("")
show("RemovePowerUps()")
--if objective is complete, then return
if self.isComplete then return end
--check input
if not unit then return end
--'removes' the shield
--Note: decided to let the player keep the shield until it runs out
--SetProperty(unit, "CurShield", 0 )
--remove the shield regeneration rate
--Note: this may be a problem for any normally shielded units
SetProperty(unit, "AddShield", 0 )
--remove the health regeneration rate
SetProperty(unit, "AddHealth", 0 )
--remove the energy regeneration rate
SetProperty(unit, "EnergyRestore", 0 )
end--end of RemovePowerUps()
--==========
-- Set the number of guys in the level to the number in game options
--==========
ScriptCB_SetNumBots( botsPerTeam or ScriptCB_GetCTFNumBots() or 10)
--use CTF time limit if current limit is nil
self.timeLimit = self.timeLimit or ScriptCB_GetCTFMaxTimeLimit() or 11
--===============================
-- Initialization logic
--===============================
--initialize the base objective data first--
Objective.Start(self)
-- initialize internal values---------------
self.lastVOPlayTime = -100000.0
--if multiplayer rules, then
if self.multiplayerRules then
--use GUI capture limit
self.captureLimit = self.captureLimit or ScriptCB_GetCTFCaptureLimit() or 3
--set to unlimited reinforcments
SetReinforcementCount(self.teamATT, -1)
SetReinforcementCount(self.teamDEF, -1)
--let C++ know what type of flag mode
--the flag mode changes the flag images displayed by the game code
SetFlagGameplayType("1flag")
else
SetFlagGameplayType("campaign")
end
--display the team points at the top of the screen
ShowTeamPoints(self.teamATT, true)
ShowTeamPoints(self.teamDEF, true)
--give the AI a starting goal
self.goals = self.goals or {}
table.insert( self.goals, AddAIGoal(self.teamATT, "Deathmatch", self.AIGoalWeight or 1) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Deathmatch", self.AIGoalWeight or 1) )
------------
-- Timers --
------------
--create, set and start the startDelayTimer.
CreateTimer("startDelayTimer")
SetTimerValue("startDelayTimer", startDelay or 17)
ShowTimer("startDelayTimer")
StartTimer("startDelayTimer")
--when the startDelayTimer is up, spawn the first holocron and let the games begin.
OnTimerElapse(
function(timer)
--stop displaying the start timer
ShowTimer(nil)
--no longer needed, so destroy startDelay timer to free up some memory
DestroyTimer("startDelayTimer")
--spawn the starting holocron in a random spot
spawnNewFlag()
--just in case a player is already standing right where the flag spawns in...
self.carrier = GetFlagCarrier(self.flag)
if self.carrier then
UpdateMarkerPulses()
FlagMessage(GetCharacterTeam(self.carrier), "taken")
self:OnTaken(self.flag, self.carrier)
end
UpdateMarkerPulses(self.flag)
----------------------
-- Core.lvl strings --
----------------------
--I'm not sure where in the language files these should go.
--You can put (and rename) them where you feel is right. Let me know where.
--Here is what I think their values should be:
--modeName = Holocron
--objectiveDescription = Mode Holocron. Hold the Holocron to score points for your team.
--hint1 = The Holocron carrier is protected by a shield. Attack the carrier in groups.
--hint2 = If you team kill, you will start to randomly die.
--hint3 = The carrier keeps the remaining sheild strength after he or she scores.
--for each team, set the mission objective
AddMissionObjective(self.teamATT, "holo.modeName", "holo.objective")
AddMissionObjective(self.teamDEF, "holo.modeName2", "holo.objective2")
--add mission hints
AddMissionHint("holo.hint1")
AddMissionHint("holo.hint2")
AddMissionHint("holo.hint3")
--activate objective so it shows up on the ingame map screen
ActivateObjective("holo.modeName")
ActivateObjective("holo.modeName2")
end, "startDelayTimer"
)
CreateTimer("captureTimer")
SetTimerValue("captureTimer", self.captureTime or 120 )
--when the captureTimer is up, the player with the flag scores a capture
OnTimerElapse(
function(timer)
--if objective is complete, then return
if self.isComplete then return end
--if there is no flag carrier, return
if self.carrier == nil then return end
show("Holocron captured.")
--get the carrier's team
local carrierTeam = GetCharacterTeam(self.carrier)
--remove the carrier's unit powerups
local unit = GetCharacterUnit(self.carrier)
RemovePowerUps(unit)
--the carrier has scored a capture
CaptureFlag(carrierTeam)
--reset and hide this timer
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer(nil)
end, "captureTimer"
)
--=======================================
-- Event responses
--=======================================
--when flag resets to starting position
OnFlagReset(
function (holoPtr)
show("")
show("OnFlagReset")
--if objective is complete, then return
if self.isComplete then return end
--get the flag name
local flagName = GetEntityName(holoPtr)
--map sure the resetting flag is the given objective flag
if self.flag ~= flagName then return end
--check to make sure carrier is not nil
--NOTE: need to have this here incase unit carries flag too long?
if self.carrier ~= nil then
--remove the carrier's unit powerups
local unit = GetCharacterUnit(self.carrier)
RemovePowerUps(unit)
end
--set as not moved
self.carrier = nil
--stop, reset, and hide the flag capture timer
StopTimer("captureTimer")
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer(nil)
--spawn a new Holocron if the current one gets reset
spawnNewFlag()
--update flag's ingame map marker
UpdateMarkerPulses(self.flag)
end
)
--when a player pickups the flag
OnFlagPickUp(
function(holoPtr, carrierObj)
show("")
show("OnFlagPickUp")
--if objective is complete, then return
if self.isComplete then return end
--get the flag name
local flagName = GetEntityName(holoPtr)
--make sure its the objective flag. Not sure what the assert is doing.
if self.flag ~= flagName then
assert("self.flag:", self.flag, " does not equal flagName:", flagName, " (don't forget flags cant have capitals in their names!)")
end
--get the carrier's team
local carrierTeam = GetCharacterTeam(carrierObj)
--set the flag's carrier
self.carrier = carrierObj
--send flag taken message out to players
FlagMessage(carrierTeam, "taken")
--IDEA: If the carrier's team is on its last capture, start the victory count down?
--NOTE: Holocron might not be the only objective so this is a bad idea.
--stop, reset, display, then start the flag capture timer
StopTimer("captureTimer") --NOTE: not sure if this is needed
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer("captureTimer")
StartTimer("captureTimer")
--give the carrier's unit powerups
local unit = GetCharacterUnit(carrierObj)
GivePowerUps(unit)
--update flag's ingame map marker
UpdateMarkerPulses(self.flag)
--get the holocron object
local flagPtr = GetObjectPtr(self.flag)
assert(flagPtr, "ERROR: flag "..self.flag.." does not exist in the map")
--clear the Holocron AI goals
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
--clear the old goal handlers
self.goals = {}
--TODO: make sure the AI goals changes from holoPtr to carrier work ingame.
--if the holocron carrier is human have the AI defend, else have the AI run around
if IsCharacterHuman(self.carrier) then
--tell AI to defend the human player
table.insert( self.goals, AddAIGoal(carrierTeam, "Defend", self.AIGoalWeight*60 or 60, self.carrier) )
--don't want the human covered with bots
table.insert( self.goals, AddAIGoal(carrierTeam, "Deathmatch", self.AIGoalWeight*10 or 10, self.carrier) )
else
--AI pickuped flag, so tell holocron holder to randomly run around the map
table.insert( self.goals, AddAIGoal(carrierTeam, "Follow", self.AIGoalWeight*60 or 60, self.carrier) )
--tell others to defent the carrier
table.insert( self.goals, AddAIGoal(carrierTeam, "Defend", self.AIGoalWeight*30 or 30, self.carrier) )
--tell a few AI to attack the enemy anywhere
table.insert( self.goals, AddAIGoal(carrierTeam, "Deathmatch", self.AIGoalWeight*10 or 10) )
end
--tell the enemy AI to follow and destroy the holocron carrier
local enemyTeam = GetOpposingTeam(carrierTeam)
table.insert( self.goals, AddAIGoal(enemyTeam, "Destroy", self.AIGoalWeight*70 or 70, self.carrier) )
table.insert( self.goals, AddAIGoal(enemyTeam, "Follow", self.AIGoalWeight*20 or 20, self.carrier) )
--keep a few bots spread around the map to catch the next spawning Holocron
table.insert( self.goals, AddAIGoal(enemyTeam, "Deathmatch", self.AIGoalWeight*10 or 10) )
end
)
--when a player drops the flag
OnFlagDrop(
function(holoPtr, carrierObj)
show("")
show("OnFlagDrop")
--if objective is complete, then return
if self.isComplete then return end
local flagName = GetEntityName(holoPtr)
--make sure its the objective flag
if self.flag ~= flagName then return end
--stop, reset, and hide the flag capture timer
StopTimer("captureTimer")
SetTimerValue("captureTimer", self.captureTime or 120)
ShowTimer(nil)
--Note: unit is dead, so no need to remove the powerups
--remove the carrier's unit powerups
local unit = GetCharacterUnit(carrierObj)
RemovePowerUps(unit)
--store the last carrier incase the carrier was TKed
self.lastCarrier = self.carrier
--no more flag carrier
self.carrier = nil
--send out flag dropped text and voice message
FlagMessage(GetCharacterTeam(carrierObj), "dropped")
--update flag's ingame map marker
UpdateMarkerPulses(self.flag)
--get the holocron object
local flagPtr = GetObjectPtr(self.flag)
assert(flagPtr, "ERROR: flag does not exist in the map")
--clear the current AI Holocron goals
local a
for a = 1, table.getn(self.goals) do
DeleteAIGoal( self.goals[a] )
end
--clear the old goal handlers
self.goals = {}
--tell 40% of the AI to go after the Holocron. Hopefully, one of them will run over it and pick it up.
table.insert( self.goals, AddAIGoal(self.teamATT, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Follow", self.AIGoalWeight*40 or 40, holoPtr) )
--tell 20% of the AI to attack any enemies coming near the Holocron
table.insert( self.goals, AddAIGoal(self.teamATT, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Defend", self.AIGoalWeight*20 or 20, holoPtr) )
--tell 10% of the AI go go to the enemy bases and attack
--this is to send troops to slow down the enemy from reaching the Holocron.
table.insert( self.goals, AddAIGoal(self.teamATT, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
table.insert( self.goals, AddAIGoal(self.teamDEF, "Conquest", self.AIGoalWeight*10 or 10, holoPtr) )
end
)
--when the a team's points change
OnTeamPointsChange(
function (team, points)
show("")
show("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
self:Complete(team)
end
end
)
--kill a unit if he/she TKs the holocron carrier
OnCharacterDeath(
function( dead, killer )
--if the dead player did not have the holocron, leave the event
--Note: most units will fail this test, so it is put first
if dead ~= self.lastCarrier then return end
show("OnCharacterDeath, last carrier killed")
--if not on same team, leave event
if GetCharacterTeam(dead) ~= GetCharacterTeam(killer) then return end
--Note: it may be possible to trick this TK carrier killer function. See the commented out OnCharacterSpawn()
--the played who died was the last flag carrier and he/was Tked, so kill the killer
ScriptCB_PlayerSuicide(killer)
end
)
--Note: this is needed to prevent the a Tker from dying when he/she kills the player
-- who last held the flag (that player has since respawned and no longer carriers the flag).
-- There is a risk that the game may be busy and the last carrier player
-- respawns before the Tker can be killed. In which case, the Tker
-- will get away with murder.
--Note2: On second thought, this will just slow the game even more. Why not
-- let the Tker die? He/she shouldn't be Tking players anyway. Some
-- Tkers are in for surprising sudden deaths
--Note3: Modders, if you want to prevent this little glitch and enable an even
-- smaller glitch, uncomment the following OnCharacterSpawn()
--if the player who was holding the flag has respawned, clear last holocron carrier var.
--OnCharacterSpawn(
-- function( player )
-- if player == self.lastCarrier then
-- self.lastCarrier = nil
-- end
-- end
--)
end
-----------------------------------------------------
-- Sound cues for events
gSoundEventsCTF_src = {
all = {
returned_att = "all_allFlag_returned",
returned_def = "all_impFlag_returned",
captured_att = "all_allFlag_score",
captured_def = "all_impFlag_score",
taken_att = "all_1Flag_take_all",
taken_def = "all_1Flag_take_imp",
dropped_att = "all_1Flag_drop_all",
dropped_def = "all_1Flag_drop_imp",
},
imp = {
returned_att = "imp_impFlag_returned",
returned_def = "imp_allFlag_returned",
captured_att = "imp_impFlag_score",
captured_def = "imp_allFlag_score",
taken_att = "imp_1Flag_take_imp",
taken_def = "imp_1Flag_take_all",
dropped_att = "imp_1Flag_drop_imp",
dropped_def = "imp_1Flag_drop_all",
},
rep = {
returned_att = "rep_repFlag_returned",
returned_def = "rep_cisFlag_returned",
captured_att = "rep_repFlag_score",
captured_def = "rep_cisFlag_score",
taken_att = "rep_1Flag_take_rep",
taken_def = "rep_1Flag_take_cis",
dropped_att = "rep_1Flag_drop_rep",
dropped_def = "rep_1Flag_drop_cis",
},
cis = {
returned_att = "cis_cisFlag_returned",
returned_def = "cis_repFlag_returned",
captured_att = "cis_cisFlag_score",
captured_def = "cis_repFlag_score",
taken_att = "cis_1Flag_take_cis",
taken_def = "cis_1Flag_take_rep",
dropped_att = "cis_1Flag_drop_cis",
dropped_def = "cis_1Flag_drop_rep",
},
}[/code]
Jump to
- Site Rules: Please Read Before Posting
- ↳ Site Rules
- Star Wars Battlefront Series
- ↳ SWBF2 General
- ↳ SWBF2 Modding
- ↳ SWBF2 Map/Mod Works In Progress
- ↳ SWBF2 Released Maps & Mods
- ↳ 3D Modeling & Animation
- ↳ All things SWBF1
- ↳ Released Assets
- Gametoast Hosted Mods -- Battlefront Series
- ↳ SWBF1 Conversion Pack
- ↳ The Dark Times
- ↳ SWBF2 Xbox Mod
- ↳ SWBF2 PSP Mod
- Gametoast Site And Clan Discussion
- ↳ [GT] Gametoast Clan (all games)
- ↳ Feedback for Gametoast
- Other Games
- ↳ Game Modding - Other
- ↳ Game Discussion - Other
- ↳ Steam Games
- Miscellaneous
- ↳ Star Wars General Discussion
- ↳ Off-Topic...
- ↳ Media Forum
- ↳ Technical Advice and Tutorials
- ↳ Destiny of the Galaxy Mod
- ↳ Crysis - Discussion & Editing
- ↳ Jedi Knight Series - Discussion & Editing
- ↳ Gametoast Competitions
- ↳ Saga Of The 607th Mod
- ↳ The Dynamic Project
- ↳ Last Days
- ↳ Battlefront Zer0
- ↳ Minecraft Gaming & Modding
- ↳ Minecraft Modding
- ↳ Minecraft General
- ↳ Xbox Live
