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.

Scripter's corner : Snippets, Classes, Tips and more

I guess, since I can hardly go "nuuuu they be stealin mah code" when I just edited poccil's.

Code:
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <windows.h>

#include <math.h>

#define EXPORTDLL __declspec(dllexport) //__stdcall

 

////////////////////////////////////////////////////////

 

typedef struct{

 DWORD flags;

 DWORD klass;

 void (*dmark)(void*);

 void (*dfree)(void*);

 double *data;//red is index 1, green is index 2, blue 3, alpha 4

} RGSSCOLOR;

 

typedef struct{

 DWORD unk1;

 DWORD unk2;

 BITMAPINFOHEADER *infoheader;

 RGBQUAD *firstRow;

 RGBQUAD *lastRow;

} RGSSBMINFO;

 

typedef struct{

 DWORD unk1;

 DWORD unk2;

 RGSSBMINFO *bminfo;

} BITMAPSTRUCT;

 

typedef struct{

 DWORD flags;

 DWORD klass;

 void (*dmark)(void*);

 void (*dfree)(void*);

 BITMAPSTRUCT *bm;

} RGSSBITMAP;

 

#define ASSERT(x)  if(!x){DebugOut("Failed: %s: %d",#x,__LINE__);}

 

////////////////////////////////////////////////////////

 

BOOL EXPORTDLL Bitmap_Recolor(

        long object, DWORD color1, DWORD color2){

    DWORD tmp=0;

    RGSSBMINFO *bitmap=((RGSSBITMAP*)(object<<1))->bm->bminfo;

    DWORD rowsize;

    DWORD width,height;

    LPBYTE row;

    byte blend[4];

    long xStart=0;

    long yStart=0;

    long x, y;

    int r1,g1,b1,a1; //Recolor to colors

    int r2,g2,b2,a2; //Recolor from colors

    int r3,g3,b3,a3; //Color of current pixel

    r1 = GetRValue(color1); g1 = GetGValue(color1); b1 = GetBValue(color1); a1 = color1>>24;

    r2 = GetRValue(color2); g2 = GetGValue(color2); b2 = GetBValue(color2); a2 = color2>>24;

    if(!bitmap)return FALSE;

    width=bitmap->infoheader->biWidth;

    height=bitmap->infoheader->biHeight;

    rowsize=width*4;

    if(width==xStart||height==yStart)return TRUE;

    row=bitmap->firstRow-yStart*rowsize+xStart*4;

    for (y=yStart; y<height; y++)

    {

        LPBYTE thisrow=row;

        for (x=xStart; x<width; x++)

        {

            r3=thisrow[0];

            g3=thisrow[1];

            b3=thisrow[2];

            a3=thisrow[3];

            if ((r2 == r3) && (g2 == g3) && (b2 == b3))// && (a2 == a3))

            {

                thisrow[0]=r1;

                thisrow[1]=g1;

                thisrow[2]=b1;

                thisrow[3]=a1;

            }

            thisrow+=4;

        }

        row-=rowsize;

    }

    return TRUE;

}

Also I messed up the original upload, I forgot to un-comment some lines I had removed for testing in the dll and got a few numbers backwards on the stuff in the Bitmap class. It's fixed now though.
 
Oh whoops, I didn't mean to. I don't look at the release board much, I just stay in script support .-.
Well, his script does something different, and then uses get_pixel and set_pixel to set the colors. That's actually the best type of place for using this dll/script since it's just a glorified, faster get/set.
 
Just when I added alpha transparency support to mine ^^ But yeah, it appears to be a more efficient way just telling from the code, but I'll stay with my version for own uses nevertheless... especially since I created it for icon remapping XD Also, it doesn't really do the same thing, as mine's layouted to work with palettes, while yours does individual colors.

You should know I link the above post in my thread, so please let me know if you don't want that, I'll take it out then.

Keep up the good work!
 
Along with the update of my Database Flag Reader script, I'll post this little snippet in here for string conversion into integers, floats, boolean outputs, arrays, hashes or just nil.

