HiddenChest RGSS Player Executable
One Day Tepe Wrote:Still, there is a problem with the SDK, specifically with overriding methods via super functions instead of aliasing.

That's incredibly weird indeed! Shocked
I can only wonder what kind of methods or variables they were expecting to find in the parent classes by calling the super method. Are you sure that's not specific to certain classes? Happy with a sweat I mean, like sprites or windows.
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9

Maranatha!

The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.

[Image: SP1-Scripter.png]
[Image: SP1-Writer.png]
[Image: SP1-Poet.png]
[Image: SP1-PixelArtist.png]
[Image: SP1-Reporter.png]

My Original Stories (available in English and Spanish)

List of Compiled Binary Executables I have published...
HiddenChest & Roole

Give me a free copy of your completed game if you include at least 3 of my scripts! Laughing + Tongue sticking out

Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Reply }
(12-11-2024, 01:30 AM)kyonides Wrote:
One Day Tepe Wrote:Still, there is a problem with the SDK, specifically with overriding methods via super functions instead of aliasing.

That's incredibly weird indeed! Shocked
I can only wonder what kind of methods or variables they were expecting to find in the parent classes by calling the super method. Are you sure that's not specific to certain classes? Happy with a sweat I mean, like sprites or windows.

Actually, here's an example:
Code:
#==============================================================================
# ** Window_Base
#------------------------------------------------------------------------------
#  This class is for all in-game windows.
#==============================================================================

