216 lines
8.6 KiB
Python
216 lines
8.6 KiB
Python
|
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
|