[rgss]  def self.decrypt_string(value)
    if value.to_i != 0 or value == '0'
      # integer and float
      value.include?('.') ? result = value.to_f : result = value.to_i
    elsif value == 'true'
      # boolean true
      result = true
    elsif value == 'false'
      # boolean false
      result = false
    elsif value.include?('[') and value.include?(']')
      # array
      result = []
      value.delete!('[ ]')
      array = value.split(',')
      for i in 0...array.size
        result = decrypt_string(array)
      end
    elsif value.include?('{') and value.include?('}')
      # hash
      result = {}
      value.delete!('{ }')
      hash = value.split(',')
      for i in 0...hash.size
        temp = hash.split('=>')
        result[temp[0]] = decrypt_string(temp[1])
      end
    elsif value == 'nil'
      # nil
      result = nil
    else
      # string
      result = value
    end
    return result
  end
[/rgss]
 
Nice, BlueScope. I suppose the only strangety with that is the uncertain data type which results, but that's the point isn't it? And I don't care what Firefox says, "strangety" is definitely a word!

I've got two modules that some of you might find interesting; they both deal with Win32API. The first is a Settings module, which reads the game.ini file and can read and write entries to it. It keeps a cache of the values as it reads them, and writes immediately whenever a setting is changed. The cache can be easily cleared as well:

[rgss]#===============================================================================
# ** Settings
#-------------------------------------------------------------------------------
#    References game.ini and caches and returns the relevant settings.
#===============================================================================
 
module Settings
  ReadINI = Win32API.new('kernel32', 'GetPrivateProfileString', 'PPPPLP', 'L')
  WriteINI = Win32API.new('kernel32', 'WritePrivateProfileString', 'PPPP', 'L')
  FileName = ".\\game.ini"
  @data = {}
  #-----------------------------------------------------------------------------
  # * Find cached value
  #-----------------------------------------------------------------------------
  def self.[](key)
    unless @data.has_key?(key)
      @data[key] = "\0" * 256
      ReadINI.call("Game", key, "", @data[key], 256, FileName)
      @data[key].delete!("\0")
    end
    return @data[key]
  end
  #-----------------------------------------------------------------------------
  # * Set cached value and write to the settings file
  #-----------------------------------------------------------------------------
  def self.[]=(key, value)
    @data[key] = value
    WriteINI.call("Game", key, value, FileName)
  end
  #-----------------------------------------------------------------------------
  # * Clears the cache so that external changes to the settings file can be read
  #-----------------------------------------------------------------------------
  def self.clear
    @data.clear
  end
end
[/rgss]

The second is a wrapper module for user32.dll GetSystemMetrics functions. It acts just like an initialized Win32API object (with its :call method) but I've mapped out all of the functions (up to 81). You can call it by something as simple as GSM.call(GSM::CXSCREEN) (that returns the width portion of your current screen resolution):

[rgss]#===============================================================================
# ** GSM
#-------------------------------------------------------------------------------
#    Wrapper for GetSystemMetrics which defines the constants it can return
#    For more complete descriptions, see Microsoft's website:
#    http://msdn.microsoft.com/en-us/library/ms724385(VS.85).aspx
#===============================================================================
 
