Kujira no Hara

Pour présenter ses jeux en cours de création, terminés ou abandonnés
Avatar du membre
Nemau
Administrateur du site
Messages : 827
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 09 mars 2023, 03:41

Cool !

Avatar du membre
Roi of the Suisse
Messages : 2091
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 17 mars 2023, 00:33

Tiens je suis tombé là-dessus :

https://amours-de-fans.livejournal.com/20258.html

Ça date de 2011, mais ça fait plaisir quand même.

Avatar du membre
Roi of the Suisse
Messages : 2091
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 17 mars 2023, 14:36

Script de traduction du jeu en anglais, fait à partir du script de correction d'orthographe de zues18 :

Code : Tout sélectionner

#=================================
# Correcteur d'orthographe
# Script créé par Zeus81
#=================================
#
#
# Comment ça marche ?
#
#  Tout d'abord il faut le lancer en écrivant dans un script $scene = Scene_Scan2.new
#  Ensuite vous faites Analyser les messages.
#  Le script va générer un fichier texte dans lequel seront listés tous les messages utilisés dans le jeu.
#  Ensuite il y deux façons de corriger les fautes d'orthographes dans votre jeu.
#
#  1ère méthode (manuelle) :
#    Vous détectez les fautes avec un logiciel (Word par exemple).
#    Puis vous lisez le code du début de la ligne pour savoir d'où vient le message et vous allez le corriger directement dans le jeu.
#    Exemple d'une ligne :
#      0/012/037/003/072/0 : J'est mal aux doigt.
#      Le code se lit de la manière suivante :
#        - Le premier chiffre indique le type d'évènement :
#            0 -> Evènement d'une map
#            1 -> Evènement commun
#            2 -> Evènement de combat
#        - Le trois chiffres suivants indiquent l'id de la map (entre 001 et 999).
#          Si c'est un évènement commun ou de combat il y a 000.
#        - Le trois chiffres suivants indiquent l'id de l'évènement.
#        - Le trois chiffres suivants indiquent la page de l'évènement (moins un).
#        - Le chiffres suivants indiquent la ligne dans les commandes de l'évènement (moins un).
#        - Le dernier chiffre indique le type du message :
#            0 -> Affichage d'un message
#            1 -> Premier choix dans une proposition de choix
#            2 -> Deuxième choix dans une proposition de choix
#            3 -> Troisième choix dans une proposition de choix
#            4 -> Quatrième choix dans une proposition de choix
#      Dans cet exemple on a donc :
#        type d'évènement : 0 -> Evènement d'une map
#        id de la map : 012 -> Map n°12
#        id de l'évènement : 037 -> Evènement n°37
#        page : 003 -> Page n°4
#        ligne : 072 -> Ligne n°73
#        type du message : 0 -> Affichage d'un message
#
#  2ème méthode (automatique) :
#    Vous corrigez les fautes dans le fichier avec votre logiciel.
#    Vous enregistrez le fichier corrigé avec un codage Unicode UTF-8 en le renommant "Messages OK.txt".
#    Le codage UTF-8 est le codage utilisé par RPG Maker, on est donc obligé de le respecter.
#    Vous fermez RPG Maker afin qu'il n'interfère pas dans les modifications.
#    Vous relancez votre jeu à partir du Game.exe
#    Vous ré-exécutez le script mais cette fois vous faites Corriger les messages.
#    Le script va remplacer les messages erronés du jeu par les messages corrigés du fichier "Messages OK.txt".
 
 
class Window_Scan2 < Window_Selectable
    
  def initialize
    super(0, 0, 640, 480)
    self.contents = Bitmap.new(width - 32, height - 32)
    self.contents.font.name = "Comic Sans MS"
    @item_max = 5
    @index = 0
    refresh
  end
  
  def refresh
    self.contents.clear
    self.contents.fill_rect(0, 48, 608, 1, normal_color)
    self.contents.fill_rect(0, 400, 608, 1, normal_color)
    self.contents.fill_rect(304, 64, 1, 320, normal_color)
    self.contents.fill_rect(404-50, 240, 200, 1, normal_color)
    
    self.contents.font.size = 28
    self.contents.font.color = knockout_color
    self.contents.draw_text(0, 0, 608, 48, "Correcteur d'orthographe", 1)
    
    self.contents.font.size = 20
    self.contents.font.color = normal_color
    self.contents.draw_text(0, 64, 300, 24, "Pas à pas", 1)
    self.contents.draw_text(432-50, 128, 176, 32, "Evènements des maps")
    self.contents.draw_text(432-50, 160, 176, 32, "Evènements communs")
    self.contents.draw_text(432-50, 192, 176, 32, "Evènements des combats")
    self.contents.draw_text(400-50, 256, 208, 32, "Exporter les messages", 1)
    self.contents.draw_text(400-50, 288, 208, 32, "Réimporter les messages", 1)
    
    self.contents.font.size = 18
    self.contents.draw_text(0, 88, 300, 24, "- Sélectionner les évènements à analyser")
    self.contents.draw_text(0, 112, 300, 24, "- Faire analyser les messages")
    self.contents.draw_text(0, 136, 300, 24, "- Corriger les fautes d'orthographe")
    self.contents.draw_text(0, 160, 300, 24, "  à l'aide d'un logiciel de traitement de texte")
    self.contents.draw_text(0, 184, 300, 24, "- Enregistrer le fichier corrigé au format unicode")
    self.contents.draw_text(0, 208, 300, 24, "  'UTF-8' en le renommant 'Messages OK.txt'.")
    self.contents.draw_text(0, 232, 300, 24, "  Pour enregistrer au bon format faire")
    self.contents.draw_text(0, 256, 300, 24, "  'Enregistrer sous' 'Format *.txt' 'Codage UTF-8'")
    self.contents.draw_text(0, 280, 300, 24, "  (Ca y est même dans le bloc note)")
    self.contents.draw_text(0, 304, 300, 24, "- Fermer RPG Maker puis lancer le jeu avec le 'Game.exe'")
    self.contents.draw_text(0, 328, 300, 24, "- Faire corriger les messages")
    self.contents.draw_text(0, 352, 300, 24, "- Et c'est fini")
    
    draw_states
  end
  
  def draw_states
    draw_state(408-50, 128, $scene.map_events_scan)
    draw_state(408-50, 160, $scene.common_events_scan)
    draw_state(408-50, 192, $scene.battle_events_scan)
  end
  
  def draw_state(x, y, state)
    if state == true
      color = Color.new(255, 0, 0)
    else
      color = Color.new(128, 128, 128)
    end
    self.contents.fill_rect(x+3, y+11, 10, 10, Color.new(29, 82, 129))
    self.contents.fill_rect(x+4, y+12, 8, 8, Color.new(255, 255, 255))
    self.contents.fill_rect(x+5, y+13, 6, 6, color)
  end
  
  def update_cursor_rect
    y = @index*32 + 128
    y += 32 if @index > 2
    self.cursor_rect.set(400-50, y, 208, 32)
  end
  
