Page 1 of 1

AI Playing as Heroes

Posted: Tue Jan 08, 2013 2:23 am
by Glitch25
During the campagin General Grevious appears as a bot as well as a few other heroes. I've gone through the mission files but I could not find any line of code that allowed or disallowed AI heroes so I assumed it had to be within the odf files.

I thought "com_jedi_default" would be the key to it. But it is not. I'm aware that Archer01 released a lua that allowed AI to play as Heroes at one point. I doubt I could learn anything from that, it was munged upon release. Now I'm at a standstill on this matter.

Does anyone know how to let the AI play as the heroes?

Re: AI Playing as Heroes

Posted: Tue Jan 08, 2013 2:31 am
by yuke5
A script actually was released.
Hidden/Spoiler:
-----------------------------------------------------------------
-----------------------------------------------------------------
-- AIHeroSupport Script by T. Simpson
-- Version 1.2
-- Screen Names: Archer01, Theodranis
-- E-mail: [email protected]
-- Sept 24, 2006
-- Copyright (c) 2006 T. Simpson.

-- About this script: This was my attempt to correct something
-- that I thought was fundementaly "broken" with StarWars BattleFront 2,
-- and that would be the AI never using the heroes.

-- Please note: Several times along the way I found out I couldn't do
-- something I needed to, or a function didn't return anything when it "should"
-- have (all the other functions similar to it do) so I had to find a work-around
-- solution, the result is a somewhat messy script.

-- Usage:
-- During ScriptPostLoad():
-- Create Object (and override variables)
-- Set Hero Classes using the special function (be sure to remove the original SetHeroClass() commands from your script)
-- Set spawn CPs
-- Call Start()

-- NOTE: For ADVANCED scripters only:
-- This script assumes that the ATT team is always 1 and DEF is always 2
-- This can be changed however by overriding the teamATT and teamDEF variables when :New() is called
-- But because the game's scripts also assume ATT == 1 and DEF == 2 it is suggested that this feature be left alone


-- Legal Stuff:
-- You are welcome to use this script in your custom made mods and maps so long as they are not being rented or sold.
-- If you use this script, please credit me in the readme of the project you used it in.
-- Do not claim this script as your own. It may not be much, but I did spend some time writing it after all.
-- Do not edit this script.
-- If you need to override any of the variables, please do so from your own script. Do not edit this one.
-- I am not responsible for any damages that might be incurred through the use of this script.
-- THIS SCRIPT IS NOT MADE, DISTRIBUTED, OR SUPPORTED BY LUCASARTS, A DIVISION OF LUCASFILM ENTERTAINMENT COMPANY LTD.
-----------------------------------------------------------------
-----------------------------------------------------------------

AIHeroSupport = nil --Force garbage collection (just in case)

AIHeroSupport =
{
-- Basic team defaults --
teamATT = 1,
teamDEF = 2,
--------------------

-- Scripters can override these variables from their script --
AIATTHeroHealth = nil,
AIDEFHeroHealth = nil,

disableInNetGame = false,

initSpawnTime = 10,
minSpawnTime = 25,
minAfterHuman = 25,

cycleTime = 10,
netCycleTime = 20,

gameMode = nil,
spawnHero = true,

botImmuneHeroes = false,
botDamageThreshold = 0.3,

enforceSingleHero = false, --Does a lot more "loop" work, but ensures that only one hero is present
--------------------

-- These variables should NOT be overwritten --
isConquest = false,
infiniteReforceBound = 2000000000, --Bounding number used to identify infinite reinforcements
AIHeroCycleTimer = nil,
cpList = {},
heroClassIndexList = {},
heroEntityList = {},
heroClassNameList = {},
botCount = nil,
cpAdded = false,
hasStarted = false,
shouldHeroSpawnTeam = {},
HeroSpawnTimer = {},
safetySpawnTime = 2,
recentAIHero = {},
--------------------
}

-- Version ID Number (for version detection) --
__AIHeroSupport_LUA__ = 3

-- Object Creation Function --
function AIHeroSupport:New(o)
o = o or {}
setmetatable(o,self)
self.__index = self
return o
end

--- SET HERO CLASS AND RECORD CLASS INDEX FOR LATER ---
function AIHeroSupport:SetHeroClass(teamPtr,className)

if self.hasStarted then
self:PrintError("Error!: SetHeroClass cannot be used if the hero script has already started")
return false
end