module GSM
  CXSCREEN      = 0  # Width of the current master screen resolution
  CYSCREEN      = 1  # Height of the current master screen resolution
 
  CXVSCROLL     = 2  # Width of a vertical scroll bar
  CYHSCROLL     = 3  # Height of a horizontal scroll bar
 
  CYCAPTION     = 4  # Height of a caption area
 
  CXBORDER      = 5  # Width of a window border
  CYBORDER      = 6  # Height of a window border
 
  CXDLGFRAME    = 7
  CXFIXEDFRAME  = 7 # Width of non-resizable captioned window frame
  CYDLGFRAME    = 8
  CYFIXEDFRAME  = 8 # Height of non-resizable captioned window frame
 
  CYVTHUMB      = 9  # Height of a thumb button on vertical scrollbars
  CXHTHUMB      = 10 # Width of a thumb button on horizontal scrollbars
 
  CXICON        = 11 # Default width of an icon
  CYICON        = 12 # Default height of an icon
 
  CXCURSOR      = 13 # Width of a cursor
  CYCURSOR      = 14 # Height of a cursor
 
  CYMENU        = 15 # Height of a single-line menu bar
 
  CXFULLSCREEN  = 16 # Width of client rect for a full-screen window
  CYFULLSCREEN  = 17 # Height of client rect for a full-screen window
 
  CYKANJIWINDOW = 18 # Height of kanji window at bottom of screen, if there
 
  MOUSEPRESENT  = 19 # Non-zero if mouse is present; 0 if not
 
  CYVSCROLL     = 20 # Height of the arrow bitmap on vertical scrollbars
  CXHSCROLL     = 21 # Width of the arrow bitmap on horizontal scrollbars
 
  DEBUG         = 22 # Non-zero if debug User.exe is installed; 0 if not
  SWAPBUTTON    = 23 # Non-zero if mouse button values are swapped
 
  CXMIN         = 28 # Minimum width of a window
  CYMIN         = 29 # Minimum height of a window
 
  CXSIZE        = 30 # Width of a button in a window caption or title bar
  CYSIZE        = 31 # Height of a button in a window caption or title bar
 
  CXFRAME       = 32
  CXSIZEFRAME   = 32 # Width of the sizing border around a resizable window
  CYFRAME       = 33
  CYSIZEFRAME   = 33 # Height of the sizing border around a resizable window
 
  CXMINTRACK    = 34 # Minimum "tracking" width of a window
  CYMINTRACK    = 35 # Minimum "tracking" height of a window
 
  CXDOUBLECLK   = 36 # Width of rect which second click must be in for double
  CYDOUBLECLK   = 37 # Height of rect which second click must be in for double
 
  CXICONSPACING = 38 # Width of a grid cell for items in large icon view
  CYICONSPACING = 39 # Height of a grid cell for items in large icon view
 
  MENUDROPALIGNMENT = 40 # 0 if drop-down menus are left-aligned...
 
  PENWINDOWS    = 41 # Non-zero if Microsoft Windows for Pen computing
                     #  extensions are installed; 0 if not
 
  DBCSENABLED   = 42 # Non-zero if user32.dll supports DBCS; 0 if not
 
  CMOUSEBUTTONS = 43 # Number of available mouse buttons, or 0 for no mouse
 
  SECURE        = 44 # Always returns 0
 
  CXEDGE        = 45 # Width of a 3-D style border
  CYEDGE        = 46 # Height of a 3-D style border
 
  CXMINSPACING  = 47 # Width of a grid cell for minimized windows
  CYMINSPACING  = 48 # Height of a grid cell for minimized windows
 
  CXSMICON      = 49 # Recommended width of a small icon
  CYSMICON      = 50 # Recommended height of a small icon
 
  CYSMCAPTION   = 51 # Height of a small caption
  CXSMSIZE      = 52 # Width of small caption buttons
  CYSMSIZE      = 53 # Height of small caption buttons
  CXMENUSIZE    = 54 # Width of menu bar buttons
  CYMENUSIZE    = 55 # Height of menu bar buttons
 
  ARRANGE       = 56 # Flags that specify how system arranges minimized windows
  CXMINIMIZED   = 57 # Width of a minimized window
  CYMINIMIZED   = 58 # Height of a minimized window
 
  CXMAXTRACK    = 59 # Default maximum width of resizable windows
  CYMAXTRACK    = 60 # Default maximum height of resizable windows
  CXMAXIMIZED   = 61 # Default width of maximized top-level window
  CYMAXIMIZED   = 62 # Default height of maximized top-level window
 
  NETWORK       = 63 # The least significant bit is set if a network is
                     #  present; otherwise, it is cleared
 
  CLEANBOOT     = 67 # System boot type; 0:Normal, 1:Safe, 2:Safe w/networking
 
  CXDRAG        = 68
  CYDRAG        = 69 # Number of pixels mouse can move before initiating drag
 
  SHOWSOUNDS    = 70 # Non-zero if user requires visible output; 0 if not
 
  CXMENUCHECK   = 71 # Width of the default menu check-mark bitmap
  CYMENUCHECK   = 72 # Height of the default menu check-mark bitmap
 
  SLOWMACHINE   = 73 # Non-zero if system has a slow processor; 0 if not
                     #  No, seriously, that's what Microsoft said!
 
  MIDEASTENABLED = 74 # Non-zero if system can use Hebrew, Arabic languages
 
  MOUSEWHEELPRESENT = 75 # Nonzero mouse has vertical scroll wheel; 0 if not
 
  XVIRTUALSCREEN    = 76 # Coordinates of the left side of the virtual screen
  YVIRTUALSCREEN    = 77 # Coordinates of the top of the virtual screen
  CXVIRTUALSCREEN   = 78 # Virtual width of all screens put together
  CYVIRTUALSCREEN   = 79 # Virtual height of all screen put together
  CMONITORS         = 80 # Numbers of display monitors on a desktop
  SAMEDISPLAYFORMAT = 81 # Non-zero if all screen use same color depth...
 
  # The actual API call
  @api = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
  def self.call(i)
    return @api.call(i)
  end
