oldschool-toontown/toontown/toon/DistributedToonAI.py

4429 lines
173 KiB
Python
Raw Normal View History

2019-11-02 17:27:54 -05:00
from otp.ai.AIBaseGlobal import *
from pandac.PandaModules import *
from otp.otpbase import OTPGlobals
from direct.directnotify import DirectNotifyGlobal
from . import ToonDNA
2019-11-02 17:27:54 -05:00
from toontown.suit import SuitDNA
from . import InventoryBase
from . import Experience
2019-11-02 17:27:54 -05:00
from otp.avatar import DistributedAvatarAI
from otp.avatar import DistributedPlayerAI
from direct.distributed import DistributedSmoothNodeAI
from toontown.toonbase import ToontownGlobals
from toontown.quest import QuestRewardCounter
from toontown.quest import Quests
from toontown.toonbase import ToontownBattleGlobals
from toontown.battle import SuitBattleGlobals
from direct.task import Task
from toontown.catalog import CatalogItemList
from toontown.catalog import CatalogItem
from direct.showbase import PythonUtil
from direct.distributed.ClockDelta import *
from toontown.toonbase.ToontownGlobals import *
import types
from toontown.fishing import FishGlobals
from toontown.fishing import FishCollection
from toontown.fishing import FishTank
from .NPCToons import npcFriends, isZoneProtected
2019-11-02 17:27:54 -05:00
from toontown.coghq import CogDisguiseGlobals
import random
import re
from toontown.chat import ResistanceChat
from toontown.racing import RaceGlobals
from toontown.hood import ZoneUtil
from toontown.toon import NPCToons
from toontown.estate import FlowerCollection
from toontown.estate import FlowerBasket
from toontown.estate import GardenGlobals
from toontown.golf import GolfGlobals
from toontown.parties import PartyGlobals
from toontown.parties.PartyInfo import PartyInfoAI
from toontown.parties.InviteInfo import InviteInfoBase
from toontown.parties.PartyReplyInfo import PartyReplyInfoBase
from toontown.parties.PartyGlobals import InviteStatus
from toontown.toonbase import ToontownAccessAI
from toontown.toonbase import TTLocalizer
from toontown.catalog import CatalogAccessoryItem
from toontown.minigame import MinigameCreatorAI
from . import ModuleListAI
from functools import reduce
2019-11-02 17:27:54 -05:00
if simbase.wantPets:
from toontown.pets import PetLookerAI, PetObserve
else:
class PetLookerAI:
class PetLookerAI:
pass
if simbase.wantKarts:
from toontown.racing.KartDNA import *
class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLookerAI.PetLookerAI):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedToonAI')
maxCallsPerNPC = 100
partTypeIds = {ToontownGlobals.FT_FullSuit: (CogDisguiseGlobals.leftLegIndex,
CogDisguiseGlobals.rightLegIndex,
CogDisguiseGlobals.torsoIndex,
CogDisguiseGlobals.leftArmIndex,
CogDisguiseGlobals.rightArmIndex),
ToontownGlobals.FT_Leg: (CogDisguiseGlobals.leftLegIndex, CogDisguiseGlobals.rightLegIndex),
ToontownGlobals.FT_Arm: (CogDisguiseGlobals.leftArmIndex, CogDisguiseGlobals.rightArmIndex),
ToontownGlobals.FT_Torso: (CogDisguiseGlobals.torsoIndex,)}
lastFlagAvTime = globalClock.getFrameTime()
flagCounts = {}
pingedAvs = {}
WantTpTrack = simbase.config.GetBool('want-tptrack', False)
DbCheckPeriodPaid = simbase.config.GetInt('toon-db-check-period-paid', 10 * 60)
DbCheckPeriodUnpaid = simbase.config.GetInt('toon-db-check-period-unpaid', 1 * 60)
BanOnDbCheckFail = simbase.config.GetBool('want-ban-dbcheck', 0)
DbCheckAccountDateEnable = config.GetBool('account-blackout-enable', 1)
DbCheckAccountDateBegin = config.GetString('account-blackout-start', '2013-08-20 12:30:00')
DbCheckAccountDateDisconnect = config.GetBool('account-blackout-disconnect', 0)
WantOldGMNameBan = simbase.config.GetBool('want-old-gm-name-ban', 1)
def __init__(self, air):
DistributedPlayerAI.DistributedPlayerAI.__init__(self, air)
DistributedSmoothNodeAI.DistributedSmoothNodeAI.__init__(self, air)
if simbase.wantPets:
PetLookerAI.PetLookerAI.__init__(self)
self.air = air
self.dna = ToonDNA.ToonDNA()
self.inventory = None
self.fishCollection = None
self.fishTank = None
self.experience = None
self.quests = []
self.cogs = []
self.cogCounts = []
self.NPCFriendsDict = {}
self.clothesTopsList = []
self.clothesBottomsList = []
self.hatList = []
self.glassesList = []
self.backpackList = []
self.shoesList = []
self.hat = (0, 0, 0)
self.glasses = (0, 0, 0)
self.backpack = (0, 0, 0)
self.shoes = (0, 0, 0)
self.cogTypes = [0,
0,
0,
0]
self.cogLevel = [0,
0,
0,
0]
self.cogParts = [0,
0,
0,
0]
self.cogRadar = [0,
0,
0,
0]
self.cogIndex = -1
self.disguisePageFlag = 0
self.sosPageFlag = 0
self.buildingRadar = [0,
0,
0,
0]
self.fishingRod = 0
self.fishingTrophies = []
self.trackArray = []
self.emoteAccess = [0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0]
self.maxBankMoney = ToontownGlobals.DefaultMaxBankMoney
self.gardenSpecials = []
self.houseId = 0
self.posIndex = 0
self.savedCheesyEffect = ToontownGlobals.CENormal
self.savedCheesyHoodId = 0
self.savedCheesyExpireTime = 0
self.ghostMode = 0
self.immortalMode = 0
self.numPies = 0
self.pieType = 0
self._isGM = False
self._gmType = None
self.hpOwnedByBattle = 0
if simbase.wantPets:
self.petTrickPhrases = []
if simbase.wantBingo:
self.bingoCheat = False
self.customMessages = []
self.catalogNotify = ToontownGlobals.NoItems
self.mailboxNotify = ToontownGlobals.NoItems
self.catalogScheduleCurrentWeek = 0
self.catalogScheduleNextTime = 0
self.monthlyCatalog = CatalogItemList.CatalogItemList()
self.weeklyCatalog = CatalogItemList.CatalogItemList()
self.backCatalog = CatalogItemList.CatalogItemList()
self.onOrder = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.DeliveryDate)
self.onGiftOrder = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.DeliveryDate)
self.mailboxContents = CatalogItemList.CatalogItemList(store=CatalogItem.Customization)
self.awardMailboxContents = CatalogItemList.CatalogItemList(store=CatalogItem.Customization)
self.onAwardOrder = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.DeliveryDate)
self.kart = None
if simbase.wantKarts:
self.kartDNA = [-1] * getNumFields()
self.tickets = 200
self.allowSoloRace = False
self.allowRaceTimeout = True
self.setBattleId(0)
self.gardenStarted = False
self.flowerCollection = None
self.shovel = 0
self.shovelSkill = 0
self.wateringCan = 0
self.wateringCanSkill = 0
self.hatePets = 1
self.golfHistory = None
self.golfHoleBest = None
self.golfCourseBest = None
self.unlimitedSwing = False
self.previousAccess = None
self.numMailItems = 0
self.simpleMailNotify = ToontownGlobals.NoItems
self.inviteMailNotify = ToontownGlobals.NoItems
self.invites = []
self.hostedParties = []
self.partiesInvitedTo = []
self.partyReplyInfoBases = []
self.modulelist = ModuleListAI.ModuleList()
self._dbCheckDoLater = None
return
def generate(self):
DistributedPlayerAI.DistributedPlayerAI.generate(self)
DistributedSmoothNodeAI.DistributedSmoothNodeAI.generate(self)
def announceGenerate(self):
DistributedPlayerAI.DistributedPlayerAI.announceGenerate(self)
DistributedSmoothNodeAI.DistributedSmoothNodeAI.announceGenerate(self)
if self.isPlayerControlled():
self._doDbCheck()
if self.WantOldGMNameBan:
self._checkOldGMName()
messenger.send('avatarEntered', [self])
self.sendUpdate('setDefaultShard', [self.air.districtId])
2019-11-02 17:27:54 -05:00
if hasattr(self, 'gameAccess') and self.gameAccess != 2:
if self.hat[0] != 0:
self.replaceItemInAccessoriesList(ToonDNA.HAT, 0, 0, 0, self.hat[0], self.hat[1], self.hat[2])
self.b_setHatList(self.hatList)
self.b_setHat(0, 0, 0)
if self.glasses[0] != 0:
self.replaceItemInAccessoriesList(ToonDNA.GLASSES, 0, 0, 0, self.glasses[0], self.glasses[1], self.glasses[2])
self.b_setGlassesList(self.glassesList)
self.b_setGlasses(0, 0, 0)
if self.backpack[0] != 0:
self.replaceItemInAccessoriesList(ToonDNA.BACKPACK, 0, 0, 0, self.backpack[0], self.backpack[1], self.backpack[2])
self.b_setBackpackList(self.backpackList)
self.b_setBackpack(0, 0, 0)
if self.shoes[0] != 0:
self.replaceItemInAccessoriesList(ToonDNA.SHOES, 0, 0, 0, self.shoes[0], self.shoes[1], self.shoes[2])
self.b_setShoesList(self.shoesList)
self.b_setShoes(0, 0, 0)
self.startPing()
def setLocation(self, parentId, zoneId):
DistributedPlayerAI.DistributedPlayerAI.setLocation(self, parentId, zoneId)
if self.isPlayerControlled():
if 100 <= zoneId < ToontownGlobals.DynamicZonesBegin:
hood = ZoneUtil.getHoodId(zoneId)
self.sendUpdate('setLastHood', [hood])
self.setDefaultZone(hood)
self.sendUpdate('setDefaultZone', [hood])
2019-12-01 21:54:47 -06:00
canonicalZoneId = ZoneUtil.getCanonicalZoneId(zoneId)
canonicalHood = ZoneUtil.getHoodId(canonicalZoneId)
2019-12-01 21:54:47 -06:00
hoodsVisited = list(self.getHoodsVisited())
if canonicalHood not in hoodsVisited:
hoodsVisited.append(canonicalHood)
self.b_setHoodsVisited(hoodsVisited)
if canonicalZoneId == ToontownGlobals.GoofySpeedway:
teleportAccess = self.getTeleportAccess()
if ToontownGlobals.GoofySpeedway not in teleportAccess:
teleportAccess.append(ToontownGlobals.GoofySpeedway)
self.b_setTeleportAccess(teleportAccess)
2019-11-02 17:27:54 -05:00
def _doDbCheck(self, task = None):
self._dbCheckDoLater = None
self.air.sendQueryToonMaxHp(self.doId, self._handleDbCheckResult)
return Task.done
def _doDbCheckBan(self, desc):
if self.BanOnDbCheckFail:
self.ban(desc)
else:
self.air.writeServerEvent('suspicious', self.doId, desc)
self.requestDelete()
def _handleDbCheckResult(self, result):
if not self.isGenerated():
return
if result is None:
self._doDbCheckBan('toon %s not present in the database' % self.doId)
else:
self.air.securityMgr.getAccountId(self.doId, self._handleDbCheckGetAccountResult)
return
def _handleDbCheckGetAccountResult(self, accountId):
if not self.isGenerated():
return
if accountId is None:
self._renewDoLater()
else:
self.air.sendFieldQuery('AccountAI', 'ACCOUNT_AV_SET', accountId, self._handleDbCheckGetAvSetResult)
if DistributedToonAI.DbCheckAccountDateEnable:
self.air.sendFieldQuery('AccountAI', 'CREATED', accountId, self._handleDbCheckAccountCreatedResult)
return
def _handleDbCheckGetAvSetResult(self, avSet):
if not self.isGenerated():
return
renewDoLater = True
if avSet is None:
self._doDbCheckBan("toon %s's account has no ACCOUNT_AV_SET in the DB" % self.doId)
renewDoLater = False
elif self.doId not in avSet:
self._doDbCheckBan('toon %s not in ACCOUNT_AV_SET in the DB' % self.doId)
renewDoLater = False
self._renewDoLater(renewDoLater)
return
def _handleDbCheckAccountCreatedResult(self, created):
if not self.isGenerated():
return
if created is None:
self._doDbCheckBan("toon %s's account has no CREATED in the DB" % self.doId)
elif created >= DistributedToonAI.DbCheckAccountDateBegin:
msg = 'account created during invalid period (toon) %s' % created
if DistributedToonAI.DbCheckAccountDateDisconnect:
self.disconnect()
msg += ', disconnecting'
self.air.writeServerEvent('account', self.doId, msg)
self.notify.warning('%s ' % self.doId + msg)
return
def _renewDoLater(self, renew = True):
if renew:
delay = self.DbCheckPeriodUnpaid
if self.gameAccess == OTPGlobals.AccessFull:
delay = self.DbCheckPeriodPaid
self._dbCheckDoLater = taskMgr.doMethodLater(delay, self._doDbCheck, 'dbCheck-%s' % self.doId)
def sendDeleteEvent(self):
if simbase.wantPets:
isInEstate = self.isInEstate()
wasInEstate = self.wasInEstate()
if isInEstate or wasInEstate:
PetObserve.send(self.estateZones, PetObserve.PetActionObserve(PetObserve.Actions.LOGOUT, self.doId))
if wasInEstate:
self.cleanupEstateData()
DistributedAvatarAI.DistributedAvatarAI.sendDeleteEvent(self)
def delete(self):
self.notify.debug('----Deleting DistributedToonAI %d ' % self.doId)
if self._dbCheckDoLater:
taskMgr.remove(self._dbCheckDoLater)
self._dbCheckDoLater = None
if self.isPlayerControlled():
messenger.send('avatarExited', [self])
if simbase.wantPets:
if self.isInEstate():
print('ToonAI - Exit estate toonId:%s' % self.doId)
2019-11-02 17:27:54 -05:00
self.exitEstate()
if self.zoneId != ToontownGlobals.QuietZone:
self.announceZoneChange(ToontownGlobals.QuietZone, self.zoneId)
taskName = self.uniqueName('cheesy-expires')
taskMgr.remove(taskName)
taskName = self.uniqueName('next-catalog')
taskMgr.remove(taskName)
taskName = self.uniqueName('next-delivery')
taskMgr.remove(taskName)
taskName = self.uniqueName('next-award-delivery')
taskMgr.remove(taskName)
taskName = 'next-bothDelivery-%s' % self.doId
taskMgr.remove(taskName)
self.stopToonUp()
del self.dna
if self.inventory:
self.inventory.unload()
del self.inventory
del self.experience
if simbase.wantPets:
PetLookerAI.PetLookerAI.destroy(self)
del self.kart
self.cleanupPing()
self.stopPing()
self._sendExitServerEvent()
DistributedSmoothNodeAI.DistributedSmoothNodeAI.delete(self)
DistributedPlayerAI.DistributedPlayerAI.delete(self)
return
def deleteDummy(self):
self.notify.debug('----deleteDummy DistributedToonAI %d ' % self.doId)
if self.inventory:
self.inventory.unload()
del self.inventory
self.experience = None
taskName = self.uniqueName('next-catalog')
taskMgr.remove(taskName)
return
def ban(self, comment):
simbase.air.banManager.ban(self.doId, self.DISLid, comment)
def disconnect(self):
self.requestDelete()
def patchDelete(self):
del self.dna
if self.inventory:
self.inventory.unload()
del self.inventory
del self.experience
if simbase.wantPets:
PetLookerAI.PetLookerAI.destroy(self)
self.doNotDeallocateChannel = True
self.zoneId = None
DistributedSmoothNodeAI.DistributedSmoothNodeAI.delete(self)
DistributedPlayerAI.DistributedPlayerAI.delete(self)
return
def handleLogicalZoneChange(self, newZoneId, oldZoneId):
DistributedAvatarAI.DistributedAvatarAI.handleLogicalZoneChange(self, newZoneId, oldZoneId)
if self.isPlayerControlled() and self.WantTpTrack:
messenger.send(self.staticGetLogicalZoneChangeAllEvent(), [newZoneId, oldZoneId, self])
if self.cogIndex != -1 and not ToontownAccessAI.canWearSuit(self.doId, newZoneId):
if simbase.config.GetBool('cogsuit-hack-prevent', False):
self.b_setCogIndex(-1)
if not simbase.air.cogSuitMessageSent:
self.notify.warning('%s handleLogicalZoneChange as a suit: %s' % (self.doId, self.cogIndex))
self.air.writeServerEvent('suspicious', self.doId, 'Toon wearing a cog suit with index: %s in a zone they are not allowed to in. Zone: %s' % (self.cogIndex, newZoneId))
simbase.air.cogSuitMessageSent = True
if simbase.config.GetBool('want-ban-wrong-suit-place', False):
commentStr = 'Toon %s wearing a suit in a zone they are not allowed to in. Zone: %s' % (self.doId, newZoneId)
dislId = self.DISLid
simbase.air.banManager.ban(self.doId, dislId, commentStr)
def announceZoneChange(self, newZoneId, oldZoneId):
from toontown.pets import PetObserve
2019-12-05 20:38:58 -06:00
self.air.welcomeValleyManager.toonSetZone(self.doId, newZoneId)
2019-11-02 17:27:54 -05:00
broadcastZones = [oldZoneId, newZoneId]
if self.isInEstate() or self.wasInEstate():
broadcastZones = union(broadcastZones, self.estateZones)
PetObserve.send(broadcastZones, PetObserve.PetActionObserve(PetObserve.Actions.CHANGE_ZONE, self.doId, (oldZoneId, newZoneId)))
def checkAccessorySanity(self, accessoryType, idx, textureIdx, colorIdx):
if idx == 0 and textureIdx == 0 and colorIdx == 0:
return 1
if accessoryType == ToonDNA.HAT:
stylesDict = ToonDNA.HatStyles
accessoryTypeStr = 'Hat'
elif accessoryType == ToonDNA.GLASSES:
stylesDict = ToonDNA.GlassesStyles
accessoryTypeStr = 'Glasses'
elif accessoryType == ToonDNA.BACKPACK:
stylesDict = ToonDNA.BackpackStyles
accessoryTypeStr = 'Backpack'
elif accessoryType == ToonDNA.SHOES:
stylesDict = ToonDNA.ShoesStyles
accessoryTypeStr = 'Shoes'
else:
return 0
try:
styleStr = list(stylesDict.keys())[list(stylesDict.values()).index([idx, textureIdx, colorIdx])]
2019-11-02 17:27:54 -05:00
accessoryItemId = 0
for itemId in list(CatalogAccessoryItem.AccessoryTypes.keys()):
2019-11-02 17:27:54 -05:00
if styleStr == CatalogAccessoryItem.AccessoryTypes[itemId][CatalogAccessoryItem.ATString]:
accessoryItemId = itemId
break
if accessoryItemId == 0:
self.air.writeServerEvent('suspicious', self.doId, 'Toon tried to wear invalid %s %d %d %d' % (accessoryTypeStr,
idx,
textureIdx,
colorIdx))
return 0
if not simbase.config.GetBool('want-check-accessory-sanity', False):
return 1
accessoryItem = CatalogAccessoryItem.CatalogAccessoryItem(accessoryItemId)
result = self.air.catalogManager.isItemReleased(accessoryItem)
if result == 0:
self.air.writeServerEvent('suspicious', self.doId, 'Toon wore unreleased accessoryItem %d' % accessoryItemId)
return result
except:
self.air.writeServerEvent('suspicious', self.doId, 'Toon tried to wear invalid %s %d %d %d' % (accessoryTypeStr,
idx,
textureIdx,
colorIdx))
return 0
def b_setHat(self, idx, textureIdx, colorIdx):
self.d_setHat(idx, textureIdx, colorIdx)
self.setHat(idx, textureIdx, colorIdx)
def d_setHat(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.HAT, idx, textureIdx, colorIdx):
pass
self.sendUpdate('setHat', [idx, textureIdx, colorIdx])
def setHat(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.HAT, idx, textureIdx, colorIdx):
pass
self.hat = (idx, textureIdx, colorIdx)
def getHat(self):
return self.hat
def b_setGlasses(self, idx, textureIdx, colorIdx):
self.d_setGlasses(idx, textureIdx, colorIdx)
self.setGlasses(idx, textureIdx, colorIdx)
def d_setGlasses(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.GLASSES, idx, textureIdx, colorIdx):
pass
self.sendUpdate('setGlasses', [idx, textureIdx, colorIdx])
def setGlasses(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.GLASSES, idx, textureIdx, colorIdx):
pass
self.glasses = (idx, textureIdx, colorIdx)
def getGlasses(self):
return self.glasses
def b_setBackpack(self, idx, textureIdx, colorIdx):
self.d_setBackpack(idx, textureIdx, colorIdx)
self.setBackpack(idx, textureIdx, colorIdx)
def d_setBackpack(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.BACKPACK, idx, textureIdx, colorIdx):
pass
self.sendUpdate('setBackpack', [idx, textureIdx, colorIdx])
def setBackpack(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.BACKPACK, idx, textureIdx, colorIdx):
pass
self.backpack = (idx, textureIdx, colorIdx)
def getBackpack(self):
return self.backpack
def b_setShoes(self, idx, textureIdx, colorIdx):
self.d_setShoes(idx, textureIdx, colorIdx)
self.setShoes(idx, textureIdx, colorIdx)
def d_setShoes(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.SHOES, idx, textureIdx, colorIdx):
pass
self.sendUpdate('setShoes', [idx, textureIdx, colorIdx])
def setShoes(self, idx, textureIdx, colorIdx):
if not self.checkAccessorySanity(ToonDNA.SHOES, idx, textureIdx, colorIdx):
pass
self.shoes = (idx, textureIdx, colorIdx)
def getShoes(self):
return self.shoes
def b_setDNAString(self, string):
self.d_setDNAString(string)
self.setDNAString(string)
def d_setDNAString(self, string):
self.sendUpdate('setDNAString', [string])
def setDNAString(self, string):
self.dna.makeFromNetString(string)
if simbase.config.GetBool('adjust-dna', True) and self.verifyDNA() == False:
logStr = 'AvatarHackWarning! invalid dna colors for %s old: %s new: %s' % (self.doId, str(ToonDNA.ToonDNA(string).asTuple()), str(self.dna.asTuple()))
self.notify.warning(logStr)
self.air.writeServerEvent('suspicious', self.doId, logStr)
def verifyDNA(self):
changed = False
if self.isPlayerControlled():
allowedColors = []
if self.dna.gender == 'm':
allowedColors = ToonDNA.defaultBoyColorList + [26]
else:
allowedColors = ToonDNA.defaultGirlColorList + [26]
if self.dna.legColor not in allowedColors:
self.dna.legColor = allowedColors[0]
changed = True
if self.dna.armColor not in allowedColors:
self.dna.armColor = allowedColors[0]
changed = True
if self.dna.headColor not in allowedColors:
self.dna.headColor = allowedColors[0]
changed = True
if changed:
self.d_setDNAString(self.dna.makeNetString())
return not changed
def getDNAString(self):
return self.dna.makeNetString()
def getStyle(self):
return self.dna
def b_setExperience(self, experience):
self.d_setExperience(experience)
self.setExperience(experience)
def d_setExperience(self, experience):
self.sendUpdate('setExperience', [experience])
def setExperience(self, experience):
self.experience = Experience.Experience(experience, self)
def getExperience(self):
return self.experience.makeNetString()
def b_setInventory(self, inventory):
self.setInventory(inventory)
self.d_setInventory(self.getInventory())
def d_setInventory(self, inventory):
self.sendUpdate('setInventory', [inventory])
def setInventory(self, inventoryNetString):
if self.inventory:
self.inventory.updateInvString(inventoryNetString)
else:
self.inventory = InventoryBase.InventoryBase(self, inventoryNetString)
emptyInv = InventoryBase.InventoryBase(self)
emptyString = emptyInv.makeNetString()
lengthMatch = len(inventoryNetString) - len(emptyString)
if lengthMatch != 0:
if len(inventoryNetString) == 42:
oldTracks = 7
oldLevels = 6
elif len(inventoryNetString) == 49:
oldTracks = 7
oldLevels = 7
else:
oldTracks = 0
oldLevels = 0
if oldTracks == 0 and oldLevels == 0:
self.notify.warning('reseting invalid inventory to MAX on toon: %s' % self.doId)
self.inventory.zeroInv()
self.inventory.maxOutInv(1, 1)
else:
newInventory = InventoryBase.InventoryBase(self)
oldList = emptyInv.makeFromNetStringForceSize(inventoryNetString, oldTracks, oldLevels)
for indexTrack in range(0, oldTracks):
for indexGag in range(0, oldLevels):
newInventory.addItems(indexTrack, indexGag, oldList[indexTrack][indexGag])
self.inventory.unload()
self.inventory = newInventory
self.d_setInventory(self.getInventory())
def getInventory(self):
return self.inventory.makeNetString()
def doRestock(self, noUber = 1, noPaid = 1):
self.inventory.zeroInv()
self.inventory.maxOutInv(noUber, noPaid)
self.d_setInventory(self.inventory.makeNetString())
def setDefaultShard(self, shard):
self.defaultShard = shard
self.notify.debug('setting default shard to %s' % shard)
def getDefaultShard(self):
return self.defaultShard
def setDefaultZone(self, zone):
self.defaultZone = zone
self.notify.debug('setting default zone to %s' % zone)
def getDefaultZone(self):
return self.defaultZone
def setShtickerBook(self, string):
self.notify.debug('setting shticker book to %s' % string)
def getShtickerBook(self):
return ''
def d_setFriendsList(self, friendsList):
self.sendUpdate('setFriendsList', [friendsList])
return None
def setFriendsList(self, friendsList):
self.notify.debug('setting friends list to %s' % self.friendsList)
self.friendsList = friendsList
if friendsList:
friendId = friendsList[-1]
otherAv = self.air.doId2do.get(friendId)
self.air.questManager.toonMadeFriend(self, otherAv)
def getFriendsList(self):
return self.friendsList
def extendFriendsList(self, friendId, friendCode):
for i in range(len(self.friendsList)):
friendPair = self.friendsList[i]
if friendPair[0] == friendId:
self.friendsList[i] = (friendId, friendCode)
return
self.friendsList.append((friendId, friendCode))
def d_setMaxNPCFriends(self, max):
self.sendUpdate('setMaxNPCFriends', [max])
def setMaxNPCFriends(self, max):
if max & 32768:
self.b_setSosPageFlag(1)
max &= 32767
configMax = simbase.config.GetInt('max-sos-cards', 16)
if configMax != max:
if self.sosPageFlag == 0:
self.b_setMaxNPCFriends(configMax)
else:
self.b_setMaxNPCFriends(configMax | 32768)
else:
self.maxNPCFriends = max
if self.maxNPCFriends != 8 and self.maxNPCFriends != 16:
self.notify.warning('Wrong max SOS cards %s, %d' % (self.maxNPCFriends, self.doId))
def b_setMaxNPCFriends(self, max):
self.setMaxNPCFriends(max)
self.d_setMaxNPCFriends(max)
def getMaxNPCFriends(self):
return self.maxNPCFriends
def getBattleId(self):
if self.battleId >= 0:
return self.battleId
else:
return 0
def b_setBattleId(self, battleId):
self.setBattleId(battleId)
self.d_setBattleId(battleId)
def d_setBattleId(self, battleId):
if self.battleId >= 0:
self.sendUpdate('setBattleId', [battleId])
else:
self.sendUpdate('setBattleId', [0])
def setBattleId(self, battleId):
self.battleId = battleId
def d_setNPCFriendsDict(self, NPCFriendsDict):
NPCFriendsList = []
for friend in list(NPCFriendsDict.keys()):
2019-11-02 17:27:54 -05:00
NPCFriendsList.append((friend, NPCFriendsDict[friend]))
self.sendUpdate('setNPCFriendsDict', [NPCFriendsList])
return None
def setNPCFriendsDict(self, NPCFriendsList):
self.NPCFriendsDict = {}
for friendPair in NPCFriendsList:
self.NPCFriendsDict[friendPair[0]] = friendPair[1]
self.notify.debug('setting NPC friends dict to %s' % self.NPCFriendsDict)
def getNPCFriendsDict(self):
return self.NPCFriendsDict
def b_setNPCFriendsDict(self, NPCFriendsList):
self.setNPCFriendsDict(NPCFriendsList)
self.d_setNPCFriendsDict(self.NPCFriendsDict)
def resetNPCFriendsDict(self):
self.b_setNPCFriendsDict([])
def attemptAddNPCFriend(self, npcFriend, numCalls = 1):
if numCalls <= 0:
self.notify.warning('invalid numCalls: %d' % numCalls)
return 0
if npcFriend in self.NPCFriendsDict:
2019-11-02 17:27:54 -05:00
self.NPCFriendsDict[npcFriend] += numCalls
elif npcFriend in npcFriends:
if len(list(self.NPCFriendsDict.keys())) >= self.maxNPCFriends:
2019-11-02 17:27:54 -05:00
return 0
self.NPCFriendsDict[npcFriend] = numCalls
else:
self.notify.warning('invalid NPC: %d' % npcFriend)
return 0
if self.NPCFriendsDict[npcFriend] > self.maxCallsPerNPC:
self.NPCFriendsDict[npcFriend] = self.maxCallsPerNPC
self.d_setNPCFriendsDict(self.NPCFriendsDict)
if self.sosPageFlag == 0:
self.b_setMaxNPCFriends(self.maxNPCFriends | 32768)
return 1
def attemptSubtractNPCFriend(self, npcFriend):
if npcFriend not in self.NPCFriendsDict:
2019-11-02 17:27:54 -05:00
self.notify.warning('attemptSubtractNPCFriend: invalid NPC %s' % npcFriend)
return 0
if hasattr(self, 'autoRestockSOS') and self.autoRestockSOS:
cost = 0
else:
cost = 1
self.NPCFriendsDict[npcFriend] -= cost
if self.NPCFriendsDict[npcFriend] <= 0:
del self.NPCFriendsDict[npcFriend]
self.d_setNPCFriendsDict(self.NPCFriendsDict)
return 1
def restockAllNPCFriends(self):
desiredNpcFriends = [2001,
2011,
3112,
4119,
1116,
3137,
3135]
self.resetNPCFriendsDict()
for npcId in desiredNpcFriends:
self.attemptAddNPCFriend(npcId, 1)
def d_setMaxAccessories(self, max):
self.sendUpdate('setMaxAccessories', [self.maxAccessories])
def setMaxAccessories(self, max):
self.maxAccessories = max
def b_setMaxAccessories(self, max):
self.setMaxAccessories(max)
self.d_setMaxAccessories(max)
def getMaxAccessories(self):
return self.maxAccessories
def isTrunkFull(self, extraAccessories = 0):
numAccessories = (len(self.hatList) + len(self.glassesList) + len(self.backpackList) + len(self.shoesList)) / 3
return numAccessories + extraAccessories >= self.maxAccessories
def d_setHatList(self, clothesList):
self.sendUpdate('setHatList', [clothesList])
return None
def setHatList(self, clothesList):
self.hatList = clothesList
def b_setHatList(self, clothesList):
self.setHatList(clothesList)
self.d_setHatList(clothesList)
def getHatList(self):
return self.hatList
def d_setGlassesList(self, clothesList):
self.sendUpdate('setGlassesList', [clothesList])
return None
def setGlassesList(self, clothesList):
self.glassesList = clothesList
def b_setGlassesList(self, clothesList):
self.setGlassesList(clothesList)
self.d_setGlassesList(clothesList)
def getGlassesList(self):
return self.glassesList
def d_setBackpackList(self, clothesList):
self.sendUpdate('setBackpackList', [clothesList])
return None
def setBackpackList(self, clothesList):
self.backpackList = clothesList
def b_setBackpackList(self, clothesList):
self.setBackpackList(clothesList)
self.d_setBackpackList(clothesList)
def getBackpackList(self):
return self.backpackList
def d_setShoesList(self, clothesList):
self.sendUpdate('setShoesList', [clothesList])
return None
def setShoesList(self, clothesList):
self.shoesList = clothesList
def b_setShoesList(self, clothesList):
self.setShoesList(clothesList)
self.d_setShoesList(clothesList)
def getShoesList(self):
return self.shoesList
def addToAccessoriesList(self, accessoryType, geomIdx, texIdx, colorIdx):
if self.isTrunkFull():
return 0
if accessoryType == ToonDNA.HAT:
itemList = self.hatList
elif accessoryType == ToonDNA.GLASSES:
itemList = self.glassesList
elif accessoryType == ToonDNA.BACKPACK:
itemList = self.backpackList
elif accessoryType == ToonDNA.SHOES:
itemList = self.shoesList
else:
return 0
index = 0
for i in range(0, len(itemList), 3):
if itemList[i] == geomIdx and itemList[i + 1] == texIdx and itemList[i + 2] == colorIdx:
return 0
if accessoryType == ToonDNA.HAT:
self.hatList.append(geomIdx)
self.hatList.append(texIdx)
self.hatList.append(colorIdx)
elif accessoryType == ToonDNA.GLASSES:
self.glassesList.append(geomIdx)
self.glassesList.append(texIdx)
self.glassesList.append(colorIdx)
elif accessoryType == ToonDNA.BACKPACK:
self.backpackList.append(geomIdx)
self.backpackList.append(texIdx)
self.backpackList.append(colorIdx)
elif accessoryType == ToonDNA.SHOES:
self.shoesList.append(geomIdx)
self.shoesList.append(texIdx)
self.shoesList.append(colorIdx)
return 1
def replaceItemInAccessoriesList(self, accessoryType, geomIdxA, texIdxA, colorIdxA, geomIdxB, texIdxB, colorIdxB):
if accessoryType == ToonDNA.HAT:
itemList = self.hatList
elif accessoryType == ToonDNA.GLASSES:
itemList = self.glassesList
elif accessoryType == ToonDNA.BACKPACK:
itemList = self.backpackList
elif accessoryType == ToonDNA.SHOES:
itemList = self.shoesList
else:
return 0
index = 0
for i in range(0, len(itemList), 3):
if itemList[i] == geomIdxA and itemList[i + 1] == texIdxA and itemList[i + 2] == colorIdxA:
if accessoryType == ToonDNA.HAT:
self.hatList[i] = geomIdxB
self.hatList[i + 1] = texIdxB
self.hatList[i + 2] = colorIdxB
elif accessoryType == ToonDNA.GLASSES:
self.glassesList[i] = geomIdxB
self.glassesList[i + 1] = texIdxB
self.glassesList[i + 2] = colorIdxB
elif accessoryType == ToonDNA.BACKPACK:
self.backpackList[i] = geomIdxB
self.backpackList[i + 1] = texIdxB
self.backpackList[i + 2] = colorIdxB
else:
self.shoesList[i] = geomIdxB
self.shoesList[i + 1] = texIdxB
self.shoesList[i + 2] = colorIdxB
return 1
return 0
def hasAccessory(self, accessoryType, geomIdx, texIdx, colorIdx):
if accessoryType == ToonDNA.HAT:
itemList = self.hatList
cur = self.hat
elif accessoryType == ToonDNA.GLASSES:
itemList = self.glassesList
cur = self.glasses
elif accessoryType == ToonDNA.BACKPACK:
itemList = self.backpackList
cur = self.backpack
elif accessoryType == ToonDNA.SHOES:
itemList = self.shoesList
cur = self.shoes
else:
raise 'invalid accessory type %s' % accessoryType
if cur == (geomIdx, texIdx, colorIdx):
return True
for i in range(0, len(itemList), 3):
2019-11-02 17:27:54 -05:00
if itemList[i] == geomIdx and itemList[i + 1] == texIdx and itemList[i + 2] == colorIdx:
return True
return False
def isValidAccessorySetting(self, accessoryType, geomIdx, texIdx, colorIdx):
if not geomIdx and not texIdx and not colorIdx:
return True
return self.hasAccessory(accessoryType, geomIdx, texIdx, colorIdx)
def removeItemInAccessoriesList(self, accessoryType, geomIdx, texIdx, colorIdx):
if accessoryType == ToonDNA.HAT:
itemList = self.hatList
elif accessoryType == ToonDNA.GLASSES:
itemList = self.glassesList
elif accessoryType == ToonDNA.BACKPACK:
itemList = self.backpackList
elif accessoryType == ToonDNA.SHOES:
itemList = self.shoesList
else:
return 0
listLen = len(itemList)
if listLen < 3:
self.notify.warning('Accessory list is not long enough to delete anything')
return 0
index = 0
for i in range(0, len(itemList), 3):
if itemList[i] == geomIdx and itemList[i + 1] == texIdx and itemList[i + 2] == colorIdx:
itemList = itemList[0:i] + itemList[i + 3:listLen]
if accessoryType == ToonDNA.HAT:
self.hatList = itemList[:]
styles = ToonDNA.HatStyles
descDict = TTLocalizer.HatStylesDescriptions
elif accessoryType == ToonDNA.GLASSES:
self.glassesList = itemList[:]
styles = ToonDNA.GlassesStyles
descDict = TTLocalizer.GlassesStylesDescriptions
elif accessoryType == ToonDNA.BACKPACK:
self.backpackList = itemList[:]
styles = ToonDNA.BackpackStyles
descDict = TTLocalizer.BackpackStylesDescriptions
elif accessoryType == ToonDNA.SHOES:
self.shoesList = itemList[:]
styles = ToonDNA.ShoesStyles
descDict = TTLocalizer.ShoesStylesDescriptions
styleName = 'none'
for style in list(styles.items()):
2019-11-02 17:27:54 -05:00
if style[1] == [geomIdx, texIdx, colorIdx]:
styleName = style[0]
break
if styleName == 'none' or styleName not in descDict:
2019-11-02 17:27:54 -05:00
self.air.writeServerEvent('suspicious', self.doId, ' tried to remove wrong accessory code %d %d %d' % (geomIdx, texIdx, colorIdx))
else:
self.air.writeServerEvent('accessory', self.doId, ' removed accessory %s' % descDict[styleName])
return 1
return 0
def d_setMaxClothes(self, max):
self.sendUpdate('setMaxClothes', [self.maxClothes])
def setMaxClothes(self, max):
self.maxClothes = max
def b_setMaxClothes(self, max):
self.setMaxClothes(max)
self.d_setMaxClothes(max)
def getMaxClothes(self):
return self.maxClothes
def isClosetFull(self, extraClothes = 0):
numClothes = len(self.clothesTopsList) / 4 + len(self.clothesBottomsList) / 2
return numClothes + extraClothes >= self.maxClothes
def d_setClothesTopsList(self, clothesList):
self.sendUpdate('setClothesTopsList', [clothesList])
return None
def setClothesTopsList(self, clothesList):
self.clothesTopsList = clothesList
def b_setClothesTopsList(self, clothesList):
self.setClothesTopsList(clothesList)
self.d_setClothesTopsList(clothesList)
def getClothesTopsList(self):
return self.clothesTopsList
def addToClothesTopsList(self, topTex, topTexColor, sleeveTex, sleeveTexColor):
if self.isClosetFull():
return 0
index = 0
for i in range(0, len(self.clothesTopsList), 4):
if self.clothesTopsList[i] == topTex and self.clothesTopsList[i + 1] == topTexColor and self.clothesTopsList[i + 2] == sleeveTex and self.clothesTopsList[i + 3] == sleeveTexColor:
return 0
self.clothesTopsList.append(topTex)
self.clothesTopsList.append(topTexColor)
self.clothesTopsList.append(sleeveTex)
self.clothesTopsList.append(sleeveTexColor)
return 1
def replaceItemInClothesTopsList(self, topTexA, topTexColorA, sleeveTexA, sleeveTexColorA, topTexB, topTexColorB, sleeveTexB, sleeveTexColorB):
index = 0
for i in range(0, len(self.clothesTopsList), 4):
if self.clothesTopsList[i] == topTexA and self.clothesTopsList[i + 1] == topTexColorA and self.clothesTopsList[i + 2] == sleeveTexA and self.clothesTopsList[i + 3] == sleeveTexColorA:
self.clothesTopsList[i] = topTexB
self.clothesTopsList[i + 1] = topTexColorB
self.clothesTopsList[i + 2] = sleeveTexB
self.clothesTopsList[i + 3] = sleeveTexColorB
return 1
return 0
def removeItemInClothesTopsList(self, topTex, topTexColor, sleeveTex, sleeveTexColor):
listLen = len(self.clothesTopsList)
if listLen < 4:
self.notify.warning('Clothes top list is not long enough to delete anything')
return 0
index = 0
for i in range(0, listLen, 4):
if self.clothesTopsList[i] == topTex and self.clothesTopsList[i + 1] == topTexColor and self.clothesTopsList[i + 2] == sleeveTex and self.clothesTopsList[i + 3] == sleeveTexColor:
self.clothesTopsList = self.clothesTopsList[0:i] + self.clothesTopsList[i + 4:listLen]
return 1
return 0
def d_setClothesBottomsList(self, clothesList):
self.sendUpdate('setClothesBottomsList', [clothesList])
return None
def setClothesBottomsList(self, clothesList):
self.clothesBottomsList = clothesList
def b_setClothesBottomsList(self, clothesList):
self.setClothesBottomsList(clothesList)
self.d_setClothesBottomsList(clothesList)
def getClothesBottomsList(self):
return self.clothesBottomsList
def addToClothesBottomsList(self, botTex, botTexColor):
if self.isClosetFull():
self.notify.warning('clothes bottoms list is full')
return 0
index = 0
for i in range(0, len(self.clothesBottomsList), 2):
if self.clothesBottomsList[i] == botTex and self.clothesBottomsList[i + 1] == botTexColor:
return 0
self.clothesBottomsList.append(botTex)
self.clothesBottomsList.append(botTexColor)
return 1
def replaceItemInClothesBottomsList(self, botTexA, botTexColorA, botTexB, botTexColorB):
index = 0
for i in range(0, len(self.clothesBottomsList), 2):
if self.clothesBottomsList[i] == botTexA and self.clothesBottomsList[i + 1] == botTexColorA:
self.clothesBottomsList[i] = botTexB
self.clothesBottomsList[i + 1] = botTexColorB
return 1
return 0
def removeItemInClothesBottomsList(self, botTex, botTexColor):
listLen = len(self.clothesBottomsList)
if listLen < 2:
self.notify.warning('Clothes bottoms list is not long enough to delete anything')
return 0
index = 0
for i in range(0, len(self.clothesBottomsList), 2):
if self.clothesBottomsList[i] == botTex and self.clothesBottomsList[i + 1] == botTexColor:
self.clothesBottomsList = self.clothesBottomsList[0:i] + self.clothesBottomsList[i + 2:listLen]
return 1
return 0
def d_catalogGenClothes(self):
self.sendUpdate('catalogGenClothes', [self.doId])
def d_catalogGenAccessories(self):
self.sendUpdate('catalogGenAccessories', [self.doId])
def takeDamage(self, hpLost, quietly = 0, sendTotal = 1):
if not self.immortalMode:
if not quietly:
self.sendUpdate('takeDamage', [hpLost])
if hpLost > 0 and self.hp > 0:
self.hp -= hpLost
if self.hp <= 0:
self.hp = -1
messenger.send(self.getGoneSadMessage())
if not self.hpOwnedByBattle:
self.hp = min(self.hp, self.maxHp)
if sendTotal:
self.d_setHp(self.hp)
@staticmethod
def getGoneSadMessageForAvId(avId):
return 'goneSad-%s' % avId
def getGoneSadMessage(self):
return self.getGoneSadMessageForAvId(self.doId)
def setHp(self, hp):
DistributedPlayerAI.DistributedPlayerAI.setHp(self, hp)
if hp <= 0:
messenger.send(self.getGoneSadMessage())
def b_setTutorialAck(self, tutorialAck):
self.d_setTutorialAck(tutorialAck)
self.setTutorialAck(tutorialAck)
def d_setTutorialAck(self, tutorialAck):
self.sendUpdate('setTutorialAck', [tutorialAck])
def setTutorialAck(self, tutorialAck):
self.tutorialAck = tutorialAck
def getTutorialAck(self):
return self.tutorialAck
def d_setEarnedExperience(self, earnedExp):
self.sendUpdate('setEarnedExperience', [earnedExp])
def setInterface(self, string):
self.notify.debug('setting interface to %s' % string)
def getInterface(self):
return ''
def setZonesVisited(self, hoods):
self.safeZonesVisited = hoods
self.notify.debug('setting safe zone list to %s' % self.safeZonesVisited)
def getZonesVisited(self):
return self.safeZonesVisited
def setHoodsVisited(self, hoods):
self.hoodsVisited = hoods
self.notify.debug('setting hood zone list to %s' % self.hoodsVisited)
def getHoodsVisited(self):
return self.hoodsVisited
def setLastHood(self, hood):
self.lastHood = hood
def getLastHood(self):
return self.lastHood
def b_setAnimState(self, animName, animMultiplier):
self.setAnimState(animName, animMultiplier)
self.d_setAnimState(animName, animMultiplier)
def d_setAnimState(self, animName, animMultiplier):
timestamp = globalClockDelta.getRealNetworkTime()
self.sendUpdate('setAnimState', [animName, animMultiplier, timestamp])
return None
def setAnimState(self, animName, animMultiplier, timestamp = 0):
if animName not in ToontownGlobals.ToonAnimStates:
desc = 'tried to set invalid animState: %s' % (animName,)
if config.GetBool('want-ban-animstate', 1):
simbase.air.banManager.ban(self.doId, self.DISLid, desc)
else:
self.air.writeServerEvent('suspicious', self.doId, desc)
return
self.animName = animName
self.animMultiplier = animMultiplier
def b_setCogStatus(self, cogStatusList):
self.setCogStatus(cogStatusList)
self.d_setCogStatus(cogStatusList)
def setCogStatus(self, cogStatusList):
self.notify.debug('setting cogs to %s' % cogStatusList)
self.cogs = cogStatusList
def d_setCogStatus(self, cogStatusList):
self.sendUpdate('setCogStatus', [cogStatusList])
def getCogStatus(self):
return self.cogs
def b_setCogCount(self, cogCountList):
self.setCogCount(cogCountList)
self.d_setCogCount(cogCountList)
def setCogCount(self, cogCountList):
self.notify.debug('setting cogCounts to %s' % cogCountList)
self.cogCounts = cogCountList
def d_setCogCount(self, cogCountList):
self.sendUpdate('setCogCount', [cogCountList])
def getCogCount(self):
return self.cogCounts
def b_setCogRadar(self, radar):
self.setCogRadar(radar)
self.d_setCogRadar(radar)
def setCogRadar(self, radar):
if not radar:
self.notify.warning('cogRadar set to bad value: %s. Resetting to [0,0,0,0]' % radar)
self.cogRadar = [0,
0,
0,
0]
else:
self.cogRadar = radar
def d_setCogRadar(self, radar):
self.sendUpdate('setCogRadar', [radar])
def getCogRadar(self):
return self.cogRadar
def b_setBuildingRadar(self, radar):
self.setBuildingRadar(radar)
self.d_setBuildingRadar(radar)
def setBuildingRadar(self, radar):
if not radar:
self.notify.warning('buildingRadar set to bad value: %s. Resetting to [0,0,0,0]' % radar)
self.buildingRadar = [0,
0,
0,
0]
else:
self.buildingRadar = radar
def d_setBuildingRadar(self, radar):
self.sendUpdate('setBuildingRadar', [radar])
def getBuildingRadar(self):
return self.buildingRadar
def b_setCogTypes(self, types):
self.setCogTypes(types)
self.d_setCogTypes(types)
def setCogTypes(self, types):
if not types:
self.notify.warning('cogTypes set to bad value: %s. Resetting to [0,0,0,0]' % types)
self.cogTypes = [0,
0,
0,
0]
else:
self.cogTypes = types
def d_setCogTypes(self, types):
self.sendUpdate('setCogTypes', [types])
def getCogTypes(self):
return self.cogTypes
def b_setCogLevels(self, levels):
self.setCogLevels(levels)
self.d_setCogLevels(levels)
def setCogLevels(self, levels):
if not levels:
self.notify.warning('cogLevels set to bad value: %s. Resetting to [0,0,0,0]' % levels)
self.cogLevels = [0,
0,
0,
0]
else:
self.cogLevels = levels
def d_setCogLevels(self, levels):
self.sendUpdate('setCogLevels', [levels])
def getCogLevels(self):
return self.cogLevels
def incCogLevel(self, dept):
newLevel = self.cogLevels[dept] + 1
cogTypeStr = SuitDNA.suitHeadTypes[self.cogTypes[dept]]
lastCog = self.cogTypes[dept] >= SuitDNA.suitsPerDept - 1
if not lastCog:
maxLevel = SuitBattleGlobals.SuitAttributes[cogTypeStr]['level'] + 4
else:
maxLevel = ToontownGlobals.MaxCogSuitLevel
if newLevel > maxLevel:
if not lastCog:
self.cogTypes[dept] += 1
self.d_setCogTypes(self.cogTypes)
cogTypeStr = SuitDNA.suitHeadTypes[self.cogTypes[dept]]
self.cogLevels[dept] = SuitBattleGlobals.SuitAttributes[cogTypeStr]['level']
self.d_setCogLevels(self.cogLevels)
else:
self.cogLevels[dept] += 1
self.d_setCogLevels(self.cogLevels)
if lastCog:
if self.cogLevels[dept] in ToontownGlobals.CogSuitHPLevels:
maxHp = self.getMaxHp()
maxHp = min(ToontownGlobals.MaxHpLimit, maxHp + 1)
self.b_setMaxHp(maxHp)
self.toonUp(maxHp)
self.air.writeServerEvent('cogSuit', self.doId, '%s|%s|%s' % (dept, self.cogTypes[dept], self.cogLevels[dept]))
def getNumPromotions(self, dept):
if dept not in SuitDNA.suitDepts:
self.notify.warning('getNumPromotions: Invalid parameter dept=%s' % dept)
return 0
deptIndex = SuitDNA.suitDepts.index(dept)
cogType = self.cogTypes[deptIndex]
cogTypeStr = SuitDNA.suitHeadTypes[cogType]
lowestCogLevel = SuitBattleGlobals.SuitAttributes[cogTypeStr]['level']
multiple = 5 * cogType
additional = self.cogLevels[deptIndex] - lowestCogLevel
numPromotions = multiple + additional
return numPromotions
def b_setCogParts(self, parts):
self.setCogParts(parts)
self.d_setCogParts(parts)
def setCogParts(self, parts):
if not parts:
self.notify.warning('cogParts set to bad value: %s. Resetting to [0,0,0,0]' % parts)
self.cogParts = [0,
0,
0,
0]
else:
self.cogParts = parts
def d_setCogParts(self, parts):
self.sendUpdate('setCogParts', [parts])
def getCogParts(self):
return self.cogParts
def giveCogPart(self, part, dept):
dept = CogDisguiseGlobals.dept2deptIndex(dept)
parts = self.getCogParts()
parts[dept] = parts[dept] | part
self.b_setCogParts(parts)
def hasCogPart(self, part, dept):
dept = CogDisguiseGlobals.dept2deptIndex(dept)
if self.cogParts[dept] & part:
return 1
else:
return 0
def giveGenericCogPart(self, factoryType, dept):
for partTypeId in self.partTypeIds[factoryType]:
nextPart = CogDisguiseGlobals.getNextPart(self.getCogParts(), partTypeId, dept)
if nextPart:
break
if nextPart:
self.giveCogPart(nextPart, dept)
return nextPart
else:
return None
return None
def takeCogPart(self, part, dept):
dept = CogDisguiseGlobals.dept2deptIndex(dept)
parts = self.getCogParts()
if parts[dept] & part:
parts[dept] = parts[dept] ^ part
self.b_setCogParts(parts)
def loseCogParts(self, dept):
loseCount = random.randrange(CogDisguiseGlobals.MinPartLoss, CogDisguiseGlobals.MaxPartLoss + 1)
parts = self.getCogParts()
partBitmask = parts[dept]
partList = list(range(17))
2019-11-02 17:27:54 -05:00
while loseCount > 0 and partList:
losePart = random.choice(partList)
partList.remove(losePart)
losePartBit = 1 << losePart
if partBitmask & losePartBit:
partBitmask &= ~losePartBit
loseCount -= 1
parts[dept] = partBitmask
self.b_setCogParts(parts)
def b_setCogMerits(self, merits):
self.setCogMerits(merits)
self.d_setCogMerits(merits)
def setCogMerits(self, merits):
if not merits:
self.notify.warning('cogMerits set to bad value: %s. Resetting to [0,0,0,0]' % merits)
self.cogMerits = [0,
0,
0,
0]
else:
self.cogMerits = merits
def d_setCogMerits(self, merits):
self.sendUpdate('setCogMerits', [merits])
def getCogMerits(self):
return self.cogMerits
def b_promote(self, dept):
self.promote(dept)
self.d_promote(dept)
def promote(self, dept):
if self.cogLevels[dept] < ToontownGlobals.MaxCogSuitLevel:
self.cogMerits[dept] = 0
self.incCogLevel(dept)
def d_promote(self, dept):
merits = self.getCogMerits()
if self.cogLevels[dept] < ToontownGlobals.MaxCogSuitLevel:
merits[dept] = 0
self.d_setCogMerits(merits)
def readyForPromotion(self, dept):
merits = self.cogMerits[dept]
totalMerits = CogDisguiseGlobals.getTotalMerits(self, dept)
if merits >= totalMerits:
return 1
else:
return 0
def b_setCogIndex(self, index):
self.setCogIndex(index)
if simbase.config.GetBool('cogsuit-hack-prevent', False):
self.d_setCogIndex(self.cogIndex)
else:
self.d_setCogIndex(index)
def setCogIndex(self, index):
if index != -1 and not ToontownAccessAI.canWearSuit(self.doId, self.zoneId):
if not simbase.air.cogSuitMessageSent:
self.notify.warning('%s setCogIndex invalid: %s' % (self.doId, index))
if simbase.config.GetBool('want-ban-wrong-suit-place', False):
commentStr = 'Toon %s trying to set cog index to %s in Zone: %s' % (self.doId, index, self.zoneId)
simbase.air.banManager.ban(self.doId, self.DISLid, commentStr)
else:
self.cogIndex = index
def d_setCogIndex(self, index):
self.sendUpdate('setCogIndex', [index])
def getCogIndex(self):
return self.cogIndex
def b_setDisguisePageFlag(self, flag):
self.setDisguisePageFlag(flag)
self.d_setDisguisePageFlag(flag)
def setDisguisePageFlag(self, flag):
self.disguisePageFlag = flag
def d_setDisguisePageFlag(self, flag):
self.sendUpdate('setDisguisePageFlag', [flag])
def getDisguisePageFlag(self):
return self.disguisePageFlag
def b_setSosPageFlag(self, flag):
self.setSosPageFlag(flag)
self.d_setSosPageFlag(flag)
def setSosPageFlag(self, flag):
self.sosPageFlag = flag
def d_setSosPageFlag(self, flag):
self.sendUpdate('setSosPageFlag', [flag])
def getSosPageFlag(self):
return self.sosPageFlag
def b_setFishCollection(self, genusList, speciesList, weightList):
self.setFishCollection(genusList, speciesList, weightList)
self.d_setFishCollection(genusList, speciesList, weightList)
def d_setFishCollection(self, genusList, speciesList, weightList):
self.sendUpdate('setFishCollection', [genusList, speciesList, weightList])
def setFishCollection(self, genusList, speciesList, weightList):
self.fishCollection = FishCollection.FishCollection()
self.fishCollection.makeFromNetLists(genusList, speciesList, weightList)
def getFishCollection(self):
return self.fishCollection.getNetLists()
def b_setMaxFishTank(self, maxTank):
self.d_setMaxFishTank(maxTank)
self.setMaxFishTank(maxTank)
def d_setMaxFishTank(self, maxTank):
self.sendUpdate('setMaxFishTank', [maxTank])
def setMaxFishTank(self, maxTank):
self.maxFishTank = maxTank
def getMaxFishTank(self):
return self.maxFishTank
def b_setFishTank(self, genusList, speciesList, weightList):
self.setFishTank(genusList, speciesList, weightList)
self.d_setFishTank(genusList, speciesList, weightList)
def d_setFishTank(self, genusList, speciesList, weightList):
self.sendUpdate('setFishTank', [genusList, speciesList, weightList])
def setFishTank(self, genusList, speciesList, weightList):
self.fishTank = FishTank.FishTank()
self.fishTank.makeFromNetLists(genusList, speciesList, weightList)
def getFishTank(self):
return self.fishTank.getNetLists()
def makeRandomFishTank(self):
self.fishTank.generateRandomTank()
self.d_setFishTank(*self.fishTank.getNetLists())
def addFishToTank(self, fish):
numFish = len(self.fishTank)
if numFish >= self.maxFishTank:
self.notify.warning('addFishToTank: cannot add fish, tank is full')
return 0
elif self.fishTank.addFish(fish):
self.d_setFishTank(*self.fishTank.getNetLists())
return 1
else:
self.notify.warning('addFishToTank: addFish failed')
return 0
def removeFishFromTankAtIndex(self, index):
if self.fishTank.removeFishAtIndex(index):
self.d_setFishTank(*self.fishTank.getNetLists())
return 1
else:
self.notify.warning('removeFishFromTank: cannot find fish')
return 0
def b_setFishingRod(self, rodId):
self.d_setFishingRod(rodId)
self.setFishingRod(rodId)
def d_setFishingRod(self, rodId):
self.sendUpdate('setFishingRod', [rodId])
def setFishingRod(self, rodId):
self.fishingRod = rodId
def getFishingRod(self):
return self.fishingRod
def b_setFishingTrophies(self, trophyList):
self.setFishingTrophies(trophyList)
self.d_setFishingTrophies(trophyList)
def setFishingTrophies(self, trophyList):
self.notify.debug('setting fishingTrophies to %s' % trophyList)
self.fishingTrophies = trophyList
def d_setFishingTrophies(self, trophyList):
self.sendUpdate('setFishingTrophies', [trophyList])
def getFishingTrophies(self):
return self.fishingTrophies
def b_setQuests(self, questList):
flattenedQuests = []
for quest in questList:
flattenedQuests.extend(quest)
self.setQuests(flattenedQuests)
self.d_setQuests(flattenedQuests)
def d_setQuests(self, flattenedQuests):
self.sendUpdate('setQuests', [flattenedQuests])
def setQuests(self, flattenedQuests):
self.notify.debug('setting quests to %s' % flattenedQuests)
questList = []
questLen = 5
for i in range(0, len(flattenedQuests), questLen):
questList.append(flattenedQuests[i:i + questLen])
self.quests = questList
def getQuests(self):
flattenedQuests = []
for quest in self.quests:
flattenedQuests.extend(quest)
return flattenedQuests
def getQuest(self, questId, visitNpcId = None, rewardId = None):
for quest in self.quests:
if quest[0] != questId:
continue
if visitNpcId != None:
if visitNpcId != quest[1] and visitNpcId != quest[2]:
continue
if rewardId != None:
if rewardId != quest[3]:
continue
return quest
return
def hasQuest(self, questId, visitNpcId = None, rewardId = None):
if self.getQuest(questId, visitNpcId=visitNpcId, rewardId=rewardId) == None:
return False
else:
return True
return
def removeQuest(self, id, visitNpcId = None):
index = -1
for i in range(len(self.quests)):
if self.quests[i][0] == id:
if visitNpcId:
otherId = self.quests[i][2]
if visitNpcId == otherId:
index = i
break
else:
index = i
break
if index >= 0:
del self.quests[i]
self.b_setQuests(self.quests)
return 1
else:
return 0
def addQuest(self, quest, finalReward, recordHistory = 1):
self.quests.append(quest)
self.b_setQuests(self.quests)
if recordHistory:
if quest[0] != Quests.VISIT_QUEST_ID:
newQuestHistory = self.questHistory + [quest[0]]
while newQuestHistory.count(Quests.VISIT_QUEST_ID) != 0:
newQuestHistory.remove(Quests.VISIT_QUEST_ID)
self.b_setQuestHistory(newQuestHistory)
if finalReward:
newRewardHistory = self.rewardHistory + [finalReward]
self.b_setRewardHistory(self.rewardTier, newRewardHistory)
def removeAllTracesOfQuest(self, questId, rewardId):
self.notify.debug('removeAllTracesOfQuest: questId: %s rewardId: %s' % (questId, rewardId))
self.notify.debug('removeAllTracesOfQuest: quests before: %s' % self.quests)
removedQuest = self.removeQuest(questId)
self.notify.debug('removeAllTracesOfQuest: quests after: %s' % self.quests)
self.notify.debug('removeAllTracesOfQuest: questHistory before: %s' % self.questHistory)
removedQuestHistory = self.removeQuestFromHistory(questId)
self.notify.debug('removeAllTracesOfQuest: questHistory after: %s' % self.questHistory)
self.notify.debug('removeAllTracesOfQuest: reward history before: %s' % self.rewardHistory)
removedRewardHistory = self.removeRewardFromHistory(rewardId)
self.notify.debug('removeAllTracesOfQuest: reward history after: %s' % self.rewardHistory)
return (removedQuest, removedQuestHistory, removedRewardHistory)
def requestDeleteQuest(self, questDesc):
if len(questDesc) != 5:
self.air.writeServerEvent('suspicious', self.doId, 'Toon tried to delete invalid questDesc %s' % str(questDesc))
self.notify.warning('%s.requestDeleteQuest(%s) -- questDesc has incorrect params' % (self, str(questDesc)))
return
questId = questDesc[0]
rewardId = questDesc[3]
if not self.hasQuest(questId, rewardId=rewardId):
self.air.writeServerEvent('suspicious', self.doId, "Toon tried to delete quest they don't have %s" % str(questDesc))
self.notify.warning("%s.requestDeleteQuest(%s) -- Toon doesn't have that quest" % (self, str(questDesc)))
return
if not Quests.isQuestJustForFun(questId, rewardId):
self.air.writeServerEvent('suspicious', self.doId, 'Toon tried to delete non-Just For Fun quest %s' % str(questDesc))
self.notify.warning('%s.requestDeleteQuest(%s) -- Tried to cancel non-Just For Fun quest' % (self, str(questDesc)))
return
removedStatus = self.removeAllTracesOfQuest(questId, rewardId)
if 0 in removedStatus:
self.notify.warning('%s.requestDeleteQuest(%s) -- Failed to remove quest, status=%s' % (self, str(questDesc), removedStatus))
def b_setQuestCarryLimit(self, limit):
self.setQuestCarryLimit(limit)
self.d_setQuestCarryLimit(limit)
def d_setQuestCarryLimit(self, limit):
self.sendUpdate('setQuestCarryLimit', [limit])
def setQuestCarryLimit(self, limit):
self.notify.debug('setting questCarryLimit to %s' % limit)
self.questCarryLimit = limit
def getQuestCarryLimit(self):
return self.questCarryLimit
def b_setMaxCarry(self, maxCarry):
self.setMaxCarry(maxCarry)
self.d_setMaxCarry(maxCarry)
def d_setMaxCarry(self, maxCarry):
self.sendUpdate('setMaxCarry', [maxCarry])
def setMaxCarry(self, maxCarry):
self.maxCarry = maxCarry
def getMaxCarry(self):
return self.maxCarry
def b_setCheesyEffect(self, effect, hoodId, expireTime):
self.setCheesyEffect(effect, hoodId, expireTime)
self.d_setCheesyEffect(effect, hoodId, expireTime)
def d_setCheesyEffect(self, effect, hoodId, expireTime):
self.sendUpdate('setCheesyEffect', [effect, hoodId, expireTime])
def setCheesyEffect(self, effect, hoodId, expireTime):
if simbase.air.holidayManager and ToontownGlobals.WINTER_CAROLING not in simbase.air.holidayManager.currentHolidays and ToontownGlobals.WACKY_WINTER_CAROLING not in simbase.air.holidayManager.currentHolidays and effect == ToontownGlobals.CESnowMan:
self.b_setCheesyEffect(ToontownGlobals.CENormal, hoodId, expireTime)
return
self.savedCheesyEffect = effect
self.savedCheesyHoodId = hoodId
self.savedCheesyExpireTime = expireTime
if self.air.doLiveUpdates:
taskName = self.uniqueName('cheesy-expires')
taskMgr.remove(taskName)
if effect != ToontownGlobals.CENormal:
duration = expireTime * 60 - time.time()
if duration > 0:
taskMgr.doMethodLater(duration, self.__undoCheesyEffect, taskName)
else:
self.__undoCheesyEffect(None)
return
def getCheesyEffect(self):
return (self.savedCheesyEffect, self.savedCheesyHoodId, self.savedCheesyExpireTime)
def __undoCheesyEffect(self, task):
self.b_setCheesyEffect(ToontownGlobals.CENormal, 0, 0)
return Task.cont
def b_setTrackAccess(self, trackArray):
self.setTrackAccess(trackArray)
self.d_setTrackAccess(trackArray)
def d_setTrackAccess(self, trackArray):
self.sendUpdate('setTrackAccess', [trackArray])
def setTrackAccess(self, trackArray):
self.trackArray = trackArray
def getTrackAccess(self):
return self.trackArray
def addTrackAccess(self, track):
self.trackArray[track] = 1
self.b_setTrackAccess(self.trackArray)
def removeTrackAccess(self, track):
self.trackArray[track] = 0
self.b_setTrackAccess(self.trackArray)
def hasTrackAccess(self, track):
if self.trackArray and track < len(self.trackArray):
return self.trackArray[track]
else:
return 0
def fixTrackAccess(self):
fixed = 0
healExp, trapExp, lureExp, soundExp, throwExp, squirtExp, dropExp = self.experience.experience
numTracks = reduce(lambda a, b: a + b, self.trackArray)
if self.rewardTier in [0,
1,
2,
3]:
if numTracks != 2:
self.notify.warning('bad num tracks in tier: %s, %s' % (self.rewardTier, self.trackArray))
self.b_setTrackAccess([0, 0, 0, 0, 1, 1, 0])
fixed = 1
elif self.rewardTier in [4, 5, 6]:
if numTracks != 3:
self.notify.warning('bad num tracks in tier: %s, %s' % (self.rewardTier, self.trackArray))
if self.trackArray[ToontownBattleGlobals.SOUND_TRACK] and not self.trackArray[ToontownBattleGlobals.HEAL_TRACK]:
self.b_setTrackAccess([0, 0, 0, 1, 1, 1, 0])
elif self.trackArray[ToontownBattleGlobals.HEAL_TRACK] and not self.trackArray[ToontownBattleGlobals.SOUND_TRACK]:
self.b_setTrackAccess([1, 0, 0, 0, 1, 1, 0])
elif soundExp >= healExp:
self.b_setTrackAccess([0, 0, 0, 1, 1, 1, 0])
else:
self.b_setTrackAccess([1, 0, 0, 0, 1, 1, 0])
fixed = 1
elif self.rewardTier in [7, 8, 9, 10]:
if numTracks != 4:
self.notify.warning('bad num tracks in tier: %s, %s' % (self.rewardTier, self.trackArray))
if self.trackArray[ToontownBattleGlobals.SOUND_TRACK] and not self.trackArray[ToontownBattleGlobals.HEAL_TRACK]:
if dropExp >= lureExp:
self.b_setTrackAccess([0, 0, 0, 1, 1, 1, 1])
else:
self.b_setTrackAccess([0, 0, 1, 1, 1, 1, 0])
elif self.trackArray[ToontownBattleGlobals.HEAL_TRACK] and not self.trackArray[ToontownBattleGlobals.SOUND_TRACK]:
if dropExp >= lureExp:
self.b_setTrackAccess([1, 0, 0, 0, 1, 1, 1])
else:
self.b_setTrackAccess([1, 0, 1, 0, 1, 1, 0])
elif soundExp >= healExp:
if dropExp >= lureExp:
self.b_setTrackAccess([0, 0, 0, 1, 1, 1, 1])
else:
self.b_setTrackAccess([0, 0, 1, 1, 1, 1, 0])
elif dropExp >= lureExp:
self.b_setTrackAccess([1, 0, 0, 0, 1, 1, 1])
else:
self.b_setTrackAccess([1, 0, 1, 0, 1, 1, 0])
fixed = 1
elif self.rewardTier in [11, 12, 13]:
if numTracks != 5:
self.notify.warning('bad num tracks in tier: %s, %s' % (self.rewardTier, self.trackArray))
if self.trackArray[ToontownBattleGlobals.SOUND_TRACK] and not self.trackArray[ToontownBattleGlobals.HEAL_TRACK]:
if self.trackArray[ToontownBattleGlobals.DROP_TRACK] and not self.trackArray[ToontownBattleGlobals.LURE_TRACK]:
if healExp >= trapExp:
self.b_setTrackAccess([1, 0, 0, 1, 1, 1, 1])
else:
self.b_setTrackAccess([0, 1, 0, 1, 1, 1, 1])
elif healExp >= trapExp:
self.b_setTrackAccess([1, 0, 1, 1, 1, 1, 0])
else:
self.b_setTrackAccess([0, 1, 1, 1, 1, 1, 0])
elif self.trackArray[ToontownBattleGlobals.HEAL_TRACK] and not self.trackArray[ToontownBattleGlobals.SOUND_TRACK]:
if self.trackArray[ToontownBattleGlobals.DROP_TRACK] and not self.trackArray[ToontownBattleGlobals.LURE_TRACK]:
if soundExp >= trapExp:
self.b_setTrackAccess([1, 0, 0, 1, 1, 1, 1])
else:
self.b_setTrackAccess([1, 1, 0, 0, 1, 1, 1])
elif soundExp >= trapExp:
self.b_setTrackAccess([1, 0, 1, 1, 1, 1, 0])
else:
self.b_setTrackAccess([1, 1, 1, 0, 1, 1, 0])
fixed = 1
elif numTracks != 6:
self.notify.warning('bad num tracks in tier: %s, %s' % (self.rewardTier, self.trackArray))
sortedExp = [healExp,
trapExp,
lureExp,
soundExp,
dropExp]
sortedExp.sort()
if trapExp == sortedExp[0]:
self.b_setTrackAccess([1, 0, 1, 1, 1, 1, 1])
elif lureExp == sortedExp[0]:
self.b_setTrackAccess([1, 1, 0, 1, 1, 1, 1])
elif dropExp == sortedExp[0]:
self.b_setTrackAccess([1, 1, 1, 1, 1, 1, 0])
elif soundExp == sortedExp[0]:
self.b_setTrackAccess([1, 1, 1, 0, 1, 1, 1])
elif healExp == sortedExp[0]:
self.b_setTrackAccess([0, 1, 1, 1, 1, 1, 1])
else:
self.notify.warning('invalid exp?!: %s, %s' % (sortedExp, self.trackArray))
self.b_setTrackAccess([1, 0, 1, 1, 1, 1, 1])
fixed = 1
if fixed:
self.inventory.zeroInv()
self.inventory.maxOutInv()
self.d_setInventory(self.inventory.makeNetString())
self.notify.info('fixed tracks: %s' % self.trackArray)
return fixed
def b_setTrackProgress(self, trackId, progress):
self.setTrackProgress(trackId, progress)
self.d_setTrackProgress(trackId, progress)
def d_setTrackProgress(self, trackId, progress):
self.sendUpdate('setTrackProgress', [trackId, progress])
def setTrackProgress(self, trackId, progress):
self.trackProgressId = trackId
self.trackProgress = progress
def addTrackProgress(self, trackId, progressIndex):
if self.trackProgressId != trackId:
self.notify.warning('tried to update progress on a track toon is not training')
newProgress = self.trackProgress | 1 << progressIndex - 1
self.b_setTrackProgress(self.trackProgressId, newProgress)
def clearTrackProgress(self):
self.b_setTrackProgress(-1, 0)
def getTrackProgress(self):
return [self.trackProgressId, self.trackProgress]
def b_setHoodsVisited(self, hoodsVisitedArray):
self.hoodsVisited = hoodsVisitedArray
self.d_setHoodsVisited(hoodsVisitedArray)
def d_setHoodsVisited(self, hoodsVisitedArray):
self.sendUpdate('setHoodsVisited', [hoodsVisitedArray])
def b_setTeleportAccess(self, teleportZoneArray):
self.setTeleportAccess(teleportZoneArray)
self.d_setTeleportAccess(teleportZoneArray)
def d_setTeleportAccess(self, teleportZoneArray):
self.sendUpdate('setTeleportAccess', [teleportZoneArray])
def setTeleportAccess(self, teleportZoneArray):
self.teleportZoneArray = teleportZoneArray
def getTeleportAccess(self):
return self.teleportZoneArray
def hasTeleportAccess(self, zoneId):
return zoneId in self.teleportZoneArray
def addTeleportAccess(self, zoneId):
if zoneId not in self.teleportZoneArray:
self.teleportZoneArray.append(zoneId)
self.b_setTeleportAccess(self.teleportZoneArray)
def removeTeleportAccess(self, zoneId):
if zoneId in self.teleportZoneArray:
self.teleportZoneArray.remove(zoneId)
self.b_setTeleportAccess(self.teleportZoneArray)
def checkTeleportAccess(self, zoneId):
if zoneId not in self.getTeleportAccess():
simbase.air.writeServerEvent('suspicious', self.doId, 'Toon teleporting to zone %s they do not have access to.' % zoneId)
if simbase.config.GetBool('want-ban-teleport', False):
commentStr = 'Toon %s teleporting to a zone %s they do not have access to' % (self.doId, zoneId)
simbase.air.banManager.ban(self.doId, self.DISLid, commentStr)
def b_setQuestHistory(self, questList):
self.setQuestHistory(questList)
self.d_setQuestHistory(questList)
def d_setQuestHistory(self, questList):
self.sendUpdate('setQuestHistory', [questList])
def setQuestHistory(self, questList):
self.notify.debug('setting quest history to %s' % questList)
self.questHistory = questList
def getQuestHistory(self):
return self.questHistory
def removeQuestFromHistory(self, questId):
if questId in self.questHistory:
self.questHistory.remove(questId)
self.d_setQuestHistory(self.questHistory)
return 1
else:
return 0
def removeRewardFromHistory(self, rewardId):
rewardTier, rewardHistory = self.getRewardHistory()
if rewardId in rewardHistory:
rewardHistory.remove(rewardId)
self.b_setRewardHistory(rewardTier, rewardHistory)
return 1
else:
return 0
def b_setRewardHistory(self, tier, rewardList):
self.setRewardHistory(tier, rewardList)
self.d_setRewardHistory(tier, rewardList)
def d_setRewardHistory(self, tier, rewardList):
self.sendUpdate('setRewardHistory', [tier, rewardList])
def setRewardHistory(self, tier, rewardList):
self.air.writeServerEvent('questTier', self.getDoId(), str(tier))
self.notify.debug('setting reward history to tier %s, %s' % (tier, rewardList))
self.rewardTier = tier
self.rewardHistory = rewardList
def getRewardHistory(self):
return (self.rewardTier, self.rewardHistory)
def getRewardTier(self):
return self.rewardTier
def fixAvatar(self):
anyChanged = 0
qrc = QuestRewardCounter.QuestRewardCounter()
if qrc.fixAvatar(self):
self.notify.info("Fixed avatar %d's quest rewards." % self.doId)
anyChanged = 1
if self.hp > self.maxHp:
self.notify.info('Changed avatar %d to have hp %d instead of %d, to fit with maxHp' % (self.doId, self.maxHp, self.hp))
self.b_setHp(self.maxHp)
anyChanged = 1
inventoryChanged = 0
carry = self.maxCarry
for track in range(len(ToontownBattleGlobals.Tracks)):
if not self.hasTrackAccess(track):
for level in range(len(ToontownBattleGlobals.Levels[track])):
count = self.inventory.inventory[track][level]
if count != 0:
self.notify.info('Changed avatar %d to throw away %d items in track %d level %d; no access to track.' % (self.doId,
count,
track,
level))
self.inventory.inventory[track][level] = 0
inventoryChanged = 1
else:
curSkill = self.experience.getExp(track)
for level in range(len(ToontownBattleGlobals.Levels[track])):
count = self.inventory.inventory[track][level]
if curSkill < ToontownBattleGlobals.Levels[track][level]:
if count != 0:
self.notify.info('Changed avatar %d to throw away %d items in track %d level %d; no access to level.' % (self.doId,
count,
track,
level))
self.inventory.inventory[track][level] = 0
inventoryChanged = 1
else:
newCount = min(count, carry)
newCount = min(count, self.inventory.getMax(track, level))
if count != newCount:
self.notify.info('Changed avatar %d to throw away %d items in track %d level %d; too many gags.' % (self.doId,
count - newCount,
track,
level))
self.inventory.inventory[track][level] = newCount
inventoryChanged = 1
carry -= newCount
self.inventory.calcTotalProps()
if inventoryChanged:
self.d_setInventory(self.inventory.makeNetString())
anyChanged = 1
if len(self.quests) > self.questCarryLimit:
self.notify.info('Changed avatar %d to throw out %d quests; too many quests.' % (self.doId, len(self.quests) - self.questCarryLimit))
self.b_setQuests(self.quests[:self.questCarryLimit])
self.fixAvatar()
anyChanged = 1
if not (self.emoteAccess[0] and self.emoteAccess[1] and self.emoteAccess[2] and self.emoteAccess[3] and self.emoteAccess[4]):
self.emoteAccess[0] = 1
self.emoteAccess[1] = 1
self.emoteAccess[2] = 1
self.emoteAccess[3] = 1
self.emoteAccess[4] = 1
self.b_setEmoteAccess(self.emoteAccess)
self.notify.info('Changed avatar %d to have emoteAccess: %s' % (self.doId, self.emoteAccess))
anyChanged = 1
return anyChanged
def b_setEmoteAccess(self, bits):
self.setEmoteAccess(bits)
self.d_setEmoteAccess(bits)
def d_setEmoteAccess(self, bits):
self.sendUpdate('setEmoteAccess', [bits])
def setEmoteAccess(self, bits):
if len(bits) == 20:
bits.extend([0,
0,
0,
0,
0])
self.b_setEmoteAccess(bits)
elif len(bits) != len(self.emoteAccess):
self.notify.warning('New emote access list must be the same size as the old one.')
return
self.emoteAccess = bits
def getEmoteAccess(self):
return self.emoteAccess
def setEmoteAccessId(self, id, bit):
self.emoteAccess[id] = bit
self.d_setEmoteAccess(self.emoteAccess)
def b_setHouseId(self, id):
self.setHouseId(id)
self.d_setHouseId(id)
def d_setHouseId(self, id):
self.sendUpdate('setHouseId', [id])
def setHouseId(self, id):
self.houseId = id
def getHouseId(self):
return self.houseId
def setPosIndex(self, index):
self.posIndex = index
def getPosIndex(self):
return self.posIndex
def b_setCustomMessages(self, customMessages):
self.d_setCustomMessages(customMessages)
self.setCustomMessages(customMessages)
def d_setCustomMessages(self, customMessages):
self.sendUpdate('setCustomMessages', [customMessages])
def setCustomMessages(self, customMessages):
self.customMessages = customMessages
def getCustomMessages(self):
return self.customMessages
def b_setResistanceMessages(self, resistanceMessages):
self.d_setResistanceMessages(resistanceMessages)
self.setResistanceMessages(resistanceMessages)
def d_setResistanceMessages(self, resistanceMessages):
self.sendUpdate('setResistanceMessages', [resistanceMessages])
def setResistanceMessages(self, resistanceMessages):
self.resistanceMessages = resistanceMessages
def getResistanceMessages(self):
return self.resistanceMessages
def addResistanceMessage(self, textId):
msgs = self.getResistanceMessages()
for i in range(len(msgs)):
if msgs[i][0] == textId:
msgs[i][1] += 1
self.b_setResistanceMessages(msgs)
return
msgs.append([textId, 1])
self.b_setResistanceMessages(msgs)
def removeResistanceMessage(self, textId):
msgs = self.getResistanceMessages()
for i in range(len(msgs)):
if msgs[i][0] == textId:
msgs[i][1] -= 1
if msgs[i][1] <= 0:
del msgs[i]
self.b_setResistanceMessages(msgs)
return 1
self.notify.warning("Toon %s doesn't have resistance message %s" % (self.doId, textId))
return 0
def restockAllResistanceMessages(self, charges = 1):
from toontown.chat import ResistanceChat
msgs = []
for menuIndex in ResistanceChat.resistanceMenu:
for itemIndex in ResistanceChat.getItems(menuIndex):
textId = ResistanceChat.encodeId(menuIndex, itemIndex)
msgs.append([textId, charges])
self.b_setResistanceMessages(msgs)
def b_setCatalogSchedule(self, currentWeek, nextTime):
self.setCatalogSchedule(currentWeek, nextTime)
self.d_setCatalogSchedule(currentWeek, nextTime)
def d_setCatalogSchedule(self, currentWeek, nextTime):
self.sendUpdate('setCatalogSchedule', [currentWeek, nextTime])
def setCatalogSchedule(self, currentWeek, nextTime):
self.catalogScheduleCurrentWeek = currentWeek
self.catalogScheduleNextTime = nextTime
if self.air.doLiveUpdates:
taskName = self.uniqueName('next-catalog')
taskMgr.remove(taskName)
duration = max(10.0, nextTime * 60 - time.time())
taskMgr.doMethodLater(duration, self.__deliverCatalog, taskName)
def getCatalogSchedule(self):
return (self.catalogScheduleCurrentWeek, self.catalogScheduleNextTime)
def __deliverCatalog(self, task):
self.air.catalogManager.deliverCatalogFor(self)
return Task.done
def b_setCatalog(self, monthlyCatalog, weeklyCatalog, backCatalog):
self.setCatalog(monthlyCatalog, weeklyCatalog, backCatalog)
self.d_setCatalog(monthlyCatalog, weeklyCatalog, backCatalog)
def d_setCatalog(self, monthlyCatalog, weeklyCatalog, backCatalog):
self.sendUpdate('setCatalog', [monthlyCatalog.getBlob(), weeklyCatalog.getBlob(), backCatalog.getBlob()])
def setCatalog(self, monthlyCatalog, weeklyCatalog, backCatalog):
self.monthlyCatalog = CatalogItemList.CatalogItemList(monthlyCatalog)
self.weeklyCatalog = CatalogItemList.CatalogItemList(weeklyCatalog)
self.backCatalog = CatalogItemList.CatalogItemList(backCatalog)
def getCatalog(self):
return (self.monthlyCatalog.getBlob(), self.weeklyCatalog.getBlob(), self.backCatalog.getBlob())
def b_setCatalogNotify(self, catalogNotify, mailboxNotify):
self.setCatalogNotify(catalogNotify, mailboxNotify)
self.d_setCatalogNotify(catalogNotify, mailboxNotify)
def d_setCatalogNotify(self, catalogNotify, mailboxNotify):
self.sendUpdate('setCatalogNotify', [catalogNotify, mailboxNotify])
def setCatalogNotify(self, catalogNotify, mailboxNotify):
self.catalogNotify = catalogNotify
self.mailboxNotify = mailboxNotify
def getCatalogNotify(self):
return (self.catalogNotify, self.mailboxNotify)
def b_setDeliverySchedule(self, onOrder, doUpdateLater = True):
self.setDeliverySchedule(onOrder, doUpdateLater)
self.d_setDeliverySchedule(onOrder)
def d_setDeliverySchedule(self, onOrder):
self.sendUpdate('setDeliverySchedule', [onOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate)])
def setDeliverySchedule(self, onOrder, doUpdateLater = True):
self.setBothSchedules(onOrder, None)
return
self.onOrder = CatalogItemList.CatalogItemList(onOrder, store=CatalogItem.Customization | CatalogItem.DeliveryDate)
if hasattr(self, 'name'):
if doUpdateLater and self.air.doLiveUpdates and hasattr(self, 'air'):
taskName = self.uniqueName('next-delivery')
taskMgr.remove(taskName)
now = int(time.time() / 60 + 0.5)
nextItem = None
nextTime = self.onOrder.getNextDeliveryDate()
nextItem = self.onOrder.getNextDeliveryItem()
if nextItem != None:
pass
if nextTime != None:
duration = max(10.0, nextTime * 60 - time.time())
taskMgr.doMethodLater(duration, self.__deliverPurchase, taskName)
return
def getDeliverySchedule(self):
return self.onOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate)
def b_setBothSchedules(self, onOrder, onGiftOrder, doUpdateLater = True):
self.setBothSchedules(onOrder, onGiftOrder, doUpdateLater)
self.d_setDeliverySchedule(onOrder)
def setBothSchedules(self, onOrder, onGiftOrder, doUpdateLater = True):
if onOrder != None:
self.onOrder = CatalogItemList.CatalogItemList(onOrder, store=CatalogItem.Customization | CatalogItem.DeliveryDate)
if onGiftOrder != None:
self.onGiftOrder = CatalogItemList.CatalogItemList(onGiftOrder, store=CatalogItem.Customization | CatalogItem.DeliveryDate)
if not hasattr(self, 'air') or self.air == None:
return
if doUpdateLater and self.air.doLiveUpdates and hasattr(self, 'name'):
taskName = 'next-bothDelivery-%s' % self.doId
now = int(time.time() / 60 + 0.5)
nextItem = None
nextGiftItem = None
nextTime = None
nextGiftTime = None
if self.onOrder:
nextTime = self.onOrder.getNextDeliveryDate()
nextItem = self.onOrder.getNextDeliveryItem()
if self.onGiftOrder:
nextGiftTime = self.onGiftOrder.getNextDeliveryDate()
nextGiftItem = self.onGiftOrder.getNextDeliveryItem()
if nextItem:
pass
if nextGiftItem:
pass
if nextTime == None:
nextTime = nextGiftTime
if nextGiftTime == None:
nextGiftTime = nextTime
2019-12-30 18:17:24 -06:00
if nextGiftTime is not None and nextTime is not None and nextGiftTime < nextTime:
2019-11-02 17:27:54 -05:00
nextTime = nextGiftTime
existingDuration = None
checkTaskList = taskMgr.getTasksNamed(taskName)
if checkTaskList:
currentTime = globalClock.getFrameTime()
checkTask = checkTaskList[0]
existingDuration = checkTask.wakeTime - currentTime
if nextTime:
newDuration = max(10.0, nextTime * 60 - time.time())
if existingDuration and existingDuration >= newDuration:
taskMgr.remove(taskName)
taskMgr.doMethodLater(newDuration, self.__deliverBothPurchases, taskName)
elif existingDuration and existingDuration < newDuration:
pass
else:
taskMgr.doMethodLater(newDuration, self.__deliverBothPurchases, taskName)
return
def __deliverBothPurchases(self, task):
now = int(time.time() / 60 + 0.5)
delivered, remaining = self.onOrder.extractDeliveryItems(now)
deliveredGifts, remainingGifts = self.onGiftOrder.extractDeliveryItems(now)
simbase.air.deliveryManager.sendDeliverGifts(self.getDoId(), now)
giftItem = CatalogItemList.CatalogItemList(deliveredGifts, store=CatalogItem.Customization | CatalogItem.DeliveryDate)
if len(giftItem) > 0:
self.air.writeServerEvent('Getting Gift', self.doId, 'sender %s receiver %s gift %s' % (giftItem[0].giftTag, self.doId, giftItem[0].getName()))
self.b_setMailboxContents(self.mailboxContents + delivered + deliveredGifts)
self.b_setCatalogNotify(self.catalogNotify, ToontownGlobals.NewItems)
self.b_setBothSchedules(remaining, remainingGifts)
return Task.done
def setGiftSchedule(self, onGiftOrder, doUpdateLater = True):
self.setBothSchedules(None, onGiftOrder)
return
self.onGiftOrder = CatalogItemList.CatalogItemList(onGiftOrder, store=CatalogItem.Customization | CatalogItem.DeliveryDate)
if doUpdateLater and self.air.doLiveUpdates and hasattr(self, 'air') and hasattr(self, 'name'):
taskName = self.uniqueName('next-gift')
taskMgr.remove(taskName)
now = int(time.time() / 60 + 0.5)
nextItem = None
nextTime = self.onGiftOrder.getNextDeliveryDate()
nextItem = self.onGiftOrder.getNextDeliveryItem()
if nextItem != None:
pass
if nextTime != None:
duration = max(10.0, nextTime * 60 - time.time())
duration += 30
taskMgr.doMethodLater(duration, self.__deliverGiftPurchase, taskName)
return
def getGiftSchedule(self):
return self.onGiftOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate)
def __deliverGiftPurchase(self, task):
now = int(time.time() / 60 + 0.5)
delivered, remaining = self.onGiftOrder.extractDeliveryItems(now)
self.notify.info('Gift Delivery for %s: %s.' % (self.doId, delivered))
self.b_setMailboxContents(self.mailboxContents + delivered)
simbase.air.deliveryManager.sendDeliverGifts(self.getDoId(), now)
self.b_setCatalogNotify(self.catalogNotify, ToontownGlobals.NewItems)
return Task.done
def __deliverPurchase(self, task):
now = int(time.time() / 60 + 0.5)
delivered, remaining = self.onOrder.extractDeliveryItems(now)
self.notify.info('Delivery for %s: %s.' % (self.doId, delivered))
self.b_setMailboxContents(self.mailboxContents + delivered)
self.b_setDeliverySchedule(remaining)
self.b_setCatalogNotify(self.catalogNotify, ToontownGlobals.NewItems)
return Task.done
def b_setMailboxContents(self, mailboxContents):
self.setMailboxContents(mailboxContents)
self.d_setMailboxContents(mailboxContents)
def d_setMailboxContents(self, mailboxContents):
self.sendUpdate('setMailboxContents', [mailboxContents.getBlob(store=CatalogItem.Customization)])
if len(mailboxContents) == 0:
self.b_setCatalogNotify(self.catalogNotify, ToontownGlobals.NoItems)
self.checkMailboxFullIndicator()
def checkMailboxFullIndicator(self):
if self.houseId and hasattr(self, 'air'):
if self.air:
house = self.air.doId2do.get(self.houseId)
if house and house.mailbox:
house.mailbox.b_setFullIndicator(len(self.mailboxContents) != 0 or self.numMailItems or self.getNumInvitesToShowInMailbox() or len(self.awardMailboxContents) != 0)
def setMailboxContents(self, mailboxContents):
self.notify.debug('Setting mailboxContents to %s.' % mailboxContents)
self.mailboxContents = CatalogItemList.CatalogItemList(mailboxContents, store=CatalogItem.Customization)
self.notify.debug('mailboxContents is %s.' % self.mailboxContents)
def getMailboxContents(self):
return self.mailboxContents.getBlob(store=CatalogItem.Customization)
def b_setGhostMode(self, flag):
self.setGhostMode(flag)
self.d_setGhostMode(flag)
def d_setGhostMode(self, flag):
self.sendUpdate('setGhostMode', [flag])
def setGhostMode(self, flag):
self.ghostMode = flag
def setImmortalMode(self, flag):
self.immortalMode = flag
def b_setSpeedChatStyleIndex(self, index):
self.setSpeedChatStyleIndex(index)
self.d_setSpeedChatStyleIndex(index)
def d_setSpeedChatStyleIndex(self, index):
self.sendUpdate('setSpeedChatStyleIndex', [index])
def setSpeedChatStyleIndex(self, index):
self.speedChatStyleIndex = index
def getSpeedChatStyleIndex(self):
return self.speedChatStyleIndex
def b_setMaxMoney(self, maxMoney):
self.d_setMaxMoney(maxMoney)
self.setMaxMoney(maxMoney)
def d_setMaxMoney(self, maxMoney):
self.sendUpdate('setMaxMoney', [maxMoney])
def setMaxMoney(self, maxMoney):
self.maxMoney = maxMoney
def getMaxMoney(self):
return self.maxMoney
def addMoney(self, deltaMoney):
money = deltaMoney + self.money
pocketMoney = min(money, self.maxMoney)
self.b_setMoney(pocketMoney)
overflowMoney = money - self.maxMoney
if overflowMoney > 0:
bankMoney = self.bankMoney + overflowMoney
self.b_setBankMoney(bankMoney)
def takeMoney(self, deltaMoney, bUseBank = True):
totalMoney = self.money
if bUseBank:
totalMoney += self.bankMoney
if deltaMoney > totalMoney:
self.notify.warning('Not enough money! AvId: %s Has:%s Charged:%s' % (self.doId, totalMoney, deltaMoney))
return False
if bUseBank and deltaMoney > self.money:
self.b_setBankMoney(self.bankMoney - (deltaMoney - self.money))
self.b_setMoney(0)
else:
self.b_setMoney(self.money - deltaMoney)
return True
def b_setMoney(self, money):
if bboard.get('autoRich-%s' % self.doId, False):
money = self.getMaxMoney()
self.setMoney(money)
self.d_setMoney(money)
def d_setMoney(self, money):
self.sendUpdate('setMoney', [money])
def setMoney(self, money):
if money < 0:
simbase.air.writeServerEvent('suspicious', self.doId, 'toon has invalid money %s, forcing to zero' % money)
money = 0
commentStr = 'User %s has negative money %s' % (self.doId, money)
dislId = self.DISLid
if simbase.config.GetBool('want-ban-negative-money', False):
simbase.air.banManager.ban(self.doId, dislId, commentStr)
self.money = money
def getMoney(self):
return self.money
def getTotalMoney(self):
return self.money + self.bankMoney
def b_setMaxBankMoney(self, maxMoney):
self.d_setMaxBankMoney(maxMoney)
self.setMaxBankMoney(maxMoney)
def d_setMaxBankMoney(self, maxMoney):
self.sendUpdate('setMaxBankMoney', [maxMoney])
def setMaxBankMoney(self, maxMoney):
self.maxBankMoney = maxMoney
def getMaxBankMoney(self):
return self.maxBankMoney
def b_setBankMoney(self, money):
bankMoney = min(money, self.maxBankMoney)
self.setBankMoney(bankMoney)
self.d_setBankMoney(bankMoney)
def d_setBankMoney(self, money):
self.sendUpdate('setBankMoney', [money])
def setBankMoney(self, money):
self.bankMoney = money
def getBankMoney(self):
return self.bankMoney
def b_setEmblems(self, emblems):
self.setEmblems(emblems)
self.d_setEmblems(emblems)
def setEmblems(self, emblems):
self.emblems = emblems
def d_setEmblems(self, emblems):
if simbase.air.wantEmblems:
self.sendUpdate('setEmblems', [emblems])
def getEmblems(self):
return self.emblems
def addEmblems(self, emblemsToAdd):
newEmblems = self.emblems[:]
for i in range(ToontownGlobals.NumEmblemTypes):
2019-11-02 17:27:54 -05:00
newEmblems[i] += emblemsToAdd[i]
self.b_setEmblems(newEmblems)
def subtractEmblems(self, emblemsToSubtract):
newEmblems = self.emblems[:]
for i in range(ToontownGlobals.NumEmblemTypes):
2019-11-02 17:27:54 -05:00
newEmblems[i] -= emblemsToSubtract[i]
self.b_setEmblems(newEmblems)
def isEnoughEmblemsToBuy(self, itemEmblemPrices):
for emblemIndex, emblemPrice in enumerate(itemEmblemPrices):
if emblemIndex >= len(self.emblems):
return False
if self.emblems[emblemIndex] < emblemPrice:
return False
return True
def tossPie(self, x, y, z, h, p, r, sequence, power, timestamp32):
if not self.validate(self.doId, self.numPies > 0, 'tossPie with no pies available'):
return
if self.numPies != ToontownGlobals.FullPies:
self.b_setNumPies(self.numPies - 1)
def b_setNumPies(self, numPies):
self.setNumPies(numPies)
self.d_setNumPies(numPies)
def d_setNumPies(self, numPies):
self.sendUpdate('setNumPies', [numPies])
def setNumPies(self, numPies):
self.numPies = numPies
def b_setPieType(self, pieType):
self.setPieType(pieType)
self.d_setPieType(pieType)
def d_setPieType(self, pieType):
self.sendUpdate('setPieType', [pieType])
def setPieType(self, pieType):
self.pieType = pieType
def d_setTrophyScore(self, score):
self.sendUpdate('setTrophyScore', [score])
def stopToonUp(self):
taskMgr.remove(self.uniqueName('safeZoneToonUp'))
self.ignore(self.air.getAvatarExitEvent(self.getDoId()))
def startToonUp(self, healFrequency):
self.stopToonUp()
self.healFrequency = healFrequency
self.__waitForNextToonUp()
def __waitForNextToonUp(self):
taskMgr.doMethodLater(self.healFrequency, self.toonUpTask, self.uniqueName('safeZoneToonUp'))
def toonUpTask(self, task):
self.toonUp(1)
self.__waitForNextToonUp()
return Task.done
def toonUp(self, hpGained, quietly = 0, sendTotal = 1):
if hpGained > self.maxHp:
hpGained = self.maxHp
if not quietly:
self.sendUpdate('toonUp', [hpGained])
if self.hp + hpGained <= 0:
self.hp += hpGained
else:
self.hp = max(self.hp, 0) + hpGained
clampedHp = min(self.hp, self.maxHp)
if not self.hpOwnedByBattle:
self.hp = clampedHp
if sendTotal and not self.hpOwnedByBattle:
self.d_setHp(clampedHp)
def isToonedUp(self):
return self.hp >= self.maxHp
def makeBlackCat(self):
if self.dna.getAnimal() != 'cat':
return 'not a cat'
self.air.writeServerEvent('blackCat', self.doId, '')
newDna = ToonDNA.ToonDNA()
newDna.makeFromNetString(self.dna.makeNetString())
black = 26
newDna.updateToonProperties(armColor=black, legColor=black, headColor=black)
self.b_setDNAString(newDna.makeNetString())
return None
def b_announceBingo(self):
self.d_announceBingo()
self.announceBingo
def d_announceBingo(self):
self.sendUpdate('announceBingo', [])
def announceBingo(self):
pass
def incrementPopulation(self):
if self.isPlayerControlled():
DistributedPlayerAI.DistributedPlayerAI.incrementPopulation(self)
def decrementPopulation(self):
if self.isPlayerControlled():
DistributedPlayerAI.DistributedPlayerAI.decrementPopulation(self)
if __dev__:
def _logGarbage(self):
if self.isPlayerControlled():
DistributedPlayerAI.DistributedPlayerAI._logGarbage(self)
def reqSCResistance(self, msgIndex, nearbyPlayers):
self.d_setSCResistance(msgIndex, nearbyPlayers)
def d_setSCResistance(self, msgIndex, nearbyPlayers):
if not ResistanceChat.validateId(msgIndex):
self.air.writeServerEvent('suspicious', self.doId, 'said resistance %s, which is invalid.' % msgIndex)
return
if not self.removeResistanceMessage(msgIndex):
self.air.writeServerEvent('suspicious', self.doId, 'said resistance %s, but does not have it.' % msgIndex)
return
if hasattr(self, 'autoResistanceRestock') and self.autoResistanceRestock:
self.restockAllResistanceMessages(1)
affectedPlayers = []
for toonId in nearbyPlayers:
toon = self.air.doId2do.get(toonId)
if not toon:
self.notify.warning('%s said resistance %s for %s; not on server' % (self.doId, msgIndex, toonId))
elif toon.__class__ != DistributedToonAI:
self.air.writeServerEvent('suspicious', self.doId, 'said resistance %s for %s; object of type %s' % (msgIndex, toonId, toon.__class__.__name__))
elif toonId in affectedPlayers:
self.air.writeServerEvent('suspicious', self.doId, 'said resistance %s for %s twice in same message.' % (msgIndex, toonId))
else:
toon.doResistanceEffect(msgIndex)
affectedPlayers.append(toonId)
if len(affectedPlayers) > 50:
self.air.writeServerEvent('suspicious', self.doId, 'said resistance %s for %s toons.' % (msgIndex, len(affectedPlayers)))
self.notify.warning('%s said resistance %s for %s toons: %s' % (self.doId,
msgIndex,
len(affectedPlayers),
affectedPlayers))
self.sendUpdate('setSCResistance', [msgIndex, affectedPlayers])
type = ResistanceChat.getMenuName(msgIndex)
value = ResistanceChat.getItemValue(msgIndex)
self.air.writeServerEvent('resistanceChat', self.zoneId, '%s|%s|%s|%s' % (self.doId,
type,
value,
affectedPlayers))
def doResistanceEffect(self, msgIndex):
msgType, itemIndex = ResistanceChat.decodeId(msgIndex)
msgValue = ResistanceChat.getItemValue(msgIndex)
if msgType == ResistanceChat.RESISTANCE_TOONUP:
if msgValue == -1:
self.toonUp(self.maxHp)
else:
self.toonUp(msgValue)
self.notify.debug('Toon-up for ' + self.name)
elif msgType == ResistanceChat.RESISTANCE_RESTOCK:
self.inventory.NPCMaxOutInv(msgValue)
self.d_setInventory(self.inventory.makeNetString())
self.notify.debug('Restock for ' + self.name)
elif msgType == ResistanceChat.RESISTANCE_MONEY:
if msgValue == -1:
self.addMoney(999999)
else:
self.addMoney(msgValue)
self.notify.debug('Money for ' + self.name)
def squish(self, damage):
self.takeDamage(damage)
if simbase.wantKarts:
def hasKart(self):
return self.kartDNA[KartDNA.bodyType] != -1
def b_setTickets(self, numTickets):
if numTickets > RaceGlobals.MaxTickets:
numTickets = RaceGlobals.MaxTickets
self.d_setTickets(numTickets)
self.setTickets(numTickets)
def d_setTickets(self, numTickets):
if numTickets > RaceGlobals.MaxTickets:
numTickets = RaceGlobals.MaxTickets
self.sendUpdate('setTickets', [numTickets])
def setTickets(self, numTickets):
if numTickets > RaceGlobals.MaxTickets:
numTickets = RaceGlobals.MaxTickets
self.tickets = numTickets
def getTickets(self):
return self.tickets
def b_setKartingTrophies(self, trophyList):
self.setKartingTrophies(trophyList)
self.d_setKartingTrophies(trophyList)
def setKartingTrophies(self, trophyList):
self.notify.debug('setting kartingTrophies to %s' % trophyList)
self.kartingTrophies = trophyList
def d_setKartingTrophies(self, trophyList):
self.sendUpdate('setKartingTrophies', [trophyList])
def getKartingTrophies(self):
return self.kartingTrophies
def b_setKartingHistory(self, history):
self.setKartingHistory(history)
self.d_setKartingHistory(history)
def setKartingHistory(self, history):
self.notify.debug('setting kartingHistory to %s' % history)
self.kartingHistory = history
def d_setKartingHistory(self, history):
self.sendUpdate('setKartingHistory', [history])
def getKartingHistory(self):
return self.kartingHistory
def b_setKartingPersonalBest(self, bestTimes):
best1 = bestTimes[0:6]
best2 = bestTimes[6:]
self.setKartingPersonalBest(best1)
self.setKartingPersonalBest2(best2)
self.d_setKartingPersonalBest(bestTimes)
def d_setKartingPersonalBest(self, bestTimes):
best1 = bestTimes[0:6]
best2 = bestTimes[6:]
self.sendUpdate('setKartingPersonalBest', [best1])
self.sendUpdate('setKartingPersonalBest2', [best2])
def setKartingPersonalBest(self, bestTimes):
self.notify.debug('setting karting to %s' % bestTimes)
self.kartingPersonalBest = bestTimes
def setKartingPersonalBest2(self, bestTimes2):
self.notify.debug('setting karting2 to %s' % bestTimes2)
self.kartingPersonalBest2 = bestTimes2
def getKartingPersonalBest(self):
return self.kartingPersonalBest
def getKartingPersonalBest2(self):
return self.kartingPersonalBest2
def getKartingPersonalBestAll(self):
return self.kartingPersonalBest + self.kartingPersonalBest2
def setKartDNA(self, kartDNA):
self.b_setKartBodyType(kartDNA[KartDNA.bodyType])
self.b_setKartBodyColor(kartDNA[KartDNA.bodyColor])
self.b_setKartAccColor(kartDNA[KartDNA.accColor])
self.b_setKartEngineBlockType(kartDNA[KartDNA.ebType])
self.b_setKartSpoilerType(kartDNA[KartDNA.spType])
self.b_setKartFrontWheelWellType(kartDNA[KartDNA.fwwType])
self.b_setKartBackWheelWellType(kartDNA[KartDNA.bwwType])
self.b_setKartRimType(kartDNA[KartDNA.rimsType])
self.b_setKartDecalType(kartDNA[KartDNA.decalType])
def b_setKartBodyType(self, bodyType):
self.d_setKartBodyType(bodyType)
self.setKartBodyType(bodyType)
def d_setKartBodyType(self, bodyType):
self.sendUpdate('setKartBodyType', [bodyType])
def setKartBodyType(self, bodyType):
self.kartDNA[KartDNA.bodyType] = bodyType
def getKartBodyType(self):
return self.kartDNA[KartDNA.bodyType]
def b_setKartBodyColor(self, bodyColor):
self.d_setKartBodyColor(bodyColor)
self.setKartBodyColor(bodyColor)
def d_setKartBodyColor(self, bodyColor):
self.sendUpdate('setKartBodyColor', [bodyColor])
def setKartBodyColor(self, bodyColor):
self.kartDNA[KartDNA.bodyColor] = bodyColor
def getKartBodyColor(self):
return self.kartDNA[KartDNA.bodyColor]
def b_setKartAccessoryColor(self, accColor):
self.d_setKartAccessoryColor(accColor)
self.setKartAccessoryColor(accColor)
def d_setKartAccessoryColor(self, accColor):
self.sendUpdate('setKartAccessoryColor', [accColor])
def setKartAccessoryColor(self, accColor):
self.kartDNA[KartDNA.accColor] = accColor
def getKartAccessoryColor(self):
return self.kartDNA[KartDNA.accColor]
def b_setKartEngineBlockType(self, ebType):
self.d_setKartEngineBlockType(ebType)
self.setKartEngineBlockType(ebType)
def d_setKartEngineBlockType(self, ebType):
self.sendUpdate('setKartEngineBlockType', [ebType])
def setKartEngineBlockType(self, ebType):
self.kartDNA[KartDNA.ebType] = ebType
def getKartEngineBlockType(self):
return self.kartDNA[KartDNA.ebType]
def b_setKartSpoilerType(self, spType):
self.d_setKartSpoilerType(spType)
self.setKartSpoilerType(spType)
def d_setKartSpoilerType(self, spType):
self.sendUpdate('setKartSpoilerType', [spType])
def setKartSpoilerType(self, spType):
self.kartDNA[KartDNA.spType] = spType
def getKartSpoilerType(self):
return self.kartDNA[KartDNA.spType]
def b_setKartFrontWheelWellType(self, fwwType):
self.d_setKartFrontWheelWellType(fwwType)
self.setKartFrontWheelWellType(fwwType)
def d_setKartFrontWheelWellType(self, fwwType):
self.sendUpdate('setKartFrontWheelWellType', [fwwType])
def setKartFrontWheelWellType(self, fwwType):
self.kartDNA[KartDNA.fwwType] = fwwType
def getKartFrontWheelWellType(self):
return self.kartDNA[KartDNA.fwwType]
def b_setKartBackWheelWellType(self, bwwType):
self.d_setKartBackWheelWellType(bwwType)
self.setKartBackWheelWellType(bwwType)
def d_setKartBackWheelWellType(self, bwwType):
self.sendUpdate('setKartBackWheelWellType', [bwwType])
def setKartBackWheelWellType(self, bwwType):
self.kartDNA[KartDNA.bwwType] = bwwType
def getKartBackWheelWellType(self):
return self.kartDNA[KartDNA.bwwType]
def b_setKartRimType(self, rimsType):
self.d_setKartRimType(rimsType)
self.setKartRimType(rimsType)
def d_setKartRimType(self, rimsType):
self.sendUpdate('setKartRimType', [rimsType])
def setKartRimType(self, rimsType):
self.kartDNA[KartDNA.rimsType] = rimsType
def getKartRimType(self):
return self.kartDNA[KartDNA.rimsType]
def b_setKartDecalType(self, decalType):
self.d_setKartDecalType(decalType)
self.setKartDecalType(decalType)
def d_setKartDecalType(self, decalType):
self.sendUpdate('setKartDecalType', [decalType])
def setKartDecalType(self, decalType):
self.kartDNA[KartDNA.decalType] = decalType
def getKartDecalType(self):
return self.kartDNA[KartDNA.decalType]
def b_setKartAccessoriesOwned(self, accessories):
self.d_setKartAccessoriesOwned(accessories)
self.setKartAccessoriesOwned(accessories)
def d_setKartAccessoriesOwned(self, accessories):
self.sendUpdate('setKartAccessoriesOwned', [accessories])
def setKartAccessoriesOwned(self, accessories):
if (__debug__):
import pdb
self.accessories = accessories
def getKartAccessoriesOwned(self):
owned = copy.deepcopy(self.accessories)
while InvalidEntry in owned:
owned.remove(InvalidEntry)
return owned
def addOwnedAccessory(self, accessoryId):
print('in add owned accessory')
if accessoryId in AccessoryDict:
2019-11-02 17:27:54 -05:00
if self.accessories.count(accessoryId) > 0:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to add accessory %s which is already owned!' % accessoryId)
return
if self.accessories.count(InvalidEntry) > 0:
accList = list(self.accessories)
index = self.accessories.index(InvalidEntry)
accList[index] = accessoryId
self.b_setKartAccessoriesOwned(accList)
else:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to add accessory %s when accessory inventory is full!' % accessoryId)
return
else:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to add accessory %s which is not a valid accessory.' % accessoryId)
return
def removeOwnedAccessory(self, accessoryId):
if accessoryId in AccessoryDict:
2019-11-02 17:27:54 -05:00
if self.accessories.count(accessoryId) == 0:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to remove accessory %s which is not currently owned!' % accessoryId)
return
else:
accList = list(self.accessories)
index = self.accessories.index(accessoryId)
accList[index] = InvalidEntry
self.air.writeServerEvent('deletedKartingAccessory', self.doId, '%s' % accessoryId)
self.b_setKartAccessoriesOwned(accList)
else:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to remove accessory %s which is not a valid accessory.' % accessoryId)
return
def updateKartDNAField(self, dnaField, fieldValue):
if not checkKartFieldValidity(dnaField):
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update to dna value %s in the invalid field %s' % (fieldValue, dnaField))
return
if dnaField == KartDNA.bodyType:
if fieldValue not in list(KartDict.keys()) and fieldValue != InvalidEntry:
2019-11-02 17:27:54 -05:00
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update kart body to invalid body %s.' % fieldValue)
return
self.b_setKartBodyType(fieldValue)
else:
accFields = [KartDNA.ebType,
KartDNA.spType,
KartDNA.fwwType,
KartDNA.bwwType,
KartDNA.rimsType,
KartDNA.decalType]
colorFields = [KartDNA.bodyColor, KartDNA.accColor]
if dnaField in accFields:
if fieldValue == InvalidEntry:
self.__updateKartDNAField(dnaField, fieldValue)
else:
if fieldValue not in self.accessories:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update to accessory %s which is not currently owned.' % fieldValue)
return
field = getAccessoryType(fieldValue)
if field == InvalidEntry:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update accessory %s in an illegal field %s' % (fieldValue, field))
return
elif field != dnaField:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update accessory %s in a field %s that does not match client specified field %s' % (fieldValue, field, dnaField))
return
self.__updateKartDNAField(dnaField, fieldValue)
elif dnaField in colorFields:
if fieldValue == InvalidEntry:
self.__updateKartDNAField(dnaField, fieldValue)
else:
if fieldValue not in self.accessories:
if fieldValue != getDefaultColor():
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update to color %s which is not owned!' % fieldValue)
return
elif fieldValue == getDefaultColor() and self.kartDNA[dnaField] != InvalidEntry:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update to default color %s which is not owned!' % fieldValue)
return
if getAccessoryType(fieldValue) != KartDNA.bodyColor:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to update invalid color %s for dna field %s' % (fieldValue, dnaField))
return
self.__updateKartDNAField(dnaField, fieldValue)
else:
self.air.writeServerEvent('suspicious', self.doId, 'attempt to udpate accessory %s in the invalid field %s' % (fieldValue, dnaField))
return
def __updateKartDNAField(self, dnaField, fieldValue):
if dnaField == KartDNA.bodyColor:
self.b_setKartBodyColor(fieldValue)
elif dnaField == KartDNA.accColor:
self.b_setKartAccessoryColor(fieldValue)
elif dnaField == KartDNA.ebType:
self.b_setKartEngineBlockType(fieldValue)
elif dnaField == KartDNA.spType:
self.b_setKartSpoilerType(fieldValue)
elif dnaField == KartDNA.fwwType:
self.b_setKartFrontWheelWellType(fieldValue)
elif dnaField == KartDNA.bwwType:
self.b_setKartBackWheelWellType(fieldValue)
elif dnaField == KartDNA.rimsType:
self.b_setKartRimType(fieldValue)
elif dnaField == KartDNA.decalType:
self.b_setKartDecalType(fieldValue)
def setAllowSoloRace(self, allowSoloRace):
self.allowSoloRace = allowSoloRace
def setAllowRaceTimeout(self, allowRaceTimeout):
self.allowRaceTimeout = allowRaceTimeout
if simbase.wantPets:
def getPetId(self):
return self.petId
def b_setPetId(self, petId):
self.d_setPetId(petId)
self.setPetId(petId)
def d_setPetId(self, petId):
self.sendUpdate('setPetId', [petId])
def setPetId(self, petId):
self.petId = petId
def getPetTrickPhrases(self):
return self.petTrickPhrases
def b_setPetTrickPhrases(self, tricks):
self.setPetTrickPhrases(tricks)
self.d_setPetTrickPhrases(tricks)
def d_setPetTrickPhrases(self, tricks):
self.sendUpdate('setPetTrickPhrases', [tricks])
def setPetTrickPhrases(self, tricks):
self.petTrickPhrases = tricks
def deletePet(self):
if self.petId == 0:
self.notify.warning("this toon doesn't have a pet to delete!")
return
simbase.air.petMgr.deleteToonsPet(self.doId)
def setPetMovie(self, petId, flag):
self.notify.debug('setPetMovie: petId: %s, flag: %s' % (petId, flag))
pet = simbase.air.doId2do.get(petId)
if pet is not None:
if pet.__class__.__name__ == 'DistributedPetAI':
pet.handleAvPetInteraction(flag, self.getDoId())
else:
self.air.writeServerEvent('suspicious', self.doId, 'setPetMovie: playing pet movie %s on non-pet object %s' % (flag, petId))
return
def setPetTutorialDone(self, bDone):
self.notify.debug('setPetTutorialDone')
self.bPetTutorialDone = True
def setFishBingoTutorialDone(self, bDone):
self.notify.debug('setFishBingoTutorialDone')
self.bFishBingoTutorialDone = True
def setFishBingoMarkTutorialDone(self, bDone):
self.notify.debug('setFishBingoMarkTutorialDone')
self.bFishBingoMarkTutorialDone = True
def enterEstate(self, ownerId, zoneId):
DistributedToonAI.notify.debug('enterEstate: %s %s %s' % (self.doId, ownerId, zoneId))
if self.wasInEstate():
self.cleanupEstateData()
collSphere = CollisionSphere(0, 0, 0, self.getRadius())
collNode = CollisionNode('toonColl-%s' % self.doId)
collNode.addSolid(collSphere)
collNode.setFromCollideMask(BitMask32.allOff())
collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
self.collNodePath = self.attachNewNode(collNode)
taskMgr.add(self._moveSphere, self._getMoveSphereTaskName(), priority=OTPGlobals.AICollMovePriority)
self.inEstate = 1
self.estateOwnerId = ownerId
self.estateZones = simbase.air.estateMgr.getEstateZones(ownerId)
self.estateHouseZones = simbase.air.estateMgr.getEstateHouseZones(ownerId)
self.enterPetLook()
def _getPetLookerBodyNode(self):
return self.collNodePath
def _getMoveSphereTaskName(self):
return 'moveSphere-%s' % self.doId
def _moveSphere(self, task):
self.collNodePath.setZ(self.getRender(), 0)
return Task.cont
def isInEstate(self):
return hasattr(self, 'inEstate') and self.inEstate
def exitEstate(self, ownerId = None, zoneId = None):
DistributedToonAI.notify.debug('exitEstate: %s %s %s' % (self.doId, ownerId, zoneId))
DistributedToonAI.notify.debug('current zone: %s' % self.zoneId)
self.exitPetLook()
taskMgr.remove(self._getMoveSphereTaskName())
self.collNodePath.removeNode()
del self.collNodePath
del self.estateOwnerId
del self.estateHouseZones
del self.inEstate
self._wasInEstate = 1
def wasInEstate(self):
return hasattr(self, '_wasInEstate') and self._wasInEstate
def cleanupEstateData(self):
del self.estateZones
del self._wasInEstate
def setSC(self, msgId):
DistributedToonAI.notify.debug('setSC: %s' % msgId)
from toontown.pets import PetObserve
PetObserve.send(self.zoneId, PetObserve.getSCObserve(msgId, self.doId))
if msgId in [21006]:
self.setHatePets(1)
elif msgId in [21000,
21001,
21003,
21004,
21200,
21201,
21202,
21203,
21204,
21205,
21206]:
self.setHatePets(0)
def setSCCustom(self, msgId):
DistributedToonAI.notify.debug('setSCCustom: %s' % msgId)
from toontown.pets import PetObserve
PetObserve.send(self.zoneId, PetObserve.getSCObserve(msgId, self.doId))
def setHatePets(self, hate):
self.hatePets = hate
def takeOutKart(self, zoneId = None):
if not self.kart:
from toontown.racing import DistributedVehicleAI
self.kart = DistributedVehicleAI.DistributedVehicleAI(self.air, self.doId)
if zoneId:
self.kart.generateWithRequired(zoneId)
else:
self.kart.generateWithRequired(self.zoneId)
self.kart.start()
def reqCogSummons(self, type, suitIndex):
if type not in ('single', 'building', 'invasion'):
self.air.writeServerEvent('suspicious', self.doId, 'invalid cog summons type: %s' % type)
self.sendUpdate('cogSummonsResponse', ['fail', suitIndex, 0])
return
if suitIndex >= len(SuitDNA.suitHeadTypes):
self.air.writeServerEvent('suspicious', self.doId, 'invalid suitIndex: %s' % suitIndex)
self.sendUpdate('cogSummonsResponse', ['fail', suitIndex, 0])
return
if not self.hasCogSummons(suitIndex, type):
self.air.writeServerEvent('suspicious', self.doId, 'bogus cog summons')
self.sendUpdate('cogSummonsResponse', ['fail', suitIndex, 0])
return
if ZoneUtil.isWelcomeValley(self.zoneId):
self.sendUpdate('cogSummonsResponse', ['fail', suitIndex, 0])
return
returnCode = None
if type == 'single':
returnCode = self.doSummonSingleCog(suitIndex)
elif type == 'building':
returnCode = self.doBuildingTakeover(suitIndex)
elif type == 'invasion':
returnCode = self.doCogInvasion(suitIndex)
if returnCode:
if returnCode[0] == 'success':
self.air.writeServerEvent('cogSummoned', self.doId, '%s|%s|%s' % (type, suitIndex, self.zoneId))
self.removeCogSummonsEarned(suitIndex, type)
self.sendUpdate('cogSummonsResponse', returnCode)
return
def doSummonSingleCog(self, suitIndex):
if suitIndex >= len(SuitDNA.suitHeadTypes):
self.notify.warning('Bad suit index: %s' % suitIndex)
return ['badIndex', suitIndex, 0]
suitName = SuitDNA.suitHeadTypes[suitIndex]
streetId = ZoneUtil.getBranchZone(self.zoneId)
if streetId not in self.air.suitPlanners:
2019-11-02 17:27:54 -05:00
return ['badlocation', suitIndex, 0]
sp = self.air.suitPlanners[streetId]
map = sp.getZoneIdToPointMap()
zones = [self.zoneId, self.zoneId - 1, self.zoneId + 1]
for zoneId in zones:
if zoneId in map:
2019-11-02 17:27:54 -05:00
points = map[zoneId][:]
suit = sp.createNewSuit([], points, suitName=suitName)
if suit:
return ['success', suitIndex, 0]
return ['badlocation', suitIndex, 0]
def doBuildingTakeover(self, suitIndex):
streetId = ZoneUtil.getBranchZone(self.zoneId)
if streetId not in self.air.suitPlanners:
2019-11-02 17:27:54 -05:00
self.notify.warning('Street %d is not known.' % streetId)
return ['badlocation', suitIndex, 0]
sp = self.air.suitPlanners[streetId]
bm = sp.buildingMgr
building = self.findClosestDoor()
if building == None:
return ['badlocation', suitIndex, 0]
level = None
if suitIndex >= len(SuitDNA.suitHeadTypes):
self.notify.warning('Bad suit index: %s' % suitIndex)
return ['badIndex', suitIndex, 0]
suitName = SuitDNA.suitHeadTypes[suitIndex]
track = SuitDNA.getSuitDept(suitName)
type = SuitDNA.getSuitType(suitName)
level, type, track = sp.pickLevelTypeAndTrack(None, type, track)
building.suitTakeOver(track, level, None)
self.notify.warning('cogTakeOver %s %s %d %d' % (track,
level,
building.block,
self.zoneId))
return ['success', suitIndex, building.doId]
def doCogInvasion(self, suitIndex):
invMgr = self.air.suitInvasionManager
if invMgr.getInvading():
returnCode = 'busy'
else:
if suitIndex >= len(SuitDNA.suitHeadTypes):
self.notify.warning('Bad suit index: %s' % suitIndex)
return ['badIndex', suitIndex, 0]
cogType = SuitDNA.suitHeadTypes[suitIndex]
numCogs = 1000
if invMgr.startInvasion(cogType, numCogs, False):
returnCode = 'success'
else:
returnCode = 'fail'
return [returnCode, suitIndex, 0]
def b_setCogSummonsEarned(self, cogSummonsEarned):
self.d_setCogSummonsEarned(cogSummonsEarned)
self.setCogSummonsEarned(cogSummonsEarned)
def d_setCogSummonsEarned(self, cogSummonsEarned):
self.sendUpdate('setCogSummonsEarned', [cogSummonsEarned])
def setCogSummonsEarned(self, cogSummonsEarned):
self.cogSummonsEarned = cogSummonsEarned
def getCogSummonsEarned(self):
return self.cogSummonsEarned
def restockAllCogSummons(self):
numSuits = len(SuitDNA.suitHeadTypes)
fullSetForSuit = 1 | 2 | 4
allSummons = numSuits * [fullSetForSuit]
self.b_setCogSummonsEarned(allSummons)
def addCogSummonsEarned(self, suitIndex, type):
summons = self.getCogSummonsEarned()
curSetting = summons[suitIndex]
if type == 'single':
curSetting |= 1
elif type == 'building':
curSetting |= 2
elif type == 'invasion':
curSetting |= 4
summons[suitIndex] = curSetting
self.b_setCogSummonsEarned(summons)
def removeCogSummonsEarned(self, suitIndex, type):
summons = self.getCogSummonsEarned()
curSetting = summons[suitIndex]
if self.hasCogSummons(suitIndex, type):
if type == 'single':
curSetting &= -2
elif type == 'building':
curSetting &= -3
elif type == 'invasion':
curSetting &= -5
summons[suitIndex] = curSetting
self.b_setCogSummonsEarned(summons)
if hasattr(self, 'autoRestockSummons') and self.autoRestockSummons:
self.restockAllCogSummons()
return True
self.notify.warning("Toon %s doesn't have a %s summons for %s" % (self.doId, type, suitIndex))
return False
def hasCogSummons(self, suitIndex, type = None):
summons = self.getCogSummonsEarned()
curSetting = summons[suitIndex]
if type == 'single':
return curSetting & 1
elif type == 'building':
return curSetting & 2
elif type == 'invasion':
return curSetting & 4
return curSetting
def hasParticularCogSummons(self, deptIndex, level, type):
if deptIndex not in list(range(len(SuitDNA.suitDepts))):
2019-11-02 17:27:54 -05:00
self.notify.warning('invalid parameter deptIndex %s' % deptIndex)
return False
if level not in list(range(SuitDNA.suitsPerDept)):
2019-11-02 17:27:54 -05:00
self.notify.warning('invalid parameter level %s' % level)
return False
suitIndex = deptIndex * SuitDNA.suitsPerDept + level
retval = self.hasCogSummons(suitIndex, type)
return retval
def assignNewCogSummons(self, level = None, summonType = None, deptIndex = None):
if level != None:
if deptIndex in range(len(SuitDNA.suitDepts)):
dept = deptIndex
else:
numDepts = len(SuitDNA.suitDepts)
dept = random.randrange(0, numDepts)
suitIndex = dept * SuitDNA.suitsPerDept + level
elif deptIndex in range(len(SuitDNA.suitDepts)):
randomLevel = random.randrange(0, SuitDNA.suitsPerDept)
suitIndex = deptIndex * SuitDNA.suitsPerLevel + randomLevel
else:
numSuits = len(SuitDNA.suitHeadTypes)
suitIndex = random.randrange(0, numSuits)
if summonType in ['single', 'building', 'invasion']:
type = summonType
else:
typeWeights = ['single'] * 70 + ['building'] * 25 + ['invasion'] * 5
type = random.choice(typeWeights)
if suitIndex >= len(SuitDNA.suitHeadTypes):
self.notify.warning('Bad suit index: %s' % suitIndex)
self.addCogSummonsEarned(suitIndex, type)
return (suitIndex, type)
def findClosestDoor(self):
zoneId = self.zoneId
streetId = ZoneUtil.getBranchZone(zoneId)
sp = self.air.suitPlanners[streetId]
if not sp:
return None
bm = sp.buildingMgr
if not bm:
return None
zones = [zoneId,
zoneId - 1,
zoneId + 1,
zoneId - 2,
zoneId + 2]
for zone in zones:
for i in bm.getToonBlocks():
building = bm.getBuilding(i)
extZoneId, intZoneId = building.getExteriorAndInteriorZoneId()
if not NPCToons.isZoneProtected(intZoneId):
if hasattr(building, 'door'):
if building.door.zoneId == zone:
return building
return None
def b_setGardenTrophies(self, trophyList):
self.setGardenTrophies(trophyList)
self.d_setGardenTrophies(trophyList)
def setGardenTrophies(self, trophyList):
self.notify.debug('setting gardenTrophies to %s' % trophyList)
self.gardenTrophies = trophyList
def d_setGardenTrophies(self, trophyList):
self.sendUpdate('setGardenTrophies', [trophyList])
def getGardenTrophies(self):
return self.gardenTrophies
def setGardenSpecials(self, specials):
for special in specials:
if special[1] > 255:
special[1] = 255
self.gardenSpecials = specials
def getGardenSpecials(self):
return self.gardenSpecials
def d_setGardenSpecials(self, specials):
self.sendUpdate('setGardenSpecials', [specials])
def b_setGardenSpecials(self, specials):
for special in specials:
if special[1] > 255:
newCount = 255
index = special[0]
self.gardenSpecials.remove(special)
self.gardenSpecials.append((index, newCount))
self.gardenSpecials.sort()
self.setGardenSpecials(specials)
self.d_setGardenSpecials(specials)
def addGardenItem(self, index, count):
for item in self.gardenSpecials:
if item[0] == index:
newCount = item[1] + count
self.gardenSpecials.remove(item)
self.gardenSpecials.append((index, newCount))
self.gardenSpecials.sort()
self.b_setGardenSpecials(self.gardenSpecials)
return
self.gardenSpecials.append((index, count))
self.gardenSpecials.sort()
self.b_setGardenSpecials(self.gardenSpecials)
def removeGardenItem(self, index, count):
for item in self.gardenSpecials:
if item[0] == index:
newCount = item[1] - count
self.gardenSpecials.remove(item)
if newCount > 0:
self.gardenSpecials.append((index, newCount))
self.gardenSpecials.sort()
self.b_setGardenSpecials(self.gardenSpecials)
return
self.notify.warning("removing garden item %d that toon doesn't have" % index)
def b_setFlowerCollection(self, speciesList, varietyList):
self.setFlowerCollection(speciesList, varietyList)
self.d_setFlowerCollection(speciesList, varietyList)
def d_setFlowerCollection(self, speciesList, varietyList):
self.sendUpdate('setFlowerCollection', [speciesList, varietyList])
def setFlowerCollection(self, speciesList, varietyList):
self.flowerCollection = FlowerCollection.FlowerCollection()
self.flowerCollection.makeFromNetLists(speciesList, varietyList)
def getFlowerCollection(self):
return self.flowerCollection.getNetLists()
def b_setMaxFlowerBasket(self, maxFlowerBasket):
self.d_setMaxFlowerBasket(maxFlowerBasket)
self.setMaxFlowerBasket(maxFlowerBasket)
def d_setMaxFlowerBasket(self, maxFlowerBasket):
self.sendUpdate('setMaxFlowerBasket', [maxFlowerBasket])
def setMaxFlowerBasket(self, maxFlowerBasket):
self.maxFlowerBasket = maxFlowerBasket
def getMaxFlowerBasket(self):
return self.maxFlowerBasket
def b_setFlowerBasket(self, speciesList, varietyList):
self.setFlowerBasket(speciesList, varietyList)
self.d_setFlowerBasket(speciesList, varietyList)
def d_setFlowerBasket(self, speciesList, varietyList):
self.sendUpdate('setFlowerBasket', [speciesList, varietyList])
def setFlowerBasket(self, speciesList, varietyList):
self.flowerBasket = FlowerBasket.FlowerBasket()
self.flowerBasket.makeFromNetLists(speciesList, varietyList)
def getFlowerBasket(self):
return self.flowerBasket.getNetLists()
def makeRandomFlowerBasket(self):
self.flowerBasket.generateRandomBasket()
self.d_setFlowerBasket(*self.flowerBasket.getNetLists())
def addFlowerToBasket(self, species, variety):
numFlower = len(self.flowerBasket)
if numFlower >= self.maxFlowerBasket:
self.notify.warning('addFlowerToBasket: cannot add flower, basket is full')
return 0
elif self.flowerBasket.addFlower(species, variety):
self.d_setFlowerBasket(*self.flowerBasket.getNetLists())
return 1
else:
self.notify.warning('addFlowerToBasket: addFlower failed')
return 0
def removeFlowerFromBasketAtIndex(self, index):
if self.flowerBasket.removeFlowerAtIndex(index):
self.d_setFlowerBasket(*self.flowerBasket.getNetLists())
return 1
else:
self.notify.warning('removeFishFromTank: cannot find fish')
return 0
def b_setShovel(self, shovelId):
self.d_setShovel(shovelId)
self.setShovel(shovelId)
def d_setShovel(self, shovelId):
self.sendUpdate('setShovel', [shovelId])
def setShovel(self, shovelId):
self.shovel = shovelId
def getShovel(self):
return self.shovel
def b_setShovelSkill(self, skillLevel):
self.sendGardenEvent()
if skillLevel >= GardenGlobals.ShovelAttributes[self.shovel]['skillPts']:
if self.shovel < GardenGlobals.MAX_SHOVELS - 1:
self.b_setShovel(self.shovel + 1)
self.setShovelSkill(0)
self.d_setShovelSkill(0)
self.sendUpdate('promoteShovel', [self.shovel])
self.air.writeServerEvent('garden_new_shovel', self.doId, '%d' % self.shovel)
else:
self.setShovelSkill(skillLevel)
self.d_setShovelSkill(skillLevel)
def d_setShovelSkill(self, skillLevel):
self.sendUpdate('setShovelSkill', [skillLevel])
def setShovelSkill(self, skillLevel):
self.shovelSkill = skillLevel
def getShovelSkill(self):
return self.shovelSkill
def b_setWateringCan(self, wateringCanId):
self.d_setWateringCan(wateringCanId)
self.setWateringCan(wateringCanId)
def d_setWateringCan(self, wateringCanId):
self.sendUpdate('setWateringCan', [wateringCanId])
def setWateringCan(self, wateringCanId):
self.wateringCan = wateringCanId
def getWateringCan(self):
return self.wateringCan
def b_setWateringCanSkill(self, skillLevel):
self.sendGardenEvent()
if skillLevel >= GardenGlobals.WateringCanAttributes[self.wateringCan]['skillPts']:
if self.wateringCan < GardenGlobals.MAX_WATERING_CANS - 1:
self.b_setWateringCan(self.wateringCan + 1)
self.setWateringCanSkill(0)
self.d_setWateringCanSkill(0)
self.sendUpdate('promoteWateringCan', [self.wateringCan])
self.air.writeServerEvent('garden_new_wateringCan', self.doId, '%d' % self.wateringCan)
else:
skillLevel = GardenGlobals.WateringCanAttributes[self.wateringCan]['skillPts'] - 1
self.setWateringCanSkill(skillLevel)
self.d_setWateringCanSkill(skillLevel)
else:
self.setWateringCanSkill(skillLevel)
self.d_setWateringCanSkill(skillLevel)
def d_setWateringCanSkill(self, skillLevel):
self.sendUpdate('setWateringCanSkill', [skillLevel])
def setWateringCanSkill(self, skillLevel):
self.wateringCanSkill = skillLevel
def getWateringCanSkill(self):
return self.wateringCanSkill
def b_setTrackBonusLevel(self, trackBonusLevelArray):
self.setTrackBonusLevel(trackBonusLevelArray)
self.d_setTrackBonusLevel(trackBonusLevelArray)
def d_setTrackBonusLevel(self, trackBonusLevelArray):
self.sendUpdate('setTrackBonusLevel', [trackBonusLevelArray])
def setTrackBonusLevel(self, trackBonusLevelArray):
self.trackBonusLevel = trackBonusLevelArray
def getTrackBonusLevel(self, track = None):
if track == None:
return self.trackBonusLevel
else:
return self.trackBonusLevel[track]
return
def checkGagBonus(self, track, level):
trackBonus = self.getTrackBonusLevel(track)
return trackBonus >= level
def giveMeSpecials(self, id = None):
print('Specials Go!!')
2019-11-02 17:27:54 -05:00
self.b_setGardenSpecials([(0, 3),
(1, 2),
(2, 3),
(3, 2),
(4, 3),
(5, 2),
(6, 3),
(7, 2),
(100, 1),
(101, 3),
(102, 1)])
def reqUseSpecial(self, special):
response = self.tryToUseSpecial(special)
self.sendUpdate('useSpecialResponse', [response])
def tryToUseSpecial(self, special):
estateOwnerDoId = simbase.air.estateMgr.zone2owner.get(self.zoneId)
response = 'badlocation'
doIHaveThisSpecial = False
for curSpecial in self.gardenSpecials:
if curSpecial[0] == special and curSpecial[1] > 0:
doIHaveThisSpecial = True
break
if not doIHaveThisSpecial:
return response
if not self.doId == estateOwnerDoId:
self.notify.warning("how did this happen, planting an item you don't own")
return response
if estateOwnerDoId:
estate = simbase.air.estateMgr.estate.get(estateOwnerDoId)
if estate and hasattr(estate, 'avIdList'):
ownerIndex = estate.avIdList.index(estateOwnerDoId)
if ownerIndex >= 0:
estate.doEpochNow(onlyForThisToonIndex=ownerIndex)
self.removeGardenItem(special, 1)
response = 'success'
self.air.writeServerEvent('garden_fertilizer', self.doId, '')
return response
def sendGardenEvent(self):
if hasattr(self, 'estateZones') and hasattr(self, 'doId'):
if simbase.wantPets and self.hatePets:
PetObserve.send(self.estateZones, PetObserve.PetActionObserve(PetObserve.Actions.GARDEN, self.doId))
def setGardenStarted(self, bStarted):
self.gardenStarted = bStarted
def d_setGardenStarted(self, bStarted):
self.sendUpdate('setGardenStarted', [bStarted])
def b_setGardenStarted(self, bStarted):
self.setGardenStarted(bStarted)
self.d_setGardenStarted(bStarted)
def getGardenStarted(self):
return self.gardenStarted
def logSuspiciousEvent(self, eventName):
senderId = self.air.getAvatarIdFromSender()
eventStr = 'senderId=%s ' % senderId
eventStr += eventName
strSearch = re.compile('AvatarHackWarning! nodename')
if strSearch.search(eventName, 0, 100):
self.air.district.recordSuspiciousEventData(len(eventStr))
self.air.writeServerEvent('suspicious', self.doId, eventStr)
if simbase.config.GetBool('want-ban-setSCSinging', True):
if 'invalid msgIndex in setSCSinging:' in eventName:
if senderId == self.doId:
commentStr = 'Toon %s trying to call setSCSinging' % self.doId
simbase.air.banManager.ban(self.doId, self.DISLid, commentStr)
else:
self.notify.warning('logSuspiciousEvent event=%s senderId=%s != self.doId=%s' % (eventName, senderId, self.doId))
if simbase.config.GetBool('want-ban-setAnimState', True):
if eventName.startswith('setAnimState: '):
if senderId == self.doId:
commentStr = 'Toon %s trying to call setAnimState' % self.doId
simbase.air.banManager.ban(self.doId, self.DISLid, commentStr)
else:
self.notify.warning('logSuspiciousEvent event=%s senderId=%s != self.doId=%s' % (eventName, senderId, self.doId))
def getGolfTrophies(self):
return self.golfTrophies
def getGolfCups(self):
return self.golfCups
def b_setGolfHistory(self, history):
self.setGolfHistory(history)
self.d_setGolfHistory(history)
def d_setGolfHistory(self, history):
self.sendUpdate('setGolfHistory', [history])
def setGolfHistory(self, history):
self.notify.debug('setting golfHistory to %s' % history)
self.golfHistory = history
self.golfTrophies = GolfGlobals.calcTrophyListFromHistory(self.golfHistory)
self.golfCups = GolfGlobals.calcCupListFromHistory(self.golfHistory)
def getGolfHistory(self):
return self.golfHistory
def b_setGolfHoleBest(self, holeBest):
self.setGolfHoleBest(holeBest)
self.d_setGolfHoleBest(holeBest)
def d_setGolfHoleBest(self, holeBest):
packed = GolfGlobals.packGolfHoleBest(holeBest)
self.sendUpdate('setPackedGolfHoleBest', [packed])
def setGolfHoleBest(self, holeBest):
self.golfHoleBest = holeBest
def getGolfHoleBest(self):
return self.golfHoleBest
def getPackedGolfHoleBest(self):
packed = GolfGlobals.packGolfHoleBest(self.golfHoleBest)
return packed
def setPackedGolfHoleBest(self, packedHoleBest):
unpacked = GolfGlobals.unpackGolfHoleBest(packedHoleBest)
self.setGolfHoleBest(unpacked)
def b_setGolfCourseBest(self, courseBest):
self.setGolfCourseBest(courseBest)
self.d_setGolfCourseBest(courseBest)
def d_setGolfCourseBest(self, courseBest):
self.sendUpdate('setGolfCourseBest', [courseBest])
def setGolfCourseBest(self, courseBest):
self.golfCourseBest = courseBest
def getGolfCourseBest(self):
return self.golfCourseBest
def setUnlimitedSwing(self, unlimitedSwing):
self.unlimitedSwing = unlimitedSwing
def getUnlimitedSwing(self):
return self.unlimitedSwing
def b_setUnlimitedSwing(self, unlimitedSwing):
self.setUnlimitedSwing(unlimitedSwing)
self.d_setUnlimitedSwing(unlimitedSwing)
def d_setUnlimitedSwing(self, unlimitedSwing):
self.sendUpdate('setUnlimitedSwing', [unlimitedSwing])
def b_setPinkSlips(self, pinkSlips):
self.d_setPinkSlips(pinkSlips)
self.setPinkSlips(pinkSlips)
def d_setPinkSlips(self, pinkSlips):
self.sendUpdate('setPinkSlips', [pinkSlips])
def setPinkSlips(self, pinkSlips):
self.pinkSlips = pinkSlips
def getPinkSlips(self):
return self.pinkSlips
def addPinkSlips(self, amountToAdd):
pinkSlips = min(self.pinkSlips + amountToAdd, 255)
self.b_setPinkSlips(pinkSlips)
def removePinkSlips(self, amount):
if hasattr(self, 'autoRestockPinkSlips') and self.autoRestockPinkSlips:
amount = 0
pinkSlips = max(self.pinkSlips - amount, 0)
self.b_setPinkSlips(pinkSlips)
def setPreviousAccess(self, access):
self.previousAccess = access
def b_setAccess(self, access):
self.setAccess(access)
self.d_setAccess(access)
def d_setAccess(self, access):
self.sendUpdate('setAccess', [access])
def setAccess(self, access):
paidStatus = simbase.config.GetString('force-paid-status', 'none')
if paidStatus == 'unpaid':
access = 1
print('Setting Access %s' % access)
2019-11-02 17:27:54 -05:00
if access == OTPGlobals.AccessInvalid:
if not __dev__:
self.air.writeServerEvent('Setting Access', self.doId, 'setAccess not being sent by the OTP Server, changing access to unpaid')
access = OTPGlobals.AccessVelvetRope
elif __dev__:
access = OTPGlobals.AccessFull
self.setGameAccess(access)
def setGameAccess(self, access):
self.gameAccess = access
def getGameAccess(self):
return self.gameAccess
def b_setNametagStyle(self, nametagStyle):
self.d_setNametagStyle(nametagStyle)
self.setNametagStyle(nametagStyle)
def d_setNametagStyle(self, nametagStyle):
self.sendUpdate('setNametagStyle', [nametagStyle])
def setNametagStyle(self, nametagStyle):
self.nametagStyle = nametagStyle
def getNametagStyle(self):
return self.nametagStyle
def logMessage(self, message):
avId = self.air.getAvatarIdFromSender()
if __dev__:
print('CLIENT LOG MESSAGE %s %s' % (avId, message))
2019-11-02 17:27:54 -05:00
try:
self.air.writeServerEvent('clientLog', avId, message)
except:
self.air.writeServerEvent('suspicious', avId, 'client sent us a clientLog that caused an exception')
def b_setMail(self, mail):
self.d_setMail(mail)
self.setMail(mail)
def d_setMail(self, mail):
self.sendUpdate('setMail', [mail])
def setMail(self, mail):
self.mail = mail
def setNumMailItems(self, numMailItems):
self.numMailItems = numMailItems
def setSimpleMailNotify(self, simpleMailNotify):
self.simpleMailNotify = simpleMailNotify
def setInviteMailNotify(self, inviteMailNotify):
self.inviteMailNotify = inviteMailNotify
def setInvites(self, invites):
self.invites = []
for i in range(len(invites)):
2019-11-02 17:27:54 -05:00
oneInvite = invites[i]
newInvite = InviteInfoBase(*oneInvite)
self.invites.append(newInvite)
def updateInviteMailNotify(self):
invitesInMailbox = self.getInvitesToShowInMailbox()
newInvites = 0
readButNotRepliedInvites = 0
for invite in invitesInMailbox:
if invite.status == PartyGlobals.InviteStatus.NotRead:
newInvites += 1
elif invite.status == PartyGlobals.InviteStatus.ReadButNotReplied:
readButNotRepliedInvites += 1
if __dev__:
partyInfo = self.getOnePartyInvitedTo(invite.partyId)
if not partyInfo:
self.notify.error('party info not found in partiesInvtedTo, partyId = %s' % str(invite.partyId))
if newInvites:
self.setInviteMailNotify(ToontownGlobals.NewItems)
elif readButNotRepliedInvites:
self.setInviteMailNotify(ToontownGlobals.OldItems)
else:
self.setInviteMailNotify(ToontownGlobals.NoItems)
def getNumNonResponseInvites(self):
count = 0
for i in range(len(self.invites)):
2019-11-02 17:27:54 -05:00
if self.invites[i].status == InviteStatus.NotRead or self.invites[i].status == InviteStatus.ReadButNotReplied:
count += 1
return count
def getInvitesToShowInMailbox(self):
result = []
for invite in self.invites:
appendInvite = True
if invite.status == InviteStatus.Accepted or invite.status == InviteStatus.Rejected:
appendInvite = False
if appendInvite:
partyInfo = self.getOnePartyInvitedTo(invite.partyId)
if not partyInfo:
appendInvite = False
if appendInvite:
if partyInfo.status == PartyGlobals.PartyStatus.Cancelled:
appendInvite = False
if appendInvite:
endDate = partyInfo.endTime.date()
curDate = simbase.air.toontownTimeManager.getCurServerDateTime().date()
if endDate < curDate:
appendInvite = False
if appendInvite:
result.append(invite)
return result
def getNumInvitesToShowInMailbox(self):
result = len(self.getInvitesToShowInMailbox())
return result
def setHostedParties(self, hostedParties):
self.hostedParties = []
for i in range(len(hostedParties)):
2019-11-02 17:27:54 -05:00
hostedInfo = hostedParties[i]
newParty = PartyInfoAI(*hostedInfo)
self.hostedParties.append(newParty)
def setPartiesInvitedTo(self, partiesInvitedTo):
self.partiesInvitedTo = []
for i in range(len(partiesInvitedTo)):
2019-11-02 17:27:54 -05:00
partyInfo = partiesInvitedTo[i]
newParty = PartyInfoAI(*partyInfo)
self.partiesInvitedTo.append(newParty)
self.updateInviteMailNotify()
self.checkMailboxFullIndicator()
def getOnePartyInvitedTo(self, partyId):
result = None
for i in range(len(self.partiesInvitedTo)):
2019-11-02 17:27:54 -05:00
partyInfo = self.partiesInvitedTo[i]
if partyInfo.partyId == partyId:
result = partyInfo
break
return result
def setPartyReplyInfoBases(self, replies):
self.partyReplyInfoBases = []
for i in range(len(replies)):
2019-11-02 17:27:54 -05:00
partyReply = replies[i]
repliesForOneParty = PartyReplyInfoBase(*partyReply)
self.partyReplyInfoBases.append(repliesForOneParty)
def updateInvite(self, inviteKey, newStatus):
for invite in self.invites:
if invite.inviteKey == inviteKey:
invite.status = newStatus
self.updateInviteMailNotify()
self.checkMailboxFullIndicator()
break
def updateReply(self, partyId, inviteeId, newStatus):
for partyReply in self.partyReplyInfoBases:
if partyReply.partyId == partyId:
for reply in partyReply.replies:
if reply.inviteeId == inviteeId:
reply.inviteeId = newStatus
break
def canPlanParty(self):
nonCancelledPartiesInTheFuture = 0
for partyInfo in self.hostedParties:
if partyInfo.status not in (PartyGlobals.PartyStatus.Cancelled, PartyGlobals.PartyStatus.Finished, PartyGlobals.PartyStatus.NeverStarted):
nonCancelledPartiesInTheFuture += 1
if nonCancelledPartiesInTheFuture >= PartyGlobals.MaxHostedPartiesPerToon:
break
result = nonCancelledPartiesInTheFuture < PartyGlobals.MaxHostedPartiesPerToon
return result
def setPartyCanStart(self, partyId):
self.notify.debug('setPartyCanStart called passing in partyId=%s' % partyId)
found = False
for partyInfo in self.hostedParties:
if partyInfo.partyId == partyId:
partyInfo.status = PartyGlobals.PartyStatus.CanStart
found = True
break
if not found:
self.notify.warning("setPartyCanStart can't find partyId %s" % partyId)
def setPartyStatus(self, partyId, newStatus):
self.notify.debug('setPartyStatus called passing in partyId=%s newStauts=%d' % (partyId, newStatus))
found = False
for partyInfo in self.hostedParties:
if partyInfo.partyId == partyId:
partyInfo.status = newStatus
found = True
break
info = self.getOnePartyInvitedTo(partyId)
if info:
found = True
info.status = newStatus
if not found:
self.notify.warning("setPartyCanStart can't find hosted or invitedTO partyId %s" % partyId)
def b_setAwardMailboxContents(self, awardMailboxContents):
self.setAwardMailboxContents(awardMailboxContents)
self.d_setAwardMailboxContents(awardMailboxContents)
def d_setAwardMailboxContents(self, awardMailboxContents):
self.sendUpdate('setAwardMailboxContents', [awardMailboxContents.getBlob(store=CatalogItem.Customization)])
def setAwardMailboxContents(self, awardMailboxContents):
self.notify.debug('Setting awardMailboxContents to %s.' % awardMailboxContents)
self.awardMailboxContents = CatalogItemList.CatalogItemList(awardMailboxContents, store=CatalogItem.Customization)
self.notify.debug('awardMailboxContents is %s.' % self.awardMailboxContents)
if len(awardMailboxContents) == 0:
self.b_setAwardNotify(ToontownGlobals.NoItems)
self.checkMailboxFullIndicator()
def getAwardMailboxContents(self):
return self.awardMailboxContents.getBlob(store=CatalogItem.Customization)
def b_setAwardSchedule(self, onOrder, doUpdateLater = True):
self.setAwardSchedule(onOrder, doUpdateLater)
self.d_setAwardSchedule(onOrder)
def d_setAwardSchedule(self, onOrder):
self.sendUpdate('setAwardSchedule', [onOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate)])
def setAwardSchedule(self, onAwardOrder, doUpdateLater = True):
self.onAwardOrder = CatalogItemList.CatalogItemList(onAwardOrder, store=CatalogItem.Customization | CatalogItem.DeliveryDate)
if hasattr(self, 'name'):
if doUpdateLater and self.air.doLiveUpdates and hasattr(self, 'air'):
taskName = self.uniqueName('next-award-delivery')
taskMgr.remove(taskName)
now = int(time.time() / 60 + 0.5)
nextItem = None
nextTime = self.onAwardOrder.getNextDeliveryDate()
nextItem = self.onAwardOrder.getNextDeliveryItem()
if nextItem != None:
pass
if nextTime != None:
duration = max(10.0, nextTime * 60 - time.time())
taskMgr.doMethodLater(duration, self.__deliverAwardPurchase, taskName)
return
def __deliverAwardPurchase(self, task):
now = int(time.time() / 60 + 0.5)
delivered, remaining = self.onAwardOrder.extractDeliveryItems(now)
self.notify.info('Award Delivery for %s: %s.' % (self.doId, delivered))
self.b_setAwardMailboxContents(self.awardMailboxContents + delivered)
self.b_setAwardSchedule(remaining)
if delivered:
self.b_setAwardNotify(ToontownGlobals.NewItems)
return Task.done
def b_setAwardNotify(self, awardMailboxNotify):
self.setAwardNotify(awardMailboxNotify)
self.d_setAwardNotify(awardMailboxNotify)
def d_setAwardNotify(self, awardMailboxNotify):
self.sendUpdate('setAwardNotify', [awardMailboxNotify])
def setAwardNotify(self, awardNotify):
self.awardNotify = awardNotify
def b_setGM(self, type):
self.sendUpdate('setGM', [type])
self.setGM(type)
def setGM(self, type):
wasGM = self._isGM
formerType = self._gmType
self._isGM = type != 0
self._gmType = None
if self._isGM:
self._gmType = type - 1
MaxGMType = len(TTLocalizer.GM_NAMES) - 1
if self._gmType > MaxGMType:
self.notify.warning('toon %s has invalid GM type: %s' % (self.doId, self._gmType))
self._gmType = MaxGMType
self._updateGMName(formerType)
return
def isGM(self):
return self._isGM
def _nameIsPrefixed(self, prefix):
if len(self.name) > len(prefix):
if self.name[:len(prefix)] == prefix:
return True
return False
def _updateGMName(self, formerType = None):
if formerType is None:
formerType = self._gmType
name = self.name
if formerType is not None:
gmPrefix = TTLocalizer.GM_NAMES[formerType] + ' '
if self._nameIsPrefixed(gmPrefix):
name = self.name[len(gmPrefix):]
if self._isGM:
gmPrefix = TTLocalizer.GM_NAMES[self._gmType] + ' '
newName = gmPrefix + name
else:
newName = name
if self.name != newName:
self.b_setName(newName)
return
def setName(self, name):
DistributedPlayerAI.DistributedPlayerAI.setName(self, name)
if self.WantOldGMNameBan:
if self.isGenerated():
self._checkOldGMName()
self._updateGMName()
def _checkOldGMName(self):
if '$' in set(self.name):
if config.GetBool('want-ban-old-gm-name', 0):
self.ban('invalid name: %s' % self.name)
else:
self.air.writeServerEvent('suspicious', self.doId, '$ found in toon name')
def setModuleInfo(self, info):
avId = self.air.getAvatarIdFromSender()
key = 'outrageous'
self.moduleWhitelist = self.modulelist.loadWhitelistFile()
self.moduleBlacklist = self.modulelist.loadBlacklistFile()
for obfuscatedModule in info:
module = ''
p = 0
for ch in obfuscatedModule:
ic = ord(ch) ^ ord(key[p])
p += 1
if p >= len(key):
p = 0
module += chr(ic)
if module not in self.moduleWhitelist:
if module in self.moduleBlacklist:
self.air.writeServerEvent('suspicious', avId, 'Black List module %s loaded into process.' % module)
if simbase.config.GetBool('want-ban-blacklist-module', False):
commentStr = 'User has blacklist module: %s attached to their game process' % module
dislId = self.DISLid
simbase.air.banManager.ban(self.doId, dislId, commentStr)
else:
self.air.writeServerEvent('suspicious', avId, 'Unknown module %s loaded into process.' % module)
def teleportResponseToAI(self, toAvId, available, shardId, hoodId, zoneId, fromAvId):
if not self.WantTpTrack:
return
senderId = self.air.getAvatarIdFromSender()
if toAvId != self.doId:
self.air.writeServerEvent('suspicious', self.doId, 'toAvId=%d is not equal to self.doId' % toAvId)
return
if available != 1:
self.air.writeServerEvent('suspicious', self.doId, 'invalid availableValue=%d' % available)
return
if fromAvId == 0:
return
self.air.teleportRegistrar.registerValidTeleport(toAvId, available, shardId, hoodId, zoneId, fromAvId)
dg = self.dclass.aiFormatUpdate('teleportResponse', fromAvId, fromAvId, self.doId, [toAvId,
available,
shardId,
hoodId,
zoneId])
self.air.send(dg)
@staticmethod
def staticGetLogicalZoneChangeAllEvent():
return 'DOLogicalChangeZone-all'
def _garbageInfo(self):
if hasattr(self, 'inventory'):
if not hasattr(self.inventory, '_createStack'):
return 'inventory has no create stack'
else:
return self.inventory._createStack
return 'no inventory'
def flagAv(self, avId, reason, params):
self.notify.debug('reason: %s timepassed: %s' % (reason, globalClock.getFrameTime() - DistributedToonAI.lastFlagAvTime))
if reason == AV_FLAG_REASON_TOUCH and globalClock.getFrameTime() - DistributedToonAI.lastFlagAvTime > AV_TOUCH_CHECK_DELAY_AI:
DistributedToonAI.lastFlagAvTime = globalClock.getFrameTime()
av = self.air.doId2do.get(avId)
otherAv = self.air.doId2do.get(int(params[0]))
self.notify.debug('checking suspicious avatar positioning %s for %s with %s' % (avId, reason, params))
if av and otherAv and isinstance(av, DistributedToonAI) and isinstance(otherAv, DistributedToonAI) and av.zoneId == otherAv.zoneId and av.zoneId not in MinigameCreatorAI.MinigameZoneRefs:
self.notify.debug('...in zone %s' % av.zoneId)
componentNode = av.getParent().attachNewNode('blah')
componentNode.setPos(av.getComponentX(), av.getComponentY(), av.getComponentZ())
avPos = componentNode.getPos(av.getRender())
componentNode.reparentTo(otherAv.getParent())
componentNode.setPos(otherAv.getComponentX(), otherAv.getComponentY(), otherAv.getComponentZ())
otherAvPos = componentNode.getPos(otherAv.getRender())
componentNode.removeNode()
zDist = avPos.getZ() - otherAvPos.getZ()
avPos2D = copy.copy(avPos)
avPos2D.setZ(0)
otherAvPos2D = copy.copy(otherAvPos)
otherAvPos2D.setZ(0)
moveVec = avPos2D - otherAvPos2D
dist = moveVec.length()
self.notify.debug('2d dist between avs is %s %s %s' % (dist, avPos, otherAvPos))
if dist < AV_TOUCH_CHECK_DIST and zDist < AV_TOUCH_CHECK_DIST_Z:
self.notify.debug('...moving!')
if dist == 0.0:
moveVec = Vec3(1.0, 0, 0)
else:
moveVec.normalize()
moveVec = moveVec * AV_TOUCH_CHECK_DIST
avHpr = av.getHpr(av.getRender())
newX = avPos.getX() + moveVec.getX()
newY = avPos.getY() + moveVec.getY()
newZ = avPos.getZ() + moveVec.getZ()
newH = avHpr.getX()
newP = avHpr.getY()
newR = avHpr.getZ()
av.setPosHpr(av.getRender(), newX, newY, newZ, newH, newP, newR)
newAvPos = av.getPos()
if newAvPos.getX() > 3000 or newAvPos.getX() < -3000 or newAvPos.getY() > 3000 or newAvPos.getY() < -3000:
return
av.d_setXY(newAvPos.getX(), newAvPos.getY())
self.notify.debug('setting ai pos: %s %s %s and sending pos: %s' % (newX,
newY,
newZ,
newAvPos))
if len(DistributedToonAI.flagCounts) > AV_FLAG_HISTORY_LEN:
DistributedToonAI.flagCounts = {}
avPairKey = str(min(av.doId, otherAv.doId)) + '+' + str(max(av.doId, otherAv.doId))
prevCount = DistributedToonAI.flagCounts.setdefault(avPairKey, [{}, globalClock.getFrameTime(), {}])
if av.doId not in prevCount[2]:
2019-11-02 17:27:54 -05:00
prevCount[2][av.doId] = [None, None]
if av.doId not in prevCount[0]:
2019-11-02 17:27:54 -05:00
prevCount[0][av.doId] = 0
self.notify.debug('moving av %s, newPos: %s oldPos: %s' % (av.doId, prevCount[2][av.doId], avPos))
if prevCount[2][av.doId][0] == None or prevCount[2][av.doId][1] == None:
pass
elif prevCount[2][av.doId][0] != avPos.getX() or prevCount[2][av.doId][1] != avPos.getY():
prevCount[0][av.doId] += 1
prevCount[2][av.doId] = [newX, newY]
if prevCount[0][av.doId] > AV_TOUCH_COUNT_LIMIT:
if globalClock.getFrameTime() - prevCount[1] < AV_TOUCH_COUNT_TIME:
zoneId = not hasattr(av, 'zoneId') and 'undef' or av.zoneId
battleId = not hasattr(av, 'battleId') and 'undef' or av.battleId
animName = not hasattr(av, 'animName') and 'undef' or av.animName
inEstate = not hasattr(av, 'isInEstate') and 'undef' or av.isInEstate()
ghostMode = not hasattr(av, 'ghostMode') and 'undef' or av.ghostMode
immortalMode = not hasattr(av, 'immortalMode') and 'undef' or av.immortalMode
isGm = not hasattr(av, '_isGM') and 'undef' or av._isGM
valStr = '%s %s %s %s %s %s %s %s' % (otherAv.doId,
zoneId,
battleId,
animName,
inEstate,
ghostMode,
immortalMode,
isGm)
self.notify.info('av %s is consistently in an inappropriate position with %s...' % (av.doId, valStr))
self.air.writeServerEvent('suspicious', avId, ' consistently in an inappropriate position with toon %s' % valStr)
response = simbase.config.GetString('toon-pos-hack-response', 'nothing')
av.handleHacking(response, 'collision and position hacking', [otherAv])
del DistributedToonAI.flagCounts[avPairKey]
return
def handleHacking(self, response, comment, coconspirators = []):
if response == 'quietzone':
self.b_setLocation(self.parentId, ToontownGlobals.QuietZone)
elif response == 'disconnect':
self.disconnect()
elif response == 'disconnectall':
self.disconnect()
for coconspirator in coconspirators:
coconspirator.disconnect()
elif response == 'ban':
self.ban('collision and position hacking')
self.disconnect()
elif response == 'banall':
self.ban('collision and position hacking')
self.disconnect()
for coconspirator in coconspirators:
coconspirator.ban('collision and position hacking')
coconspirator.disconnect()
def requestPing(self, avId):
av = self.air.doId2do.get(avId)
if av:
from toontown.toon.DistributedNPCToonBaseAI import DistributedNPCToonBaseAI
if isinstance(av, DistributedNPCToonBaseAI):
return
if isinstance(av, DistributedToonAI) and avId not in DistributedToonAI.pingedAvs:
2019-11-02 17:27:54 -05:00
av.sendPing()
return Task.again
def sendPing(self):
def verify(theId):
if self.air:
msg = '%s failed to respond to ping!' % theId
self.notify.warning(msg)
self.air.writeServerEvent('suspicious', theId, msg)
self.cleanupPing()
disconnect = simbase.config.GetBool('client-ping-disconnect', True)
if disconnect:
av = self.air.getDo(theId)
if av:
av.disconnect()
return Task.done
val = ''
for i in range(14):
val = val + random.choice('abcdefghijklmnopqrstuvwxyz')
self.sendUpdateToAvatarId(self.doId, 'ping', [val])
DistributedToonAI.pingedAvs[self.doId] = [globalClock.getFrameTime(), val]
delay = simbase.config.GetInt('client-ping-timeout', 150)
taskMgr.doMethodLater(delay, verify, 'pingverify-' + str(self.doId), extraArgs=[self.doId])
def pingresp(self, resp):
senderId = self.air.getAvatarIdFromSender()
if senderId not in DistributedToonAI.pingedAvs or self.air == None:
2019-11-02 17:27:54 -05:00
self.cleanupPing()
return
val = DistributedToonAI.pingedAvs[senderId][1]
key = 'monkeyvanilla!'
module = ''
p = 0
for ch in val:
ic = ord(ch) ^ ord(key[p])
p += 1
if p >= len(key):
p = 0
module += chr(ic)
match = module == resp
if not match:
msg = '%s failed to respond to ping! with invalid response' % senderId
self.notify.warning(msg)
self.air.writeServerEvent('suspicious', senderId, msg)
self.cleanupPing()
return
def cleanupPing(self):
taskMgr.remove('pingverify-' + str(self.doId))
if self.doId in DistributedToonAI.pingedAvs:
2019-11-02 17:27:54 -05:00
del DistributedToonAI.pingedAvs[self.doId]
def startPing(self):
from toontown.toon.DistributedNPCToonBaseAI import DistributedNPCToonBaseAI
if isinstance(self, DistributedNPCToonBaseAI):
return
delay = simbase.config.GetInt('client-ping-period', 60)
taskMgr.doMethodLater(delay, self.requestPing, 'requestping-' + str(self.doId), extraArgs=[self.doId])
def stopPing(self):
taskMgr.remove('requestping-' + str(self.doId))