Sentinel2
Now introducing........... Sentinel2!
This bot does pretty much the same as SentinelBot, but better
This bot will be kind of a servant to the specified player. You can assign a bot to a player (or yourself), and that bot will listen only to that player. But to add a bot, you have to enter a password, so, you can give a bot to a player, but only you know the password so only you can add Sentinel2 bots.
Oh, and also, the Bot will behave like a normal s_bot. When the player who owns the bot says the name of a player, all the Sentinel2 bots will orbit that player, or kill it (depending on the team it is in). To make Sentinel2 bots behave like normal s_bots again, the player who has bots assigned must say "Bots, stop" and the assigned bots will return to normal.
NOTE: Remeber to change the "PASSWORDHERE" to your custom password around the top of the bot code.
Adding bot: /addbot Sentinel2 <team> <password> <playerNameToListen>
Example: /addbot Sentinel2 0 holaDude Fordcars
So, in summary:
"Bots, stop" -- make bots return to normal
A player's name -- Orbit that player
To install, put the bot code in a file and name it Sentinel2. Then, put that file in the Bots folder located with bitfighter.ini.
This bot does pretty much the same as SentinelBot, but better
This bot will be kind of a servant to the specified player. You can assign a bot to a player (or yourself), and that bot will listen only to that player. But to add a bot, you have to enter a password, so, you can give a bot to a player, but only you know the password so only you can add Sentinel2 bots.
Oh, and also, the Bot will behave like a normal s_bot. When the player who owns the bot says the name of a player, all the Sentinel2 bots will orbit that player, or kill it (depending on the team it is in). To make Sentinel2 bots behave like normal s_bots again, the player who has bots assigned must say "Bots, stop" and the assigned bots will return to normal.
NOTE: Remeber to change the "PASSWORDHERE" to your custom password around the top of the bot code.
Adding bot: /addbot Sentinel2 <team> <password> <playerNameToListen>
Example: /addbot Sentinel2 0 holaDude Fordcars
So, in summary:
"Bots, stop" -- make bots return to normal
A player's name -- Orbit that player
To install, put the bot code in a file and name it Sentinel2. Then, put that file in the Bots folder located with bitfighter.ini.
- Code:
- -- MODIFICATION OF S_BOT (QuickBotv2)
-- S_BOT by sam686
-- Sentinel2 by fordcars
goalPt = point.new(0,0)
itemsla = { }
prevtarget = nil
gotoPositionWasNil = true
o = point.new(0,0)
botLoc = nil -- Bot's location, will be updated when onTick() is run
-- This function gets run once during setup. It is the only time we can declare variables
-- and have them be defined as globals.
function main()
subscribe(Event.MsgReceived)
botRadius = bot:getRad()
pathTimerMax = 250
pathTimer = pathTimerMax
dirToGo = 0
game = GameInfo()
difficulty = tonumber(arg[3]) or .5
agression = tonumber(arg[4]) or 0.5
defense = tonumber(arg[5]) or 0
speed = tonumber(arg[6]) or 1
directionThreshold = tonumber(arg[7]) or .25
passwordla = arg[1] or nil
listenplayerarg = arg[2] or nil
listenplayergame = nil
playerattackinfo = nil
playerattack = nil
if (passwordla ~= nil) then
if (listenplayerarg ~= nil) then
if (passwordla == "PASSWORDHERE") then
listenplayergame = listenplayerarg -- Set variable as master player (listen player game)
end
end
end
gameType = game:getGameType()
averageIndex = 1
averageMax = 20
averageArray = { }
for i = 1, averageMax do
averageArray[i] = false
end
myOrbitalDirection = 1
myObjective = math.random(0, 10)
end
items = { } -- Global variable, reusable container for findGlobalObjects. Reusing this table avoids costs of
-- constructing and destructing it every time we call findGlobalObjects(). Be sure to clear the
-- table before reusing it!
function shieldSelf()
table.clear(items)
findObjects(items, ObjType.Bullet, ObjType.Seeker, ObjType.Asteroid, ObjType.Mine)
local distToShieldAt = botRadius * 2 + (1 - difficulty) * 100
if (items ~= nil) then
for i,bullet in ipairs(items) do
local bulletLoc = bullet:getLoc()
local bulletVel = bullet:getVel()
local angleDiff = math.abs(angleDifference(point.angleTo(o, bulletVel), point.angleTo(bulletLoc, botLoc)))
--logprint(angleDiff)
local bulletFromTeam = false
if (game:isTeamGame() == true) and (bullet:getTeamIndx() == bot:getTeamIndx()) then -- If bullet is from team
bulletFromTeam = true -- bullet from team is true
end
if (bulletFromTeam == false) and (point.distanceTo(bulletLoc, botLoc) < distToShieldAt + bullet:getRad() + point.distanceTo(o, bulletVel) * 50 and angleDiff < math.pi / 4) then
bot:activateModule(Module.Shield)
return(true)
end
end
end
end
function angleDifference(angleA, angleB)
return (math.mod(math.mod(angleA - angleB, math.pi * 2) + math.pi * 3, math.pi * 2) - math.pi)
end
function fireAtObjects()
table.clear(items)
findObjects(items, ObjType.Robot, ObjType.Turret, ObjType.Ship, ObjType.Asteroid,
ObjType.ForceFieldProjector, ObjType.SpyBug, ObjType.Core)
-- Cycle through list of potential items until we find one that we can attack
for index, enemy in ipairs(items) do
if(fireAtObject(enemy, Weapon.Phaser)) then
break
end
end
end
-- Fires at the specified object with the specified weapon if the obj is a good target.
-- Does not fire if object is on the same team or if there is something in the way.
-- Returns whether it fired or not.
function fireAtObject(obj, weapon)
local classId = obj:getClassId()
if(classId == ObjType.Turret or classId == ObjType.ForceFieldProjector) then
-- Ignore all same-team engineered objects... even in single-team games
if obj:getTeamIndx() == bot:getTeamIndx() then
return false -- Cancel fireAtObject function
end
if obj:getHealth() < .1 then -- If item is essentially dead
return false
end
end
-- No shooting various team related objects
if (obj:getTeamIndx() == bot:getTeamIndx() and game:isTeamGame()) or -- Same team
obj:getTeamIndx() == Team.Neutral then -- Neutral team
if (classId == ObjType.Ship or classId == ObjType.Robot or -- Turrets and FFs handled above
classId == ObjType.Core or classId == ObjType.SpyBug) then
return false
end
end
-- No shooting non-flag carriers in single player rabbit
if gameType == GameType.Rabbit and not game:isTeamGame() and
(classId == ObjType.Ship or classId == ObjType.Robot) and
not bot:hasFlag() and not obj:hasFlag() then
return false
end
-- We made it here! We have a valid target..
local angle = getFiringSolution(obj)
if angle ~= nil and bot:hasWeapon(weapon) then
bot:setAngle(angle + math.rad((math.random()-0.5)*20*(1-difficulty)))
bot:setWeapon(weapon)
bot:fire()
--logprint("bot:fire() called!");
return(true)
end
--logprint("Firing solution not found.");
return(false)
end
function getName()
return("S_Bot")
end
function shield()
averageArray[averageIndex] = shieldSelf()
averageIndex = math.mod(averageIndex,averageMax) + 1
local shieldPercent = 0
for i = 1, averageMax do
if(averageArray[averageIndex]) then
shieldPercent = shieldPercent + 1
end
end
shieldPercent = shieldPercent / averageMax
if(shieldPercent > directionThreshold) then
myOrbitalDirection = -myOrbitalDirection
for i = 1, averageMax do
averageArray[i] = false
end
end
end
function orbitPoint(pt, dir, inputDist, inputStrictness)
local distAway = botRadius * 7
local strictness = 2
local direction = 1
if(dir ~= nil) then
direction = dir
end
if(inputDist ~= nil) then
distAway = inputDist
end
if(inputStrictness ~= nil) then
strictness = inputStrictness
end
if(pt ~= nil) then
local dist = point.distanceTo(pt, botLoc)
local deltaDistance = (dist - distAway) * strictness / distAway
local sign = 1
if(deltaDistance > 0) then
sign = 1
elseif(deltaDistance < 0) then
sign = -1
end
local changeInAngle = (math.abs(deltaDistance)/(deltaDistance + sign)) * math.pi/2
local angleToPoint = point.angleTo(pt, bot:getLoc())
dirToGo = angleToPoint + (math.pi/2 + changeInAngle)*direction
--bot:setThrust(speed, dirToGo)
end
end
function gotoPosition(pt)
if pt ~= nil then
gotoPositionWasNil = false
if pathTimer < .01 then
goalPt = bot:getWaypoint(pt)
if(goalPt ~= nil) then
dirToGo = point.angleTo(botLoc, goalPt)
end
end
end
end
function gotoAndOrbitPosition(pt)
if pt ~= nil then
gotoPositionWasNil = false
if not bot:hasLosPt(pt) then
gotoPositionWasNil = false
gotoPosition(pt)
else
gotoPositionWasNil = false
orbitPoint(pt, myOrbitalDirection, botRadius * 5, 2)
end
end
end
-- Returns true if it found an enemy to fight
function attackNearbyEnemies(target, agressionLevel)
if target ~= nil then
local targetLoc = target:getLoc()
-- local dist = point.distanceTo(botLoc, targetLoc)
local myPow = bot:getEnergy() + bot:getHealth()
table.clear(items)
findObjects(items, ObjType.Ship, ObjType.Robot)
local otherPow = target:getEnergy() + target:getHealth() * #items
--advantage is between -1 and 1, -1 meaning an extreme disadvantage and 1 meaning an extreme advantage
local advantage = (myPow - otherPow) / math.max(myPow, otherPow)
if(advantage / 2 + .5 >agressionLevel) then
--orbitPoint(targetLoc, myOrbitalDirection, botRadius * 9, 2)
prevtarget = targetLoc
return(false) -- was true
else
end
end
return(false)
end
-- Returns the objective for the bot, in the form of an object the bot can navigate towards. This makes bots choose different defending locations.
-- If onTeam is true, will only return items on specified team. If onTeam is false, will return items *not* on
-- specified team. If called with fewer than three args, will ignore team altogether.
function getObjective(objType, team, onTeam)
table.clear(items)
bot:findGlobalObjects(items, objType) -- Returns a list of all items of type objType in the game
local itemsOnMyTeam = {}
local currentIndex = 1
for index, item in ipairs(items) do -- Iterate through all found items
local itemTeamIndex = item:getTeamIndx()
if (objType == ObjType.Flag) and (gameType == GameType.Nexus) then
if not item:isOnShip() then
itemsOnMyTeam[currentIndex] = item
currentIndex = currentIndex + 1
end
elseif (objType == ObjType.Flag) and
((gameType == GameType.HTF) or (gameType == GameType.Retrieve)) and
item:isInCaptureZone() then
--logprint(item:getCaptureZone():getTeamIndx());
if item:getCaptureZone():getTeamIndx() ~= bot:getTeamIndx() then
itemsOnMyTeam[currentIndex] = item
currentIndex = currentIndex + 1
end
elseif (objType == ObjType.GoalZone) and (gameType == GameType.HTF or gameType == GameType.Retrieve) then
if onTeam == nil or ((itemTeamIndex == team) == onTeam) then
if not item:hasFlag() then
itemsOnMyTeam[currentIndex] = item
currentIndex = currentIndex + 1
end
end
else
if (itemTeamIndex == Team.Neutral ) and (objType ~= ObjType.GoalZone or gameType ~= GameType.ZC) then
itemTeamIndex = team -- anything Neutral is on our team (except zone control neutral goal zone)
end
if onTeam == nil or ((itemTeamIndex == team) == onTeam) then
itemsOnMyTeam[currentIndex] = item
currentIndex = currentIndex + 1
end
end
end
local listMax = 0
--find max
if itemsOnMyTeam[1] ~= nil then
for index,item in ipairs(itemsOnMyTeam) do
if(item ~= nil) then
listMax = listMax + 1
end
end
local targetNum = math.mod(myObjective, listMax) + 1
return(itemsOnMyTeam[targetNum])
else
return(nil)
end
-- local closestitem = 0 --itemsOnMyTeam[1]
-- local cur = 1
-- local closestdist = 99999999
-- while itemsOnMyTeam[cur] ~= nil do
-- local item1 = itemsOnMyTeam[cur]
-- if item1 ~= nil then
-- local loc = item1.getLoc()
-- if loc ~= nil then
-- local dist = point.distanceTo(botLoc, loc)
-- if dist < closestdist then
-- closestdist = dist
-- closesetitem = item1
-- end
-- end
-- end
-- cur=cur+1
-- end
-- return(closestitem)
end
function doObjective(closestEnemy)
gotoPositionWasNil = true
if(gameType == GameType.Bitmatch) then
--Nothing to do here.
elseif(gameType == GameType.Nexus) then
if playerattackinfo == nil then
-- Grab any flags that are found, and go to nexus when it opens
local otherFlag = getObjective(ObjType.Flag) -- Find any flags
if otherFlag ~= nil then -- If there is a flag avalible
gotoPosition(otherFlag:getLoc())
end
-- If bot has more than 4 flags and the nexus is open or we're within 10 seconds of opening
if bot:getFlagCount() > 4 and (game:isNexusOpen() or game:getNexusTimeLeft() < 10) then -- Need to know if nexus is open
local nexusOrFlag = getObjective(ObjType.Nexus) -- unimplemented push function error.
if nexusOrFlag ~= nil then
gotoPosition(nexusOrFlag:getLoc())
end
end
end
elseif(gameType == GameType.Rabbit) then
if playerattackinfo == nil then
--Grab a flag, or go after the flag.
if not bot:hasFlag() then
local otherFlag = getObjective(ObjType.Flag, bot:getTeamIndx(), true) -- Find flags on our team
gotoPosition(otherFlag:getLoc())
end
end
elseif(gameType == GameType.HTF or gameType == GameType.Retrieve) then
if playerattackinfo == nil then
-- Grab the flag and put it into goal zones
-- Robot keeps trying to pick up the flags that is already in the goalZones
if bot:hasFlag() then -- If the bot has the flag
local otherFlag = getObjective(ObjType.GoalZone, bot:getTeamIndx(), true) -- Find an avalible GoalZone on our team
if otherFlag ~= nil then -- If there is an avalible GoalZone
gotoPosition(otherFlag:getLoc()) -- Go to it
end
else -- If the bot doesn't have the flag
local otherFlag = getObjective(ObjType.Flag, bot:getTeamIndx(), true) -- Find flags on our team
if otherFlag ~= nil then -- If there is a flag avalible
gotoPosition(otherFlag:getLoc()) -- Go to it
end
end
end
elseif(gameType == GameType.CTF) then
if playerattackinfo == nil then
--defend the flag
local myFlag = getObjective(ObjType.Flag, bot:getTeamIndx(), true) -- Find flags on our team
local otherFlag = getObjective(ObjType.Flag, bot:getTeamIndx(), false) -- Find flags not on our team
if(defense < .5) then -- If bot doesn't defend allot (default is 0)
if bot:hasFlag() then -- If the bot has a flag
if not myFlag:isOnShip() then -- If my flag is not on a ship
gotoPosition(myFlag:getLoc()) -- Go to position of my flag
else
gotoAndOrbitPosition(myFlag:getLoc()) -- Otherwise, go and orbit the flag on enemy
end
--gotoPosition(myFlag:getLoc())
else -- If the bot doesn't have the flag
local retrievingFlag = false
if myFlag ~= nil then
if not myFlag:isInInitLoc() and not myFlag:isOnShip() and -- If my flag is not in its initial location and my flag is not on a ship
point.distSquared(myFlag:getLoc(), bot:getLoc()) <= 2000 * 2000 then -- .. and we're within some sane range of the flag
gotoPosition(myFlag:getLoc()) -- Go to and return my flag
retrievingFlag = true
end
end
if otherFlag ~= nil then -- If there is an enemy flag
if not retrievingFlag then -- .. and this bot isn't already retrieving a flag
if myFlag:isOnShip() then -- If my flag is on a ship
gotoPosition(myFlag:getLoc()) -- Go to position of my flag
elseif not otherFlag:isOnShip() then -- If enemy flag is not on a ship
gotoPosition(otherFlag:getLoc()) -- Go to that flag
else
gotoAndOrbitPosition(otherFlag:getLoc()) -- Go and orbit our team flag's carrier
end
end
end
end
else
if bot:hasFlag() then -- If the bot has a flag and has more than .5 defense
gotoPosition(myFlag:getLoc()) -- Go to team flag
elseif myFlag:isInInitLoc() then -- If the bot doesn't have a flag and the team flag is in intial location
gotoAndOrbitPosition(myFlag:getLoc()) -- Go and orbit team flag
else
if myFlag:isOnShip() then -- If team flag is on a ship
gotoAndOrbitPosition(myFlag:getLoc()) -- Go and orbit team flag
else
gotoPosition(myFlag:getLoc()) -- If team flag is not on a ship, go to team flag
end
end
end
end
elseif(gameType == GameType.Soccer) then
if playerattackinfo == nil then
--grab soccer and put into enemy goal
-- How do we know if we are holding soccer ? (not supported when cannot pickup soccer (016)
if bot:getMountedItems(ObjType.SoccerBallItem)[1] ~= nil then
local otherFlag = getObjective(ObjType.GoalZone, bot:getTeamIndx(), false) -- Find GoalZones not on our team
if otherFlag ~= nil then
gotoPosition(otherFlag:getLoc())
end
else
local otherFlag = getObjective(ObjType.SoccerBallItem) -- Find SoccerBall
if otherFlag ~= nil then
gotoPosition(otherFlag:getLoc())
end
end
end
elseif(gameType == GameType.ZC) then
if playerattackinfo == nil then
-- Grab flag, then go after zones that is not ours.
if not bot:hasFlag() then
local otherFlag = getObjective(ObjType.Flag, bot:getTeamIndx(), true) -- Find flags on our team
if otherFlag ~= nil then
if otherFlag:isOnShip() then
gotoAndOrbitPosition(otherFlag:getLoc())
else
gotoPosition(otherFlag:getLoc())
end
end
else
local otherFlag = getObjective(ObjType.GoalZone, bot:getTeamIndx(), false) -- Find GoalZones on our team
if otherFlag then
gotoPosition(otherFlag:getLoc())
end
end
end
elseif(gameType == GameType.Core) then
if playerattackinfo == nil then
local obj = getObjective(ObjType.Core, bot:getTeamIndx(), false) -- Find enemy Core
if obj ~= nil then
gotoAndOrbitPosition(obj:getLoc())
end
end
end
-- If we have no where to go, go to nearest enemy.
if gotoPositionWasNil then
if playerattackinfo == nil then
if(closestEnemy ~= nil) then
prevtarget = closestEnemy:getLoc()
end
if(prevtarget ~= nil) then
gotoAndOrbitPosition(prevtarget)
end
end
end
end
function goInDirection()
bot:setThrust(speed, dirToGo)
end
function onMsgReceived(message, senderPlayerInfo)
if senderPlayerInfo:getName() ~= nil then
if senderPlayerInfo:getName() == listenplayergame then
playerattack = message
end
end
end
-- This function gets called every game tick; deltaTime is the time that has elapsed since it was last called
function onTick(deltaTime)
botLoc = bot:getLoc()
pathTimer = pathTimer - deltaTime
assert(bot:getLoc() ~= nil)
local closestEnemy = bot:findClosestEnemy()
-- attackNearbyEnemies returns true if there is an enemy to fight, false if the bot can do something else
attackNearbyEnemies(closestEnemy, 1 - agression)
doObjective(closestEnemy) -- Set bot's objective
-- -------------------------------------------------------------Up is shooting enemies and variables
if playerattack ~= nil then -- If there is a player to attack
if playerattack == "Bots, stop" then
playerattackinfo = nil
end
table.clear(itemsla)
bot:findGlobalObjects(itemsla, ObjType.Ship, ObjType.Robot)
for index, item in ipairs(itemsla) do
if item:getPlayerInfo() ~= nil then
if item:getPlayerInfo():getName() == playerattack then
playerattackinfo = item:getLoc()
break
end
end
end
if playerattackinfo ~= nil then
gotoAndOrbitPosition(playerattackinfo)
end
end
goInDirection() -- Move the ship
fireAtObjects() -- Fire weapons
shield() -- Apply shield
if(pathTimer < 0) then
pathTimer = pathTimerMax + math.random(0, pathTimerMax)
end
end
skybax: Why is this health pack following me?
bobdaduck: uh, it likes you.