end
 
 
class Scene_Scan2
    
  attr_reader :map_events_scan
  attr_reader :common_events_scan
  attr_reader :battle_events_scan
  
  def initialize
    GC.disable
    Thread.new do
      loop do
        Graphics.update
        sleep(1)
      end
    end
    $data_system = load_data("Data/System.rxdata")
    $game_system = Game_System.new
    @map_events_scan = true
    @common_events_scan = true
    @battle_events_scan = true
  end
  
  def main
    @scan_window = Window_Scan2.new
    Graphics.transition
    loop do
      update
      Graphics.update
      Input.update
    end
  end
    
  def update
    @scan_window.update
    if Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      case @scan_window.index
      when 0
        @map_events_scan = !@map_events_scan
      when 1
        @common_events_scan = !@common_events_scan
      when 2
        @battle_events_scan = !@battle_events_scan
      when 3
        start_scan
      when 4
        start_correction
      end
      @scan_window.draw_states
    end
  end
   
  def read_data
    @data_common_events = load_data("Data/CommonEvents.rxdata")
    @data_troops = load_data("Data/Troops.rxdata")
    @data_maps = []
    for map_id in 1..999
      filename = sprintf("Data/Map%03d.rxdata", map_id)
      next if FileTest.exist?(filename) == false
      @data_maps[map_id] = load_data(filename)
    end
  end
 
  def save_corrected_data
    for map_id in 1..999
      next if @data_maps[map_id] == nil
      save_data(@data_maps[map_id], sprintf("Data/Map%03d.rxdata", map_id))
    end
    save_data(@data_common_events, "Data/CommonEvents.rxdata")
    save_data(@data_troops, "Data/Troops.rxdata")
    print("Enregistrement des données du projet terminé.")
  end
  
  def start_scan
    read_data
    @messages = []
    @messages[0] = "\357\273\277Ce fichier a été enregistré avec un codage Unicode UTF-8.\n"
    @messages[1] = "Si vous voyez des caractères bizarres à la place des accents, c'est que votre logiciel ne lit pas ce codage.\n"
    @messages[2] = "Pour convertir le fichier en codage standard ouvrez le avec le bloc note et faites \"Enregistrer sous\" avec un codage ANSI\n"
    @messages[3] = "Le fichier corrigé final devra être enregistré avec un codage Unicode UTF-8.\n"
    @messages[4] = "Ce fichier devra impérativement s'appeler \"Messages OK.txt\".\n"
    @messages[5] = "Ne modifiez pas le code au début de chaque ligne.\n"
    @messages[6] = "Ne rajoutez aucune ligne.\n"
    @messages[7] = "Ne supprimez pas ces lignes.\n\n"
    check_maps if @map_events_scan == true
    check_common_events if @common_events_scan == true
    check_battle_events if @battle_events_scan == true
    file = File.open("Messages.txt", "w")
      file.write(@messages.to_s)
    file.close
    print("                 L'analyse est terminé !\n",
          "      Le résultat se trouve dans le fichier\n",
          "\"Messages.txt\" dans le dossier de votre jeu.")
  end
      
  def check_maps
    for map_id in 1..999
      next if @data_maps[map_id] == nil
      for event_id in @data_maps[map_id].events.keys.sort
        for page_id in 0...@data_maps[map_id].events[event_id].pages.size
          for list_id in 0...@data_maps[map_id].events[event_id].pages[page_id].list.size
            name_prefix = sprintf("%01d/%03d/%03d/%03d/", 0, map_id, event_id, page_id)
            memorize_message(@data_maps[map_id].events[event_id].pages[page_id].list, list_id, name_prefix)
          end
        end
      end
    end
  end
      
  def check_common_events
    for event_id in 1...@data_common_events.size
      for list_id in 0...@data_common_events[event_id].list.size
        name_prefix = sprintf("%01d/%03d/%03d/%03d/", 1, 0, event_id, 0)
        memorize_message(@data_common_events[event_id].list, list_id, name_prefix)
      end
    end
  end
      
  def check_battle_events
    for event_id in 1...@data_troops.size 
      for page_id in 0...@data_troops[event_id].pages.size
        for list_id in 0...@data_troops[event_id].pages[page_id].list.size
          name_prefix = sprintf("%01d/%03d/%03d/%03d/", 2, 0, event_id, page_id)
          memorize_message(@data_troops[event_id].pages[page_id].list, list_id, name_prefix)
        end
      end
    end
  end
  
  # Faut-il conserver le saut de ligne ?
  # On a besoin de recoller les morceaux de phrase pour la traduction
  # Mais certains retours à la ligne doivent être conservés
  def faut_il_conserver_le_saut_de_ligne(ligne_actuelle, ligne_precedente)
    
    # Fin de phrase juste avant
    if end_with(strip(ligne_precedente), '.')
      return true
    end
    if end_with(strip(ligne_precedente), '!')
      return true
    end
    if end_with(strip(ligne_precedente), '?')
      return true
    end
    
    c1 = initiale(ligne_actuelle)
    c2 = initiale(ligne_actuelle, 2)
    c3 = initiale(ligne_actuelle, 3)
    
    # Balise de couleur, ou nom du heros
    if c1 == '\\' and ['c', 'n'].include? c2
      return false
    end
    # Lignes d'un panneau directionnel
    if ['<', '>', '/', '\\'].include? c1
      return true
    end

    return false
  end
  
  def calculate_hash(message)
    if message == nil or message == ""
      return "0"
    end
    return sprintf("%06d", (message.sum+17)*(message.size*31) % 1000000 )
  end
  
  def strip(str)
    while start_with(str, " ")
      str = str[1..-1]
    end
    while end_with(str," ") 
      str = str[0..-2]
    end
    return str
  end
  
  # ième lettre du texte
  def initiale(texte, i = 1)
    if texte == nil
      return " "
    end
    if texte.size <= i-1
      return " "
    end
    return texte.split(//)[i-1]
  end
  
  # Ecrire le message dans le fichier d'exportation avec son code
  def memorize_message(list, list_id, name_prefix)
    message = get_message(list, list_id)
    if message != nil and message != ""
      message_hash = calculate_hash(message)
      name = name_prefix + message_hash
      @messages.push(name+" : "+message+"\n")
    end
  end
  
  def get_message(list, list_id)
    event = list[list_id]
    # Message
    if event.code == 101
      # Premiere ligne
      message = list[list_id].parameters[0]
      
      # Autres lignes
      for i in 1..4
        if list[list_id+i].code != 401
          break
        end
        
        # Conserver les retours à la ligne ?
        ligne_actuelle = strip(list[list_id+i].parameters[0])
        ligne_precedente = strip(list[list_id+i-1].parameters[0])
        if faut_il_conserver_le_saut_de_ligne(ligne_actuelle, ligne_precedente)
          message += " ----- "
        else
          message += " "
        end
          
        message += list[list_id+i].parameters[0]
      end
    # Choix
    elsif event.code == 102
      message = ""
      for i in 0...event.parameters[0].size
        alternative = event.parameters[0][i]
        if alternative != nil and strip(alternative) != ""
          message += "|" unless message == ""
          message += alternative
        end
      end
    else
      return
    end
    
    if message == nil
      message = "[nil]"
    end
    
    # Retirer les doubles espaces
    while message["  "]
      message = message.gsub('  ', ' ')
    end
    
    return message
  end
      
  def start_correction
    if FileTest.exist?("Messages OK.txt") == false
      print("Le fichier \"Messages OK.txt\" est introuvable !\n",
            "La correction n'a donc pas pu s'effectuer !!!")
      return
    end
    if $DEBUG == true
      print("Pour corriger votre projet doit être fermé !")
      return
    end
    file = File.open("Messages OK.txt", "r")
      @messages = file.readlines
    file.close
    if @messages[0][0, 3] != "\357\273\277"
      print("Le fichier \"Messages OK.txt\" n'a pas été enregistré en codage Unicode \"UTF-8\".")
      return
    end
    read_data
    print("Début de l'insertion des commentaires de traduction...")
    if correction_scan == false
      print("L'insertion des commentaires de traduction a été annulée !")
      return
    else
      print("Début de la sauvegarde des données du jeu...")
      save_corrected_data
      print("La correction automatique est terminée !")
    end
  end
  
  def correction_scan
    for i in 8...50 #@messages.size
      next if @messages[i][0, 1] == "\n"
      type = @messages[i][0, 1].to_i
      map_id = @messages[i][2, 3].to_i
      event_id = @messages[i][6, 3].to_i
      page_id = @messages[i][10, 3].to_i
      j = 6 #longueur du hash
      message_hash = @messages[i][14, j]
      message_type = @messages[i][13+j, 1].to_i
      erreur = false
      erreur |= (type > 2)
      erreur |= (@messages[i][1, 1] != "/")
      erreur |= (@messages[i][5, 1] != "/")
      erreur |= (@messages[i][9, 1] != "/")
      erreur |= (@messages[i][13, 1] != "/")
      erreur |= (@messages[i][14+j, 3] != " : ")
      if erreur == true
        print("Le code d'une ligne a été modifié. "+i.to_s )
        return false
      end
      @messages[i][0, 17+j] = ""
      @messages[i][-1, 1] = ""
      case type
      when 0
        list = @data_maps[map_id].events[event_id].pages[page_id].list
      when 1
        list = @data_common_events[event_id].list
      when 2
        list = @data_troops[event_id].pages[page_id].list
      end
      
      insert_translation_at_the_right_place(list, message_hash, @messages[i])
      
    end
    print("Insertion des commentaires de traduction terminée.")
    return true
  end
  
  def insert_translation_at_the_right_place(list, message_hash, traduction)
    for list_id in 0...list.size
      message = get_message(list, list_id)
      if message != nil        
        if message_hash == calculate_hash(message)
          if no_translation_above(list, list_id)
            arr = cut_message(traduction, 30)
            insert_comments(arr, list, list_id)
            return
          end 
        end
      end
    end
  end
  
  # inverser une chaine de caracteres
  def reverse(string)
    word = ""
    string.split('').each { |c|
        word = c + word
    }
    word
  end  
  
  # est ce que la chaine de caractere commence par la sous-chaine ?
  def start_with(str, substr)
    return str.index(substr) == 0
  end
  
  # est ce que la chaine de caractere se termine par la sous-chaine ?
  def end_with(str, substr)
    return start_with(reverse(str), reverse(substr))
  end
  
  # il n'y a pas déjà une traduction au dessus du message
  def no_translation_above(list, list_id)
    i = list_id
    while i > 0
      i -= 1
      if list[i].code != 408 and list[i].code != 108
        return true
      else
        if list[i].code == 108 and start_with(list[i].parameters[0], "(en)")
          return false
        end
      end
    end
    return true
  end
  
  # compter les occurences d'une sous-chaine dans une chaine
  def count_em(str, substr)
    str.scan(/(?=#{substr})/).size
  end

  # decouper le message en lignes
  # on prend en compte les retours à la ligne forcés
  # et aussi on ajoute des retours dans les lignes trop longues
  def cut_message(message, max_length)
    forced_new_lines = count_em(message, " ----- ")
    if forced_new_lines >= 4
      print("ERREUR ! Trop de lignes dans le message : "+message)
    elsif forced_new_lines == 3
      return message.split(" ----- ")
    else
      remaining_splits = 3 - forced_new_lines
      lines = message.split(" ----- ")
      # On doit distribuer les splits restants 
      # au prorata des longueurs de lignes
      splits_distributed = []
      lines.size.times { splits_distributed.push(0) }
      # On donne le split à la plus longue ligne
      # en prenant en compte les splits qu'on lui a déjà donnés
      while remaining_splits > 0
        w = 0
        for k in 0...lines.size
          line = lines[k]
          if true_size(line) / (1+splits_distributed[k]) > true_size(lines[w]) / (1+splits_distributed[w])
            w = k
          end
        end
        splits_distributed[w] += 1
        remaining_splits -= 1
      end
      # On coupe les lignes en fonction des splits attribués
      arr = []
      for k in 0...lines.size
        line = lines[k]
        #print("whole : "+line)
        # Peut-être qu'on a plus de splits que vraiment nécessaire
        needed_splits = (true_size(line)/max_length.to_f).round - 1
        if needed_splits < 0 
          needed_splits = 0
        end
        if needed_splits < splits_distributed[k]
          splits_distributed[k] = needed_splits
        end
        # On coupe la ligne !
        while splits_distributed[k] > 0 and true_size(line) > max_length
          x = find_split_index(line, max_length)
          beginning = line[0..x]
          line = line[x..-1]
          # Ne pas faire une ligne avec seulement de la ponctuation
          if line.count("a-zA-Z") == 0 
            line = beginning + line
            break
          end
          arr.push(beginning)
          #print("chunk : "+beginning)
        end
        arr.push(line)
        #print("chunk (last) : "+line)
      end
      return arr
    end
  end
  
  # longueur de la chaine de caractères sans les balises
  def true_size(line)
    true_line = line
    true_line = true_line.gsub(/\\c\[[0-9]+\]/, '')
    true_line = true_line.gsub(/\\v\[[0-9]+\]/, '999')
    true_line = true_line.gsub(/\\n\[[0-9]+\]/, 'Charles-Edouard')
    return true_line.size
  end
  
  def find_split_index(line, max_length)
    # On cherche tous les emplacements où il y a un espace
    i = -1
    indexes = []
    while i = line.index(' ',i+1)
      indexes.push(i)
    end
    # On cherche l'index qui ressemble le plus à max_length
    w = 0
    for index in indexes
      if (index-max_length).abs < (w-max_length).abs
        w = index
      end
    end
    return w
  end
  
  def cut_message_old(message, max_length)
    lines = message.split(" ----- ")
    arr = []
    for line in lines
      #print("whole : "+line)
      while true_size(line) > max_length
        beginning = line[0..max_length]
        line = line[(max_length+1)..-1]
        x = line.index(' ')
        beginning += line[0..x] unless x == 0 or x == nil
        line = line[x..-1] unless x == 0 or x == nil
        # Ne pas faire une ligne avec seulement de la ponctuation
        if line.count("a-zA-Z") == 0 
          line = beginning + line
          break
        end
        arr.push(beginning)
        #print("chunk : "+beginning)
      end
      arr.push(line)
      #print("chunk (last) : "+line)
    end
  end
  
  def insert_comments(arr, list, list_id)
    indent = list[list_id].indent
    for line_id in 0...arr.size
      line = strip(arr[line_id])
      commentaire = RPG::EventCommand.new
      commentaire.indent = indent
      if line_id == 0
        commentaire.code = 108
        commentaire.parameters[0] = "(en) "+line
      else
        commentaire.code = 408
        commentaire.parameters[0] = line
      end
      list.insert(list_id+line_id, commentaire)
      #print(list_id.to_s+" - "+commentaire.code.to_s+" - "+commentaire.parameters[0])
    end
  end
 
end

Avatar du membre
Nemau
Administrateur du site
Messages : 827
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 17 mars 2023, 19:06

Roi of the Suisse a écrit :
17 mars 2023, 00:33
Tiens je suis tombé là-dessus :

https://amours-de-fans.livejournal.com/20258.html

Ça date de 2011, mais ça fait plaisir quand même.
Ca me dit que le site est indisponible. :c

Edit : ah si c'est bon.

Avatar du membre
Nemau
Administrateur du site
Messages : 827
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 18 mars 2023, 12:51

En manipulant des statues je me suis retrouvé bloqué ici :

Image

Heureusement j'avais sauvegardé pas trop longtemps avant donc pas de souci. Il est possible qu'on puisse se bloquer ailleurs, je n'ai pas testé (je joue normalement). Je suppose que c'est inévitable du fait que le système nous permet de tirer des statues quand on est dans un coin. Tu peux prendre le parti de laisser le joueur pouvoir se bloquer ad vitam. Ce n'est pas l'idéal (c'est frustrant, surtout si on n'a pas sauvegardé depuis longtemps - mais ça ça vaut aussi si on meurt donc bon) mais si ça permet de garder le système de statues tel qu'il est (avec tout ce qu'il permet) ça en vaut peut-être le coup.

N'hésite pas à me dire si tu préfères que la prochaine fois je commente le jeu ailleurs (par MP sur Oniro, ou sur le topic d'Oniro pour donner de la visibilité au jeu).

Avatar du membre
Roi of the Suisse
Messages : 2091
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 19 mars 2023, 11:21

Ici c’est très bien.

Pour l’instant je fais juste attention de mettre une lanterne pas très loin avant un casse-tête compliqué. Voire juste à côté.

Je vais sûrement donner au héros un pipeau magique qui téléporte à un endroit safe en cas de blocage (dernière lanterne visitée…). Ça résoudra cette histoire définitivement.

J’oublie tout le temps cette histoire, parce que je ne me coince jamais. Mais c’est important, surtout pour un jeu qui se veut tout public.

Avatar du membre
Nemau
Administrateur du site
Messages : 827
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 19 mars 2023, 12:30

Un truc qui téléporte à la dernière lanterne me semble une très bonne idée.

Je note au fur et à mesure les petites coquilles à corriger, je te ferai un rapport à la fin. Ce ne sera pas 100% exhaustif, parfois je ne note pas certains trucs peu importants, de plus je joue à peu près normalement, je ne fais pas un vrai travail de testeur.


Par contre j'ai eu deux bugs, un pas très grave et un très important :

Bug 1, a priori pas important : après avoir terminé le premier donjon, j'ai parlé à une boîte aux lettres, elle m'a donné une pub du magicien Dose en me disant (il me semble) que je pouvais la lire via le menu, or j'ai cherché dans le menu elle n'apparaît nulle part. Est-ce que ça a un impact sur la suite du jeu ? Que disait cette pub ?

Bug 2, très important. Lorsqu'on parle au roi Crapo la première fois, ça désactive pendant un certain temps le switch 0001 "TOUJOURS ON" (ou un nom dans le genre), le temps qu'il fasse sa danse je crois. Sur cette même map ("Roi Crapo Ier") il y a un event (018 "brouillard de forêt"), en processus parallèle, qui possède une partie "if 0001 TOUJOURS ON est désactivé", partie qui ajoute plusieurs objets, augmente la vie maximum, etc. J'ai supprimé cette partie de cet event (pour être sûr de ne plus jamais être embêté) et j'ai créé un event pour me supprimer tout ce que j'avais acquis via ce bug (y compris les armes en double, les avoir semblait ne rien changer mais sait-on jamais). J'ai évidemment supprimé mon event ensuite.


Globalement je ne peux dire que gros GG (GGG ?), ce jeu est un grand cru. Les donjons sont très bons, l'exploration du monde est fun, la difficulté est bien dosée, les quêtes annexes sont nombreuses sans être relou, l'ambiance est cool, l'humour est distillé un peu partout sans jamais être lourd... Pour le moment je ne fais que redécouvrir la version améliorée de ce que je connaissais déjà (j'avais fait le jeu à l'époque où il n'y avait que de deux donjons), mais je m'amuse quand même.