SetHeroClass(teamPtr, className)
local heroIndex = (GetTeamClassCount(teamPtr) - 1)
self.heroClassIndexList[teamPtr] = heroIndex

self.heroClassNameList[teamPtr] = className

return heroIndex
end

--- Error message for user debug ---
function AIHeroSupport:PrintError(msg)
print(" ")
print("_______!!!AIHeroSupport ->", msg)
end

--- ADD SPAWN FUNCTION ---
function AIHeroSupport:AddSpawnCP(cpName,pathName)
local tempCPPtr = GetObjectPtr(cpName)
local tempPathPtr = GetPathPoint(pathName, 0)

--print("!!!!!!!!!!!Hero: CPVal returned >", tempCPPtr," PathPointReturned >",tempPathPtr)

if not tempCPPtr then
self:PrintError("Warning!: Invalid CP > " .. cpName)
elseif not tempPathPtr then
self:PrintError("Warning!: Invalid path > " .. pathName)
else
self.cpList[cpName] = pathName
self.cpAdded = true
end
end

-- Allows enabling and disabling of AI hero spawn --
function AIHeroSupport:EnableHeroes(inVal)
self.spawnHero = inVal
end

function AIHeroSupport:EnableHeroTeam(teamPtr,inVal)
if teamPtr then
self.shouldHeroSpawnTeam[teamPtr] = inVal
end
end

--- Sets the bot count ---
function AIHeroSupport:SetBotCount(amount)
local sizeATT = GetUnitCount(self.teamATT)
local sizeDEF = GetUnitCount(self.teamDEF)

if sizeATT < amount then
self:PrintError("Warning!: Bot count larger than ATT unit count")
end

if sizeDEF < amount then
self:PrintError("Warning!: Bot count larger than DEF unit count")
end

if amount then
if amount >= 1 then
ScriptCB_SetNumBots(amount - 1)
self.botCount = amount
elseif amount == 0 then
ScriptCB_SetNumBots(0)
self.botCount = 0
else
self:PrintError("Error!: Invalid bot count setting")
end
end
end

---- MAIN START FUNCTION ----
function AIHeroSupport:Start()

--Doesn't run a second time
if self.hasStarted then return end

if ScriptCB_InNetGame() then
if self.disableInNetGame then return end
self.cycleTime = self.netCycleTime
end

--Init special vars here
self.shouldHeroSpawnTeam[self.teamATT] = true
self.shouldHeroSpawnTeam[self.teamDEF] = true