end
[/rgss]

If anything in there is cryptic, don't blame me (maybe some of them are my fault for trying to shorten the description to fit on one line). Microsoft's descriptions are extremely specific to the point of technical gibberish.

Oh, heh, I'd check and see what Microsoft thinks about your processor:
[rgss]print GSM.call(GSM::SLOWMACHINE).to_s # Non-zero if system has a slow processor; 0 if not
                                      #  No, seriously, that's what Microsoft said!
[/rgss]
 
No problem BlueScope, I intended it to be used by anyone needing it. Get_pixel/set_pixel is useful but just too slow. :|

I came up with a couple new bitmap editing methods.
One takes an array of arrays of x-y locations (like [[0,0], [2,5], [8,3]]) and then changes all pixels in the bitmap at those locations to the given color.
The other... does kind of an image mask thing. Not sure what it's called exactly. Basically it takes a different bitmap as an argument, then modifies the original to be the same shape as the given one. For example, you could take an image larger than any battler you expect to encounter and put some kinda of effect in it, then have it conform to the shape of the battler it's currently displayed on top of. You could create something similar to the Pokemon stat buff/debuff effects with it.
(EDIT: Thought of another idea for it, you could create a bitmap, fill it with something like Color.new(40,40,40,192), and then fit it to a character and you have a shadow :o Just y scale its sprite a bit and maybe flip it upside down, then make it follow the character around.)

There's a few restrictions so far, the set array one is kinda slow if you use a large array because setting up the array in Ruby is slow, and the mask one needs some advanced stuff added to it (currently it always starts in the upper left and just leaves anything outside the size of the bitmap providing the shape)

The link to the dll:
http://www.bwdyeti.com/bitmap.rar

And the code to call it:
[rgss]class Bitmap
  def recolor_c(color_to,color_from)
    raise RGSSError.new("Disposed bitmap") if disposed?
    func=Win32API.new("bitmap.dll","Bitmap_Recolor","lll","")
    func.call(self.__id__,toColor(color_to),toColor(color_from))
  end
 
  def set_pixel_array_c(ary, color)
    raise RGSSError.new("Disposed bitmap") if disposed?
    return if ary.length == 0
    str = ary[0][0].to_s + ',' + ary[0][1].to_s
    for i in 1...ary.length
      str.concat('|' + ary[0].to_s + ',' + ary[1].to_s)
    end
    func = Win32API.new("bitmap.dll", "Set_Pixel_Array", "llpn", "")
    func.call(self.__id__, toColor(color), str, ary.length)
  end
 
  def fit_to_bitmap_c(other_bitmap)
    raise RGSSError.new("Disposed bitmap") if disposed?
    raise RGSSError.new("Disposed bitmap") if other_bitmap.disposed?
    func=Win32API.new("bitmap.dll","Fit_To_Bitmap","ll","")
    func.call(self.__id__, other_bitmap.__id__)
  end
 
  def toColor(c)
    r=c.red.to_i
    g=c.green.to_i
    b=c.blue.to_i
    a=c.alpha.to_i
    return b|(g<<8)|(r<<16)|(a<<24)
  end