Là je viens de terminer le second donjon, et j'ai une dizaine d'heures de jeu (oui je prends mon temps ^^).

Avatar du membre
Roi of the Suisse
Messages : 2091
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 20 mars 2023, 14:21

Ok, merci pour ton retour, il est très précieux.
Prends ton temps, ça n'est pas une course, il n'y a aucune fierté à avoir à avancer rapidement.

J'ai ajouté ce dont on a parlé plus haut :

Image

Image

C'est un objet qui manquait vraiment au jeu.

Je vais regarder les bugs dont tu parles.
Le prospectus est dans le menu "COURRIER" je crois. Si c'est juste ça, je vais au moins mentionner ce menu "courrier" dans le dialogue de la boîte aux lettres.

Avatar du membre
Nemau
Administrateur du site
Messages : 827
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 21 mars 2023, 00:12

Un menu courrier ? Je viens d'aller voir, je ne le trouve nulle part. x) Peut-être une touche en particulier à presser ?

Bon, je viens de terminer le donjon 3 (~17h de jeu, 62%), et avant de le faire j'ai fait a priori tout ce qu'on pouvait faire jusque-là. Bien que je ne note pas absolument tout, j'ai déjà un nombre conséquent de choses à dire, donc les voici. J'ai noté en temps réel la plupart des points ci-dessous, sauf certains qui du coup sont rédigés ici de mémoire, d'où certaines imprécisions/doutes. Les premiers points sont obvious ou subjectifs (c'était au tout début, je faisais du zèle ^^) mais on passe rapidement à des trucs plus importants :