------ Local functions (just following the convention of the game developers ------
local getValidSpawnPath = function(teamPtr)
local pathList = {}
local cpCount = 0
--local pathPtr = nil

for cp,path in pairs(self.cpList) do
--print("!!!!!!!!!!!Hero: Spawn test CP", cp," Path", path)
if IsObjectAlive(cp) then
--print("!!!!!!!!!!!Hero: Spawn test CP", cp," Path", path, " CPTEAM", GetObjectTeam(cp))
if GetObjectTeam(cp) == teamPtr then
--print("!!!!!!!!!!!Hero: Path gotten >>", path)
cpCount = cpCount + 1
pathList[cpCount] = path
end
end
end

--print("!!!!!!!!!!!Hero: Number of valid paths >", cpCount,"TEAM >", teamPtr)

if cpCount == 1 then
--Just get the first entry, skips randomizer
local path = pathList[1]
--print("!!!!!!!!!!!Hero: Single path gotten >>", path, "TEAM >", teamPtr)
return path
elseif cpCount >= 2 then
local cpIndex = math.random(1,cpCount)
local path = pathList[cpIndex]
--print("!!!!!!!!!!!Hero: Random path gotten >>", path, "TEAM >", teamPtr)
return path
end

--print("!!!!!!!!!!!Hero: No valid path found TEAM >", teamPtr)
return false
end

local removeAllBotHeroes = function(teamPtr)
local heroIndex = self.heroClassIndexList[teamPtr]
if heroIndex then
local teamSize = GetTeamSize(teamPtr)
for i = 0, (teamSize-1) do
local characterIndex = GetTeamMember(teamPtr, i)
if characterIndex then
local charClass = GetCharacterClass(characterIndex)
if charClass then
if charClass == heroIndex then
if not IsCharacterHuman(characterIndex) then
local characterUnit = GetCharacterUnit(characterIndex)
if characterUnit then
KillObject(characterUnit)
end
end
end
end
end
end
end
end

local spawnChar = function(teamPtr, characterIndex, charClass)
if not characterIndex then return false end
local spawnPathName = getValidSpawnPath(teamPtr)
if not spawnPathName then return false end --Error check
local spawnNode = GetPathPoint(spawnPathName, 0)
--if not spawnNode then return end
--if spawnPathName then
if spawnNode then
--print("!!!!!!!!!!!Hero: TEST 2")
local charUnit = GetCharacterUnit(characterIndex)
--print("!!!!!!!!!!!Hero: Activate unit >>", characterIndex)
if not charUnit then
if charClass then
SelectCharacterClass(characterIndex, charClass)
end
SpawnCharacter(characterIndex, spawnNode)
local charUnit = GetCharacterUnit(characterIndex)
if charUnit then
if teamPtr == self.teamATT then
if self.AIATTHeroHealth then
SetProperty(charUnit,"MaxHealth", self.AIATTHeroHealth)
SetProperty(charUnit,"CurHealth", self.AIATTHeroHealth)
--print("!!!!!!!!!!!Hero: Attack hero health set")
end
elseif teamPtr == self.teamDEF then
if self.AIDEFHeroHealth then
SetProperty(charUnit,"MaxHealth", self.AIDEFHeroHealth)
SetProperty(charUnit,"CurHealth", self.AIDEFHeroHealth)
--print("!!!!!!!!!!!Hero: Defend hero health set")
end
end

if self.botImmuneHeroes and self.botDamageThreshold then
SetAIDamageThreshold(charUnit, self.botDamageThreshold)
end

--print("!!!!!!!!!!!Hero: Special spawned ", characterIndex, " at node", spawnNode, "Class", GetCharacterClass(characterIndex), " VERIFY >", charUnit)
return true
end
end
end
return false
end

local getUnspawnedBot = function(teamPtr)
local teamSize = GetTeamSize(teamPtr)

if self.botCount then
if self.botCount <= 0 then
return false
end
end

for i = 0, (teamSize-1) do
local characterIndex = GetTeamMember(teamPtr, i)
--print("!!!!!!!!!!!Hero: Checking index >>", characterIndex)
if characterIndex then
if not IsCharacterHuman(characterIndex) then
local characterUnit = GetCharacterUnit(characterIndex)
if not characterUnit then
return characterIndex
end
end
end
end

return false
end

local activateHeroSameTeam = function(teamPtr)

if not self.spawnHero then return end

local characterIndex = self.heroEntityList[teamPtr]
local heroIndex = self.heroClassIndexList[teamPtr]

--if not heroIndex then return end

if characterIndex then
if GetCharacterClass(characterIndex) == heroIndex then
local characterUnit = GetCharacterUnit(characterIndex)
if characterUnit then
--print("!!!!!!!!!!!Hero: Hero actiavtion skipped >>", characterIndex)
return
end
end
end

--Spawn code here
local newHeroIndex = getUnspawnedBot(teamPtr)
if newHeroIndex then
local spawned = spawnChar(teamPtr,newHeroIndex,heroIndex)
if spawned then
self.heroEntityList[teamPtr] = newHeroIndex
self.recentAIHero[newHeroIndex] = true
--print("!!!!!!!!!!!Hero: Hero actiavtion complete >>", newHeroIndex)
end
end
end

local deactivateHeroSameTeam = function(teamPtr)
local characterIndex = self.heroEntityList[teamPtr]
local heroIndex = self.heroClassIndexList[teamPtr]

--if not heroIndex then return end

if not characterIndex then return end --Skip if no hero is active
if GetCharacterClass(characterIndex) == heroIndex then
local characterUnit = GetCharacterUnit(characterIndex)
self.heroEntityList[teamPtr] = nil
if characterUnit then
--This check on isConquest is not really needed, but there for safety
if self.isConquest then
--This check is to handle the 'infinite' reinforcement count
--Avoids overflow and automatic defeat
if GetReinforcementCount(teamPtr) < self.infiniteReforceBound then
AddReinforcements(teamPtr, 1)
--print("!!!!!!!!!!!Hero: REFORCE POINT ADDED!")
end
end
KillObject(characterUnit)
--print("!!!!!!!!!!!Hero: Hero killed due to deactivation >>", characterIndex)
end
end
end

local humanHeroActive = function(teamPtr)
local teamSize = GetTeamSize(teamPtr)
for i = 0, (teamSize-1) do
local characterIndex = GetTeamMember(teamPtr, i)
if IsCharacterHuman(characterIndex) then
local charClass = GetCharacterClass(characterIndex)
if charClass then
if self.heroClassIndexList[teamPtr] == charClass then
--print("!!!!!!!!!!!Hero: Human Hero Unit", characterIndex," found as class", charClass, " Team >", teamPtr)
return true
end
end
end

end
--print("!!!!!!!!!!!Hero: No Human Hero Unit Team >", teamPtr)
return false
end

local verifySingleHero = function(teamPtr)
if humanHeroActive(teamPtr) then
removeAllBotHeroes(teamPtr)
else
local heroEntity = self.heroEntityList[teamPtr]
if heroEntity then
local heroIndex = self.heroClassIndexList[teamPtr]
local teamSize = GetTeamSize(teamPtr)
for i = 0, (teamSize-1) do
local characterIndex = GetTeamMember(teamPtr, i)
if characterIndex then
if not IsCharacterHuman(characterIndex) then
if characterIndex ~= heroEntity then
local charClass = GetCharacterClass(characterIndex)
if charClass then
if charClass == heroIndex then
local characterUnit = GetCharacterUnit(characterIndex)
if characterUnit then
KillObject(characterUnit)
--print("!!!!!!!!!!!Hero: Extra hero found and removed Team >", teamPtr)
end
end
end
end
end
end
end
else
removeAllBotHeroes(teamPtr)
end
end
end

local cycleTimerTest = function(teamPtr)
local heroIndex = self.heroClassIndexList[teamPtr]
if heroIndex then
--print("!!!!!!!!!!!Hero: Timer test1")
if humanHeroActive(teamPtr) then
deactivateHeroSameTeam(teamPtr)
--print("!!!!!!!!!!!Hero: Hero cycle-deactivated")
else
if self.shouldHeroSpawnTeam[teamPtr] then
local characterIndex = self.heroEntityList[teamPtr]

if characterIndex then
if GetCharacterClass(characterIndex) == heroIndex then
local charUnit = GetCharacterUnit(characterIndex)
if not charUnit then
StartTimer(self.HeroSpawnTimer[teamPtr])
--print("!!!!!!!!!!!Hero: Spawn Timer Cycle-Started")
end
else
StartTimer(self.HeroSpawnTimer[teamPtr])
--print("!!!!!!!!!!!Hero: Spawn Timer Cycle-Started")
end
else
StartTimer(self.HeroSpawnTimer[teamPtr])
--print("!!!!!!!!!!!Hero: Spawn Timer Cycle-Started")
end
end
end

if self.enforceSingleHero then
verifySingleHero(teamPtr)
--print("!!!!!!!!!!!Hero: Enforce called >>", teamPtr)
end

end
end

local initHeroCycleTimer = function()
self.AIHeroCycleTimer = CreateTimer("AIHeroCycleTimer")
SetTimerValue(self.AIHeroCycleTimer, self.cycleTime)

OnTimerElapse(
function(timer)
--print("!!!!!!!!!!!Hero: TIMER CALLBACK!")
StopTimer(self.AIHeroCycleTimer)

-- Other code here
cycleTimerTest(self.teamATT)
cycleTimerTest(self.teamDEF)

SetTimerValue(self.AIHeroCycleTimer, self.cycleTime)
StartTimer(self.AIHeroCycleTimer)
end,
self.AIHeroCycleTimer
)

StartTimer(self.AIHeroCycleTimer)
end

local createSpawnCallbacks = function(teamPtr)

OnTimerElapse(
function(timer)
--print("!!!!!!!!!!!Hero: Hero spawn timer finished", teamPtr)
StopTimer(self.HeroSpawnTimer[teamPtr])
SetTimerValue(self.HeroSpawnTimer[teamPtr], self.safetySpawnTime)

if not humanHeroActive(teamPtr) then
if self.shouldHeroSpawnTeam[teamPtr] then
--print("!!!!!!!!!!!Hero: Hero activated >>", teamPtr)
activateHeroSameTeam(teamPtr)
end
end
end,
self.HeroSpawnTimer[teamPtr]
)

OnCharacterDeathTeam(
function(character,killer)
local charClass = GetCharacterClass(character)
--if charClass then
if charClass == self.heroClassIndexList[teamPtr] then
StopTimer(self.HeroSpawnTimer[teamPtr])
--print("!!!!!!!!!!!Hero: Hero died >>", character,"Team >>",teamPtr)
if IsCharacterHuman(character) then
SetTimerValue(self.HeroSpawnTimer[teamPtr], self.minAfterHuman)
--print("!!!!!!!!!!!Hero: Hero timer set for humanTime >>", teamPtr)
else
SetTimerValue(self.HeroSpawnTimer[teamPtr], self.minSpawnTime)
--print("!!!!!!!!!!!Hero: Hero timer set for minSpawn >>", teamPtr)
end
StartTimer(self.HeroSpawnTimer[teamPtr])
end
--end
end,
teamPtr
)

end

local initBotCountProtect = function(teamPtr)
OnCharacterSpawnTeam(
function(character)
if self.recentAIHero[character] then
local charClass = GetCharacterClass(character)
if charClass ~= self.heroClassIndexList[teamPtr] then
--This check on isConquest is not really needed, but there for safety
if self.isConquest then
--This check is to handle the 'infinite' reinforcement count
--Avoids overflow and automatic defeat
if GetReinforcementCount(teamPtr) < self.infiniteReforceBound then
AddReinforcements(teamPtr, 1)
--print("!!!!!!!!!!!Hero: REFORCE POINT ADDED!")
end
end
local charUnit = GetCharacterUnit(character)
KillObject(charUnit)
self.recentAIHero[character] = nil
--print("!!!!!!!!!!!Hero: Recent hero spawn killed >>", character)
end
end
end,
teamPtr
)
end


------ Actual function ------
--print("!!!!!!!!!!!Hero: STARTED!")

--Class check should take 0,1, or 2 heroes into account
OnCharacterChangeClass(
function(character)
--print("!!!!!!!!!!!Hero: CLASSCHANGE CALLBACK!")

--Ignore AI since they can't be heroes normally
if not IsCharacterHuman(character) then return end

--print("!!!!!!!!!!!Hero: Human class change!")

--Check class and do what is needed
local charTeam = GetCharacterTeam(character)
local charClass = GetCharacterClass(character)

if charTeam == self.teamATT then
if charClass == self.heroClassIndexList[self.teamATT] then
deactivateHeroSameTeam(self.teamATT)
--print("!!!!!!!!!!!Hero: Attack hero deactivated")
end
elseif charTeam == self.teamDEF then
if charClass == self.heroClassIndexList[self.teamDEF] then
deactivateHeroSameTeam(self.teamDEF)
--print("!!!!!!!!!!!Hero: Defense hero deactivated")
end
end
end
)

--Hero cycle timer (callback in function)
initHeroCycleTimer()

initBotCountProtect(self.teamATT)
initBotCountProtect(self.teamDEF)

--Checks gameMode and stops hero spawn if AI count is zero
if self.gameMode then
local numBots = nil
local modeString = string.lower(self.gameMode)

if modeString == "conquest" then
self.isConquest = true
numBots = ScriptCB_GetCONNumBots()
elseif modeString == "ctf" then
numBots = ScriptCB_GetCTFNumBots()
elseif modeString == "assault" then
numBots = ScriptCB_GetASSNumBots()
elseif modeString == "hunt" then
numBots = ScriptCB_GetASSNumBots()
elseif modeString == "xl" then
self.gameMode = nil
numBots = nil
elseif modeString == "conqueststyle" then
self.isConquest = true
self.gameMode = nil
numBots = nil
elseif modeString == "uberconquest" then
self.isConquest = true
self.gameMode = nil
numBots = nil
elseif modeString == "nonconquest" then
self.gameMode = nil
numBots = nil
else
self.gameMode = nil
numBots = nil
self:PrintError("Warning!: Gamemode not recoginized")
end

self.botCount = numBots
--print("!!!!!!!!!!!Hero: Number of bots set >>", self.botCount)

if numBots then
self:SetBotCount(numBots)
end


end

-- Check for CPs
if not self.cpAdded then
self:PrintError("Warning!: No spawn CP added")
end


if self.minSpawnTime then

if self.minSpawnTime < 1 then
self.minSpawnTime = 15
self:PrintError("Warning!: minSpawnTime was set to an invalid value, resetting to 15 seconds")
end


self.HeroSpawnTimer[self.teamATT] = CreateTimer("ATTHeroTimer")
self.HeroSpawnTimer[self.teamDEF] = CreateTimer("DEFHeroTimer")

SetTimerValue(self.HeroSpawnTimer[self.teamATT], self.initSpawnTime)
SetTimerValue(self.HeroSpawnTimer[self.teamDEF], self.initSpawnTime)

if self.heroClassIndexList[self.teamATT] then
createSpawnCallbacks(self.teamATT)
StartTimer(self.HeroSpawnTimer[self.teamATT])
end

if self.heroClassIndexList[self.teamDEF] then
createSpawnCallbacks(self.teamDEF)
StartTimer(self.HeroSpawnTimer[self.teamDEF])
end


else
self:PrintError("Error!: No minSpawnTime set")
end


self.hasStarted = true

end --(End of Start())
Load this script via LUA.

Then, just follow his tutorial. Load whatever heroes you want, custom or not.
Hidden/Spoiler:
-----------------------------------------------------------------------------------------------------

---------- Hero Support Script for StarWars: BattleFront 2 ----------
Version 1.2

Script by T. Simpson
Screen names: Archer01 or Theodranis
Email: [email protected]
Date: Sept 26, 2006

This script adds AI hero support to a custom or modded map.

Sample scripts have been included to show how it works. The Conquest sample has a bunch of comments explaining everything. The CTF version does not include the comments, so it is a better example of how your script should "look".

Good luck!

Sample scripts:
Example_con.lua -- Commented sample
Example_ctf.lua -- Uncommented sample
Display_Fix.lua -- Display fix sample (see below for details)



Note: Do NOT edit the AIHeroSupport script. Override variables from your own script if needed. If you find a bug, please inform me so that I may fix it.

-----------------------------------------------------------------------------------------------------

***Tutorial:

These are the steps you need to follow to add the script to your map...

*Setting up the script so your map lua can use it:

1- Go into the "\Common" folder for your map
2- Find the "mission.req" file and open it in a text/script editor
3- You should see a few lists of items each contained in quotaion marks
4- Find the list that begins with "script"
5- Add "AIHeroSupport" to the end of the script list
6- Save and close the file
7- Copy the "AIHeroSupport.lua" file into your map's "\Common\scripts" folder
8- The script can now be used in your map's lua

*Setting up your map's lua:

1- Open your map's lua file in text/script editor
2- You will see a bunch of "ScriptCB_DoFile(something here)" commands at the top
3- Add this just after them:

ScriptCB_DoFile("AIHeroSupport")

4- Now further down in the script find the line that says something like "conquest:Start()" or "ctf:Start()". Right after this line is where the hero support code should be added...
5- First add this line:

herosupport = AIHeroSupport:New{AIATTHeroHealth = 5000, AIDEFHeroHealth = 3000, gameMode = "NonConquest",}

- Note: The stuff in the curly braces are the different settings the script uses. It is a list of variables seperated by commas. All the variables you can set here have default settings, so if you don't set a variable yourself the default setting is used. See below for a list of the variable names and what they do. Variable names ARE case sensitive.

6- After adding that line, you then set your hero classes using:

herosupport:SetHeroClass(team, "heroClassName")

-Note: If you have more than 7 unit types (including the hero type) on a side, the info boxes for them will not be sized properly during gameplay (the list will go off the end of the screen). There is an easy fix for this. Finish the tutorial, then read the section below relating to this problem.

7- After setting the hero classes, you then need to tell the script the names of the CPs and spawn paths it should use for the heroes. Do that by adding a line like the following for every CP that you want the heroes to be able to spawn at:

herosupport:AddSpawnCP("CPname","SpawnPathNameForTheCP")

8- After all the CPs have been added, add this line:

herosupport:Start()

9- Now this is a VERY important part, the "SetHeroClass" function can only be used once for each team. If it is used a second time, nasty stuff will likely happen. Go through the script and remove all uses of the "SetHeroClass" function, except for the two you added earlier of course, so there won't be any problems. Your final script should have at most only two (2) mentions of "SetHeroClass". Don't forget about your text editor's search function when making sure this is so.

10- That's it. Munge your map, and try it out!

-----------------------------------------------------------------------------------------------------

***Unit List Display Issue

When more than 7 unit types are available for selection (ie more than the standard 6 normal and 1 hero), the display boxes in the spawn screen will not be sized correctly if the code block described above is left that way. There are a variety of ways to fix this, but the simplest (and most practical) is as follows:

1- Start with the first three (3) lines of the hero code block -> the "AIHeroSupport:New{}" and the two "herosupport:SetHeroClass()" lines.

2- Now simply CUT those three lines, and paste them at the very end of the "ScriptInit()" function. If you don't know where that spot is... It is just after the "AddCameraShot()" function calls, but just before the "end" statement at the bottom of the file (that "end" statement marks the end of the function). That will fix the display problem.

Note: Make sure you move ONLY those three lines. The "AddSpawnCP" and "Start" functions may not (and likely won't) work correctly if you move them too. Leave those lines where they are.

See the packaged sample script if you need an example.

-----------------------------------------------------------------------------------------------------

***Script Variable List:

Variable name: gameMode
- Possible values: (possible values below)
- Default = "NonConquest"
This should be set to the gameMode the map is using. It can be set to any of the following:

"Conquest" -- Uses the bot count from the Conquest map select settings
"ConquestStyle" -- Like Conquest, but ignores bot count settings
"UberConquest" -- Use this if it is a conquest map that uses UberMode
"CTF" -- Uses the bot count from the CTF map select settings
"Assault" -- Uses the bot count from the Assault map select settings
"Hunt" -- Uses the bot count from the Hunt map select settings
"xl" -- Uses this if it is an XL map that uses points
"NonConquest" -- Like any non-conquest, but ignores bot count settings

NOTE: For saftey sake, only use the conquest-related gamemodes if the map tracks/uses the reinforcement count. For maps that use team "points" use the other modes.


Variable name: AIATTHeroHealth
- Possible values: (a number)
- Default = the hero unit's normal health
The health the attacking team's bot hero should have (does not affect human hero's health). If this variable is not set, the hero's normal health is used.

Variable name: AIDEFHeroHealth
- Possible values: (a number)
- Default = the hero unit's normal health
Same, but for the defender's hero.

Variable name: minSpawnTime
- Possible values: (a number in seconds)
- Default = 25 seconds
The minmal delay between a bot Hero death and it's respawn. This is only the "minimum" amount of time. Usually the bot will spawn in just fine, but not every spawn attempt will end successfully. In the unsuccessful case (team full, unit memory not fully cleared, etc), it may take a little longer for the actual spawn to occur.

Variable name: initSpawnTime
- Possible values: (a number in seconds)
- Default = 10 seconds
This is like minSpawnTime but is only used once at the start of the match. This is how long from match-start before the first bot hero spawn attempt.

Variable name: minAfterHuman
- Possible values: (a number in seconds)
- Default = 25 seconds
This is like minSpawnTime but is used after a human controlled hero dies.

Variable name: botImmuneHeroes
- Possible values: (true or false)
- Default = false
Make it so the bot heroes can only be killed by a human player.

Variable name: botDamageThreshold
- Possible values: (a number between 0 and 1)
- Default = 0.3
If botImmuneHeroes is set to true, this is how much health the hero unit will have remaining before it stops taking damage from other bots. It is represented as a percentage (example: 0.3 == 30% health remaining).

Variable name: disableInNetGame
- Possible values: (true or false)
- Default = false
Disables the AI Hero Support aspect if it is a multiplayer match. When disabled this way, the AIHeroSupport script never starts.

-----------------------------------------------------------------------------------------------------

***Global Functions (can be used at any time):

Function name -> AIHeroSupport:New{}
Returns the hero support script object reference.


***Object Functions (functions that can be used anytime AFTER New{} is called):

Function name -> objectName:AddSpawnCP(cpName,pathName)
Adds the CP and associated spawn path data to the script's list.

Function name -> objectName:Start()
Starts the hero script. Only use this once.

Function name -> objectName:EnableHeroes(boolean)
Use true or false. Enables or disables the AI hero spawn for both teams.

Function name -> objectName:EnableHeroTeam(teamPtr,inVal)
Enables or disables the AI hero spawn for the specified team. Use true or false for inVal.


***Special case Object Functions (functions that can be used AFTER New{} is called):

Function name -> objectName:SetHeroClass(teamPtr,className)
Sets the hero class className for teamPtr and records necessary information needed to run the script.
NOTE: This has to be used BEFORE the "Start()" function call. It will not work correctly if used afterwards.

-----------------------------------------------------------------------------------------------------

Known glitches:
- The AI heroes will still spawn even when heroes are disabled in the game options. The human players will not be able to play as the heroes, but the hero unit will still be on the map as a bot. I'm not sure if this can be fixed... (I'm also not sure if I want this "fixed")



