Main Menu
  • Welcome to The RPG Maker Resource Kit.

[Resolved]Syntax Help - Script Posted in RMXP Scripts

Started by themrmystery, February 06, 2009, 09:22:12 PM

0 Members and 1 Guest are viewing this topic.

themrmystery

Hello,

I'm in the process of learning to write RGSS scripts, and I have the basics down, and a pile of resources, however I am having trouble finding/figuring out the syntax needed for two checks I would like to make;

If anyone could help me with the syntax that'd be great!

Checks I would like to make;

1) Check if actor_id has learned skill_id (return true) or 0 for false and 1 for true
2) Change/Add to actor_id 's weapon_set
   
More info: Basically for check 1, I just want a simple syntax for, if Aluxes has learned skill "Cut" (actor_id[1], skill_id[1]) print "yes"

For syntax 2; I'd like know if it's possible to add weapon_sets from more than one class to one actor ... So say Aluxes (actor_id[1]) could access $data_classes.weapon_set[1,2]

or something like that


Thanks!
I'll post the finished script once I have this figured out, the first one's always the toughest, but the most rewarding!

modern algebra

For 1, $game_actors[actor_id].skill_learn? (skill_id)

For 2) it's not particulary easy by default. Because it's stored in a $data_ class, information is reset everytime the game is exited. So you just need to save what class weapon sets the actor an have, probably best if you do that in Game_Actor, and then you would need to alter the way equippable? checks to include alterior classes. The best way to do that would probably be to alias the method, then for each class ID that is available to the actor, change @class_id and send it through ~ if it returns true for any of them, then return true. Else return false.

themrmystery

#2
I apologize in the forefront for being a beginner but;

As for check #1; it works fine, but I've been trying:

for actor in $game_party.actors
      print actor.skill_learn? (28)
    end


and I guess my question is, will that return "true" if ANYONE in my party knows the skill? OR only true for the individual actor that knows it?

Basically, I'm trying to turn they syntax Modern Algebra gave me:

$game_actors[actor_id].skill_learn? (skill_id)

into:

$game_actors[@actor_id].skill_learn? (skill_id)

where @actor_id is whichever actor the skill_learn? returns true for

So if multiple actor_id's have learned they skill, they all return true for that actor, this way i don't have to add code to check each individual actor id!

Thanks!


Edit: I solved this, the above listed code snippet, worked, I just thought it didn't at first!

themrmystery

I feel, like a fool, I actual made a code snippet that works! Haha.

Onward to figuring out #2!

themrmystery

I've been reading your alias the method tutorial on http://rmrk.net/index.php?topic=25550.0 and I'm having a bit of trouble.

When I enter my code into a script (free-standing from the game_actor) it tells me equippable? is an undefined method? even though it's defined in game_actor?

How do I rename the oldmethod to my newmethod, without having to insert my script into game_actor?

def initialize
    alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
    # If weapon
    if item.is_a?(RPG::Weapon)
      # If included among equippable weapons in current class
      if $data_classes[@class_id].weapon_set.include?(item.id)
        return true
      end
    end
    return false
    mystery_multi_weapon_sets(item)
  end
end


And yes I realize this code should essentially do nothing, as it just defines the newmethod to do exactly what the old method does, but I'm just trying to get one step down at a time =)

Thanks again!

modern algebra

You can put it in a new slot, but you still need to define what class it is going in.  There are also a couple syntax errors you got going in there. I do not know what you want to do with initialize, so I removed it entirely. You probably will need it for creating your extra class IDs, but for now I assume we just want to work with equippable? So what you have should be:


class Game_Actor
   
  alias mystery_multi_weapon_sets equippable?
  def equippable?(item)
    # If weapon
    if item.is_a?(RPG::Weapon)
      # If included among equippable weapons in current class
      if $data_classes[@class_id].weapon_set.include?(item.id)
        return true
      end
    end
    return false
    mystery_multi_weapon_sets(item)
  end
end


As the code currently is, it will alway return false for armors, and I know this is not intended to be a final version so it doesn't matter but I thought I would point it out anyway.

themrmystery

Yea, I was just using def initialize to stop the game from crashing immediately, and so I could call the script from an Action Button event, to check my if / else options with print text messages, to make sure they return the right true / false readings =)

I think I just figured something else out... I could set my class to: class Use_Weapons < Game_Actor

thanks for the reply though, this first script is taking so long to write, but my next script will be far easier (i hope)

modern algebra

