spellbook: Boss battle create/manip magic words.
This commit is contained in:
parent
5c0ca00131
commit
8051c15e89
16 changed files with 238 additions and 7 deletions
|
@ -714,8 +714,6 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas
|
|||
empty = InventoryBase.InventoryBase(toon)
|
||||
toon.b_setInventory(empty.makeNetString())
|
||||
toon.b_setHp(0)
|
||||
db = DatabaseObject.DatabaseObject(self.air, toonId)
|
||||
db.storeObject(toon, ['setInventory', 'setHp'])
|
||||
self.notify.info('killing mem leak from temporary DistributedToonAI %d' % toonId)
|
||||
toon.deleteDummy()
|
||||
return
|
||||
|
|
|
@ -9,7 +9,7 @@ class BossbotHQBossBattle(CogHQBossBattle.CogHQBossBattle):
|
|||
|
||||
def __init__(self, loader, parentFSM, doneEvent):
|
||||
CogHQBossBattle.CogHQBossBattle.__init__(self, loader, parentFSM, doneEvent)
|
||||
self.teleportInPosHpr = (88, -214, 0, 210, 0, 0)
|
||||
self.teleportInPosHpr = (-1.40, 59.78, 0, 360, 0, 0)
|
||||
for stateName in ['movie']:
|
||||
state = self.fsm.getStateNamed(stateName)
|
||||
state.addTransition('crane')
|
||||
|
|
|
@ -110,11 +110,21 @@ class CogHQBossBattle(BattlePlace.BattlePlace):
|
|||
self.bossCog = bossCog
|
||||
if self.bossCog:
|
||||
self.bossCog.d_avatarEnter()
|
||||
else:
|
||||
# HACK: For some reason, when teleporting to a boss via a magic word, the place may load
|
||||
# first instead of the boss cog. So listen to when the boss is generated.
|
||||
self.acceptOnce('announceBoss', self.__bossGenerate)
|
||||
self._telemLimiter = TLGatherAllAvs('CogHQBossBattle', RotationLimitToH)
|
||||
NametagGlobals.setMasterArrowsOn(1)
|
||||
base.localAvatar.inventory.setRespectInvasions(0)
|
||||
self.fsm.request(requestStatus['how'], [requestStatus])
|
||||
|
||||
def __bossGenerate(self, boss):
|
||||
if self.bossCog:
|
||||
return
|
||||
self.bossCog = boss
|
||||
self.bossCog.d_avatarEnter()
|
||||
|
||||
def exit(self):
|
||||
self.fsm.requestFinalState()
|
||||
base.localAvatar.inventory.setRespectInvasions(1)
|
||||
|
|
|
@ -143,6 +143,7 @@ class CogHQLoader(StateData.StateData):
|
|||
def enterCogHQBossBattle(self, requestStatus):
|
||||
self.placeClass = self.getBossPlaceClass()
|
||||
self.enterPlace(requestStatus)
|
||||
self.hood.hideTitleText()
|
||||
|
||||
def exitCogHQBossBattle(self):
|
||||
self.exitPlace()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from panda3d.core import *
|
||||
from panda3d.physics import *
|
||||
from direct.interval.IntervalGlobal import *
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
from direct.distributed import DistributedSmoothNode
|
||||
|
|
|
@ -9,7 +9,7 @@ class LawbotHQBossBattle(CogHQBossBattle.CogHQBossBattle):
|
|||
|
||||
def __init__(self, loader, parentFSM, doneEvent):
|
||||
CogHQBossBattle.CogHQBossBattle.__init__(self, loader, parentFSM, doneEvent)
|
||||
self.teleportInPosHpr = (88, -214, 0, 210, 0, 0)
|
||||
self.teleportInPosHpr = (-2.84, -99.47, 0, 360, 0, 0)
|
||||
|
||||
def load(self):
|
||||
CogHQBossBattle.CogHQBossBattle.load(self)
|
||||
|
|
|
@ -9,7 +9,7 @@ class SellbotHQBossBattle(CogHQBossBattle.CogHQBossBattle):
|
|||
|
||||
def __init__(self, loader, parentFSM, doneEvent):
|
||||
CogHQBossBattle.CogHQBossBattle.__init__(self, loader, parentFSM, doneEvent)
|
||||
self.teleportInPosHpr = (0, 95, 18, 180, 0, 0)
|
||||
self.teleportInPosHpr = (0, 61, 18, 180, 0, 0)
|
||||
|
||||
def load(self):
|
||||
CogHQBossBattle.CogHQBossBattle.load(self)
|
||||
|
|
|
@ -192,7 +192,8 @@ class PlayGame(StateData.StateData):
|
|||
if how in ['tunnelIn',
|
||||
'teleportIn',
|
||||
'doorIn',
|
||||
'elevatorIn']:
|
||||
'elevatorIn',
|
||||
'movie']:
|
||||
self.fsm.request('quietZone', [doneStatus])
|
||||
else:
|
||||
self.notify.error('Exited hood with unexpected mode %s' % how)
|
||||
|
|
|
@ -250,6 +250,9 @@ class MaxToon(MagicWord):
|
|||
|
||||
def handleWord(self, invoker, avId, toon, *args):
|
||||
from toontown.toonbase import ToontownGlobals
|
||||
from toontown.quest import Quests
|
||||
from toontown.suit import SuitDNA
|
||||
from toontown.coghq import CogDisguiseGlobals
|
||||
|
||||
# TODO: Handle this better, like giving out all awards, set the quest tier, stuff like that.
|
||||
# This is mainly copied from Anesidora just so I can better work on things.
|
||||
|
@ -271,6 +274,14 @@ class MaxToon(MagicWord):
|
|||
toon.b_setMoney(toon.maxMoney)
|
||||
toon.b_setBankMoney(toon.maxBankMoney)
|
||||
|
||||
toon.b_setQuests([])
|
||||
toon.b_setQuestCarryLimit(ToontownGlobals.MaxQuestCarryLimit)
|
||||
toon.b_setRewardHistory(Quests.LOOPING_FINAL_TIER, [])
|
||||
|
||||
toon.b_setCogParts([*CogDisguiseGlobals.PartsPerSuitBitmasks])
|
||||
toon.b_setCogTypes([SuitDNA.suitsPerDept - 1] * 4)
|
||||
toon.b_setCogLevels([ToontownGlobals.MaxCogSuitLevel] * 4)
|
||||
|
||||
return f"Successfully maxed {toon.getName()}!"
|
||||
|
||||
class AbortMinigame(MagicWord):
|
||||
|
@ -339,6 +350,115 @@ class Quests(MagicWord):
|
|||
else:
|
||||
return "Valid commands: \"finish\""
|
||||
|
||||
class BossBattle(MagicWord):
|
||||
aliases = ["boss"]
|
||||
desc = "Create a new or manupliate the current boss battle."
|
||||
execLocation = MagicWordConfig.EXEC_LOC_SERVER
|
||||
arguments = [("command", str, True), ("type", str, False, ""), ("start", int, False, 1)]
|
||||
|
||||
def handleWord(self, invoker, avId, toon, *args):
|
||||
command = args[0].lower()
|
||||
type = args[1].lower()
|
||||
start = args[2]
|
||||
|
||||
"""
|
||||
Commands:
|
||||
- create [type] [start: 1]: Creates a boss and teleports to it.
|
||||
- start: Starts/Restarts the battle from the beginning.
|
||||
- stop: Stops the battle by going to the Frolic state.
|
||||
- skip: Skips the boss to the next state (needs getNextState to be implemented).
|
||||
- final: Skips the boss to the final round.
|
||||
- kill: Skips the boss to the Victory state.
|
||||
"""
|
||||
|
||||
# create command shortcut:
|
||||
if command in ("vp", "cfo", "cj", "ceo"):
|
||||
type = command
|
||||
command = "create"
|
||||
try:
|
||||
start = int(args[1])
|
||||
except ValueError:
|
||||
start = 1
|
||||
|
||||
from toontown.suit.DistributedBossCogAI import DistributedBossCogAI
|
||||
boss = None
|
||||
for do in self.air.doId2do.values():
|
||||
if isinstance(do, DistributedBossCogAI):
|
||||
if do.isToonKnown(invoker.doId):
|
||||
boss = do
|
||||
break
|
||||
|
||||
if command == "create":
|
||||
if boss:
|
||||
return "You're already in a boss battle. Please finish this one."
|
||||
if type == "vp":
|
||||
from toontown.suit.DistributedSellbotBossAI import DistributedSellbotBossAI
|
||||
boss = DistributedSellbotBossAI(self.air)
|
||||
elif type == "cfo":
|
||||
from toontown.suit.DistributedCashbotBossAI import DistributedCashbotBossAI
|
||||
boss = DistributedCashbotBossAI(self.air)
|
||||
elif type == "cj":
|
||||
from toontown.suit.DistributedLawbotBossAI import DistributedLawbotBossAI
|
||||
boss = DistributedLawbotBossAI(self.air)
|
||||
elif type == "ceo":
|
||||
from toontown.suit.DistributedBossbotBossAI import DistributedBossbotBossAI
|
||||
boss = DistributedBossbotBossAI(self.air)
|
||||
else:
|
||||
return f"Unknown boss type: \"{type}\""
|
||||
|
||||
zoneId = self.air.allocateZone()
|
||||
boss.generateWithRequired(zoneId)
|
||||
if start:
|
||||
boss.addToon(avId)
|
||||
boss.b_setState('WaitForToons')
|
||||
else:
|
||||
boss.b_setState('Frolic')
|
||||
|
||||
respText = f"Created {type.upper()} boss battle"
|
||||
if not start:
|
||||
respText += " in Frolic state"
|
||||
|
||||
return respText + ", teleporting...", ["cogHQLoader", "cogHQBossBattle", "movie" if start else "teleportIn", boss.getHoodId(), boss.zoneId, 0]
|
||||
|
||||
# The following commands needs the invoker to be in a boss battle.
|
||||
if not boss:
|
||||
return "You ain't in a boss battle! Use the \"create\" command to create a boss battle."
|
||||
|
||||
boss.acceptNewToons()
|
||||
if command == "start":
|
||||
boss.b_setState('WaitForToons')
|
||||
return "Boss battle started!"
|
||||
|
||||
elif command == "stop":
|
||||
boss.b_setState("Frolic")
|
||||
return "Boss battle stopped!"
|
||||
|
||||
elif command == "skip":
|
||||
try:
|
||||
nextState = boss.getNextState()
|
||||
except NotImplementedError:
|
||||
return "\"getNextState\" is not implemented for this boss battle!"
|
||||
if nextState:
|
||||
boss.b_setState(nextState)
|
||||
return f"Skipped to {nextState}!"
|
||||
return f"Cannot skip \"{boss.getCurrentOrNextState()}\" state."
|
||||
|
||||
elif command in ("final", "pie", "crane"):
|
||||
if boss.dept == 'c':
|
||||
boss.b_setState("BattleFour")
|
||||
else:
|
||||
boss.b_setState("BattleThree")
|
||||
return "Skipped to final round!"
|
||||
|
||||
elif command in ("kill", "victory", "finish"):
|
||||
boss.b_setState("Victory")
|
||||
return "Killed the boss!"
|
||||
|
||||
# The create command is already described when the invoker is not in a battle. These are the commands
|
||||
# they can use INSIDE the battle.
|
||||
return respText + f"Unknown command: \"{command}\". Valid commands: \"start\", \"stop\", \"skip\", \"final\", \"kill\"."
|
||||
|
||||
|
||||
# Instantiate all classes defined here to register them.
|
||||
# A bit hacky, but better than the old system
|
||||
for item in list(globals().values()):
|
||||
|
|
|
@ -118,6 +118,9 @@ class DistributedBossCog(DistributedAvatar.DistributedAvatar, BossCog.BossCog):
|
|||
self.bubbleF.setTag('attackCode', str(ToontownGlobals.BossCogFrontAttack))
|
||||
self.bubbleF.stash()
|
||||
|
||||
# HACK: See toontown/coghq/CogHQBossBattle.py
|
||||
messenger.send('announceBoss', [self])
|
||||
|
||||
def disable(self):
|
||||
DistributedAvatar.DistributedAvatar.disable(self)
|
||||
self.battleAId = None
|
||||
|
|
|
@ -685,3 +685,6 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI):
|
|||
|
||||
def doNextAttack(self, task):
|
||||
self.b_setAttackCode(ToontownGlobals.BossCogNoAttack)
|
||||
|
||||
def getNextState(self):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -87,7 +87,7 @@ class DistributedBossbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS
|
|||
self.battleOneBattlesMade = True
|
||||
|
||||
def getHoodId(self):
|
||||
return ToontownGlobals.LawbotHQ
|
||||
return ToontownGlobals.BossbotHQ
|
||||
|
||||
def generateSuits(self, battleNumber):
|
||||
if battleNumber == 1:
|
||||
|
@ -885,3 +885,29 @@ class DistributedBossbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS
|
|||
def toggleMove(self):
|
||||
self.moveAttackAllowed = not self.moveAttackAllowed
|
||||
return self.moveAttackAllowed
|
||||
|
||||
def getNextState(self):
|
||||
currState = self.getCurrentOrNextState()
|
||||
if currState == "Elevator":
|
||||
return "Introduction"
|
||||
elif currState == "Introduction":
|
||||
return "BattleOne"
|
||||
elif currState == "BattleOne":
|
||||
return "PrepareBattleTwo"
|
||||
elif currState == "PrepareBattleTwo":
|
||||
return "BattleTwo"
|
||||
elif currState == "BattleTwo":
|
||||
return "PrepareBattleThree"
|
||||
elif currState == "PrepareBattleThree":
|
||||
return "BattleThree"
|
||||
elif currState == "BattleThree":
|
||||
return "PrepareBattleFour"
|
||||
elif currState == "PrepareBattleFour":
|
||||
return "BattleFour"
|
||||
elif currState == "BattleFour":
|
||||
return "Victory"
|
||||
# Do not skip Victory, weird stuff may happen, like not collecting their rewards.
|
||||
elif currState == "Reward":
|
||||
return "Epilogue"
|
||||
|
||||
return None
|
||||
|
|
|
@ -19,6 +19,7 @@ from toontown.distributed import DelayDelete
|
|||
from toontown.chat import ResistanceChat
|
||||
from toontown.coghq import CogDisguiseGlobals
|
||||
from panda3d.core import *
|
||||
from panda3d.physics import *
|
||||
from panda3d.otp import *
|
||||
import random
|
||||
import math
|
||||
|
@ -482,6 +483,14 @@ class DistributedCashbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM):
|
|||
|
||||
return track
|
||||
|
||||
def moveLocalToonToBattleThreePos(self):
|
||||
# This exists because when skipping to the crane round via a magic word, the toon gets
|
||||
# teleported to the center, taking damage in the progress. This is done to remedy that.
|
||||
i = self.involvedToons.index(localAvatar.doId)
|
||||
if not i:
|
||||
i = 0
|
||||
localAvatar.setPosHpr(*ToontownGlobals.CashbotToonsBattleThreeStartPosHpr[i])
|
||||
|
||||
def makeBossFleeMovie(self):
|
||||
hadEnough = TTLocalizer.CashbotBossHadEnough
|
||||
outtaHere = TTLocalizer.CashbotBossOuttaHere
|
||||
|
@ -758,6 +767,7 @@ class DistributedCashbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM):
|
|||
self.evWalls.unstash()
|
||||
self.midVault.stash()
|
||||
self.__hideResistanceToon()
|
||||
self.moveLocalToonToBattleThreePos()
|
||||
localAvatar.setCameraFov(ToontownGlobals.BossBattleCameraFov)
|
||||
self.generateHealthBar()
|
||||
self.updateHealthBar()
|
||||
|
|
|
@ -477,3 +477,21 @@ class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS
|
|||
def enterEpilogue(self):
|
||||
DistributedBossCogAI.DistributedBossCogAI.enterEpilogue(self)
|
||||
self.d_setRewardId(self.rewardId)
|
||||
|
||||
def getNextState(self):
|
||||
currState = self.getCurrentOrNextState()
|
||||
if currState == "Elevator":
|
||||
return "Introduction"
|
||||
elif currState == "Introduction":
|
||||
return "BattleOne"
|
||||
elif currState == "BattleOne":
|
||||
return "PrepareBattleThree"
|
||||
elif currState == "PrepareBattleThree":
|
||||
return "BattleThree"
|
||||
elif currState == "BattleThree":
|
||||
return "Victory"
|
||||
# Do not skip Victory, weird stuff may happen, like not collecting their rewards.
|
||||
elif currState == "Reward":
|
||||
return "Epilogue"
|
||||
|
||||
return None
|
||||
|
|
|
@ -856,3 +856,23 @@ class DistributedLawbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM
|
|||
if battleDifficulty >= numDifficultyLevels:
|
||||
battleDifficulty = numDifficultyLevels - 1
|
||||
self.b_setBattleDifficulty(battleDifficulty)
|
||||
|
||||
def getNextState(self):
|
||||
currState = self.getCurrentOrNextState()
|
||||
if currState == "Elevator":
|
||||
return "Introduction"
|
||||
elif currState == "Introduction":
|
||||
return "BattleOne"
|
||||
elif currState == "BattleOne":
|
||||
return "RollToBattleTwo"
|
||||
elif currState == "RollToBattleTwo":
|
||||
return "PrepareBattleTwo"
|
||||
elif currState in ("PrepareBattleTwo", "BattleTwo"):
|
||||
return "PrepareBattleThree"
|
||||
elif currState in ("PrepareBattleThree", "BattleThree", "NearVictory"):
|
||||
return "Victory"
|
||||
# Do not skip Victory, weird stuff may happen, like not collecting their rewards.
|
||||
elif currState == "Reward":
|
||||
return "Epilogue"
|
||||
|
||||
return None
|
||||
|
|
|
@ -452,3 +452,23 @@ class DistributedSellbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS
|
|||
barrel.requestDelete()
|
||||
|
||||
self.barrels = []
|
||||
|
||||
def getNextState(self):
|
||||
currState = self.getCurrentOrNextState()
|
||||
if currState == "Elevator":
|
||||
return "Introduction"
|
||||
elif currState == "Introduction":
|
||||
return "BattleOne"
|
||||
elif currState == "BattleOne":
|
||||
return "RollToBattleTwo"
|
||||
elif currState == "RollToBattleTwo":
|
||||
return "PrepareBattleTwo"
|
||||
elif currState in ("PrepareBattleTwo", "BattleTwo"):
|
||||
return "PrepareBattleThree"
|
||||
elif currState in ("PrepareBattleThree", "BattleThree", "NearVictory"):
|
||||
return "Victory"
|
||||
# Do not skip Victory, weird stuff may happen, like not collecting their rewards.
|
||||
elif currState == "Reward":
|
||||
return "Epilogue"
|
||||
|
||||
return None
|
||||
|
|
Loading…
Reference in a new issue