Known bugs (things like crashing, stuff that can cause problems with gameplay, etc):
- None that I know of.

-----------------------------------------------------------------------------------------------------

***Legal Stuff:
You are welcome to use this script in your custom made mods and maps so long as they are not being rented or sold. If you use this script, please credit me in the readme of the project you used it in. Do not claim this script as your own (it may not be much, but I did spend some time writing it after all). Do not edit this script. If you need to override any of the variables, please do so from your own script. I am not responsible for any damages that might be incurred through the use of this script.

THIS SCRIPT IS NOT MADE, DISTRIBUTED, OR SUPPORTED BY LUCASARTS, A DIVISION OF LUCASFILM ENTERTAINMENT COMPANY LTD.

-----------------------------------------------------------------------------------------------------




-----------------------------------------------------------------------------------------------------

***STUFF FOR ADVANCED SCRIPT-WRITERS ONLY:

*** VARIBALE LIST ***
***NOTE: It is very unlikely that you will need to change the following variables (so don't unless you know what you're doing)...

Variable name: cycleTime
- Possible values: (a number in seconds)
- Default = 10
How often the script looks for heroes on the map. When the cycleTime has passed, the script checks the units for hero status. If the script happened to not catch a human changing to a hero class (thus resulting in the AI hero never being removed), the AI hero will also be removed at this time. This check does a lot of "loop" work (may slow down a map if done too often). NOTE: This is just here as an extra option for flexability, I would suggest you leave this variable alone.

