228 lines
8 KiB
Python
228 lines
8 KiB
Python
|
import time, random
|
||
|
|
||
|
from toontown.battle import SuitBattleGlobals
|
||
|
from toontown.suit import SuitDNA
|
||
|
from toontown.suit.SuitInvasionGlobals import *
|
||
|
from toontown.toonbase import ToontownGlobals
|
||
|
|
||
|
|
||
|
class SuitInvasionManagerAI:
|
||
|
def __init__(self, air):
|
||
|
self.air = air
|
||
|
|
||
|
self.invading = False
|
||
|
self.start = 0
|
||
|
self.remaining = 0
|
||
|
self.total = 0
|
||
|
self.suitDeptIndex = None
|
||
|
self.suitTypeIndex = None
|
||
|
self.flags = 0
|
||
|
|
||
|
self.air.accept(
|
||
|
'startInvasion', self.handleStartInvasion)
|
||
|
self.air.accept(
|
||
|
'stopInvasion', self.handleStopInvasion)
|
||
|
|
||
|
# We want to handle shard status queries so that a ShardStatusReceiver
|
||
|
# being created after we're created will know where we're at:
|
||
|
self.air.accept('queryShardStatus', self.sendInvasionStatus)
|
||
|
|
||
|
self.sendInvasionStatus()
|
||
|
|
||
|
def getInvading(self):
|
||
|
return self.invading
|
||
|
|
||
|
def getInvadingCog(self):
|
||
|
return (self.suitDeptIndex, self.suitTypeIndex, self.flags)
|
||
|
|
||
|
def startInvasion(self, suitDeptIndex=None, suitTypeIndex=None, flags=0,
|
||
|
type=INVASION_TYPE_NORMAL):
|
||
|
if self.invading:
|
||
|
# An invasion is currently in progress; ignore this request.
|
||
|
return False
|
||
|
|
||
|
if (suitDeptIndex is None) and (suitTypeIndex is None) and (not flags):
|
||
|
# This invasion is no-op.
|
||
|
return False
|
||
|
|
||
|
if (suitDeptIndex is None) and (suitTypeIndex is not None):
|
||
|
# It's impossible to determine the invading Cog.
|
||
|
return False
|
||
|
|
||
|
if flags not in (0, IFV2, IFSkelecog, IFWaiter):
|
||
|
# The provided flag combination is not possible.
|
||
|
return False
|
||
|
|
||
|
if (suitDeptIndex is not None) and (suitDeptIndex >= len(SuitDNA.suitDepts)):
|
||
|
# Invalid suit department.
|
||
|
return False
|
||
|
|
||
|
if (suitTypeIndex is not None) and (suitTypeIndex >= SuitDNA.suitsPerDept):
|
||
|
# Invalid suit type.
|
||
|
return False
|
||
|
|
||
|
if type not in (INVASION_TYPE_NORMAL, INVASION_TYPE_MEGA, INVASION_TYPE_BRUTAL):
|
||
|
# Invalid invasion type.
|
||
|
return False
|
||
|
|
||
|
# Looks like we're all good. Begin the invasion:
|
||
|
self.invading = True
|
||
|
self.start = int(time.time())
|
||
|
self.suitDeptIndex = suitDeptIndex
|
||
|
self.suitTypeIndex = suitTypeIndex
|
||
|
self.flags = flags
|
||
|
|
||
|
# How many suits do we want?
|
||
|
if type == INVASION_TYPE_NORMAL:
|
||
|
self.total = random.randint(1000, 3000)
|
||
|
elif type == INVASION_TYPE_MEGA:
|
||
|
self.total = 5000
|
||
|
elif type == INVASION_TYPE_BRUTAL:
|
||
|
self.total = 10000
|
||
|
self.remaining = self.total
|
||
|
|
||
|
self.flySuits()
|
||
|
self.notifyInvasionStarted()
|
||
|
|
||
|
# Update the invasion tracker on the districts page in the Shticker Book:
|
||
|
if self.suitDeptIndex is not None:
|
||
|
self.air.districtStats.b_setInvasionStatus(self.suitDeptIndex + 1)
|
||
|
else:
|
||
|
self.air.districtStats.b_setInvasionStatus(5)
|
||
|
|
||
|
# If this is a normal invasion, and the players take too long to defeat
|
||
|
# all of the Cogs, we'll want the invasion to timeout:
|
||
|
if type == INVASION_TYPE_NORMAL:
|
||
|
timeout = config.GetInt('invasion-timeout', 1800)
|
||
|
taskMgr.doMethodLater(timeout, self.stopInvasion, 'invasionTimeout')
|
||
|
|
||
|
# If this is a mega invasion, and the players take to long to defeat
|
||
|
# all of the cogs, we want the invasion to take a bit longer to timeout:
|
||
|
if type == INVASION_TYPE_MEGA:
|
||
|
timeout = config.GetInt('invasion-timeout', 3200)
|
||
|
|
||
|
# If this is a brutal invasion, the players will have a very long time to
|
||
|
# Defeat the cogs before the invasion times out:
|
||
|
if type == INVASION_TYPE_BRUTAL:
|
||
|
timeout = config.GetInt('invasion-timeout', 10000)
|
||
|
|
||
|
self.sendInvasionStatus()
|
||
|
return True
|
||
|
|
||
|
def stopInvasion(self, task=None):
|
||
|
if not self.invading:
|
||
|
# We are not currently invading.
|
||
|
return False
|
||
|
|
||
|
# Stop the invasion timeout task:
|
||
|
taskMgr.remove('invasionTimeout')
|
||
|
|
||
|
# Update the invasion tracker on the districts page in the Shticker Book:
|
||
|
self.air.districtStats.b_setInvasionStatus(0)
|
||
|
|
||
|
# Revert what was done when the invasion started:
|
||
|
self.notifyInvasionEnded()
|
||
|
self.invading = False
|
||
|
self.start = 0
|
||
|
self.suitDeptIndex = None
|
||
|
self.suitTypeIndex = None
|
||
|
self.flags = 0
|
||
|
self.total = 0
|
||
|
self.remaining = 0
|
||
|
self.flySuits()
|
||
|
|
||
|
self.sendInvasionStatus()
|
||
|
return True
|
||
|
|
||
|
def getSuitName(self):
|
||
|
if self.suitDeptIndex is not None:
|
||
|
if self.suitTypeIndex is not None:
|
||
|
return SuitDNA.getSuitName(self.suitDeptIndex, self.suitTypeIndex)
|
||
|
else:
|
||
|
return SuitDNA.suitDepts[self.suitDeptIndex]
|
||
|
else:
|
||
|
return SuitDNA.suitHeadTypes[0]
|
||
|
|
||
|
def notifyInvasionStarted(self):
|
||
|
msgType = ToontownGlobals.SuitInvasionBegin
|
||
|
if self.flags & IFSkelecog:
|
||
|
msgType = ToontownGlobals.SkelecogInvasionBegin
|
||
|
elif self.flags & IFWaiter:
|
||
|
msgType = ToontownGlobals.WaiterInvasionBegin
|
||
|
elif self.flags & IFV2:
|
||
|
msgType = ToontownGlobals.V2InvasionBegin
|
||
|
self.air.newsManager.sendUpdate(
|
||
|
'setInvasionStatus',
|
||
|
[msgType, self.getSuitName(), self.total, self.flags])
|
||
|
|
||
|
def notifyInvasionEnded(self):
|
||
|
msgType = ToontownGlobals.SuitInvasionEnd
|
||
|
if self.flags & IFSkelecog:
|
||
|
msgType = ToontownGlobals.SkelecogInvasionEnd
|
||
|
elif self.flags & IFWaiter:
|
||
|
msgType = ToontownGlobals.WaiterInvasionEnd
|
||
|
elif self.flags & IFV2:
|
||
|
msgType = ToontownGlobals.V2InvasionEnd
|
||
|
self.air.newsManager.sendUpdate(
|
||
|
'setInvasionStatus', [msgType, self.getSuitName(), 0, self.flags])
|
||
|
|
||
|
def notifyInvasionUpdate(self):
|
||
|
self.air.newsManager.sendUpdate(
|
||
|
'setInvasionStatus',
|
||
|
[ToontownGlobals.SuitInvasionUpdate, self.getSuitName(),
|
||
|
self.remaining, self.flags])
|
||
|
|
||
|
def notifyInvasionBulletin(self, avId):
|
||
|
msgType = ToontownGlobals.SuitInvasionBulletin
|
||
|
if self.flags & IFSkelecog:
|
||
|
msgType = ToontownGlobals.SkelecogInvasionBulletin
|
||
|
elif self.flags & IFWaiter:
|
||
|
msgType = ToontownGlobals.WaiterInvasionBulletin
|
||
|
elif self.flags & IFV2:
|
||
|
msgType = ToontownGlobals.V2InvasionBulletin
|
||
|
self.air.newsManager.sendUpdateToAvatarId(
|
||
|
avId, 'setInvasionStatus',
|
||
|
[msgType, self.getSuitName(), self.remaining, self.flags])
|
||
|
|
||
|
def flySuits(self):
|
||
|
for suitPlanner in self.air.suitPlanners.values():
|
||
|
suitPlanner.flySuits()
|
||
|
|
||
|
def handleSuitDefeated(self):
|
||
|
self.remaining -= 1
|
||
|
if self.remaining == 0:
|
||
|
self.stopInvasion()
|
||
|
elif self.remaining == (self.total/2):
|
||
|
self.notifyInvasionUpdate()
|
||
|
self.sendInvasionStatus()
|
||
|
|
||
|
def handleStartInvasion(self, shardId, *args):
|
||
|
if shardId == self.air.ourChannel:
|
||
|
self.startInvasion(*args)
|
||
|
|
||
|
def handleStopInvasion(self, shardId):
|
||
|
if shardId == self.air.ourChannel:
|
||
|
self.stopInvasion()
|
||
|
|
||
|
def sendInvasionStatus(self):
|
||
|
if self.invading:
|
||
|
if self.suitDeptIndex is not None:
|
||
|
if self.suitTypeIndex is not None:
|
||
|
type = SuitBattleGlobals.SuitAttributes[self.getSuitName()]['name']
|
||
|
else:
|
||
|
type = SuitDNA.getDeptFullname(self.getSuitName())
|
||
|
else:
|
||
|
type = None
|
||
|
status = {
|
||
|
'invasion': {
|
||
|
'type': type,
|
||
|
'flags': self.flags,
|
||
|
'remaining': self.remaining,
|
||
|
'total': self.total,
|
||
|
'start': self.start
|
||
|
}
|
||
|
}
|
||
|
else:
|
||
|
status = {'invasion': None}
|
||
|
self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status])
|