Team and Hero Decision Evaluation - Nostrademous/Dota2-FullOverwrite GitHub Wiki
-------------------------------------------------------------------------------
--- AUTHOR: Nostrademous
--- GITHUB REPO: https://github.com/Nostrademous/Dota2-FullOverwrite
-------------------------------------------------------------------------------
require( GetScriptDirectory().."/constants" )
local freqTeamThink = 0.1
local lastTeamThink = -1000.0
local teamForcedPlayerAssignments = {}
function MainThink()
-- Exercise TeamThink() at coded frequency
if GameTime() > lastTeamThink then
TeamThink()
lastTeamThink = GameTime() + freqTeamThink
end
-- Exercise individual Hero think at every frame (if possible).
-- HeroThink() will check assignments from TeamThink()
-- for that individual Hero that it should perform, if any.
local bot = GetBot()
return HeroThink(bot)
end
function TeamThink()
-- This is at top as all item purchases are Immediate actions,
-- and therefore won't affect any other decision making.
-- Intent is to smartly determine which heroes should purchases
-- Team items like Tome of Knowledge, Wards, Dust/Sentry, and
-- even stuff like picking up Gem, Aegis, Cheese, etc.
ConsiderTeamWideItemAcquisition()
-- This is at top as all courier actions are Immediate actions,
-- and therefore won't affect any other decision making.
-- Intent is to make courier use more efficient by aligning
-- the purchases of multiple localized heroes together.
ConsiderTeamWideCourierUse()
-- This is a fight orchestration evaluator. It will determined
-- based on the global picture and location of all enemy and
-- friendly units whether we should pick a fight whether in
-- the middle of nowhere, as part of a push/defense of a lane,
-- or even as part of an ally defense. All Heroes involved will
-- have their actionQueues filled out by this function and
-- their only responsibility will be to do those actions. Note,
-- heroes with Global skills (Invoker Sun Strike, Zeus Ult, etc.)
-- can be part of this without actually being present in the area.
ConsiderTeamFightAssignment()
-- Determine which lanes should be pushed and which Heroes should
-- be part of the push.
ConsiderTeamLanePush()
-- Determine which lanes should be defended and which Heroes should
-- be part of the defense.
ConsiderTeamLaneDefense()
-- Determine which hero (based on their role) should farm where. By
-- default it is best to probably leave their default lane assignment,
-- but if they are getting killed repeatedly we could rotate them. This
-- also considers jungling assignments and lane rotations.
ConsiderTeamFarmDesignation()
-- Determine if we should Roshan and which Heroes should be part of it.
ConsiderTeamRoshan()
-- Determine if we should seek out a specific enemy for a kill attempt
-- and which Heroes should be part of the kill.
ConsiderTeamRoam()
-- If we see a rune, determine if any specific Heroes should get it
-- (to fill a bottle for example). If not the hero that saw it will get it.
ConsiderTeamRune()
-- If any of our Heroes needs to heal up, Shrines are an option.
-- However, we should be smart about the use and see if any other
-- friends could benefit as well rather than just being selfish.
ConsiderTeamShrine()
end
function HeroThink(bot)
local highestDesireValue = 0.0
local highestDesireMode = constants.MODE_NONE
local evaluatedDesireValue = BOT_MODE_DESIRE_NONE
-- Consider incoming projectiles or nearby AOE and if we can evade.
-- This is of highest importance b/c if we are stunned/disabled we
-- cannot do any of the other actions we might be asked to perform.
evaluatedDesireValue = ConsiderEvading(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_EVADE
end
-- If we really want to evade ( >= 0.9 ); short-circuit
-- consideration of other modes for better performance.
if evaluatedDesireValue >= BOT_MODE_DESIRE_VERYHIGH then
return highestDesireMode
end
-- Fight orchestration is done at a global Team level.
-- This just checks if we are given a fight target and a specific
-- action queue to execute as part of the fight.
evaluatedDesireValue = ConsiderAttacking(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_FIGHT
end
-- Which Heroes should be present for Shrine heal is made at Team level.
-- This just tells us if we should be part of this event.
evaluatedDesireValue = ConsiderShrine(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_SHRINE
end
-- Determine if we should retreat. Team Fight Assignements can
-- over-rule our desire though. It might be more important for us to die
-- in a fight but win the over-all battle. If no Team Fight Assignment,
-- then it is up to the Hero to manage their safety from global and
-- tower/creep damage.
evaluatedDesireValue = ConsiderRetreating(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_RETREAT
end
-- If we really want to Attack, Use Shrine or Retreat ( >= 0.75 );
-- short-circuit consideration of other modes for better performance.
if evaluatedDesireValue >= BOT_MODE_DESIRE_HIGH then
return highestDesireMode
end
-- Courier usage is done at Team wide level. We can do our own
-- shopping at secret/side shop if we are informed that the courier
-- will be unavailable to use for a certain period of time.
evaluatedDesireValue = ConsiderSecretAndSideShop(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_SPECIALSHOP
end
-- The decision is made at Team level.
-- This just checks if the Hero is part of the push, and if so,
-- what lane.
evaluatedDesireValue = ConsiderPushingLane(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_PUSHLANE
end
-- The decision is made at Team level.
-- This just checks if the Hero is part of the defense, and
-- where to go to defend if so.
evaluatedDesireValue = ConsiderDefendingLane(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_DEFENDLANE
end
-- This is a localized lane decision. An ally defense can turn into an
-- orchestrated Team level fight, but that will be determined at the
-- Team level. If not a fight, then this is just a "buy my retreating
-- friend some time to go heal up / retreat".
evaluatedDesireValue = ConsiderDefendingAlly(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_DEFENDALLY
end
-- Roaming decision are made at the Team level to keep all relevant
-- heroes informed of the upcoming kill opportunity.
-- This just checks if this Hero is part of the Gank.
evaluatedDesireValue = ConsiderRoam(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_ROAM
end
-- The decision if and who should get Rune is made Team wide.
-- This just checks if this Hero should get it.
evaluatedDesireValue = ConsiderRune(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_RUNEPICKUP
end
-- The decision to Roshan is done in TeamThink().
-- This just checks if this Hero should be part of the effort.
evaluatedDesireValue = ConsiderRoshan(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_ROSHAN
end
-- Farming assignments are made Team Wide.
-- This just tells the Hero where he should go to Farm.
evaluatedDesireValue = ConsiderFarm(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_FARM
end
-- Laning assignments are made Team Wide for Pushing & Defending.
-- Laning assignments are initially determined at start of game/hero-selection.
-- This just tells the Hero which Lane he is supposed to be in.
evaluatedDesireValue = ConsiderLaning(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_LANING
end
-- Warding is done on a per-lane basis. This evaluates if this Hero
-- should ward, and where. (might be a team wide thing later)
evaluatedDesireValue = ConsiderWarding(bot)
if evaluatedDesireValue > highestDesireValue then
highestDesireValue = evaluatedDesireValue
highestDesireMode = constants.MODE_WARD
end
return highestDesireMode
end