No experience scripting, multiple goals, requesting help

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
Hi. So, as someone who has basically no experience scripting in RPG Maker XP (but can code in other languages so he is capable of learning), I have some things I need to do that I do not know how to do. I'm not sure how to best ask this, so I'll list out my goals:

(and before anyone tells me to use another engine, for my purposes I have to use XP.)

-Save variables (in this case, endings completed in a game with multiple endings) to system data rather than a file
-Change options displayed in Title Screen (ie. when one ending is acquired, Staff Room option becomes available)
-Add events to main game if certain endings have been acquired.
-Create a Music Test menu

Even just leading me in the right direction for these goals is enough. Thank you in advance.
 

Shaz

Global Moderators
Global Mod
Joined
Mar 2, 2012
Messages
41,206
Reaction score
14,247
First Language
English
Primarily Uses
RMMV

I've moved this thread to RGSS Script Requests. Please be sure to post your threads in the correct forum next time. Thank you.

 

MobiusXVI

Game Maker
Veteran
Joined
Mar 20, 2013
Messages
387
Reaction score
94
First Language
English
Primarily Uses
I would recommend you check out Trihan's post in the Learning RGSS forum: Slip into Ruby. If you follow the how to make a bestiary section, that should give you a good idea of how to make a music test menu.

For the New Game+ features, technically you can do all that in-engine. You would reserve some switches/variables for tracking the ending completion, but the rest you just have to reset in order to restart the game. It would work something like this, after your game ends run an event:
- Set switches for the ending they got
- Show choices dialog: "do you want to start a new game?"
- If yes, then reset all non-game-ending switches/variables
- Move player to starting map/location
- (optional) reset player stats

Then you can have events set up in your world which trigger on the game ending switches. The one thing I'm not sure of it if there's an easy way to reset event self-switches, but everything else is doable.
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
32,107
Reaction score
7,996
First Language
German
Primarily Uses
RMMV
as said above, most of what you want can be done by RGSS scripts and you can follow the links on how to learn RGSS.
But there is one case where you should reconsider
-Add events to main game if certain endings have been acquired.

Creating events by script is difficult and not really needed.
It is MUCH easier to create the event in the editor as usual and only either
- condition them to a switch that will only be ON after those endings are available
- or create the event on an internal and unused map and only copy them to the current map if neccessary.
 

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
as said above, most of what you want can be done by RGSS scripts and you can follow the links on how to learn RGSS.
But there is one case where you should reconsider

- condition them to a switch that will only be ON after those endings are available
- or create the event on an internal and unused map and only copy them to the current map if neccessary.
By "Add events to main game if certain endings have been acquired.", I would think that would just be a variable check, and said variables get turned on at the beginning of the game if conditions are met in the system data. Writing the whole event via script was not what I had in mind at all.


I would recommend you check out Trihan's post in the Learning RGSS forum: Slip into Ruby. If you follow the how to make a bestiary section, that should give you a good idea of how to make a music test menu.

For the New Game+ features, technically you can do all that in-engine. You would reserve some switches/variables for tracking the ending completion, but the rest you just have to reset in order to restart the game. It would work something like this, after your game ends run an event:
- Set switches for the ending they got
- Show choices dialog: "do you want to start a new game?"
- If yes, then reset all non-game-ending switches/variables
- Move player to starting map/location
- (optional) reset player stats

Then you can have events set up in your world which trigger on the game ending switches. The one thing I'm not sure of it if there's an easy way to reset event self-switches, but everything else is doable.
What you're suggesting appears to be saving the data to the file and then just allowing the game to trigger a newgame+ from there. That's NOT what I'm after, and actually something I want to avoid. I want it to be that the player could return to the main menu (and will be forced to after clearing the game) and then the next time they start the game, it knows what endings have been acquired, and provides an additional option on the menu accordingly. I know this can be done, as I have seen an example: Corpse Party if Past End changes it's title screen if you've beaten the game, and that was made in RPG Maker XP.

Why do I want to avoid this? Simple. There's 16 endings in the game, and that method would require a player play through all variations just to get completion, if it were saved to a save file rather than a different file. (And no, it's not one of those meta games like Confess my Love that has a bunch of endings that are more or less just one playthrough of the game, it's a full-length game, better compared to Until Dawn in terms of ending structure) Basically, I want to make the process of getting all endings less of a drag if I can.

