text: from panda3d.core import *
  from direct.fsm import FSM
  from direct.task import Task
  from direct.directnotify import DirectNotifyGlobal
  from direct.distributed.ClockDelta import globalClockDelta
  from direct.interval.IntervalGlobal import *
  from pirates.ai import HolidayGlobals
  from pirates.effects.RainMist import RainMist
  from pirates.effects.RainDrops import RainDrops
  from pirates.effects.RainSplashes import RainSplashes
  from pirates.effects.RainSplashes2 import RainSplashes2
  from pirates.piratesbase import AvatarShadowCaster
  from pirates.piratesbase import PiratesGlobals
  from pirates.piratesbase import TODGlobals
  from pirates.piratesbase import TODDefs
  from pirates.piratesbase import SkyGroup
  import time
  from pirates.piratesbase import TimeOfDayManagerBase
  import random
  
  
  class TimeOfDayManager(FSM.FSM, TimeOfDayManagerBase.TimeOfDayManagerBase):
      notify = directNotify.newCategory('TimeOfDayManager')
  
      def __init__(self):
          FSM.FSM.__init__(self, 'TimeOfDayManager')
          TimeOfDayManagerBase.TimeOfDayManagerBase.__init__(self)
          self.lightSwitch = [0, 0, 0]
          self.cycleType = TODGlobals.TOD_REGULAR_CYCLE
          self.cycleDuration = 0
          self.currentState = -1
          self.prevState = -1
          self.lastState = 0
          self.envEffect = None
          self.lastEffective = (0, 0)
          self.inTransition = 0
          self.needCheckSub = 0
          self.ambientSFXList = []
          self.lastServerTimeArrived = 0
          self.cycleSpeed = 1
          self.timeOffset = 0
          tempTime = globalClockDelta.getFrameNetworkTime(bits=32)
          self.startingServerTime = globalClockDelta.networkToLocalTime(tempTime)
          self.startTodTime = globalClockDelta.networkToLocalTime(globalClockDelta.getFrameNetworkTime(bits=32))
          self.lastWaterColor = Vec4(0, 0, 0, 0)
          self.lastWaterColorFactor = Vec4(0, 0, 0, 0)
          self.frontLightColor = Vec4(0, 0, 0, 0)
          self.backLightColor = Vec4(0, 0, 0, 0)
          self.clearColor = Vec4(0, 0, 0, 0)
          self.frontLightFlutter = None
          self.backLightFlutter = None
          self.flutterFront = 0
          self.flutterBack = 0
          self.waterColorFactor = None
          self.environment = TODGlobals.ENV_DEFAULT
          self.envSubstitutionDict = {}
          self.waitTaskName = 'waitForNextTODState-' + str(hash(self))
          self.nextDoLater = None
          self.startingTime = 0
          self.startingState = -1
          self.transitionIval = None
          self.sunMoveIval = None
          self.moonPhaseIval = None
          self.targetMoonPhase = None
          self.moonJolly = 0
          self.moonJollyIval = None
          self.softTOD = base.config.GetBool('want-soft-tod-changes', True)
          self.wantAdvancedWeather = base.config.GetBool('advanced-weather', True)
          self.rainDrops = None
          self.rainMist = None
          self.rainSplashes = None
          self.rainSplashes2 = None
          self.rain = False
          self.skyGroup = SkyGroup.SkyGroup()
          self.skyGroup.reparentTo(camera)
          self.fixedSky = False
          self.skyEnabled = True
          self.seapatch = None
          self.sunLight = self.skyGroup.dirLightSun
          self.dlight = self.skyGroup.dirLightSun
          self.grassLight = self.skyGroup.grassLight
          self.alight = self.skyGroup.ambLight
          self.shadowLight = self.skyGroup.dirLightShadowSun
          self.fog = Fog('TimeOfDayFog')
          self.setFogExpDensity(TODGlobals.FOG_DEFAULT_EXP)
          self.fogExpDensity = 0.0
          self.linearFog = Fog('LinearTimeOfDayFog')
          self.currFogOnset = 0.0
          self.currFogPeak = 100.0
          self.lerpFogIval = None
          self.fogMask = 0
          self.fogType = None
          self.fogColor = Vec4(0.0, 0.0, 0.0, 0.0)
          self.setFogType(TODGlobals.FOG_OFF)
          self.showSky = 0
          self.avatarShadowCaster = None
          if base.config.GetBool('want-avatar-shadows', 1):
              self.enableAvatarShadows()
  
          self.isPaused = 0
          if base.config.GetBool('want-shaders',
                                 1) and base.win and base.win.getGsg():
              pass
          self.use_shader = base.win.getGsg().getShaderModel() >= GraphicsStateGuardian.SM20
          self.accept('HolidayStarted', self.handleHolidayStarted)
          self.accept('HolidayEnded', self.handleHolidayEnded)
          self.forcedStateEnabled = False
          self.currentStateDuration = None
          self.debugTOD = False
          self.alteratedSettingsList = []
  
      def toggleDebugMode(self):
          if self.debugTOD:
              self.debugTOD = False
              base.talkAssistant.receiveGameMessage('Turning off TOD info')
          else:
              self.debugTOD = True
              base.talkAssistant.receiveGameMessage('Turning on TOD info')
              base.talkAssistant.receiveGameMessage('Time is %s %s %s' % (str(self.getCurrentIngameTime())[
                                                    :5], TODGlobals.StateDict[self.currentState], TODGlobals.ENV_DEBUG_NAMES[self.environment]))
  
      def enableAvatarShadows(self):
          if not self.avatarShadowCaster:
              self.avatarShadowCaster = AvatarShadowCaster.AvatarShadowCaster(
                  self.sunLight)
  
          self.avatarShadowCaster.enable()
          self.skyGroup.shadowCaster = self.avatarShadowCaster
          self.skyGroup.applySunAngle()
  
      def disableAvatarShadows(self):
          if self.avatarShadowCaster:
              self.avatarShadowCaster.disable()
  
          self.skyGroup.shadowCaster = None
  
      def setRelativeRotation(self, h=0):
          if hasattr(base.localAvatar, 'gridParent'):
              if base.localAvatar.gridParent and base.localAvatar.gridParent.grid:
                  self.skyGroup.setRelativeCompassH(
                      base.localAvatar.gridParent.grid.getH())
              else:
                  self.skyGroup.setRelativeCompassH(0.0)
  
      def disable(self):
          if self.envEffect is not None:
              self.stopEnvEffect(self.envEffect)
  
          self.ignore('gotTimeSync')
          self.ignore('HolidayStarted')
          self.ignore('HolidayEnded')
          taskMgr.remove('pauseTimeOfDayManagerTask')
          self.request('Off')
          if self.transitionIval:
              self.transitionIval.pause()
              self.transitionIval = None
  
          if self.sunMoveIval:
              self.sunMoveIval.pause()
  
          del self.sunMoveIval
          if self.moonPhaseIval:
              self.moonPhaseIval.pause()
  
          del self.moonPhaseIval
          if self.moonJollyIval:
              self.moonJollyIval.pause()
  
          del self.moonJollyIval
  
      def delete(self):
          render.clearLight(self.alight)
          render.clearLight(self.sunLight)
          render.clearLight(self.shadowLight)
          self.alight = None
          self.dlight = None
          self.shadowLight = None
          self.grassLight = None
          self.sunLight = None
          if self.lerpFogIval:
              self.lerpFogIval.pause()
              self.lerpFogIval = None
  
          if self.avatarShadowCaster:
              self.avatarShadowCaster.disable()
              self.avatarShadowCaster = None
  
          if self.transitionIval:
              self.transitionIval.pause()
              self.transitionIval = None
  
          self.fog = None
          self.ignoreAll()
          self.skyGroup.stopCloudIval()
          self.skyGroup.removeNode()
          del self.skyGroup
  
      def enterInitState(self):
          if self.forcedStateEnabled:
              return None
  
          if self.isPaused:
              stateName = TODGlobals.getStateName(self.startingState)
              self.request(stateName)
              taskMgr.doMethodLater(10.0, self.pause, 'pauseTimeOfDayManagerTask')
          else:
              self.syncTimeOfDay(0)
  
      def syncTimeOfDay(self, soft=1):
          if self.environment == TODGlobals.ENV_SAILING:
              pass
  
          if self.forcedStateEnabled:
              return None
  
          self.notify.debug('Syncing time of day...')
          (stateId, stateTime) = self._computeCurrentState()
          stateName = TODGlobals.getStateName(stateId)
          if hasattr(base, 'pe'):
              self.request('EnvironmentTOD')
          else:
              self.request('EnvironmentTOD')
          if self.debugTOD:
              base.talkAssistant.receiveGameMessage('syncTimeOfDay')
  
      def _computeCurrentState(self):
          if self.cycleDuration == 0:
              return (self.startingState, 0.0)
  
          elapsedTime = globalClockDelta.localElapsedTime(
              self.startingTime, bits=32)
          remTime = elapsedTime % self.cycleDuration
          stateId = self.startingState
          while None:
              stateDuration = self.cycleDuration * \
                  TODGlobals.getStateDuration(self.cycleType, stateId)
              if remTime < stateDuration:
                  return (stateId, remTime)
                  continue
              remTime -= stateDuration
              stateId = TODGlobals.getNextStateId(self.cycleType, stateId)
  
      def _waitForNextStateRequest(self, stateId, elapsedTime):
          taskMgr.remove(self.waitTaskName)
          if self.cycleDuration == 0:
              self.notify.debug('stopping in state: %s' % stateId)
              return 0
  
          nextStateId = TODGlobals.getNextStateId(self.cycleType, stateId)
          nextStateName = TODGlobals.getStateName(nextStateId)
          stateDuration = self.cycleDuration * \
              TODGlobals.getStateDuration(self.cycleType, stateId)
          delayTime = stateDuration - elapsedTime
          self.nextDoLater = taskMgr.doMethodLater(
              delayTime, self._doLaterRequest, self.waitTaskName, extraArgs=[])
          return stateDuration
  
      def _getStateDuration(self, stateId):
          stateDuration = self.cycleDuration * \
              TODGlobals.getStateDuration(self.cycleType, stateId)
          return stateDuration
  
      def _doLaterRequest(self):
          (stateId, elapsedTime) = self._computeCurrentState()
          nextStateName = TODGlobals.getStateName(stateId)
          self.request('EnvironmentTOD')
          return Task.done
  
      def getStateName(self, stateId):
          return TODGlobals.getStateName(stateId)
  
      def pause(self, task=None):
          if self.transitionIval:
              self.transitionIval.pause()
  
          taskMgr.remove(self.waitTaskName)
  
      def setFrontLightColor(self, newColor):
          frontLight = self.skyGroup.dirLightSun
          ambientColor = self.alight.node().getColor()
          self.frontLightColor = newColor
          if not self.flutterFront:
              lightValueForColor = TODGlobals.computeLightColor(
                  self.frontLightColor, ambientColor, self.lightSwitch)
              frontLight.node().setColor(lightValueForColor)
  
      def getFrontLightColor(self):
          return self.frontLightColor
  
      def setBackLightColor(self, newColor):
          backLight = self.skyGroup.dirLightShadowSun
          ambientColor = self.alight.node().getColor()
          self.backLightColor = newColor
          if not self.flutterBack:
              lightValueForColor = TODGlobals.computeLightColor(
                  self.backLightColor, ambientColor, self.lightSwitch)
              backLight.node().setColor(lightValueForColor)
  
      def getBackLightColor(self):
          return self.backLightColor
  
      def setFillLightColor(self, newColor):
          self.alight.node().setColor(newColor)
  
      def getFillLightColor(self):
          return self.alight.node().getColor()
  
      def startFlutter(self):
          self.flutterFront = 1
          self.flutterBack = 1
          self.frontLightFlutter = self.frontLightColor
          self.backLightFlutter = self.backLightColor
          self.lastFrontRandom = 1.0
          self.lastBackRandom = 1.0
          taskMgr.add(
              self._TimeOfDayManager__flutterLights,
              'todManager-flutterLights')
  
      def endFlutter(self):
          taskMgr.remove('todManager-flutterLights')
          self.flutterFront = 0
          self.flutterBack = 0
  
      def _TimeOfDayManager__flutterLights(self, task):
          frontLight = self.skyGroup.dirLightSun
          backLight = self.skyGroup.dirLightShadowSun
          ambientColor = self.alight.node().getColor()
          randFront = random.random()
          randBack = random.random()
          blendFront = (randFront + self.lastFrontRandom) * 0.5
          blendBack = (randBack + self.lastBackRandom) * 0.5
          self.lastFrontRandom = randFront
          self.lastBackRandom = randBack
          factorFront = self.frontLightColor * (0.75 + blendFront * 0.5)
          factorBack = self.backLightColor * (0.75 + blendBack * 0.5)
          self.frontLightFlutter = self.frontLightFlutter * \
              0.80000000000000004 + factorFront * 0.20000000000000001
          self.backLightFlutter = self.backLightFlutter * \
              0.80000000000000004 + factorBack * 0.20000000000000001
          lightValueForColor = TODGlobals.computeLightColor(
              self.frontLightFlutter, ambientColor, self.lightSwitch)
          frontLight.node().setColor(lightValueForColor)
          lightValueForColor = TODGlobals.computeLightColor(
              self.backLightFlutter, ambientColor, self.lightSwitch)
          backLight.node().setColor(lightValueForColor)
          return task.cont
  
      def storeAlteredSetting(self, env, tod, settingName):
          settingTuple = (env, tod, settingName)
          if settingTuple not in self.alteratedSettingsList:
              self.alteratedSettingsList.append(settingTuple)
  
          messenger.send('TOD_Setting_Change', [])
  
      def listAlteredTODs(self, env):
          alteredList = []
          for entry in self.alteratedSettingsList:
              if entry[0] == env:
                  if entry[1] not in alteredList:
                      alteredList.append(entry[1])
  
              entry[1] not in alteredList
  
          return alteredList
  
      def revertTODChange(self, env, tod):
          entryToRemoveList = []
          for entry in self.alteratedSettingsList:
              if entry[0] == env and entry[1] == tod:
                  settingName = entry[2]
                  del TODGlobals.ENV_SETTINGS_DICT[env][tod][settingName]
                  entryToRemoveList.append(entry)
                  envDict = TODGlobals.BACKUP_ENV_SETTINGS_DICT.get(env)
                  if envDict:
                      timeDict = envDict.get(tod)
                      if timeDict:
                          settingValue = timeDict.get(settingName)
                          if settingValue:
                              TODGlobals.ENV_SETTINGS_DICT[env][tod][settingName] = settingValue
  
                  if TODGlobals.ENV_SETTINGS_DICT[env][tod] == {}:
                      del TODGlobals.ENV_SETTINGS_DICT[env][tod]
  
              TODGlobals.ENV_SETTINGS_DICT[env][tod] == {}
  
          for entry in entryToRemoveList:
              self.alteratedSettingsList.remove(entry)
  
      def insertTODSettings(self, environment, todState, ambientColor, frontColor,
                            backColor, fogColor, fogExp, fogRange, lightSwitch, sunDir):
          envGroup = TODGlobals.ENV_SETTINGS_DICT.get(environment)
          if envGroup:
              settingGroup = envGroup.get(self.currentState)
              if not settingGroup:
                  envGroup[self.currentState] = {}
  
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['AmbientColor'] = ambientColor
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['FrontColor'] = frontColor
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['BackColor'] = backColor
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['FogColor'] = fogColor
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['FogExp'] = fogExp
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['FogLinearRange'] = (
                  fogRange[0], fogRange[1])
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['LightSwitch'] = (
                  lightSwitch[0], lightSwitch[1], lightSwitch[2])
              TODGlobals.ENV_SETTINGS_DICT[environment][todState]['Direction'] = Vec3(
                  sunDir[0], sunDir[1], sunDir[2])
              self.storeAlteredSetting(environment, todState, 'AmbientColor')
              self.storeAlteredSetting(environment, todState, 'FrontColor')
              self.storeAlteredSetting(environment, todState, 'BackColor')
              self.storeAlteredSetting(environment, todState, 'FogColor')
              self.storeAlteredSetting(environment, todState, 'FogExp')
              self.storeAlteredSetting(environment, todState, 'FogLinearRange')
              self.storeAlteredSetting(environment, todState, 'LightSwitch')
              self.storeAlteredSetting(environment, todState, 'Direction')
  
          print 'Inserting env%s tod %s\nambient %s\nfront %s\nback %s\nfogColor %s\nfogExp %s\nfogRange %s\n' % (self.environment, self.currentState, ambientColor, frontColor, backColor, fogColor, fogExp, fogRange)
  
      def insertEnvDict(self, envIndex, envDict):
          for todName in envDict:
              todDict = envDict[todName]
              todIndex = TODGlobals.NAME_TO_ID_DICT[todName]
              if todDict and todDict != {}:
                  self.insertTODSettingDict(envIndex, todIndex, todDict)
                  continue
  
      def insertTODSettingDict(self, env, tod, settingDict):
          for settingName in settingDict:
              self.insertTODSetting(
                  env, tod, settingName, settingDict[settingName])
  
      def insertTODSetting(self, env, todId, settingName, settingValue):
          print 'insertTODSetting %s %s %s %s' % (env, todId, settingName, settingValue)
          tod = TODGlobals.StateDict.get(todId, None)
          if tod is None:
              return None
  
          envGroup = TODGlobals.ENV_SETTINGS_DICT.get(env)
          if not envGroup:
              TODGlobals.ENV_SETTINGS_DICT[env] = {}
  
          settingGroup = envGroup.get(tod)
          if not settingGroup:
              TODGlobals.ENV_SETTINGS_DICT[env][tod] = {}
  
          if tod == 'BASE' and env == TODGlobals.ENV_DEFAULT:
              pass
  
          if TODGlobals.ENV_SETTINGS_DICT[env][tod].get(settingName):
              del TODGlobals.ENV_SETTINGS_DICT[env][tod][settingName]
  
          parentSettingValue = TODGlobals.getTodEnvSetting(tod, env, settingName)
          if parentSettingValue == settingValue:
              return None
          elif settingName == 'Direction':
              sameCount = 0
              for compIndex in xrange(3):
                  if parentSettingValue[compIndex] % 360.0 == settingValue[compIndex] % 360.0:
                      sameCount += 1
                      continue
  
              if sameCount >= 3:
                  return None
  
          if settingName == 'FogLinearRange':
              TODGlobals.ENV_SETTINGS_DICT[env][tod][settingName] = (
                  settingValue[0], settingValue[1])
          else:
              TODGlobals.ENV_SETTINGS_DICT[env][tod][settingName] = settingValue
          self.storeAlteredSetting(env, tod, settingName)
  
      def setLightSwitch(self, switchList):
          frontOn = switchList[0]
          ambientOn = switchList[1]
          backOn = switchList[2]
          oldFront = self.getFrontLightColor()
          oldBack = self.getBackLightColor()
          if frontOn != self.lightSwitch[0]:
              if frontOn:
                  render.setLight(self.sunLight)
              else:
                  render.clearLight(self.sunLight)
  
          if ambientOn != self.lightSwitch[1]:
              if ambientOn:
                  render.setLight(self.alight)
              else:
                  render.clearLight(self.alight)
  
          if backOn != self.lightSwitch[2]:
              if backOn:
                  render.setLight(self.shadowLight)
              else:
                  render.clearLight(self.shadowLight)
  
          self.lightSwitch = switchList
          self.setFrontLightColor(oldFront)
          self.setBackLightColor(oldBack)
  
      def _transitionTimeOfDay(self, fromState, toState, t, startEnv=None, destEnv=None):
          if self.forcedStateEnabled:
              return Parallel()
  
          if destEnv is None:
              destEnv = self.environment
  
          if startEnv is None:
              startEnv = destEnv
  
          environment = self.environment
          timeLightSwitch = TODGlobals.getTodEnvSetting(
              toState, environment, 'LightSwitch')
          fromAmbient = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'AmbientColor')
          fromFogColor = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'FogColor')
          fromFogExp = TODGlobals.getTodEnvSetting(fromState, startEnv, 'FogExp')
          fromFogOnset = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'FogLinearRange')[0]
          fromFogPeak = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'FogLinearRange')[1]
          fromStarColor = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'StarColor')
          fromFrontLight = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'FrontColor')
          fromBackLight = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'BackColor')
          ival = Parallel(
              LerpFunctionInterval(
                  self.alight.node().setColor,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'AmbientColor'),
                  fromData=fromAmbient,
                  name='TOD_aLightColor-%d'),
              LerpFunctionInterval(
                  self.grassLight.node().setColor,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'AmbientColor'),
                  fromData=fromAmbient,
                  name='TOD_grassLightColor-%d'),
              LerpFunctionInterval(
                  self.setFogColor,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'FogColor'),
                  fromData=fromFogColor,
                  name='TOD_fogColor-%d'),
              LerpFunctionInterval(
                  self.setFogExpDensity,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'FogExp'),
                  fromData=fromFogExp,
                  name='TOD_fogExp-%d'),
              LerpFunctionInterval(
                  self.setLinearFogOnset,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'FogLinearRange')[0],
                  fromData=fromFogOnset,
                  name='TOD_fogExp-%d'),
              LerpFunctionInterval(
                  self.setLinearFogPeak,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'FogLinearRange')[1],
                  fromData=fromFogPeak,
                  name='TOD_fogExp-%d'),
              LerpFunctionInterval(
                  self.skyGroup.stars.setColorScale,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'StarColor'),
                  fromData=fromStarColor,
                  name='TOD_fogExp-%d'),
              name='TOD_transitionTimeOfDay')
          if not self.fixedSky:
              fromSkyType = TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'SkyType')
              fromSkyColor = TODGlobals.SKY_CLEARCOLORS[fromSkyType]
              toSkyType = TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'SkyType')
              toSkyColor = TODGlobals.SKY_CLEARCOLORS[toSkyType]
              ival.append(
                  LerpFunctionInterval(
                      self.setSkyClearColor,
                      duration=t,
                      fromData=fromSkyColor,
                      toData=toSkyColor))
              if hasattr(base, 'pe'):
                  ival.append(
                      LerpFunctionInterval(
                          base.setBackgroundColor,
                          duration=t,
                          fromData=fromSkyColor,
                          toData=toSkyColor))
  
              toSkySettings = TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'SkyType')
              fromSkySettings = TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'SkyType')
              if t > 0.0:
                  ival.append(
                      self.skyGroup.transitionSky(
                          fromSkySettings,
                          toSkySettings,
                          duration=t))
  
          if base.cr.activeWorld and hasattr(
                  base.cr.activeWorld, 'getWater') and base.cr.activeWorld.getWater():
              if self.use_shader:
                  self.seapatch = base.cr.activeWorld.getWater()
              else:
                  self.seapatch = base.cr.activeWorld.getWater().patchNP
  
          if base.cr.newsManager and base.cr.newsManager.getHoliday(
                  HolidayGlobals.SAINTPATRICKSDAY):
              self.setSaintPatricksSea()
          elif self.use_shader:
              fromSeaColor = TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'SeaColorShader')
              toSeaColor = TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'SeaColorShader')
              ival.append(
                  LerpFunctionInterval(
                      self.modifyWaterColor,
                      duration=t,
                      fromData=fromSeaColor,
                      toData=toSeaColor))
              fromSeaColorFactor = TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'SeaFactor')
              toSeaColorFactor = TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'SeaFactor')
              ival.append(
                  LerpFunctionInterval(
                      self.modifyWaterColorFactor,
                      duration=t,
                      fromData=fromSeaColorFactor,
                      toData=toSeaColorFactor))
          else:
              fromSeaColor = TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'SeaColor')
              toSeaColor = TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'SeaColor')
              ival.append(
                  LerpFunctionInterval(
                      self.modifyWaterColor,
                      duration=t,
                      fromData=fromSeaColor,
                      toData=toSeaColor))
          self.currLight = self.skyGroup.getLight(fromState)
          self.dLight = self.skyGroup.getLight(toState)
          fromDirectionalColor = TODGlobals.computeLightColor(
              TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'FrontColor'), TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'AmbientColor'), timeLightSwitch)
          toDirectionalColor = TODGlobals.computeLightColor(
              TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'FrontColor'), TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'AmbientColor'), timeLightSwitch)
          ival.append(
              LerpFunctionInterval(
                  self.setFrontLightColor,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'FrontColor'),
                  fromData=fromFrontLight,
                  name='TOD_dLightColor-%d'))
          self.currShadowLight = self.skyGroup.getShadowLight(fromState)
          self.shadowLight = self.skyGroup.getShadowLight(toState)
          fromShadowLight = TODGlobals.computeLightColor(
              TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'BackColor'), TODGlobals.getTodEnvSetting(
                  fromState, startEnv, 'AmbientColor'), timeLightSwitch)
          toShadowLight = TODGlobals.computeLightColor(
              TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'BackColor'), TODGlobals.getTodEnvSetting(
                  toState, destEnv, 'AmbientColor'), timeLightSwitch)
          ival.append(
              LerpFunctionInterval(
                  self.setBackLightColor,
                  duration=t,
                  toData=TODGlobals.getTodEnvSetting(
                      toState,
                      destEnv,
                      'BackColor'),
                  fromData=fromBackLight,
                  name='TOD_dLightColor-%d'))
          fromMoonOverlay = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'MoonOverlay')
          fromMoonSize = TODGlobals.getTodEnvSetting(
              fromState, startEnv, 'MoonSize')
          fromMoonState = self.skyGroup.moonState
          toMoonOverlay = TODGlobals.getTodEnvSetting(
              toState, destEnv, 'MoonOverlay')
          toMoonSize = TODGlobals.getTodEnvSetting(toState, destEnv, 'MoonSize')
          toMoonState = TODGlobals.getTodEnvSetting(
              toState, destEnv, 'MoonPhase')
          if self.moonJolly:
              fromMoonOverlay = 0.5
              toMoonOverlay = 0.5
  
          if self.moonJollyIval and self.moonJollyIval.isPlaying():
              pass
  
          ival.append(
              LerpFunctionInterval(
                  self.skyGroup.setMoonOverlayAlpha,
                  duration=t,
                  fromData=fromMoonOverlay,
                  toData=toMoonOverlay,
                  name='TOD-Trans-MoonJolly'))
          ival.append(
              LerpFunctionInterval(
                  self.skyGroup.setMoonSize,
                  duration=t,
                  fromData=fromMoonSize,
                  toData=toMoonSize,
                  name='TOD-Trans-MoonSize'))
          if self.moonPhaseIval and self.moonPhaseIval.isPlaying():
              pass
  
          ival.append(
              LerpFunctionInterval(
                  self.setMoonState,
                  duration=t,
                  fromData=fromMoonState,
                  toData=toMoonState,
                  name='TOD-Trans-MoonPhase'))
  
          return ival
  
      def setMoonState(self, moonPhase):
          if self.moonPhaseIval:
              return None
  
          self.skyGroup.setMoonState(moonPhase)
  
      def setMoonStateAnim(self, moonPhase):
          self.skyGroup.setMoonState(moonPhase)
  
      def animateMoon(self, fromCurrent, startPhase, phase, duration):
          if self.inTransition:
              pass
  
          if self.moonPhaseIval:
              self.moonPhaseIval.finish()
  
          if fromCurrent:
              startPhase = self.skyGroup.moonState
  
          self.moonPhaseIval = Sequence()
          self.moonPhaseIval.append(
              LerpFunctionInterval(
                  self.setMoonStateAnim,
                  duration=duration,
                  fromData=startPhase,
                  toData=phase,
                  name='animateMoon-Trans-MoonPhase'))
          self.moonPhaseIval.start()
  
      def switchJollyMoon(self, jolly):
          if not self.moonJolly and jolly:
              self.moonJollyIval = Sequence()
              self.moonJollyIval.append(
                  LerpFunctionInterval(
                      self.skyGroup.setMoonOverlayAlpha,
                      duration=3.0,
                      fromData=0.0,
                      toData=0.5,
                      name='Switch-MoonJolly'))
              self.moonJollyIval.start()
          elif self.moonJolly and not jolly:
              self.moonJollyIval = Sequence()
              self.moonJollyIval.append(
                  LerpFunctionInterval(
                      self.skyGroup.setMoonOverlayAlpha,
                      duration=3.0,
                      fromData=0.5,
                      toData=0.0,
                      name='Switch-MoonJolly'))
              self.moonJollyIval.start()
  
          self.moonJolly = jolly
  
      def switchRain(self, rain):
          if not self.rain and rain:
              self.rainDrops = RainDrops(base.camera)
              self.rainDrops.reparentTo(render)
              self.rainDrops.startLoop()
  
              self.rainMist = RainMist(base.camera)
              self.rainMist.reparentTo(render)
              self.rainMist.startLoop()
  
              self.rainSplashes = RainSplashes(base.camera)
              self.rainSplashes.reparentTo(render)
              self.rainSplashes.startLoop()
  
              self.rainSplashes2 = RainSplashes2(base.camera)
              self.rainSplashes2.reparentTo(render)
              self.rainSplashes2.startLoop()
          elif self.rain and not rain:
              self.rainDrops.stopLoop()
              self.rainMist.stopLoop()
              self.rainSplashes.stopLoop()
              self.rainSplashes2.stopLoop()
  
              self.rainDrops.destroy()
              self.rainMist.destroy()
              self.rainSplashes.destroy()
              self.rainSplashes2.destroy()
  
              self.rainDrops = None
              self.rainMist = None
              self.rainSplashes = None
              self.rainSplashes2 = None 
  
          self.rain = rain
  
      def _prepareState(self, stateId, environment=None):
          self.notify.debug('_prepareState %s' % stateId)
          if self.forcedStateEnabled:
              return None
  
          if environment is None:
              environment = self.environment
  
          if TODGlobals.getTodEnvSetting(
                  stateId, environment, 'SkyType') == TODGlobals.SKY_OFF:
              self.skyGroup.stash()
              self.showSky = 0
          else:
              self.skyGroup.unstash()
              self.showSky = 1
          if not self.fixedSky:
              skyType = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'SkyType')
              clearColor = TODGlobals.SKY_CLEARCOLORS[skyType]
              self.setSkyClearColor(clearColor)
              if hasattr(base, 'pe'):
                  base.setBackgroundColor(
                      base.backgroundDrawable.getClearColor())
  
              skySettings = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'SkyType')
              self.setSkyType(skySettings)
  
          lastSunDir = TODGlobals.getTodEnvSetting(
              self.lastState, environment, 'Direction')
          self.skyGroup.setSunTrueAngle(lastSunDir)
          if base.cr.activeWorld and hasattr(
                  base.cr.activeWorld, 'getWater') and base.cr.activeWorld.getWater():
              if self.use_shader:
                  self.seapatch = base.cr.activeWorld.getWater()
              else:
                  self.seapatch = base.cr.activeWorld.getWater().patchNP
  
          if self.use_shader:
              seaColor = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'SeaColorShader')
              waterColorFactor = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'SeaFactor')
              self.modifyWaterColor(seaColor)
              self.modifyWaterColorFactor(waterColorFactor)
          else:
              seaColor = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'SeaColor')
              self.modifyWaterColor(seaColor)
              self.modifyWaterColorFactor()
          fogType = TODGlobals.getTodEnvSetting(stateId, environment, 'FogType')
          self.setFogType(fogType)
          if render.getFog():
              fogColor = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'FogColor')
              self.fog.setColor(fogColor)
              fogExp = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'FogExp')
              self.setFogExpDensity(fogExp)
              linearFogRanges = TODGlobals.getTodEnvSetting(
                  stateId, environment, 'FogLinearRange')
              self.currFogOnset = linearFogRanges[0]
              self.currFogPeak = linearFogRanges[1]
              self.linearFog.setLinearRange(self.currFogOnset, self.currFogPeak)
  
          lightSwitch = TODGlobals.getTodEnvSetting(
              stateId, environment, 'LightSwitch')
          self.setLightSwitch(lightSwitch)
          envEffect = TODGlobals.getTodEnvSetting(
              stateId, environment, 'EnvEffect')
          self.setEnvEffect(envEffect)
          ambientColor = TODGlobals.getTodEnvSetting(
              stateId, environment, 'AmbientColor')
          self.alight.node().setColor(ambientColor)
          self.grassLight.node().setColor(ambientColor)
          self.shadowLight = self.skyGroup.getShadowLight(stateId)
          self.dlight = self.skyGroup.getLight(stateId)
          if self.dlight:
              highLightColor = TODGlobals.computeLightColor(
                  TODGlobals.getTodEnvSetting(
                      stateId, environment, 'FrontColor'), TODGlobals.getTodEnvSetting(
                      stateId, environment, 'AmbientColor'), lightSwitch=lightSwitch)
              self.setFrontLightColor(
                  TODGlobals.getTodEnvSetting(
                      stateId, environment, 'FrontColor'))
  
          if self.shadowLight:
              shadowLightColor = TODGlobals.computeLightColor(
                  TODGlobals.getTodEnvSetting(
                      stateId, environment, 'BackColor'), TODGlobals.getTodEnvSetting(
                      stateId, environment, 'AmbientColor'), lightSwitch=lightSwitch)
              self.setBackLightColor(
                  TODGlobals.getTodEnvSetting(
                      stateId, environment, 'BackColor'))
  
          if self.avatarShadowCaster:
              self.avatarShadowCaster.setLightSrc(self.dlight)
  
      def setWeatherId(self, weatherId, transitionTime=5.0):
          if not self.wantAdvancedWeather:
              return
  
          if weatherId not in TODGlobals.WEATHER_TYPES:
              self.notify.warning('Received invalid weather id: %d' % weatherId)
              return
  
          self.notify.debug('Setting weather to %d!' % weatherId)
          weatherData = TODGlobals.WEATHER_TYPES[weatherId]
          self.setCloudsType(weatherData['clouds'], transitionTime)
  
          rainSequence = Sequence(
              Wait(transitionTime),
              Func(self.switchRain, weatherData['rain']))
          rainSequence.start()
  
      def setCloudsType(self, cloudType, duration=5.0):
          if cloudType not in TODGlobals.CLOUD_TRANSITIONS:
              return 
          self.skyGroup.transitionClouds(cloudType, duration).start()
          self.skyGroup.setSky(self.skyGroup.lastSky)
  
      def setSkyType(self, skyType):
          if skyType == TODGlobals.SKY_OFF:
              self.showSky = 0
          else:
              self.showSky = 1
          self.skyGroup.setSky(skyType)
          clearColor = TODGlobals.SKY_CLEARCOLORS[skyType]
          self.setSkyClearColor(clearColor)
  
      def setSkyClearColor(self, clearColor, override=0):
          self.clearColor = clearColor
          if not self.showSky:
              base.backgroundDrawable.setClearColor(self.fogColor)
              return None
  
          if not (self.fixedSky) or override:
              base.backgroundDrawable.setClearColor(clearColor)
  
      def getCurrentIngameTime(self, time=None):
          cycleSpeed = self.cycleSpeed
          if cycleSpeed <= 0:
              cycleSpeed = 1
  
          if time is None:
              currentTime = globalClockDelta.networkToLocalTime(
                  globalClockDelta.getFrameNetworkTime(bits=32))
          else:
              currentTime = time
          REALSECONDS_PER_GAMEDAY = PiratesGlobals.TOD_REALSECONDS_PER_GAMEDAY / cycleSpeed
          REALSECONDS_PER_GAMEHOUR = float(
              REALSECONDS_PER_GAMEDAY /
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY)
          cycleDuration = REALSECONDS_PER_GAMEHOUR * \
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY
          timeElapsed = currentTime - self.startingServerTime
          timeIntoCycle = (timeElapsed + self.timeOffset) % cycleDuration
          hoursIntoCycle = timeIntoCycle / REALSECONDS_PER_GAMEHOUR
          return hoursIntoCycle
  
      def getEnvAtTime(self, baseEnv, timeForEnv):
          print 'getEnvAtTime %s %s' % (baseEnv, timeForEnv)
          subEntry = self.envSubstitutionDict.get(baseEnv)
          if not subEntry:
              print ' base %s' % baseEnv
              return baseEnv
          else:
              timeStamp = globalClockDelta.networkToLocalTime(
                  subEntry[3], bits=32)
              if timeForEnv > timeStamp:
                  print ' sub2 %s' % subEntry[2]
                  return subEntry[2]
              else:
                  print ' sub1 %s' % subEntry[1]
                  return subEntry[1]
  
      def addEnvSub(self, baseEnv, envReplacement, netTime=None):
          cycleSpeed = self.cycleSpeed
          if cycleSpeed <= 0:
              cycleSpeed = 1
  
          localNetTime = globalClockDelta.networkToLocalTime(
              globalClockDelta.getFrameNetworkTime(bits=32))
          REALSECONDS_PER_GAMEDAY = PiratesGlobals.TOD_REALSECONDS_PER_GAMEDAY / cycleSpeed
          REALSECONDS_PER_GAMEHOUR = float(
              REALSECONDS_PER_GAMEDAY /
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY)
          cycleDuration = REALSECONDS_PER_GAMEHOUR * \
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY
          (fieldStartTime, absoluteTODCycle) = self.getSubTimeList(
              self.cycleType, self.environment)
          (previousIndex, currentIndex, nextIndex, stateStartTime) = self.getTODStateDatatAtTime(
              fieldStartTime, absoluteTODCycle, globalClock.getFrameTime(), REALSECONDS_PER_GAMEHOUR)
          previousStateTransTime = absoluteTODCycle[previousIndex][2]
          lastEnv = baseEnv
          envEntry = self.envSubstitutionDict.get(baseEnv)
          if netTime is None:
              netTime = globalClockDelta.getFrameNetworkTime(bits=32)
  
          timeStamp = globalClockDelta.networkToLocalTime(netTime, bits=32)
          needStartRetro = 0
          if previousStateTransTime and timeStamp < previousStateTransTime and baseEnv == self.environment:
              needStartRetro = 1
  
          print 'Adding EnvSub for %s stamp %s current time %s netTime %s' % (baseEnv, timeStamp, globalClock.getFrameTime(), localNetTime)
          if envEntry:
              lastEnv = envEntry[2]
          else:
              currentEnvLook = baseEnv
          if lastEnv == envReplacement:
              pass
  
          newEnvEntry = (baseEnv, lastEnv, envReplacement, netTime)
          self.envSubstitutionDict[baseEnv] = newEnvEntry
          if baseEnv == self.environment:
              if self.inTransition:
                  self.needCheckSub = 1
              else:
                  self.doStartTimeOfDay()
                  return None
  
          if needStartRetro:
              if self.debugTOD:
                  base.talkAssistant.receiveGameMessage(
                      'Starting time of day for retroActive TimeStamp')
  
              if self.transitionIval:
                  self.transitionIval.finish()
                  self.transitionIval = None
  
              self.doStartTimeOfDay()
  
      def getEnvSub(self, environment, testTime):
          entry = self.envSubstitutionDict.get(environment)
          if not entry:
              return environment
          else:
              netTime = entry[3]
              timeStamp = globalClockDelta.networkToLocalTime(netTime, bits=32)
              if testTime > timeStamp:
                  return entry[2]
              else:
                  return entry[1]
  
      def getSubTimeList(self, cycleType, env):
          if self.notify.getDebug():
              print 'getSubTimeList'
          cycleSpeed = self.cycleSpeed
          if cycleSpeed <= 0:
              cycleSpeed = 1
  
          REALSECONDS_PER_GAMEDAY = PiratesGlobals.TOD_REALSECONDS_PER_GAMEDAY / cycleSpeed
          REALSECONDS_PER_GAMEHOUR = float(
              REALSECONDS_PER_GAMEDAY /
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY)
          cycleDuration = REALSECONDS_PER_GAMEHOUR * \
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY
          cycleList = TODGlobals.CycleStateTimeList.get(
              cycleType) + TODGlobals.CycleStateTimeList.get(cycleType) + TODGlobals.CycleStateTimeList.get(cycleType)
          modCycleList = []
          currentGameTime = self.getCurrentIngameTime()
          currentFrameTime = globalClock.getFrameTime()
          subCycleTimeStart = None
          subCycleTimeTransEnd = None
          sub = self.envSubstitutionDict.get(env)
          if self.notify.getDebug():
              print ' sub was %s for %s' % (sub, env)
          gameTimeToSeconds = currentGameTime * REALSECONDS_PER_GAMEHOUR
          cycleStartFrameTime = currentFrameTime - gameTimeToSeconds
          cycleEndFrameTime = currentFrameTime + \
              (cycleDuration - gameTimeToSeconds)
          fieldStartFrameTime = cycleStartFrameTime - REALSECONDS_PER_GAMEDAY
          fieldEndFrameTime = cycleEndFrameTime + REALSECONDS_PER_GAMEDAY
          subInField = 0
          subBeforeField = 0
          subAfterField = 0
          if sub:
              netTime = sub[3]
              timeStamp = globalClockDelta.networkToLocalTime(netTime, bits=32)
              if self.notify.getDebug():
                  print 'Sub TimeStamp %s current Time %s' % (timeStamp, currentFrameTime)
              if timeStamp > fieldStartFrameTime and timeStamp < fieldEndFrameTime:
                  if self.notify.getDebug():
                      print ' sub found in current cycle'
                  start = timeStamp - cycleStartFrameTime
                  subCycleTimeStart = float(start) / REALSECONDS_PER_GAMEHOUR
                  subCycleTimeTransEnd = subCycleTimeStart + sub[3]
                  subInField = 1
              elif timeStamp > fieldEndFrameTime:
                  subAfterField = 1
              elif timeStamp < fieldStartFrameTime:
                  subBeforeField = 1
  
          absoluteTimeList = self.getAbsoluteTimeList(
              cycleList, -(PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY))
          if not sub:
              newBaseCycleEntry = absoluteTimeList
          else:
              envPre = sub[1]
              envPost = sub[2]
              if subInField:
                  subStart = subCycleTimeStart
                  subLength = 1.0
                  subEnd = subStart + subLength
                  noSub = 0
  
              subListAbsolute = []
              index = 0
              for timeEntry in absoluteTimeList:
                  vId = timeEntry[0]
                  startTime = timeEntry[1]
                  transEndTime = timeEntry[2]
                  endTime = timeEntry[3]
                  transLength = transEndTime - startTime
                  subEntry = None
                  if (subAfterField or subInField) and endTime < subStart:
                      regEntry = (vId, startTime, transEndTime, endTime, envPre)
                      subListAbsolute.append(regEntry)
                      index += 1
                      continue
                  if (subBeforeField or subInField) and startTime > subEnd:
                      regEntry = (vId, startTime, transEndTime, endTime, envPost)
                      subListAbsolute.append(regEntry)
                      index += 1
                      continue
                  if subEnd > endTime:
                      regEntry = (vId, startTime, transEndTime, endTime, envPre)
                      subListAbsolute.append(regEntry)
                      index += 1
                      continue
                  if subStart < transEndTime:
                      regEntry = (
                          vId,
                          startTime,
                          transEndTime,
                          transEndTime,
                          envPre)
                      index += 1
                      subListAbsolute.append(regEntry)
                      subStart = transEndTime
                      subLength = 1.0
                      subEnd = subStart + subLength
                      subEntry = (vId, subStart, subEnd, endTime, envPost)
                      subListAbsolute.append(subEntry)
                      index += 1
                      continue
                  regEntry = (vId, startTime, transEndTime, subStart, envPre)
                  subListAbsolute.append(regEntry)
                  index += 1
                  subLength = 1.0
                  subEntry = (vId, subStart, subEnd, endTime, envPost)
                  index += 1
                  subListAbsolute.append(subEntry)
  
              newBaseCycleEntry = subListAbsolute
          index = 0
          for timeEntry in newBaseCycleEntry:
              index += 1
  
          return (fieldStartFrameTime, newBaseCycleEntry)
  
      def getTODStateDatatAtTime(self, fieldStartTimeInSeconds,
                                 absoluteCycleList, currentTimeSeconds, secondsPerHour):
          fieldStartHour = absoluteCycleList[0][1]
          timeInHours = fieldStartHour + \
              (currentTimeSeconds - fieldStartTimeInSeconds) / secondsPerHour
          currentIndex = 0
          nextIndex = None
          previousIndex = None
          stateStartTime = None
          for stateIndex in xrange(len(absoluteCycleList)):
              state = absoluteCycleList[stateIndex]
              tod = state[0]
              time = state[1]
              transTime = state[2]
              if time <= timeInHours:
                  currentIndex = stateIndex
                  stateStartTime = time
                  continue
  
          nextIndex = (currentIndex + 1) % len(absoluteCycleList)
          previousIndex = currentIndex - 1
          if previousIndex < 0:
              previousIndex = len(absoluteCycleList) - 1
  
          return (previousIndex, currentIndex, nextIndex, stateStartTime)
  
      def getAbsoluteTimeList(self, cycleList, startTime=0):
          absoluteTimeList = []
          runningTimeTotal = startTime
          for timeEntry in cycleList:
              absoluteTimeList.append(
                  (timeEntry[0],
                   runningTimeTotal,
                   runningTimeTotal +
                   timeEntry[2],
                      runningTimeTotal +
                      timeEntry[1],
                      None))
              runningTimeTotal += timeEntry[1]
  
          return absoluteTimeList
  
      def setInTransition(self, inTrans):
          self.inTransition = inTrans
          if self.needCheckSub and self.inTransition == 0:
              self.needCheckSub = 0
              self.doStartTimeOfDay()
  
      def setDesiredTime(self, desiredTime):
          cycleSpeed = self.cycleSpeed
          if cycleSpeed <= 0:
              cycleSpeed = 1
  
          REALSECONDS_PER_GAMEDAY = PiratesGlobals.TOD_REALSECONDS_PER_GAMEDAY / cycleSpeed
          REALSECONDS_PER_GAMEHOUR = float(
              REALSECONDS_PER_GAMEDAY /
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY)
          cycleDuration = REALSECONDS_PER_GAMEHOUR * \
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY
          currentTime = self.getCurrentIngameTime() - self.timeOffset / \
              REALSECONDS_PER_GAMEHOUR
          offsetInHours = (
              desiredTime - currentTime) % PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY
          offsetInSeconds = offsetInHours * REALSECONDS_PER_GAMEHOUR
          self.timeOffset = offsetInSeconds
  
      def doStartTimeOfDayTask(self, task=None):
          self.doStartTimeOfDay()
          return task.done
  
      def doStartTimeOfDay(self, initial=0):
          pauseTOD = 0
          cycleSpeed = self.cycleSpeed
          if cycleSpeed <= 0:
              cycleSpeed = 1
              pauseTOD = 1
  
          REALSECONDS_PER_GAMEDAY = PiratesGlobals.TOD_REALSECONDS_PER_GAMEDAY / cycleSpeed
          REALSECONDS_PER_GAMEHOUR = float(
              REALSECONDS_PER_GAMEDAY /
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY)
          cycleDuration = REALSECONDS_PER_GAMEHOUR * \
              PiratesGlobals.TOD_GAMEHOURS_IN_GAMEDAY
          lastTime = self.startTodTime
          self.startTodTime = globalClockDelta.networkToLocalTime(
              globalClockDelta.getFrameNetworkTime(bits=32))
          lastTODlength = self.startTodTime - lastTime
          (fieldStartTime, absoluteTODCycle) = self.getSubTimeList(
              self.cycleType, self.environment)
          startServerTime = self.startingServerTime
          currentTimeSeconds = globalClock.getFrameTime()
          totalElapsedTime = (
              currentTimeSeconds - startServerTime) + self.timeOffset
          timeIntoCycle = totalElapsedTime % cycleDuration
          hoursIntoCycle = timeIntoCycle / REALSECONDS_PER_GAMEHOUR
          currentGameTimeInHours = hoursIntoCycle
          (previousIndex, currentIndex, nextIndex, stateStartTime) = self.getTODStateDatatAtTime(
              fieldStartTime, absoluteTODCycle, currentTimeSeconds + 0.5, REALSECONDS_PER_GAMEHOUR)
          previousStateStartTime = absoluteTODCycle[previousIndex][1]
          currentStateData = absoluteTODCycle[currentIndex]
          TOD = currentStateData[0]
          totalStateTimeHours = currentStateData[3] - currentStateData[1]
          totalTransTimeHours = currentStateData[2] - currentStateData[1]
          if totalTransTimeHours > totalStateTimeHours:
              totalTransTimeHours = totalStateTimeHours
  
          self.currentState = TOD
          secondsIntoCycle = float(
              currentGameTimeInHours - stateStartTime) * REALSECONDS_PER_GAMEHOUR
          secondsLeftInCycle = float(
              totalTransTimeHours) * REALSECONDS_PER_GAMEHOUR - secondsIntoCycle
          if secondsIntoCycle < 0 and 0:
              taskMgr.doMethodLater(
                  1.0, self.doStartTimeOfDayTask, self.waitTaskName)
              return None
  
          self.lastState = absoluteTODCycle[previousIndex][0]
          self.currentStateDuration = float(
              totalStateTimeHours) * REALSECONDS_PER_GAMEHOUR
          stateDuration = self.currentStateDuration
          transitionTimeSeconds = float(
              totalTransTimeHours) * REALSECONDS_PER_GAMEHOUR
          stateStartTime = currentTimeSeconds - secondsIntoCycle
          previousStateStartTime = absoluteTODCycle[previousIndex][1]
          previoudStateEndTime = absoluteTODCycle[previousIndex][3]
          previousLength = (previoudStateEndTime -
                            previousStateStartTime) * REALSECONDS_PER_GAMEHOUR
          startEnv = absoluteTODCycle[previousIndex][4]
          destEnv = absoluteTODCycle[currentIndex][4]
          if startEnv is None:
              startEnv = self.environment
  
          if destEnv is None:
              destEnv = self.environment
  
          if (initial or self.lastState ==
                  self.currentState) and startEnv == destEnv:
              self._prepareState(self.currentState, environment=destEnv)
  
          newEffective = (startEnv, destEnv)
          self.lastEffective = newEffective
          elapsedTime = secondsIntoCycle
          if self.debugTOD:
              base.talkAssistant.receiveGameMessage('TOD:%s T Sec:%s D Sec:%s In Sec:%s\nfrom %s-%s to %s-%s\nNext %s ' % (str(currentGameTimeInHours)[:5], str(transitionTimeSeconds)[:5], str(stateDuration)[:5], str(secondsIntoCycle)[
                                                    :6], TODGlobals.ENV_DEBUG_NAMES[startEnv], TODGlobals.StateDict[absoluteTODCycle[previousIndex][0]], TODGlobals.ENV_DEBUG_NAMES[destEnv], TODGlobals.StateDict[absoluteTODCycle[currentIndex][0]], TODGlobals.StateDict[absoluteTODCycle[nextIndex][0]]))
  
          if TODGlobals.SunRotationStates[self.lastState] != TODGlobals.SunRotationStates[self.currentState]:
              fade = 1
              transitionTime = min(
                  transitionTimeSeconds,
                  TODGlobals.NONGROUP_MAX_TRANSITION_TIME)
              sunMoveTime = transitionTime
          else:
              fade = 0
              sunMoveTime = stateDuration
          sunCorrection = elapsedTime
          if initial:
              sunDirLast = TODGlobals.getTodEnvSetting(
                  self.lastState, destEnv, 'Direction')
              self.skyGroup.setSunTrueAngle(sunDirLast)
              sunCorrection = 0
  
          sunDir = TODGlobals.getTodEnvSetting(
              self.currentState, destEnv, 'Direction')
          if self.transitionIval:
              self.transitionIval.finish()
              self.transitionIval = None
  
          if self.sunMoveIval:
              self.sunMoveIval.pause()
              self.sunMoveIval = None
  
          masterIval = Parallel()
          transAndClearIval = Sequence()
          if self.lastState != self.currentState or startEnv != destEnv:
              self.setInTransition(1)
              timeofDayTrans = self._transitionTimeOfDay(
                  self.lastState,
                  self.currentState,
                  transitionTimeSeconds,
                  startEnv=startEnv,
                  destEnv=destEnv)
              transClearIval = Sequence()
              transClearIval.append(Wait(transitionTimeSeconds))
              transClearIval.append(Func(self.setInTransition, 0))
              transAndClearIval.append(timeofDayTrans)
              transAndClearIval.append(Func(self.setInTransition, 0))
              masterIval.append(transAndClearIval)
  
          self.sunMoveIval = self.skyGroup.transitionSunAngle(
              sunDir, sunMoveTime - sunCorrection, fade, sunDirLast=None)
          self.transitionIval = masterIval
          self.transitionIval.start(elapsedTime)
          if initial:
              self.sunMoveIval.start(elapsedTime)
          else:
              self.sunMoveIval.start()
          taskMgr.remove(self.waitTaskName)
          if not pauseTOD:
              timeToNextState = self.currentStateDuration - elapsedTime
              taskMgr.doMethodLater(
                  timeToNextState,
                  self.doStartTimeOfDayTask,
                  self.waitTaskName)
          else:
              self.transitionIval.finish()
              self.sunMoveIval.finish()
          self.accept('settingLocalShip', self.switchFogDensity)
          messenger.send('timeOfDayChange', [
              self.currentState,
              stateDuration,
              elapsedTime,
              transitionTimeSeconds])
          return (stateDuration, elapsedTime, transitionTimeSeconds)
  
      def doEndTimeOfDay(self):
          self.currentStateDuration = None
          self.notify.debug('exit: %s' % self.currentState)
          self.ignore('settingLocalShip')
          taskMgr.remove(self.waitTaskName)
          if self.transitionIval:
              self.transitionIval.pause()
              self.transitionIval = None
  
      def enterEnvironmentTOD(self):
          self.notify.debug('enterEnvironmentTOD')
          (stateDuration, elapsedTime, transitionTime) = self.doStartTimeOfDay(initial=1)
  
      def exitEnvironmentTOD(self):
          self.notify.debug('exitEnvironmentTOD')
          self.doEndTimeOfDay()
  
      def enterNoLighting(self):
          self.notify.debug('enter: NoLighting')
          taskMgr.remove(self.waitTaskName)
          if self.transitionIval:
              self.transitionIval.pause()
              self.transitionIval = None
  
          render.clearLight(self.alight)
          render.clearLight(self.shadowLight)
          render.clearLight(self.sunLight)
          render.setFogOff()
          messenger.send('nametagAmbientLightChanged', [None])
          if self.nextDoLater:
              self.nextDoLater.remove()
              self.nextDoLater = None
  
      def exitNoLighting(self):
          self.notify.debug('exit: NoLighting')
          render.setLight(self.alight)
          render.setLight(self.sunLight)
          render.setLight(self.shadowLight)
          messenger.send('nametagAmbientLightChanged', [
              self.alight])
  
      def enterIndoors(self, todSettings=None):
          self.notify.debug('enterIndoors')
          self.currentState = PiratesGlobals.TOD_CUSTOM
          self.fixedSky = True
          self._prepareState(self.currentState)
          sunDir = TODGlobals.getTodEnvSetting(
              self.currentState, self.environment, 'Direction')
          self.skyGroup.setSunTrueAngle(sunDir)
          if hasattr(base, 'pe'):
              self._prepareState(PiratesGlobals.TOD_CUSTOM)
              self.setSkyClearColor(Vec4(0, 0, 0, 0), 1)
              base.setBackgroundColor(base.backgroundDrawable.getClearColor())
              self.linearFog.setColor(
                  TODGlobals.getTodEnvSetting(
                      PiratesGlobals.TOD_CUSTOM,
                      self.environment,
                      'FogColor'))
  
          if todSettings:
              if todSettings.get('AmbientColors') and todSettings['AmbientColors'].get(
                      self.currentState):
                  self.setFillLightColor(
                      todSettings['AmbientColors'][self.currentState])
  
              if todSettings.get('DirectionalColors') and todSettings['DirectionalColors'].get(
                      self.currentState):
                  self.setFrontLightColor(
                      todSettings['DirectionalColors'][self.currentState])
  
              if todSettings.get('BacklightColors') and todSettings['BacklightColors'].get(
                      self.currentState):
                  self.setBackLightColor(
                      todSettings['BacklightColors'][self.currentState])
  
              if todSettings.get('LightSwitches') and todSettings['LightSwitches'].get(
                      self.currentState):
                  self.setLightSwitch(
                      todSettings['LightSwitches'][self.currentState])
  
              if todSettings.get('SunDirections') and todSettings['SunDirections'].get(
                      self.currentState):
                  self.skyGroup.setSunTrueAngle(
                      todSettings['SunDirections'][self.currentState])
  
              if todSettings.get('FogColors') and todSettings['FogColors'].get(
                      self.currentState):
                  fogColor = todSettings['FogColors'][self.currentState]
                  self.linearFog.setColor(fogColor)
                  self.setSkyClearColor(fogColor, 1)
  
              if todSettings.get('LinearFogRanges') and todSettings['LinearFogRanges'].get(
                      self.currentState):
                  fogRanges = todSettings['LinearFogRanges'][self.currentState]
                  self.currFogOnset = fogRanges[0]
                  self.currFogPeak = fogRanges[1]
                  self.defaultFogOnset = self.currFogOnset
                  self.defaultFogPeak = self.currFogPeak
                  base.farCull.setPos(0, self.currFogPeak + 5, 0)
                  self.linearFog.setLinearRange(
                      self.currFogOnset, self.currFogPeak)
  
              if todSettings.get('FogRanges') and todSettings['FogRanges'].get(
                      self.currentState):
                  fogDensity = todSettings['FogRanges'][self.currentState]
                  self.setFogExpDensity(fogDensity)
  
              if todSettings.get('FogTypes') and todSettings['FogTypes'].get(
                      self.currentState):
                  fogType = todSettings['FogTypes'][self.currentState]
                  self.setFogType(fogType)
  
          messenger.send('timeOfDayChange', [
              self.currentState,
              0,
              0,
              0])
  
      def exitIndoors(self):
          self.notify.debug('exitIndoors')
          self.fixedSky = False
          base.positionFarCull()
  
      def enterOff(self):
          self.notify.debug('enter: Off')
          if self.transitionIval:
              self.transitionIval.pause()
              self.transitionIval = None
  
          self.disableAvatarShadows()
          taskMgr.remove(self.waitTaskName)
          render.clearLight(self.alight)
          render.clearLight(self.dlight)
          messenger.send('nametagAmbientLightChanged', [
              None])
          if self.nextDoLater:
              self.nextDoLater.remove()
              self.nextDoLater = None
  
      def exitOff(self):
          self.notify.debug('exit: Off')
          render.setLight(self.alight)
          render.setLight(self.dlight)
          if base.win and not base.win.isClosed():
              if base.config.GetBool('want-avatar-shadows', 1):
                  self.enableAvatarShadows()
  
          messenger.send('nametagAmbientLightChanged', [
              self.alight])
  
      def getTimeUntil(self, stateId):
          if not TODGlobals.isStateIdValid(self.cycleType, stateId):
              return self.cycleDuration
  
          (currStateId, remTime) = self._computeCurrentState()
          if currStateId == stateId:
              return -remTime
  
          while currStateId != stateId:
              currStateId = TODGlobals.getNextStateId(
                  self.cycleType, currStateId)
              stateDuration = TODGlobals.getStateDuration(
                  self.cycleType, currStateId) * self.cycleDuration
              remTime += stateDuration
          return remTime - stateDuration
  
      def setEnvironment(self, envId, envData=None):
          print 'setEnvironment %s %s %s' % (TODGlobals.ENVIRONMENT_NAMES.get(envId, 'unnamed'), envId, envData)
          envName = TODGlobals.ENVIRONMENT_NAMES.get(envId, 'Unknown')
          self.notify.debug('setEnvironment: %s' % envId)
          if self.environment == envId and envData is None:
              return None
  
          self.environment = envId
          if envData is not None:
              TODGlobals.ENV_SETTINGS_DICT[TODGlobals.ENV_DATAFILE] = envData
  
          self.fixedSky = False
          self.disableForcedState()
          self.enterInitState()
          messenger.send('environmentChanged')
  
      def setEnvEffect(self, effectNumber):
          if effectNumber != self.envEffect:
              self.stopEnvEffect(self.envEffect)
              self.startEnvEffect(effectNumber)
  
          self.envEffect = effectNumber
  
      def stopEnvEffect(self, envNum):
          if envNum == 0:
              pass
  
          if envNum == 1:
              self.envSound.stop()
              del self.envSound
              self.endAmbientSFX()
  
      def startEnvEffect(self, envNum):
          if envNum == 0:
              pass
  
          if envNum == 1:
              self.envSound = loader.loadSfx('audio/sfx_ocean_wind.mp3')
              self.envSound.setLoop(True)
              self.envSound.setVolume(0.69999999999999996)
              self.envSound.setPlayRate(1.0)
              self.envSound.play()
              self.startAmbientSFX()
  
      def registerAmbientSFXNode(self, node):
          if node not in self.ambientSFXList:
              self.ambientSFXList.append(node)
  
      def removeAmbientSFXNode(self, node):
          if node in self.ambientSFXList:
              self.ambientSFXList.remove(node)
  
      def runAmbientSFXTask(self, task=None):
          if not self.inAmbTime or self.closestNode is None:
              self.ambSound.setVolume(0.0)
              if task:
                  return task.cont
              else:
                  return None
  
          minDistance = self.closestNode.getDistance(base.cam)
          cutoff = 500.0
          fullrange = 50.0
          fullCut = cutoff + fullrange
          if minDistance <= fullCut and self.timeVol:
              volume = min(1.0, 1.0 - float(minDistance / fullCut))
              self.ambSound.setVolume(volume * self.timeVol)
          else:
              volume = 0
              self.ambSound.setVolume(0.0)
          if task:
              return task.cont
  
      def recalcClosestAmbNode(self, task=None):
          taskMgr.remove('ambientNodeSFXTask')
          minDistance = None
          self.closestNode = None
          for node in self.ambientSFXList:
              distance = node.getDistance(base.cam)
              if minDistance is None or distance < minDistance:
                  minDistance = distance
                  self.closestNode = node
                  continue
  
          taskMgr.doMethodLater(
              2.5,
              self.recalcClosestAmbNode,
              'ambientNodeSFXTask')
          timeStart = (5.5, 6.0)
          timeEnd = (20.0, 20.5)
          self.timeVol = 1.0
          timeCurrent = self.getCurrentIngameTime()
          if timeCurrent < timeStart[0] or timeCurrent > timeEnd[1]:
              self.timeVol = 0
              if self.inAmbTime:
                  self.envSound.stop()
                  self.ambSound.stop()
  
              self.inAmbTime = 0
          elif timeCurrent < timeStart[1]:
              timeDiff = timeStart[0] - timeStart[1]
              self.timeVol = 1.0 - (timeCurrent - timeStart[1]) / timeDiff
              if not self.inAmbTime:
                  self.envSound.play()
                  self.ambSound.play()
  
              self.inAmbTime = 1
          elif timeCurrent > timeEnd[0]:
              timeDiff = timeEnd[0] - timeEnd[1]
              self.timeVol = 1.0 - (timeEnd[0] - timeCurrent) / timeDiff
              if not self.inAmbTime:
                  self.envSound.play()
                  self.ambSound.play()
  
              self.inAmbTime = 1
          elif not self.inAmbTime:
              self.envSound.play()
              self.ambSound.play()
  
          self.inAmbTime = 1
          if self.environment == TODDefs.ENV_INTERIOR:
              self.timeVol = self.timeVol * 0.65000000000000002
  
          self.envSound.setVolume(0.69999999999999996 * self.timeVol)
          if task:
              return task.done
  
      def startAmbientSFX(self):
          self.ambSound = loader.loadSfx('audio/sfx_ocean_shore.mp3')
          self.ambSound.setLoop(True)
          self.ambSound.setVolume(0.0)
          self.ambSound.setPlayRate(1.0)
          self.ambSound.play()
          self.closestNode = None
          self.inAmbTime = 0
          self.recalcClosestAmbNode()
          taskMgr.add(self.runAmbientSFXTask, 'ambientRangeSFXTask')
  
      def endAmbientSFX(self):
          self.ambSound.stop()
          del self.ambSound
          del self.closestNode
          del self.inAmbTime
          taskMgr.remove('ambientRangeSFXTask')
          taskMgr.remove('ambientNodeSFXTask')
  
      def enableForcedState(self, state=None, gameArea=None):
          if state and gameArea:
              self.request(state, gameArea)
          elif state:
              self.request(state)
  
          self.forcedStateEnabled = True
  
      def disableForcedState(self):
          self.forcedStateEnabled = False
  
      def modifyWaterColor(self, color):
          self.lastWaterColor = color
          if not self.seapatch:
              return None
  
          if self.use_shader:
              v3Color = Vec3(color[0], color[1], color[2])
              if not self.seapatch.seamodel.isEmpty():
                  self.seapatch.modify_water_color_add_np(v3Color)
  
          elif not self.seapatch.isEmpty():
              self.seapatch.setColorScale(color)
  
      def modifyWaterColorFactor(self, colorFactor=None):
          self.lastWaterColorFactor = colorFactor
          if not self.seapatch:
              return None
  
          if colorFactor is None:
              self.waterColorFactor = Vec3(1.0, 1.0, 1.0)
          else:
              self.waterColorFactor = Vec3(
                  colorFactor[0], colorFactor[1], colorFactor[2])
          if self.use_shader:
              if not self.seapatch.seamodel.isEmpty():
                  self.seapatch.modify_water_color_factor_np(
                      self.waterColorFactor)
  
      def setSaintPatricksSea(self):
          if self.use_shader:
              self.modifyWaterColor(
                  VBase3(
                      0.22,
                      0.56000000000000005,
                      0.14999999999999999))
              self.modifyWaterColorFactor(
                  VBase3(
                      0.40000000000000002,
                      1.0,
                      0.29999999999999999))
          else:
              self.modifyWaterColor(
                  VBase4(
                      0.25,
                      0.90000000000000002,
                      0.20000000000000001,
                      1.0))
              self.modifyWaterColorFactor()
  
      def handleHolidayStarted(self, holidayName):
          pass
  
      def handleHolidayEnded(self, holidayName):
          pass
  
      def setFogColor(self, fogColor):
          self.fogColor = fogColor
          if self.linearFog:
              self.linearFog.setColor(fogColor)
  
          if self.fog:
              self.fog.setColor(fogColor)
  
      def getFogColor(self):
          return self.fogColor
  
      def setFogMask(self, fogMask):
          self.fogMask = fogMask
          self.setFogType(self.fogType, 1)
  
      def setFogType(self, fogType, override=0):
          if fogType != self.fogType or override:
              render.clearFog()
              self.fogType = fogType
              if not self.fogMask:
                  if self.fogType == TODGlobals.FOG_EXP:
                      self.fog.setExpDensity(self.fogExpDensity)
                      self.fog.setColor(self.fogColor)
                      render.setFog(self.fog)
                  elif self.fogType == TODGlobals.FOG_LINEAR:
                      self.linearFog.setColor(self.fogColor)
                      base.farCull.setPos(0, self.currFogPeak + 5, 0)
                      self.linearFog.setLinearRange(self.currFogOnset, self.currFogPeak)
                      render.setFog(self.linearFog)
  
      def setLinearFogOnset(self, onset):
          self.currFogOnset = onset
          self.linearFog.setLinearRange(self.currFogOnset, self.currFogPeak)
  
      def setLinearFogPeak(self, peak):
          self.currFogPeak = peak
          self.linearFog.setLinearRange(self.currFogOnset, self.currFogPeak)
          base.farCull.setPos(0, self.currFogPeak + 5, 0)
  
      def setFogExpDensity(self, newValue):
          self.fogExpDensity = newValue
          if self.fog:
              if hasattr(base, 'localAvatar') and base.localAvatar.ship:
                  self.fog.setExpDensity(
                      self.fogExpDensity * TODGlobals.SHIP_FOG_MULT)
              else:
                  self.fog.setExpDensity(self.fogExpDensity)
  
      def getFogExpDensity(self):
          return self.fogExpDensity
  
      def switchFogDensity(self, onShip):
          if onShip:
              self.fog.setExpDensity(
                  self.fogExpDensity *
                  TODGlobals.SHIP_FOG_MULT)
          else:
              self.fog.setExpDensity(self.fogExpDensity)
  
      def restoreLinearFog(self):
          return None
          if self.currFogOnset == self.defaultFogOnset and self.currFogPeak == self.defaultFogPeak:
              return None
  
          self.lerpLinearFog(self.defaultFogOnset, self.defaultFogPeak)
  
      def lerpLinearFog(self, targetOnset, targetPeak, lerpTime=1.0):
          if self.lerpFogIval:
              self.lerpFogIval.pause()
  
          baseOnset = self.currFogOnset
          basePeak = self.currFogPeak
  
          def setLinearFog(v):
              self.currFogOnset = baseOnset * (1 - v) + targetOnset * v
              self.currFogPeak = basePeak * (1 - v) + targetPeak * v
              base.farCull.setPos(0, self.currFogPeak + 10, 0)
              self.linearFog.setLinearRange(self.currFogOnset, self.currFogPeak)
  
          self.lerpFogIval = LerpFunctionInterval(
              setLinearFog,
              duration=lerpTime,
              fromData=0.0,
              toData=1.0,
              name='LerpFogIval')
          self.lerpFogIval.start()
  
      def getEnviroDictString(self, environment=None, tabs=0, heading='SettingsDict ='):
          if environment is None:
              environment = self.environment
  
          envDict = TODGlobals.ENV_SETTINGS_DICT[environment]
          tab = '    '
          outputString = ''
          outputString += tab * tabs
          outputString += '%s {' % heading
          outputString += '\n'
          for timeIndex in TODGlobals.INORDER_TOD_LIST:
              timeName = TODGlobals.StateDict.get(timeIndex)
              timeDict = envDict.get(timeName)
              if timeDict and timeDict != {}:
                  outputString += tab * tabs
                  outputString += '    "%s" : {' % timeName
                  outputString += '\n'
                  for timeSettingName in TODGlobals.TOD_ATTRIBUTES:
                      timeSetting = timeDict.get(timeSettingName)
                      if timeSetting is not None:
                          if timeSettingName == 'FogType':
                              timeSetting = TODGlobals.FOG_CODES[timeSetting]
                          elif timeSettingName == 'SkyType':
                              timeSetting = TODGlobals.SKY_CODES[timeSetting]
  
                          outputString += tab * tabs
                          outputString += '        "%s" : %s,' % (
                              timeSettingName, timeSetting)
                          outputString += '\n'
                          continue
  
                  outputString += tab * tabs
                  outputString += '        },'
                  outputString += '\n'
                  continue
  
          outputString += tab * tabs
          outputString += '}'
          return outputString
  