Script Commands Bug Fixes
#1
Bug Fixes for Both of RMXP's Interpreter's Script Commands

Introduction

For ages we've known very well that the RMXP Interpreter class had an issue with command_355 aka the script event command. It has to evaluate the result of a script pasted as mere text in a very small window. The problem was that certain non truthy values, anything that doesn't return true as end result, might get ignored by the game engine. This part and its related solution are nothing new in the XP community and I just "copied & pasted" that centuries old solution here.

Nonetheless, that's not all this scriptlet has to offer. I was discussing some issues with XP in a VX ACE channel when I noticed there was another Bug bug that usually got ignored in RMXP. It was the script condition in the conditional branch event command! Shocked

The issue is very simple. You open the conditional branch and choose the script condition and type something there that's supposed to return a boolean value. (No if conditional reserved term is required there.) Now you'd expect me to tell you that it had the same issue the script command has... but nope, that's not the case here.

Both a truthy (true) and a falsey (false) value are fine and work just as intended. Yet, here comes the dreadful nil value into play!

Whenever your call returns a nil, your check becomes invalid and the engine simply skips it. Who Knows? Just like that, guys! Happy with a sweat

Don't Worried worry pals! The scriptlet below has come to Save-Point to solve that issue! Winking

The Script

Code:
# * Bug Fixes for Both of RMXP's Interpreter's Script Commands * #
#  2025-02-12
#  Result: You won't get any more issues with comannds returning nil values!

class Interpreter
  # * Conditional Branch * #
  # Altered the Script Condition at the very end of this command
  def command_111
    # Initialize local variable: result
    result = false
    case @parameters[0]
    when 0  # switch
      result = ($game_switches[@parameters[1]] == (@parameters[2] == 0))
    when 1  # variable
      value1 = $game_variables[@parameters[1]]
      if @parameters[2] == 0
        value2 = @parameters[3]
      else
        value2 = $game_variables[@parameters[3]]
      end
      case @parameters[4]
      when 0  # value1 is equal to value2
        result = (value1 == value2)
      when 1  # value1 is greater than or equal to value2
        result = (value1 >= value2)
      when 2  # value1 is less than or equal to value2
        result = (value1 <= value2)
      when 3  # value1 is greater than value2
        result = (value1 > value2)
      when 4  # value1 is less than value2
        result = (value1 < value2)
      when 5  # value1 is not equal to value2
        result = (value1 != value2)
      end
    when 2  # self switch
      if @event_id > 0
        key = [$game_map.map_id, @event_id, @parameters[1]]
        if @parameters[2] == 0
          result = ($game_self_switches[key] == true)
        else
          result = ($game_self_switches[key] != true)
        end
      end
    when 3  # timer
      if $game_system.timer_working
        sec = $game_system.timer / Graphics.frame_rate
        if @parameters[2] == 0
          result = (sec >= @parameters[1])
        else
          result = (sec <= @parameters[1])
        end
      end
    when 4  # actor
      actor = $game_actors[@parameters[1]]
      if actor != nil
        case @parameters[2]
        when 0  # in party
          result = ($game_party.actors.include?(actor))
        when 1  # name
          result = (actor.name == @parameters[3])
        when 2  # skill
          result = (actor.skill_learn?(@parameters[3]))
        when 3  # weapon
          result = (actor.weapon_id == @parameters[3])
        when 4  # armor
          result = (actor.armor1_id == @parameters[3] or
                    actor.armor2_id == @parameters[3] or
                    actor.armor3_id == @parameters[3] or
                    actor.armor4_id == @parameters[3])
        when 5  # state
          result = (actor.state?(@parameters[3]))
        end
      end
    when 5  # enemy
      enemy = $game_troop.enemies[@parameters[1]]
      if enemy != nil
        case @parameters[2]
        when 0  # appear
          result = (enemy.exist?)
        when 1  # state
          result = (enemy.state?(@parameters[3]))
        end
      end
    when 6  # character
      character = get_character(@parameters[1])
      if character != nil
        result = (character.direction == @parameters[2])
      end
    when 7  # gold
      if @parameters[2] == 0
        result = ($game_party.gold >= @parameters[1])
      else
        result = ($game_party.gold <= @parameters[1])
      end
    when 8  # item
      result = ($game_party.item_number(@parameters[1]) > 0)
    when 9  # weapon
      result = ($game_party.weapon_number(@parameters[1]) > 0)
    when 10  # armor
      result = ($game_party.armor_number(@parameters[1]) > 0)
    when 11  # button
      result = (Input.press?(@parameters[1]))
    when 12  # script
      result = eval(@parameters[1])
    end
    # Store determinant results in hash
    # Added pos variable for the sake of convenience
    pos = @list[@index].indent
    # Bug Fix - Turn any nil value into false by default
    @branch[pos] = !!result
    # If determinant results are true
    if @branch[pos]
      # Delete branch data
      @branch.delete(pos)
      # Continue
      return true
    end
    # If it doesn't meet the conditions: command skip
    return command_skip
  end
  # * Script Event Command * #
  # Just a small variant of a very old bug fix published by somebody else
  def command_355
    # Set first line to script
    script = @list[@index].parameters[0] + "\n"
    # Loop
    loop do
      # If next event command is second line of script or after
      if @list[@index+1].code == 655
        # Add second line or after to script
        script += @list[@index+1].parameters[0] + "\n"
      # If event command is not second line or after
      else
        # Abort loop
        break
      end
      # Advance index
      @index += 1
    end
    # Evaluation
    result = eval(script)
    # Removed Several Lines Here Before Continue
    return true
  end