class Window_Bess < Window
  #--------------------------------------------------------------------------
  # * Object Initialization
  #    x      : window x-coordinate
  #    y      : window y-coordinate
  #    width  : window width
  #    height : window height
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super()
    @windowskin_name = $game_system.windowskin_name
    self.windowskin = RPG::Cache.windowskin(@windowskin_name)
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.z = 100
  end
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  def dispose
    # Dispose if window contents bit map is set
    if self.contents != nil
      self.contents.dispose
    end
    super
  end
  #--------------------------------------------------------------------------
  # * Get Text Color
  #    n : text color number (0-7)
  #--------------------------------------------------------------------------
  def text_color(n)
    case n
    when 0
      return Color.new(255, 255, 255, 255)
    when 1
      return Color.new(128, 128, 255, 255)
    when 2
      return Color.new(255, 128, 128, 255)
    when 3
      return Color.new(128, 255, 128, 255)
    when 4
      return Color.new(128, 255, 255, 255)
    when 5
      return Color.new(255, 128, 255, 255)
    when 6
      return Color.new(255, 255, 128, 255)
    when 7
      return Color.new(192, 192, 192, 255)
    else
      normal_color
    end
  end
  #--------------------------------------------------------------------------
  # * Get Normal Text Color
  #--------------------------------------------------------------------------
  def normal_color
    return Color.new(255, 255, 255, 255)
  end
  #--------------------------------------------------------------------------
  # * Get Disabled Text Color
  #--------------------------------------------------------------------------
  def disabled_color
    return Color.new(255, 255, 255, 128)
  end
  #--------------------------------------------------------------------------
  # * Get System Text Color
  #--------------------------------------------------------------------------
  def system_color
    return Color.new(192, 224, 255, 255)
  end
  #--------------------------------------------------------------------------
  # * Get Crisis Text Color
  #--------------------------------------------------------------------------
  def crisis_color
    return Color.new(255, 255, 64, 255)
  end
  #--------------------------------------------------------------------------
  # * Get Knockout Text Color
  #--------------------------------------------------------------------------
  def knockout_color
    return Color.new(255, 64, 0)
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    # Reset if windowskin was changed
    if $game_system.windowskin_name != @windowskin_name
      @windowskin_name = $game_system.windowskin_name
      self.windowskin = RPG::Cache.windowskin(@windowskin_name)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Graphic
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_actor_graphic(actor, x, y)
    bitmap = RPG::Cache.character(actor.character_name, actor.character_hue)
    cw = bitmap.width / 4
    ch = bitmap.height / 4
    src_rect = Rect.new(0, 0, cw, ch)
    self.contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
  end
  #--------------------------------------------------------------------------
  # * Draw Name
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_actor_name(actor, x, y)
    self.contents.font.color = normal_color
    self.contents.draw_text(x, y, 120, 32, actor.name)
  end
  #--------------------------------------------------------------------------
  # * Draw Class
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_actor_class(actor, x, y)
    self.contents.font.color = normal_color
    self.contents.draw_text(x, y, 236, 32, actor.class_name)
  end
  #--------------------------------------------------------------------------
  # * Draw Level
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_actor_level(actor, x, y)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 32, 32, "Lv")
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 32, y, 24, 32, actor.level.to_s, 2)
  end
  #--------------------------------------------------------------------------
  # * Make State Text String for Drawing
  #    actor      : actor
  #    width      : draw spot width
  #    need_normal : Whether or not [normal] is needed (true / false)
  #--------------------------------------------------------------------------
  def make_battler_state_text(battler, width, need_normal)
    # Get width of brackets
    brackets_width = self.contents.text_size("[]").width
    # Make text string for state names
    text = ""
    for i in battler.states
      if $data_states[i].rating >= 1
        if text == ""
          text = $data_states[i].name
        else
          new_text = text + "/" + $data_states[i].name
          text_width = self.contents.text_size(new_text).width
          if text_width > width - brackets_width
            break
          end
          text = new_text
        end
      end
    end
    # If text string for state names is empty, make it [normal]
    if text == ""
      if need_normal
        text = "[Normal]"
      end
    else
      # Attach brackets
      text = "[" + text + "]"
    end
    # Return completed text string
    return text
  end
  #--------------------------------------------------------------------------
  # * Draw State
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #    width : draw spot width
  #--------------------------------------------------------------------------
  def draw_actor_state(actor, x, y, width = 120)
    text = make_battler_state_text(actor, width, true)
    self.contents.font.color = actor.hp == 0 ? knockout_color : normal_color
    self.contents.draw_text(x, y, width, 32, text)
  end
  #--------------------------------------------------------------------------
  # * Draw EXP
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_actor_exp(actor, x, y)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 24, 32, "E")
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 24, y, 84, 32, actor.exp_s, 2)
    self.contents.draw_text(x + 108, y, 12, 32, "/", 1)
    self.contents.draw_text(x + 120, y, 84, 32, actor.next_exp_s)
  end
  #--------------------------------------------------------------------------
  # * Draw HP
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #    width : draw spot width
  #--------------------------------------------------------------------------
  def draw_actor_hp(actor, x, y, width = 144)
    # Draw "HP" text string
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 32, 32, $data_system.words.hp)
    # Calculate if there is draw space for MaxHP
    if width - 32 >= 108
      hp_x = x + width - 108
      flag = true
    elsif width - 32 >= 48
      hp_x = x + width - 48
      flag = false
    end
    # Draw HP
    self.contents.font.color = actor.hp == 0 ? knockout_color :
      actor.hp <= actor.maxhp / 4 ? crisis_color : normal_color
    self.contents.draw_text(hp_x, y, 48, 32, actor.hp.to_s, 2)
    # Draw MaxHP
    if flag
      self.contents.font.color = normal_color
      self.contents.draw_text(hp_x + 48, y, 12, 32, "/", 1)
      self.contents.draw_text(hp_x + 60, y, 48, 32, actor.maxhp.to_s)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw SP
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #    width : draw spot width
  #--------------------------------------------------------------------------
  def draw_actor_sp(actor, x, y, width = 144)
    # Draw "SP" text string
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 32, 32, $data_system.words.sp)
    # Calculate if there is draw space for MaxHP
    if width - 32 >= 108
      sp_x = x + width - 108
      flag = true
    elsif width - 32 >= 48
      sp_x = x + width - 48
      flag = false
    end
    # Draw SP
    self.contents.font.color = actor.sp == 0 ? knockout_color :
      actor.sp <= actor.maxsp / 4 ? crisis_color : normal_color
    self.contents.draw_text(sp_x, y, 48, 32, actor.sp.to_s, 2)
    # Draw MaxSP
    if flag
      self.contents.font.color = normal_color
      self.contents.draw_text(sp_x + 48, y, 12, 32, "/", 1)
      self.contents.draw_text(sp_x + 60, y, 48, 32, actor.maxsp.to_s)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Parameter
  #    actor : actor
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #    type  : parameter type (0-6)
  #--------------------------------------------------------------------------
  def draw_actor_parameter(actor, x, y, type)
    case type
    when 0
      parameter_name = $data_system.words.atk
      parameter_value = actor.atk
    when 1
      parameter_name = $data_system.words.pdef
      parameter_value = actor.pdef
    when 2
      parameter_name = $data_system.words.mdef
      parameter_value = actor.mdef
    when 3
      parameter_name = $data_system.words.str
      parameter_value = actor.str
    when 4
      parameter_name = $data_system.words.dex
      parameter_value = actor.dex
    when 5
      parameter_name = $data_system.words.agi
      parameter_value = actor.agi
    when 6
      parameter_name = $data_system.words.int
      parameter_value = actor.int
    end
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 120, 32, parameter_name)
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 120, y, 36, 32, parameter_value.to_s, 2)
  end
  #--------------------------------------------------------------------------
  # * Draw Item Name
  #    item : item
  #    x    : draw spot x-coordinate
  #    y    : draw spot y-coordinate
  #--------------------------------------------------------------------------
  def draw_item_name(item, x, y)
    if item == nil
      return
    end
    bitmap = RPG::Cache.icon(item.icon_name)
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24))
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 28, y, 212, 32, item.name)
  end
