3618 lines
143 KiB
Python
3618 lines
143 KiB
Python
# python imports
|
|
import string
|
|
import time
|
|
import random
|
|
import datetime
|
|
|
|
# panda3d imports
|
|
from pandac.PandaModules import *
|
|
from direct.showbase import PythonUtil
|
|
from direct.task import Task
|
|
|
|
# toontown imports
|
|
from otp.ai.AIBaseGlobal import *
|
|
from otp.ai.AIZoneData import AIZoneData
|
|
from direct.distributed import DistributedObjectAI
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from toontown.toon import InventoryBase
|
|
from toontown.toonbase import ToontownGlobals
|
|
from toontown.toonbase import ToontownBattleGlobals
|
|
from toontown.suit import DistributedSuitPlannerAI
|
|
from toontown.battle import DistributedBattleBaseAI
|
|
from toontown.toon import DistributedToonAI
|
|
from . import WelcomeValleyManagerAI
|
|
from toontown.hood import ZoneUtil
|
|
from toontown.battle import SuitBattleGlobals
|
|
from toontown.quest import Quests
|
|
from toontown.minigame import MinigameCreatorAI
|
|
from toontown.estate import DistributedPhoneAI
|
|
from toontown.suit import DistributedBossCogAI
|
|
from toontown.suit import DistributedSellbotBossAI
|
|
from toontown.suit import DistributedCashbotBossAI
|
|
from toontown.suit import DistributedLawbotBossAI
|
|
from toontown.suit import DistributedBossbotBossAI
|
|
from toontown.catalog import CatalogItemList
|
|
from toontown.pets import PetTricks
|
|
from toontown.suit import SuitDNA
|
|
from toontown.toon import ToonDNA
|
|
from toontown.toonbase import TTLocalizer
|
|
from otp.ai import MagicWordManagerAI
|
|
from toontown.estate import GardenGlobals
|
|
from otp.otpbase import OTPGlobals
|
|
from toontown.golf import GolfManagerAI
|
|
from toontown.golf import GolfGlobals
|
|
from toontown.parties import PartyGlobals
|
|
from toontown.parties import PartyUtils
|
|
from toontown.uberdog.DataStoreAIClient import DataStoreAIClient
|
|
from toontown.uberdog import DataStoreGlobals
|
|
|
|
if (simbase.wantKarts):
|
|
from toontown.racing.KartDNA import *
|
|
|
|
class ToontownMagicWordManagerAI(MagicWordManagerAI.MagicWordManagerAI):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory("ToontownMagicWordManagerAI")
|
|
|
|
GameAvatarClass = DistributedToonAI.DistributedToonAI
|
|
|
|
# is it a safezone?
|
|
Str2szId = {
|
|
'ttc': ToontownGlobals.ToontownCentral,
|
|
'tt': ToontownGlobals.ToontownCentral,
|
|
'tc': ToontownGlobals.ToontownCentral,
|
|
'dd': ToontownGlobals.DonaldsDock,
|
|
'dg': ToontownGlobals.DaisyGardens,
|
|
'mml': ToontownGlobals.MinniesMelodyland,
|
|
'mm': ToontownGlobals.MinniesMelodyland,
|
|
'br': ToontownGlobals.TheBrrrgh,
|
|
'ddl': ToontownGlobals.DonaldsDreamland,
|
|
'dl': ToontownGlobals.DonaldsDreamland,
|
|
}
|
|
|
|
|
|
def __init__(self, air):
|
|
MagicWordManagerAI.MagicWordManagerAI.__init__(self, air)
|
|
self.__bossBattleZoneId = [None, None, None, None]
|
|
self.__bossCog = [None, None, None, None]
|
|
|
|
def doMagicWord(self, word, av, zoneId, senderId):
|
|
def wordIs(w, word=word):
|
|
return word[:(len(w)+1)] == ('%s ' % w) or word == w
|
|
|
|
if (MagicWordManagerAI.MagicWordManagerAI.doMagicWord(self, word, av,
|
|
zoneId, senderId) == 1):
|
|
pass
|
|
elif word == "~allstuff":
|
|
av.inventory.maxOutInv()
|
|
av.d_setInventory(av.inventory.makeNetString())
|
|
self.notify.debug("Maxing out inventory for " + av.name)
|
|
elif word == "~nostuff":
|
|
av.inventory.zeroInv(1)
|
|
av.d_setInventory(av.inventory.makeNetString())
|
|
self.notify.debug("Zeroing inventory for " + av.name)
|
|
elif word == "~restock":
|
|
av.doRestock(1)
|
|
elif word == "~restockUber":
|
|
av.doRestock(0)
|
|
|
|
elif word == "~rich":
|
|
av.b_setMoney(av.maxMoney)
|
|
av.b_setBankMoney(av.maxBankMoney)
|
|
self.notify.debug(av.name + " is now rich")
|
|
elif word == "~poor":
|
|
av.b_setMoney(0)
|
|
av.b_setBankMoney(0)
|
|
self.notify.debug(av.name + " is now poor")
|
|
elif wordIs("~jelly"):
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
count = int(args[1])
|
|
# this will just fill up the pocketbook,
|
|
# but wont add to the bank
|
|
av.b_setMoney(min(count, av.getMaxMoney()))
|
|
else:
|
|
av.b_setMoney(av.getMaxMoney())
|
|
elif wordIs("~bank"):
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
count = int(args[1])
|
|
av.b_setBankMoney(count)
|
|
else:
|
|
av.b_setBankMoney(av.getMaxBankMoney())
|
|
elif wordIs("~maxBankMoney"):
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
count = int(args[1])
|
|
av.b_setMaxBankMoney(count)
|
|
response = "Max bank money set to %s" % (av.getMaxBankMoney())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
else:
|
|
response = "Max bank money is %s" % (av.getMaxBankMoney())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs("~pie"):
|
|
# Give ourselves a pie. Or four.
|
|
count = 0
|
|
type = None
|
|
args = word.split()
|
|
if len(args) == 1:
|
|
count = 1
|
|
for arg in args[1:]:
|
|
from toontown.toonbase import ToontownBattleGlobals
|
|
if arg in ToontownBattleGlobals.pieNames:
|
|
type = ToontownBattleGlobals.pieNames.index(arg)
|
|
else:
|
|
try:
|
|
count = int(arg)
|
|
except:
|
|
response = "Invalid pie argument: %s" % (arg)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
return
|
|
|
|
if type != None:
|
|
av.b_setPieType(type)
|
|
av.b_setNumPies(av.numPies + count)
|
|
|
|
elif word == "~amateur":
|
|
av.b_setTrackAccess([0, 0, 0, 0, 1, 1, 0])
|
|
av.b_setMaxCarry(20)
|
|
av.b_setQuestCarryLimit(1)
|
|
av.experience.zeroOutExp()
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
av.b_setMaxHp(15)
|
|
av.b_setHp(15)
|
|
newInv = InventoryBase.InventoryBase(av)
|
|
newInv.maxOutInv()
|
|
av.inventory.setToMin(newInv.inventory)
|
|
av.d_setInventory(av.inventory.makeNetString())
|
|
self.notify.debug("Default exp for " + av.name)
|
|
elif word == "~amateur+":
|
|
av.experience.setAllExp(9)
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
av.b_setMaxHp(30)
|
|
av.b_setHp(30)
|
|
# make sure we're not over maxProps too
|
|
newInv = InventoryBase.InventoryBase(av)
|
|
newInv.maxOutInv()
|
|
av.inventory.setToMin(newInv.inventory)
|
|
av.d_setInventory(av.inventory.makeNetString())
|
|
self.notify.debug("Setting exp to 9 for " + av.name)
|
|
elif word == "~professional":
|
|
av.b_setTrackAccess([1, 1, 1, 1, 1, 1, 1])
|
|
av.b_setMaxCarry(ToontownGlobals.MaxCarryLimit)
|
|
av.b_setQuestCarryLimit(ToontownGlobals.MaxQuestCarryLimit)
|
|
av.experience.maxOutExp()
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
av.b_setMaxHp(ToontownGlobals.MaxHpLimit)
|
|
av.b_setHp(ToontownGlobals.MaxHpLimit)
|
|
self.notify.debug("Max exp for " + av.name)
|
|
elif word == "~professional--":
|
|
av.b_setTrackAccess([1, 1, 1, 1, 1, 1, 1])
|
|
av.b_setMaxCarry(ToontownGlobals.MaxCarryLimit)
|
|
av.b_setQuestCarryLimit(ToontownGlobals.MaxQuestCarryLimit)
|
|
av.experience.makeExpHigh()
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
av.b_setMaxHp(ToontownGlobals.MaxHpLimit-15)
|
|
av.b_setHp(ToontownGlobals.MaxHpLimit-15)
|
|
self.notify.debug("High exp for " + av.name)
|
|
elif word == "~regularToon":
|
|
pickTrack = ([1, 1, 1, 1, 1, 1, 0],
|
|
[1, 1, 1, 0, 1, 1, 1],
|
|
[0, 1, 1, 1, 1, 1, 1],
|
|
[1, 0, 1, 1, 1, 1, 1])
|
|
av.b_setTrackAccess(random.choice(pickTrack))
|
|
av.b_setMaxCarry(ToontownGlobals.MaxCarryLimit)
|
|
av.b_setQuestCarryLimit(ToontownGlobals.MaxQuestCarryLimit)
|
|
av.experience.makeExpRegular()
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
laughminus = int(random.random() * 20.0) + 10.0
|
|
av.b_setMaxHp(ToontownGlobals.MaxHpLimit-laughminus)
|
|
av.b_setHp(ToontownGlobals.MaxHpLimit-laughminus)
|
|
self.notify.debug("regular exp for " + av.name)
|
|
elif word == "~maxexp--":
|
|
av.b_setTrackAccess([1, 1, 1, 1, 1, 1, 1])
|
|
av.b_setMaxCarry(ToontownGlobals.MaxCarryLimit)
|
|
av.b_setQuestCarryLimit(ToontownGlobals.MaxQuestCarryLimit)
|
|
av.experience.maxOutExpMinusOne()
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
av.b_setMaxHp(ToontownGlobals.MaxHpLimit)
|
|
av.b_setHp(ToontownGlobals.MaxHpLimit)
|
|
self.notify.debug("Max exp-- for " + av.name)
|
|
elif wordIs('~mintRaider'):
|
|
av.experience.maxOutExp()
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
av.b_setQuestHistory([])
|
|
av.b_setRewardHistory(Quests.DL_TIER+2, [])
|
|
av.fixAvatar()
|
|
# 7LP for fishing, + 5LP for SellbotHQ, /2
|
|
av.b_setMaxHp(av.getMaxHp()+6)
|
|
av.b_setHp(av.getMaxHp())
|
|
trackAccess = [1, 1, 1, 1, 1, 1, 1]
|
|
trackAccess[random.choice((0, 1, 2, 3, 6))] = 0
|
|
av.b_setTrackAccess(trackAccess)
|
|
|
|
elif word[:4] == "~exp":
|
|
self.doExp(word, av, zoneId, senderId)
|
|
|
|
elif word[:7] == "~trophy":
|
|
self.doTrophy(word, av, zoneId, senderId)
|
|
|
|
elif word == "~trophies":
|
|
# Report the top 10 trophy holders.
|
|
scores = self.air.trophyMgr.getSortedScores()
|
|
response = ''
|
|
for i in range(min(len(scores), 10)):
|
|
score, avId = scores[i]
|
|
av = self.air.doId2do.get(avId, None)
|
|
if av:
|
|
avName = av.name
|
|
else:
|
|
avName = avId
|
|
response += '%s %s\n' % (score, avName)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif word[:8] == "~effect ":
|
|
# Apply a cheesy rendering effect.
|
|
self.doCheesyEffect(word, av, zoneId, senderId)
|
|
|
|
elif word[:12] == "~cogTakeOver":
|
|
self.doCogTakeOver(word, av, zoneId, senderId)
|
|
|
|
elif wordIs("~cogdoTakeOver"):
|
|
if simbase.air.wantCogdominiums:
|
|
self.doCogdoTakeOver(word, av, zoneId, senderId)
|
|
|
|
elif word[:13] == "~toonTakeOver":
|
|
self.doToonTakeOver(word, av, zoneId, senderId)
|
|
|
|
elif word[:8] == "~welcome":
|
|
self.doWelcome(word, av, zoneId, senderId)
|
|
|
|
elif word == "~finishTutorial":
|
|
av.b_setTutorialAck(1)
|
|
av.b_setQuests([])
|
|
av.b_setQuestHistory([])
|
|
av.b_setRewardHistory(2, [])
|
|
av.fixAvatar()
|
|
self.down_setMagicWordResponse(senderId, "Finished tutorial.")
|
|
|
|
elif word == "~finishQuests":
|
|
self.air.questManager.completeAllQuestsMagically(av)
|
|
self.down_setMagicWordResponse(senderId, "Finished quests.")
|
|
|
|
elif word[:12] == "~finishQuest":
|
|
args = word.split()
|
|
index = int(args[1])
|
|
result = self.air.questManager.completeQuestMagically(av, index)
|
|
if result:
|
|
self.down_setMagicWordResponse(senderId, ("Finished quest %s." % (index)))
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, ("Quest %s not found." % (index)))
|
|
|
|
elif word == "~clearQuests":
|
|
# Reset all quest fields as if this were a new toon
|
|
av.b_setQuests([])
|
|
av.b_setQuestHistory([])
|
|
currentTier = av.getRewardTier()
|
|
av.b_setRewardHistory(currentTier, [])
|
|
self.down_setMagicWordResponse(senderId, "Cleared quests.")
|
|
|
|
elif word == "~getQuestTier":
|
|
# Report the current quest tier
|
|
response = "tier %d" % (av.getRewardTier())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif word[:13] == "~setQuestTier":
|
|
# Sets reward tier and optionally index
|
|
args = word.split()
|
|
tier = int(args[1])
|
|
tier = min(tier, Quests.getNumTiers())
|
|
av.b_setQuestHistory([])
|
|
av.b_setRewardHistory(tier, [])
|
|
av.fixAvatar()
|
|
|
|
elif word[:12] == "~assignQuest":
|
|
# Intelligently assigns a quest
|
|
args = word.split()
|
|
questId = int(args[1])
|
|
|
|
# Make sure this quest exists
|
|
questDesc = Quests.QuestDict.get(questId)
|
|
if questDesc is None:
|
|
self.down_setMagicWordResponse(senderId, "Quest %s not found" % (questId))
|
|
return
|
|
|
|
# Make sure the av is in that tier
|
|
avTier = av.getRewardTier()
|
|
tier = questDesc[Quests.QuestDictTierIndex]
|
|
if tier != avTier:
|
|
self.down_setMagicWordResponse(senderId, "Avatar not in that tier: %s. You can ~setQuestTier %s, if you want." % (tier, tier))
|
|
return
|
|
|
|
# Make sure the av has room for this quest
|
|
if not self.air.questManager.needsQuest(av):
|
|
self.down_setMagicWordResponse(senderId, "Quests are already full")
|
|
return
|
|
|
|
# Make sure the av does not already have this quest
|
|
for questDesc in av.quests:
|
|
if questId == questDesc[0]:
|
|
self.down_setMagicWordResponse(senderId, "Already has quest: %s" % (questId))
|
|
return
|
|
|
|
# Should we check your reward history too?
|
|
|
|
fromNpcId = Quests.ToonHQ # A reasonable default
|
|
|
|
rewardId = Quests.getQuestReward(questId, av)
|
|
# Some quests do not have a reward specified. Instead they have
|
|
# the keyword <Any> which tells the quest system to try to
|
|
# match something up. In our case, we are not going through
|
|
# normal channels, so just pick some reward so things do not
|
|
# crash. How about some jellybeans?
|
|
if rewardId == Quests.Any:
|
|
# Just give 100 jellybeans (rewardId = 604 from Quests.py)
|
|
rewardId = 604
|
|
|
|
toNpcId = Quests.getQuestToNpcId(questId)
|
|
# Account for some trickery in the quest description
|
|
# If the toNpcId is marked <Any> or <Same> let's just use ToonHQ
|
|
if toNpcId == Quests.Any:
|
|
toNpcId = Quests.ToonHQ
|
|
elif toNpcId == Quests.Same:
|
|
toNpcId = Quests.ToonHQ
|
|
|
|
startingQuest = Quests.isStartingQuest(questId)
|
|
self.air.questManager.assignQuest(av.doId,
|
|
fromNpcId,
|
|
questId,
|
|
rewardId,
|
|
toNpcId,
|
|
startingQuest,
|
|
)
|
|
self.down_setMagicWordResponse(senderId, "Quest %s assigned" % (questId))
|
|
|
|
elif wordIs("~nextQuest"):
|
|
# forces NPCs to offer you a particular quest
|
|
args = word.split()
|
|
if len(args) == 1:
|
|
# clear any existing request
|
|
questId = self.air.questManager.cancelNextQuest(av.doId)
|
|
if questId:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "Cancelled request for quest %s" % (questId))
|
|
return
|
|
|
|
questId = int(args[1])
|
|
|
|
# Make sure this quest exists
|
|
questDesc = Quests.QuestDict.get(questId)
|
|
if questDesc is None:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "Quest %s not found" % (questId))
|
|
return
|
|
|
|
# Make sure the av is in that tier
|
|
avTier = av.getRewardTier()
|
|
tier = questDesc[Quests.QuestDictTierIndex]
|
|
if tier != avTier:
|
|
self.down_setMagicWordResponse(senderId, "Avatar not in that tier: %s. You can ~setQuestTier %s, if you want." % (tier, tier))
|
|
return
|
|
|
|
# Make sure the av does not already have this quest
|
|
for questDesc in av.quests:
|
|
if questId == questDesc[0]:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "Already has quest: %s" % (questId))
|
|
return
|
|
|
|
self.air.questManager.setNextQuest(av.doId, questId)
|
|
self.down_setMagicWordResponse(senderId,
|
|
"Quest %s queued" % (questId))
|
|
|
|
elif word == "~visitHQ":
|
|
# Sets quests to return to HQ Officer instead of whomever.
|
|
# Saves walking all over the map to test quests.
|
|
for quest in av.quests:
|
|
quest[2] = Quests.ToonHQ
|
|
av.b_setQuests(av.quests)
|
|
|
|
elif wordIs('~teleportAll'):
|
|
av.b_setHoodsVisited(ToontownGlobals.HoodsForTeleportAll)
|
|
av.b_setTeleportAccess(ToontownGlobals.HoodsForTeleportAll)
|
|
|
|
elif word[:10] == "~buildings":
|
|
self.doBuildings(word, av, zoneId, senderId)
|
|
|
|
elif word[:16] == "~buildingPercent":
|
|
self.doBuildingPercent(word, av, zoneId, senderId)
|
|
|
|
elif wordIs('~call'):
|
|
self.doCall(word, av, zoneId, senderId)
|
|
|
|
elif wordIs('~battle'):
|
|
self.doBattle(word, av, zoneId, senderId)
|
|
|
|
elif word[:5] == "~cogs":
|
|
self.doCogs(word, av, zoneId, senderId)
|
|
|
|
# Suit Invasions
|
|
elif word[:12] == "~getInvasion":
|
|
self.getCogInvasion(word, av, zoneId, senderId)
|
|
elif word[:14] == "~startInvasion":
|
|
self.doCogInvasion(word, av, zoneId, senderId)
|
|
elif word[:13] == "~stopInvasion":
|
|
self.stopCogInvasion(word, av, zoneId, senderId)
|
|
|
|
# Fireworks
|
|
elif word[:18] == "~startAllFireworks":
|
|
self.startAllFireworks(word, av, zoneId, senderId)
|
|
elif word[:15] == "~startFireworks":
|
|
self.startFireworks(word, av, zoneId, senderId)
|
|
elif word[:14] == "~stopFireworks":
|
|
self.stopFireworks(word, av, zoneId, senderId)
|
|
elif word[:17] == "~stopAllFireworks":
|
|
self.stopAllFireworks(word, av, zoneId, senderId)
|
|
|
|
elif word == "~save":
|
|
# Save the AI state. Presently, this is just the set of
|
|
# buildings.
|
|
self.air.saveBuildings()
|
|
|
|
response = "Building state saved."
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif word[:9] == "~minigame":
|
|
self.doMinigame(word, av, zoneId, senderId)
|
|
|
|
elif wordIs('~factory'):
|
|
# select which factory to enter
|
|
# AI-global for now
|
|
from toontown.coghq import FactoryManagerAI
|
|
args = word.split()
|
|
if len(args) == 1:
|
|
# no arguments given
|
|
if FactoryManagerAI.FactoryManagerAI.factoryId is None:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "usage: ~factory [id]")
|
|
else:
|
|
fId = FactoryManagerAI.FactoryManagerAI.factoryId
|
|
FactoryManagerAI.FactoryManagerAI.factoryId = None
|
|
self.down_setMagicWordResponse(
|
|
senderId, "cancelled request for factory %s" % fId)
|
|
else:
|
|
factoryId = int(args[1])
|
|
if not factoryId in ToontownGlobals.factoryId2factoryType:
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"unknown factory '%s'" % factoryId)
|
|
else:
|
|
FactoryManagerAI.FactoryManagerAI.factoryId = factoryId
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"selected factory %s" % factoryId)
|
|
|
|
elif wordIs('~mintId'):
|
|
args = word.split()
|
|
postName = 'mintId-%s' % av.doId
|
|
if len(args) < 2:
|
|
if bboard.has(postName):
|
|
bboard.remove(postName)
|
|
response = 'cleared mint request'
|
|
else:
|
|
response = '~mintId id'
|
|
else:
|
|
try:
|
|
id = int(args[1])
|
|
# make sure it's a valid id
|
|
foo = ToontownGlobals.MintNumRooms[id]
|
|
except:
|
|
response = 'bad mint id: %s' % args[1]
|
|
else:
|
|
bboard.post(postName, id)
|
|
response = 'selected mint %s' % id
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~mintFloor'):
|
|
args = word.split()
|
|
postName = 'mintFloor-%s' % av.doId
|
|
if len(args) < 2:
|
|
if bboard.has(postName):
|
|
bboard.remove(postName)
|
|
response = 'cleared mint floor request'
|
|
else:
|
|
response = '~mintFloor num'
|
|
else:
|
|
try:
|
|
floor = int(args[1])
|
|
except:
|
|
response = 'bad floor index: %s' % args[1]
|
|
else:
|
|
bboard.post(postName, floor)
|
|
response = 'selected floor %s' % floor
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~mintRoom'):
|
|
args = word.split()
|
|
postName = 'mintRoom-%s' % av.doId
|
|
if len(args) < 2:
|
|
if bboard.has(postName):
|
|
bboard.remove(postName)
|
|
response = 'cleared mint room request'
|
|
else:
|
|
response = '~mintRoom <id|name>'
|
|
else:
|
|
from toontown.coghq import MintRoomSpecs
|
|
id = None
|
|
name = None
|
|
try:
|
|
id = int(args[1])
|
|
name = MintRoomSpecs.CashbotMintRoomId2RoomName[id]
|
|
except:
|
|
if args[1] in MintRoomSpecs.CashbotMintRoomName2RoomId:
|
|
name = args[1]
|
|
id = MintRoomSpecs.CashbotMintRoomName2RoomId[name]
|
|
else:
|
|
response = 'invalid room: %s' % args[1]
|
|
bboard.post(postName, id)
|
|
response = 'selected mint room %s: %s' % (id, name)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~stageRoom'):
|
|
args = word.split()
|
|
postName = 'stageRoom-%s' % av.doId
|
|
if len(args) < 2:
|
|
if bboard.has(postName):
|
|
bboard.remove(postName)
|
|
response = 'cleared stage room request'
|
|
else:
|
|
response = '~stageRoom <id|name>'
|
|
else:
|
|
from toontown.coghq import StageRoomSpecs
|
|
id = None
|
|
name = None
|
|
try:
|
|
id = int(args[1])
|
|
name = StageRoomSpecs.CashbotStageRoomId2RoomName[id]
|
|
except:
|
|
if args[1] in StageRoomSpecs.CashbotStageRoomName2RoomId:
|
|
name = args[1]
|
|
id = StageRoomSpecs.CashbotStageRoomName2RoomId[name]
|
|
else:
|
|
response = 'invalid room: %s' % args[1]
|
|
bboard.post(postName, id)
|
|
response = 'selected stage room %s: %s' % (id, name)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs("~autoRestock"):
|
|
args = word.split()
|
|
postName = 'autoRestock-%s' % av.doId
|
|
enable = not bboard.get(postName, 0)
|
|
# are they explicitly setting the state?
|
|
if len(args) > 1:
|
|
try:
|
|
enable = int(args[1])
|
|
except:
|
|
self.down_setMagicWordResponse(senderId,
|
|
'invalid state flag: %s' %
|
|
args[1])
|
|
return
|
|
if enable:
|
|
state = 'ON'
|
|
bboard.post(postName, 1)
|
|
else:
|
|
state = 'OFF'
|
|
bboard.remove(postName)
|
|
self.down_setMagicWordResponse(senderId, 'autoRestock %s' % state)
|
|
|
|
elif wordIs("~resistanceRestock"):
|
|
from toontown.chat import ResistanceChat
|
|
args = word.split()
|
|
if len(args) < 2:
|
|
charges = 10
|
|
else:
|
|
charges = int(args[1])
|
|
msgs = []
|
|
for menuIndex in ResistanceChat.resistanceMenu:
|
|
for itemIndex in ResistanceChat.getItems(menuIndex):
|
|
textId = ResistanceChat.encodeId(menuIndex, itemIndex)
|
|
msgs.append([textId, charges])
|
|
av.b_setResistanceMessages(msgs)
|
|
response = 'Resistance phrases restocked - %d charges' % charges
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs("~restockSummons"):
|
|
numSuits = len(SuitDNA.suitHeadTypes)
|
|
fullSetForSuit = 0x01 | 0x02 | 0x04
|
|
allSummons = numSuits * [fullSetForSuit]
|
|
av.b_setCogSummonsEarned(allSummons)
|
|
self.down_setMagicWordResponse(senderId, "Summons restocked")
|
|
|
|
elif wordIs("~clearSummons"):
|
|
numSuits = len(SuitDNA.suitHeadTypes)
|
|
allSummons = numSuits * [0]
|
|
av.b_setCogSummonsEarned(allSummons)
|
|
self.down_setMagicWordResponse(senderId, "Summons emptied")
|
|
|
|
elif wordIs("~newSummons"):
|
|
args = word.split()
|
|
|
|
level = None
|
|
if len(args) > 1:
|
|
level = int(args[1])
|
|
|
|
if level and (level < 0 or level >= SuitDNA.suitsPerDept):
|
|
self.down_setMagicWordResponse(
|
|
senderId, "usage: ~newSummons [level:0-11]")
|
|
else:
|
|
(suitIndex, type) = av.assignNewCogSummons(level)
|
|
suitName = SuitDNA.suitHeadTypes[suitIndex]
|
|
suitFullName = SuitBattleGlobals.SuitAttributes[suitName]['name']
|
|
self.down_setMagicWordResponse(
|
|
senderId, "%s summons added for %s" % (type, suitFullName))
|
|
|
|
elif wordIs("~treasures"):
|
|
self.doTreasures(word, av, zoneId, senderId)
|
|
|
|
elif wordIs("~emote"):
|
|
self.doEmotes(word, av, zoneId, senderId)
|
|
|
|
elif wordIs("~catalog"):
|
|
self.doCatalog(word, av, zoneId, senderId)
|
|
|
|
elif word == "~resetFurniture":
|
|
house = None
|
|
if av.houseId:
|
|
house = self.air.doId2do.get(av.houseId)
|
|
if house:
|
|
house.setInitialFurniture()
|
|
house.resetFurniture()
|
|
response = "Furniture reset."
|
|
else:
|
|
response = "Could not find house."
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
# Fishing
|
|
elif word == "~clearFishTank":
|
|
av.b_setFishTank([], [], [])
|
|
self.down_setMagicWordResponse(senderId, "Cleared fish tank.")
|
|
|
|
elif word == "~sellFishTank":
|
|
# Add up the total value of all the fish
|
|
totalValue = 0
|
|
totalValue = av.fishTank.getTotalValue()
|
|
# Credit the money
|
|
av.addMoney(totalValue)
|
|
# Clear the fish tank
|
|
av.b_setFishTank([], [], [])
|
|
# Feedback to sender
|
|
self.down_setMagicWordResponse(senderId, ("Sold fish in tank for %s jellbeans." % totalValue))
|
|
|
|
elif word == "~clearFishCollection":
|
|
av.b_setFishCollection([], [], [])
|
|
av.b_setFishingTrophies([])
|
|
self.down_setMagicWordResponse(senderId, "Cleared fish collection.")
|
|
|
|
elif word == "~completeFishCollection":
|
|
from toontown.fishing import FishGlobals
|
|
genusList = []
|
|
speciesList = []
|
|
weightList = []
|
|
for genus in FishGlobals.getGenera():
|
|
numSpecies = len(FishGlobals.getSpecies(genus))
|
|
for species in range(numSpecies):
|
|
weight = FishGlobals.getRandomWeight(genus, species)
|
|
genusList.append(genus)
|
|
speciesList.append(species)
|
|
weightList.append(weight)
|
|
|
|
av.b_setFishCollection(genusList, speciesList, weightList)
|
|
self.down_setMagicWordResponse(senderId, "Complete fish collection.")
|
|
|
|
elif word == "~randomFishTank":
|
|
av.makeRandomFishTank()
|
|
self.down_setMagicWordResponse(senderId, "Created random fishtank")
|
|
|
|
elif word == "~allFishingTrophies":
|
|
from toontown.fishing import FishGlobals
|
|
allTrophyList = FishGlobals.TrophyDict.keys()
|
|
av.b_setFishingTrophies(allTrophyList)
|
|
self.down_setMagicWordResponse(senderId, "All fishing trophies")
|
|
|
|
elif word[:4] == "~rod":
|
|
from toontown.fishing import FishGlobals
|
|
# Sets reward tier and optionally index
|
|
args = word.split()
|
|
rodId = int(args[1])
|
|
if ((rodId > FishGlobals.MaxRodId) or
|
|
(rodId < 0)):
|
|
self.down_setMagicWordResponse(senderId, ("Invalid rod: %s" % (rodId)))
|
|
else:
|
|
av.b_setFishingRod(rodId)
|
|
self.down_setMagicWordResponse(senderId, ("New fishing rod: %s" % (rodId)))
|
|
|
|
|
|
elif wordIs('~inGameEdit'):
|
|
# edit a level in the game engine
|
|
# Note - do not call this as a toon - call ~edit instead. That
|
|
# will automatically append your level doId so the AI knows
|
|
# which one you want to edit, along with your edit username
|
|
|
|
# make sure this AI is set up for editing
|
|
if not __dev__:
|
|
self.down_setMagicWordResponse(senderId,
|
|
"AI not running in dev mode")
|
|
return
|
|
from otp.level import EditorGlobals
|
|
msg = EditorGlobals.checkNotReadyToEdit()
|
|
if msg is not None:
|
|
self.down_setMagicWordResponse(senderId, msg)
|
|
return
|
|
|
|
args = word.split()
|
|
levelDoId = int(args[1])
|
|
editUsername = args[2]
|
|
|
|
level = self.air.doId2do.get(levelDoId)
|
|
if not level:
|
|
self.down_setMagicWordResponse(
|
|
senderId, ("Level %s not found" % levelDoId))
|
|
return
|
|
|
|
from toontown.coghq import DistributedInGameEditorAI
|
|
editor = DistributedInGameEditorAI.DistributedInGameEditorAI(
|
|
self.air, level, senderId, editUsername)
|
|
|
|
self.down_setMagicWordResponse(
|
|
senderId, ("Editing level %s as %s" % (
|
|
levelDoId, editUsername)))
|
|
|
|
elif word[:13] == "~setNPCFriend":
|
|
args = word.split()
|
|
npcId = int(args[1])
|
|
numCalls = int(args[2])
|
|
if self.doNpcFriend(av, npcId, numCalls):
|
|
self.down_setMagicWordResponse(senderId, "added NPC friend")
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "invalid NPC name")
|
|
|
|
elif wordIs("~pianos"):
|
|
if self.doNpcFriend(av, 1116, 100):
|
|
self.down_setMagicWordResponse(senderId, "got pianos")
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "error getting pianos")
|
|
|
|
elif wordIs("~resetNPCFriendsDict"):
|
|
av.resetNPCFriendsDict()
|
|
self.down_setMagicWordResponse(senderId, "Reset NPC Friends Dict")
|
|
|
|
elif wordIs('~uberDrop'):
|
|
from toontown.toon import NPCToons
|
|
if (av.attemptAddNPCFriend(
|
|
1116, DistributedToonAI.DistributedToonAI.maxCallsPerNPC
|
|
) == 1):
|
|
self.down_setMagicWordResponse(senderId, "added NPC friend")
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "failed")
|
|
|
|
elif wordIs("~bossBattle"):
|
|
self.doBossBattle(word, av, zoneId, senderId)
|
|
|
|
elif wordIs('~disguisePage'):
|
|
args = word.split()
|
|
flag = 1
|
|
if len(args) >= 2:
|
|
flag = int(args[1])
|
|
av.b_setDisguisePageFlag(flag)
|
|
self.down_setMagicWordResponse(senderId, "Disguise page = %s" % (flag))
|
|
|
|
elif wordIs("~allParts"):
|
|
from toontown.coghq import CogDisguiseGlobals
|
|
args = word.split()
|
|
for dept in self.getDepts(args):
|
|
parts = av.getCogParts()
|
|
parts[dept] = CogDisguiseGlobals.PartsPerSuitBitmasks[dept]
|
|
|
|
av.b_setCogParts(parts)
|
|
self.down_setMagicWordResponse(senderId, "Set cog parts: %s" % (parts))
|
|
|
|
elif wordIs("~noParts"):
|
|
args = word.split()
|
|
for dept in self.getDepts(args):
|
|
parts = av.getCogParts()
|
|
parts[dept] = 0
|
|
|
|
av.b_setCogParts(parts)
|
|
self.down_setMagicWordResponse(senderId, "Set cog parts: %s" % (parts))
|
|
|
|
elif wordIs("~part"):
|
|
args = word.split()
|
|
depts = self.getDepts(args)
|
|
if len(args) > 1:
|
|
# trust that user typed the factory type correctly...
|
|
factoryType = args[1]
|
|
else:
|
|
factoryType = ToontownGlobals.FT_FullSuit
|
|
|
|
for dept in depts:
|
|
av.giveGenericCogPart(factoryType, dept)
|
|
|
|
self.down_setMagicWordResponse(senderId, "Set cog parts: %s" % (av.getCogParts()))
|
|
|
|
elif wordIs("~merits"):
|
|
args = word.split()
|
|
depts = self.getDepts(args)
|
|
if len(args) > 1:
|
|
numMerits = int(args[1])
|
|
if numMerits > 32767:
|
|
numMerits = 32767
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "Specify number of merits to set.")
|
|
return
|
|
|
|
merits = av.getCogMerits()[:]
|
|
for dept in depts:
|
|
merits[dept] = numMerits
|
|
av.b_setCogMerits(merits)
|
|
|
|
self.down_setMagicWordResponse(senderId, "Set cog merits: %s" % (merits))
|
|
|
|
elif wordIs("~promote"):
|
|
args = word.split()
|
|
depts = self.getDepts(args)
|
|
|
|
for dept in depts:
|
|
av.b_promote(dept)
|
|
|
|
self.down_setMagicWordResponse(senderId, "Set cogTypes: %s and cogLevels: %s" % (av.getCogTypes(), av.getCogLevels()))
|
|
|
|
elif wordIs("~cogSuit"):
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
cogType = args[1]
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "Specify cog type, or 'clear'.")
|
|
return
|
|
|
|
if cogType == 'clear':
|
|
av.b_setCogTypes([0, 0, 0, 0])
|
|
av.b_setCogLevels([0, 0, 0, 0])
|
|
|
|
elif cogType == 'on':
|
|
if len(args) > 2 and args[2] in SuitDNA.suitDepts:
|
|
dept = SuitDNA.suitDepts.index(args[2])
|
|
av.b_setCogIndex(dept)
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "Specify dept.")
|
|
return
|
|
|
|
elif cogType == 'off':
|
|
av.b_setCogIndex(-1)
|
|
return
|
|
|
|
else:
|
|
dept = SuitDNA.getSuitDept(cogType)
|
|
if dept == None:
|
|
self.down_setMagicWordResponse(senderId, "Unknown cog type: %s" % (cogType))
|
|
return
|
|
|
|
deptIndex = SuitDNA.suitDepts.index(dept)
|
|
type = SuitDNA.getSuitType(cogType)
|
|
minLevel = SuitBattleGlobals.SuitAttributes[cogType]['level']
|
|
|
|
# determine max level (usually minLevel + 4, but 50 for last cog)
|
|
if type >= (SuitDNA.suitsPerDept - 1):
|
|
maxLevel = ToontownGlobals.MaxCogSuitLevel + 1
|
|
else:
|
|
maxLevel = minLevel + 4
|
|
|
|
if len(args) > 2:
|
|
level = int(args[2]) - 1
|
|
if level < minLevel or level > maxLevel:
|
|
self.down_setMagicWordResponse(senderId, "Invalid level for %s (should be %s to %s)" % (cogType, minLevel + 1, minLevel + 5))
|
|
return
|
|
else:
|
|
level = minLevel
|
|
|
|
cogTypes = av.getCogTypes()[:]
|
|
cogLevels = av.getCogLevels()[:]
|
|
cogTypes[deptIndex] = type - 1
|
|
cogLevels[deptIndex] = level
|
|
av.b_setCogTypes(cogTypes)
|
|
av.b_setCogLevels(cogLevels)
|
|
|
|
self.down_setMagicWordResponse(senderId, "Set cogTypes: %s and cogLevels: %s" % (av.getCogTypes(), av.getCogLevels()))
|
|
|
|
elif wordIs("~pinkSlips"):
|
|
args = word.split()
|
|
depts = self.getDepts(args)
|
|
if len(args) > 1:
|
|
numSlips = int(args[1])
|
|
if numSlips > 255:
|
|
numSlips = 255
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "Specify number of pinkSlips to set.")
|
|
return
|
|
|
|
av.b_setPinkSlips(numSlips)
|
|
|
|
self.down_setMagicWordResponse(senderId, "Set PinkSlips: %s" % (numSlips))
|
|
|
|
|
|
elif wordIs("~setPaid"):
|
|
args = word.split()
|
|
depts = self.getDepts(args)
|
|
if len(args) > 1:
|
|
paid = int(args[1])
|
|
if paid:
|
|
paid = 1
|
|
av.b_setAccess(OTPGlobals.AccessFull)
|
|
else:
|
|
paid = 0
|
|
av.b_setAccess(OTPGlobals.AccessVelvetRope)
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "0 for unpaid 1 for paid")
|
|
return
|
|
|
|
self.down_setMagicWordResponse(senderId, "setPaid: %s" % (paid))
|
|
|
|
|
|
|
|
elif wordIs("~holiday"):
|
|
# Start or stop a holiday
|
|
holiday = 5
|
|
fStart = 1
|
|
args = word.split()
|
|
if len(args) == 1:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "Usage:\n~holiday id\n~holiday id start\n~holiday id end\n~holiday list")
|
|
return
|
|
elif len(args) > 1:
|
|
if args[1] == 'list':
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"1: July 4\n2: New Years\n3: Halloween\n4: Winter Decorations\n5: Skelecog Invades\n6: Mr. Holly Invades\n7: Fish Bingo\n8: Species Election\n9: Black Cat\n10: Resistance Event\n11: Reset Daily Recs\n12: Reset Weekly Recs\n13: Trick-or-Treat\n14: Grand Prix\n17: Trolley Metagame")
|
|
return
|
|
else:
|
|
holiday = int(args[1])
|
|
doPhase = None
|
|
stopForever = False
|
|
if len(args) > 2:
|
|
if args[2] == 'start':
|
|
fStart = 1
|
|
elif args[2] == 'end':
|
|
fStart = 0
|
|
if len(args) > 3:
|
|
if args[3] == 'forever':
|
|
stopForever = True
|
|
elif args[2] == 'phase':
|
|
if len(args) >3 :
|
|
doPhase = args[3]
|
|
else:
|
|
self.down_setMagicWordResponce(senderId,"need a number after phase")
|
|
else:
|
|
self.down_setMagicWordResponse(
|
|
senderId, 'Arg 2 should be "start" or "end" or "end forever" or "phase"')
|
|
return
|
|
if doPhase:
|
|
result = self.air.holidayManager.forcePhase(holiday, doPhase)
|
|
self.down_setMagicWordResponse(senderId, "succeeded=%s forcing holiday %d to phase %s" %(result,holiday,doPhase))
|
|
elif fStart:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "Starting holiday %d" % holiday)
|
|
self.air.holidayManager.startHoliday(holiday)
|
|
else:
|
|
self.down_setMagicWordResponse(
|
|
senderId, "Ending holiday %d stopForever=%s" % (holiday, stopForever))
|
|
self.air.holidayManager.endHoliday(holiday, stopForever)
|
|
|
|
elif wordIs('~pet') and simbase.wantPets:
|
|
def summonPet(petId, callback=None, zoneId=zoneId):
|
|
def handleGetPet(success, pet, petId=petId, zoneId=zoneId):
|
|
if success:
|
|
pet.generateWithRequiredAndId(petId, self.air.districtId, zoneId)
|
|
if callback is not None:
|
|
callback(success, pet)
|
|
self.air.petMgr.getPetObject(petId, handleGetPet)
|
|
|
|
petId = av.getPetId()
|
|
if petId == 0:
|
|
def handleCreate(success, petId, zoneId=zoneId):
|
|
if success:
|
|
self.air.petMgr.assignPetToToon(petId, av.doId)
|
|
def handlePetGenerated(success, pet, avId=av.doId,
|
|
zoneId=zoneId):
|
|
if success:
|
|
pet._initDBVals(
|
|
avId,
|
|
traitSeed=PythonUtil.randUint31())
|
|
pet.sendSetZone(zoneId)
|
|
pet.delete()
|
|
# since this is the first time the pet is being
|
|
# created, and we're going to be setting properties
|
|
# on the pet, generate it in the Quiet zone first,
|
|
# then move it to the requested zone.
|
|
summonPet(petId, callback=handlePetGenerated,
|
|
zoneId=ToontownGlobals.QuietZone)
|
|
self.air.petMgr.createNewPetObject(handleCreate)
|
|
response = 'creating new pet...'
|
|
else:
|
|
if petId in self.air.doId2do:
|
|
response = 'pet %s already active' % petId
|
|
else:
|
|
summonPet(petId)
|
|
response = 'summoning pet %s...' % petId
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~dismiss') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.requestDelete()
|
|
response = "pet %s dismissed" % pet.doId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~deletePet') and simbase.wantPets:
|
|
petId = av.getPetId()
|
|
if petId == 0:
|
|
response = "don't have a pet"
|
|
else:
|
|
# if the pet is active, dismiss it
|
|
pet = self.air.doId2do.get(petId)
|
|
if pet is not None:
|
|
pet.requestDelete()
|
|
self.air.petMgr.deleteToonsPet(av.doId)
|
|
response = "deleted pet %s" % petId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~petName') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
args = word.split()
|
|
if len(args) < 2:
|
|
response = "~petName name"
|
|
else:
|
|
pet.b_setPetName(args[1])
|
|
response = 'name changed'
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
elif wordIs('~feed') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.feed(av)
|
|
response = "fed pet"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~attend') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.scratch(av)
|
|
response = "attended pet"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~callPet') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.call(av)
|
|
response = "called pet"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~stay') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.handleStay(av)
|
|
response = "Stay, %s." % pet.getPetName()
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~shoo') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.handleShoo(av)
|
|
response = "Shoo, %s." % pet.getPetName()
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~maxMood') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.maxMood()
|
|
response = "pet mood maxed"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~minMood') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet.minMood()
|
|
response = "pet mood minimized"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~petMood') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
args = word.split()
|
|
if len(args) < 3:
|
|
response = '~petMood component value'
|
|
else:
|
|
from toontown.pets import PetMood
|
|
comp = args[1]
|
|
value = float(args[2])
|
|
if comp not in PetMood.PetMood.Components:
|
|
response = "unknown mood '%s'" % comp
|
|
else:
|
|
pet.mood.setComponent(comp, value)
|
|
response = "mood set"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~moodTimescale') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
args = word.split()
|
|
if len(args) < 2:
|
|
response = '~moodTimescale timescale'
|
|
else:
|
|
simbase.petMoodTimescale = float(args[1])
|
|
# make the new timescale take effect immediately
|
|
pet.mood._driftMoodTask()
|
|
response = 'pet mood timescale = %s' % args[1]
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~typicalTraits') and simbase.wantPets:
|
|
szId = None
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
szId = self.Str2szId.get(args[1])
|
|
if szId == None:
|
|
szId = ToontownGlobals.ToontownCentral
|
|
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet._setTypicalTraits(szId)
|
|
# delete him to make sure we don't have a pet whose
|
|
# internal state is out-of-sync
|
|
pet.requestDelete()
|
|
response = 'set typical traits for %s' % szId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~medianTraits') and simbase.wantPets:
|
|
szId = None
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
szId = self.Str2szId.get(args[1])
|
|
if szId == None:
|
|
szId = ToontownGlobals.ToontownCentral
|
|
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet._setMedianTraits(szId)
|
|
# delete him to make sure we don't have a pet whose
|
|
# internal state is out-of-sync
|
|
pet.requestDelete()
|
|
response = 'set median traits for %s' % szId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~lowTraits') and simbase.wantPets:
|
|
szId = None
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
szId = self.Str2szId.get(args[1])
|
|
if szId == None:
|
|
szId = ToontownGlobals.ToontownCentral
|
|
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet._setLowTraits(szId)
|
|
# delete him to make sure we don't have a pet whose
|
|
# internal state is out-of-sync
|
|
pet.requestDelete()
|
|
response = 'set low traits for %s' % szId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~highTraits') and simbase.wantPets:
|
|
szId = None
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
szId = self.Str2szId.get(args[1])
|
|
if szId == None:
|
|
szId = ToontownGlobals.ToontownCentral
|
|
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
pet._setHighTraits(szId)
|
|
# delete him to make sure we don't have a pet whose
|
|
# internal state is out-of-sync
|
|
pet.requestDelete()
|
|
response = 'set high traits for %s' % szId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~leash') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
response = pet.toggleLeash(av.doId)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~lockPet') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
if pet.isLockedDown():
|
|
response = 'pet already locked down'
|
|
else:
|
|
pet.lockPet()
|
|
response = 'pet locked down'
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~unlockPet') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
if not pet.isLockedDown():
|
|
response = 'pet already not locked down'
|
|
else:
|
|
pet.unlockPet()
|
|
response = 'pet no longer locked down'
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~attendPet') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
response = 'attendPet'
|
|
pet.handleAvPetInteraction(4, av.getDoId())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~feedPet') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
response = 'feedPet'
|
|
pet.handleAvPetInteraction(3, av.getDoId())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~petStress') and simbase.wantPets:
|
|
from toontown.pets import DistributedPetAI
|
|
args = word.split()
|
|
numPets = 56 # 50 friends, six Toons/acct #100 * 3 # 500 toons, 100 at estate, 3 pets per
|
|
if len(args) > 1:
|
|
numPets = int(args[1])
|
|
for i in xrange(numPets):
|
|
pet = DistributedPetAI.DistributedPetAI(self.air)
|
|
# make up a fake owner doId
|
|
pet._initFakePet(100+i, 'StressPet%s' % i)
|
|
pet.generateWithRequired(zoneId)
|
|
pet.setPos(randFloat(-30, 30),
|
|
randFloat(-30, 30), 0)
|
|
pet.b_setParent(ToontownGlobals.SPRender)
|
|
|
|
elif wordIs('~petTricks') and simbase.wantPets:
|
|
from toontown.pets import PetConstants, PetTricks
|
|
args = word.split()
|
|
trickIds = []
|
|
invalid = 0
|
|
for num in args[1:]:
|
|
id = int(num)
|
|
if id not in PetTricks.Tricks:
|
|
invalid = 1
|
|
response = 'invalid trick ID: %s' % id
|
|
break
|
|
trickIds.append(id)
|
|
if not invalid:
|
|
av.b_setPetTrickPhrases(trickIds)
|
|
response = 'set pet trick phrases: %s' % trickIds
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~trickAptitude') and simbase.wantPets:
|
|
pet, response = self.getPet(av)
|
|
if pet:
|
|
args = word.split()
|
|
if len(args) < 2:
|
|
response = '~trickAptitude aptitude'
|
|
else:
|
|
from toontown.pets import PetTricks
|
|
pet.b_setTrickAptitudes([float(args[1])] *
|
|
(len(PetTricks.Tricks)-1))
|
|
response = 'trick aptitude = %s' % args[1]
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~spamTrick'):
|
|
# spam the nearby pets with N commands to do the 'jump' trick
|
|
from toontown.pets import PetObserve
|
|
for i in xrange(20):
|
|
PetObserve.send(av.zoneId,
|
|
PetObserve.getSCObserve(21200, av.doId))
|
|
|
|
elif wordIs('~blackCat'):
|
|
response = 'done'
|
|
error = av.makeBlackCat()
|
|
if error:
|
|
response = error
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~bingoCheat') and simbase.wantBingo:
|
|
av.bingoCheat = not av.bingoCheat
|
|
if av.bingoCheat:
|
|
response = "Bingo cheating turned on. You will always catch boots."
|
|
else:
|
|
response = "Bingo cheating turned off"
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif __dev__ and wordIs('~airender'):
|
|
showZone = zoneId
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
showZone = int(args[1])
|
|
from otp.ai import ShowBaseAI
|
|
base = ShowBaseAI.ShowBaseAI('zone %s' % showZone)
|
|
base.zoneData = AIZoneData(self.air.districtId, showZone)
|
|
render = base.zoneData.getRender()
|
|
base.camNode.setScene(render)
|
|
base.camera.reparentTo(render)
|
|
render.showCS()
|
|
axis = loader.loadModel('models/misc/xyzAxis')
|
|
axis.reparentTo(render)
|
|
axis.setPosHpr(render, 0, 0, 0, 0, 0, 0)
|
|
self.down_setMagicWordResponse(
|
|
senderId, 'rendering AI zone %s' % showZone)
|
|
|
|
elif __dev__ and wordIs("~aics"):
|
|
showZone = zoneId
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
showZone = int(args[1])
|
|
zoneData = AIZoneData(self.air.districtId, showZone)
|
|
render = zoneData.getRender(showZone)
|
|
|
|
csVisible = 0
|
|
if hasattr(render, 'csVisible'):
|
|
csVisible = render.csVisible
|
|
|
|
if csVisible:
|
|
render.hideCS()
|
|
action = 'hidden'
|
|
else:
|
|
render.showCS()
|
|
action = 'shown'
|
|
|
|
render.csVisible = not csVisible
|
|
self.down_setMagicWordResponse(
|
|
senderId, 'collisions %s for %s' % (action, showZone))
|
|
|
|
### Karting ###
|
|
elif(word[:8] == '~BuyKart'):
|
|
if (simbase.wantKarts):
|
|
accList = av.getKartAccessoriesOwned()
|
|
#accList[-1] = getDefaultColor()
|
|
accList[-2] = getDefaultRim()
|
|
|
|
response = "Av %s now owns accessories: %s" % (av.getDoId(), accList)
|
|
av.b_setKartAccessoriesOwned(accList)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif(word[:13] == '~BuyAccessory'):
|
|
if (simbase.wantKarts):
|
|
response = "Av %s attempting to buy accessory %s" % (av.getDoId(), word[14:])
|
|
av.addOwnedAccessory(int(word[14:]))
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif(word[:8] == '~Tickets'):
|
|
if (simbase.wantKarts):
|
|
response = "Av %s now has %s tickets" % (av.getDoId(), word[9:])
|
|
av.b_setTickets(int(word[9:]))
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~allowSoloRace'):
|
|
if (simbase.wantKarts):
|
|
av.setAllowSoloRace(not av.allowSoloRace)
|
|
if av.allowSoloRace:
|
|
response = "Av %s can now race solo" % (av.getDoId())
|
|
else:
|
|
response = "Av %s can no longer Race solo" % (av.getDoId())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~allowRaceTimeout'):
|
|
if (simbase.wantKarts):
|
|
av.setAllowRaceTimeout(not av.allowRaceTimeout)
|
|
if av.allowRaceTimeout:
|
|
response = "Av %s can timeout of races" % (av.getDoId())
|
|
else:
|
|
response = "Av %s can not timeout of races" % (av.getDoId())
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~drive'):
|
|
# Execute an arbitrary Python command on the AI.
|
|
av.takeOutKart()
|
|
self.down_setMagicWordResponse(
|
|
senderId, "I feel the need... the need for SPEED!")
|
|
|
|
# Golf
|
|
elif wordIs("~golf"):
|
|
self.doGolf(word, av, zoneId, senderId)
|
|
|
|
# Mail
|
|
elif wordIs("~mail"):
|
|
self.doMail(word, av, zoneId, senderId)
|
|
|
|
# Parties
|
|
elif wordIs("~party"):
|
|
self.doParty(word, av, zoneId, senderId)
|
|
|
|
#Gardening
|
|
elif wordIs("~garden"):
|
|
self.doGarden(word, av, zoneId, senderId)
|
|
|
|
elif word == "~clearGardenSpecials":
|
|
newWord = '~garden clearCarriedSpecials'
|
|
self.doGarden(newWord, av, zoneId, senderId)
|
|
|
|
elif word == "~clearFlowerCollection":
|
|
newWord = '~garden clearCollection'
|
|
self.doGarden(newWord, av, zoneId, senderId)
|
|
|
|
elif word == "~completeFlowerCollection":
|
|
newWord = '~garden completeCollection'
|
|
self.doGarden(newWord, av, zoneId, senderId)
|
|
|
|
elif wordIs('~startGarden'):
|
|
newWord = '~garden start'
|
|
self.doGarden(newWord, av, zoneId, senderId)
|
|
|
|
elif wordIs('~clearGarden'):
|
|
newWord = '~garden clear'
|
|
self.doGarden(newWord, av, zoneId, senderId)
|
|
|
|
elif wordIs('~cannons'):
|
|
sender = simbase.air.doId2do.get(senderId)
|
|
if sender:
|
|
zoneId = sender.zoneId
|
|
estateOwnerDoId = simbase.air.estateMgr.zone2owner.get(zoneId)
|
|
estate = simbase.air.estateMgr.estate.get(estateOwnerDoId)
|
|
|
|
if hasattr(estate, "cannonFlag"):
|
|
if estate.cannonFlag:
|
|
estate.endCannons()
|
|
response = "Cannons Ended"
|
|
else:
|
|
estate.startCannons()
|
|
response = "Cannons Started"
|
|
|
|
elif wordIs('~gameTable'):
|
|
sender = simbase.air.doId2do.get(senderId)
|
|
if sender:
|
|
zoneId = sender.zoneId
|
|
estateOwnerDoId = simbase.air.estateMgr.zone2owner.get(zoneId)
|
|
estate = simbase.air.estateMgr.estate.get(estateOwnerDoId)
|
|
|
|
if hasattr(estate, 'gameTableFlag'):
|
|
if estate.gameTableFlag:
|
|
estate.endGameTable()
|
|
response = 'Game Table Ended'
|
|
else:
|
|
estate.startGameTable()
|
|
response = 'Game Table Started'
|
|
|
|
elif wordIs('~plantGarden'):
|
|
newWord = '~garden plant'
|
|
args = word.split()
|
|
for i in range(1, len(args)):
|
|
newWord += ' '
|
|
newWord += args[i]
|
|
self.doGarden(newWord, av, zoneId, senderId)
|
|
|
|
elif wordIs('~trialerCount'):
|
|
total = 0
|
|
trialer =0
|
|
paid = 0
|
|
unknown = 0
|
|
allToons = simbase.air.doFindAll('DistributedToonAI')
|
|
for toon in allToons:
|
|
total += 1
|
|
if toon.getGameAccess() == ToontownGlobals.AccessFull:
|
|
paid += 1
|
|
elif toon.getGameAccess() == ToontownGlobals.AccessVelvetRope:
|
|
trialer += 1
|
|
else:
|
|
unknown += 1
|
|
response = "%d trialers, %d paid, %d total" % (trialer, paid, total)
|
|
if unknown:
|
|
response += "%d unknown" % unknown
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
elif wordIs('~deleteBackupStores'):
|
|
storeClient = DataStoreAIClient(self.air, DataStoreGlobals.GEN, None)
|
|
storeClient.deleteBackupStores()
|
|
storeClient.closeStore()
|
|
|
|
elif wordIs("~autoRich"):
|
|
# Available only __dev__ and GMs. Guard against hacked clients sending this. If a non-GM
|
|
# needs to do this on LIVE, simply use ~rich instead.
|
|
if __dev__ or av.hasGMName():
|
|
# Basically this is a signal that a GM has logged in.
|
|
if av.hasGMName():
|
|
self.air.writeServerEvent('GM', av.doId, 'GM %s used auto-rich' % av.getName())
|
|
assert self.notify.debug('GM %s %s used auto-rich' % (av.doId, av.getName()))
|
|
|
|
args = word.split()
|
|
postName = 'autoRich-%s' % av.doId
|
|
enable = not bboard.get(postName, 0)
|
|
# are they explicitly setting the state?
|
|
if len(args) > 1:
|
|
try:
|
|
enable = int(args[1])
|
|
except:
|
|
self.down_setMagicWordResponse(senderId,
|
|
'invalid state flag: %s' %
|
|
args[1])
|
|
return
|
|
if enable:
|
|
state = 'ON'
|
|
av.b_setMoney(av.maxMoney)
|
|
av.b_setBankMoney(av.maxBankMoney)
|
|
bboard.post(postName, 1)
|
|
else:
|
|
state = 'OFF'
|
|
bboard.remove(postName)
|
|
self.down_setMagicWordResponse(senderId, 'autoRich %s' % state)
|
|
else:
|
|
self.air.writeServerEvent('suspicious', av.doId, 'non-GM toon with name %s using ~autoRich' % av.getName())
|
|
|
|
else:
|
|
# The word is not an AI-side magic word. If the sender is
|
|
# different than the target avatar, then pass the magic
|
|
# word down to the target client-side MagicWordManager to
|
|
# execute a client-side magic word.
|
|
if (senderId != av.doId):
|
|
self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId])
|
|
|
|
def doNpcFriend(self, av, npcId, numCalls):
|
|
return av.attemptAddNPCFriend(npcId, numCalls) == 1
|
|
|
|
def getDepts(self, args):
|
|
# Returns a list of the dept indices specified by args[1], or
|
|
# all depts if nothing is specified. If a dept is specified,
|
|
# args[1] is removed from the list.
|
|
|
|
depts = []
|
|
if len(args) > 1:
|
|
if args[1] == 'all':
|
|
depts = [0, 1, 2, 3]
|
|
del args[1]
|
|
else:
|
|
allLettersGood = 1
|
|
for letter in args[1]:
|
|
if letter in SuitDNA.suitDepts:
|
|
dept = SuitDNA.suitDepts.index(letter)
|
|
depts.append(dept)
|
|
else:
|
|
allLettersGood = 0
|
|
break
|
|
|
|
if allLettersGood:
|
|
del args[1]
|
|
else:
|
|
depts = []
|
|
|
|
if depts:
|
|
return depts
|
|
else:
|
|
return [0, 1, 2, 3]
|
|
|
|
|
|
def doExp(self, word, av, zoneId, senderId):
|
|
"""Handle the ~exp magic word."""
|
|
track = None
|
|
args=word.split()
|
|
trackIndex = -1
|
|
increment = 0
|
|
gotIncrement = 0
|
|
|
|
if len(args) > 1:
|
|
trackStr = args[1]
|
|
if trackStr != "all":
|
|
trackIndex = ToontownBattleGlobals.Tracks.index(trackStr)
|
|
|
|
if len(args) > 2:
|
|
increment = int(args[2])
|
|
gotIncrement = 1
|
|
|
|
if trackIndex == -1:
|
|
for trackIndex in range(ToontownBattleGlobals.MAX_TRACK_INDEX + 1):
|
|
if av.hasTrackAccess(trackIndex):
|
|
if not gotIncrement:
|
|
# No increment specified; the default is whatever
|
|
# it takes to get to the next track.
|
|
increment = av.experience.getNextExpValue(trackIndex) - av.experience.getExp(trackIndex)
|
|
|
|
self.notify.debug("Adding %d to %s track for %s." % (increment, ToontownBattleGlobals.Tracks[trackIndex], av.name))
|
|
av.experience.addExp(trackIndex, increment)
|
|
else:
|
|
if not gotIncrement:
|
|
# No increment specified; the default is whatever
|
|
# it takes to get to the next track.
|
|
increment = av.experience.getNextExpValue(trackIndex) - av.experience.getExp(trackIndex)
|
|
|
|
self.notify.debug("Adding %d to %s track for %s." % (increment, ToontownBattleGlobals.Tracks[trackIndex], av.name))
|
|
av.experience.addExp(trackIndex, increment)
|
|
|
|
av.d_setExperience(av.experience.makeNetString())
|
|
|
|
|
|
def doTrophy(self, word, av, zoneId, senderId):
|
|
"""Handle the ~trophy magic word: artificially set (or
|
|
restore) the trophy score."""
|
|
|
|
args = word.split()
|
|
if len(args) > 1:
|
|
score = int(args[1])
|
|
|
|
response = "Set trophy score to %s." % (score)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
else:
|
|
# No score specified; restore the actual trophy score.
|
|
score = self.air.trophyMgr.getTrophyScore(av.doId)
|
|
|
|
response = "Trophy score is %s." % (score)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
av.d_setTrophyScore(score)
|
|
|
|
|
|
def doCheesyEffect(self, word, av, zoneId, senderId):
|
|
effect = None
|
|
if zoneId >= ToontownGlobals.DynamicZonesBegin:
|
|
hoodId = 1
|
|
else:
|
|
hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
|
|
timeLimit = 10
|
|
|
|
args = word.split()
|
|
try:
|
|
effect = eval("ToontownGlobals.CE" + args[1])
|
|
except:
|
|
try:
|
|
effect = eval(args[1])
|
|
except:
|
|
effect = None
|
|
|
|
if effect == None:
|
|
self.down_setMagicWordResponse(senderId, "Unknown effect %s." % (args[1]))
|
|
return
|
|
|
|
if len(args) > 2:
|
|
timeLimit = int(args[2])
|
|
|
|
# Let it expire in timeLimit minutes.
|
|
expireTime = (int)(time.time() / 60 + 0.5) + timeLimit
|
|
av.b_setCheesyEffect(effect, hoodId, expireTime)
|
|
|
|
def doCogTakeOver(self, word, av, zoneId, senderId):
|
|
"""Handle the ~cogTakeOver magic word."""
|
|
track = None
|
|
level = None
|
|
streetId = ZoneUtil.getBranchZone(zoneId)
|
|
args = word.split()
|
|
|
|
now = args.count("now")
|
|
if now:
|
|
args.remove("now")
|
|
slow = args.count("slow")
|
|
if slow:
|
|
args.remove("slow")
|
|
|
|
if len(args)>1:
|
|
track=args[1]
|
|
if track == 'x':
|
|
track = None
|
|
|
|
if len(args)>2:
|
|
if args[2] != 'x':
|
|
level=int(args[2])
|
|
level = max(min(level, 9), 1)
|
|
|
|
if len(args)>4:
|
|
if args[4] == 'all':
|
|
streetId = 'all'
|
|
else:
|
|
streetId=int(args[4])
|
|
|
|
if not self.air.suitPlanners.has_key(streetId):
|
|
response = "Street %d is not known." % (streetId)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
return
|
|
|
|
if streetId == 'all':
|
|
# All buildings, everywhere.
|
|
blockMap = {}
|
|
for sp in self.air.suitPlanners.values():
|
|
if sp.buildingMgr:
|
|
blockMap[sp.buildingMgr] = sp.buildingMgr.getToonBlocks()
|
|
|
|
else:
|
|
# Just the buildings on this street.
|
|
sp = self.air.suitPlanners[streetId]
|
|
bm = sp.buildingMgr
|
|
|
|
blocks = None
|
|
if len(args)>3:
|
|
if (args[3] == "all"):
|
|
blocks = bm.getToonBlocks()
|
|
elif (args[3] == "this"):
|
|
blocks = None
|
|
else:
|
|
blocks=[int(args[3])]
|
|
|
|
if blocks == None:
|
|
# Try to figure out what doors we're standing in front
|
|
# of.
|
|
blocks = []
|
|
for i in bm.getToonBlocks():
|
|
building = bm.getBuilding(i)
|
|
if hasattr(building, "door"):
|
|
if building.door.zoneId == zoneId:
|
|
blocks.append(i)
|
|
|
|
blockMap = { bm: blocks }
|
|
|
|
points = sp.streetPointList[:]
|
|
failureCount = 0
|
|
minPathLen = 2
|
|
maxPathLen = 10
|
|
if slow:
|
|
minPathLen = None
|
|
maxPathLen = None
|
|
|
|
total = 0
|
|
for bm, blocks in blockMap.items():
|
|
total += len(blocks)
|
|
for i in blocks:
|
|
if now:
|
|
# Take over the building immediately.
|
|
level, type, track = \
|
|
sp.pickLevelTypeAndTrack(level, None, track)
|
|
building = bm.getBuilding(i)
|
|
building.suitTakeOver(track, level - 1, None)
|
|
|
|
else:
|
|
# Dispatch a suit to take over the building.
|
|
if not slow:
|
|
# Let the suit take its time.
|
|
points = sp.getStreetPointsForBuilding(i)
|
|
|
|
suit = None
|
|
retryCount = 0
|
|
while suit == None and len(points) > 0 and retryCount < 20:
|
|
suit = sp.createNewSuit([], points,
|
|
suitTrack = track,
|
|
suitLevel = level,
|
|
toonBlockTakeover = i,
|
|
minPathLen = minPathLen,
|
|
maxPathLen = maxPathLen)
|
|
retryCount += 1
|
|
if suit == None:
|
|
failureCount += 1
|
|
|
|
self.notify.debug("cogTakeOver %s %s %d %d" %
|
|
(track, level, i, zoneId))
|
|
|
|
response = "%d buildings." % (total)
|
|
if (failureCount > 0):
|
|
response += " %d failed." % (failureCount)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doCogdoTakeOver(self, word, av, zoneId, senderId):
|
|
"""Handle the ~cogdoTakeOver magic word."""
|
|
level = None
|
|
streetId = ZoneUtil.getBranchZone(zoneId)
|
|
args = word.split()
|
|
|
|
now = args.count("now")
|
|
if now:
|
|
args.remove("now")
|
|
slow = args.count("slow")
|
|
if slow:
|
|
args.remove("slow")
|
|
|
|
if len(args)>1:
|
|
if args[1] != 'x':
|
|
level=int(args[2])
|
|
level = max(min(level, 9), 1)
|
|
|
|
if len(args)>4:
|
|
if args[4] == 'all':
|
|
streetId = 'all'
|
|
else:
|
|
streetId=int(args[4])
|
|
|
|
if not self.air.suitPlanners.has_key(streetId):
|
|
response = "Street %d is not known." % (streetId)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
return
|
|
|
|
if streetId == 'all':
|
|
# All buildings, everywhere.
|
|
blockMap = {}
|
|
for sp in self.air.suitPlanners.values():
|
|
if sp.buildingMgr:
|
|
blockMap[sp.buildingMgr] = sp.buildingMgr.getToonBlocks()
|
|
|
|
else:
|
|
# Just the buildings on this street.
|
|
sp = self.air.suitPlanners[streetId]
|
|
bm = sp.buildingMgr
|
|
|
|
blocks = None
|
|
if len(args)>3:
|
|
if (args[3] == "all"):
|
|
blocks = bm.getToonBlocks()
|
|
elif (args[3] == "this"):
|
|
blocks = None
|
|
else:
|
|
blocks=[int(args[3])]
|
|
|
|
if blocks == None:
|
|
# Try to figure out what doors we're standing in front
|
|
# of.
|
|
blocks = []
|
|
for i in bm.getToonBlocks():
|
|
building = bm.getBuilding(i)
|
|
if hasattr(building, "door"):
|
|
if building.door.zoneId == zoneId:
|
|
blocks.append(i)
|
|
|
|
blockMap = { bm: blocks }
|
|
|
|
points = sp.streetPointList[:]
|
|
failureCount = 0
|
|
minPathLen = 2
|
|
maxPathLen = 10
|
|
if slow:
|
|
minPathLen = None
|
|
maxPathLen = None
|
|
|
|
total = 0
|
|
for bm, blocks in blockMap.items():
|
|
total += len(blocks)
|
|
for i in blocks:
|
|
if now:
|
|
# Take over the building immediately.
|
|
level, type, track = \
|
|
sp.pickLevelTypeAndTrack(level, None, track)
|
|
building = bm.getBuilding(i)
|
|
building.cogdoTakeOver(level - 1, None)
|
|
|
|
else:
|
|
# Dispatch a suit to take over the building.
|
|
if not slow:
|
|
# Let the suit take its time.
|
|
points = sp.getStreetPointsForBuilding(i)
|
|
|
|
suit = None
|
|
retryCount = 0
|
|
while suit == None and len(points) > 0 and retryCount < 20:
|
|
track = random.choice(SuitDNA.suitDepts)
|
|
suit = sp.createNewSuit([], points,
|
|
suitTrack = track,
|
|
suitLevel = level,
|
|
toonBlockTakeover = i,
|
|
cogdoTakeover = True,
|
|
minPathLen = minPathLen,
|
|
maxPathLen = maxPathLen)
|
|
retryCount += 1
|
|
if suit == None:
|
|
failureCount += 1
|
|
|
|
self.notify.debug("cogdoTakeOver %s %s %d %d" %
|
|
(track, level, i, zoneId))
|
|
|
|
response = "%d cogdos." % (total)
|
|
if (failureCount > 0):
|
|
response += " %d failed." % (failureCount)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doToonTakeOver(self, word, av, zoneId, senderId):
|
|
"""Handle the ~toonTakeOver magic word."""
|
|
streetId = ZoneUtil.getBranchZone(zoneId)
|
|
args=word.split()
|
|
if len(args)>2:
|
|
if args[2] == 'all':
|
|
streetId = 'all'
|
|
else:
|
|
streetId=int(args[2])
|
|
|
|
if not self.air.suitPlanners.has_key(streetId):
|
|
response = "Street %d is not known." % (streetId)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
return
|
|
|
|
if streetId == 'all':
|
|
# All buildings, everywhere.
|
|
blockMap = {}
|
|
for sp in self.air.suitPlanners.values():
|
|
if sp.buildingMgr:
|
|
blockMap[sp.buildingMgr] = sp.buildingMgr.getSuitBlocks()
|
|
|
|
else:
|
|
# Just the buildings on this street.
|
|
bm=self.air.buildingManagers[streetId]
|
|
blocks = None
|
|
if len(args)>1:
|
|
if (args[1] == "all"):
|
|
blocks = bm.getSuitBlocks()
|
|
elif (args[1] == "this"):
|
|
blocks = None
|
|
else:
|
|
blocks=[int(args[1])]
|
|
|
|
if blocks == None:
|
|
# Try to figure out what doors we're standing in front
|
|
# of.
|
|
blocks = []
|
|
for i in bm.getSuitBlocks():
|
|
building = bm.getBuilding(i)
|
|
if hasattr(building, "elevator"):
|
|
if building.elevator.zoneId == zoneId and \
|
|
building.elevator.fsm.getCurrentState().getName() == 'waitEmpty':
|
|
blocks.append(i)
|
|
blockMap = { bm: blocks }
|
|
|
|
total = 0
|
|
for bm, blocks in blockMap.items():
|
|
total += len(blocks)
|
|
for i in blocks:
|
|
building = bm.getBuilding(i)
|
|
building.b_setVictorList([0, 0, 0, 0])
|
|
building.updateSavedBy([(av.doId, av.name, av.dna.asTuple())])
|
|
building.toonTakeOver()
|
|
self.notify.debug("Toon take over %s %s" % (i, streetId))
|
|
|
|
response = "%d buildings." % (total)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def formatWelcomeValley(self, hood):
|
|
mgr = self.air.welcomeValleyManager
|
|
|
|
if hood == mgr.newHood:
|
|
return "%s N" % (hood[0].zoneId)
|
|
elif hood in mgr.removingHoods:
|
|
return "%s R" % (hood[0].zoneId)
|
|
else:
|
|
return "%s" % (hood[0].zoneId)
|
|
|
|
def doWelcome(self, word, av, zoneId, senderId):
|
|
"""Handle the ~welcome magic word, for managing Welcome Valley."""
|
|
args = word.split()
|
|
|
|
hoodId = ZoneUtil.getHoodId(zoneId)
|
|
mgr = self.air.welcomeValleyManager
|
|
|
|
# if this is a GS hoodId, just grab the TT hood
|
|
if (hoodId % 2000) < 1000:
|
|
hood = mgr.welcomeValleys.get(hoodId)
|
|
else:
|
|
hood = mgr.welcomeValleys.get(hoodId - 1000)
|
|
|
|
if len(args) == 1:
|
|
# No parameter: report the current zone and population.
|
|
if hood == None:
|
|
response = "Not in Welcome Valley."
|
|
else:
|
|
response = "%s, pg = %s, hood = %s" % (
|
|
self.formatWelcomeValley(hood),
|
|
hood[0].getPgPopulation(),
|
|
hood[0].getHoodPopulation())
|
|
|
|
elif args[1] == "pg":
|
|
# ~welcome pg: list the playground population of all
|
|
# Welcome Valleys.
|
|
|
|
response = ""
|
|
hoodIds = mgr.welcomeValleys.keys()
|
|
hoodIds.sort()
|
|
for hoodId in hoodIds:
|
|
hood = mgr.welcomeValleys[hoodId]
|
|
response += "\n%s %s" % (
|
|
self.formatWelcomeValley(hood),
|
|
hood[0].getPgPopulation())
|
|
|
|
if response == "":
|
|
response = "No Welcome Valleys."
|
|
else:
|
|
response = response[1:]
|
|
|
|
elif args[1] == "hood":
|
|
# ~welcome hood: list the hood population of all
|
|
# Welcome Valleys.
|
|
|
|
response = ""
|
|
hoodIds = mgr.welcomeValleys.keys()
|
|
hoodIds.sort()
|
|
for hoodId in hoodIds:
|
|
hood = mgr.welcomeValleys[hoodId]
|
|
response += "\n%s %s" % (
|
|
self.formatWelcomeValley(hood),
|
|
hood[0].getHoodPopulation())
|
|
|
|
if response == "":
|
|
response = "No Welcome Valleys."
|
|
else:
|
|
response = response[1:]
|
|
|
|
elif args[1] == "login":
|
|
# ~welcome login avId: simulate a new player logging in.
|
|
# avId is an arbitrary number which should probably not
|
|
# match any real avatars.
|
|
avId = int(args[2])
|
|
|
|
zoneId = mgr.avatarRequestZone(avId, ToontownGlobals.WelcomeValleyToken)
|
|
response = "%s assigned to %s." % (avId, zoneId)
|
|
|
|
elif args[1] == "logout":
|
|
# ~welcome logout avId: simulate a player logging out.
|
|
# avId is an arbitrary number which should probably not
|
|
# match any real avatars.
|
|
avId = int(args[2])
|
|
|
|
avZoneId = mgr.avatarZones.get(avId)
|
|
if avZoneId:
|
|
mgr.avatarLogout(avId)
|
|
response = "%s logged out from %s." % (avId, avZoneId)
|
|
else:
|
|
response = "%s is unknown." % (avId)
|
|
|
|
elif args[1] == "zone":
|
|
# ~welcome zone avId [zoneId]: simulate a player switching
|
|
# zones. avId is an arbitrary number which should
|
|
# probably not match any real avatars.
|
|
avId = int(args[2])
|
|
if len(args) > 3:
|
|
newZoneId = int(args[3])
|
|
else:
|
|
newZoneId = zoneId
|
|
|
|
zoneId = mgr.avatarRequestZone(avId, newZoneId)
|
|
response = "%s redirected to %s." % (avId, zoneId)
|
|
|
|
elif args[1] == "new":
|
|
# ~welcome new [hoodId]: immediately move the indicated
|
|
# (or current) hood to the New pool.
|
|
if len(args) > 2:
|
|
hoodId = int(args[2])
|
|
else:
|
|
hoodId = zoneId
|
|
response = mgr.makeNew(hoodId)
|
|
|
|
elif args[1] == "stable":
|
|
# ~welcome stable [hoodId]: immediately move the indicated
|
|
# (or current) hood to the Stable pool.
|
|
if len(args) > 2:
|
|
hoodId = int(args[2])
|
|
else:
|
|
hoodId = zoneId
|
|
response = mgr.makeStable(hoodId)
|
|
|
|
elif args[1] == "remove":
|
|
# ~welcome remove [hoodId]: immediately move the indicated
|
|
# (or current) hood to the Removing pool.
|
|
if len(args) > 2:
|
|
hoodId = int(args[2])
|
|
else:
|
|
hoodId = zoneId
|
|
response = mgr.makeRemoving(hoodId)
|
|
|
|
elif args[1] == "check":
|
|
# ~welcome check: check that our record logged-in avatars
|
|
# are actually real avatars; logs out any others.
|
|
removed = mgr.checkAvatars()
|
|
if removed:
|
|
response = "Logged out %s phony avatars." % (len(removed))
|
|
else:
|
|
response = "All avatars real."
|
|
|
|
elif args[1] == "parms":
|
|
# ~welcome parms [min stable max]: report or adjust the
|
|
# balancing parameters.
|
|
if len(args) == 5:
|
|
PGminimum = int(args[2])
|
|
PGstable = int(args[3])
|
|
PGmaximum = int(args[4])
|
|
WelcomeValleyManagerAI.PGminimum = PGminimum
|
|
WelcomeValleyManagerAI.PGstable = PGstable
|
|
WelcomeValleyManagerAI.PGmaximum = PGmaximum
|
|
|
|
response = "min = %s, stable = %s, max = %s" % (
|
|
WelcomeValleyManagerAI.PGminimum,
|
|
WelcomeValleyManagerAI.PGstable,
|
|
WelcomeValleyManagerAI.PGmaximum)
|
|
|
|
else:
|
|
response = "Invalid welcome command: %s" % (args[1])
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def __sortBuildingDist(self, a, b):
|
|
return a[0] - b[0]
|
|
|
|
def doBuildings(self, word, av, zoneId, senderId):
|
|
"""Handle the ~buildings magic word."""
|
|
streetId = ZoneUtil.getBranchZone(zoneId)
|
|
|
|
if word == "~buildings where":
|
|
# "~buildings where": report the distribution of buildings.
|
|
dist = {}
|
|
for sp in self.air.suitPlanners.values():
|
|
if sp.buildingMgr:
|
|
numActual = len(sp.buildingMgr.getSuitBlocks())
|
|
if not dist.has_key(numActual):
|
|
dist[numActual] = []
|
|
dist[numActual].append(sp.zoneId)
|
|
|
|
# Sort the distribution by number of buildings.
|
|
sorted = []
|
|
for tuple in dist.items():
|
|
sorted.append(tuple)
|
|
sorted.sort(self.__sortBuildingDist)
|
|
|
|
# Now format the distribution into a text response.
|
|
response = ""
|
|
for numActual, zones in sorted:
|
|
if numActual != 0:
|
|
response += "\n%s: %d" % (zones, numActual)
|
|
|
|
if response == "":
|
|
response = "No cog buildings."
|
|
else:
|
|
response = response[1:]
|
|
|
|
else:
|
|
# "~buildings zoneId" or "~buildings all"
|
|
|
|
args=word.split()
|
|
if len(args) > 1:
|
|
if args[1] == "all":
|
|
streetId = "all"
|
|
else:
|
|
streetId = int(args[1])
|
|
|
|
if streetId == "all":
|
|
numTarget = 0
|
|
numActual = 0
|
|
numTotalBuildings = 0
|
|
numAttempting = 0
|
|
numPerTrack = {}
|
|
numPerHeight = {}
|
|
for sp in self.air.suitPlanners.values():
|
|
numTarget += sp.targetNumSuitBuildings
|
|
if sp.buildingMgr:
|
|
numActual += len(sp.buildingMgr.getSuitBlocks())
|
|
numTotalBuildings += len(sp.frontdoorPointList)
|
|
numAttempting += sp.numAttemptingTakeover
|
|
sp.countNumBuildingsPerTrack(numPerTrack)
|
|
sp.countNumBuildingsPerHeight(numPerHeight)
|
|
|
|
response = "Overall, %d cog buildings (%s, %s) out of %d; target is %d. %d cogs are attempting takeover." % (
|
|
numActual, sp.formatNumSuitsPerTrack(numPerTrack),
|
|
sp.formatNumSuitsPerTrack(numPerHeight),
|
|
numTotalBuildings, numTarget, numAttempting)
|
|
|
|
elif not self.air.suitPlanners.has_key(streetId):
|
|
response = "Street %d is not known." % (streetId)
|
|
|
|
else:
|
|
sp = self.air.suitPlanners[streetId]
|
|
|
|
numTarget = sp.targetNumSuitBuildings
|
|
if sp.buildingMgr:
|
|
numActual = len(sp.buildingMgr.getSuitBlocks())
|
|
else:
|
|
numActual = 0
|
|
numTotalBuildings = len(sp.frontdoorPointList)
|
|
numAttempting = sp.numAttemptingTakeover
|
|
numPerTrack = {}
|
|
numPerHeight = {}
|
|
sp.countNumBuildingsPerTrack(numPerTrack)
|
|
sp.countNumBuildingsPerHeight(numPerHeight)
|
|
|
|
response = "Street %d has %d cog buildings (%s, %s) out of %d; target is %d. %d cogs are attempting takeover." % (
|
|
streetId, numActual,
|
|
sp.formatNumSuitsPerTrack(numPerTrack),
|
|
sp.formatNumSuitsPerTrack(numPerHeight),
|
|
numTotalBuildings, numTarget, numAttempting)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doBuildingPercent(self, word, av, zoneId, senderId):
|
|
"""Handle the ~buildingPercent magic word."""
|
|
percent = None
|
|
|
|
args=word.split()
|
|
if len(args) > 1:
|
|
percent = int(args[1])
|
|
|
|
if percent == None:
|
|
response = "Suit building target percentage is %d" % (DistributedSuitPlannerAI.DistributedSuitPlannerAI.TOTAL_SUIT_BUILDING_PCT)
|
|
else:
|
|
DistributedSuitPlannerAI.DistributedSuitPlannerAI.TOTAL_SUIT_BUILDING_PCT = percent
|
|
sp = self.air.suitPlanners.values()[0]
|
|
sp.assignInitialSuitBuildings()
|
|
response = "Reset target percentage to %d" % (percent)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doCall(self, word, av, zoneId, senderId):
|
|
"""Handle the ~call magic word."""
|
|
streetId = ZoneUtil.getBranchZone(zoneId)
|
|
|
|
args=word.split()
|
|
name = None
|
|
level = None
|
|
skelecog = None
|
|
revives = None
|
|
|
|
if len(args) > 1:
|
|
name = args[1]
|
|
if name == 'x':
|
|
name = None
|
|
|
|
if len(args) > 2:
|
|
level = int(args[2])
|
|
|
|
if len(args) > 3:
|
|
skelecog = int(args[3])
|
|
|
|
if len(args) > 4:
|
|
revives = int(args[4])
|
|
|
|
if not self.air.suitPlanners.has_key(streetId):
|
|
response = "Street %d is not known." % (streetId)
|
|
|
|
else:
|
|
sp = self.air.suitPlanners[streetId]
|
|
map = sp.getZoneIdToPointMap()
|
|
canonicalZoneId = ZoneUtil.getCanonicalZoneId(zoneId)
|
|
if not map.has_key(canonicalZoneId):
|
|
response = "Zone %d isn't near a suit point." % (canonicalZoneId)
|
|
else:
|
|
points = map[canonicalZoneId][:]
|
|
suit = sp.createNewSuit([], points,
|
|
suitName = name,
|
|
suitLevel = level,
|
|
skelecog = skelecog,
|
|
revives = revives)
|
|
if suit:
|
|
response = "Here comes %s." % (SuitBattleGlobals.SuitAttributes[suit.dna.name]['name'])
|
|
else:
|
|
response = "Could not create suit."
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doBattle(self, word, av, zoneId, senderId):
|
|
"""Handle the ~battle magic word."""
|
|
|
|
# There's no easy way to find the battle that the caller is
|
|
# near or involved in. We'll have to walk through all the
|
|
# battles currently in the doId2do map.
|
|
battle = self.__findInvolvedBattle(av.doId)
|
|
if battle == None:
|
|
battle = self.__findBattleInZone(zoneId)
|
|
|
|
if battle == None:
|
|
response = "No battle in zone %s." % (zoneId)
|
|
else:
|
|
args = word.split()
|
|
if len(args) < 2:
|
|
response = "Battle %s in state %s" % (battle.doId, battle.fsm.getCurrentState().getName())
|
|
|
|
elif args[1] == 'abort':
|
|
battle.abortBattle()
|
|
response = "Battle %s aborted." % (battle.doId)
|
|
|
|
else:
|
|
response = "Uknown battle command %s" % (args[1])
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def __findInvolvedBattle(self, avId):
|
|
"""Returns the battle, if any, in which the indicated avatar
|
|
is a participant, or None if the avatar is not involved in any
|
|
battles."""
|
|
|
|
for dobj in self.air.doId2do.values():
|
|
if (isinstance(dobj, DistributedBattleBaseAI.DistributedBattleBaseAI)):
|
|
if avId in dobj.toons:
|
|
return dobj
|
|
|
|
def __findBattleInZone(self, zoneId):
|
|
"""Returns the battle, if any, in the indicated zoneId, or
|
|
None if no battle is occurring in the indicated zone."""
|
|
|
|
for dobj in self.air.doId2do.values():
|
|
if (isinstance(dobj, DistributedBattleBaseAI.DistributedBattleBaseAI)):
|
|
if dobj.zoneId == zoneId:
|
|
return dobj
|
|
|
|
|
|
|
|
|
|
def doCogInvasion(self, word, av, zoneId, senderId):
|
|
"""Handle the ~invasion magic word."""
|
|
|
|
invMgr = self.air.suitInvasionManager
|
|
|
|
if invMgr.getInvading():
|
|
cogType = invMgr.getCogType()
|
|
numRemaining = invMgr.getNumCogsRemaining()
|
|
cogName = SuitBattleGlobals.SuitAttributes[cogType[0]]['name']
|
|
response = ("Invasion already in progress: %s, %s" % (cogName, numRemaining))
|
|
else:
|
|
args=word.split()
|
|
if len(args) < 3 or len(args) > 4:
|
|
response = "Error: Must specify cogType and numCogs"
|
|
else:
|
|
cogType = args[1]
|
|
numCogs = int(args[2])
|
|
if len(args) == 4:
|
|
skeleton = int(args[3])
|
|
else:
|
|
skeleton = 0
|
|
cogNameDict = SuitBattleGlobals.SuitAttributes.get(cogType)
|
|
if cogNameDict:
|
|
cogName = cogNameDict['name']
|
|
if skeleton:
|
|
cogName = TTLocalizer.Skeleton + " " + cogName
|
|
if invMgr.startInvasion(cogType, numCogs, skeleton):
|
|
response = ("Invasion started: %s, %s" % (cogName, numCogs))
|
|
else:
|
|
response = ("Invasion failed: %s, %s" % (cogName, numCogs))
|
|
else:
|
|
response = ("Unknown cogType: %s" % (cogType))
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def stopCogInvasion(self, word, av, zoneId, senderId):
|
|
invMgr = self.air.suitInvasionManager
|
|
|
|
if invMgr.getInvading():
|
|
self.air.suitInvasionManager.stopInvasion()
|
|
response = ("Invasion stopped.")
|
|
else:
|
|
response = ("No invasion found.")
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def getCogInvasion(self, word, av, zoneId, senderId):
|
|
invMgr = self.air.suitInvasionManager
|
|
|
|
if invMgr.getInvading():
|
|
cogType, skeleton = invMgr.getCogType()
|
|
numRemaining = invMgr.getNumCogsRemaining()
|
|
cogName = SuitBattleGlobals.SuitAttributes[cogType]['name']
|
|
if skeleton:
|
|
cogName = TTLocalizer.Skeleton + " " + cogName
|
|
response = ("Invasion is in progress: %s, %s remaining" % (cogName, numRemaining))
|
|
else:
|
|
response = ("No invasion found.")
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def startAllFireworks(self, word, av, zoneId, senderId):
|
|
fMgr = self.air.fireworkManager
|
|
fMgr.stopAllShows()
|
|
fMgr.startAllShows(None)
|
|
response = "Shows started in all hoods."
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def startFireworks(self, word, av, zoneId, senderId):
|
|
fMgr = self.air.fireworkManager
|
|
if fMgr.isShowRunning(zoneId):
|
|
response = ("Show already running in zone: %s" % (zoneId))
|
|
else:
|
|
args=word.split()
|
|
if len(args) == 2:
|
|
showType = int(args[1])
|
|
if fMgr.startShow(zoneId, showType, 1):
|
|
response = ("Show started, showType: %s" % showType)
|
|
else:
|
|
response = ("Show failed, showType: %s" % showType)
|
|
else:
|
|
# Default to showType 0
|
|
response = (TTLocalizer.startFireworksResponse \
|
|
%( ToontownGlobals.NEWYEARS_FIREWORKS, \
|
|
PartyGlobals.FireworkShows.Summer, \
|
|
ToontownGlobals.JULY4_FIREWORKS))
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def stopFireworks(self, word, av, zoneId, senderId):
|
|
if self.air.fireworkManager.stopShow(zoneId):
|
|
response = ("Show stopped, zoneId: %s" % zoneId)
|
|
else:
|
|
response = ("Show stop failed, zoneId: %s" % zoneId)
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def stopAllFireworks(self, word, av, zoneId, senderId):
|
|
numStopped = self.air.fireworkManager.stopAllShows()
|
|
response = ("Stopped %s firework show(s)" % (numStopped))
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doCogs(self, word, av, zoneId, senderId):
|
|
"""Handle the ~cogs magic word."""
|
|
streetId = ZoneUtil.getBranchZone(zoneId)
|
|
|
|
args=word.split()
|
|
firstKeyword = 1
|
|
|
|
sync = 0
|
|
fly = 0
|
|
count = -1
|
|
|
|
if len(args) > 1:
|
|
if args[1] == "all":
|
|
streetId = "all"
|
|
firstKeyword = 2
|
|
else:
|
|
try:
|
|
streetId = int(args[1])
|
|
firstKeyword = 2
|
|
except:
|
|
pass
|
|
|
|
# Check for extra keywords.
|
|
for k in range(firstKeyword, len(args)):
|
|
word = args[k]
|
|
if word == "sync":
|
|
sync = 1
|
|
elif word == "fly":
|
|
fly = 1
|
|
elif word == "count=x":
|
|
count = None
|
|
elif word[:6] == "count=":
|
|
count = int(word[6:])
|
|
else:
|
|
self.down_setMagicWordResponse(senderId, "invalid keyword %s" % (word))
|
|
return
|
|
|
|
if streetId == "all":
|
|
numTarget = 0
|
|
numActual = 0
|
|
numPerTrack = {}
|
|
sp = None
|
|
for sp in self.air.suitPlanners.values():
|
|
numTarget += sp.calcDesiredNumFlyInSuits() + sp.calcDesiredNumBuildingSuits()
|
|
numActual += sp.numFlyInSuits + sp.numBuildingSuits
|
|
sp.countNumSuitsPerTrack(numPerTrack)
|
|
if sync:
|
|
sp.resyncSuits()
|
|
if fly:
|
|
sp.flySuits()
|
|
if count != -1:
|
|
sp.currDesired = count
|
|
|
|
if sp == None:
|
|
response = "No cogs active."
|
|
else:
|
|
response = "Overall, %d cogs (%s); target is %d." % (
|
|
numActual, sp.formatNumSuitsPerTrack(numPerTrack), numTarget)
|
|
|
|
elif not self.air.suitPlanners.has_key(streetId):
|
|
response = "Street %d is not known." % (streetId)
|
|
|
|
else:
|
|
sp = self.air.suitPlanners[streetId]
|
|
|
|
numTarget = sp.calcDesiredNumFlyInSuits() + sp.calcDesiredNumBuildingSuits()
|
|
numActual = sp.numFlyInSuits + sp.numBuildingSuits
|
|
numPerTrack = {}
|
|
sp.countNumSuitsPerTrack(numPerTrack)
|
|
|
|
if sync:
|
|
sp.resyncSuits()
|
|
if fly:
|
|
sp.flySuits()
|
|
if count != -1:
|
|
sp.currDesired = count
|
|
response = "Street %d has %d cogs (%s); target is %d." % (
|
|
streetId, numActual, sp.formatNumSuitsPerTrack(numPerTrack),
|
|
numTarget)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doMinigame(self, word, av, zoneId, senderId):
|
|
"""Handle the ~minigame magic word: request a particular minigame."""
|
|
args = word.split()
|
|
if len(args) == 1:
|
|
# No minigame parameter specified: clear the request.
|
|
mgRequest = MinigameCreatorAI.RequestMinigame.get(av.doId)
|
|
if mgRequest != None:
|
|
mgId = mgRequest[0]
|
|
del MinigameCreatorAI.RequestMinigame[av.doId]
|
|
response = "Request for minigame %d cleared." % (mgId)
|
|
else:
|
|
response = "Usage: ~minigame [<name|id> [difficulty] [safezone]]"
|
|
else:
|
|
# Try to determine the minigame id, keep flag, and the difficulty
|
|
# and safezone overrides, if any
|
|
name = args[1]
|
|
mgId = None
|
|
mgKeep = 0
|
|
mgDiff = None
|
|
mgSzId = None
|
|
|
|
try:
|
|
mgId = int(name)
|
|
numMgs = len(ToontownGlobals.MinigameIDs)
|
|
if mgId < 1 or mgId > numMgs or mgId not in ToontownGlobals.MinigameIDs:
|
|
response = "minigame ID '%s' is out of range" % mgId
|
|
mgId = None
|
|
except:
|
|
name = string.lower(name)
|
|
if name[-4:] == "game":
|
|
name = name[:-4]
|
|
if name[:11] == "distributed":
|
|
name = name[11:]
|
|
mgId = ToontownGlobals.MinigameNames.get(name)
|
|
if mgId == None:
|
|
response = "Unknown minigame '%s'." % (name)
|
|
|
|
argIndex = 2
|
|
while argIndex < len(args):
|
|
arg = args[argIndex]
|
|
arg = string.lower(arg)
|
|
argIndex += 1
|
|
|
|
# it's either a difficulty (float), 'keep',
|
|
# or a safezone (string)
|
|
|
|
# is it 'keep'?
|
|
if arg == 'keep':
|
|
mgKeep = 1
|
|
continue
|
|
|
|
# is it a difficulty?
|
|
try:
|
|
mgDiff = float(arg)
|
|
continue
|
|
except:
|
|
pass
|
|
|
|
mgSzId = self.Str2szId.get(arg)
|
|
if mgSzId is not None:
|
|
continue
|
|
|
|
# it's a string, but it's not a safezone.
|
|
response = ("unknown safezone '%s'; use "
|
|
"tt, dd, dg, mm, br, dl" % arg)
|
|
mgId = None
|
|
break
|
|
|
|
if mgId != None:
|
|
# mdId must be the first element
|
|
MinigameCreatorAI.RequestMinigame[av.doId] = (
|
|
mgId, mgKeep, mgDiff, mgSzId)
|
|
response = "Selected minigame %d" % mgId
|
|
if mgDiff is not None:
|
|
response += ", difficulty %s" % mgDiff
|
|
if mgSzId is not None:
|
|
response += ", safezone %s" % mgSzId
|
|
if mgKeep:
|
|
response += ", keep=true"
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doTreasures(self, word, av, zoneId, senderId):
|
|
"""Handle the ~treasures magic word: fill up the safezone with
|
|
treasures."""
|
|
args = word.split()
|
|
|
|
hood = None
|
|
for h in self.air.hoods:
|
|
if h.zoneId == zoneId:
|
|
hood = h
|
|
break
|
|
|
|
if hood == None or hood.treasurePlanner == None:
|
|
self.down_setMagicWordResponse(senderId, "Not in a safezone.")
|
|
return
|
|
|
|
tp = hood.treasurePlanner
|
|
|
|
if len(args) == 1:
|
|
# No parameter: report the current treasure count.
|
|
response = "%s treasures." % (tp.numTreasures())
|
|
|
|
elif args[1] == "all":
|
|
# ~treasures all: fill up all available treasures.
|
|
tp.placeAllTreasures()
|
|
response = "now %s treasures." % (tp.numTreasures())
|
|
|
|
else:
|
|
response = "Invalid treasures command: %s" % (args[1])
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doEmotes(self, word, av, zoneId, senderId):
|
|
"""Handle the ~emote magic word: turns on/off the specified emotion"""
|
|
args = word.split()
|
|
if len(args) == 1:
|
|
# No parameter specified: clear the request.
|
|
response = "No emote specified."
|
|
elif len(args) == 2:
|
|
# No parameter specified: clear the request.
|
|
response = "Need to specify 0 or 1."
|
|
else:
|
|
emoteId = int(args[1])
|
|
on = int(args[2])
|
|
if emoteId > len(av.emoteAccess) or emoteId < 0:
|
|
response = "Not a valid emote"
|
|
elif on not in [0, 1]:
|
|
response = "Not a valid bit"
|
|
else:
|
|
av.setEmoteAccessId(emoteId, on)
|
|
if on:
|
|
response = "Emote %d enabled" % emoteId
|
|
else:
|
|
response = "Emote %d disabled" % emoteId
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doCatalog(self, word, av, zoneId, senderId):
|
|
"""Handle the ~catalog magic word: manage catalogs"""
|
|
now = time.time()
|
|
args = word.split()
|
|
|
|
# There may be an optional "after" parameter on many of these
|
|
# commands, which specifies the number of minutes to delay
|
|
# before doing the action.
|
|
afterMinutes = 0
|
|
if "after" in args:
|
|
a = args.index("after")
|
|
afterMinutes = int(args[a + 1])
|
|
del args[a + 1]
|
|
del args[a]
|
|
|
|
if len(args) == 1:
|
|
# No parameter: report the current catalog.
|
|
duration = (av.catalogScheduleNextTime * 60) - time.time()
|
|
response = "Week %d, next catalog in %s." % \
|
|
(av.catalogScheduleCurrentWeek,
|
|
PythonUtil.formatElapsedSeconds(duration))
|
|
|
|
elif args[1] == "next":
|
|
# ~catalog next: advance to the next catalog.
|
|
week = av.catalogScheduleCurrentWeek + 1
|
|
self.air.catalogManager.forceCatalog(av, week, afterMinutes)
|
|
response = "Issued catalog for week %s." % (week)
|
|
|
|
elif args[1] == "week":
|
|
# ~catalog week n: force to the catalog of the nth week.
|
|
# Note: need to have catalog-skip-seeks set to true to jump
|
|
# more than one week
|
|
week = int(args[2])
|
|
if week > 0:
|
|
self.air.catalogManager.forceCatalog(av, week, afterMinutes)
|
|
response = "Forced to catalog week %s." % (week)
|
|
else:
|
|
response = "Invalid catalog week %s." % (week)
|
|
|
|
elif args[1] == "season":
|
|
# ~catalog season mm/dd: regenerate the monthly catalog
|
|
# items as if it were the indicated month and day.
|
|
if len(args) == 3:
|
|
mmdd = args[2].split('/')
|
|
mm = int(mmdd[0])
|
|
dd = int(mmdd[1])
|
|
else:
|
|
mm = int(args[2])
|
|
dd = int(args[3])
|
|
|
|
self.air.catalogManager.forceMonthlyCatalog(av, mm, dd)
|
|
response = "%s items for %d/%0d." % (len(av.monthlyCatalog), mm, dd)
|
|
|
|
elif (args[1] == "clear") or (args[1] == "reset"):
|
|
# ~catalog clear: reset the catalog (and the back catalog)
|
|
# to its initial state.
|
|
av.b_setCatalog(CatalogItemList.CatalogItemList(),
|
|
CatalogItemList.CatalogItemList(),
|
|
CatalogItemList.CatalogItemList())
|
|
av.catalogScheduleCurrentWeek = 0
|
|
av.catalogScheduleNextTime = 0
|
|
self.air.catalogManager.deliverCatalogFor(av)
|
|
response = "Catalog reset."
|
|
|
|
elif args[1] == "deliver":
|
|
# ~catalog deliver: force the immediate delivery of all
|
|
# of the on-order item(s).
|
|
|
|
now = (int)(time.time() / 60 + 0.5)
|
|
deliveryTime = now + afterMinutes
|
|
|
|
for item in av.onOrder:
|
|
item.deliveryDate = deliveryTime
|
|
av.onOrder.markDirty()
|
|
av.b_setDeliverySchedule(av.onOrder)
|
|
|
|
response = "Delivered %s item(s)." % (len(av.onOrder))
|
|
|
|
elif args[1] in ["reload", "dump"]:
|
|
# These commands are handled by the client; we ignore them.
|
|
return
|
|
|
|
else:
|
|
response = "Invalid catalog command: %s" % (args[1])
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doDna(self, word, av, zoneId, senderId):
|
|
"""Handle the ~dna magic word: change your dna"""
|
|
|
|
# Strip of the "~dna" part; everything else is parameters to
|
|
# AvatarDNA.updateToonProperties.
|
|
parms = string.strip(word[4:])
|
|
|
|
# Get a copy of the avatar's current DNA.
|
|
dna = ToonDNA.ToonDNA(av.dna.makeNetString())
|
|
|
|
# Modify it according to the user's parameter selection.
|
|
eval("dna.updateToonProperties(%s)" % (parms))
|
|
|
|
av.b_setDNAString(dna.makeNetString())
|
|
response = "%s" % (dna.asTuple(),)
|
|
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def getPet(self, av):
|
|
response = None
|
|
pet = None
|
|
|
|
petId = av.getPetId()
|
|
if petId == 0:
|
|
response = "don't have a pet"
|
|
else:
|
|
pet = self.air.doId2do.get(petId)
|
|
if pet is None:
|
|
response = "pet not active, use ~pet"
|
|
return pet, response
|
|
|
|
def doBossBattle(self, word, av, zoneId, senderId):
|
|
"""Handle the ~bossBattle magic word: manage a final boss
|
|
battle."""
|
|
|
|
args = word.split()
|
|
|
|
# Find the particular Boss Cog that's in the same zone with
|
|
# the avatar.
|
|
bossCog = None
|
|
for distObj in self.air.doId2do.values():
|
|
if isinstance(distObj, DistributedBossCogAI.DistributedBossCogAI):
|
|
if distObj.zoneId == zoneId:
|
|
bossCog = distObj
|
|
break
|
|
|
|
if bossCog == None:
|
|
# The caller isn't in a zone with a Boss Cog; use the
|
|
# default Boss zone.
|
|
|
|
# In this case, we must accept a dept indicator.
|
|
if len(args) < 2 or args[1] not in SuitDNA.suitDepts:
|
|
response = "Error: Must specify boss dept: s, m, l, c"
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
return
|
|
|
|
dept = args[1]
|
|
del args[1]
|
|
deptIndex = SuitDNA.suitDepts.index(dept)
|
|
|
|
if self.__bossBattleZoneId[deptIndex] == None:
|
|
# Make up a new zone for the battle.
|
|
zoneId = self.air.allocateZone()
|
|
self.__bossBattleZoneId[deptIndex] = zoneId
|
|
|
|
bossCog = self.makeBossCog(dept, zoneId)
|
|
bossCog.b_setState('Frolic')
|
|
self.__bossCog[deptIndex] = bossCog
|
|
|
|
else:
|
|
bossCog = self.__bossCog[deptIndex]
|
|
|
|
response = None
|
|
if len(args) == 1:
|
|
# No parameter: send the avatar to the battle zone.
|
|
self.sendUpdateToAvatarId(av.doId, 'requestTeleport',
|
|
["cogHQLoader", "cogHQBossBattle",
|
|
bossCog.getHoodId(),
|
|
bossCog.zoneId, 0])
|
|
|
|
elif args[1] == "list":
|
|
# ~bossBattle [smlc] list: list the current boss battles
|
|
# underway for the indicated type of suit.
|
|
response = ""
|
|
for bc in DistributedBossCogAI.AllBossCogs:
|
|
if bc.dept == bossCog.dept and bc != bossCog:
|
|
response += ", %s %s %s" % (bc.zoneId, bc.state, len(bc.involvedToons))
|
|
if response:
|
|
response = response[2:]
|
|
else:
|
|
response = "No boss battles."
|
|
|
|
elif args[1] == "spy":
|
|
# ~bossBattle spy [smlc] <zoneId>: go visit the indicated
|
|
# boss battle in ghost mode.
|
|
zoneId = int(args[2])
|
|
bc = bossCog
|
|
for bc in DistributedBossCogAI.AllBossCogs:
|
|
if bc.zoneId == zoneId:
|
|
break
|
|
if bc.zoneId == zoneId:
|
|
self.sendUpdateToAvatarId(av.doId, 'requestTeleport',
|
|
["cogHQLoader", "cogHQBossBattle",
|
|
bc.getHoodId(),
|
|
bc.zoneId, 0])
|
|
av.b_setGhostMode(2)
|
|
else:
|
|
response = "No boss battle in zone %s" % (zoneId)
|
|
|
|
|
|
elif args[1] == "start":
|
|
# ~bossBattle start: restart the boss battle.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Elevator started."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('WaitForToons')
|
|
|
|
elif args[1] == "one":
|
|
# ~bossBattle one: straight to battle one.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Battle one started."
|
|
bossCog.acceptNewToons()
|
|
bossCog.makeBattleOneBattles()
|
|
bossCog.b_setState('BattleOne')
|
|
|
|
elif args[1] == "preTwo":
|
|
# ~bossBattle preTwo: preview to battle two.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
elif not hasattr(bossCog, 'enterRollToBattleTwo'):
|
|
response = "Battle two preview."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('PrepareBattleTwo')
|
|
else:
|
|
response = "Battle two preview."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('RollToBattleTwo')
|
|
|
|
elif args[1] == "two":
|
|
# ~bossBattle two: straight to battle two.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Battle two started."
|
|
bossCog.acceptNewToons()
|
|
if hasattr(bossCog, 'makeBattleTwoBattles'):
|
|
bossCog.makeBattleTwoBattles()
|
|
bossCog.b_setState('BattleTwo')
|
|
|
|
elif args[1] == "preThree":
|
|
# ~bossBattle preThree: preview to battle three.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Battle three preview."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('PrepareBattleThree')
|
|
|
|
elif args[1] == "three":
|
|
# ~bossBattle three: straight to battle three.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Battle three started."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('BattleThree')
|
|
|
|
elif args[1] == "preFour":
|
|
# ~bossBattle preFour: preview to battle four.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Battle four preview."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('PrepareBattleFour')
|
|
|
|
elif args[1] == "four":
|
|
# ~bossBattle four: straight to battle four.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Battle four started."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('BattleFour')
|
|
|
|
elif args[1] == "victory":
|
|
# ~bossBattle victory: straight to the victory sequence.
|
|
if not bossCog.hasToons():
|
|
response = "No toons."
|
|
else:
|
|
response = "Victory sequence started."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('Victory')
|
|
|
|
elif args[1] == "fsm":
|
|
# ~bossBattle fsm state: directly to named state.
|
|
if len(args) <= 2:
|
|
response = "No state specified."
|
|
else:
|
|
response = "Requested state %s." % (args[2])
|
|
bossCog.b_setState(args[2])
|
|
|
|
elif args[1] == "stop":
|
|
# ~bossBattle start: stop the boss battle.
|
|
response = "Battle stopped."
|
|
bossCog.acceptNewToons()
|
|
bossCog.b_setState('Frolic')
|
|
|
|
elif args[1] == "hit":
|
|
# ~bossBattle hit [damage]: hit the boss cog during the
|
|
# pie scene. This will make him dizzy first if he is not
|
|
# already dizzy (as if we successfully lobbed a pie into
|
|
# the undercarriage) and then applies the indicated damage
|
|
# (as if we hit his upper body the indicated number of
|
|
# times).
|
|
|
|
if len(args) <= 2:
|
|
damage = 1
|
|
else:
|
|
damage = int(args[2])
|
|
|
|
##
|
|
## this is very suspect .. it is reasigning a internal var(msgSender)..
|
|
## it is trying to make the message look like it came from a difrent avatarID
|
|
## to other areas of the code .. ???
|
|
self.air.msgSender = av.doId
|
|
bossCog.magicWordHit(damage, av.doId)
|
|
|
|
elif args[1] == "safe":
|
|
# ~bossBattle safe: Ignore hits to the toon during the pie
|
|
# scene. This magic word is handled by the client.
|
|
pass
|
|
|
|
elif args[1] == "avatarEnter":
|
|
# ~bossBattle avatarEnter: Force a call to d_avatarEnter
|
|
#This magic word is handled by the client.
|
|
pass
|
|
|
|
elif args[1] == "stun":
|
|
# ~bossBattle stun: stun all of the goons in the CFO
|
|
# battle. This magic word is handled by the client.
|
|
pass
|
|
|
|
elif args[1] == "destroy":
|
|
# ~bossBattle destroy: destroy all of the goons in the CFO
|
|
# battle. This magic word is handled by the client.
|
|
pass
|
|
|
|
elif args[1] == "reset":
|
|
# ~bossBattle reset: reset all of the goons, cranes, and
|
|
# safes in the CFO sequence.
|
|
bossCog.magicWordReset()
|
|
|
|
elif args[1] == "goons":
|
|
# ~bossBattle goons [num]: reset all of the goons and set
|
|
# the number to the indicated value.
|
|
if len(args) > 2:
|
|
bossCog.maxGoons = int(args[2])
|
|
|
|
bossCog.magicWordResetGoons()
|
|
elif args[1] == "toggleMove":
|
|
# make the ceo toggle doing move attacks
|
|
if hasattr(bossCog, 'toggleMove'):
|
|
doingMoveAttack = bossCog.toggleMove()
|
|
response = "doing move attack = %s" % doingMoveAttack
|
|
else:
|
|
response = "toggleMove is only for CEO"
|
|
else:
|
|
response = "Invalid bossBattle command: %s" % (args[1])
|
|
|
|
if response:
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def makeBossCog(self, dept, zoneId):
|
|
bossCog = None
|
|
|
|
if dept == 's':
|
|
bossCog = DistributedSellbotBossAI.DistributedSellbotBossAI(self.air)
|
|
bossCog.generateWithRequired(zoneId)
|
|
bossCog.b_setState('Frolic')
|
|
|
|
elif dept == 'm':
|
|
bossCog = DistributedCashbotBossAI.DistributedCashbotBossAI(self.air)
|
|
bossCog.generateWithRequired(zoneId)
|
|
|
|
elif dept == 'l':
|
|
bossCog = DistributedLawbotBossAI.DistributedLawbotBossAI(self.air)
|
|
bossCog.generateWithRequired(zoneId)
|
|
bossCog.b_setState('Frolic')
|
|
elif dept == 'c':
|
|
bossCog = DistributedBossbotBossAI.DistributedBossbotBossAI(self.air)
|
|
bossCog.generateWithRequired(zoneId)
|
|
bossCog.b_setState('Frolic')
|
|
|
|
else:
|
|
raise StandardError('Not implemented: boss cog %s' % (dept))
|
|
|
|
return bossCog
|
|
|
|
|
|
def doGarden(self, word, av, zoneId, senderId):
|
|
"""Handle the ~garden magic worde."""
|
|
|
|
args = word.split()
|
|
|
|
response = None
|
|
action = None
|
|
if len(args) == 1:
|
|
# No parameter: change it to usage
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"Usage:\n~garden action <optional paremeters>\n'~garden help' for more info ")
|
|
return
|
|
|
|
action = args[1]
|
|
if action == 'help':
|
|
response = 'start\nclear\nwilt <plot>\nunwilt <plot>\nplant <plantKey> <plot> <water> <growth> <variety>\nclearCarriedSpecials\nclearCollection\ncompleteCollection\nwater <waterLevel>\nshovel <0-3> <shovelSkill>\nrandomBasket\nnuke\nepoch <opt num>\nwateringCan <0-3> <skill>'
|
|
elif action == 'start':
|
|
messenger.send("gardenTest", [senderId])
|
|
response = "Test Garden Planted"
|
|
elif action == 'clear':
|
|
messenger.send("gardenClear", [senderId])
|
|
response = "Garden Cleared"
|
|
elif action == 'nuke':
|
|
#clear the garden and remove the planters
|
|
#clear the garden started flag
|
|
messenger.send("gardenNuke", [senderId])
|
|
av.b_setGardenStarted(False)
|
|
response = "Garden Nuked"
|
|
elif action == 'specials':
|
|
#messenger.send("gardenSpecials", [senderId])
|
|
receiver = self.air.doId2do.get(senderId)
|
|
if receiver:
|
|
receiver.giveMeSpecials()
|
|
response = "Garden Specials Added"
|
|
elif action == 'wilt':
|
|
if len(args) >= 3:
|
|
messenger.send("wiltGarden", [senderId, int(args[2])] )
|
|
else:
|
|
messenger.send("wiltGarden", [senderId])
|
|
response = "Garden wilted"
|
|
elif action == 'unwilt':
|
|
if len(args) >= 3:
|
|
messenger.send("unwiltGarden", [senderId, int(args[2])] )
|
|
else:
|
|
messenger.send("unwiltGarden", [senderId])
|
|
response = "Garden unwilted"
|
|
elif action == 'water':
|
|
waterLevel = 1
|
|
if len(args) > 2:
|
|
waterLevel = int(args[2])
|
|
specificHardPoint = -1
|
|
if len(args) > 3:
|
|
specificHardPoint = int(args[3])
|
|
|
|
messenger.send("waterGarden", [senderId, waterLevel, specificHardPoint] )
|
|
|
|
response = "water level changed to %d" % waterLevel
|
|
elif action == 'growth':
|
|
waterLevel = 1
|
|
if len(args) > 2:
|
|
waterLevel = int(args[2])
|
|
specificHardPoint = -1
|
|
if len(args) > 3:
|
|
specificHardPoint = int(args[3])
|
|
|
|
messenger.send("growthGarden", [senderId, waterLevel, specificHardPoint] )
|
|
|
|
response = "growth level changed to %d" % waterLevel
|
|
elif action == 'plant':
|
|
type = 0
|
|
plot = 0
|
|
water = 0
|
|
growth = 1
|
|
variety = 0
|
|
if len(args) > 2:
|
|
type = int(args[2])
|
|
if len(args) > 3:
|
|
plot = int(args[3])
|
|
if len(args) > 4:
|
|
water = int(args[4])
|
|
if len(args) > 5:
|
|
growth = int(args[5])
|
|
if len(args) > 6:
|
|
variety = int(args[6])
|
|
|
|
response = "Planting type=%d plot=%d water=%d growth=%d" % (type,plot,water,growth)
|
|
messenger.send("gardenPlant", [senderId, type, plot, water, growth, variety])
|
|
elif action == 'clearCarriedSpecials':
|
|
av.b_setGardenSpecials( [])
|
|
response = "Cleared garden specials carried by toon"
|
|
elif action == 'clearCollection':
|
|
av.b_setFlowerCollection( [], [])
|
|
response = "Cleared flower collection."
|
|
elif action == 'completeCollection':
|
|
#from toontown.estate import GardenGlobals
|
|
varietyList = []
|
|
speciesList = []
|
|
flowerSpecies = GardenGlobals.getFlowerSpecies()
|
|
for species in flowerSpecies:
|
|
numVarieties = len(GardenGlobals.getFlowerVarieties(species))
|
|
for variety in range(numVarieties):
|
|
speciesList.append(species)
|
|
varietyList.append(variety)
|
|
|
|
av.b_setFlowerCollection( speciesList, varietyList)
|
|
av.b_setGardenTrophies([])
|
|
response = "Complete flower collection."
|
|
elif action == 'epoch':
|
|
numEpoch = 1
|
|
if len(args) > 2:
|
|
numEpoch = int(args[2])
|
|
messenger.send("epochGarden", [senderId, numEpoch])
|
|
response = "%d garden epoch has been run" % numEpoch
|
|
elif action == 'shovel':
|
|
if len(args) < 3:
|
|
response = "specify a shovel (0-3)"
|
|
else:
|
|
shovel = 0
|
|
passedShovel = int(args[2])
|
|
if passedShovel >= 0 and \
|
|
passedShovel < GardenGlobals.MAX_SHOVELS:
|
|
shovel = passedShovel
|
|
skill =0
|
|
if len(args) >= 4:
|
|
passedSkill = int(args[3])
|
|
skill = min (passedSkill, GardenGlobals.ShovelAttributes[shovel]['skillPts'] - 1)
|
|
skill = max (skill, 0)
|
|
|
|
av.b_setShovel(shovel)
|
|
av.b_setShovelSkill(skill)
|
|
response = "Set shovel=%d shovelSkill=%d" % (shovel,skill)
|
|
elif action == 'wateringCan':
|
|
if len(args) < 3:
|
|
response = "specify a watering can (0-3)"
|
|
else:
|
|
wateringCan = 0
|
|
passedWateringCan = int(args[2])
|
|
if passedWateringCan >= 0 and \
|
|
passedWateringCan < GardenGlobals.MAX_WATERING_CANS:
|
|
wateringCan = passedWateringCan
|
|
skill =0
|
|
if len(args) >= 4:
|
|
passedSkill = int(args[3])
|
|
skill = min (passedSkill, GardenGlobals.WateringCanAttributes[wateringCan]['skillPts'] - 1)
|
|
skill = max (skill, 0)
|
|
|
|
av.b_setWateringCan(wateringCan)
|
|
av.b_setWateringCanSkill(skill)
|
|
response = "Set wateringCan=%d wateringCanSkill=%d" % (wateringCan,skill)
|
|
elif action == 'randomBasket':
|
|
av.makeRandomFlowerBasket()
|
|
self.down_setMagicWordResponse(senderId, "Created random flower basket")
|
|
elif action == "allTrophies":
|
|
allTrophyList = GardenGlobals.TrophyDict.keys()
|
|
av.b_setGardenTrophies(allTrophyList)
|
|
self.down_setMagicWordResponse(senderId, "All garden trophies")
|
|
else:
|
|
response = 'Invalid garden command.'
|
|
if response:
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
def doGolf(self, word, av, zoneId, senderId):
|
|
"""Handle the ~golf magic words."""
|
|
args = word.split()
|
|
response = None
|
|
action = None
|
|
|
|
if len(args) == 1:
|
|
# No parameter: change it to usage
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"Usage:\n~golf action <optional paremeters>\n'~golf help' for more info ")
|
|
return
|
|
|
|
action = args[1]
|
|
if action == 'help':
|
|
response = 'endHole\nendcourse\ntest\nclearHistory\nMaxHistory'
|
|
elif action == 'drive':
|
|
course = GolfManagerAI.GolfManagerAI().findGolfCourse(senderId)
|
|
response = "drive failed."
|
|
if course:
|
|
result = course.toggleDrivePermission(senderId)
|
|
if result:
|
|
response = "Press up, down, left&right simultaneously to drive."
|
|
else:
|
|
response = "Toon is no longer driving."
|
|
elif action == 'endhole' or action == 'endHole':
|
|
course = GolfManagerAI.GolfManagerAI().findGolfCourse(senderId)
|
|
if course:
|
|
holeId, holeDoId = course.abortCurrentHole()
|
|
response = "Aborting holeId %d, doId=%d" % (holeId, holeDoId)
|
|
else:
|
|
response = "Couldn't find golf course"
|
|
elif action == 'endcourse' or action == 'endCourse':
|
|
course = GolfManagerAI.GolfManagerAI().findGolfCourse(senderId)
|
|
if course:
|
|
course.setCourseAbort()
|
|
response = "Aborting course %d" % course.doId
|
|
else:
|
|
response = "Couldn't find golf course"
|
|
elif action == 'test':
|
|
#messenger.send("gardenTest", [senderId])
|
|
response = "golf test"
|
|
avList = [senderId];
|
|
args = word.split()
|
|
import string
|
|
for i in range(2, len(args)):
|
|
avList.append(string.atoi(args[i]))
|
|
manager = GolfManagerAI.GolfManagerAI()
|
|
#simbase.golfGoer.generateWithRequired(OTPGlobals.UberZone)
|
|
courseId = 0
|
|
zoneId = manager.readyGolfCourse(avList, courseId)
|
|
for avId in avList:
|
|
golfer = simbase.air.doId2do.get(avId)
|
|
if golfer:
|
|
golfer.sendUpdate("sendToGolfCourse", [zoneId])
|
|
response = 'sending to golf course %d courseId=%d' % \
|
|
(zoneId, courseId)
|
|
elif action == 'clearBest':
|
|
response = 'clearBest failed'
|
|
av = simbase.air.doId2do.get(senderId)
|
|
if av:
|
|
emptyHoleBest = [0] * 18
|
|
av.b_setGolfHoleBest(emptyHoleBest)
|
|
emptyCourseBest = [0] * 3
|
|
av.b_setGolfCourseBest(emptyCourseBest)
|
|
response = 'golf best cleared'
|
|
elif action == 'maxBest':
|
|
response = 'maxBest failed'
|
|
av = simbase.air.doId2do.get(senderId)
|
|
if av:
|
|
emptyHoleBest = [1] * 18
|
|
av.b_setGolfHoleBest(emptyHoleBest)
|
|
emptyCourseBest = [1] * 3
|
|
av.b_setGolfCourseBest(emptyCourseBest)
|
|
response = 'golf best maxed'
|
|
elif action == 'clearHistory':
|
|
response = 'clearHistory failed'
|
|
emptyHistory = [0] * 18
|
|
av = simbase.air.doId2do.get(senderId)
|
|
if av:
|
|
av.b_setGolfHistory(emptyHistory)
|
|
response = 'golf history cleared'
|
|
elif action == 'maxHistory':
|
|
response = 'maxHistory failed'
|
|
maxHistory = [600] * 18
|
|
av = simbase.air.doId2do.get(senderId)
|
|
if av:
|
|
av.b_setGolfHistory(maxHistory)
|
|
response = 'golf history maxeded'
|
|
elif action == 'midHistory':
|
|
# set it up so that we just need one more course complete to get a cup
|
|
response = 'midHistory failed'
|
|
midHistory = [0] * 18
|
|
midHistory[GolfGlobals.CoursesCompleted] = GolfGlobals.TrophyRequirements[GolfGlobals.CoursesCompleted][1] - 1
|
|
#midHistory = [GolfGlobals.CoursesUnderPar] = GolfGlobals.TrophyRequirements[GolfGlobals.CoursesUnderPar][0]
|
|
midHistory[GolfGlobals.HoleInOneShots] = GolfGlobals.TrophyRequirements[GolfGlobals.HoleInOneShots][0]
|
|
midHistory[GolfGlobals.EagleOrBetterShots] = GolfGlobals.TrophyRequirements[GolfGlobals.EagleOrBetterShots][0]
|
|
midHistory[GolfGlobals.BirdieOrBetterShots] = GolfGlobals.TrophyRequirements[GolfGlobals.BirdieOrBetterShots][0]
|
|
midHistory[GolfGlobals.ParOrBetterShots] = GolfGlobals.TrophyRequirements[GolfGlobals.ParOrBetterShots][0]
|
|
midHistory[GolfGlobals.MultiPlayerCoursesCompleted] = GolfGlobals.TrophyRequirements[GolfGlobals.MultiPlayerCoursesCompleted][0]
|
|
midHistory[GolfGlobals.CourseZeroWins] = GolfGlobals.TrophyRequirements[GolfGlobals.CourseZeroWins][0]
|
|
midHistory[GolfGlobals.CourseOneWins] = GolfGlobals.TrophyRequirements[GolfGlobals.CourseOneWins][0]
|
|
midHistory[GolfGlobals.CourseTwoWins] = GolfGlobals.TrophyRequirements[GolfGlobals.CourseTwoWins][0]
|
|
|
|
av = simbase.air.doId2do.get(senderId)
|
|
if av:
|
|
av.b_setGolfHistory(midHistory)
|
|
response = 'golf history midded'
|
|
elif action == 'unlimitedSwing' or action == "us":
|
|
av.b_setUnlimitedSwing(not av.getUnlimitedSwing())
|
|
if av.getUnlimitedSwing():
|
|
response = "Av %s has an unlimited swing" % (av.getDoId())
|
|
else:
|
|
response = "Av %s does NOT have unlimited swings" % (av.getDoId())
|
|
elif action == 'hole':
|
|
import string
|
|
manager = GolfManagerAI.GolfManagerAI()
|
|
if len(args) <= 2:
|
|
# No minigame parameter specified: clear the request.
|
|
holeRequest = GolfManagerAI.RequestHole.get(av.doId)
|
|
if holeRequest != None:
|
|
holeId = holeRequest[0]
|
|
del GolfManagerAI.RequestHole[av.doId]
|
|
response = "Request for hole %d cleared." % (holeId)
|
|
else:
|
|
response = "Usage: ~golf hole [<holeId>]"
|
|
else:
|
|
holeId = None
|
|
holeKeep = 0
|
|
name = args[2]
|
|
try:
|
|
holeId = int(name)
|
|
if holeId not in GolfGlobals.HoleInfo:
|
|
response = "hole ID '%s' is out of range" % holeId
|
|
holeId = None
|
|
except:
|
|
#name = string.lower(name)
|
|
#for testHoleId in GolfGlobals.HoleInfo:
|
|
# holeName = string.lower(GolfGlobals.getHoleName(testHoleId))
|
|
# if name == holeName:
|
|
# holeId = testHoleId
|
|
# break;
|
|
if holeId == None:
|
|
response = "Unknown hole '%s'." % (name)
|
|
|
|
argIndex = 2
|
|
while argIndex < len(args):
|
|
arg = args[argIndex]
|
|
arg = string.lower(arg)
|
|
argIndex += 1
|
|
|
|
# it's either a difficulty (float), 'keep',
|
|
# or a safezone (string)
|
|
|
|
# is it 'keep'?
|
|
if arg == 'keep':
|
|
holeKeep = 1
|
|
continue
|
|
|
|
if holeId != None:
|
|
# hoId must be the first element
|
|
GolfManagerAI.RequestHole[av.doId] = (
|
|
holeId, holeKeep)
|
|
response = "Selected hole %d as 1st hole" % holeId
|
|
if holeKeep:
|
|
response += ", keep=true"
|
|
|
|
|
|
if response:
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doMail(self,word, av, zoneId, senderId):
|
|
"""Handle mail magic words."""
|
|
args = word.split()
|
|
response = None
|
|
action = None
|
|
|
|
if len(args) == 1:
|
|
# No parameter: change it to usage
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"Usage:\n~mail action <optional paremeters>\n'~mail help' for more info ")
|
|
return
|
|
|
|
action = args[1]
|
|
|
|
if action == 'simple':
|
|
if len(args) < 4:
|
|
response = "~mail simple <recipient avId> 'text'"
|
|
else:
|
|
recipient = int(args[2])
|
|
text = args[3]
|
|
for i in xrange(4, len(args)):
|
|
text += ' ' + args[i]
|
|
self.air.mailManager.sendSimpleMail(
|
|
senderId, recipient, text)
|
|
|
|
if response:
|
|
self.down_setMagicWordResponse(senderId, response)
|
|
|
|
|
|
def doParty(self,word, av, zoneId, senderId):
|
|
"""Handle mail magic words."""
|
|
args = word.split()
|
|
response = None
|
|
action = None
|
|
|
|
if len(args) == 1:
|
|
# No parameter: change it to usage
|
|
self.down_setMagicWordResponse(
|
|
senderId,
|
|
"Available commands: plan, new, update, checkStart, end, debugGrid")
|
|
return
|
|
|
|
action = args[1]
|
|
|
|
if action == 'new':
|
|
if len(args) < 2:
|
|
response = "~party new <inviteeAvId1> <inviteeAvId2> <inviteeAvId3> ... <inviteeAvIdX>"
|
|
else:
|
|
invitees = []
|
|
for i in xrange(2, len(args)):
|
|
invitees.append( int(args[i]))
|
|
# start the party 1 minute from now
|
|
startTime = datetime.datetime.now(self.air.toontownTimeManager.serverTimeZone) + datetime.timedelta(minutes=-1)
|
|
endTime = startTime + datetime.timedelta(hours=PartyGlobals.DefaultPartyDuration)
|
|
|
|
from toontown.parties.PartyEditorGrid import PartyEditorGrid
|
|
|
|
# Make the avatar rich.
|
|
av.b_setMaxBankMoney(5000)
|
|
av.b_setMoney(av.maxMoney)
|
|
av.b_setBankMoney(av.maxBankMoney)
|
|
|
|
gridEditor = PartyEditorGrid(None)
|
|
|
|
# Flip on the Y so it matches the grid in-game.
|
|
gridEditor.grid.reverse()
|
|
|
|
# Given a center coord (x or y) and a size (w or h), returns a list of indices in
|
|
# in the grid on that axis. (WARNING: Can return invalid indices.)
|
|
def gridComputeRange(centerGrid, size):
|
|
result = []
|
|
if size == 1:
|
|
result = [centerGrid]
|
|
else:
|
|
# Need to round with negative values otherwise for center=0, size=3, the
|
|
# result will be [1, 0] when we expect [1, 0, -1].
|
|
# The range without rounding: range(int(1.5), int(-1.5), -1)
|
|
# The range with rounding: range(int(1.5), int(-2), -1)
|
|
# Not a problem with center>=2 in this example:
|
|
# The range without rounding: range(int(3.5), int(0.5), -1)
|
|
# The range with rounding: range(int(3.5), int(0), -1)
|
|
result = range(int(centerGrid + size/2.0),
|
|
int(centerGrid - round(size/2.0)), -1)
|
|
|
|
# The result list should be the same size as given.
|
|
assert len(result) == size, "Bad result range: c=%s s=%s result=%s" % (centerGrid, size, result)
|
|
|
|
return result
|
|
|
|
# Returns true if the given space is available centered at x,y with dims w,h.
|
|
def gridIsAvailable(x, y, w, h):
|
|
for j in gridComputeRange(y, h):
|
|
if 0 > j or j >= len(gridEditor.grid):
|
|
return False
|
|
for i in gridComputeRange(x, w):
|
|
if 0 > i or i >= len(gridEditor.grid[0]):
|
|
return False
|
|
if gridEditor.grid[j][i] == None:
|
|
return False
|
|
|
|
#print("grid available: xy(%s %s) wh(%s %s)" % (x, y, w, h))
|
|
return True
|
|
|
|
# Returns the first x,y (centered) that has space for w,h.
|
|
def gridGetAvailable(w, h):
|
|
for y in range(len(gridEditor.grid)):
|
|
for x in range(len(gridEditor.grid[0])):
|
|
if gridIsAvailable(x, y, w, h):
|
|
return x, y
|
|
return None, None
|
|
|
|
# Returns True and an x,y (centered) coord for the given space. Marks that space used.
|
|
def gridTryPlace(w, h):
|
|
x, y = gridGetAvailable(w, h)
|
|
if not x == None:
|
|
for j in gridComputeRange(y, h):
|
|
for i in gridComputeRange(x, w):
|
|
gridEditor.grid[j][i] = None
|
|
return True, x, y
|
|
else:
|
|
return False, None, None
|
|
|
|
actualActIdsToAdd = [
|
|
#PartyGlobals.ActivityIds.PartyJukebox, # mut.ex: PartyJukebox40
|
|
PartyGlobals.ActivityIds.PartyCannon,
|
|
#PartyGlobals.ActivityIds.PartyTrampoline,
|
|
PartyGlobals.ActivityIds.PartyCatch,
|
|
#PartyGlobals.ActivityIds.PartyDance, # mut.ex: PartyDance20
|
|
PartyGlobals.ActivityIds.PartyTugOfWar,
|
|
PartyGlobals.ActivityIds.PartyFireworks,
|
|
PartyGlobals.ActivityIds.PartyClock,
|
|
PartyGlobals.ActivityIds.PartyJukebox40,
|
|
PartyGlobals.ActivityIds.PartyDance20,
|
|
PartyGlobals.ActivityIds.PartyCog,
|
|
PartyGlobals.ActivityIds.PartyVictoryTrampoline, # victory party
|
|
]
|
|
|
|
actualDecorIdsToAdd = [
|
|
PartyGlobals.DecorationIds.BalloonAnvil,
|
|
PartyGlobals.DecorationIds.BalloonStage,
|
|
PartyGlobals.DecorationIds.Bow,
|
|
PartyGlobals.DecorationIds.Cake,
|
|
PartyGlobals.DecorationIds.Castle,
|
|
PartyGlobals.DecorationIds.GiftPile,
|
|
PartyGlobals.DecorationIds.Horn,
|
|
PartyGlobals.DecorationIds.MardiGras,
|
|
PartyGlobals.DecorationIds.NoiseMakers,
|
|
PartyGlobals.DecorationIds.Pinwheel,
|
|
PartyGlobals.DecorationIds.GagGlobe,
|
|
#PartyGlobals.DecorationIds.BannerJellyBean,
|
|
PartyGlobals.DecorationIds.CakeTower,
|
|
#PartyGlobals.DecorationIds.HeartTarget, # valentoons
|
|
#PartyGlobals.DecorationIds.HeartBanner, # valentoons
|
|
#PartyGlobals.DecorationIds.FlyingHeart, # valentoons
|
|
PartyGlobals.DecorationIds.Hydra, # 16: victory party
|
|
PartyGlobals.DecorationIds.BannerVictory, # 17: victory party
|
|
PartyGlobals.DecorationIds.CannonVictory, # 18: victory party
|
|
PartyGlobals.DecorationIds.CogStatueVictory, # 19: victory party
|
|
PartyGlobals.DecorationIds.TubeCogVictory, # 20: victory party
|
|
PartyGlobals.DecorationIds.cogIceCreamVictory, # 21: victory party
|
|
]
|
|
|
|
activities = []
|
|
|
|
for itemId in actualActIdsToAdd:
|
|
item = PartyGlobals.ActivityInformationDict[itemId]
|
|
success, x, y = gridTryPlace(*item['gridsize'])
|
|
if success:
|
|
print("~party new ADDED: Activity %s %s at %s, %s" % (itemId, str(item['gridsize']), x, y))
|
|
# item index, grid x, grid y, heading
|
|
partyItem = (itemId, x, y, 0)
|
|
activities.append(partyItem)
|
|
else:
|
|
print("~party new SKIPPED: No room for activity %s" % itemId)
|
|
|
|
decorations = []
|
|
|
|
for itemId in actualDecorIdsToAdd:
|
|
item = PartyGlobals.DecorationInformationDict[itemId]
|
|
success, x, y = gridTryPlace(*item['gridsize'])
|
|
if success:
|
|
print("~party new ADDED: Decoration %s %s at %s, %s" % (itemId, str(item['gridsize']), x, y))
|
|
# item index, grid x, grid y, heading
|
|
partyItem = (itemId, x, y, 0)
|
|
decorations.append(partyItem)
|
|
else:
|
|
print("~party new SKIPPED: No room for decoration %s" % itemId)
|
|
|
|
isPrivate = False
|
|
inviteTheme = PartyGlobals.InviteTheme.Birthday
|
|
self.air.partyManager.addPartyRequest(
|
|
senderId,
|
|
startTime.strftime("%Y-%m-%d %H:%M:%S"),
|
|
endTime.strftime("%Y-%m-%d %H:%M:%S"),
|
|
isPrivate,
|
|
inviteTheme,
|
|
activities,
|
|
decorations,
|
|
invitees,
|
|
)
|
|
# force an immediate check of which parties can start
|
|
self.air.partyManager.forceCheckStart()
|
|
|
|
elif action == 'update':
|
|
# simulate this avatarLogging in, which forces invites
|
|
# and party updates from the dbs
|
|
self.air.partyManager.partyUpdate(senderId)
|
|
|
|
elif action == 'checkStart':
|
|
# force an immediate check of which parties can start
|
|
self.air.partyManager.forceCheckStart()
|
|
|
|
elif action == 'unreleasedServer':
|
|
newVal = self.air.partyManager.toggleAllowUnreleasedServer()
|
|
response = "Allow Unreleased Server= %s" % newVal
|
|
|
|
elif action == 'canBuy':
|
|
newVal = self.air.partyManager.toggleCanBuyParties()
|
|
response = "can buy parties= %s" % newVal
|
|
|
|
elif action == 'end':
|
|
response = self.air.partyManager.magicWordEnd(senderId)
|
|
|
|
elif action == 'plan':
|
|
response = "Going to party grounds to plan"
|
|
|
|
# hoodId determines the loading
|
|
hoodId = ToontownGlobals.PartyHood
|
|
|
|
self.sendUpdateToAvatarId(av.doId, 'requestTeleport',
|
|
["safeZoneLoader", "party",
|
|
hoodId, 0, 0])
|
|
|
|
if response:
|
|
self.down_setMagicWordResponse(senderId, response)
|