Sujet n°13916
Posté par Moy le 29 Juin - 23:33 (2014)
Titre : ATES 1.01
Voilà la mise à jour du script de Blizzard et ThallionDarkshine dispo à cette adresse : http://forum.chaos-project.com/index.php/topic,12869.0

Je sais que le script est déjà présent sur PSP mais ce n'est que la version 0.4, celle actuelle est la 1.01. De nombreuses fonctionnalités ont été ajoutés, il y à bien sûr la gestion de l'heure, de la teinte de l'écran par rapport au moment de la journée, des jours de la semaine,des mois, des nombres de jours dans tel ou tel mois, des jours spéciaux (comme noël, le jour de l'an, la fête des mére etc ...), des saisons, météo par rapport à la saison et au type de la map (désert, plage, plaine ...), de la température ...

Voilà sans plus attendre le script traduit le mieux possible par Moy :
Spoiler
Code:

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Advanced Time and Environment System (ATES) par Blizzard et ThallionDarkshine
# Version: 1.0
# Type: Contrôleur autonome de l'écoulement du temps et de l'environnement
# Date v0.3: 11.3.2008
# Date v0.31: 8.4.2009
# Date v0.32: 13.4.2009
# Date v0.33: 4.5.2009
# Date v0.34: 5.5.2009
# Date v1.0: 12.2.2013
# Traduction française par Moy
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#   
#  Ce travail est protégé par la licence qui suit:
# #----------------------------------------------------------------------------
# # 
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# # 
# #  Vous êtes autorisé à :
# #
# #  Partager — copier, distribuer et communiquer le matériel par tous moyens et sous tous formats
# #  Adapter — remixer, transformer et créer à partir du matériel
# # 
# #  Sleon les conditions suivantes:
# # 
# #  Attribution. Vous devez attribuer l'oeuvre de la manière indiquée par
# #  l'auteur original (mais pas d'une manière qui suggérere qu'il
# #  approuve votre utilisation de l'oeuvre).
# # 
# #  Non commercial. Vous ne devez pas utiliser ce travail à des fins commerciales.
# # 
# #  Partage à l'identique. Si vous modifiez, transformez ou adaptez cette création, vous pouvez
# #  distribuer l'œuvre résultante sous la même licence ou l'une similaire à
# #  celle-ci.
# # 
# #  - A chaque réutilisation ou distribution, vous devez faire apparaître clairement aux autres
# #    les termes de la licence de ce travail. La meilleure façon de le faire est avec un lien
# #    vers cette page web.
# # 
# #  - Chacune de ces conditions peut être levée si vous obtenez l'autorisation du
# #    titulaire du droit d'auteur.
# # 
# #  - Rien dans ce contrat ne diminue ou ne restreint le droit moral de l'auteur.
# # 
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# Compatibilité:
#
#   99% compatible avec SDK v1.x. 90% compatible avec SDK 2.x. Va corrompre vos
#    anciennes sauvegardes. Peut causes des problèmes d'incompatibilité avec DNS-es.
#
#
# Caractéristiques:
#
#   - Contrôle complet et facile de la manipulation du temps et la météo
#   - Teintes Jour/Nuit personalisables
#   - HUD facultatif
#   - Plus facile à contrôler et plus puissant que DDNS
#
#
# NOTES IMPORTANTES:
#
# - Ce système a une préconfiguration de travail, soyez conscient qu'une
#   configuration personnalisée aura besoin que vous comprenez chaques options,
#   donc s'il vous plaît lisez les instructions de configuration.
# - Pourquoi ce système utilise des interrupteurs pour déterminer si c'est le jour ou la nuit ?
#   Simple: Vous pouvez utiliser des conditions dans les attaques ennemies afin de déterminer si une
#   attaque doit être utilisé uniquement la nuit ou le jour.
#
#
# Instructions:
#
# - Explication:
#
#   Ce système de temps créra pour votre jeu des périodes de jour et de nuit.
#   L'écran sera teinté en conséquence. Vous pouvez configurer la durée du
#   jour. Les autres caractéristiques sont expliqué ci-dessous.
#   S'il vous plaît soyer sûr de configurer ce système de manière appropriée.
#
#
# - Manipulations basiques d'ATES:
#
#   Ce système travaillera essentiellement si vous le voulez,
#   mais avec un peu d'utilisation d'appel de script vous êtes en mesure de contrôler ce système entièrement.
#   Vous pouvez appeler les commandes suivantes:
#
#     ATES.on
#   Active ATES.
#
#     ATES.off
#   Désactive ATES.
#
#     ATES.tint_on
#   Active le teintement de l'écran d'ATES.
#
#     ATES.tint_off
#   Désactive le teintement de l'écran d'ATES.
#
#     ATES.clock_on
#   Active l'affichage de l'heure d'ATES
#
#     ATES.clock_off
#   désactive l'affichage de l'heure d'ATES
#
#     ATES.active?
#   Retourne "true" si ATES tourne, autrement c'est "false".
#
#     ATES.tinting?
#   Retourne "true" si le teintement de l'écran d'ATES tourne, autrement c'est "false".
#
#     ATES.day?
#   Retourne "true" si c'est le jour, autrement c'est "false". Alternativement
#   vous pouvez vérifié l'interrupteur assigné à la place.
#
#     ATES.night?
#   Retourne "true" si c'est la nuit, autrement c'est "false". Alternativement
#   vous pouvez vérifié l'interrupteur assigné à la place.
#   
#     ATES.advance(M, H)
#   Va avancer le temps de M minutes et H heures. Toutes valeurs
#   négatives annulent l'éxécution de la commande.
#   
#     ATES.make_it_day
#   C'est une caractéristique de DDNS qui permet de sauter rapidement vers la journée.
#   
#     ATES.make_it_night
#   C'est une caractéristique de DDNS qui permet de sauter rapidement vers la nuit.
#   
#     ATES.weather_on
#   Permet d'activer la météo.
#
#     ATES.weather_off
#   Permet de désactiver la météo.
#
#     ATES.lock_weather
#   Permet de blocker le temps actuel sans désactiver la météo.
#
#     ATES.unlock_weather
#   Permet de déblocker la météo.
#
#     ATES.weather_active?
#   Retourne "true" si la météo est activer, sinon "false".
#
#     ATES.set_time(TIME_INDEX or TIME_NAME)
#   Définis l'heure actuel par rapport à l'heure de l'index de TIME_INDEX ou avec
#   le nom de TIME_NAME. Mieux vaut utiliser TIME_NAME car quelques bug peuvent survenir
#   à l'utilisation de TIME_INDEX.
#
#     ATES.go_inside
#   Une caractéristique de DDNS permettant de changer le mode de lumière pour l'intérieur.
#
#     ATES.go_inside_dark
#   Une caractéristique de DDNS permettant de changer le mode de lumière pour un intérieur sombre.
#
#     ATES.go_outside
#  Une caractéristique de DDNS permettant de changer le mode de lumière pour l'extérieur.
#
#     ATES.set_weather(INDEX)
#   Configure la météo par rapport à INDEX.
#
#     ATES.terrain=(TERRAIN_NAME)
#   Configure le terrain par rapport à TERRAIN_NAME.
#
#     ATES.time_name
#   Retourne le nom du moment de la journée.
#
# - Conseils d'amélioration:
#
#   Si vous souhaitez mettre en œuvre le DDNS plus loin dans votre jeu et, par exemple
#   permettre des comportements différents de monstres durant la journée et la nuit,
#   il vous suffit de vérifier l'état ​​de l'interrupteur approprié. Par exemple
#   si NSwitch est activée infliger "Sleep" sur un ennemi.
#
#
# Info additionelle:
#
#   Les teites jour/nuit ont été testés de manière appropriée et les teints optimales
#   sont utilisé.
#   Gardez à l'esprit que ATES est initialement désactivée, vous devez l'activer en
#   utilisant les ATES.on et ATES.tint_on ensembles. (Note trad. : faux !)
#
# Si vous trouvez des bugs, reportez les ici :
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

