How to alter scripts to call other scripts to avoid conflict.

Discussion in 'RGSSx Script Support' started by Trifectus, Oct 22, 2019.

  1. Trifectus

    Trifectus Warper Member

    Messages:
    3
    Likes Received:
    0
    First Language:
    English
    Primarily Uses:
    RMVXA
    Hi, usually yadda yadda been messing about with this program for a long time but never really delved into the scripting side. Fast forward a few years and I've learned enough about coding to be able to use premade scripts and to properly troubleshoot conflicts. Currently my biggest issue is dealing with multiple scripts that provide different functionalities but overwrite the same core script.

    Namely I'm trying to get Fomar0153's Equipment Skills(ES) to work with Yanfly's Ace Equip Engine.(AEE)

    Everything is hunky dory until you try to change equipment on a character. When ES is loaded in above AEE it crashes the program whenever you try to change equipment (which is to be expected) but when I load ES below AEE everything works fine EXCEPT that they both write over the change_equip and create_item_window and when you select an item to change the inventory disappears.

    upload_2019-10-21_12-12-39.png
    The "Change" button has been selected, and the equipment window has disappeared but is still able to be interacted with.

    To be clear -- the blank space should be filled with a window that displays the equipments which it normally does without Fomar0135's Equipment Skills, but that script doesn't natively have that problem. Thus the problem is with how these two scripts interact when trying to draw/call/create or whatever the proper terminology is for the change_equip window? (I think that's right?)

    Beyond that my only gripe is that the previous menu (where you select which slot you want to change) is incredibly laggy, and it's only when that screen is active which I assume is related to the scripts not being perfectly compatible.

    I really don't know how to go about solving this beyond hoping that it's just adding a few snippets of code to AEE allowing it to call the change_equip/create_item_window from ES but even then I wouldn't really know where to insert it.

    Any idea how I can fix this beyond removing Equipment Skills?

    Cheers.

    Fomar0153's Equipment Skills - http://cobbtocs.co.uk/wp/?p=36
    Yanfly's Ace Equipment Engine - https://yanflychannel.wordpress.com/rmvxa/gameplay-scripts/ace-equip-engine/
     
    Last edited: Oct 22, 2019
    #1
  2. TheoAllen

    TheoAllen Self-proclaimed jack of all trades Veteran

    Messages:
    4,437
    Likes Received:
    5,029
    Location:
    Riftverse
    First Language:
    Indonesian
    Primarily Uses:
    RMVXA
    If you could provide the link to those two scripts and probably your edit, it is easier to get help.
     
    #2
  3. Trifectus

    Trifectus Warper Member

    Messages:
    3
    Likes Received:
    0
    First Language:
    English
    Primarily Uses:
    RMVXA
    Thanks, I wasn't sure what the linking rules might have been so erred on using the names. I'll edit them in now. The edits I make to the script don't matter as even default the scripts don't play nice together but ONLY in the screen window capacity.
     
    #3
  4. Another Fen

    Another Fen Veteran Veteran

    Messages:
    530
    Likes Received:
    244
    First Language:
    German
    Hey there,

    While scripts can certainly clash for any number of reasons and I don't believe there is a way around understanding how two scripts work in order to rule out incompatibilities in general, the vast majority of incompatibilities seem to come from one script undoing parts of another script by overwriting the same method.

    To spot shared method redefinitions you could also utilize a script like this if it helps (sorry for the terrible code, the script is quite old and was not originally meant to be reused):
    Code:
    if true
     
    unless $methodtestrun
      $methodtestrun = true
     
      class Module
       
        def metaclass
          class << self
            return self
          end
        end
      end
     
      def rgss_main
        # Skip the actual game
      end
     
      klass_block = lambda { |klass, methods|
        oldset = methods[klass]
        newset = Hash.new
        klass.instance_methods(false).each { |sym|
          newset[sym] = klass.instance_method(sym).source_location
        }
        added = newset.keys - oldset.keys
        changed = newset.keys.select { |s| oldset[s] && oldset[s] != newset[s] }
        removed = oldset.keys - newset.keys
        methods[klass] = newset
        next [added, changed, removed]
      }
     
      space_block = lambda { |name, methods, last_sources, file|
        linebreak = "\n"
        ignore_add = true
        file.write(name)
        file.write(linebreak)
        ObjectSpace.each_object(Module) do |object|
          [object, object.metaclass].each do |klass|
            added, changed, removed = *klass_block.call(klass, methods)
            smallspace = "  "
            space = "    "
            [["ADDED", added], ["REDEFINED", changed], ["REMOVED", removed]]\
            .each do |set|
              unless set[1].empty? || (set[0] == "ADDED" && ignore_add)
                file.write(smallspace)
                file.write(set[0])
                file.write(":")
                file.write(linebreak)
                set[1].each do |method|
                  file.write(space)
                  file.write(klass.to_s)
                  file.write("#")
                  file.write(method.to_s)
                  if last_sources[klass][method]
                    file.write(" "\
                    * [51 - klass.to_s.length - method.to_s.length, 2].max)
                    file.write("(")
                    file.write(last_sources[klass][method])
                    file.write(")")
                  end
                  file.write(linebreak)
                  file.flush
                end
              end
              set[1].each do |method|
                last_sources[klass][method] = name
              end
            end
          end
        end
        file.write(linebreak)
        file.flush
      }
     
      File.open("Result.txt", "w") do |file|
        methods = Hash.new { |h, k| h[k] = Hash.new }
        last_sources = Hash.new { |h, k| h[k] = Hash.new }
        space_block.call(nil, methods, last_sources, file)
        $RGSS_SCRIPTS.each do |set|
          name = set[1]
          code = set[3]
          RubyVM::InstructionSequence.compile(code).eval
          space_block.call(name, methods, last_sources, file)  unless code.strip.empty?
        end
      end
     
      msgbox("Methods collected.")
      Kernel.exit
    end
    
    end
    
    To use this, place the script at the very top of your script editor, run playtest and remove the script again.
    Open "Result.txt" in your project folder, scroll all the way down to see which redefined methods in your second script name your first script as the last source.

    Most of the time, aliased methods are save since they usually only add more stuff to the method without undoing anything other scripts may have done, but there are exceptions of course (in this case, pretty much all of them) which would have to be merged manually.


    The missing inventory window for example comes from ES's redefinition of "create_item_window" as you already mentioned, which moves the window back below the window for equipped items, which in Yanflys layout means it's moved below the screen.

    Generally you'd probably have to make your mind up about the layout. ES tries to make space for equipped skills by reducing the size of the inventory window, which in Yanflys layout does not work.


    As for the performance issue, this already seems a thing with only the ES script, with AEE only amplifying it.
    Performance issues like this in menus often come from overusing bitmap drawing commands (especially draw_text and set_pixel), which are comparatively time extensive. These are mainly used to refresh the contents of a window, and things like unconditionally refreshing a window every frame in an update method just to make sure can unnecessarily take a lot of time.

    In this case the Window_EquipSlot - update - method would stand out, which should maybe only refresh the stats window when the item has actually changed.


    I don't know whether you are primarily looking for advice or a solution here, a first attempt to merge the problematic methods could look like this:
    Code:
    class Scene_Equip
     
      def create_item_window
        # Yanfly - Equip Engine
        wx = @slot_window.x
        wy = @slot_window.y
        ww = @slot_window.width
        wh = @slot_window.height
        @item_window = Window_EquipItem.new(wx, wy, ww, wh)
        @item_window.viewport = @viewport
        @item_window.help_window = @help_window
        @item_window.status_window = @status_window
        @item_window.actor = @actor
        @item_window.set_handler(:ok,     method(:on_item_ok))
        @item_window.set_handler(:cancel, method(:on_item_cancel))
        @slot_window.item_window = @item_window
        @item_window.hide
      end
    end
    
    
    class Game_Actor
     
      #--------------------------------------------------------------------------
      # ‚óŹ Rewrites change_equip
      #--------------------------------------------------------------------------
      def change_equip(slot_id, item)
        # Yanfly - Equip Engine
        if item.nil? && !@optimize_clear
          etype_id = equip_slots[slot_id]
          return unless YEA::EQUIP::TYPES[etype_id][1]
        elsif item.nil? && @optimize_clear
          etype_id = equip_slots[slot_id]
          return unless YEA::EQUIP::TYPES[etype_id][2]
        end
        @equips[slot_id] = Game_BaseItem.new if @equips[slot_id].nil?
        # Changed Position from original - avoid trade with wrong etype_id
        return if item && equip_slots[slot_id] != item.etype_id
        # Formar0153 - Equipment Skills
        return unless trade_item_with_party(item, equips[slot_id])
        if equips[slot_id].is_a?(RPG::Weapon)
          unless Equipment_Skills::Weapons[equips[slot_id].id] == nil
            for skill in Equipment_Skills::Weapons[equips[slot_id].id]
              if Equipment_Skills::Learn_Skills
                if @ap[skill] == nil
                  @ap[skill] = 0
                end
                unless @ap[skill] >= Equipment_Skills.get_ap_cost(skill)
                  forget_skill(skill)
                end
              else
                forget_skill(skill)
              end
            end
          end
        end
        if equips[slot_id].is_a?(RPG::Armor)
          unless Equipment_Skills::Armors[equips[slot_id].id] == nil
            for skill in Equipment_Skills::Armors[equips[slot_id].id]
              if Equipment_Skills::Learn_Skills
                if @ap[skill] == nil
                  @ap[skill] = 0
                end
                unless @ap[skill] >= Equipment_Skills.get_ap_cost(skill)
                  forget_skill(skill)
                end
              else
                forget_skill(skill)
              end
            end
          end
        end
        # ---
        @equips[slot_id].object = item
        refresh
      end
    end
    
    
    class Window_EquipStatus
     
      def refresh(item = nil)
        contents.clear
        # Yanfly - Equip Engine
        8.times {|i| draw_item(0, line_height * i, i) }
        # Formar0153 - Equipment Skills
        unless item == nil
          if item.is_a?(RPG::Weapon)
            unless Equipment_Skills::Weapons[item.id] == nil
              skills = Equipment_Skills::Weapons[item.id]
            end
          end
          if item.is_a?(RPG::Armor)
            unless Equipment_Skills::Armors[item.id] == nil
              skills = Equipment_Skills::Armors[item.id]
            end
          end
          unless skills == nil
            change_color(normal_color)
            draw_text(4, 8 * line_height, width, line_height, "Equipment Skills")
            change_color(system_color)
            i = 1
            for skill in skills
              draw_text(4, (8 + i) * line_height, width, line_height,
                  $data_skills[skill].name)
              if Equipment_Skills::Learn_Skills and @actor.ap[skill] == nil
                @actor.ap[skill] = 0
              end
              i = i + 1
              if Equipment_Skills::Learn_Skills
                draw_current_and_max_values(4, (8 + i) * line_height, width - 50,
                    [@actor.ap[skill],Equipment_Skills.get_ap_cost(skill)].min,
                    Equipment_Skills.get_ap_cost(skill), system_color, system_color)
                i = i + 1
              end
            end
          end
        end
      end
    end
       
       
    class Window_EquipItem
     
      def update_help
        # Yanfly - Equip Engine
        super
        return if @actor.nil?
        return if @status_window.nil?
        return if @last_item == item
        @last_item = item
        temp_actor = Marshal.load(Marshal.dump(@actor))
        temp_actor.force_change_equip(@slot_id, item)
        @status_window.set_temp_actor(temp_actor)
        # Formar0153 - Equipment Skills
        @status_window.refresh(item)
      end
    end
       
    
    
    class Window_EquipSlot < Window_Selectable
     
      def update
        # Formar0153 - Equipment Skills (Modified)
        eqskills_update
        @status_window.refresh(self.item) if self.active && self.item != @last_item
        @last_item = self.item
      end
    end
    
    However, there could be better solutions and you still might need to move some windows around if you don't have enough space for your equipment skills left.
     
    #4
    Trifectus likes this.
  5. Trifectus

    Trifectus Warper Member

    Messages:
    3
    Likes Received:
    0
    First Language:
    English
    Primarily Uses:
    RMVXA
    I've plugged this in below everything and it has fixed all of my issues, you are awesome!

    No more lag in the previous menu and the equipment menu is properly displaying.

    I appreciate the depth of your response as well as most of my knowledge is mostly about eventing and using the database in the program so I knew this was going to be a bit out of my grasp. Outside of semi-identifying the problem I would not have had even the slightest clue where to start so this is incredibly helpful. Thanks again!
     
    #5

Share This Page