You can set your class to Use_Actors < Game_Actor and your class would inherit everything from Game_Actor, but you coud never use it unless you replaced all the current Game_Actor objects with Use_Actors objects. For your purpose, it is much better to work with Game_Actor than a subclass.

themrmystery

Here's what I have so far, and it doesn't work, the game plays normally, but what I want to happen, doesn't:

class Game_Actor

  alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
    # If weapon
    if item.is_a?(RPG::Weapon)
      # If included among equippable weapons in current class
      if $data_classes[@class_id].weapon_set.include?(item.id)
        return true
      for actor in $game_party.actors
        if actor.skill_learn? (28) == true
          if $data_classes[13].weapon_set.include?(item.id)
            return true
          end
        end
      end
      end
    end
    # If armor
    if item.is_a?(RPG::Armor)
      # If included among equippable armor in current class
      if $data_classes[@class_id].armor_set.include?(item.id)
        return true
      end
    end
    return false
    mystery_multi_weapon_sets(item)
  end
end


Which basically says, if the actor knows skill 28, and the weapon is in this other classes weapon_set, the actor should get to equip that weapon to?

EDIT: changed class Use_Multi_Weapons < Game_Actor to class Game_Actor as per above post

modern algebra

Well, you have it within the conditional branch that checks the weapon set of the class ID, which is only ever run if the weapon is already in the current website, and then you return true right before your code which means it would never run.

It might be better to have your method like this ~ report results back to me


I don't like the way you are doing it with checking actor skill learned. It would be better I think to store what additional weapon sets you have in an array, but I will do it the way you are trying. I'm doing this blind so I may make some errors. Also, why are you checking every actor? You want to be able to equip this as long as any actor has the skill or only if this actor has the skill.


class Game_Actor

  alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
     eqp_check = mystery_multi_weapon_sets (item)
     return true if eqp_check
     if item.is_a?(RPG::Weapon)
      real_class = @class_id
      # If proficiency learned
      if skill_learn? (28)
        @class_id = 13
        eqp_check = mystery_multi_weapon_sets (item)
        @class_id = real_class
      end
    end
    return eqp_check
  end
end

themrmystery

#10
Hey, thanks for the code snippet, it still doesn't work, but maybe I'll be able to figure something out with it, and get closer:

What I'm trying to accomplish:

You start the game, and pick say class of "Paladin" you know how to use swords and shields. Later in the game, you will be able to learn a skill such as "Spear Use" and after learning the feat, you as a Paladin can now use a generic class called "Spear Weapons" (id 13).  So now as a Paladin (with the skill of "Spear Use") you can now use both weapons from your Paladin Class (id 1, lets say) and the Spear class (id 13)... and the skill is id 28

Edit: added comments:

In reply to the array, yes, ideally I'd like to setup a more advanced version of the code, with much easier editing, but for now, I'd just like to make it work for one instance, and then have a starting point.

Going to explain it in more detail in the following example:

First, assumptions; 1) Skills are not automatically gained, they are chosen, or purchased.
2) Some weapons are not able to be used by ANY of the original classes.

Goals:

Party is composed of Guy1 (actor_id=1) Guy2 (actor_id=2) Girl1 (actor_id=3) and finally Girl2 (actor_id=4).
Classes are as follows fighter (class_id=1) lancer (class_id=2) mage (class_id=3) and cleric (class_id=4)

Standard Weapons Guy1/Fighter = Swords/Axes, Guy2/Lancer = Spears, Girl1/Mage = Rods, Girl2/Cleric = Holy Symbols

Weapon Classes = Bows (class_id=5), Hammers (class_id=6), 2-Handed Weapons (class_id=7)

Now say Girl2/Cleric wanted to remain a cleric, and continue to level up as a cleric, and thus continue receiving cleric skills, but she wanted to use a bow... At say level 5 she could take a skill called = Weapon Use: Bows (skill_id=1)

Now as a Cleric she can use weapon_set(class_id=4) and weapon_set(class_id=5)

Guy1 would like to start using 2 handed weapons, and still be a fighter, so he takes the skill = Weapon Use: 2-handed weapons (skill_id=2)

Now keeping on his track of becoming the fighter (without actually switching his class) he can now use weapon_set from both (class_id=[1,7])


Hope this clears up any confusing as to what the script is attempting to do.

Thanks again, going to stay up a bit longer and try a couple variations.


Current status: Game runs fine with the script, however when the skill is learned, the weapon relating to the class are still not usable by the other class.

themrmystery

Right now, I'd be happy with a script that simply makes say class_id=1 use class_id=2 weapon sets...