end
[/rgss]

Feel free to mention if anything doesn't seem to work right, I'm new to releasing code for others to use so I might not check things as thoroughly as I should before posting.

If I make any more methods like this I'll probably make a topic for it, since it's not really snippets anymore .-.
 
Don't know if I ever posted this, but it's a default value for Enumerable classes. I just added support for Procs, which allow default value to be reliant on the referenced index or hash key.

[rgss]#===============================================================================
# ** Enumerable
#-------------------------------------------------------------------------------
#    Adds default values to Enumerable classes
#===============================================================================
 
module Enumerable
  attr_writer   :default
  def default(key = nil)
    return (key == nil or !@default.is_a?(Proc)) ? @default : @default.call(key)
  end
end
 
class Array
  #-----------------------------------------------------------------------------
  # * Adds default values, which replaces nil for all array values
  #-----------------------------------------------------------------------------
  alias old_get_value :[]
  def [](index)
    return default(index) if old_get_value(index).nil?
    return old_get_value(index)
  end
end
 
class Hash
  #-----------------------------------------------------------------------------
  # * Adds default values, which replaces nil for all array values
  #-----------------------------------------------------------------------------
  alias old_get_value :[]
  def [](key)
    return default(key) unless has_key?(key)
    return old_get_value(key)
  end
end
[/rgss]

All you have to do is call an array, $ar = [], and say $ar.default = 5 or whatever. Then, when you call $ar[1] it will return 5, even though that value wasn't defined. You can use Procs, too. If you say $ar.default = Proc.new {|index| index - 1} and you call $ar[1] it will return 0, $ar[7] will return 6...it could even be a simple Array wrapper for the Proc class if you never assign any values to the array.
 
With following snippet you can use Kernel#puts and the console for easier debugging because you can read the output while testing/playing the game and you don't have toclose the annoying MessageBox.
[ruby]Win32API.new("kernel32", "AllocConsole", "V", "L").call
$stdout.reopen("CONOUT$")
 
# example usage:
puts (6 + rand(9) / 7) & 0xFC
 
# what is debugging without tracing?
trace_var:)$scene){|v| puts "Current scene: #{v}"}
[/ruby]

Returns current line:
[ruby]__LINE__
[/ruby]

Current (script) section name:
[ruby]$RGSS_SCRIPTS.at( __FILE__.sub(/Section/, '').to_i ).at(1)
[/ruby]

Fix for Kernel#caller:
[ruby]def _caller(start = 1)
  stack = caller(start)
  stack.each{|e| e.gsub!(/Section(\d+)/){$RGSS_SCRIPTS.at($1.to_i).at(1)}}
  stack
end
[/ruby]

How to remove constants or classes:
[ruby]p Object.constants.include? "RPG"  # => true
 
Object.send :remove_const, :RPG
 
p Object.constants.include? "RPG"  # => false
[/ruby]


EDIT:

Get width and height of a PNG file:
[ruby]IO.read("example.png", 8, 16).unpack("NN")
[/ruby]

Downloads bits from the Internet and saves them to a file (supports HTTP and FTP):
[ruby]def download(url, filename)
  Win32API.new("urlmon", "URLDownloadToFile", "LPPLL", "L").call(0, url, filename, 0, 0).zero?
end
[/ruby]
 

MauMau

Member

[rgss] 
# Win32API.new("kernel32", "AllocConsole", "V", "L").call
# $stdout.reopen("CONOUT$")
 
[/rgss]
Hey, This is a very good one!
I don't understand how it works, but i did some modifications here:
First: This is the Kernel module
Second: Why only puts, i want gets too!
Third: IT WORKS!!!!

Thank you Cremno, I always wanted gets and puts, now i got it!

[rgss] 
#====================================================================
# Kernel
#====================================================================
 
