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!
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.
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!
I feel, like a fool, I actual made a code snippet that works! Haha.
Onward to figuring out #2!
I've been reading your alias the method tutorial on http://rmrk.net/index.php?topic=25550.0 (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!
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.
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)
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.
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
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
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.
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 =)
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
Current Script, with list/description of problems:
Problem 1) ALL weapons display TWICE in the equip list, for equipping a new item:
[spoiler](https://rmrk.net/proxy.php?request=http%3A%2F%2Fthemrmystery.com%2FRMXP%2Fbug1.jpg&hash=67c66381e7785304562184ba45c6e3a17fc1073e)[/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](https://rmrk.net/proxy.php?request=http%3A%2F%2Fthemrmystery.com%2FRMXP%2Fbug2.jpg&hash=96e9224f709375ab661859e84589f39cd4a31618)(https://rmrk.net/proxy.php?request=http%3A%2F%2Fthemrmystery.com%2FRMXP%2Fbug3.jpg&hash=39e2b751661ad2cdea5371b346cb774de62c1ff4)[/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]
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
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
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.
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
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
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
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
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!!!
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
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.
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!
Great to hear.
Now, this is not at all necessary, but I think if you do it you will gain a useful strategy for making other scripts. With this script, you can run through 11 loops of the code every time you check if something is equippable, and most of the time that is processing data that is irrelevant (ie. checking for skills that the actor does not have).
Now, this is not necssarily a better way, but I want you to think of how you could make it so that the extra class IDs available to the actors are saved in the actor, so you would only have to check weapon sets of proficiencies that you have available. Again, this is not a necessary exercise, but I think it is a useful one if you have the time. You would want to look at the Game_Actor methods learn_skill and forget_skill.
I will look into it, although I'm trying to work on step 2: or v1.1
Which requires me to merge/add compatibility to my script with Multi-Slot Equipment by Guillaume777.
I tried using the same format, just switching variables to make it check for armor_set, so I could make armor class proficiencies... however with multi-slot, the weapons work fine, because they all can go either left/right hand, and they all can show up in both weapon spots... however, with armors, implementing my script makes the boots/gloves/rings/amulets/belts/cloaks/armor ... all of which are new equipments slots, now allow for you to equip ANY of them, in the ALL armor based slots
I'm ignoring it for now, as I only had 2 armor class proficiencies, and they were not really necessary, but eventually I'll look into making it work right