end

Infrequently Asked Questions

Q: Has anybody else posted anything like this before?
A: Who knows? Who Knows? In any case I preferred to leave the script here just in case anybody fiddling with RMXP ever needs it.

Terms of Use

You can do whatever you want with it, I just built something upon somebody else's work and that's it.
"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 }
#2
The conditional branch script command requires the result to specifically be either true or false. Try putting in a number like 12 and you'll see the conditional branch being skipped as well.
Expanding it to work with truthy and falsey values is a good idea ^^

Not a fan of your command_355 fix. Being able to run a script call every frame while it returns a special value can be useful.
Here's a version I did where you can let your script call return :wait to run it again. 
Code:
class Interpreter
  SCRIPT_WAIT_RESULTS = [:wait, FalseClass]
  #--------------------------------------------------------------------------
  # * Script
  #--------------------------------------------------------------------------
  def command_355
    # Set first line to script
    script = @list[@index].parameters[0] + "\n"
    # Store index in case we need to wait.
    current_index = @index
    # Loop
    loop do
      # If next event command is second line of script or after
      if @list[@index+1].code == 655
        # Add second line or after to script
        script += @list[@index+1].parameters[0] + "\n"
      # If event command is not second line or after
      else
        # Abort loop
        break
      end
      # Advance index
      @index += 1
    end
    # Evaluation
    result = eval(script)
    # If return value is false
    if SCRIPT_WAIT_RESULTS.include?(result)
      # Set index back (If multi-line script call)
      @index = current_index
      # End and wait
      return false
    end
    # Continue
    return true
  end
end

*hugs*
 - Zeriab
[Image: ZeriabSig.png]
Reply }
#3
(02-13-2025, 03:19 PM)Zeriab Wrote: The conditional branch script command requires the result to specifically be either true or false. Try putting in a number like 12 and you'll see the conditional branch being skipped as well.
Expanding it to work with truthy and falsey values is a good idea ^^

Well, I run a test to see what happens if you simply pass a number to a custom method like the following:

Code:
class Interpreter
  def is_true?(var)
    var
  end
end

It doesn't alter the value by default but just returns the argument immediately as you can see above.

Result: true
As people might already know, numbers and many other objects are treated as true by default.

My fix takes anything you might have put as a script condition and negates it twice. Thus, if it was a number, any non NilClass object or a TrueClass one, it will always be true. This means it does respect the need to evaluate to true or false. All nil's would become false and stop being ignored by the conditional branch. Great, don't you think? Grinning

Regarding the command_355 stuff, I do understand your desire to add the waiting time but I don't share it. My variant is inspired by VX ACE where any result of the script event command evaluation does NOT become an integral part of the interpretation mechanism. Meaning that it won't stop executing it just because it returned a falsey value like it does in XP.

Anyway, I'd need to get access to a few edge cases where I can clearly see the need to use another version or fix it some other way before I would dare to modify it or replace it.
"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 }


Possibly Related Threads…
Thread Author Replies Views Last Post
   The Steal and Peep Script DerVVulfman 12 414 Yesterday, 07:20 AM
Last Post: Ace_V
   Text Scroll Script - Enhanced DerVVulfman 23 35,982 02-18-2021, 04:16 AM
Last Post: DerVVulfman
   Cursor Script Selwyn 7 16,149 09-28-2019, 02:13 PM
Last Post: DerVVulfman
   ACBS FIX SCRIPT #2: Advanced Cry Correction DerVVulfman 1 5,028 08-09-2019, 03:42 PM
Last Post: aeliath
   ACBS FIX SCRIPT #1: Victory Cries Patch DerVVulfman 1 5,096 08-08-2019, 02:53 PM
Last Post: aeliath
   Spritesheet Generator Conversion Script DerVVulfman 0 4,528 11-21-2018, 04:48 AM
Last Post: DerVVulfman
   Event Spawner Fixes DerVVulfman 8 17,706 01-02-2018, 05:48 AM
Last Post: DerVVulfman
   Neo Mode 7 Script by MGCaladtogel MGC 59 129,739 09-29-2017, 03:48 AM
Last Post: DerVVulfman
   Longer Script Calls LiTTleDRAgo 0 5,169 05-17-2017, 12:36 AM
Last Post: LiTTleDRAgo
   SLOLS: Snake Look-alike on Load Script Zeriab 3 11,794 05-14-2017, 06:25 PM
Last Post: LiTTleDRAgo



Users browsing this thread: 1 Guest(s)