It appears to require creating an additional file, separate from the other save files. I need to know how to create that file within an event (which I presume requires some script call), write information to it, and read from the file. Checking that the file exists is simple enough with a FileTest, but past that, I am unsure. I have been attempting to reverse engineer the code from if Past End, but I haven't yet figured out much aside from how to test that a file exists, and how to put additional options on the main menu.
 

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
Here's some to code to get you started with:
Code:
module GlobalSave
  def self.save
    file = File.open('GlobalSave.rxdata', 'wb')
    Marshal.dump($game_switches.global_switches, file)
    file.close
    GlobalSave.clear_cache
  end
  
  def self.load
    return @@global_switch_data unless @@global_switch_data.nil?
    
    file = File.open('GlobalSave.rxdata', 'rb')
    @@global_switch_data = Marshal.load(file)
    file.close
    @@global_switch_data
  end
  
  def self.exist?
    File.exist?('GlobalSave.rxdata')
  end
  
  def self.clear_cache
    @@global_switch_data = nil
  end
end

module Graphics
  class << self
    alias clear_gs_cache_on_update update
    def update
      GlobalSave.clear_cache
      clear_gs_cache_on_update
    end
  end
end


class Game_Switches

  alias get_switch []
  def [](id)
    if id.between?(1, 16) && GlobalSave.exist?
      @data.slice!(0..16)
      @data.unshift(*GlobalSave.load)
    end
    get_switch(id)
  end
  
  alias set_switch []=
  def []=(id, val)
    set_switch(id, val)
    if id.between?(1, 16)
      GlobalSave.save
    end
  end
  
  def global_switches
    @data[16] ||= false
    @data[0..16]
  end

end
Currently, this sets switch IDs 1 to 16 as globally saved. It creates a new GlobalSave.rxdata file to store those 16 switches. Whenever any of those switches are requested, it opens the GlobalSave file to get its value. Likewise, whenever any of those switches change, it saves it to the GlobalSave file.

