2019-11-22 19:58:35 -06:00
|
|
|
from direct.directnotify import DirectNotifyGlobal
|
2024-07-14 15:28:28 -05:00
|
|
|
from toontown.battle import SuitBattleGlobals
|
|
|
|
import random
|
|
|
|
from direct.task import Task
|
2019-11-22 19:58:35 -06:00
|
|
|
|
|
|
|
class SuitInvasionManagerAI:
|
2024-07-14 15:28:28 -05:00
|
|
|
"""
|
|
|
|
Manages invasions of Suits
|
|
|
|
"""
|
|
|
|
|
2019-11-22 19:58:35 -06:00
|
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('SuitInvasionManagerAI')
|
|
|
|
|
|
|
|
def __init__(self, air):
|
|
|
|
self.air = air
|
2024-07-14 15:28:28 -05:00
|
|
|
self.invading = 0
|
|
|
|
self.cogType = None
|
|
|
|
self.skeleton = 0
|
|
|
|
self.totalNumCogs = 0
|
|
|
|
self.numCogsRemaining = 0
|
2019-11-22 19:58:35 -06:00
|
|
|
|
2024-07-14 15:28:28 -05:00
|
|
|
# Set of cog types to choose from See
|
|
|
|
# SuitBattleGlobals.SuitAttributes.keys() for all choices I did not
|
|
|
|
# put the highest level Cogs from each track in here to keep them
|
|
|
|
# special and only found in buildings. I threw in the Flunky just
|
|
|
|
# for fun.
|
|
|
|
self.invadingCogTypes = (
|
|
|
|
# Corporate
|
|
|
|
'f', # Flunky
|
|
|
|
'hh', # Head Hunter
|
|
|
|
'cr', # Corporate Raider
|
|
|
|
# Sales
|
|
|
|
'tf', # Two-faced
|
|
|
|
'm', # Mingler
|
|
|
|
# Money
|
|
|
|
'mb', # Money Bags
|
|
|
|
'ls', # Loan shark
|
|
|
|
# Legal
|
|
|
|
'sd', # Spin Doctor
|
|
|
|
'le', # Legal Eagle
|
|
|
|
)
|
|
|
|
|
|
|
|
# Picked from randomly how many cogs will invade
|
|
|
|
# This might need to be adjusted based on population(?)
|
|
|
|
self.invadingNumList = (1000, 2000, 3000, 4000)
|
|
|
|
|
|
|
|
# Minimum time between invasions on this shard (in seconds)
|
|
|
|
# No more than 1 per 2 days
|
|
|
|
self.invasionMinDelay = 2 * 24 * 60 * 60
|
|
|
|
# Maximum time between invasions on this shard (in seconds)
|
|
|
|
# At least once every 7 days
|
|
|
|
self.invasionMaxDelay = 7 * 24 * 60 * 60
|
|
|
|
|
|
|
|
# Kick off the first invasion
|
|
|
|
self.waitForNextInvasion()
|
|
|
|
|
|
|
|
def delete(self):
|
|
|
|
taskMgr.remove(self.taskName("cogInvasionMgr"))
|
|
|
|
|
|
|
|
def computeInvasionDelay(self):
|
|
|
|
# Compute the delay until the next invasion
|
|
|
|
return ((self.invasionMaxDelay - self.invasionMinDelay) * random.random()
|
|
|
|
+ self.invasionMinDelay)
|
|
|
|
|
|
|
|
def tryInvasionAndWaitForNext(self, task):
|
|
|
|
# Start the invasion if there is not one already
|
|
|
|
if self.getInvading():
|
|
|
|
self.notify.warning("invasionTask: tried to start random invasion, but one is in progress")
|
|
|
|
else:
|
|
|
|
self.notify.info("invasionTask: starting random invasion")
|
|
|
|
cogType = random.choice(self.invadingCogTypes)
|
|
|
|
totalNumCogs = random.choice(self.invadingNumList)
|
|
|
|
self.startInvasion(cogType, totalNumCogs)
|
|
|
|
# In either case, fire off the next invasion
|
|
|
|
self.waitForNextInvasion()
|
|
|
|
return Task.done
|
|
|
|
|
|
|
|
def waitForNextInvasion(self):
|
|
|
|
taskMgr.remove(self.taskName("cogInvasionMgr"))
|
|
|
|
delay = self.computeInvasionDelay()
|
|
|
|
self.notify.info("invasionTask: waiting %s seconds until next invasion" % delay)
|
|
|
|
taskMgr.doMethodLater(delay, self.tryInvasionAndWaitForNext,
|
|
|
|
self.taskName("cogInvasionMgr"))
|
2019-11-22 19:58:35 -06:00
|
|
|
|
|
|
|
def getInvading(self):
|
2024-07-14 15:28:28 -05:00
|
|
|
return self.invading
|
|
|
|
|
|
|
|
def getCogType(self):
|
|
|
|
return self.cogType, self.isSkeleton
|
|
|
|
|
|
|
|
def getNumCogsRemaining(self):
|
|
|
|
return self.numCogsRemaining
|
|
|
|
|
|
|
|
def getTotalNumCogs(self):
|
|
|
|
return self.totalNumCogs
|
|
|
|
|
|
|
|
def startInvasion(self, cogType, totalNumCogs, skeleton=0):
|
|
|
|
if self.invading:
|
|
|
|
self.notify.warning("startInvasion: already invading cogType: %s numCogsRemaining: %s" %
|
|
|
|
(cogType, self.numCogsRemaining))
|
|
|
|
return 0
|
|
|
|
if not SuitBattleGlobals.SuitAttributes.get(cogType):
|
|
|
|
self.notify.warning("startInvasion: unknown cogType: %s" % cogType)
|
|
|
|
return 0
|
|
|
|
|
|
|
|
self.notify.info("startInvasion: cogType: %s totalNumCogs: %s skeleton: %s" %
|
|
|
|
(cogType, totalNumCogs, skeleton))
|
|
|
|
self.invading = 1
|
|
|
|
self.cogType = cogType
|
|
|
|
self.isSkeleton = skeleton
|
|
|
|
self.totalNumCogs = totalNumCogs
|
|
|
|
self.numCogsRemaining = self.totalNumCogs
|
|
|
|
|
|
|
|
# Tell the news manager that an invasion is beginning
|
|
|
|
self.air.newsManager.invasionBegin(self.cogType, self.totalNumCogs, self.isSkeleton)
|
|
|
|
|
|
|
|
# Get rid of all the current cogs on the streets
|
|
|
|
# (except those already in battle, they can stay)
|
|
|
|
for suitPlanner in list(self.air.suitPlanners.values()):
|
|
|
|
suitPlanner.flySuits()
|
|
|
|
# Success!
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def getInvadingCog(self):
|
|
|
|
if self.invading:
|
|
|
|
self.numCogsRemaining -= 1
|
|
|
|
if self.numCogsRemaining <= 0:
|
|
|
|
self.stopInvasion()
|
|
|
|
self.notify.debug("getInvadingCog: returned cog: %s, num remaining: %s" %
|
|
|
|
(self.cogType, self.numCogsRemaining))
|
|
|
|
return self.cogType, self.isSkeleton
|
|
|
|
else:
|
|
|
|
self.notify.debug("getInvadingCog: not currently invading")
|
|
|
|
return None, None
|
|
|
|
|
|
|
|
def stopInvasion(self):
|
|
|
|
self.notify.info("stopInvasion: invasion is over now")
|
|
|
|
# Tell the news manager that an invasion is ending
|
|
|
|
self.air.newsManager.invasionEnd(self.cogType, 0, self.isSkeleton)
|
|
|
|
self.invading = 0
|
|
|
|
self.cogType = None
|
|
|
|
self.isSkeleton = 0
|
|
|
|
self.totalNumCogs = 0
|
|
|
|
self.numCogsRemaining = 0
|
|
|
|
# Get rid of all the current invasion cogs on the streets
|
|
|
|
# (except those already in battle, they can stay)
|
|
|
|
for suitPlanner in list(self.air.suitPlanners.values()):
|
|
|
|
suitPlanner.flySuits()
|
|
|
|
|
|
|
|
# Need this here since this is not a distributed object
|
|
|
|
def taskName(self, taskString):
|
|
|
|
return (taskString + "-" + str(hash(self)))
|