end


#==============================================================================
# ** Window_Help
#------------------------------------------------------------------------------
#  This window shows skill and item explanations along with actor status.
#==============================================================================

class Window_Help < Window_Bess
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 640, 64)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  #--------------------------------------------------------------------------
  # * Set Text
  #  text  : text string displayed in window
  #  align : alignment (0..flush left, 1..center, 2..flush right)
  #--------------------------------------------------------------------------
  def set_text(text, align = 0)
    # If at least one part of text and alignment differ from last time
    if text != @text or align != @align
      # Redraw text
      self.contents.clear
      self.contents.font.color = normal_color
      self.contents.draw_text(4, 0, self.width - 40, 32, text, align)
      @text = text
      @align = align
      @actor = nil
    end
    self.visible = true
  end
  #--------------------------------------------------------------------------
  # * Set Actor
  #    actor : status displaying actor
  #--------------------------------------------------------------------------
  def set_actor(actor)
    if actor != @actor
      self.contents.clear
      draw_actor_name(actor, 4, 0)
      draw_actor_state(actor, 140, 0)
      draw_actor_hp(actor, 284, 0)
      draw_actor_sp(actor, 460, 0)
      @actor = actor
      @text = nil
      self.visible = true
    end
  end
  #--------------------------------------------------------------------------
  # * Set Enemy
  #    enemy : name and status displaying enemy
  #--------------------------------------------------------------------------
  def set_enemy(enemy)
    text = enemy.name
    state_text = make_battler_state_text(enemy, 112, false)
    if state_text != ""
      text += "  " + state_text
    end
    set_text(text, 1)
  end
end

Basically, it is a complete 'duplicate' of Window_Base < Window...
now  renamed as Window_Bess < Window.   And following that, I
pasted a copy of Window_Help, whilst setting its inheritance to Window_Bess.
EX:  Window_Help < Window_Bess

I pasted this goofy thing below Scene_Debug and above main within a project running on the RPGMaker XP engine, and it ran fine.  

Then I pasted it below Scene_Debug and above Main within a HiddenChest.Exe project. And the result was a startup screen stating:  "TypeError:  superclass mismatch for class Window_Help.  

error.log Wrote:Error Type: TypeError
superclass mismatch for class Window_Help
Backtrace was empty!

It appears that the startup system verifies every module and class to verify that they are all coded properly and without any change in inheritance???

The SDK system definitely changes inheritance of many modules, adding inheritance to some where none existed before.  And this could be problematic for other scripts that indeed perform class rewrites, changing inheritances towards their own makeshift modules or classes.

And I can attest that I tried the SDK and had the same remarks given to Scene_Title having a superclass mismatch, it among others...

EDIT: I would also point out that the SDK did have fine ideas, dividing scripts into more modular sections. But the whole 'changing of inheritances'.... They tried reinventing the wheel, and that caused issues with other scripters and script compatability.
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)

[Image: QrnbKlx.jpg]
[Image: sGz1ErF.png]    [Image: liM4ikn.png]    [Image: fdzKgZA.png]    [Image: sj0H81z.png]
[Image: QL7oRau.png]    [Image: uSqjY09.png]    [Image: GAA3qE9.png]    [Image: 2Hmnx1G.png]    [Image: BwtNdKw.png%5B]
  Above are clickable links
Reply }
That's a whole different issue! It's not super related but the definition of the parent class.

In all versions of Ruby so far, you can define / open a class and then keep reopening it over and over again by just calling it without specifying the parent class ever again. I've read that you're not able to do the same with default classes in Java. (By the way, Java != Javascript guys!)

In Ruby 1.8 and 1.9 you could set a different parent class to an already existing class like Window_Command and others. Starting from the Ruby 2.x series you can no longer do that. Actually, the previous behavior is considered a Bug bug that the core developers had to address eventually.

SIDE NOTE

