658 lines
23 KiB
Python
658 lines
23 KiB
Python
from direct.directnotify import DirectNotifyGlobal
|
|
from otp.avatar import DistributedAvatarAI
|
|
from toontown.battle import BattleExperienceAI
|
|
from toontown.toonbase import ToontownGlobals
|
|
from toontown.toonbase import ToontownBattleGlobals
|
|
from toontown.toon import InventoryBase
|
|
from toontown.battle import DistributedBattleFinalAI
|
|
from toontown.building import SuitPlannerInteriorAI
|
|
from toontown.battle import BattleBase
|
|
from pandac.PandaModules import *
|
|
import SuitDNA
|
|
import random
|
|
from otp.ai.MagicWordGlobal import *
|
|
AllBossCogs = []
|
|
|
|
class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedBossCogAI')
|
|
|
|
def __init__(self, air, dept):
|
|
DistributedAvatarAI.DistributedAvatarAI.__init__(self, air)
|
|
self.dept = dept
|
|
self.dna = SuitDNA.SuitDNA()
|
|
self.dna.newBossCog(self.dept)
|
|
self.deptIndex = SuitDNA.suitDepts.index(self.dept)
|
|
self.resetBattleCounters()
|
|
self.looseToons = []
|
|
self.involvedToons = []
|
|
self.toonsA = []
|
|
self.toonsB = []
|
|
self.nearToons = []
|
|
self.suitsA = []
|
|
self.activeSuitsA = []
|
|
self.suitsB = []
|
|
self.activeSuitsB = []
|
|
self.reserveSuits = []
|
|
self.barrier = None
|
|
self.keyStates = ['BattleOne',
|
|
'BattleTwo',
|
|
'BattleThree',
|
|
'Victory']
|
|
self.bossDamage = 0
|
|
self.battleThreeStart = 0
|
|
self.battleThreeDuration = 1800
|
|
self.attackCode = None
|
|
self.attackAvId = 0
|
|
self.hitCount = 0
|
|
AllBossCogs.append(self)
|
|
return
|
|
|
|
def delete(self):
|
|
self.ignoreAll()
|
|
if self in AllBossCogs:
|
|
i = AllBossCogs.index(self)
|
|
del AllBossCogs[i]
|
|
return DistributedAvatarAI.DistributedAvatarAI.delete(self)
|
|
|
|
def getDNAString(self):
|
|
return self.dna.makeNetString()
|
|
|
|
def avatarEnter(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
self.addToon(avId)
|
|
|
|
def avatarExit(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
self.removeToon(avId)
|
|
|
|
def avatarNearEnter(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
if avId not in self.nearToons:
|
|
self.nearToons.append(avId)
|
|
|
|
def avatarNearExit(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
try:
|
|
self.nearToons.remove(avId)
|
|
except:
|
|
pass
|
|
|
|
def __handleUnexpectedExit(self, avId):
|
|
self.removeToon(avId)
|
|
|
|
def addToon(self, avId):
|
|
if avId not in self.looseToons and avId not in self.involvedToons:
|
|
self.looseToons.append(avId)
|
|
event = self.air.getAvatarExitEvent(avId)
|
|
self.acceptOnce(event, self.__handleUnexpectedExit, extraArgs=[avId])
|
|
|
|
def removeToon(self, avId):
|
|
resendIds = 0
|
|
try:
|
|
self.looseToons.remove(avId)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.involvedToons.remove(avId)
|
|
resendIds = 1
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.toonsA.remove(avId)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.toonsB.remove(avId)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.nearToons.remove(avId)
|
|
except:
|
|
pass
|
|
|
|
event = self.air.getAvatarExitEvent(avId)
|
|
self.ignore(event)
|
|
if not self.hasToons():
|
|
taskMgr.doMethodLater(10, self.__bossDone, self.uniqueName('BossDone'))
|
|
|
|
def __bossDone(self, task):
|
|
self.b_setState('Off')
|
|
messenger.send(self.uniqueName('BossDone'))
|
|
self.ignoreAll()
|
|
|
|
def hasToons(self):
|
|
return self.looseToons or self.involvedToons
|
|
|
|
def hasToonsAlive(self):
|
|
alive = 0
|
|
for toonId in self.involvedToons:
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon:
|
|
hp = toon.getHp()
|
|
if hp > 0:
|
|
alive = 1
|
|
|
|
return alive
|
|
|
|
def sendBattleIds(self):
|
|
self.sendUpdate('setBattleIds', [self.battleNumber, self.battleAId, self.battleBId])
|
|
|
|
def sendToonIds(self):
|
|
self.sendUpdate('setToonIds', [self.involvedToons, self.toonsA, self.toonsB])
|
|
|
|
def damageToon(self, toon, deduction):
|
|
toon.takeDamage(deduction)
|
|
if toon.getHp() <= 0:
|
|
self.sendUpdate('toonDied', [toon.doId])
|
|
empty = InventoryBase.InventoryBase(toon)
|
|
toon.b_setInventory(empty.makeNetString())
|
|
self.removeToon(toon.doId)
|
|
|
|
def healToon(self, toon, increment):
|
|
toon.toonUp(increment)
|
|
|
|
def d_setBattleExperience(self):
|
|
self.sendUpdate('setBattleExperience', self.getBattleExperience())
|
|
|
|
def getBattleExperience(self):
|
|
result = BattleExperienceAI.getBattleExperience(8, self.involvedToons, self.toonExp, self.toonSkillPtsGained, self.toonOrigQuests, self.toonItems, self.toonOrigMerits, self.toonMerits, self.toonParts, self.suitsKilled, self.helpfulToons)
|
|
return result
|
|
|
|
def b_setArenaSide(self, arenaSide):
|
|
self.setArenaSide(arenaSide)
|
|
self.d_setArenaSide(arenaSide)
|
|
|
|
def setArenaSide(self, arenaSide):
|
|
self.arenaSide = arenaSide
|
|
|
|
def d_setArenaSide(self, arenaSide):
|
|
self.sendUpdate('setArenaSide', [arenaSide])
|
|
|
|
def b_setState(self, state):
|
|
self.setState(state)
|
|
self.d_setState(state)
|
|
|
|
def d_setState(self, state):
|
|
self.sendUpdate('setState', [state])
|
|
|
|
def setState(self, state):
|
|
self.demand(state)
|
|
if self.air:
|
|
if state in self.keyStates:
|
|
self.air.writeServerEvent('boss-battle', doId=self.doId, dept=self.dept,
|
|
state=state,
|
|
involvedToons=self.involvedToons,
|
|
reward=self.formatReward())
|
|
|
|
def getState(self):
|
|
return self.state
|
|
|
|
def formatReward(self):
|
|
return 'unspecified'
|
|
|
|
def enterOff(self):
|
|
self.resetBattles()
|
|
self.resetToons()
|
|
self.resetBattleCounters()
|
|
|
|
def exitOff(self):
|
|
pass
|
|
|
|
def enterWaitForToons(self):
|
|
self.acceptNewToons()
|
|
self.barrier = self.beginBarrier('WaitForToons', self.involvedToons, 5, self.__doneWaitForToons)
|
|
|
|
def __doneWaitForToons(self, toons):
|
|
self.b_setState('Elevator')
|
|
|
|
def exitWaitForToons(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
|
|
def enterElevator(self):
|
|
if self.notify.getDebug():
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
self.notify.debug('%s. involved toon %s, %s/%s' % (self.doId,
|
|
toonId,
|
|
toon.getHp(),
|
|
toon.getMaxHp()))
|
|
|
|
self.resetBattles()
|
|
self.barrier = self.beginBarrier('Elevator', self.involvedToons, 30, self.__doneElevator)
|
|
|
|
def __doneElevator(self, avIds):
|
|
self.b_setState('Introduction')
|
|
|
|
def exitElevator(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
|
|
def enterIntroduction(self):
|
|
self.resetBattles()
|
|
self.arenaSide = None
|
|
self.makeBattleOneBattles()
|
|
self.barrier = self.beginBarrier('Introduction', self.involvedToons, 45, self.doneIntroduction)
|
|
return
|
|
|
|
def doneIntroduction(self, avIds):
|
|
self.b_setState('BattleOne')
|
|
|
|
def exitIntroduction(self):
|
|
self.ignoreBarrier(self.barrier)
|
|
for toonId in self.involvedToons:
|
|
toon = simbase.air.doId2do.get(toonId)
|
|
if toon:
|
|
toon.b_setCogIndex(-1)
|
|
|
|
def enterBattleOne(self):
|
|
if self.battleA:
|
|
self.battleA.startBattle(self.toonsA, self.suitsA)
|
|
if self.battleB:
|
|
self.battleB.startBattle(self.toonsB, self.suitsB)
|
|
|
|
def exitBattleOne(self):
|
|
self.resetBattles()
|
|
|
|
def enterReward(self):
|
|
self.resetBattles()
|
|
self.barrier = self.beginBarrier('Reward', self.involvedToons, BattleBase.BUILDING_REWARD_TIMEOUT, self.__doneReward)
|
|
|
|
def __doneReward(self, avIds):
|
|
self.b_setState('Epilogue')
|
|
|
|
def exitReward(self):
|
|
pass
|
|
|
|
def enterEpilogue(self):
|
|
pass
|
|
|
|
def exitEpilogue(self):
|
|
pass
|
|
|
|
def enterFrolic(self):
|
|
self.resetBattles()
|
|
|
|
def exitFrolic(self):
|
|
pass
|
|
|
|
def resetBattleCounters(self):
|
|
self.battleNumber = 0
|
|
self.battleA = None
|
|
self.battleAId = 0
|
|
self.battleB = None
|
|
self.battleBId = 0
|
|
self.arenaSide = None
|
|
self.toonSkillPtsGained = {}
|
|
self.toonExp = {}
|
|
self.toonOrigQuests = {}
|
|
self.toonItems = {}
|
|
self.toonOrigMerits = {}
|
|
self.toonMerits = {}
|
|
self.toonParts = {}
|
|
self.suitsKilled = []
|
|
self.helpfulToons = []
|
|
return
|
|
|
|
def resetBattles(self):
|
|
sendReset = 0
|
|
if self.battleA:
|
|
self.battleA.requestDelete()
|
|
self.battleA = None
|
|
self.battleAId = 0
|
|
sendReset = 1
|
|
if self.battleB:
|
|
self.battleB.requestDelete()
|
|
self.battleB = None
|
|
self.battleBId = 0
|
|
sendReset = 1
|
|
for suit in self.suitsA + self.suitsB:
|
|
suit.requestDelete()
|
|
|
|
for suit, joinChance in self.reserveSuits:
|
|
suit.requestDelete()
|
|
|
|
self.suitsA = []
|
|
self.activeSuitsA = []
|
|
self.suitsB = []
|
|
self.activeSuitsB = []
|
|
self.reserveSuits = []
|
|
self.battleNumber = 0
|
|
if sendReset:
|
|
self.sendBattleIds()
|
|
return
|
|
|
|
def resetToons(self):
|
|
if self.toonsA or self.toonsB:
|
|
self.looseToons = self.looseToons + self.involvedToons
|
|
self.involvedToons = []
|
|
self.toonsA = []
|
|
self.toonsB = []
|
|
self.sendToonIds()
|
|
|
|
def divideToons(self):
|
|
toons = self.involvedToons[:]
|
|
random.shuffle(toons)
|
|
numToons = min(len(toons), 8)
|
|
if numToons < 4:
|
|
numToonsB = numToons / 2
|
|
else:
|
|
numToonsB = (numToons + random.choice([0, 1])) / 2
|
|
self.toonsA = toons[numToonsB:numToons]
|
|
self.toonsB = toons[:numToonsB]
|
|
self.looseToons += toons[numToons:]
|
|
self.sendToonIds()
|
|
|
|
def acceptNewToons(self):
|
|
sourceToons = self.looseToons
|
|
self.looseToons = []
|
|
for toonId in sourceToons:
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon and not toon.ghostMode:
|
|
self.involvedToons.append(toonId)
|
|
else:
|
|
self.looseToons.append(toonId)
|
|
|
|
for avId in self.involvedToons:
|
|
toon = self.air.doId2do.get(avId)
|
|
if toon:
|
|
p = []
|
|
for t in ToontownBattleGlobals.Tracks:
|
|
p.append(toon.experience.getExp(t))
|
|
|
|
self.toonExp[avId] = p
|
|
self.toonOrigMerits[avId] = toon.cogMerits[:]
|
|
|
|
self.divideToons()
|
|
|
|
def initializeBattles(self, battleNumber, bossCogPosHpr):
|
|
self.resetBattles()
|
|
if not self.involvedToons:
|
|
self.notify.warning('initializeBattles: no toons!')
|
|
return
|
|
self.battleNumber = battleNumber
|
|
suitHandles = self.generateSuits(battleNumber)
|
|
self.suitsA = suitHandles['activeSuits']
|
|
self.activeSuitsA = self.suitsA[:]
|
|
self.reserveSuits = suitHandles['reserveSuits']
|
|
suitHandles = self.generateSuits(battleNumber)
|
|
self.suitsB = suitHandles['activeSuits']
|
|
self.activeSuitsB = self.suitsB[:]
|
|
self.reserveSuits += suitHandles['reserveSuits']
|
|
if self.toonsA:
|
|
self.battleA = self.makeBattle(bossCogPosHpr, ToontownGlobals.BossCogBattleAPosHpr, self.handleRoundADone, self.handleBattleADone, battleNumber, 0)
|
|
self.battleAId = self.battleA.doId
|
|
else:
|
|
self.moveSuits(self.activeSuitsA)
|
|
self.suitsA = []
|
|
self.activeSuitsA = []
|
|
if self.arenaSide == None:
|
|
self.b_setArenaSide(0)
|
|
if self.toonsB:
|
|
self.battleB = self.makeBattle(bossCogPosHpr, ToontownGlobals.BossCogBattleBPosHpr, self.handleRoundBDone, self.handleBattleBDone, battleNumber, 1)
|
|
self.battleBId = self.battleB.doId
|
|
else:
|
|
self.moveSuits(self.activeSuitsB)
|
|
self.suitsB = []
|
|
self.activeSuitsB = []
|
|
if self.arenaSide == None:
|
|
self.b_setArenaSide(1)
|
|
self.sendBattleIds()
|
|
return
|
|
|
|
def makeBattle(self, bossCogPosHpr, battlePosHpr, roundCallback, finishCallback, battleNumber, battleSide):
|
|
battle = DistributedBattleFinalAI.DistributedBattleFinalAI(self.air, self, roundCallback, finishCallback, battleSide)
|
|
self.setBattlePos(battle, bossCogPosHpr, battlePosHpr)
|
|
battle.suitsKilled = self.suitsKilled
|
|
battle.battleCalc.toonSkillPtsGained = self.toonSkillPtsGained
|
|
battle.toonExp = self.toonExp
|
|
battle.toonOrigQuests = self.toonOrigQuests
|
|
battle.toonItems = self.toonItems
|
|
battle.toonOrigMerits = self.toonOrigMerits
|
|
battle.toonMerits = self.toonMerits
|
|
battle.toonParts = self.toonParts
|
|
battle.helpfulToons = self.helpfulToons
|
|
mult = ToontownBattleGlobals.getBossBattleCreditMultiplier(battleNumber)
|
|
battle.battleCalc.setSkillCreditMultiplier(mult)
|
|
battle.generateWithRequired(self.zoneId)
|
|
return battle
|
|
|
|
def setBattlePos(self, battle, cogPosHpr, battlePosHpr):
|
|
bossNode = NodePath('bossNode')
|
|
bossNode.setPosHpr(*cogPosHpr)
|
|
battleNode = bossNode.attachNewNode('battleNode')
|
|
battleNode.setPosHpr(*battlePosHpr)
|
|
suitNode = battleNode.attachNewNode('suitNode')
|
|
suitNode.setPos(0, 1, 0)
|
|
battle.pos = battleNode.getPos(NodePath())
|
|
battle.initialSuitPos = suitNode.getPos(NodePath())
|
|
|
|
def moveSuits(self, active):
|
|
for suit in active:
|
|
self.reserveSuits.append((suit, 0))
|
|
|
|
def handleRoundADone(self, toonIds, totalHp, deadSuits):
|
|
if self.battleA:
|
|
self.handleRoundDone(self.battleA, self.suitsA, self.activeSuitsA, toonIds, totalHp, deadSuits)
|
|
|
|
def handleRoundBDone(self, toonIds, totalHp, deadSuits):
|
|
if self.battleB:
|
|
self.handleRoundDone(self.battleB, self.suitsB, self.activeSuitsB, toonIds, totalHp, deadSuits)
|
|
|
|
def handleBattleADone(self, zoneId, toonIds):
|
|
if self.battleA:
|
|
self.battleA.requestDelete()
|
|
self.battleA = None
|
|
self.battleAId = 0
|
|
self.sendBattleIds()
|
|
if self.arenaSide == None:
|
|
self.b_setArenaSide(0)
|
|
if not self.battleB and self.hasToons() and self.hasToonsAlive():
|
|
self.b_setState(self.postBattleState)
|
|
return
|
|
|
|
def handleBattleBDone(self, zoneId, toonIds):
|
|
if self.battleB:
|
|
self.battleB.requestDelete()
|
|
self.battleB = None
|
|
self.battleBId = 0
|
|
self.sendBattleIds()
|
|
if self.arenaSide == None:
|
|
self.b_setArenaSide(1)
|
|
if not self.battleA and self.hasToons() and self.hasToonsAlive():
|
|
self.b_setState(self.postBattleState)
|
|
return
|
|
|
|
def invokeSuitPlanner(self, buildingCode, skelecog):
|
|
planner = SuitPlannerInteriorAI.SuitPlannerInteriorAI(1, buildingCode, self.dna.dept, self.zoneId)
|
|
planner.respectInvasions = 0
|
|
suits = planner.genFloorSuits(0)
|
|
if skelecog:
|
|
for suit in suits['activeSuits']:
|
|
suit.b_setSkelecog(1)
|
|
|
|
for reserve in suits['reserveSuits']:
|
|
suit = reserve[0]
|
|
suit.b_setSkelecog(1)
|
|
|
|
return suits
|
|
|
|
def generateSuits(self, battleNumber):
|
|
raise StandardError, 'generateSuits unimplemented'
|
|
|
|
def handleRoundDone(self, battle, suits, activeSuits, toonIds, totalHp, deadSuits):
|
|
totalMaxHp = 0
|
|
for suit in suits:
|
|
totalMaxHp += suit.maxHP
|
|
|
|
for suit in deadSuits:
|
|
activeSuits.remove(suit)
|
|
|
|
joinedReserves = []
|
|
if len(self.reserveSuits) > 0 and len(activeSuits) < 4:
|
|
hpPercent = 100 - totalHp / totalMaxHp * 100.0
|
|
for info in self.reserveSuits:
|
|
if info[1] <= hpPercent and len(activeSuits) < 4:
|
|
suits.append(info[0])
|
|
activeSuits.append(info[0])
|
|
joinedReserves.append(info)
|
|
|
|
for info in joinedReserves:
|
|
self.reserveSuits.remove(info)
|
|
|
|
battle.resume(joinedReserves)
|
|
|
|
def getBattleThreeTime(self):
|
|
elapsed = globalClock.getFrameTime() - self.battleThreeStart
|
|
t1 = elapsed / float(self.battleThreeDuration)
|
|
return t1
|
|
|
|
def progressValue(self, fromValue, toValue):
|
|
t0 = float(self.bossDamage) / float(self.bossMaxDamage)
|
|
elapsed = globalClock.getFrameTime() - self.battleThreeStart
|
|
t1 = elapsed / float(self.battleThreeDuration)
|
|
t = max(t0, t1)
|
|
return fromValue + (toValue - fromValue) * min(t, 1)
|
|
|
|
def progressRandomValue(self, fromValue, toValue, radius = 0.2):
|
|
t = self.progressValue(0, 1)
|
|
radius = radius * (1.0 - abs(t - 0.5) * 2.0)
|
|
t += radius * random.uniform(-1, 1)
|
|
t = max(min(t, 1.0), 0.0)
|
|
return fromValue + (toValue - fromValue) * t
|
|
|
|
def reportToonHealth(self):
|
|
if self.notify.getDebug():
|
|
str = ''
|
|
for toonId in self.involvedToons:
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon:
|
|
str += ', %s (%s/%s)' % (toonId, toon.getHp(), toon.getMaxHp())
|
|
|
|
self.notify.debug('%s.toons = %s' % (self.doId, str[2:]))
|
|
|
|
def getDamageMultiplier(self):
|
|
return 1.0
|
|
|
|
def zapToon(self, x, y, z, h, p, r, bpx, bpy, attackCode, timestamp):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
if not self.validate(avId, avId in self.involvedToons, 'zapToon from unknown avatar'):
|
|
return
|
|
if attackCode == ToontownGlobals.BossCogLawyerAttack and self.dna.dept != 'l':
|
|
self.notify.warning('got lawyer attack but not in CJ boss battle')
|
|
return
|
|
toon = simbase.air.doId2do.get(avId)
|
|
if toon:
|
|
self.d_showZapToon(avId, x, y, z, h, p, r, attackCode, timestamp)
|
|
damage = ToontownGlobals.BossCogDamageLevels.get(attackCode)
|
|
if damage == None:
|
|
self.notify.warning('No damage listed for attack code %s' % attackCode)
|
|
damage = 5
|
|
damage *= self.getDamageMultiplier()
|
|
self.damageToon(toon, damage)
|
|
currState = self.getCurrentOrNextState()
|
|
if attackCode == ToontownGlobals.BossCogElectricFence and (currState == 'RollToBattleTwo' or currState == 'BattleThree'):
|
|
if bpy < 0 and abs(bpx / bpy) > 0.5:
|
|
if bpx < 0:
|
|
self.b_setAttackCode(ToontownGlobals.BossCogSwatRight)
|
|
else:
|
|
self.b_setAttackCode(ToontownGlobals.BossCogSwatLeft)
|
|
return
|
|
|
|
def d_showZapToon(self, avId, x, y, z, h, p, r, attackCode, timestamp):
|
|
self.sendUpdate('showZapToon', [avId,
|
|
x,
|
|
y,
|
|
z,
|
|
h,
|
|
p,
|
|
r,
|
|
attackCode,
|
|
timestamp])
|
|
|
|
def b_setAttackCode(self, attackCode, avId = 0):
|
|
self.d_setAttackCode(attackCode, avId)
|
|
self.setAttackCode(attackCode, avId)
|
|
|
|
def setAttackCode(self, attackCode, avId = 0):
|
|
self.attackCode = attackCode
|
|
self.attackAvId = avId
|
|
if attackCode == ToontownGlobals.BossCogDizzy or attackCode == ToontownGlobals.BossCogDizzyNow:
|
|
delayTime = self.progressValue(20, 5)
|
|
self.hitCount = 0
|
|
elif attackCode == ToontownGlobals.BossCogSlowDirectedAttack:
|
|
delayTime = ToontownGlobals.BossCogAttackTimes.get(attackCode)
|
|
delayTime += self.progressValue(10, 0)
|
|
else:
|
|
delayTime = ToontownGlobals.BossCogAttackTimes.get(attackCode)
|
|
if delayTime == None:
|
|
return
|
|
self.waitForNextAttack(delayTime)
|
|
return
|
|
|
|
def d_setAttackCode(self, attackCode, avId = 0):
|
|
self.sendUpdate('setAttackCode', [attackCode, avId])
|
|
|
|
def waitForNextAttack(self, delayTime):
|
|
currState = self.getCurrentOrNextState()
|
|
if currState == 'BattleThree':
|
|
taskName = self.uniqueName('NextAttack')
|
|
taskMgr.remove(taskName)
|
|
taskMgr.doMethodLater(delayTime, self.doNextAttack, taskName)
|
|
|
|
def stopAttacks(self):
|
|
taskName = self.uniqueName('NextAttack')
|
|
taskMgr.remove(taskName)
|
|
|
|
def doNextAttack(self, task):
|
|
self.b_setAttackCode(ToontownGlobals.BossCogNoAttack)
|
|
|
|
@magicWord(category=CATEGORY_OVERRIDE, types=[str, str, str])
|
|
def boss(cmd, val, val2=''):
|
|
"""
|
|
A bunch of commands that can be run on the current boss in the invoker's zone.
|
|
|
|
~boss state StateOne
|
|
~boss add loose avId(short)
|
|
~boss add toon avId(short)
|
|
~boss remove loose avId(short)
|
|
~boss remove toon avId(short)
|
|
"""
|
|
for object in simbase.air.doId2do.itervalues():
|
|
if isinstance(object, DistributedBossCogAI):
|
|
# Is this boss cog in the same zone as us?
|
|
if object.getLocation() == spellbook.getInvoker().getLocation():
|
|
# Yes it is! We can run commands on it.
|
|
if cmd == 'state':
|
|
object.b_setState(val)
|
|
return "Set state of the current boss battle to %s." % val
|
|
elif cmd in ['add', 'remove']:
|
|
avId = 100000000 + int(val2)
|
|
toon = simbase.air.doId2do.get(avId)
|
|
if not toon:
|
|
return "This toon is not currently online!"
|
|
if toon.getLocation() != spellbook.getInvoker().getLocation():
|
|
return "This toon is not currently in your boss battle!"
|
|
if cmd == 'add':
|
|
if val == 'loose':
|
|
object.looseToons.append(avId)
|
|
return "Added avId %d to the loose toons list!" % avId
|
|
elif val == 'toon':
|
|
object.involvedToons.append(avId)
|
|
return "Added avId %d to the involved toons list!" % avId
|
|
elif cmd == 'remove':
|
|
if val == 'loose':
|
|
if avId not in object.looseToons:
|
|
return "This toon is not in the loose toons list!"
|
|
object.looseToons.remove(avId)
|
|
return "Removed avId %d from the loose toons list!" % avId
|
|
elif val == 'toon':
|
|
if avId not in object.involvedToons:
|
|
return "This toon is not in the involved toons list!"
|
|
object.involvedToons.remove(avId)
|
|
return "Removed avId %d from the involved toons list!" % avId
|
|
return "Unknown boss command %s." % cmd
|
|
return "Unable to find boss battle which has current avatar."
|