199 lines
9.5 KiB
Python
199 lines
9.5 KiB
Python
from otp.ai.AIBaseGlobal import *
|
|
from direct.task import Task
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from toontown.quest import Quests
|
|
from toontown.toon import NPCToons
|
|
import random
|
|
from direct.showbase import PythonUtil
|
|
from . import FishGlobals
|
|
from toontown.toonbase import TTLocalizer
|
|
from . import FishBase
|
|
from . import FishGlobals
|
|
from toontown.hood import ZoneUtil
|
|
from toontown.toonbase import ToontownGlobals
|
|
|
|
|
|
class FishManagerAI:
|
|
|
|
notify = DirectNotifyGlobal.directNotify.newCategory("FishManagerAI")
|
|
|
|
def __init__(self, air):
|
|
self.air = air
|
|
|
|
def __chooseItem(self, av, zoneId):
|
|
rodId = av.getFishingRod()
|
|
rand = random.random() * 100.0
|
|
for cutoff in FishGlobals.SortedProbabilityCutoffs:
|
|
if rand <= cutoff:
|
|
itemType = FishGlobals.ProbabilityDict[cutoff]
|
|
self.notify.debug("__chooseItem: %s" % (itemType))
|
|
return itemType
|
|
self.notify.warning("Somehow we did not choose an item, returning boot")
|
|
return FishGlobals.BootItem
|
|
|
|
def __chooseFish(self, av, zoneId):
|
|
rodId = av.getFishingRod()
|
|
branchZone = ZoneUtil.getCanonicalBranchZone(zoneId)
|
|
success, genus, species, weight = FishGlobals.getRandomFishVitals(branchZone, rodId)
|
|
return (success, genus, species, weight)
|
|
|
|
def recordCatch(self, avId, zoneId, pondZoneId):
|
|
# Chooses an item to find in the water. Returns a (code,
|
|
# item) pair where code indicates the type of item, and item
|
|
# is the particular item id.
|
|
av = self.air.doId2do.get(avId)
|
|
if not av:
|
|
return (None, None)
|
|
|
|
#check to see if bingo cheating is turned on
|
|
if av.bingoCheat:
|
|
# Fished up a boot
|
|
self.notify.debug("av: %s caught the boot" % (avId))
|
|
rodId = av.getFishingRod()
|
|
self.air.writeServerEvent("fishedBoot", avId, "%s|%s" % (rodId, zoneId))
|
|
self.air.handleAvCatch(avId, pondZoneId, FishGlobals.BingoBoot)
|
|
return (FishGlobals.BootItem, None)
|
|
|
|
# First, check for a quest item.
|
|
item = self.air.questManager.findItemInWater(av, zoneId)
|
|
if item:
|
|
self.notify.debug("av: %s caught quest item: %s" % (avId, item))
|
|
# Write to server logs
|
|
rodId = av.getFishingRod()
|
|
self.air.writeServerEvent("fishedQuestItem", avId, "%s|%s|%s" % (rodId, zoneId, item))
|
|
return (FishGlobals.QuestItem, item)
|
|
|
|
# Ok, no quest item, now let's see what you pull out
|
|
# Could be a fish, jellybeans, a boot, shirts, etc
|
|
itemType = self.__chooseItem(av, zoneId)
|
|
|
|
if itemType == FishGlobals.FishItem:
|
|
# Choose which fish (this may come back with the boot too)
|
|
success, genus, species, weight = self.__chooseFish(av, zoneId)
|
|
if success:
|
|
# Ok, you found a fish
|
|
self.air.handleAvCatch(avId, pondZoneId, (genus, species))
|
|
fish = FishBase.FishBase(genus, species, weight)
|
|
# do you already have one like it?
|
|
inTank = av.fishTank.hasFish(genus, species)
|
|
if inTank:
|
|
# TODO: This is a bit wasteful to loop through the fish tank twice
|
|
hasBiggerAlready = av.fishTank.hasBiggerFish(genus, species, weight)
|
|
else:
|
|
# If we already know it is not in the tank, no sense searching around
|
|
# to see if we have one bigger
|
|
hasBiggerAlready = 0
|
|
added = av.addFishToTank(fish)
|
|
if added:
|
|
self.notify.debug("av: %s caught fish: %s %s %s" %
|
|
(avId, genus, species, weight))
|
|
# See what the collect result will be
|
|
# NOTE: this does not actually collect the fish. The NPC
|
|
# fisherman does that work
|
|
collectResult = av.fishCollection.getCollectResult(fish)
|
|
|
|
# Catch a fish, get a heal
|
|
# Nope - changed my mind. Fishing does not heal anymore
|
|
# It is strange to be able to heal out on the streets, and while
|
|
# you are in the playground you heal anyways
|
|
# av.toonUp(FishGlobals.HealAmount)
|
|
|
|
# Write to server logs
|
|
rodId = av.getFishingRod()
|
|
self.air.writeServerEvent("fishedFish", avId, "%s|%s|%s|%s|%s|%s" %
|
|
(rodId, zoneId, genus, species, weight, fish.getValue()))
|
|
if collectResult == FishGlobals.COLLECT_NO_UPDATE:
|
|
return (FishGlobals.FishItem, fish)
|
|
elif collectResult == FishGlobals.COLLECT_NEW_ENTRY:
|
|
# If it is not in our tank also, it really is a new entry
|
|
if not inTank:
|
|
return (FishGlobals.FishItemNewEntry, fish)
|
|
# Ok, we already have one in our tank. If we do not already
|
|
# have a bigger one it is a new record
|
|
elif not hasBiggerAlready:
|
|
return (FishGlobals.FishItemNewRecord, fish)
|
|
# Otherwise, just a normal catch
|
|
else:
|
|
return (FishGlobals.FishItem, fish)
|
|
elif collectResult == FishGlobals.COLLECT_NEW_RECORD:
|
|
# If we have one of these in our tank, check to see if
|
|
# it is bigger. If the one we already have in our tank is bigger
|
|
# then we do not get a new record set.
|
|
if hasBiggerAlready:
|
|
# No new record, we already have this fish
|
|
# beat, but it is still in our tank - we have
|
|
# not sold it yet so it is not in our
|
|
# collection.
|
|
return (FishGlobals.FishItem, fish)
|
|
else:
|
|
return (FishGlobals.FishItemNewRecord, fish)
|
|
else:
|
|
self.notify.error("unrecognized collectResult: %s" % (collectResult))
|
|
else:
|
|
self.notify.debug("av: %s is over the tank limit" % (avId))
|
|
return (FishGlobals.OverTankLimit, None)
|
|
else:
|
|
# If you did not choose a fish, you get the boot
|
|
self.notify.debug("av: %s tried to catch fish, but got the boot" % (avId))
|
|
rodId = av.getFishingRod()
|
|
self.air.writeServerEvent("fishedBoot", avId, "%s|%s" % (rodId, zoneId))
|
|
self.air.handleAvCatch(avId, pondZoneId, FishGlobals.BingoBoot)
|
|
return (FishGlobals.BootItem, None)
|
|
elif itemType == FishGlobals.BootItem:
|
|
# Fished up a boot
|
|
self.notify.debug("av: %s caught the boot" % (avId))
|
|
rodId = av.getFishingRod()
|
|
self.air.writeServerEvent("fishedBoot", avId, "%s|%s" % (rodId, zoneId))
|
|
self.air.handleAvCatch(avId, pondZoneId, FishGlobals.BingoBoot)
|
|
return (FishGlobals.BootItem, None)
|
|
elif itemType == FishGlobals.JellybeanItem:
|
|
# Fished up some jellybeans
|
|
rodId = av.getFishingRod()
|
|
jellybeanAmount = FishGlobals.Rod2JellybeanDict[rodId]
|
|
av.addMoney(jellybeanAmount)
|
|
self.notify.debug("av: %s caught %s jellybeans" % (avId, jellybeanAmount))
|
|
self.air.writeServerEvent("fishedJellybeans", avId, "%s|%s|%s" % (rodId, zoneId, jellybeanAmount))
|
|
return (FishGlobals.JellybeanItem, jellybeanAmount)
|
|
|
|
def creditFishTank(self, av):
|
|
"""
|
|
Do all the work of selling the tank and updating the collection.
|
|
Also updates your trophy status and maxHP if needed.
|
|
Returns 1 if you earned a trophy, 0 if you did not.
|
|
"""
|
|
assert(self.notify.debug("creditFishTank av: %s is selling all fish" % (av.getDoId())))
|
|
oldBonus = int(len(av.fishCollection)/FishGlobals.FISH_PER_BONUS)
|
|
|
|
# give the avatar jellybeans in exchange for his fish
|
|
value = av.fishTank.getTotalValue()
|
|
av.addMoney(value)
|
|
|
|
# update the avatar collection for each fish
|
|
for fish in av.fishTank.fishList:
|
|
av.fishCollection.collectFish(fish)
|
|
|
|
# clear out the fishTank
|
|
av.b_setFishTank([],[],[])
|
|
|
|
# update the collection in the database
|
|
av.d_setFishCollection(*av.fishCollection.getNetLists())
|
|
|
|
newBonus = int(len(av.fishCollection)/FishGlobals.FISH_PER_BONUS)
|
|
if newBonus > oldBonus:
|
|
self.notify.info("avatar %s gets a bonus: old: %s, new: %s" % (av.doId, oldBonus, newBonus))
|
|
oldMaxHp = av.getMaxHp()
|
|
newMaxHp = min(ToontownGlobals.MaxHpLimit, oldMaxHp + newBonus - oldBonus)
|
|
av.b_setMaxHp(newMaxHp)
|
|
# Also, give them a full heal
|
|
av.toonUp(newMaxHp)
|
|
# update the av's trophy list
|
|
newTrophies = av.getFishingTrophies()
|
|
trophyId = len(newTrophies)
|
|
newTrophies.append(trophyId)
|
|
av.b_setFishingTrophies(newTrophies)
|
|
self.air.writeServerEvent("fishTrophy", av.doId, "%s" % (trophyId))
|
|
return 1
|
|
else:
|
|
assert(self.notify.debug("avatar %s no bonus: old: %s, new: %s" % (av.doId, oldBonus, newBonus)))
|
|
return 0
|