Poodletooth-iLand/toontown/suit/DistributedCashbotBossAI.py
2015-03-03 17:10:12 -05:00

543 lines
19 KiB
Python

from pandac.PandaModules import *
from direct.directnotify import DirectNotifyGlobal
from toontown.toonbase import ToontownGlobals
from toontown.coghq import DistributedCashbotBossCraneAI
from toontown.coghq import DistributedCashbotBossSafeAI
from toontown.suit import DistributedCashbotBossGoonAI
#from toontown.coghq import DistributedCashbotBossTreasureAI
from toontown.battle import BattleExperienceAI
from toontown.chat import ResistanceChat
from direct.fsm import FSM
import DistributedBossCogAI
import SuitDNA
import random
from otp.ai.MagicWordGlobal import *
import math
class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCashbotBossAI')
maxGoons = 8
def __init__(self, air):
DistributedBossCogAI.DistributedBossCogAI.__init__(self, air, 'm')
FSM.FSM.__init__(self, 'DistributedCashbotBossAI')
self.cranes = None
self.safes = None
self.goons = None
self.treasures = {}
self.grabbingTreasures = {}
self.recycledTreasures = []
self.healAmount = 0
self.rewardId = ResistanceChat.getRandomId()
self.rewardedToons = []
self.scene = NodePath('scene')
self.reparentTo(self.scene)
cn = CollisionNode('walls')
cs = CollisionSphere(0, 0, 0, 13)
cn.addSolid(cs)
cs = CollisionInvSphere(0, 0, 0, 42)
cn.addSolid(cs)
self.attachNewNode(cn)
self.heldObject = None
self.waitingForHelmet = 0
self.avatarHelmets = {}
self.bossMaxDamage = ToontownGlobals.CashbotBossMaxDamage
return
def generate(self):
DistributedBossCogAI.DistributedBossCogAI.generate(self)
if __dev__:
self.scene.reparentTo(self.getRender())
def getHoodId(self):
return ToontownGlobals.CashbotHQ
def formatReward(self):
return str(self.rewardId)
def makeBattleOneBattles(self):
self.postBattleState = 'PrepareBattleThree'
self.initializeBattles(1, ToontownGlobals.CashbotBossBattleOnePosHpr)
def generateSuits(self, battleNumber):
cogs = self.invokeSuitPlanner(11, 0)
skelecogs = self.invokeSuitPlanner(12, 1)
activeSuits = cogs['activeSuits'] + skelecogs['activeSuits']
reserveSuits = cogs['reserveSuits'] + skelecogs['reserveSuits']
random.shuffle(activeSuits)
while len(activeSuits) > 4:
suit = activeSuits.pop()
reserveSuits.append((suit, 100))
def compareJoinChance(a, b):
return cmp(a[1], b[1])
reserveSuits.sort(compareJoinChance)
return {'activeSuits': activeSuits,
'reserveSuits': reserveSuits}
def removeToon(self, avId):
if self.cranes != None:
for crane in self.cranes:
crane.removeToon(avId)
if self.safes != None:
for safe in self.safes:
safe.removeToon(avId)
if self.goons != None:
for goon in self.goons:
goon.removeToon(avId)
DistributedBossCogAI.DistributedBossCogAI.removeToon(self, avId)
return
def __makeBattleThreeObjects(self):
if self.cranes == None:
self.cranes = []
for index in xrange(len(ToontownGlobals.CashbotBossCranePosHprs)):
crane = DistributedCashbotBossCraneAI.DistributedCashbotBossCraneAI(self.air, self, index)
crane.generateWithRequired(self.zoneId)
self.cranes.append(crane)
if self.safes == None:
self.safes = []
for index in xrange(len(ToontownGlobals.CashbotBossSafePosHprs)):
safe = DistributedCashbotBossSafeAI.DistributedCashbotBossSafeAI(self.air, self, index)
safe.generateWithRequired(self.zoneId)
self.safes.append(safe)
if self.goons == None:
self.goons = []
return
def __resetBattleThreeObjects(self):
if self.cranes != None:
for crane in self.cranes:
crane.request('Free')
if self.safes != None:
for safe in self.safes:
safe.request('Initial')
return
def __deleteBattleThreeObjects(self):
if self.cranes != None:
for crane in self.cranes:
crane.request('Off')
crane.requestDelete()
self.cranes = None
if self.safes != None:
for safe in self.safes:
safe.request('Off')
safe.requestDelete()
self.safes = None
if self.goons != None:
for goon in self.goons:
goon.request('Off')
goon.requestDelete()
self.goons = None
return
def doNextAttack(self, task):
self.__doDirectedAttack()
if self.heldObject == None and not self.waitingForHelmet:
self.waitForNextHelmet()
return
def __doDirectedAttack(self):
if self.toonsToAttack:
toonId = self.toonsToAttack.pop(0)
while toonId not in self.involvedToons:
if not self.toonsToAttack:
self.b_setAttackCode(ToontownGlobals.BossCogNoAttack)
return
toonId = self.toonsToAttack.pop(0)
self.toonsToAttack.append(toonId)
self.b_setAttackCode(ToontownGlobals.BossCogSlowDirectedAttack, toonId)
def reprieveToon(self, avId):
if avId in self.toonsToAttack:
i = self.toonsToAttack.index(avId)
del self.toonsToAttack[i]
self.toonsToAttack.append(avId)
def makeTreasure(self, goon):
return
if self.state != 'BattleThree':
return
pos = goon.getPos(self)
v = Vec3(pos[0], pos[1], 0.0)
if not v.normalize():
v = Vec3(1, 0, 0)
v = v * 27
angle = random.uniform(0.0, 2.0 * math.pi)
radius = 10
dx = radius * math.cos(angle)
dy = radius * math.sin(angle)
fpos = self.scene.getRelativePoint(self, Point3(v[0] + dx, v[1] + dy, 0))
if goon.strength <= 10:
style = ToontownGlobals.ToontownCentral
healAmount = 3
elif goon.strength <= 15:
style = random.choice([ToontownGlobals.DonaldsDock, ToontownGlobals.DaisyGardens, ToontownGlobals.MinniesMelodyland])
healAmount = 10
else:
style = random.choice([ToontownGlobals.TheBrrrgh, ToontownGlobals.DonaldsDreamland])
healAmount = 12
if self.recycledTreasures:
treasure = self.recycledTreasures.pop(0)
treasure.d_setGrab(0)
treasure.b_setGoonId(goon.doId)
treasure.b_setStyle(style)
treasure.b_setPosition(pos[0], pos[1], 0)
treasure.b_setFinalPosition(fpos[0], fpos[1], 0)
else:
#treasure = DistributedCashbotBossTreasureAI.DistributedCashbotBossTreasureAI(self.air, self, goon, style, fpos[0], fpos[1], 0)
#treasure.generateWithRequired(self.zoneId)
pass
treasure.healAmount = healAmount
self.treasures[treasure.doId] = treasure
def grabAttempt(self, avId, treasureId):
av = self.air.doId2do.get(avId)
if not av:
return
treasure = self.treasures.get(treasureId)
if treasure:
if treasure.validAvatar(av):
del self.treasures[treasureId]
treasure.d_setGrab(avId)
self.grabbingTreasures[treasureId] = treasure
taskMgr.doMethodLater(5, self.__recycleTreasure, treasure.uniqueName('recycleTreasure'), extraArgs=[treasure])
else:
treasure.d_setReject()
def __recycleTreasure(self, treasure):
if treasure.doId in self.grabbingTreasures:
del self.grabbingTreasures[treasure.doId]
self.recycledTreasures.append(treasure)
def deleteAllTreasures(self):
for treasure in self.treasures.values():
treasure.requestDelete()
self.treasures = {}
for treasure in self.grabbingTreasures.values():
taskMgr.remove(treasure.uniqueName('recycleTreasure'))
treasure.requestDelete()
self.grabbingTreasures = {}
for treasure in self.recycledTreasures:
treasure.requestDelete()
self.recycledTreasures = []
def getMaxGoons(self):
t = self.getBattleThreeTime()
if t <= 1.0:
return self.maxGoons
elif t <= 1.1:
return self.maxGoons + 1
elif t <= 1.2:
return self.maxGoons + 2
elif t <= 1.3:
return self.maxGoons + 3
elif t <= 1.4:
return self.maxGoons + 4
else:
return self.maxGoons + 8
def makeGoon(self, side = None):
if side == None:
side = random.choice(['EmergeA', 'EmergeB'])
goon = self.__chooseOldGoon()
if goon == None:
if len(self.goons) >= self.getMaxGoons():
return
goon = DistributedCashbotBossGoonAI.DistributedCashbotBossGoonAI(self.air, self)
goon.generateWithRequired(self.zoneId)
self.goons.append(goon)
if self.getBattleThreeTime() > 1.0:
goon.STUN_TIME = 4
goon.b_setupGoon(velocity=8, hFov=90, attackRadius=20, strength=30, scale=1.8)
else:
goon.STUN_TIME = self.progressValue(30, 8)
goon.b_setupGoon(velocity=self.progressRandomValue(3, 7), hFov=self.progressRandomValue(70, 80), attackRadius=self.progressRandomValue(6, 15), strength=int(self.progressRandomValue(5, 25)), scale=self.progressRandomValue(0.5, 1.5))
goon.request(side)
return
def __chooseOldGoon(self):
for goon in self.goons:
if goon.state == 'Off':
return goon
def waitForNextGoon(self, delayTime):
currState = self.getCurrentOrNextState()
if currState == 'BattleThree':
taskName = self.uniqueName('NextGoon')
taskMgr.remove(taskName)
taskMgr.doMethodLater(delayTime, self.doNextGoon, taskName)
def stopGoons(self):
taskName = self.uniqueName('NextGoon')
taskMgr.remove(taskName)
def doNextGoon(self, task):
if self.attackCode != ToontownGlobals.BossCogDizzy:
self.makeGoon()
delayTime = self.progressValue(10, 2)
self.waitForNextGoon(delayTime)
def waitForNextHelmet(self):
currState = self.getCurrentOrNextState()
if currState == 'BattleThree':
taskName = self.uniqueName('NextHelmet')
taskMgr.remove(taskName)
delayTime = self.progressValue(45, 15)
taskMgr.doMethodLater(delayTime, self.__donHelmet, taskName)
self.waitingForHelmet = 1
def __donHelmet(self, task):
self.waitingForHelmet = 0
if self.heldObject == None:
safe = self.safes[0]
safe.request('Grabbed', self.doId, self.doId)
self.heldObject = safe
return
def stopHelmets(self):
self.waitingForHelmet = 0
taskName = self.uniqueName('NextHelmet')
taskMgr.remove(taskName)
def acceptHelmetFrom(self, avId):
now = globalClock.getFrameTime()
then = self.avatarHelmets.get(avId, None)
if then == None or now - then > 300:
self.avatarHelmets[avId] = now
return 1
return 0
def magicWordHit(self, damage, avId):
if self.heldObject:
self.heldObject.demand('Dropped', avId, self.doId)
self.heldObject.avoidHelmet = 1
self.heldObject = None
self.waitForNextHelmet()
else:
self.recordHit(damage)
return
def magicWordReset(self):
if self.state == 'BattleThree':
self.__resetBattleThreeObjects()
def magicWordResetGoons(self):
if self.state == 'BattleThree':
if self.goons != None:
for goon in self.goons:
goon.request('Off')
goon.requestDelete()
self.goons = None
self.__makeBattleThreeObjects()
return
def recordHit(self, damage):
avId = self.air.getAvatarIdFromSender()
if not self.validate(avId, avId in self.involvedToons, 'recordHit from unknown avatar'):
return
if self.state != 'BattleThree':
return
self.b_setBossDamage(self.bossDamage + damage)
if self.bossDamage >= self.bossMaxDamage:
self.b_setState('Victory')
elif self.attackCode != ToontownGlobals.BossCogDizzy:
if damage >= ToontownGlobals.CashbotBossKnockoutDamage:
self.b_setAttackCode(ToontownGlobals.BossCogDizzy)
self.stopHelmets()
else:
self.b_setAttackCode(ToontownGlobals.BossCogNoAttack)
self.stopHelmets()
self.waitForNextHelmet()
def b_setBossDamage(self, bossDamage):
self.d_setBossDamage(bossDamage)
self.setBossDamage(bossDamage)
def setBossDamage(self, bossDamage):
self.reportToonHealth()
self.bossDamage = bossDamage
def d_setBossDamage(self, bossDamage):
self.sendUpdate('setBossDamage', [bossDamage])
def d_setRewardId(self, rewardId):
self.sendUpdate('setRewardId', [rewardId])
def applyReward(self):
avId = self.air.getAvatarIdFromSender()
if avId in self.involvedToons and avId not in self.rewardedToons:
self.rewardedToons.append(avId)
toon = self.air.doId2do.get(avId)
if toon:
toon.doResistanceEffect(self.rewardId)
if simbase.config.GetBool('cfo-staff-event', False):
withStaff = False
for avId in self.involvedToons:
av = self.air.doId2do.get(avId)
if av:
if av.adminAccess > 100:
withStaff = True
if withStaff:
participants = simbase.backups.load('cfo-staff-event', ('participants',), default={'doIds': []})
if avId not in participants['doIds']:
participants['doIds'].append(toon.doId)
simbase.backups.save('cfo-staff-event', ('participants',), participants)
def enterOff(self):
DistributedBossCogAI.DistributedBossCogAI.enterOff(self)
self.rewardedToons = []
def exitOff(self):
DistributedBossCogAI.DistributedBossCogAI.exitOff(self)
def enterIntroduction(self):
DistributedBossCogAI.DistributedBossCogAI.enterIntroduction(self)
self.__makeBattleThreeObjects()
self.__resetBattleThreeObjects()
def exitIntroduction(self):
DistributedBossCogAI.DistributedBossCogAI.exitIntroduction(self)
self.__deleteBattleThreeObjects()
def enterPrepareBattleThree(self):
self.resetBattles()
self.__makeBattleThreeObjects()
self.__resetBattleThreeObjects()
self.barrier = self.beginBarrier('PrepareBattleThree', self.involvedToons, 55, self.__donePrepareBattleThree)
def __donePrepareBattleThree(self, avIds):
self.b_setState('BattleThree')
def exitPrepareBattleThree(self):
if self.newState != 'BattleThree':
self.__deleteBattleThreeObjects()
self.ignoreBarrier(self.barrier)
def enterBattleThree(self):
self.setPosHpr(*ToontownGlobals.CashbotBossBattleThreePosHpr)
self.__makeBattleThreeObjects()
self.__resetBattleThreeObjects()
self.reportToonHealth()
self.toonsToAttack = self.involvedToons[:]
random.shuffle(self.toonsToAttack)
self.b_setBossDamage(0)
self.battleThreeStart = globalClock.getFrameTime()
self.resetBattles()
self.waitForNextAttack(15)
self.waitForNextHelmet()
self.makeGoon(side='EmergeA')
self.makeGoon(side='EmergeB')
taskName = self.uniqueName('NextGoon')
taskMgr.remove(taskName)
taskMgr.doMethodLater(2, self.__doInitialGoons, taskName)
def __doInitialGoons(self, task):
self.makeGoon(side='EmergeA')
self.makeGoon(side='EmergeB')
self.waitForNextGoon(10)
def exitBattleThree(self):
helmetName = self.uniqueName('helmet')
taskMgr.remove(helmetName)
if self.newState != 'Victory':
self.__deleteBattleThreeObjects()
self.deleteAllTreasures()
self.stopAttacks()
self.stopGoons()
self.stopHelmets()
self.heldObject = None
return
def enterVictory(self):
self.resetBattles()
self.suitsKilled.append({'type': None,
'level': None,
'track': self.dna.dept,
'isSkelecog': 0,
'isForeman': 0,
'isVP': 0,
'isCFO': 1,
'isSupervisor': 0,
'isVirtual': 0,
'activeToons': self.involvedToons[:]})
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)
for toonId in self.involvedToons:
toon = self.air.doId2do.get(toonId)
if toon:
toon.addResistanceMessage(self.rewardId)
toon.b_promote(self.deptIndex)
def exitVictory(self):
self.__deleteBattleThreeObjects()
def enterEpilogue(self):
DistributedBossCogAI.DistributedBossCogAI.enterEpilogue(self)
self.d_setRewardId(self.rewardId)
@magicWord(category=CATEGORY_ADMINISTRATOR)
def restartCraneRound():
"""
Restarts the crane round in the CFO.
"""
invoker = spellbook.getInvoker()
boss = None
for do in simbase.air.doId2do.values():
if isinstance(do, DistributedCashbotBossAI):
if invoker.doId in do.involvedToons:
boss = do
break
if not boss:
return "You aren't in a CFO!"
boss.exitIntroduction()
boss.b_setState('PrepareBattleThree')
boss.b_setState('BattleThree')
return 'Restarting the crane round...'
@magicWord(category=CATEGORY_ADMINISTRATOR)
def skipCFO():
"""
Skips to the final round of the CFO.
"""
invoker = spellbook.getInvoker()
boss = None
for do in simbase.air.doId2do.values():
if isinstance(do, DistributedCashbotBossAI):
if invoker.doId in do.involvedToons:
boss = do
break
if not boss:
return "You aren't in a CFO!"
if boss.state in ('PrepareBattleThree', 'BattleThree'):
return "You can't skip this round."
boss.exitIntroduction()
boss.b_setState('PrepareBattleThree')
return 'Skipping the first round...'