Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

MACL - Method and Class Library 2.3

If you are talking about adding methods and such to the macl, I was working on something that did this, but my php skills are horrible (was nothing more than directory/file reading, no Mysql). Once I learn some mysql, I plan to make something where people can add methods/classes/modules to the MACL and someone can approve the modification and it auto-updates the MACL. Users can download the current MACL into a single text file. This prevents taking such a great deal of my time to update the MACL. Hopefully by next release I will have enough MySQL experience where I can do such a thing.

This, combined with the Compiler I am still working on should save a lot of time.

I am hoping to have the new MACL by friday. I am merging the Keyboard and Mouse module and adding them to the Input module (Still keeping the Keyboard/Mouse Module in the MACL for scripts that require it). I am adding a lot of new modules/systems as well.
 

e

Sponsor

No, I was thinking more about a "build your own MACL" script, which would allow people to select diverse modules and it'd generate their MACL.rb or MACL.rxdata file with only the selected scripts and nothing else.
 
That actually wouldn't be too hard to generate, especially since it will basically require files much like the compiler. The difference is the compiler just does that automatically, adding parts scripts require. I'll try to finish at least a demo of the compiler by tomorrow so you can see it in action. But I like the idea of the build your own MACL as well. It wouldn't take much scene work to make the addition.
 
Why not both? XD I am not sure how you plan on doing it, but I plan on dividing directories for each part

- Ruby
--Higher Classes
---Object
----subclasses.txt
---Module
----attr_sec_accessor.txt
----attr_sec_reader.txt
etc.

As well as adding something so when you include something like attr_sec_accessor which requires attr_sec_reader, it automatically adds that to the include list.
 
I don't know WtF I was talking about the other night, with overwritting SDK check_reqs method to do both, but each MACL section should be SDK logged.

Code:
if Object.const_defined?(:SDK)
  SDK.log('MACL::RGSS.Whatever', 'MACL Authors', 2.4, '06-06-06')
end

MACL::Loaded << 'RGSS.Whatever'

Would you be able to put the Plane_ScrollStates system into the MACL, and make it independant from the way you did it for the Default Menu/Battle in your test bed? That script is pretty bad ass, I want to be able to draw a scroll_state anywhere. This, I had attempted to do, but I can't seem to manip the drawing coord to match where normal draw_actor_states would wind up no matter what I change it to. I wanted to be able to use it independantly for my CMS, but its really not liking me.

Code:
#===============================================================================
# ~** Window Scroll States **~
#-------------------------------------------------------------------------------
# Written by  : Kain Nobel (originated from SephirothSpawn)
# Version     : 0.0
# Last Update : 09.08.2008
#-------------------------------------------------------------------------------
# * Description :
#
#   This script allows you to use Plane_ScrollStatus in any window with the
#   draw_actor_state() method, because it is defined in Window_Base.
#===============================================================================
#-------------------------------------------------------------------------------
# * SDK Log
#-------------------------------------------------------------------------------
SDK.log('Window.ScrollStates', 'Kain Nobel', 0.0, '09.08.2008')
SDK.disable('Window.ScrollStates')
#-------------------------------------------------------------------------------
# * SDK Enabled Log - BEGIN
#-------------------------------------------------------------------------------
if SDK.enabled?('Window.ScrollStates') && defined?(MACL) && MACL.is_a?(Module)
#===============================================================================
# ** Plane_ScrollStatus
#-------------------------------------------------------------------------------
#   This is an object scrolls the status display seamlessly.
#===============================================================================
class Plane_ScrollStatus < Plane
  #--------------------------------------------------------------------------
  # * Show Icons When Avialable
  #--------------------------------------------------------------------------
  Show_Icons = true
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :actor
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(actor_index, x, y, w, h, z = 105)
    v = Viewport.new(x, y, w, h)
    v.z = z
    super(v)
    if actor_index.is_a?(Numeric) ; @actor = $game_party.actors[actor_index]
    else                          ; @actor = actor_index
    end
    update
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    unless @states == @actor.states
      @states = @actor.states.dup
      unless self.bitmap.nil?
        self.bitmap.dispose
        self.bitmap = nil
      end
      s_names, i_names = [], []
      for i in @states
        if Show_Icons && $data_states[i].icon != nil
          s_names << nil
          i_names << $data_states[i].icon_name
          next
        end
        s_names << $data_states[i].name
      end
       if s_names.empty?
        if Show_Icons && RPG::State.normal_icon != nil
          s_names << nil
          i_names << RPG::State::Normal_Icon
        else
          s_names << 'Normal'
        end
      end
      has_icons = i_names.size > 0
      string = Show_Icons && has_icons ? '' : '['
      for s in s_names
        if s.nil?
          string += " [#{i_names.shift}]"
          next
        end
        string += " #{s}"
      end
      string += ' ]' unless Show_Icons && has_icons
      if Show_Icons && has_icons
        text, icons = Bitmap.string_to_text_icons(string)
        ox = Bitmap.icon_text_sizes(text, icons)[3]
      else ; ox = Bitmap.text_size(string).width
      end
      bitmap = Bitmap.new(ox + self.viewport.rect.width, 32)
      if Show_Icons && has_icons
        bitmap.draw_icon_text(0, 0, ox, 32, string)
      else
        bitmap.draw_text(0, 0, ox, 32, string)
      end
      self.bitmap = bitmap
    end
    self.ox += 1
  end