If anybody takes some time to analyze old scripts, there were MANY that included some of the weirdest features or several cases of exploitation of undesired behaviors. Even a couple of ModernAlgebra's scripts might include excessive amounts of redundant code or inefficient calls to methods as if he only cared about making it look as if he were an expert in Ruby metaprogramming. The problem is it ended up being seriously convoluted code, or it included new arguments for methods that originally had none nor needed any in his custom scripts at all, i.e. update(*args). And nope, you don't need to add arguments to an update method except for some exception in VX ACE like update_basic, IIRC.
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9

Maranatha!

The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.

[Image: SP1-Scripter.png]
[Image: SP1-Writer.png]
[Image: SP1-Poet.png]
[Image: SP1-PixelArtist.png]
[Image: SP1-Reporter.png]

My Original Stories (available in English and Spanish)

List of Compiled Binary Executables I have published...
HiddenChest & Roole

Give me a free copy of your completed game if you include at least 3 of my scripts! Laughing + Tongue sticking out

Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Reply }
Using *args for the standard alias + monkey patch pattern increases compatibility. Let me show you some code.

Original:
Code:
class Foo
  def update
    # ...
  end
end

Script Other:
Code:
class Foo
  # ...
  alias_method :other_update, :update
  def update(bar)
    # Do stuff with bar
    other_update
  end
end

The update call path then goes like this: 
() -> Other -> Original -> 

Say I want to attach my own piece of code. Consider this piece of code with args code:
Code:
class Foo
  alias_method :zeriab_example_update, :update
  def update(*args)
    # Do new stuff
    zeriab_example_update(*args)
  end
end

I can place my script both above and below the other script. Both cases works fine.
() -> Other -> With args -> Original -> 
() -> With args -> Other -> Original -> 

Let's look at some code with no args:
Code:
class Foo
  alias_method :zeriab_example_update, :update
  def update
    # Do new stuff
    zeriab_example_update
  end
end

Again you have two possible order arrangements however only one works
() -> Other -> No args -> Original -> 
() -> No args -> Other -> Original -> 

I don't whether there is a performance impact. If not, then it's a case of pure upside. Even with a small perf impact I would often find the price worth paying.


P.s. Ruby supports passing on blocks to method calls. You can access this via the & symbol.
Code:
class Foo
  alias_method :zeriab_example_update, :update
  def update(*args, &block)
    # Do new stuff
    zeriab_example_update(*args, &block)
  end
end
I've found the usage scenarios to be very rare indeed. Only use has pretty much been when I've played around with the Enumerable mixin.
Also, you got to be careful with Procs as they cannot be serialized. If you store it in the object (@my_block = block) then you can no longer serialize that Foo object.

*hugs*
[Image: ZeriabSig.png]
Reply }
The problem comes when people simply add the *args parameter to everything, making all those methods a lot less efficient than any passing a specific number of arguments if any. The reason is that it first has to parse a C or Ruby array through a check list before assigning the values to its corresponding variables. If anything is missing, it will set nil as their default value. That's a good reason why I don't like to add *args as the parameter everywhere.
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9

Maranatha!

The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.

[Image: SP1-Scripter.png]
[Image: SP1-Writer.png]
[Image: SP1-Poet.png]
[Image: SP1-PixelArtist.png]
[Image: SP1-Reporter.png]

My Original Stories (available in English and Spanish)

List of Compiled Binary Executables I have published...
HiddenChest & Roole

Give me a free copy of your completed game if you include at least 3 of my scripts! Laughing + Tongue sticking out

Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Reply }
You have done measurements requiring this? Can you share them :3
Would be interesting seeing what sort of difference it makes in various scenarios.
I'm also curious what sort of perf impact merging alias chains down into the original code has.
Code:
class Foo
  def update(bar)
    # Do bar stuff
    # My stuff
    # do original script stuff
  end
end

Ruby version could be an important factor (1.8 vs 1.9 vs 2.7)


(12-11-2024, 12:52 PM)kyonides Wrote: The problem comes when people simply add the *args parameter to everything
People do that? Interesting, I normally use it for integration points, and where calling a method with a variable number of argument can make sense. Sometimes also when playing around with metaprogramming though that's just for fun. 

Oh yeah, a form for keyword arguments got introduced in 1.9. Bet 2.7 has a better keyword arguments making them easier to work with.
[Image: ZeriabSig.png]
Reply }


Possibly Related Threads…
Thread Author Replies Views Last Post
   Neko RMXP Player for Android JayRay 2 8,306 10-05-2014, 03:46 AM
Last Post: DerVVulfman
   ARGSS - Remaking RGSS/2 Player vgvgf 13 22,924 04-21-2010, 04:34 AM
Last Post: vgvgf



Users browsing this thread: 1 Guest(s)