module ATES
 
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # ID de l'interrupteur du jour.
  DSWITCH = 51
  # ID de l'interrupteur de la nuit.
  NSWITCH = 52
  # ID de la varible de la température.
  TVARIABLE = 51
  # Durée d'une journée en secondes dans le jeu, ne peut pas être inférieur à 36.
  # Ici une minute dans le jeu est égale à 2 seconde IRL.
  LENGTH = 2880
  # Le montant à multiplier pour entendre le son de la météo de l'intérieur.
  INSIDE_SOUND = 0.7
  # le montant à multiplier pour les tons rouge, vert, bleu et gris quand à
  # on est à l'intérieur.
  INSIDE_TONE = 0.0
  # La teintes des intérieurs sombres.
  DARK_INSIDE_TONE = Tone.new(-85, -85, -85, 85)
  # Config de la météo, créez des nouvelles météo ici
  #  note - si vous ne voulez pas un certain effet comme la météo, le brouillard ou le son,
  #         il suffit de laisser le tableau pour cet effet vide.
  #          ['NOM', RIGUEUR_CLIMAT, [TYPE_CLIMAT, FAIBLE_RESISTANCE..HAUTE_RESISTANCE],
  #            [NOM_SON, VOLUME_MIN_SON..VOLUME_MAX_SON, HAUTEUR_SON], [NOM_BROUILLARD, OPACITE_BROUILLARD, NUANCE_BROUILLARD,
  #            ZOOM_BROUILLARD, BROUILLARD_SX, BROUILLARD_SY, [TON_ROUGE, TON_VERT, TON_BLEU, TON_GRIS]],
  #            [NOM_SON_EFFET, VOLUME_MIN_SON..VOLUME_MAX_SON, HAUTEUR_SON, PROBABILITE_EFFET,
  #            DUREE_FLASH, [COULEUR_FLASH_ROUGE, COULEUR_FLASH_VERT, COULEUR_FLASH_BLEU]]]
  WEATHER = [['Crachin', 0, 1..4, [1], ['005-Rain01', 65..80, 100], [], []],
             ['Pluie', 0, 5..8, [1], ['006-Rain02', 75..90, 100], [], ['061-Thunderclap01', 60..85, 100, 0.07, 4, [255, 255, 255]]],
             ['Orage', 1, 9..10, [1], ['007-Rain03', 80..100, 100], [], ['061-Thunderclap01', 70..95, 110, 0.08, 6, [255, 255, 255]]],
             ['Couvert', 0, 1..1, [], [], ['002-Clouds01', 60, 0, 200, 4, 3, [0, 0, 0, 0]], []],
             ['Pluie', 0, 1..4, [2], ['006-Rain02', 70..85, 100], [], ['061-Thunderclap01', 65..90, 110, 0.08, 6, [255, 255, 255]]],
             ['Orage', 1, 5..8, [2], ['007-Rain03', 75..90, 100], [], ['061-Thunderclap01', 70..95, 110, 0.09, 7, [255, 255, 255]]],
             ['Orage', 2, 9..10, [2], ['007-Rain03', 90..100, 100], [], ['061-Thunderclap01', 85..100, 110, 0.11, 7, [255, 255, 255]]],
             ['Rafale', 1, 1..4, [3], ['002-Wind02', 70..85, 100], [], []],
             ['Neige', 1, 5..8, [3], ['003-Wind03', 80..95, 100], [], []],
             ['Blizzard', 2, 9..10, [3], ['004-Wind04', 85..100, 100], [], []]]
  # Durée normale de la météo en seconde.
  WEATHER_DURATION = 1140
  # Variation de la météo en seconde.
  WEATHER_VARIANCE = 480
  # Nom du temps par défault (ce qui est motré sur l'HUD quand
  # il n'y à pas de météo spéciale).
  DEFAULT_WEATHER_NAME = 'Soleil'
  # Config des saisons, créez de nouvelles saison en utilisant ce modéle :
  #          ['NOM', JOUR_COMMENCANT, MOIS_COMMENCANT, TEMPERATURE_MIN..TEMP_MAX, PROBABILITE_TEMPS,
  #            PROBABILITE_MAUVAIS_TEMPS, PROBABILITE_TRES_MAUVAIS_TEMPS, [POSSIBILITE_TEMPS]]
  SEASONS = [
             ['Printemps', 22,  3,   0..25, 0.003, 0.3, 0.05, [0, 1, 2, 3, 4, 5]] ,
             ['Eté', 21,  6,  20..35, 0.003, 0.1, 0.2, [0, 1, 3, 4, 5, 6]]  ,
             ['Automne', 20,  9,   0..25, 0.003, 0.2, 0.1, [0, 2, 3, 4, 5, 7]]  ,
             ['Hiver', 21, 12, -20..5, 0.003, 0.5, 0.1, [0, 2, 3, 4, 7, 8, 9]]
            ]
  # Cconfi terrain, créez de nouveaux terrain en utilisant ce modéle :
  #          ['NOM', TEMP_MIN..TEMP_MAX, TEMPS_EXCLU]
  TERRAINS = [
              ['Forêt', -7..0, [3]],
              ['Désert', 11..16, [8, 9]],
              ['Montagne', -9..-4, []],
              ['Plaine', -2..0, []],
              ['Plage', -5..-2, [8, 9]]
             ]
  # Date du jour le plus long, la plus longue nuit est une demi année plus tôt/tard.
  LONGEST = [21, 6]
  # Début de la journée.
  DAY_START = "Matin"
  # Début de la nuit.
  NIGHT_START = "Crépuscule"
  # Les différentes modification de teintes et différence de température à certain moment da la journée pendant les plus longs et plus courts jours.
  # Pour créer un nouveau moment dans la journé, ajouter ceci à TIMES : NOM => [ROUGE, VERTE, BLEU, GRIS, MODIFICATEUR_TEMP]
  TIMES = {
           "Aube" => [-17, -17, 17, 0, -4],
           "Matin" => [48, 30, 30, 0, -2],
           "Midi" => [24, 10, 10, 0, 5],
           "Soir" => [57, -17, -17, 0, 1],
           "Crépuscule" => [-17, -17, 17, 0, -3],
           "Nuit" => [-150, -120, -120, 200, -8]
          }
  # Quand vous les avez personnalisé, mettre les tons dans LONG_TIMES et SHORT_TIMES avec [nom_du_moment, heure, minute]
  LONG_TIMES = [["Aube", 4, 30],
                ["Matin", 5, 30],
                ["Midi", 13, 00],
                ["Soir", 21, 00],
                ["Crépuscule", 22, 00],
                ["Nuit", 1, 30]]
  SHORT_TIMES = [["Aube", 6, 30],
                ["Matin", 7, 30],
                ["Midi", 13, 00],
                ["Soir", 16, 30],
                ["Crépuscule", 17, 00],
                ["Nuit", 23, 30]]
  # rendre l'écran plus lumineux pendant les jours d'été.
  OVERLIGHTING = true
  # rendre l'écran plus sombre pendant la nuit, non recommandé.
  OVERDARKENING = false
  # la premiére année du calendrier, le joueur ne peut allé défiler avant.
  FYEAR = 1990
  # la dernière année du calendrier, le joueur ne peut allé défiler après.
  LYEAR = 2099
  # le suffixe des température
  TEMP_SUFFIX = "°C"
  # les différentes vacances et leurs dates
  #   le format pour ajouter de nouvelles vacances est:
  #     [NOM, TYPE_CONFIG, MOIS, (JOUR ou JOUR_SEMAINE, NOMBRE)]
  #   si vous souhaitez utiliser JOUR ou JOUR_SEMAINE, NOMBRE dépend de SETUP_TYPE:
  #     (0 - JOUR; 1 - JOUR_SEMAINE, NOMBRE)
  # note - Les vacances du moment remplace le nom du jour sur l'HUD
  HOLIDAYS = [
               ["Noël", 0, 11, 24],
               ["Nouvel An", 0, 0, 0],
               ["Thanksgiving", 1, 10, 4, 4],
               ["Jour de la Marmotte", 0, 1, 1],
               ["St Valentin", 0, 1, 13],
               ["Jour de la Terre", 0, 3, 21],
               ["Jour de l'arbre", 1, 3, 5, -1],
               ["Fête des Mére", 1, 5, 7, 3],
               ["Fête des Pére", 1, 6, 7, 3],
               ["Halloween", 0, 9, 30],
             ]
  # Format de l'HUD
  # par default : ['%H:%M%s', '%A', '%d/%m/%Y', '%S']
  # cela veut dire : 1ere rangée - "HEURES:MINUTES SUFFIXE"
  #                  2nd  rangée - "JOUR_SEMAINE"
  #                  3eme rangée - "JOUR/MOIS/ANNEE"
  #                  4eme rangée - "SAISON"
  # utilisez [] pour ne pas avoir d'HUD
  # differentes combinaisons à mettre pour l'HUD :
  #   %H - Heure
  #   %M - Minute
  #   %s - Suffixe (AM or PM) (only if not using 24 hour time)
  #   %A - Jour de la semaine
  #   %d - Jour du mois
  #   %D - Jour de l'année
  #   %m - Mois
  #   %n - Nom du mois
  #   %l - Durée du mois
  #   %Y - Année
  #   %L - Durée année
  #   %S - Saison
  #   %w - Temps 
  #   %t - Terrain
  #   %T - Température
  #   %p - Moment de la journée
  CFORMAT = ['%H:%M', '%d/%m/%Y', '%A', '%w']
  # largeur de l'HUD
  CWIDTH = 180
  # noms de vos jours, définit automatiquement la longueur d'une semaine
  WEEKDAYS = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi',
              'Samedi']
  WEEKDAY_ABBREVIATIONS = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam']
  # Noms de vos mois, définit automatiquement la longueur d'une année
  MONTHS = ['Janvier', 'Fevrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet',
            'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre']
  # Abbréviation du noms des mois
  MONTH_ABBREVIATIONS = ['Jan', 'Fev', 'Mars', 'Avr', 'Mai', 'Juin', 'Jui',
                         'Aout', 'Sept', 'Oct', 'Nov', 'Dec']
  # jours par mois
  MONTHDAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  # le premier jour dans le jeu [JOUR, MOIS, ANNÉE, SEMAINE]
  # définir cette option à [] si vous voulez que le jeu commence "maintenant"
  START = [29, 6, 2014, 1]
  # définir cette option à true pour activer le temps militaire (sur 24 heures)
  HOUR24 = true
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
  mon = (LONGEST[1] + MONTHS.length / 2) % 12
  mon = 12 if mon == 0
  day = LONGEST[0] + (MONTHS.length % 2) == 1 ? MONTHDAYS[mon - 1] / 2 : 0
  while day > MONTHDAYS[mon - 1]
    day -= MONTHDAYS[mon - 1]
    mon = (mon + 1) % 12
    mon = 12 if mon == 0
  end
  SHORTEST = [day, mon]

  $ates = 1.0
 
  #============================================================================
  # ATES::Time
  #============================================================================
 
  class Time
   
    attr_accessor :min
    attr_accessor :hour
    attr_accessor :day
    attr_accessor :mon
    attr_accessor :year
    attr_accessor :wday
   
    def initialize(m, h, d, mon, y, w)
      @min, @hour, @day, @mon, @year, @wday = m, h, d, mon, y, w
    end
   
  end
 
  def self.on
    $game_system.ates.active = true
    return true
  end
 
  def self.off
    $game_system.ates.active = false
    return true
  end
 
  def self.tint_on(frames = 0)
    $game_screen.start_tone_change($game_system.ates.get_environment[0], frames)
    $game_system.ates.tinting = true
    return true
  end
 
  def self.tint_off(reset = true)
    $game_screen.start_tone_change(Tone.new(0, 0, 0, 0), 0) if reset
    $game_system.ates.tinting = false
    return true
  end
 
  def self.weather_off
    $game_system.ates.weather.weather_enabled = false
    $game_system.ates.weather.pause_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
  end
 
  def self.weather_on
    $game_system.ates.weather.weather_enabled = true
    $game_system.ates.weather.resume_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
  end
 
  def self.weather_active?
    return $game_system.ates.weather.weather_enabled
  end
 
  def self.lock_weather
    $game_system.ates.weather.locked = true
  end
 
  def self.unlock_weather
    $game_system.ates.weather.locked = false
  end
 
  def self.clock_on
    $game_system.show_clock = true
    return true
  end
 
  def self.clock_off
    $game_system.show_clock = false
    return true
  end
 
  def self.active?
    return $game_system.ates.active
  end
 
  def self.tinting?
    return $game_system.ates.tinting
  end
 
  def self.day?
    i = $game_system.ates.time_index
    while true
      if $game_system.ates.current_times[i][0] == DAY_START
        return true
      elsif $game_system.ates.current_times[i][0] == NIGHT_START
        return false
      end
     
      i = (i + $game_system.ates.current_times.length - 1) % $game_system.ates.current_times.length
    end
  end
 
  def self.night?
    return !(self.day?)
  end
 
  def self.make_it_day
    time = $game_system.ates.current_times.select { |time| time[0] == DAY_START }
    h, m = time[0][1], time[0][2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.make_it_night
    time = $game_system.ates.current_times.select { |time| time[0] == NIGHT_START }
    h, m = time[0][1], time[0][2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.set_time(time = 0)
    return unless $game_system
    if time.is_a?(Fixnum)
      time = $game_system.ates.current_times[time.to_i]
    else
      time = $game_system.ates.current_times.select { |current_time| current_time[0] == time }[0]
    end
    h, m = time[1], time[2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.day_start
    return DAY_START
  end
 
  def self.night_start
    return NIGHT_START
  end
 
  def self.go_inside_dark
    weather = $game_system.ates.weather.current_weather
    $game_system.ates.map_type = 2
    self.tint_on
    $game_system.ates.weather.pause_weather(0)
    return true if weather == -1
    low, high = weather[2].first, weather[2].last
    intensity = $game_system.ates.weather.current_intensity
    if weather[4].length > 0
      volume = ATES::INSIDE_SOUND * weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
      $game_system.bgs_play(bgm)
    end
    return true
  end
 
  def self.go_inside
    weather = $game_system.ates.weather.current_weather
    $game_system.ates.map_type = 1
    self.tint_on
    $game_system.ates.weather.pause_weather(0)
    return true if weather == -1
    low, high = weather[2].first, weather[2].last
    intensity = $game_system.ates.weather.current_intensity
    if weather[4].length > 0
      volume = ATES::INSIDE_SOUND * weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
      $game_system.bgs_play(bgm)
    end
    return true
  end
 
  def self.go_outside
    $game_system.ates.weather.resume_weather(0)
    $game_system.ates.map_type = 0
    self.tint_on
    return true
  end
 
  def self.set_weather(id)
    $game_system.ates.weather.set_weather(WEATHER[id])
  end
 
  def self.terrain=(terrain)
    terrain = TERRAINS[terrain.to_i][0] if terrain.is_a?(Fixnum)
    $game_system.ates.terrain = terrain
  end
 
  def self.advance(m, h, d, mon, y)
    return false if [m, h, d, mon, y].any? {|i| i < 0}
    changed = false
    h += ($game_system.ates.time.min + m) / 60
    $game_system.ates.time.min = ($game_system.ates.time.min + m) % 60
    d += ($game_system.ates.time.hour + h) / 24
    changed = true if d > 0
    $game_system.ates.time.hour = ($game_system.ates.time.hour + h) % 24
    while d > 0
      if $game_system.ates.time.day < MONTHDAYS[mon]
        $game_system.ates.time.day += 1
      else
        $game_system.ates.time.day = 0
        mon = (mon + 1) % MONTHS.size
      end
      $game_system.ates.time.wday += 1
      $game_system.ates.time.wday %= WEEKDAYS.size
      d -= 1
    end
    y += ($game_system.ates.time.mon + mon) / MONTHS.size
    $game_system.ates.time.mon = ($game_system.ates.time.mon + mon) % MONTHS.size
    $game_system.ates.time.year += y
    return changed
  end
 
  def self.time_name
    return $game_system.ates.current_times[$game_system.ates.time_index][0]
  end
 
end

if ATES::MONTHS.size > ATES::MONTHDAYS.size
  raise 'ATEScfgError: Not all months have a length in days specified!'
#elsif ATES::DAY_START > ATES::NIGHT_START
#  raise 'ATEScfgError: A night can\'t start earlier than a day.'
elsif ATES::LENGTH < 36
  raise 'ATEScfgError: A day\'s length must be equal to or greater than 36 seconds!'
end

#==============================================================================
# Weather
#==============================================================================

class Weather
  attr_accessor :current_weather, :current_intensity, :weather_enabled, :locked
 
  def initialize
    @current_weather = -1
    @current_intensity = 0
    @normal_weather = []
    @bad_weather = []
    @very_bad_weather = []
    @weather_enabled = true
    @locked = false
  end
 
  def decimal_places(num)
    if num.is_a?(Float)
      return num.to_s.split('.')[1].length
    else
      return 0
    end
  end
 
  def get_weather(severity = 0)
    weather = []
    season = $game_system.ates.get_full_season
    ATES::WEATHER.each_with_index { |el, ind|
      weather.push(el) if el[1] == severity and season[7].include?(ind)
    }
    return weather
  end
 
  def update
    season = $game_system.ates.get_full_season
    if !@season or @season != season
      @normal_weather = get_weather
      @bad_weather = get_weather(1)
      @very_bad_weather = get_weather(2)
      @season = season
    end
    unless @locked
      places = [decimal_places(season[4]), decimal_places(season[5]), decimal_places(season[6])]
      if rand(10 ** places[0]) <= season[4] * (10 ** places[0]) and season[7].length > 0
        if rand(10 ** places[1]) <= season[4] * (10 ** places[1]) and @bad_weather.length > 0
          weather = rand(@bad_weather.length)
          weather = @bad_weather[weather]
          set_weather(weather)
        elsif rand(10 ** places[2]) <= season[4] * (10 ** places[2]) and @very_bad_weather.length > 0
          weather = rand(@very_bad_weather.length)
          weather = @very_bad_weather[weather]
          set_weather(weather)
        elsif @normal_weather.length > 0
          weather = rand(@normal_weather.length)
          weather = @normal_weather[weather]
          set_weather(weather)
        end
      end
    end
    if @current_weather != -1
      update_effect if @weather_enabled and @current_weather[6].length > 0
      @weather_count += 1
      if @weather_count >= @weather_duration
        stop_weather unless @locked
      end
    end
  end
 
  def update_effect
    weather = @current_weather
    places = decimal_places(weather[6][3])
    if rand(10 ** places) <= weather[6][3] * 10 ** places
      high, low = weather[2].first, weather[2].last
      vol = weather[6][1].first + (weather[6][1].last - weather[6][1].first) * (high - @current_intensity).to_f / (high - low)
      vol *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
      sound = RPG::AudioFile.new(weather[6][0], vol, weather[6][2])
      $game_system.se_play(sound)
      col = Color.new(0, 0, 0)
      $game_screen.start_flash(Color.new(*weather[6][5]), weather[6][4])
    end
  end
 
  def stop_weather(speed = -1)
    return if @current_weather == -1
    speed = speed == -1 ? rand(10) + 60 : speed
    if @current_weather[3].length > 0
      $game_screen.weather(0, 1, speed)
    end
    if @current_weather[4].length > 0
      $game_system.bgs_fade(speed.to_f / 40)
    end
    if @current_weather[5].length > 0
      $game_map.fog_name = ''
    end
    @current_weather = -1
  end
 
  def pause_weather(speed = -1)
    return if @current_weather == -1
    $game_system.ates.show_weather = false
    speed = speed == -1 ? rand(10) + 60 : speed
    if @current_weather[3].length > 0
      $game_screen.weather(0, 1, speed)
    end
    if @current_weather[4].length > 0
      $game_system.bgs_fade(speed.to_f / 40)
    end
    if @current_weather[5].length > 0
      $game_map.fog_name = ''
    end
  end
 
  def resume_weather(speed = -1)
    return if @current_weather == -1
    $game_system.ates.show_weather = true
    weather = @current_weather
    intensity = @current_intensity
    low, high = weather[2].first, weather[2].last
    speed = speed == -1 ? rand(10) + 60 : speed
    if weather[3].length > 0
      $game_screen.weather(weather[3][0], intensity, speed)
    end
    if weather[4].length > 0
      volume = weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
      $game_system.bgs_play(bgm)
    end
    if weather[5].length > 0
      $game_map.fog_name = weather[5][0]
      $game_map.fog_opacity = weather[5][1]
      $game_map.fog_hue = weather[5][2]
      $game_map.fog_zoom = weather[5][3]
      $game_map.fog_sx = weather[5][4]
      $game_map.fog_sy = weather[5][5]
      $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
    end
  end
 
  def set_weather(weather, speed = -1)
    stop_weather if @current_weather != -1
    @weather_count = 0
    @weather_duration = ATES::WEATHER_DURATION + rand(ATES::WEATHER_VARIANCE)
    low, high = weather[2].first, weather[2].last
    intensity = rand(high + 1 - low) + low
    @current_weather = weather
    @current_intensity = intensity
    return unless @weather_enabled
    if weather.is_a?(Fixnum)
      weather = WEATHER[weather]
    end
    speed = speed == -1 ? rand(10) + 60 : speed
    if weather[4].length > 0
      volume = weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
      volume *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
      bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
      $game_system.bgs_play(bgm)
    end
    return if $game_system.ates.map_type > 0
    if weather[3].length > 0
      if $modified_aws and weather[3].length > 1
        $game_screen.weather(weather[3][0], intensity, speed, weather[3][1])
      else
        $game_screen.weather(weather[3][0], intensity, speed)
      end
    end
    if weather[5].length > 0
      $game_map.fog_name = weather[5][0]
      $game_map.fog_opacity = weather[5][1]
      $game_map.fog_hue = weather[5][2]
      $game_map.fog_zoom = weather[5][3]
      $game_map.fog_sx = weather[5][4]
      $game_map.fog_sy = weather[5][5]
      $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
    end
  end
end

#==============================================================================
# Game_System
#==============================================================================

class Game_System
 
  attr_accessor :ates
  attr_accessor :show_clock
 
  alias init_ates_later initialize
  def initialize
    init_ates_later
    @ates = Game_ATES.new
    @show_clock = (ATES::CFORMAT != [])
  end

end

#==============================================================================
# Game_ATES
#==============================================================================

class Game_ATES
 
  attr_accessor :active
  attr_accessor :tinting
  attr_accessor :time
  attr_accessor :weather
  attr_accessor :frame_count
  attr_accessor :current_times
  attr_accessor :tone
  attr_accessor :map_type
  attr_accessor :show_weather
  attr_accessor :terrain
  attr_accessor :temp
  attr_reader   :holiday
  attr_reader   :time_index
 
  def initialize
    if ATES::START.size == 4
      @time = ATES::Time.new(0, 0, ATES::START[0], ATES::START[1],
          ATES::START[2], ATES::START[3])
    else
      @time = Time.now
      @time = ATES::Time.new(@time.min, @time.hour, @time.mday, @time.mon, @time.year, @time.wday)
    end
    @weather = Weather.new
     
    @long_times = ATES::LONG_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <= t2[1] * 100 + t2[2] }
    @short_times = ATES::SHORT_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <= t2[1] * 100 + t2[2] }
   
    @year_length = ATES::MONTHDAYS.inject { |sum, x| sum + x }
   
    @terrain = ''
    @current_times = setup_times
    @temp_modifier = (rand(201) - 100) / 100.0
    @tone, @temp = get_environment
    @holiday = get_holiday(@time.mon, @time.day, @time.wday)
    @s_time = get_time(@time.min, @time.hour)
    $game_screen.start_tone_change(@tone, 0) if $game_screen
   
    @active = true
    @tinting = true
    @show_weather = true
    @map_type = 0
    @frame_count = 0
  end
 
  def get_holiday(month, day, wday)
    ATES::HOLIDAYS.select { |i|
      case i[1]
      when 0:
        i[2..3] == [month, day]
      when 1:
        if i[4] > 0
          i[2] == month and i[3] == wday and i[4] == (day.to_f / 7 + 1).floor
        elsif i[4] < 0
          i[2] == month and i[3] == wday and -i[4] == ((ATES::MONTHDAYS[month] - 1 - day).to_f / 7 + 1).floor
        end
      end
    }[0]
  end
 
  def get_environment
   
    red = 0
    green = 0
    blue = 0
    grey = 0
    @temp_modifier += (rand(3) - 1) / 100.0 if rand(10) == 0
   
    changed = false
   
    for i in 0...@current_times.length
      time1 = get_time(@current_times[i][2], @current_times[i][1])
      time2 = get_time(@current_times[(i + 1) % @current_times.length][2], @current_times[(i + 1) % @current_times.length][1])
      current = get_time(@time.min, @time.hour)
      if time2 < time1
        time2 += 24 * 60
      end
      if current < time1
        current += 24 * 60
      end
     
      if time1 <= current and time2 >= current
       
        changed = true
        tone1 = @current_times[i]
        tone2 = @current_times[(i + 1) % @current_times.length]
        tone1 = ATES::TIMES[tone1[0]]
        tone2 = ATES::TIMES[tone2[0]]
        max = time2 - time1
       
        ratios = [(current - time1).to_f / max, (time2 - current).to_f / max]
        red = tone1[0] * ratios[1] + tone2[0] * ratios[0]
        green = tone1[1] * ratios[1] + tone2[1] * ratios[0]
        blue = tone1[2] * ratios[1] + tone2[2] * ratios[0]
        grey = tone1[3] * ratios[1] + tone2[3] * ratios[0]
       
        temp_range = get_full_season[3]
        temp_range = [temp_range.first, temp_range.last].sort
        unless @base_temp
          temp = temp_range[0] + rand(temp_range[1] - temp_range[0] + 1)
          if @terrain != ''
            modifier = ATES::TERRAINS.select { |terrain| terrain[0] == @terrain }[0][1]
            modifier = [modifier.first, modifier.last].sort
            modifier = modifier[0] + rand(modifier[1] - modifier[0] + 1)
            temp += modifier
          end
          @base_temp = temp
        else
          temp = @base_temp
        end
       
        temp_mod = round(tone1[4] * ratios[1] + tone2[4] * ratios[0], 2)
        temp += temp_mod + @temp_modifier
       
        @time_index = ratios[0] < 0.5 ? i : (i + 1) % @current_times.length
        break
      end
    end
   
    print "not right" unless changed
   
    if @map_type == 1
      return Tone.new(red * ATES::INSIDE_TONE, green * ATES::INSIDE_TONE, blue * ATES::INSIDE_TONE, grey * ATES::INSIDE_TONE), temp
    elsif @map_type == 2
      return ATES::DARK_INSIDE_TONE, temp
    else
      return Tone.new(red, green, blue, grey), temp
    end
  end
 
  def setup_times
    current_date = [@time.day, @time.mon]
    if current_date == ATES::LONGEST or @long_times == @short_times
      return @long_times
    elsif current_date == ATES::SHORTEST
      return @short_times
    end
   
    short_times = @long_times.clone
    addons = @short_times.clone
    current_date = get_date(*current_date)
    long, short = get_date(*ATES::LONGEST), get_date(*ATES::SHORTEST)
    dists = []
    if (current_date >= short and current_date <= long)
      dists = [current_date - short, long - current_date]
    elsif (current_date >= short and short >= long)
      dists = [current_date - short, long + @year_length - current_date]
    elsif (current_date <= long and long <= short)
      dists = [current_date + @year_length - short, long - current_date]
    elsif (current_date >= long and current_date <= short)
      dists = [current_date - long, short - current_date]
    elsif (current_date <= short and short <= long)
      dists = [current_date + @year_length - long, short - current_date]
    elsif (current_date >= long and long >= short)
      dists = [current_date - long, short + @year_length - current_date]
    end
    sum = dists.inject { |sum, x| sum + x }
    short_times.each { |tone|
      addons.each { |addon|
        if tone[0] == addon[0]
          ts = [tone[1] * 100 + tone[2] * 50 / 30.0, addon[1] * 100 + addon[2] * 50 / 30.0]
          ts = ts[0] * dists[0] / sum.to_f + ts[1] * dists[1] / sum.to_f
          h = (ts / 100).floor
          m = ((ts - h * 100) * 30 / 50).floor
          tone[1], tone[2] = h, m
        end
      }
    }
   
    return short_times.sort { |x, y| get_time(x[2], x[1]) <= get_time(y[2], y[1]) }
  end
 
  def round(num, places = 0)
    return ((num * 10 ** places).round.to_f) / (10 ** places)
  end
 
  def get_time(minutes, hours)
    return minutes + hours * 60
  end
 
  def get_season
    season_list = ATES::SEASONS.sort { |x, y| get_date(x[1], x[2]) <= get_date(y[1], y[2]) }
    day = @time.day
    month = @time.mon
    current = get_date(day, month)
    for i in 0...season_list.length
      seasons = [season_list[i], season_list[(i + 1) % season_list.length]]
      times = [get_date(seasons[0][1], seasons[0][2]), get_date(seasons[1][1], seasons[1][2])]
      if times[0] <= current and current < times[1]
        return seasons[0][0]
      end
    end
    return season_list[0][0]
  end
 
  def get_full_season
    season_list = ATES::SEASONS.sort { |x, y| get_date(x[1], x[2]) <= get_date(y[1], y[2]) }
    day = @time.day
    month = @time.mon
    current = get_date(day, month)
    for i in 0...season_list.length
      seasons = [season_list[i], season_list[(i + 1) % season_list.length]]
      times = [get_date(seasons[0][1], seasons[0][2]), get_date(seasons[1][1], seasons[1][2])]
      if times[0] <= current and current < times[1]
        return seasons[0]
      end
    end
    return season_list[0]
  end
 
  def get_date(day, month)
    month = ATES::MONTHS.length if month == 0
    return (ATES::MONTHDAYS[0...month - 1].inject { |sum, x| sum + x } or 0) + day
  end
 
  def update
    if @active
      @frame_count += 1
      changed = false
      if @frame_count % (ATES::LENGTH / 36) == 0
        tmp = @time.day
        changed = (ATES.advance(1, 0, 0, 0, 0))
        if @time.day != tmp
          @holiday = get_holiday(@time.mon, @time.day, @time.wday)
        end
        @weather.update
      end
      if changed
        @current_times = setup_times
      end
    end
    if ATES.day?
      $game_map.need_refresh = true if $game_switches[ATES::NSWITCH]
      $game_switches[ATES::DSWITCH] = true
      $game_switches[ATES::NSWITCH] = false
    else
      $game_map.need_refresh = true if $game_switches[ATES::DSWITCH]
      $game_switches[ATES::DSWITCH] = false
      $game_switches[ATES::NSWITCH] = true
    end
    @tone, @temp = get_environment
    tmp = get_time(@time.min, @time.hour)
    $game_screen.start_tone_change(@tone, ((@s_time - tmp).abs < [1440 / ATES::LENGTH, 1].max ? 0 : 20)) if @tinting
  end
 
end

#==============================================================================
# Bitmap
#==============================================================================

class Bitmap

  if $tons_version == nil || $tons_version < 1.6
    alias draw_text_shaded_later draw_text
  end
  def draw_text_full(x2, y2, w2 = 0, h2 = 0, text2 = '', a2 = 0)
    if x2.is_a?(Rect)
      x, y, w, h, text, a = x2.x, x2.y, x2.width, x2.height, y2, w2
    else
      x, y, w, h, text, a = x2, y2, w2, h2, text2, a2
    end
    save_color = self.font.color.clone
    self.font.color = Color.new(0, 0, 0)
    [x-1, x+1].each {|xx| [y-1, y+1].each {|yy|
            draw_text_shaded_later(xx, yy, w, h, text, a)}}
    self.font.color = save_color
    draw_text_shaded_later(x, y, w, h, text, a)
  end
 
end

#==============================================================================
# Clock_Sprite
#==============================================================================

class Clock_Sprite < Sprite
 
  def initialize
    super
    self.x, self.y, self.z = 640 - 8 - ATES::CWIDTH, 8, 5000
    self.bitmap = Bitmap.new(ATES::CWIDTH, ATES::CFORMAT.length * 32)
    if $fontface != nil
      self.bitmap.font.name = $fontface
    elsif $defaultfonttype != nil
      self.bitmap.font.name = $defaultfonttype
    end
    self.bitmap.font.size = 26
    @odd = 0
    draw if $game_system.ates.active
  end
 
  def draw
    self.bitmap.clear
    hours = $game_system.ates.time.hour
    minutes = sprintf('%02d', $game_system.ates.time.min)
    weekday = ATES::WEEKDAYS[$game_system.ates.time.wday - 1]
    wday_abbr = ATES::WEEKDAY_ABBREVIATIONS[$game_system.ates.time.wday - 1]
    day = $game_system.ates.time.day + 1
    month = $game_system.ates.time.mon + 1
    yday = ATES::MONTHDAYS[0..month - 1].inject { |s, r| s + r } + day
    month_name = ATES::MONTHS[month - 1]
    month_abbr = ATES::MONTH_ABBREVIATIONS[month - 1]
    month_days = ATES::MONTHDAYS[month - 1]
    year = $game_system.ates.time.year
    year_days = ATES::MONTHDAYS.inject { |s, r| s + r }
    season = $game_system.ates.get_season
    terrain = $game_system.ates.terrain
    temp = $game_system.ates.temp.to_s + ATES::TEMP_SUFFIX
    weather = $game_system.ates.weather.current_weather == -1 ? ATES::DEFAULT_WEATHER_NAME : $game_system.ates.weather.current_weather[0]
    tod = $game_system.ates.current_times[$game_system.ates.time_index][0]
    hday = $game_system.ates.holiday
    if hday != nil
      weekday = hday[0]
    end
    clock_text = ATES::CFORMAT.map { |ln| ln.clone }
    unless ATES::HOUR24
      suffix = "PM"
      if hours < 12
        suffix = "AM"
        hours = 12 if hours == 0
      elsif hours > 12
        suffix = "PM"
        hours -= 12
      end
    else
      suffix = ""
      hours = 24 if hours == 0
      hours = sprintf('%02d', hours)
    end
    colon = @odd % 2 == 0 ? " " : ":"
    clock_text.each { |ln|
      ln.gsub!(/%M/, minutes)
      ln.gsub!(/%H/, hours.to_s)
      ln.gsub!(/%A/, weekday)
      ln.gsub!(/%s/, " " + suffix)
      ln.gsub!(/:/, colon)
      ln.gsub!(/%m/, month.to_s)
      ln.gsub!(/%n/, month_name)
      ln.gsub!(/%l/, month_days.to_s)
      ln.gsub!(/%Y/, year.to_s)
      ln.gsub!(/%L/, year_days.to_s)
      ln.gsub!(/%d/, day.to_s)
      ln.gsub!(/%D/, yday.to_s)
      ln.gsub!(/%S/, season)
      ln.gsub!(/%w/, weather)
      ln.gsub!(/%t/, terrain)
      ln.gsub!(/%T/, temp)
      ln.gsub!(/%p/, tod)
    }
    if @odd % 2 == 0
      string = "#{hours} #{minutes}"
    else
      string = "#{hours}:#{minutes}"
    end
    string += " #{suffix}" unless ATES::HOUR24
    for i in 0...clock_text.length
      self.bitmap.draw_text_full(0, i * 32, self.bitmap.width, 32, clock_text[i], 1)
    end
    @odd = (@odd + 1) % 2
  end
   
end

#==============================================================================
# Scene_Map
#==============================================================================

class Scene_Map
 
  alias main_ates_later main
  def main
    @clock = Clock_Sprite.new if $game_system.show_clock
    main_ates_later
    @clock.dispose if @clock != nil
  end
 
  alias update_ates_later update
  def update
    $game_system.ates.update
    update_ates_later
    if $game_system.show_clock
      @clock = Clock_Sprite.new if @clock == nil
      @clock.draw if $game_system.ates.frame_count % 20 == 0
    elsif @clock != nil
      @clock.dispose
      @clock = nil
    end
  end
 
end

#==============================================================================
# Scene_Battle
#==============================================================================

class Scene_Battle
  alias update_ates_later update
  def update
    $game_system.ates.update
    update_ates_later
  end
 
end

#==============================================================================
# Game_Map
#==============================================================================

class Game_Map
  alias setup_ates_later setup
  def setup(map_id)
    $game_system.ates.update
    setup_ates_later(map_id)
    if $game_system.ates.show_weather and $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
      weather = $game_system.ates.weather.current_weather
      if weather[5].length > 0
        $game_map.fog_name = weather[5][0]
        $game_map.fog_opacity = weather[5][1]
        $game_map.fog_hue = weather[5][2]
        $game_map.fog_zoom = weather[5][3]
        $game_map.fog_sx = weather[5][4]
        $game_map.fog_sy = weather[5][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
      end
    end
   
    @events.each { |ev|
      ev = ev[1]
      if ev.list and ev.list.length > 0 and ev.list[0].code == 108 and ev.list[0].parameters[0] =~ /Terrain='(.+)'/
        $game_system.ates.terrain = $1
      end
    }
  end 
end

#==============================================================================
# Scene_Calendar
#==============================================================================

class Scene_Calendar
  def main
    # Make calendar window
    @calendar_window = Window_Calendar.new
    @calendar_window.active = true
    @calendar_window.z = 1000
    #@day_window = Window_Day.new
    #@day_window.z = 1010
    #@day_window.visible = false
    #@dir = rand(4)
    # Make spriteset
    @spriteset = Spriteset_Map.new
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of window
    @calendar_window.dispose
    #@day_window.dispose
    # Dispose of spriteset
    @spriteset.dispose
  end
 
  def update
    @calendar_window.update
    #@day_window.update
    #if @calendar_window.active
      #if Input.trigger?(Input::C)
      #  @day_window.visible = true
      #  @day_window.active = true
      #  @calendar_window.active = false
      #  @day_window.x, @day_window.y = 80, 80
      #  @day_window.appear(@dir)
      #  @dir = rand(4)
      #end
      if Input.trigger?(Input::B)
        $game_system.se_play($data_system.cancel_se)
        $scene = Scene_Map.new
      end
    #elsif @day_window.active
      #if Input.trigger?(Input::B)
      #  @day_window.disappear(@dir)
      #  @day_window.active = false
      #  @calendar_window.active = true
      #end
    #end
  end
end

#==============================================================================
# Window_Calendar
#==============================================================================

class Window_Calendar < Window_Base
  def initialize
    super(48, 48, 544, 384)
    self.contents = Bitmap.new(width - 32, height - 32)
    @month, @day, @wday, @year = $game_system.ates.time.mon, $game_system.ates.time.day, $game_system.ates.time.wday, $game_system.ates.time.year
    update
    refresh
  end
 
  def update
    prev_mon = @month
    if Input.repeat?(Input::LEFT)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      @day -= 1
      if @day == 0
        @month -= 1
        if @month == 0
          unless @year == ATES::FYEAR
            @year -= 1
            @month = ATES::MONTHS.length
          else
            @day = 1
            @month = 1
            continue = false
          end
        end
        @day = ATES::MONTHDAYS[@month - 1]
      end
      if continue
        @wday = (@wday + ATES::WEEKDAYS.length - 1) % ATES::WEEKDAYS.length
        @wday = ATES::WEEKDAYS.length if @wday == 0
      end
    end
    if Input.repeat?(Input::RIGHT)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      @day += 1
      if @day == ATES::MONTHDAYS[@month - 1] + 1
        @month += 1
        if @month == ATES::MONTHS.length + 1
          unless @year == ATES::LYEAR
            @year += 1
            @month = 1
          else
            @month = ATES::MONTHS.length
            @day = ATES::MONTHDAYS[@month - 1]
            continue = false
          end
        end
        @day = 1
      end
      if continue
        @wday = (@wday + 1) % ATES::WEEKDAYS.length
        @wday = ATES::WEEKDAYS.length if @wday == 0
      end
    end
    if Input.repeat?(Input::UP)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      tmpday = @day
      @day -= ATES::WEEKDAYS.length
      if @day <= 0
        @month -= 1
        if @month == 0
          unless @year == ATES::FYEAR
            @year -= 1
            @month = ATES::MONTHS.length
          else
            @day = tmpday
            @month = 1
            continue = false
          end
        end
        if continue
          tmp = (@wday + ATES::WEEKDAYS.length - @day) % ATES::WEEKDAYS.length
          tmp = ATES::WEEKDAYS.length if tmp == 0
          if @wday > tmp
            tmp = tmp + ATES::WEEKDAYS.length - @wday
          else
            tmp = tmp - @wday
          end
          @day = ATES::MONTHDAYS[@month - 1]
          @day -= tmp
        end
      end
    end
    if Input.repeat?(Input::DOWN)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      tmpday = @day
      @day += ATES::WEEKDAYS.length
      if @day >= ATES::MONTHDAYS[@month - 1] + 1
        @month += 1
        if @month == ATES::MONTHS.length + 1
          unless @year == ATES::LYEAR
            @year += 1
            @month = 1
          else
            @day = tmpday
            @month = ATES::MONTHS.length
            continue = false
          end
        end
        if continue
          tmp = (@wday + ATES::MONTHDAYS[@month - 2] - @day) % ATES::WEEKDAYS.length
          tmp = ATES::WEEKDAYS.length if tmp == 0
          if @wday <= tmp
            tmp -= ATES::WEEKDAYS.length
          end
          @day = @wday - tmp
        end
      end
    end
    super()
    refresh if prev_mon != @month
    row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
    row_height = height - 116
    top_margin = ((row_height % row_count) / 2.0).ceil
    row_height -= row_height % row_count
    row_height /= row_count
    colwidth = width - 32
    margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
    colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
    colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
    start_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
    start_wday = ATES::WEEKDAYS.length if start_wday == 0
    row = (@day + start_wday - 2) / ATES::WEEKDAYS.length
    self.cursor_rect.set(margin + (@wday - 1) * colwidth, 84 + top_margin + row * row_height, colwidth, 32)
  end
 
  def refresh
    self.contents.clear
    self.contents.font.size = 32
    self.contents.font.color = system_color
    self.contents.draw_text_full(Rect.new(0, 0, width - 32, 32), ATES::MONTHS[@month - 1] + " " + @year.to_s, 1)
    self.contents.font.size = 24
   
    colwidth = width - 32
    margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
    colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
    colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
   
    for i in 0...ATES::WEEKDAY_ABBREVIATIONS.length
      self.contents.draw_text_full(Rect.new(margin + i * colwidth, 40, colwidth, 32), ATES::WEEKDAY_ABBREVIATIONS[i], 1)
    end
    self.contents.fill_rect(Rect.new(0, 76, width - 32, 2), system_color)
   
    row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
    row_height = height - 116
    top_margin = ((row_height % row_count) / 2.0).ceil
    row_height -= row_height % row_count
    row_height /= row_count
    cur_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
    cur_wday = ATES::WEEKDAYS.length if cur_wday == 0
    start_wday = cur_wday
    cur_day = 1
    cur_row = (cur_day - 1) / 7
    while cur_day <= ATES::MONTHDAYS[@month - 1]
      if (cur_day == $game_system.ates.time.day and @month == $game_system.ates.time.mon and @year == $game_system.ates.time.year)
        self.contents.font.color = Color.new(240, 40, 40)
      elsif $game_system.ates.get_holiday(@month - 1, cur_day - 1, cur_wday) != nil
        self.contents.font.color = Color.new(150, 150, 0)
      else
        self.contents.font.color = normal_color
      end
      self.contents.draw_text_full(Rect.new(margin + (cur_wday - 1) * colwidth, 84 + top_margin + cur_row * row_height, colwidth, 32), cur_day.to_s, 1)
      cur_day += 1
      cur_wday = cur_wday + 1
      if cur_wday > ATES::WEEKDAYS.length
        cur_wday -= ATES::WEEKDAYS.length
        cur_row += 1
      end
    end
  end
end

#==============================================================================
# Window_Day
#==============================================================================

class Window_Day < Window_Base
  def initialize
    #(dir == 2 ? 320 : 48), (dir == 3 ? 240 : 48), (dir % 2 == 0 ? 272 : 544), (dir % 2 == 1 ? 192 : 384)
    super(80, 80, 480, 320)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
 
  def appear(dir, duration = 40)
    @d_pos = [self.x, self.y]
    case dir
    when 0:
      self.x = -480
    when 1:
      self.y = -320
    when 2:
      self.x = 640
    when 3:
      self.y = 480
    end
    @s_pos = [self.x, self.y]
    @dir = dir
    @duration = duration
    @frames = 0
    @moving = true
  end
 
  def disappear(dir, duration = 40)
    @s_pos = [self.x, self.y]
    case dir
    when 0:
      self.x += 560
    when 1:
      self.y -= 400
    when 2:
      self.x += 560
    when 3:
      self.y += 400
    end
    @d_pos = [self.x, self.y]
    self.x, self.y = *@s_pos
    @dir = dir
    @duration = duration
    @frames = 0
    @moving = true
  end
 
  def update
    if @moving
      self.x = (@d_pos[0] * @frames + @s_pos[0] * (@duration - @frames)) / @duration
      self.y = (@d_pos[1] * @frames + @s_pos[1] * (@duration - @frames)) / @duration
      @moving = ([self.x, self.y] != @d_pos)
      @frames += 1
    end
    super()
  end
end

class Window_Text < Window_Base
  def initialize
    super(48, 48, 544, 384)
    self.contents = Bitmap.new(width - 32, height - 32)
   
    @dual_keys = ['`','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E',
                  'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
                  'V','W','X','Y','Z','-','=','[',']','\\',';','\'',',','.','/']
    @single_keys = ['NumberPad 0','NumberPad 1','NumberPad 2','NumberPad 3',
                    'NumberPad 4','NumberPad 5','NumberPad 6','NumberPad 7',
                    'NumberPad 8','NumberPad 9','Space','Enter','Tab']
    @chars1 = ['`','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f',
               'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
               'x','y','z','-','=','[',']','/',';','\'',',','.','\\']
    @chars2 = ['~','!','@','#','$','%','^','&','*','(',')','A','B','C','D','E','F',
               'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
               'X','Y','Z','_','+','{','}','?',':','"','<','>','|']
    @chars = ['0','1','2','3','4','5','6','7','8','9',' ','\n','\t']
   
    @text = ""
    @cursor = true
  end
 
  def update
    @dual_keys.each_with_index { |i, ind|
      if Input.repeat?(Input::Key[i])
        @text += (Input.press?(Input::Key['Shift']) ? @chars2[ind] : @chars1[ind])
      end
    }
    @single_keys.each_with_index { |i, ind|
      if Input.repeat?(Input::Key[i])
        @text += @chars[ind]
      end
    }
    if Input.repeat?(Input::Key['Backspace'])
      @text = @text.split('')
      tmp = @text.pop()
      if (tmp == 'n' or tmp == 't') and @text[@text.length - 1] == '\\'
        @text.pop()
      end
      @text = @text.join('')
    end
    @cursor = !@cursor if Graphics.frame_count % 20 == 0
    refresh
  end
 
  def refresh
    self.contents.clear
   
    tmp = @text.gsub(/((?:\\n)+)\z/, '')
    y_mod = $1 ? $1.length / 2 : 0
    x_pos = y_mod > 0
    lns = tmp.gsub(/\\t/,'    ').split(/\\n/)
    y = 0
    x = 0
    lns.each_with_index { |ln, ind|
      rect = self.contents.text_size(ln)
      rect.height = self.contents.text_size('a').height
      rect.width += 1 unless ln.index(/[vVAwf\/\\]\z/).nil?
      rect.y = y
      self.contents.draw_text(rect, ln)
      y += rect.height
      x = rect.width
    }
    #p lns if lns.length > 1
    height = self.contents.text_size('a').height
    y -= height unless lns.last.nil?
    y += y_mod * height
    x = (x_pos ? 0 : x + 1)
    self.contents.fill_rect(Rect.new(x, y, 2, height), Color.new(0, 0, 0)) if @cursor
    #@cursor = !@cursor
  end
end


unless $BlizzABS or ($tons_version and TONS_OF_ADDONS::CUSTOM_CONTROLS)

#==============================================================================
# module Input
#==============================================================================

module Input
 
  #----------------------------------------------------------------------------
  # Simple ASCII table
  #----------------------------------------------------------------------------
  Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
         'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
         'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
         'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
         'Y' => 89, 'Z' => 90,
         '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
         '6' => 54, '7' => 55, '8' => 56, '9' => 57,
         'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
         'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
         'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
         'NumberPad 9' => 33,
         'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
         'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
         'F11' => 122, 'F12' => 123,
         ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
         '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
         'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
         'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
         'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
         'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
         'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
         'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38,
         'Arrow Right' => 39, 'Arrow Down' => 40,
         'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
         'Mouse 4' => 5, 'Mouse 5' => 6}
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  UP = [Key['Arrow Up']]
  LEFT = [Key['Arrow Left']]
  DOWN = [Key['Arrow Down']]
  RIGHT = [Key['Arrow Right']]
  A = [Key['Shift']]
  B = [Key['Esc'], Key['NumberPad 0'], Key['X']]
  C = [Key['Space'], Key['Enter'], Key['C']]
  X = [Key['A']]
  Y = [Key['S']]
  Z = [Key['D']]
  L = [Key['Q'], Key['Page Down']]
  R = [Key['W'], Key['Page Up']]
  F5 = [Key['F5']]
  F6 = [Key['F6']]
  F7 = [Key['F7']]
  F8 = [Key['F8']]
  F9 = [Key['F9']]
  SHIFT = [Key['Shift']]
  CTRL = [Key['Ctrl']]
  ALT = [Key['Alt']]
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # All keys
  KEY_COUNT = 256
  ALL_KEYS = (0...KEY_COUNT).to_a
  # Win32 API calls
  GetKeyboardState = Win32API.new('user32', 'GetKeyboardState', 'P', 'I')
  GetKeyboardLayout = Win32API.new('user32', 'GetKeyboardLayout', 'L', 'L')
  MapVirtualKeyEx = Win32API.new('user32', 'MapVirtualKeyEx', 'IIL', 'I')
  ToUnicodeEx = Win32API.new('user32', 'ToUnicodeEx', 'LLPPILL', 'L')
  # some other constants
  DOWN_STATE_MASK = 0x80
  DEAD_KEY_MASK = 0x80000000
  # data
  @state = "\0" * KEY_COUNT
  @triggered = Array.new(KEY_COUNT, false)
  @pressed = Array.new(KEY_COUNT, false)
  @released = Array.new(KEY_COUNT, false)
  @repeatedKey = -1
  @repeatedCount = 0
  #----------------------------------------------------------------------------
  # update
  #  Updates input.
  #----------------------------------------------------------------------------
  def self.update
    # get current language layout
    @language_layout = GetKeyboardLayout.call(0)
    # get new keyboard state
    GetKeyboardState.call(@state)
    # this special code is used because Ruby 1.9.x does not return a char
    # when using String#[] but another String
    key = 0
    @state.each_byte {|byte|
        # if pressed state
        if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK
          # not released anymore
          @released[key] = false
          # if not pressed yet
          if !@pressed[key]
            # pressed and triggered
            @pressed[key] = true
            @triggered[key] = true
            @repeatedKey = key
            @repeatedCount = 0
          else
            # not triggered anymore
            @triggered[key] = false
          end
          # update of repeat counter
          if key == @repeatedKey
            @repeatedCount < 17 ? @repeatedCount += 1 : @repeatedCount = 15
          end
        # not released yet
        elsif !@released[key]
          # if still pressed
          if @pressed[key]
            # not triggered, pressed or repeated, but released
            @triggered[key] = false
            @pressed[key] = false
            @released[key] = true
            if key == @repeatedKey
              @repeatedKey = -1
              @repeatedCount = 0
            end
          end
        else
          # not released anymore
          @released[key] = false
        end
        key += 1}
  end
  #----------------------------------------------------------------------------
  # dir4
  #  4 direction check.
  #----------------------------------------------------------------------------
  def self.dir4
    return 2 if self.press?(DOWN)
    return 4 if self.press?(LEFT)
    return 6 if self.press?(RIGHT)
    return 8 if self.press?(UP)
    return 0
  end
  #----------------------------------------------------------------------------
  # dir8
  #  8 direction check.
  #----------------------------------------------------------------------------
  def self.dir8
    down = self.press?(DOWN)
    left = self.press?(LEFT)
    return 1 if down && left
    right = self.press?(RIGHT)
    return 3 if down && right
    up = self.press?(UP)
    return 7 if up && left
    return 9 if up && right
    return 2 if down
    return 4 if left
    return 6 if right
    return 8 if up
    return 0
  end
  #----------------------------------------------------------------------------
  # trigger?
  #  Test if key was triggered once.
  #----------------------------------------------------------------------------
  def self.trigger?(keys)
    keys = [keys] unless keys.is_a?(Array)
    return keys.any? {|key| @triggered[key]}
  end
  #----------------------------------------------------------------------------
  # press?
  #  Test if key is being pressed.
  #----------------------------------------------------------------------------
  def self.press?(keys)
    keys = [keys] unless keys.is_a?(Array)
    return keys.any? {|key| @pressed[key]}
  end
  #----------------------------------------------------------------------------
  # repeat?
  #  Test if key is being pressed for repeating.
  #----------------------------------------------------------------------------
  def self.repeat?(keys)
    keys = [keys] unless keys.is_a?(Array)
    return (@repeatedKey >= 0 && keys.include?(@repeatedKey) &&
        (@repeatedCount == 1 || @repeatedCount == 16))
  end
  #----------------------------------------------------------------------------
  # release?
  #  Test if key was released.
  #----------------------------------------------------------------------------
  def self.release?(keys)
    keys = [keys] unless keys.is_a?(Array)
    return keys.any? {|key| @released[key]}
  end
  #----------------------------------------------------------------------------
  # get_character
  #  vk - virtual key
  #  Gets the character from keyboard input using the input locale identifier
  #  (formerly called keyboard layout handles).
  #----------------------------------------------------------------------------
  def self.get_character(vk)
    # get corresponding character from virtual key
    c = MapVirtualKeyEx.call(vk, 2, @language_layout)
    # stop if character is non-printable and not a dead key
    return '' if c < 32 && (c & DEAD_KEY_MASK != DEAD_KEY_MASK)
    # get scan code
    vsc = MapVirtualKeyEx.call(vk, 0, @language_layout)
    # result string is never longer than 4 bytes (Unicode)
    result = "\0" * 4
    # get input string from Win32 API
    length = ToUnicodeEx.call(vk, vsc, @state, result, 4, 0, @language_layout)
    return (length == 0 ? '' : result)
  end
  #----------------------------------------------------------------------------
  # get_input_string
  #  Gets the string that was entered using the keyboard over the input locale
  #  identifier (formerly called keyboard layout handles).
  #----------------------------------------------------------------------------
  def self.get_input_string
    result = ''
    # check every key
    ALL_KEYS.each {|key|
        # if repeated
        if self.repeat?(key)
          # get character from keyboard state
          c = self.get_character(key)
          # add character if there is a character
          result += c if c != ''
        end}
    # empty if result is empty
    return '' if result == ''
    # convert string from Unicode to UTF-8
    return self.unicode_to_utf8(result)
  end
  #----------------------------------------------------------------------------
  # unicode_to_utf8
  #  string - string in Unicode format
  #  Converts a string from Unicode format to UTF-8 format as RGSS does not
  #  support Unicode.
  #----------------------------------------------------------------------------
  def self.unicode_to_utf8(string)
    result = ''
    # L* format means a bunch of 4-byte wide-chars
    string.unpack('L*').each {|c|
        # characters under 0x80 are 1 byte characters
        if c < 0x0080
          result += c.chr
        # other characters under 0x800 are 2 byte characters
        elsif c < 0x0800
          result += (0xC0 | (c >> 6)).chr
          result += (0x80 | (c & 0x3F)).chr
        # other characters under 0x10000 are 3 byte characters
        elsif c < 0x10000
          result += (0xE0 | (c >> 12)).chr
          result += (0x80 | ((c >> 6) & 0x3F)).chr
          result += (0x80 | (c & 0x3F)).chr
        # other characters under 0x200000 are 4 byte characters
        elsif c < 0x200000
          result += (0xF0 | (c >> 18)).chr
          result += (0x80 | ((c >> 12) & 0x3F)).chr
          result += (0x80 | ((c >> 6) & 0x3F)).chr
          result += (0x80 | (c & 0x3F)).chr
        # other characters under 0x4000000 are 5 byte characters
        elsif c < 0x4000000
          result += (0xF8 | (c >> 24)).chr
          result += (0x80 | ((c >> 18) & 0x3F)).chr
          result += (0x80 | ((c >> 12) & 0x3F)).chr
          result += (0x80 | ((c >> 6) & 0x3F)).chr
          result += (0x80 | (c & 0x3F)).chr
        # other characters under 0x80000000 are 6 byte characters
        elsif c < 0x80000000
          result += (0xFC | (c >> 30)).chr
          result += (0x80 | ((c >> 24) & 0x3F)).chr
          result += (0x80 | ((c >> 18) & 0x3F)).chr
          result += (0x80 | ((c >> 12) & 0x3F)).chr
          result += (0x80 | ((c >> 6) & 0x3F)).chr
          result += (0x80 | (c & 0x3F)).chr
        end}
    return result
  end

end

end

Si vous voyez des erreurs de trad, dites le moi je me ferai un plaisir de les corriger Imbécile heureux.
Il y a une démo en anglais sur le lien du script original.

Posté par Howrus le 30 Juin - 02:51 (2014)
Cette version possède beaucoup de bug (avec PSP je précise) dus au système de météo, elle est partiellement incompatible avec PSP 5G0.9 de mon coté.. Le menu s'ouvre, lag un bon coup puis se ferme instantanement, de plus lorsque la météo change le climats lorsque l'on est dans un intérieur, le jeu subit une grosse baisse de fps, et deviens injouable. Si quelqu'un à le courage, faudrait adapter ce script pour qu'il ne rentre pas en conflit avec ceux déjà présents Clin d'œil foireux
(Merci quand même du partage)

Posté par Nuri Yuri le 30 Juin - 09:28 (2014)
PSP DS et 5G utilisent déjà des scripts qui demande beaucoup de ressources au processeur donc faut éviter les scripts de ce genre et opter pour des solutions plus simple que se mettent à jour de manière asynchrone par rapport à la boucle de mise à jour globale.

Posté par Aerun le 12 Juil - 22:36 (2014)
Je déconseille fortement à quiconque ne sait pas gérer son code de C/C ce script. Ce serait tirer une balle dans le pied de son projet et le voir lag au moindre event conséquent. Comme l'a dit Yuri, il est possible de gérer toutes ces fonctionnalités bien plus simplement. Imbécile heureux