end
#===============================================================================
# ** Window_Base
#-------------------------------------------------------------------------------
#   This superclasses' normal methods have been enhanced to handle the Scroll
# Status display.
#===============================================================================
class Window_Base < Window
  #-----------------------------------------------------------------------------
  # * Alias Listings
  #-----------------------------------------------------------------------------
  alias_method :scroll_states_window_base_update,   :update
  alias_method :scroll_states_window_base_dispose,  :dispose
  alias_method :scroll_states_draw_actor_state,     :draw_actor_state
  #-----------------------------------------------------------------------------
  # * Update
  #-----------------------------------------------------------------------------
  def update
    unless @scroll_states.nil?
      @scroll_states.each {|state| state.update}
    end
    scroll_states_window_base_update
  end
  #-----------------------------------------------------------------------------
  # * Dispose
  #-----------------------------------------------------------------------------
  def dispose
    unless @scroll_states.nil?
      @scroll_states.each {|state| state.dispose}
    end
    scroll_states_window_base_dispose
  end
  #-----------------------------------------------------------------------------
  # * Draw Actor State
  #-----------------------------------------------------------------------------
  def draw_actor_state(actor, x, y, width = 128, height = 32, z = 105)
    if defined?(Plane_ScrollStatus)
      @scroll_states = []
      @scroll_states << Plane_ScrollStatus.new(actor, x, y, width, height, z)
    else ; scroll_states_draw_actor_state(actor, x, y)
    end
  end
end
#-------------------------------------------------------------------------------
# * SDK Enabled Test - END
#-------------------------------------------------------------------------------
end
 
I suppose I could add the scroll status thing.

I don't know about the SDK logging. As I said above, you can just use:
Code:
if MACL.loaded('Part')
Logging it just seems rather redundant.

Tip: When you modify someone's work, put their name as the author, your name as the modifier. ;)
 
That API module is rather eloquent, as I've come to expect from you Seph.  Good job!

