mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-23 03:35:12 -06:00
943 lines
35 KiB
Python
943 lines
35 KiB
Python
from otp.ai.AIBaseGlobal import *
|
|
from direct.distributed.ClockDelta import *
|
|
from otp.ai.MagicWordGlobal import *
|
|
import DistributedBossCogAI
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from otp.avatar import DistributedAvatarAI
|
|
import DistributedSuitAI
|
|
from toontown.battle import BattleExperienceAI
|
|
from direct.fsm import FSM
|
|
from toontown.toonbase import ToontownGlobals
|
|
from toontown.toon import InventoryBase
|
|
from toontown.toonbase import TTLocalizer
|
|
from toontown.battle import BattleBase
|
|
from toontown.toon import NPCToons
|
|
from toontown.building import SuitBuildingGlobals
|
|
import SuitDNA
|
|
import random
|
|
from toontown.coghq import DistributedLawbotBossGavelAI
|
|
from toontown.suit import DistributedLawbotBossSuitAI
|
|
from toontown.coghq import DistributedLawbotCannonAI
|
|
from toontown.coghq import DistributedLawbotChairAI
|
|
from toontown.toonbase import ToontownBattleGlobals
|
|
import math
|
|
|
|
|
|
class DistributedLawbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLawbotBossAI')
|
|
limitHitCount = 6
|
|
hitCountDamage = 35
|
|
numPies = 10
|
|
maxToonLevels = 77
|
|
BossName = "CJ"
|
|
|
|
def __init__(self, air):
|
|
DistributedBossCogAI.DistributedBossCogAI.__init__(self, air, 'l')
|
|
FSM.FSM.__init__(self, 'DistributedLawbotBossAI')
|
|
self.lawyers = []
|
|
self.cannons = None
|
|
self.chairs = None
|
|
self.gavels = None
|
|
self.cagedToonNpcId = random.choice(NPCToons.npcFriends.keys())
|
|
self.bossMaxDamage = ToontownGlobals.LawbotBossMaxDamage
|
|
self.recoverRate = 0
|
|
self.recoverStartTime = 0
|
|
self.bossDamage = ToontownGlobals.LawbotBossInitialDamage
|
|
self.useCannons = 1
|
|
self.numToonJurorsSeated = 0
|
|
self.cannonBallsLeft = {}
|
|
self.toonLevels = 0
|
|
if 'Defeat' not in self.keyStates:
|
|
self.keyStates.append('Defeat')
|
|
self.toonupValue = 1
|
|
self.bonusState = False
|
|
self.bonusTimeStarted = 0
|
|
self.numBonusStates = 0
|
|
self.battleThreeTimeStarted = 0
|
|
self.battleThreeTimeInMin = 0
|
|
self.numAreaAttacks = 0
|
|
self.lastAreaAttackTime = 0
|
|
self.weightPerToon = {}
|
|
self.cannonIndexPerToon = {}
|
|
self.battleDifficulty = 0
|
|
return
|
|
|
|
def delete(self):
|
|
self.notify.debug('DistributedLawbotBossAI.delete')
|
|
self.__deleteBattleThreeObjects()
|
|
self.__deleteBattleTwoObjects()
|
|
taskName = self.uniqueName('clearBonus')
|
|
taskMgr.remove(taskName)
|
|
return DistributedBossCogAI.DistributedBossCogAI.delete(self)
|
|
|
|
def getHoodId(self):
|
|
return ToontownGlobals.LawbotHQ
|
|
|
|
def getCagedToonNpcId(self):
|
|
return self.cagedToonNpcId
|
|
|
|
def magicWordHit(self, damage, avId):
|
|
if self.attackCode != ToontownGlobals.BossCogDizzyNow:
|
|
self.hitBossInsides()
|
|
self.hitBoss(damage)
|
|
|
|
def hitBoss(self, bossDamage):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
if not self.validate(avId, avId in self.involvedToons, 'hitBoss from unknown avatar'):
|
|
return
|
|
self.validate(avId, bossDamage == 1, 'invalid bossDamage %s' % bossDamage)
|
|
if bossDamage < 1:
|
|
return
|
|
currState = self.getCurrentOrNextState()
|
|
if currState != 'BattleThree':
|
|
return
|
|
if bossDamage <= 12:
|
|
newWeight = self.weightPerToon.get(avId)
|
|
if newWeight:
|
|
bossDamage = newWeight
|
|
if self.bonusState and bossDamage <= 12:
|
|
bossDamage *= ToontownGlobals.LawbotBossBonusWeightMultiplier
|
|
bossDamage = min(self.getBossDamage() + bossDamage, self.bossMaxDamage)
|
|
self.b_setBossDamage(bossDamage, 0, 0)
|
|
if self.bossDamage >= self.bossMaxDamage:
|
|
self.b_setState('Victory')
|
|
else:
|
|
self.__recordHit()
|
|
|
|
def healBoss(self, bossHeal):
|
|
bossDamage = -bossHeal
|
|
avId = self.air.getAvatarIdFromSender()
|
|
currState = self.getCurrentOrNextState()
|
|
if currState != 'BattleThree':
|
|
return
|
|
bossDamage = min(self.getBossDamage() + bossDamage, self.bossMaxDamage)
|
|
bossDamage = max(bossDamage, 0)
|
|
self.b_setBossDamage(bossDamage, 0, 0)
|
|
if self.bossDamage == 0:
|
|
self.b_setState('Defeat')
|
|
else:
|
|
self.__recordHit()
|
|
|
|
def hitBossInsides(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
if not self.validate(avId, avId in self.involvedToons, 'hitBossInsides from unknown avatar'):
|
|
return
|
|
currState = self.getCurrentOrNextState()
|
|
if currState != 'BattleThree':
|
|
return
|
|
self.b_setAttackCode(ToontownGlobals.BossCogDizzyNow)
|
|
self.b_setBossDamage(self.getBossDamage(), 0, 0)
|
|
|
|
def hitToon(self, toonId):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
if not self.validate(avId, avId != toonId, 'hitToon on self'):
|
|
return
|
|
if avId not in self.involvedToons or toonId not in self.involvedToons:
|
|
return
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon:
|
|
self.healToon(toon, self.toonupValue)
|
|
self.sendUpdate('toonGotHealed', [toonId])
|
|
|
|
def touchCage(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
currState = self.getCurrentOrNextState()
|
|
if currState != 'BattleThree' and currState != 'NearVictory':
|
|
return
|
|
if not self.validate(avId, avId in self.involvedToons, 'touchCage from unknown avatar'):
|
|
return
|
|
toon = simbase.air.doId2do.get(avId)
|
|
if toon:
|
|
toon.b_setNumPies(self.numPies)
|
|
toon.__touchedCage = 1
|
|
|
|
def touchWitnessStand(self):
|
|
self.touchCage()
|
|
|
|
def finalPieSplat(self):
|
|
self.notify.debug('finalPieSplat')
|
|
if self.state != 'NearVictory':
|
|
return
|
|
self.b_setState('Victory')
|
|
|
|
def doTaunt(self):
|
|
if not self.state == 'BattleThree':
|
|
return
|
|
tauntIndex = random.randrange(len(TTLocalizer.LawbotBossTaunts))
|
|
extraInfo = 0
|
|
if tauntIndex == 0 and self.involvedToons:
|
|
extraInfo = random.randrange(len(self.involvedToons))
|
|
self.sendUpdate('setTaunt', [tauntIndex, extraInfo])
|
|
|
|
def doNextAttack(self, task):
|
|
for lawyer in self.lawyers:
|
|
lawyer.doNextAttack(self)
|
|
|
|
self.waitForNextAttack(ToontownGlobals.LawbotBossLawyerCycleTime)
|
|
timeSinceLastAttack = globalClock.getFrameTime() - self.lastAreaAttackTime
|
|
allowedByTime = 15 < timeSinceLastAttack or self.lastAreaAttackTime == 0
|
|
doAttack = random.randrange(1,101)
|
|
self.notify.debug('allowedByTime=%d doAttack=%d' % (allowedByTime, doAttack))
|
|
if doAttack <= ToontownGlobals.LawbotBossChanceToDoAreaAttack and allowedByTime:
|
|
self.__doAreaAttack()
|
|
self.numAreaAttacks += 1
|
|
self.lastAreaAttackTime = globalClock.getFrameTime()
|
|
else:
|
|
chanceToDoTaunt = ToontownGlobals.LawbotBossChanceForTaunt
|
|
action = random.randrange(1,101)
|
|
if action <= chanceToDoTaunt:
|
|
self.doTaunt()
|
|
pass
|
|
return
|
|
if self.attackCode == ToontownGlobals.BossCogDizzyNow:
|
|
attackCode = ToontownGlobals.BossCogRecoverDizzyAttack
|
|
else:
|
|
attackCode = random.choice([ToontownGlobals.BossCogAreaAttack,
|
|
ToontownGlobals.BossCogFrontAttack,
|
|
ToontownGlobals.BossCogDirectedAttack,
|
|
ToontownGlobals.BossCogDirectedAttack,
|
|
ToontownGlobals.BossCogDirectedAttack,
|
|
ToontownGlobals.BossCogDirectedAttack])
|
|
if attackCode == ToontownGlobals.BossCogAreaAttack:
|
|
self.__doAreaAttack()
|
|
elif attackCode == ToontownGlobals.BossCogDirectedAttack:
|
|
self.__doDirectedAttack()
|
|
else:
|
|
self.b_setAttackCode(attackCode)
|
|
def __doAreaAttack(self):
|
|
self.b_setAttackCode(ToontownGlobals.BossCogAreaAttack)
|
|
|
|
def __doDirectedAttack(self):
|
|
if self.nearToons:
|
|
toonId = random.choice(self.nearToons)
|
|
self.b_setAttackCode(ToontownGlobals.BossCogDirectedAttack, toonId)
|
|
else:
|
|
self.__doAreaAttack()
|
|
|
|
def b_setBossDamage(self, bossDamage, recoverRate, recoverStartTime):
|
|
self.d_setBossDamage(bossDamage, recoverRate, recoverStartTime)
|
|
self.setBossDamage(bossDamage, recoverRate, recoverStartTime)
|
|
|
|
def setBossDamage(self, bossDamage, recoverRate, recoverStartTime):
|
|
self.bossDamage = bossDamage
|
|
self.recoverRate = recoverRate
|
|
self.recoverStartTime = recoverStartTime
|
|
|
|
def getBossDamage(self):
|
|
now = globalClock.getFrameTime()
|
|
elapsed = now - self.recoverStartTime
|
|
return int(max(self.bossDamage - self.recoverRate * elapsed / 60.0, 0))
|
|
|
|
def d_setBossDamage(self, bossDamage, recoverRate, recoverStartTime):
|
|
timestamp = globalClockDelta.localToNetworkTime(recoverStartTime)
|
|
self.sendUpdate('setBossDamage', [bossDamage, recoverRate, timestamp])
|
|
|
|
def waitForNextStrafe(self, delayTime):
|
|
currState = self.getCurrentOrNextState()
|
|
if currState == 'BattleThree':
|
|
taskName = self.uniqueName('NextStrafe')
|
|
taskMgr.remove(taskName)
|
|
taskMgr.doMethodLater(delayTime, self.doNextStrafe, taskName)
|
|
|
|
def stopStrafes(self):
|
|
taskName = self.uniqueName('NextStrafe')
|
|
taskMgr.remove(taskName)
|
|
|
|
def doNextStrafe(self, task):
|
|
if self.attackCode != ToontownGlobals.BossCogDizzyNow:
|
|
side = random.choice([0, 1])
|
|
direction = random.choice([0, 1])
|
|
self.sendUpdate('doStrafe', [side, direction])
|
|
delayTime = 9
|
|
self.waitForNextStrafe(delayTime)
|
|
|
|
def __sendLawyerIds(self):
|
|
lawyerIds = []
|
|
for suit in self.lawyers:
|
|
lawyerIds.append(suit.doId)
|
|
|
|
self.sendUpdate('setLawyerIds', [lawyerIds])
|
|
|
|
def d_cagedToonBattleThree(self, index, avId):
|
|
self.sendUpdate('cagedToonBattleThree', [index, avId])
|
|
|
|
def formatReward(self):
|
|
return str(self.cagedToonNpcId)
|
|
|
|
def makeBattleOneBattles(self):
|
|
self.postBattleState = 'RollToBattleTwo'
|
|
self.initializeBattles(1, ToontownGlobals.LawbotBossBattleOnePosHpr)
|
|
|
|
def generateSuits(self, battleNumber):
|
|
if battleNumber == 1:
|
|
weakenedValue = ((1, 1),
|
|
(2, 2),
|
|
(2, 2),
|
|
(1, 1),
|
|
(1, 1, 1, 1, 1))
|
|
listVersion = list(SuitBuildingGlobals.SuitBuildingInfo)
|
|
if simbase.config.GetBool('lawbot-boss-cheat', 0):
|
|
listVersion[13] = weakenedValue
|
|
SuitBuildingGlobals.SuitBuildingInfo = tuple(listVersion)
|
|
return self.invokeSuitPlanner(13, 0)
|
|
else:
|
|
return self.invokeSuitPlanner(13, 1)
|
|
|
|
def removeToon(self, avId):
|
|
toon = simbase.air.doId2do.get(avId)
|
|
if toon:
|
|
toon.b_setNumPies(0)
|
|
DistributedBossCogAI.DistributedBossCogAI.removeToon(self, avId)
|
|
|
|
def enterOff(self):
|
|
self.notify.debug('enterOff')
|
|
DistributedBossCogAI.DistributedBossCogAI.enterOff(self)
|
|
self.__deleteBattleThreeObjects()
|
|
self.__resetLawyers()
|
|
|
|
def enterElevator(self):
|
|
self.notify.debug('enterElevatro')
|
|
DistributedBossCogAI.DistributedBossCogAI.enterElevator(self)
|
|
self.b_setBossDamage(ToontownGlobals.LawbotBossInitialDamage, 0, 0)
|
|
|
|
def enterIntroduction(self):
|
|
self.notify.debug('enterIntroduction')
|
|
DistributedBossCogAI.DistributedBossCogAI.enterIntroduction(self)
|
|
self.b_setBossDamage(ToontownGlobals.LawbotBossInitialDamage, 0, 0)
|
|
self.__makeChairs()
|
|
|
|
def exitIntroduction(self):
|
|
self.notify.debug('exitIntroduction')
|
|
DistributedBossCogAI.DistributedBossCogAI.exitIntroduction(self)
|
|
|
|
def enterRollToBattleTwo(self):
|
|
self.divideToons()
|
|
self.__makeCannons()
|
|
self.barrier = self.beginBarrier('RollToBattleTwo', self.involvedToons, 50, self.__doneRollToBattleTwo)
|
|
|
|
def __doneRollToBattleTwo(self, avIds):
|
|
self.b_setState('PrepareBattleTwo')
|
|
|
|
def exitRollToBattleTwo(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
|
|
def enterPrepareBattleTwo(self):
|
|
self.__makeCannons()
|
|
self.barrier = self.beginBarrier('PrepareBattleTwo', self.involvedToons, 45, self.__donePrepareBattleTwo)
|
|
self.makeBattleTwoBattles()
|
|
|
|
def __donePrepareBattleTwo(self, avIds):
|
|
self.b_setState('BattleTwo')
|
|
|
|
def exitPrepareBattleTwo(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
|
|
def __makeCannons(self):
|
|
if self.cannons == None:
|
|
self.cannons = []
|
|
startPt = Point3(*ToontownGlobals.LawbotBossCannonPosA)
|
|
endPt = Point3(*ToontownGlobals.LawbotBossCannonPosB)
|
|
totalDisplacement = endPt - startPt
|
|
self.notify.debug('totalDisplacement=%s' % totalDisplacement)
|
|
numToons = len(self.involvedToons)
|
|
stepDisplacement = totalDisplacement / (numToons + 1)
|
|
for index in xrange(numToons):
|
|
newPos = stepDisplacement * (index + 1)
|
|
self.notify.debug('curDisplacement = %s' % newPos)
|
|
newPos += startPt
|
|
self.notify.debug('newPos = %s' % newPos)
|
|
cannon = DistributedLawbotCannonAI.DistributedLawbotCannonAI(self.air, self, index, newPos[0], newPos[1], newPos[2], -90, 0, 0)
|
|
cannon.generateWithRequired(self.zoneId)
|
|
self.cannons.append(cannon)
|
|
|
|
return
|
|
|
|
def __makeChairs(self):
|
|
if self.chairs == None:
|
|
self.chairs = []
|
|
for index in xrange(12):
|
|
chair = DistributedLawbotChairAI.DistributedLawbotChairAI(self.air, self, index)
|
|
chair.generateWithRequired(self.zoneId)
|
|
self.chairs.append(chair)
|
|
|
|
return
|
|
|
|
def __makeBattleTwoObjects(self):
|
|
self.__makeCannons()
|
|
self.__makeChairs()
|
|
|
|
def __deleteCannons(self):
|
|
if self.cannons != None:
|
|
for cannon in self.cannons:
|
|
cannon.requestDelete()
|
|
|
|
self.cannons = None
|
|
return
|
|
|
|
def __deleteChairs(self):
|
|
if self.chairs != None:
|
|
for chair in self.chairs:
|
|
chair.requestDelete()
|
|
|
|
self.chairs = None
|
|
return
|
|
|
|
def __stopChairs(self):
|
|
if self.chairs != None:
|
|
for chair in self.chairs:
|
|
chair.stopCogs()
|
|
|
|
return
|
|
|
|
def __deleteBattleTwoObjects(self):
|
|
self.__deleteCannons()
|
|
self.__deleteChairs()
|
|
|
|
def getCannonBallsLeft(self, avId):
|
|
if avId in self.cannonBallsLeft:
|
|
return self.cannonBallsLeft[avId]
|
|
else:
|
|
self.notify.warning('getCannonBalsLeft invalid avId: %d' % avId)
|
|
return 0
|
|
|
|
def decrementCannonBallsLeft(self, avId):
|
|
if avId in self.cannonBallsLeft:
|
|
self.cannonBallsLeft[avId] -= 1
|
|
if self.cannonBallsLeft[avId] < 0:
|
|
self.notify.warning('decrementCannonBallsLeft <0 cannonballs for %d' % avId)
|
|
self.cannonBallsLeft[avId] = 0
|
|
else:
|
|
self.notify.warning('decrementCannonBallsLeft invalid avId: %d' % avId)
|
|
|
|
def makeBattleTwoBattles(self):
|
|
self.postBattleState = 'RollToBattleThree'
|
|
if self.useCannons:
|
|
self.__makeBattleTwoObjects()
|
|
else:
|
|
self.initializeBattles(2, ToontownGlobals.LawbotBossBattleTwoPosHpr)
|
|
|
|
def enterBattleTwo(self):
|
|
if self.useCannons:
|
|
self.cannonBallsLeft = {}
|
|
for toonId in self.involvedToons:
|
|
self.cannonBallsLeft[toonId] = ToontownGlobals.LawbotBossCannonBallMax
|
|
|
|
for chair in self.chairs:
|
|
chair.requestEmptyJuror()
|
|
|
|
self.barrier = self.beginBarrier('BattleTwo', self.involvedToons, ToontownGlobals.LawbotBossJuryBoxMoveTime + 1, self.__doneBattleTwo)
|
|
if not self.useCannons:
|
|
if self.battleA:
|
|
self.battleA.startBattle(self.toonsA, self.suitsA)
|
|
if self.battleB:
|
|
self.battleB.startBattle(self.toonsB, self.suitsB)
|
|
|
|
def __doneBattleTwo(self, avIds):
|
|
if self.useCannons:
|
|
self.b_setState('PrepareBattleThree')
|
|
else:
|
|
self.b_setState('RollToBattleThree')
|
|
|
|
def exitBattleTwo(self):
|
|
self.resetBattles()
|
|
self.numToonJurorsSeated = 0
|
|
for chair in self.chairs:
|
|
self.notify.debug('chair.state==%s' % chair.state)
|
|
if chair.state == 'ToonJuror':
|
|
self.numToonJurorsSeated += 1
|
|
|
|
self.notify.debug('numToonJurorsSeated=%d' % self.numToonJurorsSeated)
|
|
self.air.writeServerEvent('jurorsSeated', self.doId, '%s|%s|%s' % (self.dept, self.involvedToons, self.numToonJurorsSeated))
|
|
self.__deleteCannons()
|
|
self.__stopChairs()
|
|
|
|
def enterRollToBattleThree(self):
|
|
self.divideToons()
|
|
self.barrier = self.beginBarrier('RollToBattleThree', self.involvedToons, 20, self.__doneRollToBattleThree)
|
|
|
|
def __doneRollToBattleThree(self, avIds):
|
|
self.b_setState('PrepareBattleThree')
|
|
|
|
def exitRollToBattleThree(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
|
|
def enterPrepareBattleThree(self):
|
|
self.calcAndSetBattleDifficulty()
|
|
self.barrier = self.beginBarrier('PrepareBattleThree', self.involvedToons, 45, self.__donePrepareBattleThree)
|
|
|
|
def __donePrepareBattleThree(self, avIds):
|
|
self.b_setState('BattleThree')
|
|
|
|
def exitPrepareBattleThree(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
|
|
def enterBattleThree(self):
|
|
self.battleThreeTimeStarted = globalClock.getFrameTime()
|
|
self.calcAndSetBattleDifficulty()
|
|
self.calculateWeightPerToon()
|
|
diffSettings = ToontownGlobals.LawbotBossDifficultySettings[self.battleDifficulty]
|
|
self.ammoCount = diffSettings[0]
|
|
self.numGavels = diffSettings[1]
|
|
if self.numGavels >= len(ToontownGlobals.LawbotBossGavelPosHprs):
|
|
self.numGavels = len(ToontownGlobals.LawbotBossGavelPosHprs)
|
|
self.numLawyers = diffSettings[2]
|
|
if self.numLawyers >= len(ToontownGlobals.LawbotBossLawyerPosHprs):
|
|
self.numLawyers = len(ToontownGlobals.LawbotBossLawyerPosHprs)
|
|
self.toonupValue = diffSettings[3]
|
|
self.notify.debug('diffLevel=%d ammoCount=%d gavels=%d lawyers = %d, toonup=%d' % (self.battleDifficulty,
|
|
self.ammoCount,
|
|
self.numGavels,
|
|
self.numLawyers,
|
|
self.toonupValue))
|
|
self.air.writeServerEvent('lawbotBossSettings', self.doId, '%s|%s|%s|%s|%s|%s' % (self.dept,
|
|
self.battleDifficulty,
|
|
self.ammoCount,
|
|
self.numGavels,
|
|
self.numLawyers,
|
|
self.toonupValue))
|
|
self.__makeBattleThreeObjects()
|
|
self.__makeLawyers()
|
|
self.numPies = self.ammoCount
|
|
self.resetBattles()
|
|
self.setPieType()
|
|
jurorsOver = self.numToonJurorsSeated - ToontownGlobals.LawbotBossJurorsForBalancedScale
|
|
dmgAdjust = jurorsOver * ToontownGlobals.LawbotBossDamagePerJuror
|
|
self.b_setBossDamage(ToontownGlobals.LawbotBossInitialDamage + dmgAdjust, 0, 0)
|
|
if simbase.config.GetBool('lawbot-boss-cheat', 0):
|
|
self.b_setBossDamage(ToontownGlobals.LawbotBossMaxDamage - 1, 0, 0)
|
|
self.battleThreeStart = globalClock.getFrameTime()
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
toon.__touchedCage = 0
|
|
|
|
for aGavel in self.gavels:
|
|
aGavel.turnOn()
|
|
|
|
self.waitForNextAttack(5)
|
|
self.notify.debug('battleDifficulty = %d' % self.battleDifficulty)
|
|
self.numToonsAtStart = len(self.involvedToons)
|
|
|
|
def getToonDifficulty(self):
|
|
totalCogSuitTier = 0
|
|
totalToons = 0
|
|
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
totalToons += 1
|
|
totalCogSuitTier += toon.cogTypes[1]
|
|
|
|
averageTier = math.floor(totalCogSuitTier / totalToons) + 1
|
|
return int(averageTier)
|
|
|
|
def __saySomething(self, task = None):
|
|
index = None
|
|
avId = 0
|
|
if len(self.involvedToons) == 0:
|
|
return
|
|
avId = random.choice(self.involvedToons)
|
|
toon = simbase.air.doId2do.get(avId)
|
|
if toon.__touchedCage:
|
|
if self.cagedToonDialogIndex <= TTLocalizer.CagedToonBattleThreeMaxAdvice:
|
|
index = self.cagedToonDialogIndex
|
|
self.cagedToonDialogIndex += 1
|
|
elif random.random() < 0.2:
|
|
index = random.randrange(100, TTLocalizer.CagedToonBattleThreeMaxAdvice + 1)
|
|
else:
|
|
index = random.randrange(20, TTLocalizer.CagedToonBattleThreeMaxTouchCage + 1)
|
|
if index:
|
|
self.d_cagedToonBattleThree(index, avId)
|
|
self.__saySomethingLater()
|
|
return
|
|
|
|
def __saySomethingLater(self, delayTime = 15):
|
|
taskName = self.uniqueName('CagedToonSaySomething')
|
|
taskMgr.remove(taskName)
|
|
taskMgr.doMethodLater(delayTime, self.__saySomething, taskName)
|
|
|
|
def __goodJump(self, avId):
|
|
currState = self.getCurrentOrNextState()
|
|
if currState != 'BattleThree':
|
|
return
|
|
index = random.randrange(10, TTLocalizer.CagedToonBattleThreeMaxGivePies + 1)
|
|
self.d_cagedToonBattleThree(index, avId)
|
|
self.__saySomethingLater()
|
|
|
|
def __makeBattleThreeObjects(self):
|
|
if self.gavels == None:
|
|
self.gavels = []
|
|
for index in xrange(self.numGavels):
|
|
gavel = DistributedLawbotBossGavelAI.DistributedLawbotBossGavelAI(self.air, self, index)
|
|
gavel.generateWithRequired(self.zoneId)
|
|
self.gavels.append(gavel)
|
|
|
|
return
|
|
|
|
def __deleteBattleThreeObjects(self):
|
|
if self.gavels != None:
|
|
for gavel in self.gavels:
|
|
gavel.request('Off')
|
|
gavel.requestDelete()
|
|
|
|
self.gavels = None
|
|
return
|
|
|
|
def doBattleThreeInfo(self):
|
|
didTheyWin = 0
|
|
if self.bossDamage == ToontownGlobals.LawbotBossMaxDamage:
|
|
didTheyWin = 1
|
|
self.battleThreeTimeInMin = globalClock.getFrameTime() - self.battleThreeTimeStarted
|
|
self.battleThreeTimeInMin /= 60.0
|
|
self.numToonsAtEnd = 0
|
|
toonHps = []
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
self.numToonsAtEnd += 1
|
|
toonHps.append(toon.hp)
|
|
|
|
self.air.writeServerEvent('b3Info', self.doId, '%d|%.2f|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|%s|%s' % (didTheyWin,
|
|
self.battleThreeTimeInMin,
|
|
self.numToonsAtStart,
|
|
self.numToonsAtEnd,
|
|
self.numToonJurorsSeated,
|
|
self.battleDifficulty,
|
|
self.ammoCount,
|
|
self.numGavels,
|
|
self.numLawyers,
|
|
self.toonupValue,
|
|
self.numBonusStates,
|
|
self.numAreaAttacks,
|
|
toonHps,
|
|
self.weightPerToon))
|
|
|
|
def exitBattleThree(self):
|
|
self.doBattleThreeInfo()
|
|
self.stopAttacks()
|
|
self.stopStrafes()
|
|
taskName = self.uniqueName('CagedToonSaySomething')
|
|
taskMgr.remove(taskName)
|
|
self.__resetLawyers()
|
|
self.__deleteBattleThreeObjects()
|
|
|
|
def enterNearVictory(self):
|
|
self.resetBattles()
|
|
|
|
def exitNearVictory(self):
|
|
pass
|
|
|
|
def enterVictory(self):
|
|
self.resetBattles()
|
|
self.suitsKilled.append({'type': None,
|
|
'level': None,
|
|
'track': self.dna.dept,
|
|
'isSkelecog': 0,
|
|
'isForeman': 0,
|
|
'isBoss': 1,
|
|
'isSupervisor': 0,
|
|
'isVirtual': 0,
|
|
'activeToons': self.involvedToons[:]})
|
|
self.addStats()
|
|
self.barrier = self.beginBarrier('Victory', self.involvedToons, 30, self.__doneVictory)
|
|
return
|
|
|
|
def __doneVictory(self, avIds):
|
|
self.d_setBattleExperience()
|
|
self.b_setState('Reward')
|
|
BattleExperienceAI.assignRewards(self.involvedToons, self.toonSkillPtsGained, self.suitsKilled, ToontownGlobals.dept2cogHQ(self.dept), self.helpfulToons)
|
|
preferredDept = random.randrange(len(SuitDNA.suitDepts))
|
|
#typeWeights = ['single'] * 70 + ['building'] * 27 + ['invasion'] * 3
|
|
preferredSummonType = random.choice(['building', 'invasion', 'cogdo', 'skelinvasion', 'waiterinvasion', 'v2invasion'])
|
|
for toonId in self.involvedToons:
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon:
|
|
self.giveCogSummonReward(toon, preferredDept, preferredSummonType)
|
|
toon.b_promote(self.deptIndex)
|
|
|
|
def giveCogSummonReward(self, toon, prefDeptIndex, prefSummonType):
|
|
cogLevel = self.toonLevels - 1
|
|
deptIndex = prefDeptIndex
|
|
summonType = prefSummonType
|
|
hasSummon = toon.hasParticularCogSummons(prefDeptIndex, cogLevel, prefSummonType)
|
|
self.notify.debug('trying to find another reward')
|
|
if not toon.hasParticularCogSummons(prefDeptIndex, cogLevel, 'building'):
|
|
summonType = 'building'
|
|
elif not toon.hasParticularCogSummons(prefDeptIndex, cogLevel, 'invasion'):
|
|
summonType = 'invasion'
|
|
elif not toon.hasParticularCogSummons(prefDeptIndex, cogLevel, 'cogdo'):
|
|
summonType = 'cogdo'
|
|
elif not toon.hasParticularCogSummons(prefDeptIndex, cogLevel, 'skelinvasion'):
|
|
summonType = 'skelinvasion'
|
|
elif not toon.hasParticularCogSummons(prefDeptIndex, cogLevel, 'waiterinvasion'):
|
|
summonType = 'waiterinvasion'
|
|
elif not toon.hasParticularCogSummons(prefDeptIndex, cogLevel, 'v2invasion'):
|
|
summonType = 'v2invasion'
|
|
else:
|
|
foundOne = False
|
|
for curDeptIndex in xrange(len(SuitDNA.suitDepts)):
|
|
if not toon.hasParticularCogSummons(curDeptIndex, cogLevel, prefSummonType):
|
|
deptIndex = curDeptIndex
|
|
foundOne = True
|
|
break
|
|
elif not toon.hasParticularCogSummons(curDeptIndex, cogLevel, 'building'):
|
|
deptIndex = curDeptIndex
|
|
summonType = 'building'
|
|
foundOne = True
|
|
break
|
|
elif not toon.hasParticularCogSummons(curDeptIndex, cogLevel, 'invasion'):
|
|
summonType = 'invasion'
|
|
deptIndex = curDeptIndex
|
|
foundOne = True
|
|
break
|
|
elif not toon.hasParticularCogSummons(curDeptIndex, cogLevel, 'cogdo'):
|
|
summonType = 'cogdo'
|
|
deptIndex = curDeptIndex
|
|
foundOne = True
|
|
break
|
|
elif not toon.hasParticularCogSummons(curDeptIndex, cogLevel, 'skelinvasion'):
|
|
summonType = 'skelinvasion'
|
|
deptIndex = curDeptIndex
|
|
foundOne = True
|
|
break
|
|
elif not toon.hasParticularCogSummons(curDeptIndex, cogLevel, 'waiterinvasion'):
|
|
summonType = 'waiterinvasion'
|
|
deptIndex = curDeptIndex
|
|
foundOne = True
|
|
break
|
|
elif not toon.hasParticularCogSummons(curDeptIndex, cogLevel, 'v2invasion'):
|
|
summonType = 'v2invasion'
|
|
deptIndex = curDeptIndex
|
|
foundOne = True
|
|
break
|
|
|
|
possibleCogLevel = range(SuitDNA.suitsPerDept)
|
|
possibleDeptIndex = range(len(SuitDNA.suitDepts))
|
|
possibleSummonType = ['building', 'invasion', 'cogdo', 'skelinvasion', 'waiterinvasion', 'v2invasion']
|
|
#typeWeights = ['single'] * 70 + ['building'] * 27 + ['invasion'] * 3
|
|
if not foundOne:
|
|
for i in xrange(5):
|
|
randomCogLevel = random.choice(possibleCogLevel)
|
|
randomSummonType = random.choice(possibleSummonType)
|
|
randomDeptIndex = random.choice(possibleDeptIndex)
|
|
if not toon.hasParticularCogSummons(randomDeptIndex, randomCogLevel, randomSummonType):
|
|
foundOne = True
|
|
cogLevel = randomCogLevel
|
|
summonType = randomSummonType
|
|
deptIndex = randomDeptIndex
|
|
break
|
|
|
|
for curType in possibleSummonType:
|
|
if foundOne:
|
|
break
|
|
for curCogLevel in possibleCogLevel:
|
|
if foundOne:
|
|
break
|
|
for curDeptIndex in possibleDeptIndex:
|
|
if foundOne:
|
|
break
|
|
if not toon.hasParticularCogSummons(curDeptIndex, curCogLevel, curType):
|
|
foundOne = True
|
|
cogLevel = curCogLevel
|
|
summonType = curType
|
|
deptIndex = curDeptIndex
|
|
|
|
if not foundOne:
|
|
cogLevel = None
|
|
summonType = None
|
|
deptIndex = None
|
|
toon.assignNewCogSummons(cogLevel, summonType, deptIndex)
|
|
return
|
|
|
|
def exitVictory(self):
|
|
self.takeAwayPies()
|
|
|
|
def enterDefeat(self):
|
|
self.resetBattles()
|
|
self.barrier = self.beginBarrier('Defeat', self.involvedToons, 10, self.__doneDefeat)
|
|
|
|
def __doneDefeat(self, avIds):
|
|
for toonId in self.involvedToons:
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon:
|
|
toon.b_setHp(0)
|
|
|
|
def exitDefeat(self):
|
|
self.takeAwayPies()
|
|
|
|
def enterFrolic(self):
|
|
DistributedBossCogAI.DistributedBossCogAI.enterFrolic(self)
|
|
self.b_setBossDamage(0, 0, 0)
|
|
|
|
def setPieType(self):
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
toon.d_setPieType(ToontownBattleGlobals.MAX_TRACK_INDEX + 1)
|
|
|
|
def takeAwayPies(self):
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
toon.b_setNumPies(0)
|
|
|
|
def __recordHit(self):
|
|
now = globalClock.getFrameTime()
|
|
self.hitCount += 1
|
|
if self.hitCount < self.limitHitCount or self.bossDamage < self.hitCountDamage:
|
|
return
|
|
|
|
def __resetLawyers(self):
|
|
for suit in self.lawyers:
|
|
suit.requestDelete()
|
|
|
|
self.lawyers = []
|
|
|
|
def __makeLawyers(self):
|
|
self.__resetLawyers()
|
|
lawCogChoices = ['b',
|
|
'dt',
|
|
'ac',
|
|
'bs',
|
|
'sd',
|
|
'le',
|
|
'bw']
|
|
for i in xrange(self.numLawyers):
|
|
suit = DistributedLawbotBossSuitAI.DistributedLawbotBossSuitAI(self.air, None)
|
|
suit.dna = SuitDNA.SuitDNA()
|
|
lawCog = random.choice(lawCogChoices)
|
|
suit.dna.newSuit(lawCog)
|
|
suit.setPosHpr(*ToontownGlobals.LawbotBossLawyerPosHprs[i])
|
|
suit.setBoss(self)
|
|
suit.generateWithRequired(self.zoneId)
|
|
self.lawyers.append(suit)
|
|
|
|
self.__sendLawyerIds()
|
|
return
|
|
|
|
def hitChair(self, chairIndex, npcToonIndex):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
if not self.validate(avId, avId in self.involvedToons, 'hitChair from unknown avatar'):
|
|
return
|
|
if not self.chairs:
|
|
return
|
|
if chairIndex < 0 or chairIndex >= len(self.chairs):
|
|
self.notify.warning('invalid chairIndex = %d' % chairIndex)
|
|
return
|
|
if not self.state == 'BattleTwo':
|
|
return
|
|
self.chairs[chairIndex].b_setToonJurorIndex(npcToonIndex)
|
|
self.chairs[chairIndex].requestToonJuror()
|
|
|
|
def clearBonus(self, taskName):
|
|
if self and hasattr(self, 'bonusState'):
|
|
self.bonusState = False
|
|
|
|
def startBonusState(self):
|
|
self.notify.debug('startBonusState')
|
|
self.bonusTimeStarted = globalClock.getFrameTime()
|
|
self.bonusState = True
|
|
self.numBonusStates += 1
|
|
for toonId in self.involvedToons:
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon:
|
|
self.healToon(toon, ToontownGlobals.LawbotBossBonusToonup)
|
|
|
|
taskMgr.doMethodLater(ToontownGlobals.LawbotBossBonusDuration, self.clearBonus, self.uniqueName('clearBonus'))
|
|
self.sendUpdate('enteredBonusState', [])
|
|
|
|
def areAllLawyersStunned(self):
|
|
for lawyer in self.lawyers:
|
|
if not lawyer.stunned:
|
|
return False
|
|
|
|
return True
|
|
|
|
def checkForBonusState(self):
|
|
if self.bonusState:
|
|
return
|
|
if not self.areAllLawyersStunned():
|
|
return
|
|
curTime = globalClock.getFrameTime()
|
|
delta = curTime - self.bonusTimeStarted
|
|
if ToontownGlobals.LawbotBossBonusWaitTime < delta:
|
|
self.startBonusState()
|
|
|
|
def toonEnteredCannon(self, toonId, cannonIndex):
|
|
self.cannonIndexPerToon[toonId] = cannonIndex
|
|
|
|
def numJurorsSeatedByCannon(self, cannonIndex):
|
|
retVal = 0
|
|
for chair in self.chairs:
|
|
if chair.state == 'ToonJuror':
|
|
if chair.toonJurorIndex == cannonIndex:
|
|
retVal += 1
|
|
|
|
return retVal
|
|
|
|
def calculateWeightPerToon(self):
|
|
for toonId in self.involvedToons:
|
|
defaultWeight = 1
|
|
bonusWeight = 0
|
|
cannonIndex = self.cannonIndexPerToon.get(toonId)
|
|
if not cannonIndex == None:
|
|
diffSettings = ToontownGlobals.LawbotBossDifficultySettings[self.battleDifficulty]
|
|
if diffSettings[4]:
|
|
bonusWeight = self.numJurorsSeatedByCannon(cannonIndex) - diffSettings[5]
|
|
if bonusWeight < 0:
|
|
bonusWeight = 0
|
|
newWeight = defaultWeight + bonusWeight
|
|
self.weightPerToon[toonId] = newWeight
|
|
self.notify.debug('toon %d has weight of %d' % (toonId, newWeight))
|
|
|
|
def b_setBattleDifficulty(self, batDiff):
|
|
self.setBattleDifficulty(batDiff)
|
|
self.d_setBattleDifficulty(batDiff)
|
|
|
|
def setBattleDifficulty(self, batDiff):
|
|
self.battleDifficulty = batDiff
|
|
|
|
def d_setBattleDifficulty(self, batDiff):
|
|
self.sendUpdate('setBattleDifficulty', [batDiff])
|
|
|
|
def calcAndSetBattleDifficulty(self):
|
|
self.toonLevels = self.getToonDifficulty()
|
|
self.b_setBattleDifficulty(self.toonLevels)
|
|
|
|
|
|
@magicWord(category=CATEGORY_ADMINISTRATOR)
|
|
def skipCJ():
|
|
"""
|
|
Skips to the final round of the CJ.
|
|
"""
|
|
invoker = spellbook.getInvoker()
|
|
boss = None
|
|
for do in simbase.air.doId2do.values():
|
|
if isinstance(do, DistributedLawbotBossAI):
|
|
if invoker.doId in do.involvedToons:
|
|
boss = do
|
|
break
|
|
if not boss:
|
|
return "You aren't in a CJ!"
|
|
if boss.state in ('PrepareBattleThree', 'BattleThree'):
|
|
return "You can't skip this round."
|
|
boss.exitIntroduction()
|
|
boss.b_setState('PrepareBattleThree')
|
|
|
|
|
|
@magicWord(category=CATEGORY_ADMINISTRATOR)
|
|
def killCJ():
|
|
"""
|
|
Kills the CJ.
|
|
"""
|
|
invoker = spellbook.getInvoker()
|
|
boss = None
|
|
for do in simbase.air.doId2do.values():
|
|
if isinstance(do, DistributedLawbotBossAI):
|
|
if invoker.doId in do.involvedToons:
|
|
boss = do
|
|
break
|
|
if not boss:
|
|
return "You aren't in a CJ"
|
|
boss.b_setState('Victory')
|
|
return 'Killed CJ.'
|