- Le dossier du jeu se nomme "Projet 2". :edente: Bon je suppose que tu l'aurais renommé un jour ou l'autre, mais voilà.
- "Assavoir" (dans l'introduction je crois) : orthographe désuette dit le Wiktionnaire (mais c'est peut-être voulu ?).
- Pourquoi des armes "invisibles" ? Parce qu'au début tu avais la flemme de créer de nouveaux sprites pour le héros ? ^^
- Bon c'est subjectif mais : je n''aime pas le fait de voir le pourcentage de complétion (quand on sauvegarde), pour moi c'est comme un film où on te dirait régulièrement à combien tu es de la fin. L'immersion en prend un petit coup je trouve. J'aime bien avoir le pourcentage de complétion, mais une fois le jeu fini. ^^
- "Combien prendre de glands ?" : j'aurais plutôt dit "Prendre combien de glands ?" (je peux me tromper, mais cette syntaxe m'a fait bizarre au premier abord)
- Dans la maison de Mathusalem, le livre qui indique les commandes est peut-être obsolète (mais j'ai un doute).
- L'énigme du "si tu es ton propre père tu es ton propre grand-père". Pourquoi ? ^^ Qu'un père et un fils soient la même personne, c'est possible avec une machine à voyager dans le temps et un joli paradoxe, mais admettons. Mais pourquoi on serait, du coup, son propre grand-père ? En y repensant, je dirais plutôt qu'il n'y a pas de grand-père, du coup.
- Quand le présentateur radio souhaite la bienvenue au nouvel arrivant (moi je suppose), le nom de l'arrivant n'apparaît pas. À ce propos : de mémoire il n'y a qu'un seul autre endroit où mon nom est cité (un dialogue avec le serrurier - à tel point que ça m'a fait bizarre de lire mon pseudo), je pense que ça rendrait le truc un peu plus immersif si les PNJ mentionnaient davantage le nom du joueur.
- En bordure de zone il y a certaines maps dans lesquelles apparaît le nom de la zone même si on vient d'une map située dans la zone concernée.
- Toujours concernant l'affichage du nom de la zone à l'arrivée dans cette dernière : je ne sais pas si ça concerne tout le jeu, mais parfois j'ai constaté que si on débarque dans une nouvelle zone et qu'à peine sur la nouvelle map on revient sur la map précédente, le nom de la zone reste affiché tant qu'on ne change pas de nouveau de zone.
- Je ne sais pas si c'est voulu, mais quand on ouvre la bouche d'un serpent et qu'on quitte la map avant la fin du chrono virtuel, le chrono est stoppé et il reprend (de là où il s'était arrêté) lorsqu'on revient sur la map du serpent.
- Je pense qu'il serait plus logique et agréable que le caleçon ignifugé soit un objet auto-équipé, sachant qu'il ne nécessite pas qu'on appuie sur une touche pour l'utiliser (contrairement aux bottes, au panier et au tuba).
- Quand on est sur la map du demi-boss oursin (le premier, peut-être le deuxième également), le héros n'apparait pas sur le plan de la zone (en tout cas une fois le demi-boss vaincu). J'ai constaté ce bug (tête du héros n'apparaissant pas sur le plan) sur quelques autres maps (2-3 je dirais), et il y a également une map (à l'ouest de la zone viking rouge, je crois) où sur le plan la tête du héros s'affiche sur la map d'en dessous (il me semble).
- Quand on n'a pas assez d'argent, le potier des colibris nous dit un truc du genre "le vase coûte 50 coquillages, reviens quand tu auras 100 coquillages".
- "Savais-tu que c'est moi qui avais fabriqué tous les balais de Kujira ?" : j'aurais dit "Savais-tu que c'est moi qui ai fabriqué tous les balais de Kujira ?". Je n'en suis pas sûr à 100% alors n'hésite pas à vérifier (sauf si toi tu es sûr bien entendu ^^).
- "[...] matérialisation de haine fans de Didier Wampas." : il manque un mot j'ai l'impression.
- Dans le marais il y a un haiku de Matsuo Bashō qui est décalé (pour le lire il faut se placer un carreau à droite du panneau).
- Y aura-t-il un faceset pour Pozzo et Lucky ? Ça m'a fait un peu bizarre qu'ils n'en aient pas.
- Je n'ai compris qu'assez tardivement que le visage de Pozzo représentait son nez pointé vers le haut. Pour moi ses narines représentaient ses yeux. ^^ (ce qui lui donnait un air un peu méchant, convenant au personnage) À voir si je suis le seul dans ce cas où si une proportion significative de joueurs le voient pareil.
- Le mini jeu de Lucky et des panneaux, je te l'avais déjà dit la première fois que j'avais fait le jeu mais : c'est ni fun, ni drôle (là je pense au texte), ni intéressant, ni facile, ni rapide. xD Désolé, vraiment j'adore le reste du jeu mais cette énigme ...wtf ? x) Si au moins le texte faisait pleinement sens, et qu'il n'y avait qu'un seul panneau par message, ce serait un peu plus facile. J'ai dû noter sur un cahier (je n'aime pas beaucoup "sortir" du jeu ainsi) les 16 messages puis noter au fur et à mesure la solution sur un plan de la map. Et j'ai quand même dû regarder la solution en ouvrant le jeu dans RMXP, car je n'utilisais pas le bon panneau pour le 15ème message (comment comprendre quel panneau utiliser s'ils disent la même chose ?).
- Les AGV (tous ?) comportent un bug : les 4-5 premières fois que je l'ai utilisé, juste après l'ouverture des barrières le perso est resté bloqué pendant plusieurs secondes, avant que j'arrive à le débloquer je ne sais pas trop comment. Tout à l'heure j'ai repris l'AGV et pour la première fois il n'y a pas eu ce blocage temporaire du perso (est-ce que ça dépend de la station ?).
- Quand on pénètre dans la map de la plupart des Chomping-Tree (pas tous) il y a un bruit, qu'il n'y a pas quand on rentre dans n'importe quel autre caverne ou map en général.
- Quelques coffrillages demandent une confirmation pour s'ouvrir. Ça concerne quelques coffrillages de l'overworld, mais également au moins un coffrillage dans un donjon (le deuxième je crois), de mémoire.
- Le panneau de publicité pour la source de la sirène ne s'affiche que si on a 200 coquillages ou plus ? Ça m'a fait bizarre la première fois que je l'ai vu, j'ai cru à une sorte de bug (c'est en allant voir sur RMXP que j'ai compris que c'était voulu). Je pense que tu devrais le laisser même quand on a peu de rubis coquillages (edit, la force de l'habitude lol), le fait qu'il apparaisse/disparaisse en fonction de nos rubis coquillages fait bizarre. Enfin, je te laisse juger, c'est pas un vrai souci de toute façon.
- Mini jeu de comptage des balais : quand on perd ça nous prend deux vies au lieu d'une.
- Toujours au sujet du mini jeu des balais : s'il faut se refaire, à la fin du jeu, tout le jeu en comptant les balais, c'est un peu relou. x) Suggestion : que quand on perd la sorcière nous dise si c'est plus ou si c'est moins.
- On ne peut pas lire les tombes du cimetière viking quand on est face à elles (il faut les lire en étant à côté), contrairement à la tombe dans la clairière de Mathusalem.
- Juste avant de faire le troisième donjon j'étais déjà à 59% de complétion, est-ce normal ? (sachant qu'il y a six donjons...)