In its current state, it is extremely easy to "hack" the save file. Opening the file in a text editor gives you something like
Code:
..[.000000000000T0T0F
Doesn't take more than a couple brain cells to understand what you can do here.
 

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
Here's some to code to get you started with:
Code:
module GlobalSave
  def self.save
    file = File.open('GlobalSave.rxdata', 'wb')
    Marshal.dump($game_switches.global_switches, file)
    file.close
    GlobalSave.clear_cache
  end

  def self.load
    return @@global_switch_data unless @@global_switch_data.nil?
  
    file = File.open('GlobalSave.rxdata', 'rb')
    @@global_switch_data = Marshal.load(file)
    file.close
    @@global_switch_data
  end

  def self.exist?
    File.exist?('GlobalSave.rxdata')
  end

  def self.clear_cache
    @@global_switch_data = nil
  end
end

module Graphics
  class << self
    alias clear_gs_cache_on_update update
    def update
      GlobalSave.clear_cache
      clear_gs_cache_on_update
    end
  end
end


class Game_Switches

  alias get_switch []
  def [](id)
    if id.between?(1, 16) && GlobalSave.exist?
      @data.slice!(0..16)
      @data.unshift(*GlobalSave.load)
    end
    get_switch(id)
  end

  alias set_switch []=
  def []=(id, val)
    set_switch(id, val)
    if id.between?(1, 16)
      GlobalSave.save
    end
  end

  def global_switches
    @data[16] ||= false
    @data[0..16]
  end

end
Currently, this sets switch IDs 1 to 16 as globally saved. It creates a new GlobalSave.rxdata file to store those 16 switches. Whenever any of those switches are requested, it opens the GlobalSave file to get its value. Likewise, whenever any of those switches change, it saves it to the GlobalSave file.

In its current state, it is extremely easy to "hack" the save file. Opening the file in a text editor gives you something like
Code:
..[.000000000000T0T0F
Doesn't take more than a couple brain cells to understand what you can do here.
Sorry for the late response, I've begun to get busy with school so I've been slowing down a bit.

I've implemented the script, and I'm trying to test it by having a script call on a dummy object that goes "$set_switch[535] = true" (for context on the number, I decided to use ids 535-549 for the ending switches, and I updated the code accordingly. Currently that crashes the game, and I can tell that the fix is going to be blatantly simple to those who are used to the language. I am simply not that practiced with Ruby at the moment, so I need to ask how to properly call/request the script.

If it helps, here is the modified part of the code:
Code:
Line 42:
  if id.between?(534,550) && GlobalSave.exist?
Line 52:
  if id.between?(534, 550)
 

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
Code:
@data[0..16]
needs to be updated as well.
Would also help if you shared what the error code is next time.
 
Last edited:

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
Code:
@data[0..16]
needs to be updated as well.
Would also help if you shared what the error code is next time.
Updated that line. Now, as for the error:

-with $set_switch[535] = true
1611120721761.png
-with set_switch[535] = true #(no $)
1611120811743.png
 

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
You're not supposed to use anything from my script. You're supposed to use the event command for changing switches (or the set/get methods for $game_switches[ID], if you're doing that anywhere).
 

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
It's now working properly. Thank you.

Two more things I'd like to ask right now: I am working on implementing a Staff Room accessible from the main menu. I have technically implemented it (it loads the correct map), but there are issues:
-Unless I load a file prior, the game doesn't seem to load the player character properly and instantly crashes upon loading the map. If a file is loaded, it works properly, leading me to believe that it's using leftover character data from the previously loaded file in that circumstance.
-Aside from Global Variables, variables are immediately switched off after being turned on in the staff room for some reason. This is a major issue, as I intend to make the staff room where the player accesses bonus chapters of the game, and variables not working properly ... I shouldn't need to explain how that will prove an issue.

Also, the Global Variable Script appears to break the game when resetting the game via F12. Any idea how that can be fixed?

(Here is the code for the Staff Room command on the title screen specifically, as this is where the issue is occurring)
Code:
#--------------------------------------------------------------------------
  # * Command: Staff Room
  #--------------------------------------------------------------------------
  def command_staff_room
    # Play decision SE
    $game_system.se_play($data_system.decision_se)
    # Stop BGM
    Audio.bgm_stop
    # Reset frame count for measuring play time
    Graphics.frame_count = 0
    # Make each type of game object
    $game_temp          = Game_Temp.new
    $game_system        = Game_System.new
    $game_switches      = Game_Switches.new
    $game_variables     = Game_Variables.new
    $game_self_switches = Game_SelfSwitches.new
    $game_screen        = Game_Screen.new
    $game_actors        = Game_Actors.new
    $game_party         = Game_Party.new
    $game_troop         = Game_Troop.new
    $game_map           = Game_Map.new
    $game_player        = Game_Player.new
    # Set up initial party
    $game_party.setup_starting_members #This is the part that appears to be having issues.
    # Set up initial map position
    $game_map.setup(155) #This is the map id for the Staff Room. Can confirm this part works properly.
    # Move player to initial position
    $game_player.moveto(5, 6)
    # Refresh player
    $game_player.refresh
    # Run automatic change for BGM and BGS set with map
    $game_map.autoplay
    # Update map (run parallel process event)
    $game_map.update
    # Switch to map screen
    $scene = Scene_Map.new
  end
 
Last edited:

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
Try this revision of the script instead, because I'm assuming you probably didn't edit it enough to work for your needs (was trying to make it more of a learning exercise for you). Now it comes with a configuration to set up your range of switches.
Code:
RANGE_OF_SWITCHES = 535..549

module GlobalSave
  def self.save
    file = File.open('GlobalSave.rxdata', 'wb')
    Marshal.dump($game_switches.global_switches, file)
    file.close
    GlobalSave.clear_cache
  end
  
  def self.load
    return @@global_switch_data unless @@global_switch_data.nil?
    
    file = File.open('GlobalSave.rxdata', 'rb')
    @@global_switch_data = Marshal.load(file)
    file.close
    @@global_switch_data
  end
  
  def self.exist?
    File.exist?('GlobalSave.rxdata')
  end
  
  def self.clear_cache
    @@global_switch_data = nil
  end
end

module Graphics
  class << self
    alias clear_gs_cache_on_update update
    def update
      GlobalSave.clear_cache
      clear_gs_cache_on_update
    end
  end
end


class Game_Switches

  alias get_switch []
  def [](id)
    if id.between?(RANGE_OF_SWITCHES.first, RANGE_OF_SWITCHES.last) && GlobalSave.exist?
      @data.slice!(RANGE_OF_SWITCHES)
      @data.insert(RANGE_OF_SWITCHES.first, *GlobalSave.load)
    end
    get_switch(id)
  end
  
  alias set_switch []=
  def []=(id, val)
    set_switch(id, val)
    if id.between?(RANGE_OF_SWITCHES.first, RANGE_OF_SWITCHES.last)
      GlobalSave.save
    end
  end
  
  def global_switches
    @data[RANGE_OF_SWITCHES.last] ||= false
    @data[RANGE_OF_SWITCHES]
  end

end
Delete the GlobalSave.rxdata file as well before running the game. And if it still happens to give you errors, do share the error messages.
 

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
First up, I appreciate you attempting to give me a learning experience, and looking at the revisions of the code I can already say I am learning a lot about RPG Maker scripting. So thank you for that.

Also, first test of the new script, deleted the globaldata file and just restarted the game with F12 (while the game was running), got this error and a crash: 1611628889396.png

This is what's happening in that part of the code: 1611628926083.png

I'm guessing that the clear_cache doesn't function properly when the game is reset by hitting F12.

Second test, tried to create a globaldata file from beating the game, did work.

Third test, I can now get into the Staff Room without loading a gamesave first. (Not sure why as I didn't change anything in the Scene_Title yet, but alright.)

Fourth test, non-global switches now properly function in the staff room.

So yeah, currently the only remaining problem is that F12 resetting crashes the game.

Edit: Okay, actually something else is going wrong when I try to start one of the extra chapters, specifically at the point when the party members are supposed to be changed, so that is still a problem. However, the error pointed me to one of the partly-japanese scripts, so I feel that I would need to take that matter into a DM in order to be able to work on it properly.
 
Last edited:

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
F12 fix:
It's a known issue with RMXP where, instead of unloading all the scripts first, it just loads them in all again. Aliased methods will cause issues when that happens.
 

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
F12 fix:
It's a known issue with RMXP where, instead of unloading all the scripts first, it just loads them in all again. Aliased methods will cause issues when that happens.
Alright, that issue is solved now! Thank you.

I've also attempted to add something to the script to track global variables in addition to switches. Currently though, it causes an error when I try to load a file or start a new game, so I haven't been able to test if it "works without interfering with the rest of the code" yet.
Code:
#class Game_Variables
#  
#  alias get_variable []=
#  def [](id)
#    if id.between?(RANGE_OF_VARS.first, RANGE_OF_VARS.last) && GlobalSave.exist?
#      @data.slice!(RANGE_OF_VARS)
#      @data.insert(RANGE_OF_VARS.first, *GlobalSave.load)
#    end
#    get_variable(id)
#  end
#  
#  alias set_variable []=
#  def []=(id, val)
#    set_variable(id, val)
#    if id.between?(RANGE_OF_VARS.first, RANGE_OF_VARS.last)
#      GlobalSave.save
#    end
#  end
#
#  def global_variables
#    @data[RANGE_OF_VARS.last] ||= false
#    @data[RANGE_OF_VARS]
#  end
#end
And here's the error: 1611700729367.png

The line in question?
Code:
  alias get_variable []=
  def [](id)
    if id.between?(RANGE_OF_VARS.first, RANGE_OF_VARS.last) && GlobalSave.exist?
      @data.slice!(RANGE_OF_VARS)
      @data.insert(RANGE_OF_VARS.first, *GlobalSave.load)
    end
    get_variable(id) #This line right here
  end
I'm assuming there's supposed to be another parameter in get_variable, but I'm unsure what. Doesn't help that I haven't been able to find a directory for standard RPG Maker XP scripts yet ...
 

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
It's supposed to be
Code:
alias get_variable []
. I don't know why you did that.
 

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
It's supposed to be
Code:
alias get_variable []
. I don't know why you did that.
... typos. Also used set_switch as the base for that code initially, didn't notice the lack of a = on get_switch. Whoops.

And I can confirm that it is not creating the proper data, even if I tell it to create a new file called GlobalVar.rxdata specifically for the variables, no dice.

(this is a different script now)
Code:
RANGE_OF_VARS = 050..052

module GlobalVar
  def self.save
    file = File.open('SaveData/GlobalVar.rxdata', 'wb')
    Marshal.dump($game_variables.global_variables, file)
    file.close
    GlobalVar.clear_cache
  end
  
  def self.load
    return @@global_variable_data unless @@global_variable_data.nil?
    
    file = File.open('SaveData/GlobalVar.rxdata', 'rb')
    @@global_variable_data = Marshal.load(file)
    file.close
    @@global_variable_data
  end
  
  def self.exist?
    File.exist?('SaveData/GlobalVar.rxdata')
  end
  
  def self.clear_cache
    @@global_variable_data = nil
  end
end

#module Graphics
#  class << self
#    alias clear_gs_cache_on_update update
#    def update
#      GlobalVar.clear_cache
#      clear_gs_cache_on_update
#    end
#  end
#end


class Game_Variables
  
  alias get_variable []
  def [](id)
    if id.between?(RANGE_OF_VARS.first, RANGE_OF_VARS.last) && GlobalVar.exist?
      @data.slice!(RANGE_OF_VARS)
      @data.insert(RANGE_OF_VARS.first, *GlobalVar.load)
    end
    get_variable(id)
  end
  
  alias set_variable []=
  def []=(id, val)
    set_variable(id, val)
    if id.between?(RANGE_OF_VARS.first, RANGE_OF_VARS.last)
      GlobalVar.save
    end
  end

  def global_variables
    @data[RANGE_OF_VARS.last] ||= 0
    @data[RANGE_OF_VARS]
  end
end
 

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
Don't use leading zeroes. Just keep it 50..52
Code:
(050..052).each { |n| puts n }
#=>40
#=>41
#=>42
 
Last edited:

Zwataketa

Villager
Member
Joined
Nov 10, 2020
Messages
22
Reaction score
2
First Language
English
Primarily Uses
RMXP
Fixed that, but then came across this error when I attempted to change one of the global variables:
1611752166184.png
Code:
module GlobalVar
  def self.save
    file = File.open('SaveData/GlobalVar.rxdata', 'wb')
    Marshal.dump($game_variables.global_variables, file)
    file.close
    GlobalVar.clear_cache
  end
  
  def self.load
    return @@global_variable_data unless @@global_variable_data.nil? #This is the line with the error
    
    file = File.open('SaveData/GlobalVar.rxdata', 'rb')
    @@global_variable_data = Marshal.load(file)
    file.close
    @@global_variable_data
  end
  
  def self.exist?
    File.exist?('SaveData/GlobalVar.rxdata')
  end
  
  def self.clear_cache
    @@global_variable_data = nil
  end
end
 

Attachments

  • 1611752160060.png
    1611752160060.png
    3.6 KB · Views: 0

KK20

Just some XP Scripter
Veteran
Joined
Oct 11, 2018
Messages
347
Reaction score
130
First Language
English
Primarily Uses
RMXP
I figured we don't need the Graphics#update alias nor the clear_cache method:
Code:
module GlobalSave
  @@global_switch_data = nil
  
  def self.save
    @@global_switch_data = $game_switches.global_switches
    file = File.open('GlobalSave.rxdata', 'wb')
    Marshal.dump(@@global_switch_data, file)
    file.close
  end
  
  def self.load
    return @@global_switch_data unless @@global_switch_data.nil?
    
    file = File.open('GlobalSave.rxdata', 'rb')
    @@global_switch_data = Marshal.load(file)
    file.close
    @@global_switch_data
  end
  
  def self.exist?
    File.exist?('GlobalSave.rxdata')
  end
  
end
Also repurpose your module to look similar to this.
 

Latest Threads

Latest Profile Posts

Sigh...I can do everything I need for this game but make actual sprites and tile maps for it. Guess I'll look into hiring someone for that
Goes looking for assets, ends up creating memes. I have priorities?
i'm working on finishing an old game in vx ace (the first game i tried to make in vx ace), and it's making me realize how many things i've come to take for granted in mv (like the additional BCDE tile layer and the plugin manager).
It's ma birfday! Gonna chill and work on my project, editing some icons for my compass rn. Later It's pizza and a movie, maybe Blazing Saddles...
I really hope Google stadia/Amazon luna become successful household "consoles" in the future only because I could see it being 1000x easier to get RPG Maker and other indie games on their platforms & if so I PRAY they have gate keepers to keep half baked indie games out of the mix so they don't end up like steam/itch.io with 1000s of incomplete RM projects that continue to give our community a bad stigma.

Forum statistics

Threads
109,026
Messages
1,041,349
Members
141,497
Latest member
plugin_dude
Top