open-toontown/toontown/fishing/FishManagerAI.py

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