Les problèmes suivants concernent le donjon 3 (pas eu de souci dans les deux premiers donjons, en tout cas rien de suffisamment problématique pour que je le note) :
- Dans la pièce située tout en bas à gauche : la cloche de retour n'est pas sur le plan. De plus, elle permet correctement de quitter la pièce mais quand on sonne les autres cloches on ne peut pas revenir à celle-la.
- Dans une des maps possédant une clochette à faire sonner via un ballon (il me semble que c'est la map "18 19 mini ballons"), on ne voit que quelques pixels de la clochette (elle dépasse de la map). Je n'étais pas encore allé dans les autres maps possédant une clochette, du coup je ne savais pas vraiment ce que c'était (on comprend quand même facilement ce qu'il faut faire, mais voilà). Et de manière générale ça vaudrait le coup de grossir un peu la taille des clochettes je pense, elles sont un peu petites je trouve.
- Dans cette salle : on peut déplacer la statue sur la zone que j'ai marquée en rouge (jusqu'où ? j'ai pas trop essayé, de peur de bloquer la statue dans le sable).
- Même problème dans cette salle (statue allant sur le sable). Par contre je ne sais plus quelle(s) est/sont la/les statue(s) concernée(s).
- Gros bug : sans faire exprès je suis allé sur le carreau qui téléporte en dehors du donjon (en haut du monticule de sable), du coup quand le jeu m'a demandé si je voulais sortir du donjon malgré la perte de l'arme j'ai dit "non", et ...le jeu a planté. Je sais que ce n'était pas un hard lock vu que je ne pouvais plus accéder au menu. Heureusement je venais de sauvegarder. ^^
- Dans cette salle : j'ai débloqué la porte fermée en ...envoyant un des deux blocs-ballons sur la porte d'entrée (carreau entouré). Wut ? Du coup pour ne pas tricher j'ai quand même résolu l'énigme même si je n'avais plus besoin de le faire (GG d'avoir mis les deux statues inutiles pour brouiller les pistes, à cause d'elles j'ai mis pas mal de temps à résoudre l'énigme xD).
- Lors du combat avec les trois demi-boss qui tournent autour de carrés, quand on tape sur un ça semble taper sur les deux autres (en tout cas ils font l'animation de quand ils se prennent un coup).
- J'ai eu deux fois la cinématique de Rebeca et son père quand il lui parle de "science sans conscience".
- Concernant les homards de la salle du boss final du donjon, il n'y a pas d'animation quand ils se prennent un coup. Autrement ils meurent bien au bout de trois coups, pas de souci.


Remarques diverses :

- Sur la couverture du livre de la cinématique d'intro, on dirait qu'à côté du "no" de "Kujira no Hara" il y a un symbole effacé, si oui il veut dire quoi ? (c'est pour savoir s'il y a un sens caché ou dans le genre ^^)
- Dans la clairière de Mathusalem, je pense que l'inscription complète de la tombe est "Poésie". Du coup ça m'intringue, pour les raisons que tu imagines. J'espère que la suite du jeu apportera une réponse !
- J'ai rirl en lisant la description des pommes. xD
- La zone viking rouge et le donjon 3 sont à la hauteur de ce que j'avais fait jusque-là, GG.

Avatar du membre
Roi of the Suisse
Messages : 2091
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 21 mars 2023, 00:41

Ah oui, il n’y a plus de menu courrier avec mon tout nouveau menu :pwned:

J’ai décidé de remplacer le courrier par des panneaux d’information publics situés à chaque station. De toutes façons c’était bizarre une boîte aux lettres pour recevoir du courrier.
Je rêvais autrefois d’une fonctionnalité pour envoyer des cartes postales aux personnages du jeu, mais c’est du feature creep. On va déjà finir le jeu.

Je traite les bugs de ton message bientôt.

Répondre