As in... You're a Fighter, but you can't use any of the weapons listed in fighter, and it forces you to use the weapons of the Lancer.  I've tried to make a simply script to just do this, and even that won't work...

I'm at a loss for tonight, and I'm pretty tired, maybe something will become clear in the morning!

Thanks for the help, I really hope this comes together =)

modern algebra

It looks like the problem is in Window_EquipItem. The way it makes the list of items to include is by checking the weapon set directly, not the equippable? method. Take a look at that and tell me if you encounter any trouble

themrmystery

Current Script, with list/description of problems:

Problem 1) ALL weapons display TWICE in the equip list, for equipping a new item:
[spoiler][/spoiler]

Problem 2) After selecting to learn the skill with one actor, ALL actors from ALL classes can now use those weapons: Note: The double display does disappear?
[spoiler][/spoiler]

Here is the code in entirety
[spoiler]class Game_Actor

  alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
     eqp_check = mystery_multi_weapon_sets (item)
     return true if eqp_check
     if item.is_a?(RPG::Weapon)
      real_class = @class_id
      # If proficiency learned
      if skill_learn? (28)
        @class_id = 13
        eqp_check = mystery_multi_weapon_sets (item)
        @class_id = real_class
      end
    end
    return eqp_check
  end
end

class Window_EquipItem < Window_Selectable
 
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    # Add equippable weapons
    if @equip_type == 0
      for actor in $game_party.actors
        if actor.skill_learn? (28)
          weapon_set = $data_classes[13].weapon_set and $data_classes[@actor.class_id].weapon_set
        else
          weapon_set = $data_classes[@actor.class_id].weapon_set
        end
          for i in 1...$data_weapons.size
            if $game_party.weapon_number(i) > 0 and weapon_set.include?(i)
            @data.push($data_weapons[i])
            end
          end
      end
    end
    # Add equippable armor
    if @equip_type != 0
      armor_set = $data_classes[@actor.class_id].armor_set
      for i in 1...$data_armors.size
        if $game_party.armor_number(i) > 0 and armor_set.include?(i)
          if $data_armors[i].kind == @equip_type-1
            @data.push($data_armors[i])
          end
        end
      end
    end
    # Add blank page
    @data.push(nil)
    # Make a bit map and draw all items
    @item_max = @data.size
    self.contents = Bitmap.new(width - 32, row_max * 32)
    for i in 0...@item_max-1
      draw_item(i)
    end
  end
end

[/spoiler]

modern algebra

The reason all actors can use all skills is because you have this:

for actor in $game_party.actors

What that means is that it does the following code for all actors, and if one of them has the skill it returns true - since one actor has the skill, it will always return true for every actor, because that is all you are requiring of it.

This is also the reason you are getting double items. You're adding things to @data that have already been added because you are doing it twice - you have that part within the for loop.

Further, what is this check that you're doing? Is it not equivalent to checking if the actor could equip somehting, and if so, that is something you do already in the equippable? method of Game_Actor. Why not use it instead of doing the extra work?

This is probably not what I would do if I were writing the script, but I think the following code is true to your design and should accomplish what you set out to do:


class Game_Actor

  alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
     eqp_check = mystery_multi_weapon_sets (item)
     return true if eqp_check
     if item.is_a?(RPG::Weapon)
      real_class = @class_id
      # If proficiency learned
      if skill_learn? (28)
        @class_id = 2
        eqp_check = mystery_multi_weapon_sets (item)
        @class_id = real_class
      end
    end
    return eqp_check
  end
end

class Window_EquipItem
 
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    # Add equippable weapons
    if @equip_type == 0
      for i in 1...$data_weapons.size
        if $game_party.weapon_number(i) > 0 && @actor.equippable? ($data_weapons[i])
          @data.push($data_weapons[i])
        end
      end
    end
    # Add equippable armor
    if @equip_type != 0
      armor_set = $data_classes[@actor.class_id].armor_set
      for i in 1...$data_armors.size
        if $game_party.armor_number(i) > 0 and armor_set.include?(i)
          if $data_armors[i].kind == @equip_type-1
            @data.push($data_armors[i])
          end
        end
      end
    end
    # Add blank page
    @data.push(nil)
    # Make a bit map and draw all items
    @item_max = @data.size
    self.contents = Bitmap.new(width - 32, row_max * 32)
    for i in 0...@item_max-1
      draw_item(i)
    end
  end
end

themrmystery

Modern Algebra, thank you so much!  And yes, I'll admit the script is probably not setup in the best of ways, and will not be the easiest or cleanest script, but it works how it's supposed to!

