Get any map display name?

● ARCHIVED · READ-ONLY
Started by AeghtyAteKees 20 posts View original ↗
  1. I can use $game_map.display_name to access the display name for the map I'm on, but how do I access the display name of any map?
  2. The map names are stored in the map files, i.e. those files named like "Map001". To get the name for an unloaded map, you'd need to temporarily load it using the ID, then access its name like this:

    Spoiler
    Code:
    map_id = 1
    temporary_map = load_data(sprintf("Data/Map%03d.rvdata2", map_id))
    other_map_name = temporary_map.display_name
  3. Well that works nicely. Although, I've run into a larger issue I have no idea how to fix. Maybe you could help me out?

    I needed this so I can display dynamic NPC locations in Modern Algebra's Quest Journal, and I've set it up to work, but the script doesn't seem to refresh the quest data after loading it for the first time. So even though I may change my map name variable, the displayed name never changes. I don't know enough about Ruby to modify the script to refresh appropriately...

    Line 792 is where I've used my variable instead of a string.

    I would really appreciate your help!
  4. What exactly does line 792 look like for you? Basically, I'm interested in how you're referencing your variable. Also, walk me through how it doesn't refresh. So you start the game and open the journal: what's displayed? Then you change your variable and open the journal: what's displayed? That kind of walk-through is super helpful in troubleshooting.
  5. Thank you for replying! Let me try to help you help me. :)

    So my line 792 looks like :
    Code:
    q[:location]          = "#{@npc45_loc} "

    I inserted into the script, just before line 778 the following (which seems to work fine?) :
    Code:
    loc_id = $game_variables[80] #The map ID NPC 45 is currently on, set by the NPCs Common Event)
    loc_map = load_data(sprintf(
    "Data/Map%03d.rvdata2", loc_id))
    loc_name = loc_map.display_name
    @npc45_loc = loc_name

    To answer your questions, when I start the game and open the quest scene, it is empty, of course. My NPC location is dynamic and controlled by a Common Event. I add the quest (via a test event) and when I open the quest scene again, everything looks great. The quest giver location is correctly displaying the name of whatever map my NPC is supposed to be on. Then, if I run my Common Event and the NPC is determined to have moved maps (therefore updating $game_variables[80] to a new integer representing the new map ID), and I reopen the quest scene, the quest giver location has not updated, and still displays the name of the first map he was on. This system is intended to inform the player where all the moving characters are, so he/she doesn't get frustrated if they aren't where they were before. I like the dynamic feel of NPCs having schedules and different places to be, I just don't want it to become a drawback. This magical Marauder's Map feature would be a great integrated solution. :)

    A few things I've noticed through testing:

    1) my little snipped I've inserted at line 778 isn't run every time the scene is called, but only when a new quest is added. So that's not working.

    2) even if the snippet runs (forced to do so by adding another quest and running the code), line 792 (q[:location] = "#{@npc45_loc} ") is not updated. So, the displayed information remains the same, even if the variable @npc45_loc has changed.

    Hope that helps. As you can tell, I am not a coder. I add and edit crap through trial and error until I get it to work, which sometimes I never do. :D
  6. Ok, so you're already on the right track. You know your code isn't running when you'd like it to. If you scroll up from line 778 to line 610 you should see "def self.setup_quest(quest_id)". Even if you don't entirely understand that line, you should see that it says "setup_quest". So your code is only running when a quest gets setup. Hey you already knew that! :) But now you know why. So we need to move our code somewhere that will be run when the scene is called but only once so that we don't slow the game down.

    Let's go looking through the script for the "scene". So, I ctrl+F the word "scene" and find line 2386 "class Scene_Quest < Scene_MenuBase". Ok, so this should be the place. Let's look through what's here. Scrolling down we find on line 2390 "def start" and above it is a comment that says "Start Scene Processing". So this gets run at the start. Cool B), so now we know where we can put our code to run when the scene starts.

    But as you've already deduced, even if you trick the code into running, the displayed information remains the same. Boo. So what gives? Well, it has to do with how we're referencing things. Your current line 792 (q[:location] = "#{@npc45_loc} ") says take the *value* of the variable @npc45_loc and store it in a new string as the location. Effectively making a copy of it. What we want to do is tell the location to look directly at the variable. So at a simple level, we should do something like this: q[:location] = @npc45_loc

    So that would kind of work, but also not really and then we get into some deeper level ruby stuff about object references and stuff that I can't explain in a short post (like this is a short post anyway lol). Suffice it to say, we need to be a little more meticulous and move our code into its own thing. So here it is:
    Spoiler
    Code:
    module NPC_Locations
      # This stores the dynamic locations of all npcs
      # It needs to be filled with the 'keys' for each
      # npc. A key looks like this - :some_name - if
      # you copy the examples below you should be fine.
      # You can leave the location blank if want like 
      # example #2
      @@locations = {
          :npc45 => "camp"
          :new_npc => ""
      }
      # This links the npcs to their corresponding id
      # in $game_variables
      # Every npc present above needs an entry here
      @@npc_game_vars = {
          :npc45 => 80
          :new_npc => 1
      }
     
      # To then make the quest journal reference our npcs
      # we use the following:
      # q[:location] = NPC_Locations[:npc45]
      # Obviously, replace :npc45 with whatever npc key you need
    
      def self.[](name)
        @@locations[name]
      end
    
      def self.[]=(id, newvar)
        @@locations[id].clear
        @@locations[id] << newvar
      end
    
      def self.update_all()
        @@locations.each_key do |key|
            loc_id = $game_variables[ @@npc_game_vars[key] ]
            loc_map = load_data(sprintf("Data/Map%03d.rvdata2", loc_id))
            loc_name = loc_map.display_name
            NPC_Locations[key] = loc_name
        end
      end
    
    end
    
    class Scene_Quest < Scene_MenuBase
      # Create an alias for the old method so we can call it
      alias MA_start start
      # Add our code to the scene start method
      def start
        # Call the original method
        MA_start
        # Call our update code
        NPC_Locations.update_all()
      end
     
    end

    Hopefully that makes sense (and works lol, I haven't bug tested it).
  7. Wow, thanks again. Very detailed assistance!

    But..... I may have caused more confusion by trying to simplify things to start with. Let me be completely transparent and show you what I'm doing.

    I'm not using $game_variables at all, actually. I have too many NPCs and didn't want to take up tons of variables in the editor's interface. I have a separate snippet that looks like this:
    Spoiler
    Code:
    module DataManager
     
      #--------------------------------------------------------------------------
      # * Create Wrapper Class
      #--------------------------------------------------------------------------
     
      class AAKHash
     
      def initialize(default = nil)
        @data = default || {}
      end
    
      def [](key)
        @data[key] || 0
      end
    
      def []=(key, value)
        @data[key] = value
      end
     
    end
     
      #--------------------------------------------------------------------------
      # * Create Game Objects
      #--------------------------------------------------------------------------
      class << self
        alias create_game_objects_tablelist_base create_game_objects
      end
      def self.create_game_objects
        create_game_objects_tablelist_base
        $npcs = AAKHash.new
        $cards = AAKHash.new
        $guildloot = AAKHash.new
        $dailysearch = AAKHash.new
        $ingredients = AAKHash.new
      end
      #--------------------------------------------------------------------------
      # * Create Save Contents
      #--------------------------------------------------------------------------
      class << self
        alias make_save_contents_tablelist_base make_save_contents
      end
      def self.make_save_contents
        contents = make_save_contents_tablelist_base
        contents[:npcs] = $npcs
        contents[:cards] = $cards
        contents[:guildloot] = $guildloot
        contents[:dailysearch] = $dailysearch
        contents[:ingredients] = $ingredients
        contents
      end
      #--------------------------------------------------------------------------
      # * Extract Save Contents
      #--------------------------------------------------------------------------
      class << self
        alias extract_save_contents_tablelist_base extract_save_contents
      end
      def self.extract_save_contents(contents)
        extract_save_contents_tablelist_base(contents)
        $npcs = contents[:npcs]
        $cards = contents[:cards]
        $guildloot = contents[:guildloot]
        $dailysearch = contents[:dailysearch]
        $ingredients = contents[:ingredients]
      end
    
    end

    This lets me have unlimited "global variables" to use throughout the game, primarily for huge lists of data that I wanted to be easily organized and modifiable, i.e. not using the editor's $game_variables interface.

    As I didn't want to include extraneous information and complicate what we were working on, I left this out of my earlier reply. I suppose it wasn't irrelevant after all. So, where I previously said I was using $game_variables[80], I actually just reference the npc location in my hash with $npcs[:npc45_loc]. Does this change things? >.>
  8. Yes, but it doesn't change much. So if you look at the code I posted, specifically at this section:
    Spoiler
    Code:
    def self.update_all()
        @@locations.each_key do |key|
            loc_id = $game_variables[ @@npc_game_vars[key] ]
            loc_map = load_data(sprintf("Data/Map%03d.rvdata2", loc_id))
            loc_name = loc_map.display_name
            NPC_Locations[key] = loc_name
        end
      end

    It should look pretty familiar. The key difference is this "update_all" method runs once each time the quest scene is opened, and loops through all of the provided "keys". So we change one line:
    Spoiler
    Code:
    def self.update_all()
        @@locations.each_key do |key|
            loc_id = $npcs[key] #### <<<< This one
            loc_map = load_data(sprintf("Data/Map%03d.rvdata2", loc_id))
            loc_name = loc_map.display_name
            NPC_Locations[key] = loc_name
        end
      end
    and we make sure that the 'keys' all match. That is, use ":npc45_loc" for the $npcs hash and the @@locations hash. You can also just get rid of the
    @@npc_game_vars hash.
  9. Awesome!

    Now that that's fixed, what about this part of your code where we access the quest journal?

    Code:
      # To then make the quest journal reference our npcs
      # we use the following:
      # q[:location] = NPC_Locations[:npc45]
      # Obviously, replace :npc45 with whatever npc key you need

    How does this specify which quest I'm adding the location to? Or am I not understanding something?
  10. That's an example of line 792. Whereas before you used
    Code:
    q[:location] = "#{@npc45_loc}"
    now you'll use
    Code:
    q[:location] = NPC_Locations[:npc45_loc]
    Again, just make sure the "key" you use is consistent across all the hashes (where the key is the ":npc45_loc" bit)
  11. Right, I remember that. But, I'm referring to which quest in the journal we're accessing, as each journal entry has a
    Code:
    q[:location] =

    At line 778 in the quest script, it says "when 1 #sample quest". So for "when 2" or any further entry, there will be a q[:location] for each of those.
  12. I guess I don't quite understand the question, but I'll try to explain what I'm doing better so maybe that will clear things up.

    First, I'm assuming that you already have a list of NPCs that give quests. This list lives in your "$npcs" hash. The hash contains a bunch of "keys", which are the identifiers for the NPCs. If I wrote:
    Code:
    $npcs.each_key { |key|
      print key
    }
    I would get a list that looks something like this:
    :npc1
    :npc2
    :npc3
    etc.
    If I'm wrong about that, please correct me.

    Second, I'm assuming that you already have some quests built. The first (1) quest lives under line 778 in the quest script where it says "when 1". The second (2) quest lives further down in the quest script where it says "when 2". The third (3) quest lives even further down in the quest script where it says "when 3". And so on and so forth. Each of these quests has a line that looks like:
    Code:
    q[:location] =

    Then it's as simple as matching the NPC's key to the quest. Assuming NPC1 goes with quest 1, the code would look something like this:
    Code:
    when 1 # Quest 1 - SAMPLE QUEST
      ...
      q[:location] = NPC_Locations[:npc1]
      ...
    when 2 # Quest 2
      ...
      q[:location] = NPC_Locations[:npc2]
      ...
    when 3 # Quest 3
      ...
      q[:location] = NPC_Locations[:npc3]
      ...

    Sorry if that's still not clear. Hopefully it is, but if it isn't, just let me know.
  13. I just now realized that what I was seeing in your code was hashed out, and you were referring to the quest script.
    Code:
      # To then make the quest journal reference our npcs
      # we use the following:
      # q[:location] = NPC_Locations[:npc45]
      # Obviously, replace :npc45 with whatever npc key you need
    I thought we were accessing the quest script with this. Sorry. My fault!

    Next, I get an error in your code saying MA_start (found at the bottom) is an uninitialized constant.
  14. No worries! This stuff can get confusing. I'm glad you figured it out.

    AeghtyAteKees said:
    Next, I get an error in your code saying MA_start (found at the bottom) is an uninitialized constant.

    That's my bad. I sometimes forget some of Ruby's rules. Just change every instance of "MA_start" to "ma_start" (there should be two).
  15. Oh, good! That's fixed.

    How would I go about checking if the map id is 0? Because 1) sometimes an NPC's location id can be set to 0, in which case I would like to display "Unavailable" instead of a map display name, and 2) I'll get an error message if the game tries to load map data for map 0.
  16. Just before loading the map data we can check for that, and if it is zero, we can substitute "unavailable" instead. So we modify the "update_all" method again:
    Spoiler
    Code:
    def self.update_all()
       @@locations.each_key do |key|
           loc_id = $npcs[key]
           if loc_id == 0
               loc_name = "Unavailable"
           else
               loc_map = load_data(sprintf("Data/Map%03d.rvdata2", loc_id))
               loc_name = loc_map.display_name
           end       
           NPC_Locations[key] = loc_name
       end
    end
  17. Great.

    I now get no errors, but no location is displayed in the journal. I believe the journal script is set up so that if no location is specified, it leaves that line out of the window. So either the location isn't being set right, or the journal can't tell it's there.
  18. Hmmm.... If you're alright with it, would you mind PM-ing me a link to download your project? At this point, I'm out of ideas on what it could be, and it'll be faster to just directly troubleshoot it.
  19. Ok, it was just a simple ordering problem. First, you need to put my code below the quest journal in the script editor. Then you need to swap two lines on my code; update it to look like this:
    Spoiler
    Code:
    class Scene_Quest < Scene_MenuBase
      # Create an alias for the old method so we can call it
      alias ma_start start
      # Add our code to the scene start method
      def start
        # Call our update code
        NPC_Locations.update_all()  #<< Swap these
        # Call the original method
        ma_start                               #<< two lines
      end
    end
  20. It works beautifully! Thanks for all your help. ^_^