I was wondering, about having a Data module instead of $data_ variables (it's probably a stupid idea).  Does anybody know what the Data class is?  Apparently it's already defined in RGSS, as I get a "Data is not a module" error when writing "module Data".
 
Thank you.

Code:
p Object.constants.sort

class Data
  p self.constants, self.private_methods - Object.private_methods, self.public_methods - Object.public_methods
end

I tested this above all the other scripts. Apparently the last Data does exist, but has no constants, private_methods or public methods (I removed the methods from the object class and got an empty array).

I have no idea what this class is for.


What did you mean make $data_classes into a module?

Also, check this out if you haven't seen it:
Code:
#==============================================================================
# ** Modules.Game_Data (1.0)                                  By SephirothSpawn
#------------------------------------------------------------------------------
# * Description :
#
#   This modules lets you add new $game_data objects to your game with a simple
#   call script within your script.
#------------------------------------------------------------------------------
# * Syntax :
#
#   Adding new $game_data object
#    - Game_Data.add_game_data('variable_name', 'Class_Name')
#
#   Example : Adding new Game_Database to your $game datas.
#
#    - Game_Data.add_game_data('$game_database', 'Game_Database')
#==============================================================================

MACL::Loaded << 'Modules.Game_Data'

#==============================================================================
# ** Game_Data
#==============================================================================

module Game_Data
  #--------------------------------------------------------------------------
  # * Instance Variable Setup
  #--------------------------------------------------------------------------
  @additions = []
  @variable_names = []
  #--------------------------------------------------------------------------
  # * Additions
  #--------------------------------------------------------------------------
  def self.additions
    return @additions
  end
  #--------------------------------------------------------------------------
  # * Add Game Data
  #--------------------------------------------------------------------------
  def self.add_game_data(global_variable_name, game_object_class)
    # If Variable Name Used
    if @variable_names.include?(global_variable_name)
      # Print Error
      p global_variable_name + ' already used. Please use a different ' +
        'variable name.'
      return
    end
    # Add Addition
    @additions << [global_variable_name, game_object_class]
  end
end

#==============================================================================
# ** Scene_Title
#==============================================================================

class Scene_Title
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :seph_macladdgamedata_scnttl_cng, :command_new_game
  #--------------------------------------------------------------------------
  # * Command: New Game
  #--------------------------------------------------------------------------
  def command_new_game
    # Original Command: New Game
    seph_macladdgamedata_scnttl_cng
    # Pass Through Game Data List
    Game_Data.additions.each {|vg| eval "#{vg[0]} = #{vg[1]}.new"}
  end
end

#==============================================================================
# ** Scene_Save
#==============================================================================

class Scene_Save
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :seph_macladdgamedata_scnsv_wsd, :write_save_data
  #--------------------------------------------------------------------------
  # * Write Save Data
  #--------------------------------------------------------------------------
  def write_save_data(file)
    # Original Write Save Data
    seph_macladdgamedata_scnsv_wsd(file)
    # Pass Through Game Data List
    Game_Data.additions.each {|vg| eval "Marshal.dump(#{vg[0]}, file)"}
  end
end

#==============================================================================
# ** Scene_Load
#==============================================================================

class Scene_Load
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :seph_macladdgamedata_scnld_rsd, :read_save_data
  #--------------------------------------------------------------------------
  # * Read Save Data
  #--------------------------------------------------------------------------
  def read_save_data(file)
    # Original Read Save Data
    seph_macladdgamedata_scnld_rsd(file)
    # Pass Through Game Data List
    Game_Data.additions.each {|vg| eval "#{vg[0]} = Marshal.load(file)"}
  end
end

This is actually in the current MACL, just not sure if anyone has seen it (and since we are on the discussion of data).

No more aliasing Scene_Title, Scene_Save and Scene_Load, just a simple single line code and it does it all for us.

Although I am going to modify this so:

In Scene_Title, some game objects will be created before the original command_new_game, others after. They will also check for a ":setup" method and run it if the method is defined.

Scene_Save, data saved before or after original call.

Scene_Load, data loaded before or after original call. It will also check for a ":load" method here and call it if it is found. Might be overkill, but I want to make it completely possible for anyone to add a new game object with only 1 line of code.
 

e

Sponsor

Having a Data module would be pretty much useless and would only add overhead whenever using the global variables. I mean...they're global anyway!
 
I kinda wish they would have thrown all globals into a single $game class.

Code:
class Game
  def add_object(class_name)
    eval "attr_reader :class_name.downcase;"
    eval "@#{class_name.downcase} = class_name.new"
  end
end

Making all Game classes just sub-classes of this would have been a great idea.
Code:
class Game
  class Temp
  end
  class Map
  end
end

I would have thrown this into the SDK/MACL a long time ago and rewrote all of it, but it just would have been too many script problems. :(

But I will rewrite the game_data module to be something like this, and just construct a single game variable. What etheon said reminded me of wanting to do this a year ago but didn't want to piss everyone off. I guess in the MACL, we can at least use this vs. making new game objects.

Actually this is going in the SDK (too). At least a better version of this anyways. If you have anything you want to add, now is the time.
 

e

Sponsor

I don't really have anything I want to add. If it were up to me, the WHOLE thing would be re-written :p
 
I am all up for a project or re-writing everything while keeping to the main layout as much as possible. Although it wouldn't do much good outside having a library for script users. We could create an entire project remaking a lot of the RGSS and include a lot addons. Just wouldn't work for any scripts not designed for the system. RMXP - Scripters Edition. lol
 

e

Sponsor

Well, we could rewrite the whole thing whilst keeping in mind to build light interfaces, or façades, with would allow perfect and seamless integration of (most) old scripts.
 
Ok. Let's do it. Open invitation to any scripter who has ever wanted to re-write the RMXP script library. I am having a private forum made so we can develop and discuss this (so we aren't hijacking this thread anymore).

The forum will be named RMXP - Scripter's Edition (we can change the name, just making it that for now) and the password will be enterbrainless (unless we need a different password). I'll update this post with precise details when the forum is actually made.
 

e

Sponsor

I'm in! Once you get the forum up, I suggest we start drafting on how we'll do this; more specifically :

1) Source Control? (SVN, CVS, etc.)
2) RGSS Re-design : what do we keep, what do we add, what do we modify, what do we throw away
3) Facades : make a draft of the needed facades (although I suppose step 2 has to be finished first)
 