Variable name: netCycleTime
- Possible values: (a number in seconds)
- Default = 20
Same as the cycleTime but is used in multiplayer games. NOTE: Also just like cycleTime, this is just here as an extra option for flexability, I would suggest you leave this variable alone.

Variable name: enforceSingleHero
- Possible values: (true of false)
- Default = false
Considering the way I setup the script, this option is not really needed, but I decided to have it available "just in case". When enabled, this option makes the cycle test more comprehensive when looking for heroes on the map. Usually it will remove all bot controlled hero units except for one. If a hero is human controlled, it will remove all bot controlled heroes from the map. This check is executed as part of the "cycle test". The ONLY time this should be enabled is if you see more than one of the AI units using the hero at once, and on more than one occasion. This test does a lot of "loop" work so it might be a problem on slower computers.

*** FUNCTION LIST ***

Function name -> objectName:SetBotCount(number)
Overrides and sets the bot count to be used. This setting is applied to all teams (that's the way it works in the game).
!!! Note: The Start() function sets the bot count itself, so using this function before the script is started won't do anything. Also remember that the conquest, ctf, tdm, etc game scripts set the bot count themselves, so they too will override this function if it is used before them.


-----------------------------------------------------------------------------------------------------
You can download the "kit" here:

http://www.gamefront.com/files/HeroSupp ... einfo.html

Re: AI Playing as Heroes

Posted: Tue Jan 08, 2013 2:50 am
by Glitch25
Fantastic, thanks Yuke5! :D

Re: AI Playing as Heroes

Posted: Tue Jan 08, 2013 2:58 am
by AQT
It was originally released at the following, by the way:
Glitch25 wrote:During the campagin General Grevious appears as a bot as well as a few other heroes. I've gone through the mission files but I could not find any line of code that allowed or disallowed AI heroes so I assumed it had to be within the odf files.
Enemy AI heroes in the stock campaign missions were allowed to spawn the same way the AI are allowed to spawn as hero units in stock Hero Assault. Just because the hero was controlled by an AI doesn't necessarily mean it was spawned the same way where when enough points are needed to unlock it. After all, heroes are just plain-old units.

Re: AI Playing as Heroes

Posted: Sat Jan 12, 2013 6:01 pm
by nobody3
If you just want AI to use heroes (like in hero assault) but in conquest/ctf change "SetHeroClass" into "AddUnitClass"

this also works online if you host your own dedicated server, I tried it

also i did this using hex editing mission.lvl, so using mod tools may not work online(it would work online but only for you I think,not for others)