Being my first attempt at any RGSS scripting, this has been a great learning tool, and hopefully now that it works, I can make it better/easier to edit, and update for multiple skills/classes! Although, I really owe all the heavy lifting to you!

Thanks again, if I have any new problems, or need some more help with it, I'll definitely post in here again, and cross my fingers you help again =)

~Mystery

modern algebra

I'll try my best. If it weren't for someone on this forum, I probably would have quit scripting long ago, and he has my gratitude for all the fun I've had with it since. Anyway, I'm always happy to help when I can, and you did a lot of the work here.

themrmystery

Do you think you could give me a quick example of how to use a has or an array or hash:  This is what I'm trying, I just don't know the proper way to make the game pull the 28 for the skill_learn? (x) and the 13 for the @class_id = y

Don't know which is easier, but any help would be appreciated, would make editing it so much easier.

module Multi_Item_Sets
  #--------------------------------------------------------------------
  #  Multi_Item_Sets = { skill_id => class_id },..}
  #--------------------------------------------------------------------

Multi_Item_Sets = { 28 => 13, 11 => 12 }

end

class Game_Actor

  alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
    mw = Multi_Item_Sets
     eqp_check = mystery_multi_weapon_sets (item)
     return true if eqp_check
     if item.is_a?(RPG::Weapon)
      real_class = @class_id
      # If proficiency learned
      if skill_learn? (mw::Multi_Item_Sets.keys.includes?(skill))
        @class_id = mw::Multi_Item_Sets.values
        eqp_check = mystery_multi_weapon_sets (item)
        @class_id = real_class
      end
    end
    return eqp_check
  end
end

themrmystery

Tried this too, but I really don't know what I'm doing, unfortunately:

module Multi_Item_Sets

  Multi_Item_Sets = [[28,13], [11,12]]
end

class Game_Actor < Game_Battler

  alias mystery_multi_weapon_sets equippable?

  def equippable?(item)
    mw = Multi_Item_Sets
     eqp_check = mystery_multi_weapon_sets (item)
     return true if eqp_check
    if item.is_a?(RPG::Weapon)
      real_class = @class_id
      # If proficiency learned
      for i in 0...Multi_Item_Sets
          if skill_learn? (Multi_Items_Sets[i][0])
            @class_id = Multi_Items_Sets[i][0], 1
            @class_id = Multi_Item_Sets[i][1], 1
            id = Multi_Item_Sets[i][1]
            eqp_check = mystery_multi_weapon_sets (item)
            @class_id = real_class
          end
      end
    end
    return eqp_check
  end
end

themrmystery

#19
Found an easier question to ask... I think:

I've decided, for my lack of knowledge, using 2 arrays might be easier?

skill_id_array = [28, 11]
class_id_array = [13, 12]

how would I write a code such

if skill_learn? = (skill_id_array[x])
@class_id = class_id_array[x]


where x, is the place of the line.... so basically if:

x returns true for skill_learn? on 28 and false on 11
x will only print 13 for class_id

but if x returns true for both 28 and 11
then class_id will have both 13 and 12

Thanks

modern algebra

#20
I think you have the right idea with using two arrays instead of one hash, and I think they should also be made inside the class rather than a module. So, you could easily make them local variables initialized in equippable?  If you are going to have a lot of these types of skills, I would recommend something different as having a lot could make the runtime for the equippable? method very long, but if you only have a few than this will be fine I should think.

What you want to do is essentially run through each passive skill and do the check on it. There are two things that I think would be useful toward this purpose:

The for loop:

for i in 0...skill_id_array.size
  # What happens
end

What this will do is loop through what happens skill_id_array.size times with i counting up. So, on the first run through, i is 0 and on the second, i is 1, and so on.

Thus, on the first loop, skill_id_array[i] would return 28 and class_id_array[i] will return 13,
and on the second, skill_id_array[i] would return 11 and class_id_array[i] will return 12.


I think you can see how this would be useful for your purposes.

Another thing that might be useful to learn is: that when you have two booleans (true/false), a and b, then you can perform this operation:

a | b

This will return true if a, b, or both are true and return false only if both are false. Thus,

            eqp_check |= mystery_multi_weapon_sets (item)

will be false unless it returns true once. Once one of the checks succeed, it will remain true. It is a good way to check if something is true. A better way might be just to return true the first time it is true.

That might all be confusing. Just post again if I am unclear.


Also, there shouldn't be an equal sign between skill_learn? and its arguments

themrmystery

Wow, I was so close, hehe, I think I'm getting the hang of this, thanks again, it works like a beauty...

