Jump to content
Zen Blood

Creating a (Hopefully) Simple New Game Plus Feature

Recommended Posts

Hello, everyone.

 

Today I've been working on a "New Game Plus" feature, where if you have completed the game once, a switch will be set to true that allows you to select and play a new game that has extra features in it. I am very close to having this set up exactly the way I need it to be.

 

Using this little set up here, I created a switch ($extragame) that can be set to true while in-game. I will set it to true after the player has completed the whole game. At the title screen, when they select "New Game" it will take them to a scene that'll ask them if they want a "New Game" (without extra features) or a "New Game +" (that will have extra features.)

 

module DataManager
  
  class << self
    alias orig_CGO create_game_objects
    alias orig_MSC make_save_contents
    alias orig_XSC extract_save_contents
  end
  
  def self.create_game_objects
    orig_CGO
    #MY OBJECTS
    $extragame        = false unless true
    $extragame_y     = false
  end
  
  def self.make_save_contents 
    contents = {}
    contents = orig_MSC
    #MY OBJECTS
    contents[:$extragame]   = $extragame
    contents[:$extragame_y] = $extragame_y
    return contents
  end
  
  def self.extract_save_contents(contents)
    orig_XSC(contents)
    #MY OBJECTS
    $extragame          = contents[:extragame]
    $extragame_y      = contents[:extragame_y]
  end

 

