oldschool-toontown/toontown/ai/ScavengerHuntMgrAI.py

216 lines
8.6 KiB
Python
Raw Normal View History

from direct.directnotify import DirectNotifyGlobal
from direct.interval.IntervalGlobal import *
from toontown.ai import HolidayBaseAI
from otp.otpbase import OTPGlobals
from toontown.toonbase import ToontownGlobals
from toontown.hood import ZoneUtil
from toontown.ai import DistributedScavengerHuntTargetAI
from toontown.scavengerhunt.ScavengerHuntBase import ScavengerHuntBase
from toontown.uberdog.DataStoreAIClient import DataStoreAIClient
from toontown.uberdog import DataStoreGlobals
import time
import pickle
# This dictionary defines the relationship between the scavenger hunt goal id and the zone where the goal is located.
# goalId: zoneId
GOALS = {
# 0 : 2649, # TTC
# 1 : 1834, # DD
# 2 : 4835, # MM
# 3 : 5620, # DG
# 4 : 3707, # BR
# 5 : 9619, # DL
0 : 1000,
1 : 2000,
}
# This dictionary defines the milestones for this scavenger hunt
MILESTONES = {
#0: (GOALS.keys(), 'All Trick-or-Treat goals found'),
0: ((0, 1), 'All Scavenger hunt goals found'),
}
class ScavengerHuntMgrAI(HolidayBaseAI.HolidayBaseAI):
"""
This is the main Scavenger hunt holiday class. It will create
several distributed listeners in selected zones. These listeners
will wait for a toon to trigger something; for example an SC event.
"""
notify = DirectNotifyGlobal.directNotify.newCategory(
'ScavengerHuntMgrAI')
PostName = 'ScavangerHunt'
def __init__(self, air, holidayId):
HolidayBaseAI.HolidayBaseAI.__init__(self, air, holidayId)
self.hunt = None
self.targets = {}
self.storeClient = DataStoreAIClient(air,
DataStoreGlobals.SH,
self.receiveScavengerHuntResults)
@property
def goals(self):
return GOALS
@property
def milestones(self):
return MILESTONES
def start(self):
# Create a unique id for this hunt based on it's start date and time
localTime = time.localtime()
date = (localTime[0],
localTime[1],
localTime[2],
localTime[6],
)
from toontown.ai import HolidayManagerAI
startTime = HolidayManagerAI.HolidayManagerAI.holidays[self.holidayId].getStartTime(date)
scavengerHuntId = abs(hash(time.ctime(startTime)))
# Create the hunt
self.hunt = ScavengerHuntBase(scavengerHuntId, self.holidayId)
self.hunt.defineGoals(list(self.goals.keys()))
# Send a list with one item in it: [0, (0, 1, 2, 3, 4, 5)]
# This milestone defines the end of the hunt.
self.hunt.defineMilestones((x[0],x[1][0]) for x in list(self.milestones.items()))
self.createListeners()
# let the holiday system know we started
bboard.post(ScavengerHuntMgrAI.PostName)
# make sure the uberdog data store is up for this hunt
self.storeClient.openStore()
def createListeners(self):
"""
Create the listeners that will look for an event in the relavent zone
"""
for id in list(self.goals.keys()):
mgrAI = DistributedScavengerHuntTargetAI.DistributedScavengerHuntTargetAI(self.air,
self.hunt,
id,
self,
)
self.targets[id] = mgrAI
self.targets[id].generateWithRequired(self.goals[id])
def stop(self):
# let the holiday system know we stopped
bboard.remove(ScavengerHuntMgrAI.PostName)
# remove the targetAI's and their distributed counterparts
for zone in list(self.goals.keys()):
self.targets[zone].requestDelete()
self.storeClient.closeStore()
def avatarAttemptingGoal(self, avId, goal):
# We need to know what goals have already been completed
# in order to proceed. Ask the Uberdog for the data.
# We send the goal since when the Uberdog responds we
# still need to match the new goal with the avId.
queryData = (avId, goal)
self.sendScavengerHuntQuery('GetGoals', queryData)
def avatarCompletedGoal(self, avId, goal):
# This will ask the Uberdog to add this new goal
# to the avId's completed list.
queryData = (avId, goal)
self.sendScavengerHuntQuery('AddGoal', queryData)
def sendScavengerHuntQuery(self, qTypeString, qData):
# send a finalized query to the Uberdog.
self.storeClient.sendQuery(qTypeString, qData)
def receiveScavengerHuntResults(self, results):
# This function handles the result message from
# the Uberdog. See the ScavengerHuntDataStore
# class to see data format.
# Indicates that the qId was invalid for this store.
# Should never really happen
if results == None:
return
else:
# extract the queryId, and translate it to it's string
qId, data = results
qType = self.storeClient.getQueryTypeString(qId)
# We're receiving an avatar's new goal and list of completed goals
if qType == 'GetGoals':
avId, goal, done_goals = data
# See what needs to be done
self.__handleResult(avId, done_goals, goal)
# The goal was successfully added to this avId
elif qType == 'AddGoal':
avId, = data
def __handleResult(self, avId, done_goals, goal):
# This is where we check to see if the goal has already been completed.
# If it's already done, let the client know. Otherwise, check to see
# if the scavenger hunt is complete and respond accordingly.
if goal in done_goals:
ScavengerHuntMgrAI.notify.debug(
repr(avId)+' already found Scavenger hunt target '+repr(goal)+': '+repr(self.goals.get(goal, 'INVALID GOAL ID IN '+self.PostName)))
av = self.air.doId2do.get(avId)
milestoneIds = self.hunt.getRecentMilestonesHit(done_goals+[goal], goal)
if milestoneIds:
for id in milestoneIds:
ScavengerHuntMgrAI.notify.debug(
repr(avId)+' hit milestone ' + repr(id) + ': ' + self.milestones.get(milestoneIds[id], [None, 'Undefined milestone id in '+self.PostName])[1])
if (id == 0): # handle found all targets
self.huntCompletedReward(avId, goal)
else:
self.huntGoalFound(avId, goal)
else:
self.huntGoalAlreadyFound(avId)
elif 0 <= goal <= len(list(self.goals.keys())):
ScavengerHuntMgrAI.notify.debug(
repr(avId)+' found Scavenger hunt target '+repr(goal))
av = self.air.doId2do.get(avId)
if not av:
ScavengerHuntMgrAI.notify.warning(
'Tried to send goal feedback to av %s, but they left' % avId)
else:
milestoneIds = self.hunt.getRecentMilestonesHit(done_goals+[goal], goal)
if milestoneIds:
for id in milestoneIds:
ScavengerHuntMgrAI.notify.debug(
repr(avId)+' hit milestone ' + repr(id) + ': ' + self.milestones.get(milestoneIds[id], [None, 'Undefined milestone id in '+self.PostName])[1])
if (id == 0): # handle found all targets
# Wait for the goal found reward to complete
taskMgr.doMethodLater(10, self.huntCompletedReward, repr(avId)+'-huntCompletedReward', extraArgs = [avId, goal, True])
self.huntGoalFound(avId, goal)
else:
self.huntGoalFound(avId, goal)
def huntCompletedReward(self, avId, goal, firstTime = False):
"""
Reward the Toon
"""
pass
def huntGoalAlreadyFound(self, avId):
"""
This goal has already been found
"""
pass
def huntGoalFound(self, avId, goal):
"""
One of the goals in the milestone were found,
so we reward the toon.
"""
pass