import datetime import time from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectAI import DistributedObjectAI from toontown.toonbase import ToontownGlobals class NewsManagerAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory('NewsManagerAI') def __init__(self, air): DistributedObjectAI.__init__(self, air) self.weeklyCalendarHolidays = [] self.yearlyCalendarHolidays = [] self.oncelyCalendarHolidays = [] self.relativelyCalendarHolidays = [] self.multipleStartHolidays = [] def announceGenerate(self): DistributedObjectAI.announceGenerate(self) # Setup our weekly calendar holidays. self.setupWeeklyCalendarHolidays() # Setup our yearly calendar holidays. self.setupYearlyCalendarHolidays() # Setup our holiday manager. self.air.holidayManager.setup() # Setup our weekly calendar holiday task. taskMgr.add(self.__weeklyCalendarHolidayTask, self.uniqueName('weekly-calendar-holiday-task')) # Handle avatars entering the district. self.accept('avatarEntered', self.handleAvatarEntered) def delete(self): DistributedObjectAI.delete(self) taskMgr.remove(self.uniqueName('silly-saturday-task')) taskMgr.remove(self.uniqueName('start-silly-saturday-bingo')) taskMgr.remove(self.uniqueName('start-silly-saturday-circuit')) taskMgr.remove(self.uniqueName('start-weekly-calendar-holiday')) def handleAvatarEntered(self, av): if self.air.suitInvasionManager.getInvading(): self.sendUpdateToAvatarId(av.getDoId(), 'setInvasionStatus', [ToontownGlobals.SuitInvasionBulletin, self.air.suitInvasionManager.invadingCog[0], self.air.suitInvasionManager.numSuits, self.air.suitInvasionManager.invadingCog[1]]) if self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_BINGO) or \ self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_CIRCUIT) or \ self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_TROLLEY) or \ self.air.holidayManager.isHolidayRunning(ToontownGlobals.ROAMING_TRIALER_WEEKEND): self.sendUpdateToAvatarId(av.getDoId(), 'holidayNotify', []) def setupWeeklyCalendarHolidays(self): # Get our current list of weekly calendar holidays. weeklyCalendarHolidays = self.getWeeklyCalendarHolidays()[:] # These are the weekly events that run consistently each week. weeklyEvents = [ # [holidayId, weekday] [ToontownGlobals.CIRCUIT_RACING, 0], # Grand Prix Mondays [ToontownGlobals.FISH_BINGO_NIGHT, 2], # Fish Bingo Wednesdays [ToontownGlobals.SILLY_SATURDAY_BINGO, 5] # Silly Saturdays ] # If an event from weeklyEvents doesn't already exist in weeklyCalendarHolidays, add it. for weeklyEvent in weeklyEvents: if weeklyEvent not in weeklyCalendarHolidays: weeklyCalendarHolidays.append(weeklyEvent) self.b_setWeeklyCalendarHolidays(weeklyCalendarHolidays) def setupYearlyCalendarHolidays(self): # Get our current list of yearly calendar holidays. yearlyCalendarHolidays = self.getYearlyCalendarHolidays()[:] # These are the yearly events that run consistently each year. yearlyEvents = [ # [holidayId, [startMonth, startDay, startHour, startMinute], [endMonth, endDay, endHour, endMinute]] [ToontownGlobals.VALENTINES_DAY, [2, 9, 0, 0], [2, 16, 23, 59]], [ToontownGlobals.IDES_OF_MARCH, [3, 14, 0, 0], [3, 20, 23, 59]], [ToontownGlobals.APRIL_FOOLS_COSTUMES, [3, 29, 0, 0], [4, 11, 23, 59]], [ToontownGlobals.JULY4_FIREWORKS, [6, 30, 0, 0], [7, 15, 23, 59]], [ToontownGlobals.HALLOWEEN_PROPS, [10, 25, 0, 0], [11, 1, 23, 59]], [ToontownGlobals.TRICK_OR_TREAT, [10, 25, 0, 0], [11, 1, 23, 59]], [ToontownGlobals.BLACK_CAT_DAY, [10, 31, 0, 0], [10, 31, 23, 59]], [ToontownGlobals.WINTER_DECORATIONS, [12, 14, 0, 0], [1, 4, 23, 59]], [ToontownGlobals.WINTER_CAROLING, [12, 16, 0, 0], [1, 4, 23, 59]], [ToontownGlobals.NEWYEARS_FIREWORKS, [12, 31, 0, 0], [1, 6, 23, 59]] ] # If an event from yearlyEvents doesn't already exist in yearlyCalendarHolidays, add it. for yearlyEvent in yearlyEvents: if yearlyEvent not in yearlyCalendarHolidays: yearlyCalendarHolidays.append(yearlyEvent) self.b_setYearlyCalendarHolidays(yearlyCalendarHolidays) def __weeklyCalendarHolidayTask(self, task): # If needed, these will hold the holiday IDs for holidays that we want to start and/or end. holidaysToStart = [] holidaysToEnd = [] # Get our current list of weekly calendar holidays. weeklyCalendarHolidays = self.getWeeklyCalendarHolidays()[:] # Get our current day of the week. currentWeekday = self.air.toontownTimeManager.getCurServerDateTime().now( tz=self.air.toontownTimeManager.serverTimeZone).weekday() # We will now loop through all of our weekly calendar holidays. for weeklyCalendarHoliday in weeklyCalendarHolidays: # If this particular holiday is Silly Saturday, perform some special logic. if weeklyCalendarHoliday[0] == ToontownGlobals.SILLY_SATURDAY_BINGO: # Check if the current day of the week matches the desired day of the week. if currentWeekday == weeklyCalendarHoliday[1]: # It does, so let's get the current hour. currentHour = self.air.toontownTimeManager.getCurServerDateTime().now( tz=self.air.toontownTimeManager.serverTimeZone).hour # Silly Saturday events rotate every two hours. Fish Bingo starts first at midnight for two hours, # then Grand Prix, then the cycle repeats until the end of Saturday. Let's see if we should run # Fish Bingo. if not ((currentHour // 2) % 12) % 2: # It's time for Fish Bingo! Let's see if it's already running. if not self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_BINGO): # Looks like Fish Bingo isn't currently running! Now let's check to see if the Grand Prix # is currently running or not. if self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_CIRCUIT): # The Grand Prix is currently running. In that case, we want to end the Grand Prix, # then wait 5 seconds before starting Fish Bingo. self.air.holidayManager.endHoliday(ToontownGlobals.SILLY_SATURDAY_CIRCUIT) taskMgr.doMethodLater(5, self.air.holidayManager.startHoliday, self.uniqueName('start-silly-saturday-bingo'), extraArgs=[ToontownGlobals.SILLY_SATURDAY_BINGO], appendTask=True) else: # The Grand Prix is currently not running. In that case, we can just go ahead and # start Fish Bingo. self.air.holidayManager.startHoliday(ToontownGlobals.SILLY_SATURDAY_BINGO) else: # It's time for the Grand Prix! Let's see if it's already running. if not self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_CIRCUIT): # Looks like the Grand Prix isn't currently running! Now let's check to see if # Fish Bingo is currently running or not. if self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_BINGO): # Fish Bingo is currently running. In that case, we want to end Fish Bingo, then wait # 5 seconds before starting the Grand Prix. self.air.holidayManager.endHoliday(ToontownGlobals.SILLY_SATURDAY_BINGO) taskMgr.doMethodLater(5, self.air.holidayManager.startHoliday, self.uniqueName('start-silly-saturday-circuit'), extraArgs=[ToontownGlobals.SILLY_SATURDAY_CIRCUIT], appendTask=True) else: # Fish Bingo is currently not running. In that case, we can just go ahead and start # the Grand Prix. self.air.holidayManager.startHoliday(ToontownGlobals.SILLY_SATURDAY_CIRCUIT) # Get the current epoch relative to the server's time zone. currentEpoch = time.mktime(datetime.datetime.now( tz=self.air.toontownTimeManager.serverTimeZone).timetuple()) + datetime.datetime.now( tz=self.air.toontownTimeManager.serverTimeZone).microsecond * 1e-6 # We want this task to run again at the top of each hour. task.delayTime = 3600.0 - (currentEpoch % 3600.0) return task.again else: # It does not, so we want to end any Silly Saturday holidays if they are still running. # Let's check if Fish Bingo is currently running. if self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_BINGO): # It is, so we will now end Fish Bingo. self.air.holidayManager.endHoliday(ToontownGlobals.SILLY_SATURDAY_BINGO) # Now let's check if the Grand Prix is currently running. if self.air.holidayManager.isHolidayRunning(ToontownGlobals.SILLY_SATURDAY_CIRCUIT): # It is, so we will now end the Grand Prix. self.air.holidayManager.endHoliday(ToontownGlobals.SILLY_SATURDAY_CIRCUIT) else: # We've landed on a holiday other than Silly Saturday! These are a lot more straightforward. # Check if the current day of the week matches the desired day of the week. if currentWeekday == weeklyCalendarHoliday[1]: # It does, so let's check if this holiday is currently running or not. if not self.air.holidayManager.isHolidayRunning(weeklyCalendarHoliday[0]): # It is not, so we will add it to holidaysToStart. holidaysToStart.append(weeklyCalendarHoliday[0]) else: # It does not, so we want to end the holiday, so let's check if it's currently running or not. if self.air.holidayManager.isHolidayRunning(weeklyCalendarHoliday[0]): # It is, so we will add it to holidaysToEnd. holidaysToEnd.append(weeklyCalendarHoliday[0]) # We will now loop through all of our holidays that we want to end. for holidayToEnd in holidaysToEnd: # Let's check if this holiday is currently running or not. if self.air.holidayManager.isHolidayRunning(holidayToEnd): # It is, so let's end it. self.air.holidayManager.endHoliday(holidayToEnd) # We will now loop through all of our holidays that we want to start. for holidayToStart in holidaysToStart: # Let's check if this holiday is currently running or not. if not self.air.holidayManager.isHolidayRunning(holidayToStart): # It is not, so let's check if holidaysToEnd is not empty. If it isn't, then that means we just ended # one or more holidays. If this is the case, we want to delay the new holidays starting by 5 seconds. if holidaysToEnd: # holidaysToEnd is not empty, so delay the holidays starting by 5 seconds. taskMgr.doMethodLater(5, self.air.holidayManager.startHoliday, self.uniqueName('start-weekly-calendar-holiday'), extraArgs=[holidayToStart], appendTask=True) else: # holidaysToEnd is empty, so we can just start the new holidays right away. self.air.holidayManager.startHoliday(holidayToStart) # We want this task to run again at midnight. We'll calculate the seconds until midnight, then # delay the task from running again until then. tomorrow = self.air.toontownTimeManager.getCurServerDateTime().now( tz=self.air.toontownTimeManager.serverTimeZone) + datetime.timedelta(1) midnight = datetime.datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=0, minute=0, second=0, tzinfo=self.air.toontownTimeManager.serverTimeZone) secondsUntilMidnight = (midnight - self.air.toontownTimeManager.getCurServerDateTime().now( tz=self.air.toontownTimeManager.serverTimeZone)).seconds task.delayTime = secondsUntilMidnight return task.again def setWeeklyCalendarHolidays(self, weeklyCalendarHolidays): self.weeklyCalendarHolidays = weeklyCalendarHolidays def d_setWeeklyCalendarHolidays(self, weeklyCalendarHolidays): self.sendUpdate('setWeeklyCalendarHolidays', [weeklyCalendarHolidays]) def b_setWeeklyCalendarHolidays(self, weeklyCalendarHolidays): self.setWeeklyCalendarHolidays(weeklyCalendarHolidays) self.d_setWeeklyCalendarHolidays(weeklyCalendarHolidays) def getWeeklyCalendarHolidays(self): return self.weeklyCalendarHolidays def setYearlyCalendarHolidays(self, yearlyCalendarHolidays): self.yearlyCalendarHolidays = yearlyCalendarHolidays def d_setYearlyCalendarHolidays(self, yearlyCalendarHolidays): self.sendUpdate('setYearlyCalendarHolidays', [yearlyCalendarHolidays]) def b_setYearlyCalendarHolidays(self, yearlyCalendarHolidays): self.setYearlyCalendarHolidays(yearlyCalendarHolidays) self.d_setYearlyCalendarHolidays(yearlyCalendarHolidays) def getYearlyCalendarHolidays(self): return self.yearlyCalendarHolidays def setOncelyCalendarHolidays(self, oncelyCalendarHolidays): self.oncelyCalendarHolidays = oncelyCalendarHolidays def d_setOncelyCalendarHolidays(self, oncelyCalendarHolidays): self.sendUpdate('setOncelyCalendarHolidays', [oncelyCalendarHolidays]) def b_setOncelyCalendarHolidays(self, oncelyCalendarHolidays): self.setOncelyCalendarHolidays(oncelyCalendarHolidays) self.d_setOncelyCalendarHolidays(oncelyCalendarHolidays) def getOncelyCalendarHolidays(self): return self.oncelyCalendarHolidays def setRelativelyCalendarHolidays(self, relativelyCalendarHolidays): self.relativelyCalendarHolidays = relativelyCalendarHolidays def d_setRelativelyCalendarHolidays(self, relativelyCalendarHolidays): self.sendUpdate('setRelativelyCalendarHolidays', [relativelyCalendarHolidays]) def b_setRelativelyCalendarHolidays(self, relativelyCalendarHolidays): self.setRelativelyCalendarHolidays(relativelyCalendarHolidays) self.d_setRelativelyCalendarHolidays(relativelyCalendarHolidays) def getRelativelyCalendarHolidays(self): return self.relativelyCalendarHolidays def setMultipleStartHolidays(self, multipleStartHolidays): self.multipleStartHolidays = multipleStartHolidays def d_setMultipleStartHolidays(self, multipleStartHolidays): self.sendUpdate('setMultipleStartHolidays', [multipleStartHolidays]) def b_setMultipleStartHolidays(self, multipleStartHolidays): self.setMultipleStartHolidays(multipleStartHolidays) self.d_setMultipleStartHolidays(multipleStartHolidays) def getMultipleStartHolidays(self): return self.multipleStartHolidays def d_setInvasionStatus(self, msgType, cogType, numRemaining, skeleton): self.sendUpdate('setInvasionStatus', [msgType, cogType, numRemaining, skeleton]) def d_setHolidayIdList(self, holidayIdList): self.sendUpdate('setHolidayIdList', [holidayIdList]) def d_setBingoStart(self): self.sendUpdate('setBingoStart') def d_setBingoEnd(self): self.sendUpdate('setBingoEnd') def d_setCircuitRaceStart(self): self.sendUpdate('setCircuitRaceStart') def d_setCircuitRaceEnd(self): self.sendUpdate('setCircuitRaceEnd')