Alright, last time, this is all my personal methods, even if I posted them previously, I'm posting them again because things change and theres stuff I caught that didn't work right in my past methods. I've re-written everything in here and tested EACH method 12x each in the past 3 days, so if I missed anything this time around with these re-writes I should be shot

Code:
#===============================================================================
# ** Ruby.Numeric.strings
#-------------------------------------------------------------------------------
#   Created some additional methods for the Numeric class, which is the parent
# class to all number-related classes. All of these methods deal with turning
# a number into some kind of formatted string form.
#
# Method List
# -----------
#   format_s
#   precise_s
#   percent_s
#   currency_s
#
#===============================================================================
#-------------------------------------------------------------------------------
# * SDK Log
#-------------------------------------------------------------------------------
if Object.const_defined?(:SDK)
  SDK.log('MACL::Ruby.Numeric.strings', 'Kain Nobel', 2.0, '09.28.2008')
end
#-------------------------------------------------------------------------------
# * MACL Loading
#-------------------------------------------------------------------------------
MACL::Loaded << "Ruby.Numeric.strings"
#===============================================================================
# ** Numeric
#===============================================================================

class Numeric < Object
  #-----------------------------------------------------------------------------
  # * Name      : Format String
  #   Info      : Returns formatted string (exp; 1234.56 => "1,234.56")
  #   Author    : Kain Nobel
  #   Call Info : Float true will return float, false returns no floating value
  #-----------------------------------------------------------------------------
  def format_s(float = true)
    begin
      parts = self.to_s.split('.')
      parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
      return parts.length == 2 && float ? parts[0]+"."+parts[1] : parts[0]
    rescue
      return self
    end
  end
  #-----------------------------------------------------------------------------
  # * Name      : Precise
  #   Info      : Returns number to a precise ammount
  #   Author    : Kain Nobel
  #   Call Info : Digits if positive shows this many float digits
  #               Digits if negative rounds integer back this many digits
  #-----------------------------------------------------------------------------
  def precise_s(digits = 2)
    return "%01.#{digits}f"%((Float(self)*(10**digits)).round.to_f/10**digits)
  end
  #-----------------------------------------------------------------------------
  # * Name      : Percent
  #   Info      : Return number as a percent string
  #               (Example: (100 / 8.0).percent #=> "12.5 %")
  #   Author    : Kain Nobel
  #   Call Info : Max is what the percent is comparing to
  #               Tolerence is the ammount of float to show (Default 0)
  #-----------------------------------------------------------------------------
  def percent_s(tolerence = 0, format = false)
    begin
      return format ? self.format_s+"%" : self.to_s+"%"
    rescue
      return self
    end
  end
  #-----------------------------------------------------------------------------
  # * Name      : Currency
  #   Info      : Returns currency string (exp; "$1,234.56")
  #   Author    : Kain Nobel
  #   Call Info : Sign is the currency symbol, for instance "$" or "Yen" or w/e
  #               Tail true sign is pinned to end, false sign pinned to start
  #-----------------------------------------------------------------------------
  def currency(sign = nil, tail = false)
    sign = "$" if !sign.is_a?(String)
    tail = self.to_i.zero? || tail
    begin
      if tail ; return (self.precise_s(2).to_f).format_s+" "+sign
      else    ; return sign+" "+(self.precise_s(2).to_f).format_s
      end
    rescue
      return sign+" "+self.to_s
    end
  end
end

Code:
#===============================================================================
# ** Game_Map
#-------------------------------------------------------------------------------
# Public Instance Variables
# -------------------------
# @map_infos
# @map_name
# @parent_id
# @parent_name
#
# Methods List
# ------------
#
# this_event
# event_count
# map_count
# map_name
# parent_id
# parent_name
# exists?
#===============================================================================
#-------------------------------------------------------------------------------
# * SDK Log
#-------------------------------------------------------------------------------
if Object.const_defined?(:SDK)
  SDK.log('MACL::RGSS.Map', 'MACL Authors', 2.0, '09.28.2008')