module Kernel
  # AllocConsole function has no parameters, only one return
  AC = Win32API.new('kernel32', 'AllocConsole', '', 'l')
  #-------------------------------------------------------------------
  # - Prompt Window for gets and puts!
  #-------------------------------------------------------------------
 
  def debug
    AC.call
    $stdout.reopen('CONOUT$')
    $stdin.reopen('CONIN$')
    x=gets
    puts 'Debug...'
    puts '>>' << x
    trace_var:)$scene){|v| puts 'Scene >>> '<< v.to_s << Time.now.strftime("%H:%M:%S")}
  end
  debug if $DEBUG
end
 
[/rgss]

Sorry for any mistakes(English/Ruby/Win32API), MauMau
 
Well this snippet just adds 2 methods to make sure you can easily change your character / battler graphics and get them back at will via script call. Of course you still can do this by setting up some map event...

[rgss]class Game_Actor
  attr_accessor :eek:ld_graphic
  alias kyon_gma_init initialize
  def initialize(actor_id)
     @old_graphic = []
     kyon_gma_init(actor_id)
  end
 
  def change_graphic(index, graphic, value=0)
     actor = $game_actors[index+1] # Get actor
     if FileTest.exists?('Data/Actors.rxdata')
        @old_graphic[index] = [ @character_name, @battler_name, value ]
     else
        @old_graphic[index] = [ @character_name, @battler_name, @face_index ]
     end
     if actor != nil # Change graphic
        # XP - Pass Character Graphic, Hue, Battler Graphic, Hue values
        # VX -Pass Character Graphic, Index, Face Graphic, Index values
        graphic = $data_actors[graphic].character_name
        actor.set_graphic(graphic, value, graphic, value)
     end
     # Refresh player
     $game_player.refresh
     # Continue
     return true
  end
 
  def get_old_graphic(index)
     actor = $game_actors[index+1]
     if actor != nil
        # XP - Pass Character Graphic, Hue, Battler Graphic, Hue values
        # VX -Pass Character Graphic, Index, Face Graphic, Index values
        actor.set_graphic(@old_graphic[index][0], @old_graphic[index][2],
           @old_graphic[index][1], @old_graphic[index][2])
     end
     $game_player.refresh
     return true
  end
end
[/rgss]

Script Call:

$game_party.actors[0].change_graphic(0,2)

It'd transform Aluxes into a second Basil. To revert the change just call it like this...

$game_party.actors[0].get_old_graphic(0)

For VX use $game_party.members[0] instead.

The change_graphic method is a variant of the Interpreter command_322 one or more precisely it's a revised version. It doesn't just allow you to change the graphic, but it also lets you store the previous graphics names in an array temporarily.

The get_old_graphic method lets you reset the graphics at any time if deemed necessary.

BTW, it will work on both, XP and VX.

Never edit this line:

actor = $game_actors[index+1]

Or it won't work properly because the $game_actors index starts at 1 not 0 (it gets the info from $data_actors which also starts at 1).
 

MauMau

Member

Great Script!
You don't need those "return true" in the end of the method!
This is ruby, it will return the last thing anyway.
Test this:
[rgss] 
def test
 true
end
 
def test_return
 return true
end
 
p test == test_return
p test, test_return
 
[/rgss]
This works for everything in the end of a method, remember!

You can use ternary operator here, but will be a bigger line:
[rgss] 
 @old_graphic[index] = [ @character_name, @battler_name, FileTest.exists?('Data/Actors.rxdata') ? value : @face_index ]
 
[/rgss]

MauMau
 
A cool way to dynamically do stuff :p

You can call the method of an object like this

obj.my_method

but :p what if you want my_method is unknown, i mean, that you don't know at that time which method is going to be called...
You could write statements that would call the proper method with conditions and such ...

but you could also simply generate the method name :p

let's say you have a funny old text "rpg" , you know the kind of you play in a console, that asks you what you want to do :p
usually the player would either type an ID related to the action, or would type the action name, and a method would analyse that name or the ID, and would call the method for that action...

