Save-Point

Full Version: Save-Point
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Board Message
Sorry, you do not have permission to access this resource.
Save-Point - Weapons / Equipment that grants skills

Save-Point

Full Version: Weapons / Equipment that grants skills
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello! I am in need of a script for RPGMaker XP that grants a character a skill (or set of skills) if they equip a weapon or piece of armor/accessory. The skill (or skills) should also be forgotten if said weapon or equipment is removed.

In basic terms, my current intended use is a rifle giving the shoot skill. Equipping a knife removes the shoot skill.
I was also planning on making another piece of equipment that grants a set of five summon-themed spells.

I tried searching the forum's XP scripts and requests, but alas.  Feeling sick

I also tried out Kyonides' KEquip script since that would have solved both problems (the demo allowed me to add multiple spells to a single piece of equipment), but I kept getting syntax errors when I tried applying the script to my project (even with the use of just one piece of equipment for direct_weapons and one skill) and eventually gave up on it after three hours.

My current set-up for the rifle is via a common parallel event for a single weapon and skill, but I'm wary of that causing lag in certain maps, particularly if I want to make more weapons with the same mechanic.
For the equipment, I just taught all five skills via a story event (in essence, the equipment isn't functioning as I intend.)

Could anyone help?
This may sound a bit expansive, but have you looked at Angie's Equipment Sets by chance? The initial idea behind said script was to give the wearer a 'boost' of some sort if they have a matching set of armor; bonus stats, bonus or penalty status effects, learned skills. However, it need not be for full armor requirements, but a piece or pieces of armor and/or weapons.

IE: You could make it so equipping a Mythril Sword alone could give you 'Sharp' (+50% attack) while suffering 'Mute', and simultaneously give you access to 'Fire' if you don't have it while losing 'Ice' while it is equipped.

Also, do remember that some scripts don't play well with others and may need a 'patch', or it could be a simple case of script order where you place a script above or below another to get the two to work right.
(11-20-2024, 05:09 PM)DerVVulfman Wrote: [ -> ]This may sound a bit expansive, but have you looked at Angie's Equipment Sets by chance?

Oh! Not yet. I must have overlooked it as it didn't have the keywords I was browsing for.

It does seem very expansive! Wow, 39 pages. I'll give it a closer look tomorrow, though I'm wary of adding such a big script that I only intend to use a tiny function of (adding a skill and removing a skill for a "set" of 1 weapon). Won't that add a bit of clutter to my game if it'll count one weapon as a full set and give it an icon? (I browsed through the code. It's pretty neat!)

I also recently noticed that there were scrollbars in the archives that you compiled https://www.save-point.org/thread-7400-post-48964.html (so nice to see the old code from the 2000s!) and spotted this little script while scrolling Happy with a sweat :


https://www.save-point.org/showthread.php?tid=6884

It has the function I want, but as the author makeamidget confessed, it is a bit rough. I'm also not sure where to put part 1 of the code, as the portion below if Input.trigger?(Input::C) is quite long. I think mine is "stock," but here it is up to the part before def update_item  if Input.trigger?(Input::B) :


Code:
if Input.trigger?(Input::C)
     if @actor.equip_fix?(@right_window.index)
       $game_system.se_play($data_system.buzzer_se)
       return
     end
     $game_system.se_play($data_system.decision_se)
     @right_window.active = false
     @item_window.active = true
     @item_window.index = 0
     return
   end
   if Input.trigger?(Input::X)
     $game_system.se_play($data_system.decision_se)
     optimize(@right_window.index)
     @left_window.refresh
     @right_window.refresh
     @item_window1.refresh
     @item_window2.refresh
     @item_window3.refresh
     @item_window4.refresh
     @item_window5.refresh
     return
   end
   if Input.trigger?(Input::Y)
     $game_system.se_play($data_system.decision_se)
     optimize(0)
     optimize(1)
     optimize(2)
     optimize(3)
     optimize(4)
     @left_window.refresh
     @right_window.refresh
     @item_window1.refresh
     @item_window2.refresh
     @item_window3.refresh
     @item_window4.refresh
     @item_window5.refresh
     return
   end
   if Input.trigger?(Input::R)
     $game_system.se_play($data_system.cursor_se)
     @actor_index += 1
     @actor_index %= $game_party.actors.size
     $scene = Scene_Equip.new(@actor_index, @right_window.index)
     return
   end
   if Input.trigger?(Input::L)
     $game_system.se_play($data_system.cursor_se)
     @actor_index += $game_party.actors.size - 1
     @actor_index %= $game_party.actors.size
     $scene = Scene_Equip.new(@actor_index, @right_window.index)
     return
   end
end
def optimize(slot)
  if slot == 0
    object = $data_weapons[@actor.weapon_id]
    optimal = object.id
    current = 0.00
    if @actor.weapon_id != 0
      current += object.atk * WEAPON_ATK_WEIGHT
      current += object.pdef * WEAPON_PDF_WEIGHT
      current += object.mdef * WEAPON_MDF_WEIGHT
      current += object.str_plus * WEAPON_STR_WEIGHT
      current += object.dex_plus * WEAPON_DEX_WEIGHT
      current += object.agi_plus * WEAPON_AGI_WEIGHT
      current += object.int_plus * WEAPON_INT_WEIGHT
    else
      optimal = 0
    end
    max_eval = current
    @actor.equip(0, 0)
    flag = false
    zero_flag = true
    for weapon in $data_weapons
      if !flag
        flag = true
        next
      end
      evaluation = 0.00
      evaluation += weapon.atk * WEAPON_ATK_WEIGHT
      evaluation += weapon.pdef * WEAPON_PDF_WEIGHT
      evaluation += weapon.mdef * WEAPON_MDF_WEIGHT
      evaluation += weapon.str_plus * WEAPON_STR_WEIGHT
      evaluation += weapon.dex_plus * WEAPON_DEX_WEIGHT
      evaluation += weapon.agi_plus * WEAPON_AGI_WEIGHT
      evaluation += weapon.int_plus * WEAPON_INT_WEIGHT
      if evaluation > 0
        zero_flag = false
      end
      if @actor.equippable?(weapon) &&
        $game_party.weapon_number(weapon.id) > 0 && evaluation > max_eval
        max_eval = evaluation
        optimal = weapon.id
      end
    end
    if zero_flag
      optimal = 0
    end
    @actor.equip(0, optimal)

  end
  if slot >= 1
    not_equipped = false
    case slot
    when 1
      if @actor.armor1_id == 0
        not_equipped = true
      else
      object = $data_armors[@actor.armor1_id]
      end
    when 2
      if @actor.armor2_id == 0
        not_equipped = true
      else
      object = $data_armors[@actor.armor2_id]
      end
    when 3
      if @actor.armor3_id == 0
        not_equipped = true
      else
      object = $data_armors[@actor.armor3_id]
      end
    when 4
      if NO_ACCESSORY_OPTIMIZATION
        return
      end
      if @actor.armor4_id == 0
        not_equipped = true
      else
      object = $data_armors[@actor.armor4_id]
      end
    end
    optimal = object.id
    current = 0.00
    if not_equipped = false
      current += object.eva * ARMOR_EVA_WEIGHT
      current += object.pdef * ARMOR_PDF_WEIGHT
      current += object.mdef * ARMOR_MDF_WEIGHT
      current += object.str_plus * ARMOR_STR_WEIGHT
      current += object.dex_plus * ARMOR_DEX_WEIGHT
      current += object.agi_plus * ARMOR_AGI_WEIGHT
      current += object.int_plus * ARMOR_INT_WEIGHT
    else
      optimal = 0
    end
    max_eval = current
    @actor.equip(slot, 0)
    flag = false
    zero_flag = true
    for armor in $data_armors
      if !flag
        flag = true
        next
      end
      if armor.kind != slot-1
       next
      end
      evaluation = 0.00
      evaluation += armor.eva * ARMOR_EVA_WEIGHT
      evaluation += armor.pdef * ARMOR_PDF_WEIGHT
      evaluation += armor.mdef * ARMOR_MDF_WEIGHT
      evaluation += armor.str_plus * ARMOR_STR_WEIGHT
      evaluation += armor.dex_plus * ARMOR_DEX_WEIGHT
      evaluation += armor.agi_plus * ARMOR_AGI_WEIGHT
      evaluation += armor.int_plus * ARMOR_INT_WEIGHT
     if evaluation > 0
        zero_flag = false
      end
      if @actor.equippable?(armor) &&
        $game_party.armor_number(armor.id) > 0 && evaluation > max_eval
        max_eval = evaluation
        optimal = armor.id
      end
    end
    if zero_flag
      optimal = 0
    end
    @actor.equip(slot, optimal)
  end
end
Yeah... when scripters began working with ruby, not many knew about using the alias command to attach script code in a cleaner function. 

Insofar as your default script....  You're showing modified code for the 'update_right' method, not the 'update_item' method which makeamidget suggested Part 1 of his script should go.

By Modified, I mean the if...end blocks testing for Input::X and Input::Y aren't stock.

if Input.trigger?(Input::X)
  $game_system.se_play($data_system.decision_se)
  optimize(@right_window.index)
  @left_window.refresh
  @right_window.refresh
  @item_window1.refresh
  @item_window2.refresh
  .   .   .
Yeah.... this code isn't stock Winking



NOW... as to where the code goes, makeamidget said it goes within the "update_item" method, after the Input::C line.  So within this code...

# If C button was pressed
if Input.trigger?(Input::C)
  << PLACE HERE >>
  # Play equip SE
  $game_system.se_play($data_system.equip_se)
  # Get currently selected data on the item window
  item = @item_window.item
  # Change equipment
  .   .   .

It will look like this...


# If C button was pressed
if Input.trigger?(Input::C)
  actor = $game_actors[@actor.id]
  item = @item_window.item
  item2 = @right_window.item
  # equip gain skills start
  # begining of weapons
  if @right_window.index == 0
  .   .   .
(11-24-2024, 04:37 AM)DerVVulfman Wrote: [ -> ]Yeah.... this code isn't stock Winking

Shocked Now I'm really relieved I decided to share that bit of code! The project was from 2004, so I assume I've forgotten about any of the more in-depth code changes I implemented back then.
Right now the project only has a few modifications:
- KGC Conditional Skills (which does not fully suit my needs for weapon-skills, but apparently I've baked in a few other story-related skills that require the KGC script)
- Monster Diary by momomo
- Ring Menu by Dubealex (edits by Hypershadow180)
- Text Scroller by Dubealex
- Caterpillar script by Fukuyama (I saw that you made an add-on to it! I might implement that)
- New Game+ by Deke
- 8-direction movement by anonymous
- Battle defense heal by Khatharr
- Steal Script by makeamidget & Khatharr
- Custom menus by Sir_ValHor

...And now hopefully this weapon skills script by makeamidget (with help from DerVVulfman!)



I'll test it out and hopefully this resolves my request!  Blushing + Cheery
I am getting a script error:

Script 'Scene+Equip' like 712: NoMethodError occurred.
Undefined method '[]' for nil:NilClass

This is the line:
      for i in $game_party.weapon_equip_skill[item2.id]

I put the first part of the code into the def update_item section just below if Input.trigger?(Input::C), and made a new entry for the second part of the script.


First part:
Code:
  def update_item
    if Input.trigger?(Input::B)
      # SE
      $game_system.se_play($data_system.cancel_se)
      @right_window.active = true
      @item_window.active = false
      @item_window.index = -1
      return
    end
    if Input.trigger?(Input::C)
actor = $game_actors[@actor.id]
     item = @item_window.item
     item2 = @right_window.item
     #equip gain skills start
     #begining of weapons
     if @right_window.index == 0
       if item.is_a?(RPG::Weapon)
       for i in $game_party.weapon_equip_skill[item2.id]
         actor.forget_skill(i)
       end
       unless item.id == 0 || nil
       for i in $game_party.weapon_equip_skill[item.id]
         actor = $game_actors[@actor.id]
         actor.learn_skill(i)
       end
       end
     else
       for i in $game_party.weapon_equip_skill[item2.id]
         actor.forget_skill(i)
       end     
       end 
     end
     #end of weapons
     #begining of armors
     if @right_window.index >= 1
       if item.is_a?(RPG::Armor)
       for i in $game_party.armor_equip_skill[item2.id]
         actor.forget_skill(i)
       end
       unless item.id == 0 || nil
       for i in $game_party.armor_equip_skill[item.id]
         actor = $game_actors[@actor.id]
         actor.learn_skill(i)
       end
       end
     else
       for i in $game_party.armor_equip_skill[item2.id]
         actor.forget_skill(i)
       end     
       end 
     end
     #end of armors
     #equip gain skills end

      #SE
      $game_system.se_play($data_system.equip_se)
      item = @item_window.item
      @actor.equip(@right_window.index, item == nil ? 0 : item.id)
      @right_window.active = true
      @item_window.active = false
      @item_window.index = -1
      @right_window.refresh
      @item_window.refresh
      return
    end
  end
end

And I made this new entry for the second part, named Weapons_Skills, just above Main

Code:
#==================================
# Equip weapons and armors to gain skills... halfassly done by makeamidget
# 11-24-2024 assistance by DerVVulfman
#==================================
# to decide on the skills that will be learnt just go down to where
# you see something along the lines of @weapon_equip_skill[1] = [1,2,3]
# the way it is set up is @weapon_equip_skill[id of weapon] =[skill ids, multiple ones separated by commas]
# example code:   @weapon_equip_skill[4] = [21, 45, 23, 54, 12]
# example code:   @armor_equip_skill[1] = [1,4,6,4,5,6,4,3]
#==================================

class Game_Party
attr_reader :weapon_equip_skill             
attr_reader :armor_equip_skill

alias equip_skill_initialize initialize

def initialize
  equip_skill_initialize
  @weapon_equip_skill = Array.new($data_weapons.size, [])
  @armor_equip_skill = Array.new($data_armors.size, [])
  get_equip_skills
end

def get_equip_skills
  @weapon_equip_skill[48] = [212]



end
end


I only defined one weapon (ID 48) and one skill (212) for now.
As you stated, the line in question is shown below...  

      actor = $game_actors[@actor.id]
      item  = @item_window.item
      item2 = @right_window.item
      #equip gain skills start
      #begining of weapons
      if @right_window.index ==  0
        if item.is_a?(RPG::Weapon)
          for i in $game_party.weapon_equip_skill[item2.id]
            actor.forget_skill(i)
          end
          . . .

Consider that the other portion of Makeamidget's script contains the following:

class Game_Party
  attr_reader :weapon_equip_skill             
  attr_reader :armor_equip_skill

  alias equip_skill_initialize initialize

  def initialize
    equip_skill_initialize
    @weapon_equip_skill = Array.new($data_weapons.size, [])
    @armor_equip_skill = Array.new($data_armors.size, [])
    get_equip_skills
  end

This section creates new values at game start, the @weapon_equip_skill array and the @armor_equip_skill array... and then populates these arrays with the contents in the get_equip_skills method... its version of a configuration page (yuck).  This is needed to be executed at game start.

So a question...  Are you testing your project with a fresh and new game?  Or are you running from an existing save file?  I am guessing the latter, from an existing save that doesn't have these values created.

It has been a while, eh?   When you add new variables that are created solely at game start, you need a fresh game to test them.
(11-24-2024, 04:54 PM)DerVVulfman Wrote: [ -> ]This section creates new values at game start, the @weapon_equip_skill array and the @armor_equip_skill array... and then populates these arrays with the contents in the get_equip_skills method... its version of a configuration page (yuck).  This is needed to be executed at game start.

So a question...  Are you testing your project with a fresh and new game?  Or are you running from an existing save file?  I am guessing the latter, from an existing save that doesn't have these values created.

It has been a while, eh?   When you add new variables that are created solely at game start, you need a fresh game to test them.

Shocked  OH DERP! Yes, I was using an existing game file that I started way back in 2006! (Though I've since saved over it for testing purposes).

I started a new game and the script works!!!! Laughing 

It definitely has been a while since I've had to start a new save to test new script out. I've been doing a ton of graphics asset and map work without really altering anything under the hood.

Thank you so much for patiently helping me, DerVVulfman. And I'm really grateful for the warm welcome you and Zeriab showed me in my introductory post.

I'll try to contribute to the forum in the coming weeks. (But for now, I'll toy around with this new script...and also look into a newer New Game + as it appears that my current New Game + script isn't working anymore. Maybe because of the new variables?

EDIT: So I managed to get New Game+ working (I had to select a different save) and the weapon script failed for that with the same issue (line 712). Seems I really do have to start with a full New Game, haha.