Now it's time to edit the rest of the code, write in some comments, and test the whole thing, for weapons and armor!!!

themrmystery

Well, I thought it worked, it seemed to for a moment, but I got into actually implementing it, and came across a bug/error...

Problem: Using the current version of the code, it will only allow for one weapon proficiency to be learned at a time, basically, the lowest skill_id in the array wins, for example;

Example:

If "Sword Use" is skill_id = 35 and class_id = 47
If "Spear Use" is skill_id = 36 and class_id = 48
If "Axe Use" is skill_id = 37 and class_id = 49
If "Bow Use" is skill_id = 38 and class_id = 50

So in the below code, where:

      for i in 0...skill_id_array.size
        if skill_learn? (skill_id_array[i])
          @class_id = class_id_array[i]


It is returning the first skill_id found true, and then assigning that class_id, and then not rechecking for all the others, what I need is for it to return all values of (i) that are true, and run them through the @class_id ... is this possible?

class Game_Actor

  alias mystery_multi_item_sets equippable?

  def equippable?(item)

    #---- Start Configuration ----
    skill_id_array = [50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35]
    class_id_array = [39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 43, 42, 41, 40] 
    #---- End Configuration ------
   
     eqp_check |= mystery_multi_item_sets (item)
     return true if eqp_check
     if item.is_a?(RPG::Weapon)
      real_class = @class_id
      # If weapon proficiency learned
      for i in 0...skill_id_array.size
        if skill_learn? (skill_id_array[i])
          @class_id = class_id_array[i]
          eqp_check = mystery_multi_item_sets (item)
          @class_id = real_class
        end
      end
    end
    return eqp_check
  end
end


modern algebra

I don't know what you mean. I think that the code does what you want for the most part: you do go wrong at one point however (two actually, where you do the initial check, eqp_check might as well be =, not |=, but that is not what is causing the error). I will try to explain what is happening with your for loop:


      # If weapon proficiency learned
      for i in 0...skill_id_array.size
        if skill_learn? (skill_id_array[i])
          @class_id = class_id_array[i]
          eqp_check = mystery_multi_item_sets (item)
          @class_id = real_class
        end
      end


This code is almost entirely correct in that it will do everything you want, but you are not preserving when it returns true. It will always check every skill ID in the array and run the check for all skills that the actor has learned. What is problematic with this code is:

eqp_check = mystery_multi_item_sets (item)

And this is because, let's say your skill array is [12, 13] and your class array is [1, 2]

The actor has both these skills and let's say that the check for class 1 will return true (IE class 1 includes this weapon in its weapon set) while class 2 will return false (the weapon is not in class 2's weapon set).

The code being run is essentially this:

        # First run of the loop
        if skill_learn? (12) # true
          @class_id = 1 # class_id_array[0]
          eqp_check = mystery_multi_item_sets (item) # True
          @class_id = real_class
        end
        # second run of the loop
        if skill_learn? (13) # true
          @class_id = 2 # class_id_array[1]
          eqp_check = mystery_multi_item_sets (item) # False
          @class_id = real_class
        end


Do you see what's happening. eqp_check is overwritten by the second run of the loop. SO, even though the actor has the skill that allows him to use this weapon, he will not be able to because eqp_check is overwritten to false. This is why I suggested using the |= instead of the =, but that actually is not the most efficient way. Either of the two below codes should work.

Option 1

      # If weapon proficiency learned
      for i in 0...skill_id_array.size
        if skill_learn? (skill_id_array[i])
          @class_id = class_id_array[i]
          eqp_check |= mystery_multi_item_sets (item)
          @class_id = real_class
        end
      end


Option 2

      # If weapon proficiency learned
      for i in 0...skill_id_array.size
        if skill_learn? (skill_id_array[i])
          @class_id = class_id_array[i]
          eqp_check = mystery_multi_item_sets (item)
          @class_id = real_class
          return true if eqp_check
        end
      end


Option 2 is better, because all you need for this script is for the weapon to be in one of the weapon sets. Because of that, once you get it to return true once, that is enough and you can return that the item is equippable. This way, you can avoid running through all the other skills because they are irrelevant. Either ought to work though.

Leave the rest of the method the way it is, but when you initialize eqp_check (before the for loop), you should use =, not |=. I'm sorry if I confused you earlier, but when I talked about | I meant for tackling option 1, not for initializing eqp_check.

themrmystery

Ahh, I see now, yea I put the |= in the wrong spot, I didn't even notice there was two identical locations of that line, sigh... sorry about that, hehe.

Thanks though, I just tested it with all 11 different weapon sets, and it works!