If they select New Game +, the setup for a new game will execute pretty much the same as normal, but with an addition that $extragame_y (as in "yes the player selected an extra game) will be set to true after the game has technically started. Before anything else will happen, the player will be immediately prompted in-game to save. That way when the player continues on that specific save file, the whole game will have extra features from then on.

  def newgame_extra
    DataManager.setup_new_game
    fadeout_all
    $game_map.autoplay
    SceneManager.goto(Scene_Map)
    $newgameplus_y = true
  end

 

Everything is almost in place, except for the problem that if the player exits the game and re-opens it, the switch $extragame is set to false again. This doesn't happen if you go to the title screen, even if you don't save after triggering $extragame to be set to true. My solution is to find a way to make the state that switch $extragame is in to persist even after the game is closed. However, that could be an issue as well, since that means I could potentially publish the game with the switch already set to true because I've been testing out the extra game feature.

 

I'm considering to solve this solution by having switch $extragame set to true at the very end of the game, making the game autosave on the save file the player is playing on, and then whenever the game is booted up it checks to see if there's a save file where $extragame is set to true. If there is a file that meets the requirements, then the player is given the option to play on a "New Game Plus" file. 

 

I feel like I'm so close to figuring it all out, but my last idea seems to be a little out of my element. I will continue researching what I can do. If anyone has any ideas, I would be happy to hear!

 

Thank you for your time.

Share this post


Link to post
Share on other sites
Posted (edited)

Please, please, please perfect and flesh this out so it (if it doesn't already) can interact with switches and events so the player can utilize it in various ways aside from the obvious NG+ feature.

 

Regardless, this is a godsend. When done properly (Legend of Mana) it opens up a whole new set of doors for developing your game that adds some delicious, appealing layers to hardcore RPG fans.

 

LoM did it in a way where you don't get to the end and restart only to feel as if it's more of a chore to replay as this OP monster from the depths of hell. retracing your exact same steps in the exact same linear plot (Chrono Trigger), resulting in the feeling of an afterthought bonus round of sorts. Instead LoM built it's concept around the idea of cycles of death and rebirth. It also set up it's system and game world with a sandbox format that both encourages and rewards replays. LoM really nailed synergy across the board, but the replay dynamic was at the center of and was complimented by it all.

 

Excellent job and please don't give up. Keep other good NG+ systems in mind and do your best to make it all it can be. I know people will thoroughly enjoy this. I plan to use it if the hiccups get resolved.

Edited by That One NPC

Share this post


Link to post
Share on other sites

false unless true seems to be a point of contention, however, it might be solvable if you have it look for $newgameplus_y in Game_Load, or something.
Maybe, @roninator2 could be of help here. I'd see if Kayzee could help, but she's rarely around anymore...hence I didn't even tag her...

Share this post


Link to post
Share on other sites
On 3/28/2021 at 7:22 PM, That One NPC said:

Please, please, please perfect and flesh this out so it (if it doesn't already) can interact with switches and events so the player can utilize it in various ways aside from the obvious NG+ feature.

 

Regardless, this is a godsend. When done properly (Legend of Mana) it opens up a whole new set of doors for developing your game that adds some delicious, appealing layers to hardcore RPG fans.

 

LoM did it in a way where you don't get to the end and restart only to feel as if it's more of a chore to replay as this OP monster from the depths of hell. retracing your exact same steps in the exact same linear plot (Chrono Trigger), resulting in the feeling of an afterthought bonus round of sorts. Instead LoM built it's concept around the idea of cycles of death and rebirth. It also set up it's system and game world with a sandbox format that both encourages and rewards replays. LoM really nailed synergy across the board, but the replay dynamic was at the center of and was complimented by it all.

I definitely plan on using it to control certain switches and variables. There's so much that could be done. 😁 However, the extent to which I take advantage of this feature will depend on how much more time I allow myself to develop my game. LoM sounds very interesting.

 

On 3/28/2021 at 7:22 PM, That One NPC said:

Excellent job and please don't give up. Keep other good NG+ systems in mind and do your best to make it all it can be. I know people will thoroughly enjoy this. I plan to use it if the hiccups get resolved.

Thank you very much! 🙏 I would like to publish it for public use if I can make it streamline enough for a "plug and play" sort of script, as well as not needing to rely on anything too specific in my game.

 

4 hours ago, PhoenixSoul said:

false unless true seems to be a point of contention, however, it might be solvable if you have it look for $newgameplus_y in Game_Load, or something.
Maybe, @roninator2 could be of help here. I'd see if Kayzee could help, but she's rarely around anymore...hence I didn't even tag her...

Ah yes, I have kind of lost my thought process as to why I used false unless true, haha. Thank you for pointing me in the direction of Game_Load, I'll see what I can find from there.

Share this post


Link to post
Share on other sites
10 hours ago, PhoenixSoul said:

Maybe, @roninator2 could be of help here

 

5 hours ago, Zen Blood said:

There's so much that could be done

I just don't understand why yanfly's new game plus is not an option. or use the code to understand what you need to set up.

Share this post


Link to post
Share on other sites
15 hours ago, roninator2 said:

 

I just don't understand why yanfly's new game plus is not an option. or use the code to understand what you need to set up.

 

Unfortunately Yanfly's New Game + script requires Yanfly's Ace Save Engine script as well, which heavily alters my saving and loading UI, and possibly other things I'm not aware of at this moment. I could try to fish out all the problem lines of script in the Ace Save Engine, and I can understand using someone's script for a bit of guidance, but dismembering it and then using it as my own feels a little wrong. Not to mention it would take a while to differentiate what I can (and need to) cut out and what the New Game + script relies on.

 

Though upon looking at Yanfly's New Game +, I see that $data_system.switches might play a role in telling the game to search individual game files to check if a certain switch is on within one of those saves. I have a sneaking feeling that Marshal.load/dump might be needed for this as well. I'm still wrapping my head around what exactly Marshal does, so I could be completely wrong.

Share this post


Link to post
Share on other sites
Posted (edited)

You know if Marshal stuff is too confusing, you can use the RGSS 'load_data' and 'save_data' instead.

 

Here is what the VX ACE help file has to say about them:

Quote
load_data(filename)

Loads the data file indicated by filename and restores the object.


$data_actors = load_data("Data/Actors.rvdata2")
This function is essentially the same as:

File.open(filename, "rb") { |f|
  obj = Marshal.load(f)
}

However, it differs in that it can load files from within encrypted archives.

 

save_data(obj, filename)

Saves the object obj to the data file indicated by filename.


save_data($data_actors, "Data/Actors.rvdata2")
This function is the same as:

File.open(filename, "wb") { |f|
  Marshal.dump(obj, f)
}

 

Edited by Kayzee

Share this post


Link to post
Share on other sites

Right now I have a few snippets of code I've been experimenting with. For one, the names of specific save files (Save01.rvdata2, Save02.rvdata2, Save03.rvdata2, ect;)

I could use that to cycle through the different save files to check to see if a certain switch is on.

 

I've also been playing around with the lines @Kayzee shared. By the way, thank you Kayzee! I often forget to check the manual, but also I don't always know what terms I want to look for and the search bar can be a bit picky. 😩 It's nice to have some direction.

 

So I tried this as an example:

$data_actors = load_data("Data/Actors.rvdata2")
msgbox_p($data_actors)

I get a little message box giving me a bunch of information about Data/Actors. From what I can tell, it's the condition Data/Actors are in at the beginning of the game. At least it means I'm successfully getting data information, as I should.

 

"Data/Variables.rvdata2" or "Data/Switches.rvdata2" doesn't work, sadly. No surprise, since DataManager doesn't contain information on variables/switches.

image.png.1c27817652003b4e17584e7d2e8f3017.png

However, information on a switches'/variables' initial and current state in a specific save file must be kept somewhere.

 

I may even decide to toss out the idea of a custom global variable/switch, in this case $extragame. Finding a custom variable might be a bit more complicated than finding the built-in variables and switches that are often called upon with $game_variables[ ] and $game_switches[ ]

 

So now I'm tinkering with lines like "$game_variables[1].Save01.rvdata2". Doesn't work, sadly, but I'm going to try throwing alterations to see if anything sticks.

Share this post


Link to post
Share on other sites

Saved games are basically big hashes that store copies of the "$game_" values. DataManager's make_save_contents creates a hash from the "$game_" values to be saved into a saved game and extract_save_contents takes a hash from a saved game and copies it back to the "$game_" values. Oh and create_game_objects makes new "$game_" values for when a new game starts. But anyway you could scan each saved game one by one with load_data and check the hash for the right thing you need, which would be a little tedious, or you could do something like using an $extragame thing.

 

I actually made something a while ago to manage anything I wanted to save outside normal saved games maybe it will be handy for you too!

 

Spoiler

Try using this script:


module GlobalSaveData
  
  FILE_NAME = "GlobalSaveData.rvdata2"
  
  class << self
    attr_accessor :need_save
  end
  
  def self.[](key)
    get_hash[key]
  end
    
  def self.[]=(key, value)
    @need_save = true
    get_hash[key] = value
  end
  
  def self.save
    return unless @hash && @need_save
    save_data(@hash, FILE_NAME)
    puts 'Global Save Data Saved.'
    @need_save = false
  end
  
  def self.get_hash
    unless @hash 
      if File.exist?(FILE_NAME)
        @hash = load_data(FILE_NAME)
        puts 'Global Save Data Loaded.'
      else
        @hash = {}
        puts 'Global Save Data Not Found.'
      end
    end
    return @hash
  end
  
end

class Scene_Base
  
  alias_method :update_global_save_data_base, :update
  def update
    update_global_save_data_base
    GlobalSaveData.save
  end
  
end

You can just set anything you want like "GlobalSaveData[:extragame] = true" and it will automatically save it as soon as the scene updates. Checking "GlobalSaveData[:extragame]" should automatically load it.

 

Share this post


Link to post
Share on other sites
9 hours ago, Zen Blood said:

cycle through the different save files

A script called Rachael - Dynamic Title Screen Music

does this.

      for i in 0...DataManager.savefile_max
        header = DataManager.load_header(i)
        next unless header and header[:music]
        music = [music, header[:music]].max
      end

 

Share this post


Link to post
Share on other sites
4 hours ago, Kayzee said:

I wonder if that would take a while if you have a lot of save files. Can't you have up to 99 savefiles sometimes?

I think the number of save files is nigh unlimited (however many 32 bits can hold I imagine). I know I once expanded the number of save files to over a hundred.
Kinda dumb but yeah. lolz

Share this post


Link to post
Share on other sites
17 hours ago, Kayzee said:

 

  Reveal hidden contents

Try using this script:



module GlobalSaveData
  
  FILE_NAME = "GlobalSaveData.rvdata2"
  
  class << self
    attr_accessor :need_save
  end
  
  def self.[](key)
    get_hash[key]
  end
    
  def self.[]=(key, value)
    @need_save = true
    get_hash[key] = value
  end
  
  def self.save
    return unless @hash && @need_save
    save_data(@hash, FILE_NAME)
    puts 'Global Save Data Saved.'
    @need_save = false
  end
  
  def self.get_hash
    unless @hash 
      if File.exist?(FILE_NAME)
        @hash = load_data(FILE_NAME)
        puts 'Global Save Data Loaded.'
      else
        @hash = {}
        puts 'Global Save Data Not Found.'
      end
    end
    return @hash
  end
  
end

class Scene_Base
  
  alias_method :update_global_save_data_base, :update
  def update
    update_global_save_data_base
    GlobalSaveData.save
  end
  
end

You can just set anything you want like "GlobalSaveData[:extragame] = true" and it will automatically save it as soon as the scene updates. Checking "GlobalSaveData[:extragame]" should automatically load it.

 

That's incredible. It works exactly in the way that I need it to work. I may still try to put together something myself, but just so I know for future reference, would I have your full permission to use this script in the game that I am making? It is a commercial project, and it is a horror game depicting sensitive material. If you are not comfortable with this, I understand. If you're alright with me using your script, then I am very grateful and I'd like to ask if you'd like to be credited. 

Share this post


Link to post
Share on other sites
11 hours ago, Kayzee said:

It's fine with me if you wanna use it! It's not too complicated of a script anyway. Being credited might be neat, but I mostly just like to help!

Thank you, Kayzee. I really appreciate it. Just for the sake of learning, I'll try to make my own version, but it's truly a relief to know that I'm allowed to use something that works in case I just can't figure it out myself.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
Top ArrowTop Arrow Highlighted