end
#-------------------------------------------------------------------------------
# * MACL Loading
#-------------------------------------------------------------------------------
MACL::Loaded << 'RGSS.Map'
#===============================================================================
# ** Game_Map
#-------------------------------------------------------------------------------
#   Added a library of query methods for retrieving information such as event
# count and obtaining information from MapInfos.rxdata
#===============================================================================
class Game_Map
  #-----------------------------------------------------------------------------
  # * Public Instance Variables
  #-----------------------------------------------------------------------------
  attr_reader :map_infos
  #-----------------------------------------------------------------------------
  # * Alias Listings
  #-----------------------------------------------------------------------------
  alias_method :kn_MACL_game_map_setup, :setup
  #-----------------------------------------------------------------------------
  # * Setup
  #-----------------------------------------------------------------------------
  def setup(map_id)
    kn_MACL_game_map_setup(map_id)
    @map_infos ||= load_data("Data/MapInfos.rxdata")
  end
  #-----------------------------------------------------------------------------
  # * Name      : This Event
  #   Info      : Finds the first event directly in front of $game_player
  #   Author    : Kain Nobel
  #   Call Info : None, returns event here or event in front
  #-----------------------------------------------------------------------------
  def this_event
    x, y, d = $game_player.x, $game_player.y, $game_player.direction
    new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
    new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
    for event in @events.values
      return event.id if event.x == x     && event.y == y
      return event.id if event.x == new_x && event.y == new_y
    end
  end
  #-----------------------------------------------------------------------------
  # * Name      : Event Count
  #   Info      : Simply counts how many events are on the $game_map
  #   Author    : Kain Nobel
  #   Call Info : None, returns number of events on map
  #-----------------------------------------------------------------------------
  def event_count
    return @events.empty? ? 0 : @events.size
  end
  #-----------------------------------------------------------------------------
  # * Name      : Exists?
  #   Info      : Tests to see if Map exists
  #   Author    : Kain Nobel
  #   Call Info : Map ID is the Map in question
  #-----------------------------------------------------------------------------
  def exists?(map_id)
    return FileTest.exist?(sprintf("Data/Map%03d.rxdata", map_id))
  end
  #-----------------------------------------------------------------------------
  # * Name      : Map Count
  #   Info      : Returns number of valid Map filenames
  #   Author    : Kain Nobel
  #   Call Info : None, returns number of maps in project folder
  #-----------------------------------------------------------------------------
  def map_count
    return @map_infos.keys.size
  end
  #-----------------------------------------------------------------------------
  # * Name      : Map Name
  #   Info      : Sends name of the map in question to a string
  #   Author    : Kain Nobel
  #   Call Info : Map ID (Optional) returns specified Map ID's name
  #-----------------------------------------------------------------------------
  def map_name(map_id = @map_id)
    return @map_infos[map_id].name
  end
  #-----------------------------------------------------------------------------
  # * Name      : Parent ID
  #   Info      : Returns ID of parent map
  #   Author    : Kain Nobel
  #   Call Info : Map ID (Optional) returns specified Map ID's parent Map ID
  #-----------------------------------------------------------------------------
  def parent_id(map_id = @map_id)
    begin  ; return @map_infos[map_id].parent_id
    rescue ; return 0
    end
  end
  #-----------------------------------------------------------------------------
  # * Name      : Parent Name
  #   Info      : Sends name of the parent map in question to a string
  #   Author    : Kain Nobel
  #   Call Info : Map ID (Optional) returns specified Map ID's parent's name
  #-----------------------------------------------------------------------------
  def parent_name
    return map_name(parent_id)
  end
end

I've got a bunch of stuff in my CMS that could probably be used universally too. For instance, this rescue call for the Bitmap class.

Code:
#===============================================================================
# ** Bitmap
#-------------------------------------------------------------------------------
#   Aliased initialize method, to rescue 32 x 32 if origional args are too small
#===============================================================================
class Bitmap
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :cms_bitmap_initialize, :initialize
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(*args)
    begin   ; cms_bitmap_initialize(*args)
    rescue  ; cms_bitmap_initialize(32, 32)
    end
  end
end

I also have an embedded facesets system too that I wrote, that could be used universally. Give me 'til tomorrow night and I'll unnest it from my CMS and re-write it
 
The Data thing was just having this:

module Data # has to be class Data for no apparent reason
  Actors = load_data "Data\Actors.rxdata"
  Animations = load_data "Data\Animations.rxdata"
  [..]
end

I don't know, it's probably a really stupid idea.  I could be very much in on this re-writing RMXP thing though.  I think it would be nice to take a fresh Ruby base and code our own version of RGSS instead, using C++ or something and keeping it open source so it's possible to change stuff like the embedded classes (Tilemap, Input, Viewport...) and of course make it more flexible.  At that point, though, we wouldn't really be working with RMXP anymore, we'd probably be working on a newer, better maker.
 
That's not too of a bad idea with the Data module. I prefer the constants to global variables. We could definitely do that (or something similar) in the project-rewrite or whatever. We can re-write whatever aspects we want, but I am scared of us saying "Let's make a new engine" because every time someone says that, they usually disappear and never see any results or see only a few. I have no problem if we do go that route, but I want to have a finished result vs. hype.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top