Well ruby allows you to generate method names:p which is pretty cool
so to call the method of an object by knowing its name, it's quite easy:

obj.method( the_method_name ).call(the_arguments)

but here "the_method_name" can't be a string it must be a symbol , so to do that you just convert the string to a symbol using the "to_sym" method :p

obj.method( the_method_name.to_sym).call(the_arguments)

and voilà! :p
There you just need to play with string methods to generate the proper method names, of course, be careful that the generate name must refer to an actual existing method ( else you'll have an error)

Example in my physics engine, i'm testing collision between 2 kind of shapes, box, and circles, so we have only 3 type of collisions > box/box, box/circle & circle/circle.

So i did 3 methods to test each of those cases :p and i have one method that call the right method for the 2 shapes given....

Code:
  def Shape.collide(s1,s2) # Meta Prog => Compute the method name from shapes classes

      return Shape.method( (s1.class.to_s+'Vs'+s2.class.to_s).to_sym ).call(s1,s2)

  end

 

  def Shape.CircleVsCircle(c1, c2)

 

  end

  def Shape.AABBVsAABB(a1, a2)

 

  end

  def Shape.AABBVsCircle(a, c)

 

  end

 

Look at line 7 :p ^^
I also did 3 "twin" methods with reverse names that call the 3 originals but with arguments.

It's a more useful & secure than ^^ eval and works better IMO.
 
hum the online reference says that send uses symbol as well :p

the main difference is ... that "method" returns a method object, that you can call later or store in a variable,
whereas send, directly call it.

But in either case, it's still something i find really smart :p
 
The debug thing is great. I found an API call to get the game window to come back to the foreground immediately once the debug window is created:
[rgss]    Win32API.new("user32", "SetForegroundWindow", "L", "L").call(hwnd)
[/rgss]
I've put the functions into a Debug module with special features:
1) Also writes to log file 'debug.log'.
2) Can :start and :stop debugging (Debug.start and Debug.stop opens/closes the console, respectively).
3) Debug.log_by_frame can be called every frame, without flooding the console with eternal messages (only prints message every one second).
[rgss]#===============================================================================
# ** Debug
#-------------------------------------------------------------------------------
#    Provides a console window to log debugging messages
#===============================================================================
 
module Debug
  @active = false
  @file = File.open('debug.log', File::CREAT|File::APPEND|File::WRONLY)
  #-----------------------------------------------------------------------------
  # * Open a console window for debug output
  #-----------------------------------------------------------------------------
  def self.start
    @active = true
    return unless self.active
    # Open console window and select it for :puts
    Win32API.new("kernel32", "AllocConsole", "V", "L").call
    $stdout.reopen("CONOUT$")
    # Bring the game window back to the front
    Win32API.new("user32", "SetForegroundWindow", "L", "L").call(hwnd)
    # Write log headers
    self.log("========================================================")
    self.log(Time.now)
    self.log("--------------------------------------------------------")
  end
  #-----------------------------------------------------------------------------
  # * Stop debugging
  #-----------------------------------------------------------------------------
  def self.stop
    Win32API.new("kernel32", "FreeConsole", "", "L").call
    @active = false
  end
  #-----------------------------------------------------------------------------
  # * Stop debugging
  #-----------------------------------------------------------------------------
  def self.active
    return @active #and $DEBUG
  end
  #-----------------------------------------------------------------------------
  # * Write to console
  #-----------------------------------------------------------------------------
  def self.log(string)
    puts string if self.active
    @file.print string.to_s + "\n"
  end
  #-----------------------------------------------------------------------------
  # * Write to console; not done every frame
  #-----------------------------------------------------------------------------
  def self.log_by_frame(string)
    self.log(string) if Graphics.frame_count % Graphics.frame_rate == 0
  end
end
[/rgss]
(I commented out $DEBUG because for whatever reason, probably because I'm running RMXP using RGSS202E. $TEST doesn't seem to work either)
 
$TEST doesn't work either. Perhaps RMXP tries to set $DEBUG but the game.exe prevents it, expecting RMVX to set $TEST even though I'm not loading it from RMVX.
 

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