I'm working on something right now that is a thingamabob that actors can have (and maybe some NPCs or enemies), that is basically a meta skill container that has the following attributes
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills/options from main
attr_accessor :description # help window description
Essentially it's a container for multiple "single action" skills (like fire, mass fire, ice, greater ice, etc.), but it also has levels and experience points, allowing players to buy up levels in it. The multiplier is the cost multiplier for buying each level. For example, learning "weapons" might have a much higher cost than "swords", because it includes swords.
The mess I have so far is as follows, and I'm aware it won't work. I'd like some help fixing the most obvious mistakes and get a clunky version working before I mess with it further. One of the problems I'm foreseeing is not knowing how to subordinate it to actors, so that each actor's version is unique to them.
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
super()
setup(tech_id)
end
#--------------------------------------------------------------------------
# * Setup
# tech_id : tech ID
#--------------------------------------------------------------------------
def setup(tech_id)
tech = $game_technique[tech_id] #this isn't going to work - needs actor
@tech_id = tech_id
@name = tech.name
@level = tech.initial_level
@exp_list = Array.new(101)
make_exp_list
@exp = @exp_list[@level]
@skills = []
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def multiplier
return @multiplier
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
tech = $data_technique[@tech_id]
@exp_list[1] = 0
for i in 2..100
if i > tech.final_level
@exp_list[i] = 0
else
@exp_list[i] = @tech.multiplier *(i * 0.5) * (i + 1)
end
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 99999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
#--------------------------------------------------------------------------
# * Change Name #comes in handy when creating custom techniques
# name : new name
#--------------------------------------------------------------------------
def name=(name)
@name = name
end
#--------------------------------------------------------------------------
# * Change Description #comes in handy when creating custom techniques
# description : new description
#--------------------------------------------------------------------------
def description=(description)
@description = description
end
end
I envision calling parts of it by saying something like
p $game_actors[11].tech[4].name
p $game_actors[11].tech[4].level
with
p $game_actors[11].tech[4]
looking similar but smaller than what is normally spat out when you type something like
and have yet to figure out the window interface, since I originally came up with this idea with a mouse in mind and clicking on an expand icon for details in a list, similar to a text based linear skill tree or list. For now, I just want the thing to exist, and worry about interfacing and windows later.
I've revised some stuff as seen below, it still doesn't work, but I've been thinking of it sort of like a hash. I wanted some stock techniques that could be built into the system, but then you would have the option of developing your own. While that's the main point - inventing your own class abilities, the idea that some basic functions exist seems paramount.
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Stock Techniques
# tech_id : tech ID
#--------------------------------------------------------------------------
$game_technique[0].name = "Endurance" # Hit Points
$game_technique[1].name = "Dodge" # Dodge
$game_technique[2].name = "Melee" # Attack
$game_technique[3].name = "Willforce" # Spell Points
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
super()
setup(tech_id)
end
#--------------------------------------------------------------------------
# * Setup
# tech_id : tech ID
#--------------------------------------------------------------------------
def setup(tech_id)
tech = $game_technique[tech_id] #this isn't going to work - needs actor
@tech_id = tech_id
@name = tech.name
@level = 0
@multiplier = multiplier
@physical = false
@magical = false
@description = ""
@exp_list = Array.new(101)
make_exp_list
@exp = @exp_list[@level]
@skills = []
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def multiplier
#i = self.id
#n = 0 + (tech[i].skill[1].power + tech[i].skill[2].power * 0.1)
#n = 0 + skill[1].power + skill[2].power + skill[3].power
#return n
return @multiplier
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
tech = $data_technique[@tech_id]
@exp_list[1] = 0
for i in 2..100
if i > tech.final_level
@exp_list[i] = 0
else
@exp_list[i] = @tech.multiplier *(i * 0.5) * (i + 1)
end
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 99999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
#--------------------------------------------------------------------------
# * Change Name #comes in handy when creating custom techniques
# name : new name
#--------------------------------------------------------------------------
def name=(name)
@name = name
end
#--------------------------------------------------------------------------
# * Change Description #comes in handy when creating custom techniques
# description : new description
#--------------------------------------------------------------------------
def description=(description)
@description = description
end
end
Well, I did some testing, and ended up testing it with a hash in the script editor...
$game_technique = {}
$game_technique[0] = ["Endurance", 1, 0, true, false, 0, [1, 2], "Hit Point Bonus"]
and was able to use an event to produce answers to all parts of my hash.
p $game_technique[0][0]
p $game_technique[0][1]
p $game_technique[0][2]
p $game_technique[0][3]
p $game_technique[0][4]
p $game_technique[0][5]
p $game_technique[0][6][0]
p $game_technique[0][6][1]
p $game_technique[0][7]
My concern is 1. getting the info inside the game actors, and 2. doing this all preferably without a hash (which I don't currently know how to do).
If you want to get these stored into the actors, you obviously are going to have to edit class Actor. Make an array that stores the ID numbers. If you're going to define every skill at each ID value, use 'case'.
Of course, I can't think like you so I'm just throwing out ideas.
-waits for someone to start bashing about your programming-
I was beginning to think id have to stick it in actor about 2-3am this morning, while mulling over this message to myself in my scrap notes:
$game_actor[n].tech[m][a][b][c]
n = actor number
m = technique number
a = technique attribute
b = skill number (assumes a = technique's "skill list")
c = skill attribute (assumes b = skill number)
I'm thinking skill list should probably be either the 1st, the second, or the last number, to avoid confusion. If it's the first, it will be zero, $game_actor[n].tech[m][0][skill_id][skill_attribute], but as a matter of form, perhaps name should come first.
if I prided myself in my programming skills I don't think I would be so quick to ask for help on this part of the project. Actually, statements like that are why I post so seldom in this forum.
This is similar to the goal I have for my script (VX), I currently haven't updated the topic recently but I have made progress on fulfilling the ultimate goal for it. You may wish to take a look at the non-updated script it might give you a few ideas on how to manage skills.
Script (http://forum.chaos-project.com/index.php/topic,9841)
Quote from: Twb6543 on October 07, 2011, 10:45:52 am
This is similar to the goal I have for my script (VX), I currently haven't updated the topic recently but I have made progress on fulfilling the ultimate goal for it. You may wish to take a look at the non-updated script it might give you a few ideas on how to manage skills.
Script (http://forum.chaos-project.com/index.php/topic,9841)
while the script structures are different in VX, I did see some similarities for sure. We both have level at around 100 and have experience ranges and options. Right now I'm trying to figure out how to create both standardized "stock" techniques plus open, editable techniques. While I only envisioned each actor having between 2 and 4 main techniques with a lot of overlap (e.g. dodge) bringing each to about 5-10, the total number of techniques in the game was probably under 20.
I'm pretty certain now I should make the the techniques a part of the actor class, in some shape or form, rather than creating a new $data_techniques file.
class Game_Actor
attr_accessor :techniques
alias tech_init initialize(id)
def initialize(id)
@techniques = Game_Technique.new
tech_init(id)
end
end
I can't remember the exact args that go with Game_Actor, but you get the idea.
I've played around with your script a bit. I did have to make a few edits to "Game_Techniques" because of the errors in initializing.
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Stock Techniques
# tech_id : tech ID
#--------------------------------------------------------------------------
def techniques_data(id)
# return [name, mult, exp, physical?, magical?, level, skills, desc]
case id
when 0 then return ["Endurance", 1, 0, true, false, 0, [1, 2], "Hit Point Bonus"]
end
end
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
tech = techniques_data(tech_id)
@tech_id = tech_id
@name = tech[0]
@level = tech[5]
@multiplier = tech[1]
@physical = tech[3]
@magical = tech[4]
@description = tech[7]
@exp_list = Array.new(101)
make_exp_list
@exp = tech[2]
@skills = []
tech[6].each{|id|
@skills.push(id)
}
@skills.sort!
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def multiplier
#i = self.id
#n = 0 + (tech[i].skill[1].power + tech[i].skill[2].power * 0.1)
#n = 0 + skill[1].power + skill[2].power + skill[3].power
#return n
return @multiplier
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
@exp_list[1] = 0
for i in 2..100
@exp_list[i] = @exp_list[i-1] + (@multiplier * (i / 2) * (i + 1))
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 99999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
end
#===============================================================================
# Class Game_Actor
#===============================================================================
class Game_Actor < Game_Battler
attr_accessor :techniques
alias initialize_techniques initialize
def initialize(actor_id)
@techniques = []
initialize_techniques(actor_id)
end
alias setup_techniques setup
def setup(actor_id)
setup_techniques(actor_id)
# How will you determine what techniques the character starts with?
end
# Adds the specified technique to the @techniques array
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
end
end
Keep me updated on what you want fixed.
Quote from: KK20 on October 07, 2011, 03:15:54 pm
I've played around with your script a bit. I did have to make a few edits to "Game_Techniques" because of the errors in initializing. #==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Stock Techniques
# tech_id : tech ID
#--------------------------------------------------------------------------
def techniques_data(id)
# return [name, mult, exp, physical?, magical?, level, skills, desc]
case id
when 0 then return ["Endurance", 1, 0, true, false, 0, [1, 2], "Hit Point Bonus"]
end
end
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
tech = techniques_data(tech_id)
@tech_id = tech_id
@name = tech[0]
@level = tech[5]
@multiplier = tech[1]
@physical = tech[3]
@magical = tech[4]
@description = tech[7]
@exp_list = Array.new(101)
make_exp_list
@exp = tech[2]
@skills = []
tech[6].each{|id|
@skills.push(id)
}
@skills.sort!
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def multiplier
#i = self.id
#n = 0 + (tech[i].skill[1].power + tech[i].skill[2].power * 0.1)
#n = 0 + skill[1].power + skill[2].power + skill[3].power
#return n
return @multiplier
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
@exp_list[1] = 0
for i in 2..100
@exp_list[i] = @exp_list[i-1] + (@multiplier * (i / 2) * (i + 1))
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 99999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
end
#===============================================================================
# Class Game_Actor
#===============================================================================
class Game_Actor < Game_Battler
attr_accessor :techniques
alias initialize_techniques initialize
def initialize(actor_id)
@techniques = []
initialize_techniques(actor_id)
end
alias setup_techniques setup
def setup(actor_id)
setup_techniques(actor_id)
# How will you determine what techniques the character starts with?
end
# Adds the specified technique to the @techniques array
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
end
end
Keep me updated on what you want fixed.
That's F*ing brilliant actually. My main concern is whether the skill list should be id=1 or id=some other number. In your version, likely based on my hash, you have it as 6, with description as 7. I guess 0 should be name because that makes the most sense, but I'm beginning to think skills should be "1", because there's a lot of derived values after that.
in order, its basically skills.power added together = multiplier, then multiplier determines experience chart, then experience chart determines level. the other attributes - magic/physical/description are useful but not critical. I don't think the computer cares which order they appear in, but if sorted by a number, I'm guessing
?: ID Number
0: name
1: skills []
2: multiplier
3: experience total
4: level
5/6/7: magic/physical/description
When calling back the data for your techniques (name, skills, level, exp, etc), it doesn't have to be values in an array. What I mean is, taking the edit I made, you don't have to go $game_actors[1].techniques[0][0] to get the name (actually that'd cause an error). You just use $game_actors[1].techniques[0].name and "Endurance" should be the result.
Because of that, it doesn't matter how you set up your technique data. Granted, it is preferable to order your values based on importance, but it's not necessary.
Also, I added in class "Game_Actors" a method called 'add_tech(tech_id)'. If you do a script call like $game_actors[1].add_tech(0), it will add the technique with the ID value of 0 (Endurance in this case). @tech_id will equal parameter tech_id, and does not need to be part of your setup array. It can be called the same way as I stated at the top of this post.
What's next? :naughty:
Quote from: KK20 on October 08, 2011, 12:51:57 am
When calling back the data for your techniques (name, skills, level, exp, etc), it doesn't have to be values in an array. What I mean is, taking the edit I made, you don't have to go $game_actors[1].techniques[0][0] to get the name (actually that'd cause an error). You just use $game_actors[1].techniques[0].name and "Endurance" should be the result.
Because of that, it doesn't matter how you set up your technique data. Granted, it is preferable to order your values based on importance, but it's not necessary.
Also, I added in class "Game_Actors" a method called 'add_tech(tech_id)'. If you do a script call like $game_actors[1].add_tech(0), it will add the technique with the ID value of 0 (Endurance in this case). @tech_id will equal parameter tech_id, and does not need to be part of your setup array. It can be called the same way as I stated at the top of this post.
What's next? :naughty:
this:
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def multiplier
for i in 0..tech.skills.length
n = 0 + (tech.skills[i].power * 0.1)
end
return n
end
clearly doesn't work but I hope it illustrates enough to be fixed. Basically add up all the technique's skills' power values together and divide by 10. I basically suck at for loops with gaps. like if I had an array that pulled from a list of 26 variables (a..z), and the list was called my_variables, and my array was something like my_array = [a,m,x], I don't know how to add a + m + x , without adding the rest of the alphabet, or literally typing my_array[a] + my_array[m] + my_array
- ... which means if I wanted to add b, or n, or get rid of x, I would be screwed.
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Stock Techniques
# tech_id : tech ID
#--------------------------------------------------------------------------
def techniques_data(id)
# return [name, mult, exp, physical?, magical?, level, skills, desc]
case id
when 0 then return ["Endurance", 1, 0, true, false, 0, [1, 2], "Hit Point Bonus"]
end
end
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
tech = techniques_data(tech_id)
@tech_id = tech_id
@name = tech[0]
@level = tech[5]
@physical = tech[3]
@magical = tech[4]
@description = tech[7]
@skills = []
tech[6].each{|id|
@skills.push(id)
}
@skills.sort!
@multiplier = get_multi
@exp_list = Array.new(101)
make_exp_list
@exp = tech[2]
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def get_multi
m = 0
@skills.each{|i|
m += $data_skills[i].power.abs
}
return m/10
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
@exp_list[1] = 0
for i in 2..100
@exp_list[i] = @exp_list[i-1] + (@multiplier * (i / 2) * (i + 1))
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 99999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
end
#===============================================================================
# class Game_Actor
#===============================================================================
class Game_Actor < Game_Battler
attr_accessor :techniques
alias initialize_techniques initialize
def initialize(actor_id)
@techniques = []
initialize_techniques(actor_id)
end
alias setup_techniques setup
def setup(actor_id)
setup_techniques(actor_id)
# How will you determine what techniques the character starts with?
end
# Adds the specified technique to the @techniques array
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
end
end
I had to change the method name 'def multiplier' to 'def get_multi'. It is entirely possible to just move the contents of that method and put it into 'def initialize' but I wasn't sure if you wanted to, say, add more skills into the technique later on. Tested with Heal and Greater Heal (powers of 150 and 300) and it returned 45.
Also had to shift things around a bit in 'def initialize'.
Here's a happy screenshot showing pretty much what I hoped would happen if the script started working
(http://img708.imageshack.us/img708/3567/techniquesn.png)
I'm especially impressed that the experience table exists. I haven't tested leveling the technique yet, or seeing if two characters can have the same technique, but so far, it looks great.
Quote from: KK20 on October 08, 2011, 02:10:28 pm
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Stock Techniques
# tech_id : tech ID
#--------------------------------------------------------------------------
def techniques_data(id)
# return [name, mult, exp, physical?, magical?, level, skills, desc]
case id
when 0 then return ["Endurance", 1, 0, true, false, 0, [1, 2], "Hit Point Bonus"]
end
end
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
tech = techniques_data(tech_id)
@tech_id = tech_id
@name = tech[0]
@level = tech[5]
@physical = tech[3]
@magical = tech[4]
@description = tech[7]
@skills = []
tech[6].each{|id|
@skills.push(id)
}
@skills.sort!
@multiplier = get_multi
@exp_list = Array.new(101)
make_exp_list
@exp = tech[2]
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def get_multi
m = 0
@skills.each{|i|
m += $data_skills[i].power.abs
}
return m/10
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
@exp_list[1] = 0
for i in 2..100
@exp_list[i] = @exp_list[i-1] + (@multiplier * (i / 2) * (i + 1))
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 99999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
end
#===============================================================================
# class Game_Actor
#===============================================================================
class Game_Actor < Game_Battler
attr_accessor :techniques
alias initialize_techniques initialize
def initialize(actor_id)
@techniques = []
initialize_techniques(actor_id)
end
alias setup_techniques setup
def setup(actor_id)
setup_techniques(actor_id)
# How will you determine what techniques the character starts with?
end
# Adds the specified technique to the @techniques array
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
end
end
I had to change the method name 'def multiplier' to 'def get_multi'. It is entirely possible to just move the contents of that method and put it into 'def initialize' but I wasn't sure if you wanted to, say, add more skills into the technique later on. Tested with Heal and Greater Heal (powers of 150 and 300) and it returned 45.
Also had to shift things around a bit in 'def initialize'.
the stuff labled game actor... can that stuff go into the game actor, or does it have to go above main?
Also, I see you guys use "alias" a lot. What's it for?
in answer to the question "How will you determine what techniques the character starts with?" I planned on using events to grant specific techniques based on player choices during a phase called "character creation". Stock techniques include stuff like black and white magic, melee, dodge, endurance, willpower, and later some thief stuff.
You can put 'Game_Actor' in its own, separate space, as long as it is below RPG Maker's default 'Game_Actor' and above 'Main'.
There are some guides that explain what alias does, but I'll try to explain it.
class Something
def method_one
print ("a")
end
alias copy_of_method_one method_one
# Essentially means this below:
# def copy_of_method_one
# print("a")
# end
# You should know that if you define a method that already exists, you are
# rewriting the method. That's why we made a copy of the original method
# right before we're about to change it.
def method_one
print ("b")
copy_of_method_one
end
end
If you were to somehow call 'Something.method_one' you would get two pop-up windows, the first saying "b" and the next saying "a". alias means "make an exact copy of the method".
Looking forward to the next reply.
So I made some small modifications, shown below:
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
#==============================================================================
# ** Game_Technique
#------------------------------------------------------------------------------
# This class handles the Techniques. It's used within the Game_Actors class
# ($game_actors) and refers to the Technique class.
#==============================================================================
class Game_Technique
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :id # technique ID
attr_accessor :name # e.g. Black Magic, Dodge, Rifles
attr_accessor :multiplier # e.g x1, x2, ...x9, etc.
attr_accessor :exp # total exp earned
attr_accessor :physical # true or false
attr_accessor :magical # true or false
attr_accessor :level # level
attr_accessor :skills # skills, spells, merits, flaws
attr_accessor :description # help window description
#--------------------------------------------------------------------------
# * Stock Techniques
# tech_id : tech ID
#--------------------------------------------------------------------------
def techniques_data(id)
# return [name, mult, exp, physical?, magical?, level, skills, desc]
case id
when 0 then return ["Endurance", 1, 0, true, false, 0, [1, 2, 10], "Hit Point Bonus"]
end
end
#--------------------------------------------------------------------------
# * Object Initialization
# tech_id : tech ID
#--------------------------------------------------------------------------
def initialize(tech_id)
tech = techniques_data(tech_id)
@tech_id = tech_id
@name = tech[0]
@level = tech[5]
@physical = tech[3]
@magical = tech[4]
@description = tech[7]
@skills = []
tech[6].each{|id|
@skills.push(id)
}
@skills.sort!
@multiplier = get_multi
@exp_list = Array.new(100)
make_exp_list
@exp = tech[2]
end
#--------------------------------------------------------------------------
# * Get Tech ID
#--------------------------------------------------------------------------
def id
return @tech_id
end
#--------------------------------------------------------------------------
# * Get Tech Multiplier # needs revision to 0 + ...0.1+ 0.2 +x9...etc.
#--------------------------------------------------------------------------
def get_multi
m = 0
@skills.each{|i|
m += $data_skills[i].power
}
n = [1, m/10].max
return n
end
#--------------------------------------------------------------------------
# * Get Index
#--------------------------------------------------------------------------
def index
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Calculate EXP
#--------------------------------------------------------------------------
def make_exp_list
@exp_list[0] = 0
for i in 1..99
@exp_list[i] = Integer(0 + (@multiplier * ((i / 2.0) * (i + 1))))
end
end
#--------------------------------------------------------------------------
# * Get EXP String
#--------------------------------------------------------------------------
def exp_s
return @exp_list[@level+1] > 0 ? @exp.to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Next Level EXP String
#--------------------------------------------------------------------------
def next_exp_s
return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"
end
#--------------------------------------------------------------------------
# * Get Until Next Level EXP String
#--------------------------------------------------------------------------
def next_rest_exp_s
return @exp_list[@level+1] > 0 ?
(@exp_list[@level+1] - @exp).to_s : "-------"
end
#--------------------------------------------------------------------------
# * Change EXP
# exp : new EXP
#--------------------------------------------------------------------------
def exp=(exp)
@exp = [[exp, 999999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0
@level += 1
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
end
#--------------------------------------------------------------------------
# * Change Level
# level : new level
#--------------------------------------------------------------------------
def level=(level)
# Check up and down limits - NEEDS REVISION
level = [[level, $data_actors[@actor_id].final_level].min, 1].max
# Change EXP
self.exp = @exp_list[level]
end
#--------------------------------------------------------------------------
# * Learn Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def learn_skill(skill_id)
if skill_id > 0 and not skill_learn?(skill_id)
@skills.push(skill_id)
@skills.sort!
end
end
#--------------------------------------------------------------------------
# * Forget Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def forget_skill(skill_id)
@skills.delete(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Finished Learning Skill
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_learn?(skill_id)
return @skills.include?(skill_id)
end
#--------------------------------------------------------------------------
# * Determine if Skill can be Used
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
if not skill_learn?(skill_id)
return false
end
return super
end
end
mainly in the multiplier and experience point system. I dropped my array from 0-100 to 0-99, and started experience point requirements at level 1. The idea is you can have a technique listed, showing you can 'learn it', but you don't know anything about it. Also took out the absolute value for skill.power, because I wanted some "skills" to act as placeholders for flaws that reduce costs, like vows of poverty or costs permanent [mana/hp/levels/etc.]. Also set the minimum multiplier at x1, so no amount of flaws could reduce raising levels to 0.
Well it's a bit after midnight, so the alias thing is a bit over my head right now, but im happy to have received some guidance. There's not a lot of books on this programming language in my area.
An alias makes a copy of a definition and changes the name of it, this is so you can rewrite the definition without causing errors or just to add something to it...
# define the Definition to copy
# This method defines a fruit as an array containing "Apple"
def Fruit
return ["Apple"]
end
call Fruit # Returns ["Apple"]
alias :oldFruit :Fruit
def Fruit
return ["Apple","Banana"]
end
call Fruit # Returns ["Apple","Banana"]
call oldFruit # Returns ["Apple"]
# Here I show how you can use aliases to add to a definition
# This adds 1 to cost
def costadd1
@@cost += 1
end
call costadd1 # @@cost + 1
alias :costadd1old :costadd1
def costadd1
@@cost += 2
costadd1old # Calls old method
end
# Same as this
=begin
def costadd1
@@cost += 2
@@cost += 1 # Calls old method
end
=end
call costadd1 # @@cost + 2 then @@cost + 1
# Same as @@cost + 3
call costadd1old # @@cost + 1
I think I get what an Alias does - it protects the original...
So I began testing the script and made an exp fairy event to level up one of the techniques to see if
#1 would it gain experience points?
#2 would a second technique retain it's separate identity?
#3 would the technique gain a level, given enough experience points?
Well, what happened is #1 and #2 worked, and then #3 crashed on the following lines:
#====================================================================
# NEEDS HEAVY REVISION CF SKILL WINDOW
# Learn skill
for j in $data_classes[@class_id].learnings
if j.level == @level
learn_skill(j.skill_id)
end
end
end
#====================================================================
Which wasn't surprising at all, actually. So I took it out
And this is the resulting success:
(http://img6.imageshack.us/img6/6978/technique2.png)
Now the idea of having the "for i/j" thing was originally to allow people to have something like "black magic" final fantasy 4. So when you get to a certain technique level, you unlock a new spell, and again at a higher level, and so on, just like the actors do with their skill list. I haven't figured out how to set that up yet, but would presume it's a small table or array, that assigns a "level" to zero or more of your technique's skills.
Originally I thought this would only be useful for spells or "secret ninja techniques" etc., but I realize now throwing in some delayed flaws might also be interesting. For example, having some skills in your list simply act as placeholders for common events that inflict insanity, aging, or whatever, would be great for high powered Black Magic.
For now, it doesn't matter what the skills do, just that there's an optional "level attainment" list for them. I was thinking of exploiting some existing part of skills, like their element checkbox would be the fastest way to say "this skill/spell can have a level", or slightly more complex,
have three elements, like
.power x2 = level
.power x4 = level
.power x8 = level
or whatever. Then with that mechanism in place, I could actually create a "learn powerful spell early" option that would jack up the total skill multiplier.
So if something had a power of 20, and a multiplier of x2, it might be attainable at level 40, but you could have a "learn[skill_id] early" option that allows you to learn it at 20th level. I think the only problem is the complexity of the array. The simplest way to do it is to apply it to all skills, the second simplest is to have a single "skill", or a small list (like three), that reduce levels by something like 4,8, and 32 levels respectively, for a single chosen skill.
I do like the idea of 3 elements determining level attainment, but I'm pretty intimidated by the mess of being able to choose which skill is getting the discount, because it would look something like
game_actor[i].technique[a].skill[x]
game_actor[i].technique[a].skill[y][z]
Where x is the spell (like Meteo), y is the discount (like "learn 8 levels sooner"), and z refers back to Meteo.
Edit: maybe I can create an 8th category called "addendum" or "auxiliary" that's basically a junk array that after the computer checks existing skills, does additional calculations for certain skills and stores it. like which skills are discounted, what special trainers are needed, etc.
Two Questions:
if I didn't want the Game_Actor part of this program to be separated using aliases, What would it look like inside game_actor?
and where you said
alias setup_techniques setup
def setup(actor_id)
setup_techniques(actor_id)
# How will you determine what techniques the character starts with?
end
is "setup_techniques(actor_id)" a new method for creating a preexisting list? like
def setup_techniques(actor_id)
n = $data_actors[@actor_id]
case n
when 0
return n.techniques = [0,11,13]
when 1
return n.techniques = [1,3]
when 2
return n.techniques = [0,5,8]
when 3
return n.techniques = [0,2,6]
#etc.
end
end
class Game_Actor < Game_Battler
attr_accessor :techniques
def initialize(actor_id)
@techniques = []
super()
setup(actor_id)
end
def setup(actor_id)
actor = $data_actors[actor_id]
@actor_id = actor_id
@name = actor.name
@character_name = actor.character_name
@character_hue = actor.character_hue
@battler_name = actor.battler_name
@battler_hue = actor.battler_hue
@class_id = actor.class_id
@weapon_id = actor.weapon_id
@armor1_id = actor.armor1_id
@armor2_id = actor.armor2_id
@armor3_id = actor.armor3_id
@armor4_id = actor.armor4_id
@level = actor.initial_level
@exp_list = Array.new(101)
make_exp_list
@exp = @exp_list[@level]
@skills = []
@hp = maxhp
@sp = maxsp
@states = []
@states_turn = {}
@maxhp_plus = 0
@maxsp_plus = 0
@str_plus = 0
@dex_plus = 0
@agi_plus = 0
@int_plus = 0
# Learn skill
for i in 1..@level
for j in $data_classes[@class_id].learnings
if j.level == i
learn_skill(j.skill_id)
end
end
end
# Update auto state
update_auto_state(nil, $data_armors[@armor1_id])
update_auto_state(nil, $data_armors[@armor2_id])
update_auto_state(nil, $data_armors[@armor3_id])
update_auto_state(nil, $data_armors[@armor4_id])
end
end
That 'setup_techniques' was a placeholder. In all actuality, you can delete the 'alias' and 'def setup' and nothing would change. I just wasn't sure how you would initialize what techniques your actors started out with--hence, I put that there for a later time to edit.
Think of alias as the process of mitosis in biology: you start with one cell which becomes two, identical cells. Both of these cells, however, cannot have the same name, so you name one cell Bob and the other Bill. Now translate that metaphor into programming.
Quote from: KK20 on October 11, 2011, 01:04:06 pm
class Game_Actor < Game_Battler
attr_accessor :techniques
def initialize(actor_id)
@techniques = []
super()
setup(actor_id)
end
def setup(actor_id)
actor = $data_actors[actor_id]
@actor_id = actor_id
@name = actor.name
@character_name = actor.character_name
@character_hue = actor.character_hue
@battler_name = actor.battler_name
@battler_hue = actor.battler_hue
@class_id = actor.class_id
@weapon_id = actor.weapon_id
@armor1_id = actor.armor1_id
@armor2_id = actor.armor2_id
@armor3_id = actor.armor3_id
@armor4_id = actor.armor4_id
@level = actor.initial_level
@exp_list = Array.new(101)
make_exp_list
@exp = @exp_list[@level]
@skills = []
@hp = maxhp
@sp = maxsp
@states = []
@states_turn = {}
@maxhp_plus = 0
@maxsp_plus = 0
@str_plus = 0
@dex_plus = 0
@agi_plus = 0
@int_plus = 0
# Learn skill
for i in 1..@level
for j in $data_classes[@class_id].learnings
if j.level == i
learn_skill(j.skill_id)
end
end
end
# Update auto state
update_auto_state(nil, $data_armors[@armor1_id])
update_auto_state(nil, $data_armors[@armor2_id])
update_auto_state(nil, $data_armors[@armor3_id])
update_auto_state(nil, $data_armors[@armor4_id])
end
end
That 'setup_techniques' was a placeholder. In all actuality, you can delete the 'alias' and 'def setup' and nothing would change. I just wasn't sure how you would initialize what techniques your actors started out with--hence, I put that there for a later time to edit.
Think of alias as the process of mitosis in biology: you start with one cell which becomes two, identical cells. Both of these cells, however, cannot have the same name, so you name one cell Bob and the other Bill. Now translate that metaphor into programming.
Ok, I think I got it to transfer without crashing. I made a dummy holder for
#--------------------------------------------------------------------------
# * Setup Techniques for Stock Classes
#--------------------------------------------------------------------------
def setup_techniques(actor_id)
# do nothing for now
end
And now I'm going to test having the techniques actually do something to the actor, for the first time.
I've chosen "Swords" as my first target, the idea is if your actor gains this technique, they should gain access to the sword list of usable weapons.
If that works, I'm going to see if I can create a thing that depending on my 'swords' level, determines how many on the sword list I've learned. If it works, I can use similar ideas for knives, guns, and possibly spells.
Haha oh no. 'def setup_techniques' isn't another method; it's an alias for 'def setup'. What I meant as a placeholder was this:
alias setup_techniques setup
def setup(actor_id)
setup_techniques(actor_id) # Actor.setup(actor_id)
# This was where I was gonna edit/add stuff, inside this area. Right here where this comment is at.
end
Unless you actually deleted 'alias setup_techniques setup' and 'def setup' in class Game_Actor, your fix will cause an error for setting up your game actors.
Ahh, that makes more sense then. it seemed like it was just hanging out, and when I moved it into Game Actor, it didn't seem to have a place.
meanwhile, I ran into a serious problem with equipping characters:
$data_classes[i].weapon_set.push(1)
is based on classes. So if I had two fighters, and one had gained sword access, the other would also have sword access.
Quote
module RPG
class Class
def initialize
@id = 0
@name = ""
@position = 0
@weapon_set = []
@armor_set = []
@element_ranks = Table.new(1)
@state_ranks = Table.new(1)
@learnings = []
end
attr_accessor :id
attr_accessor :name
attr_accessor :position
attr_accessor :weapon_set
attr_accessor :armor_set
attr_accessor :element_ranks
attr_accessor :state_ranks
attr_accessor :learnings
end
end
Since the purpose of techniques is to more or less create custom classes from within the actor, changing classes shouldn't be the way to do it. Instead I need to find a way to tell the computer "if is actor" to skip the regular class $data_classes[ i ].weapon_set and go to some 'new and improved' game_actor[ i ].weapon_set, which inherits all the base weapons from the actor's base class (which might be zero), but then has more (or less) of them.
is that even possible? And why do I feel like Alias is a way to do it?
Just make each actor be its own unique class? Or do you plan to still have the option to change classes?
Anyways, yes, you're right that if you push a weapon into the $data_classes, you affect EVERY instance of any actor that may be of that class type. If you want to make weapons actor-specific, there might be a script for that already. Otherwise, you will have to edit a portion of the other RMXP default scripts (like the Equip_Windows).
Quote from: KK20 on October 11, 2011, 06:27:30 pm
Just make each actor be its own unique class? Or do you plan to still have the option to change classes?
Anyways, yes, you're right that if you push a weapon into the $data_classes, you affect EVERY instance of any actor that may be of that class type. If you want to make weapons actor-specific, there might be a script for that already. Otherwise, you will have to edit a portion of the other RMXP default scripts (like the Equip_Windows).
so I added an attr_accessor for weapon set in game_actor, then made one of these:
def weapon_set
weapons = $data_classes[2].weapon_set
return weapons
end
And had an event display my actor's weapon_set, and it displayed the numbered array I expected, which is a good thing. Next, I think I need to change "classes[2]" to whatever my class is, then I can change these:
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
...
# Add equippable weapons
if @equip_type == 0
weapon_set = $data_classes[@actor.class_id].weapon_set
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
Edit:
Game_Actor
def weapon_set
weapons = $data_classes[self.class_id].weapon_set
return weapons
end
Game_Actor
if item.is_a?(RPG::Weapon)
# If included among equippable weapons in current class
if @weapon_set.include?(item.id)
return true
end
end
...
Window_EquipItem
if @equip_type == 0
weapon_set = @actor.weapon_set
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
And I think that wraps up putting in the 'base' weapons, now I just need to figure out how to edit that list.
Got it:
class Game_Actor < Game_Battler
attr_accessor :techniques
attr_accessor :unique_weapon
attr_accessor :unique_armor
alias initialize_techniques initialize
def initialize(actor_id)
@techniques = []
@unique_weapon = []
@unique_armor = []
initialize_techniques(actor_id)
end
alias call_actor_setup setup
def setup(actor_id)
call_actor_setup(actor_id)
$data_classes[@class_id].weapon_set.each{|w|
@unique_weapon.push(w)
}
$data_classes[@class_id].armor_set.each{|a|
@unique_armor.push(a)
}
end
# Adds the specified technique to the @techniques array
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
end
#--------------------------------------------------------------------------
# * Determine if Equippable
# item : item
#--------------------------------------------------------------------------
def equippable?(item)
# If weapon
if item.is_a?(RPG::Weapon)
# If included among equippable weapons in current class
if @unique_weapon.include?(item.id)
return true
end
end
# If armor
if item.is_a?(RPG::Armor)
# If included among equippable armor in current class
if @unique_armor.include?(item.id)
return true
end
end
return false
end
end
#===============================================================================
# Modified Equip Window: Shows the proper equips actor can equip
#===============================================================================
class Window_EquipItem < Window_Selectable
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
# Add equippable weapons
if @equip_type == 0
weapon_set = @actor.unique_weapon
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
# Add equippable armor
if @equip_type != 0
armor_set = @actor.unique_armor
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
Tested it a bit. Seemed fine. Also possible to use $game_actors[id].unique_weapon.push(id) to add new items.
Edit: Ninja'd
Edit 2: Wait...you said you needed to find a way to add onto the base. In that case, no ninja. I've provided that.
Unique? for now I was just trying to expand the existing array using something similar to your add_tech... and my version failed.
# * Custom Weapon Set
#--------------------------------------------------------------------------
def weapon_set
weapons = $data_classes[self.class_id].weapon_set
return weapons
end
#--------------------------------------------------------------------------
# * Add Weapons *doesn't currently work*
#--------------------------------------------------------------------------
def add_weapon(weapon_id)
return if @weapon_set[weapon_id] != nil
@weapon_set.push[weapon_id]
end
weapon_set by itself works, but I don't know how to add new weapons to that set. I modified this line:
@weapon_set[weapon_id] = weapon_set.new(weapon_id)
Because I couldn't get it to work, I think its because Game_Technique is its own class, and weapon_set isn't. I wanted to use something like it because your add_tech() thing kicks ass.
Through testing, I found out that even if you did something like @weapon_set = $data_classes[@class_id].weapon_set and then did @weapon_set.push(100), it would still push 100 as a usable weapon to any actor who shared the same class. As such, I only took the array values from $data_classes[@class_id].weapon_set by using a ".each{}" and stored those values into @unique_weapon. The reason I called it Unique is because only
this specific actor has access to this list of weapons. When I did @unique_weapon.push(100)--along with all the modifications I added--only that specific actor was capable of equipping weapon 100. I even had other party members who were the same class and they couldn't equip weapon 100.
Just use my add-on I wrote, and then press CTRL+H to change the names of 'unique_weapon' and 'unique_armor' to whatever you want it to be (I'm guessing 'weapon_set' and 'armor_set').
If you want to make a custom method to add weapons/armors that don't duplicate, do something like:
def add_weapon(id)
return if @unique_weapon.include?(id)
@unique_weapon.push(id)
@unique_weapon.sort!
end
I was impressed 8)
I used your thingymabob w/minimal changes and it worked:
#--------------------------------------------------------------------------
# * Add Weapons
#--------------------------------------------------------------------------
def add_weapon(weapon_id)
return if @weapon_set.include?(weapon_id)
@weapon_set.push(weapon_id)
@weapon_set.sort!
end
You need to initialize it as a clone of $data_whatever, and it will not add to every actor of the same class.
So, instead of doing something like this:
@unique_weapons = []
$data_weapons.each {|w| @unique_weapons.push(w) }
You can simply initialize is it for each actor like this:
@unique_weapons = $data_weapons.clone
Quote from: ForeverZer0 on October 11, 2011, 08:54:46 pm
You need to initialize it as a clone of $data_whatever, and it will not add to every actor of the same class.
So, instead of doing something like this:
@unique_weapons = []
$data_weapons.each {|w| @unique_weapons.push(w) }
You can simply initialize is it for each actor like this:
@unique_weapons = $data_weapons.clone
I don't understand how you got that to work, but
You illustrate a solid point - I just checked and when I have actors of the same class, and give an actor a new weapon, all other actors of that class get the weapon. This makes absolutely no sense to me, since the weapon should be added to an actor's file, not the class file. I don't understand why this is.
starting off with checking two characters of the same class:
p $game_actors[2].weapon_set
p $game_actors[3].weapon_set
and then doing this:
$game_actors[2].add_weapon(35)
Should not have any effect on the weapon_set of actor 3, but it does.
You're saying it still adds to both when you do the clone method?
@weapon_set = $data_classes[@class_id].weapon_set.clone
It looks like this, right? I just did that right now and it worked.
Thanks for that 'clone' tip. It actually helped me out with my current project. :P
Quote from: KK20 on October 12, 2011, 02:06:21 pm
@weapon_set = $data_classes[@class_id].weapon_set.clone
It looks like this, right? I just did that right now and it worked.
Thanks for that 'clone' tip. It actually helped me out with my current project. :P
Ahah!
what I was doing was this
@weapon_set = $data_classes[self.class_id].weapon_set.clone
instead of this
@weapon_set = $data_classes[@class_id].weapon_set.clone
and so whenever i tested it, neither actor equipment changed upon adding.
then I tried this
@weapon_set = $data_weapons.clone
and that didn't work out too well at all.
Really? That first line (self.class_id) shouldn't have done anything. Just tested it--no errors.
And the $data_weapons was just an example, not a fix for the script. $data_weapons is something completely different.
Will be gone for a few hours. Try and find a list of what you want done next when I get back; I'm bored.
ok so I got to sticking the weapons into the actor list based on their techniques, and this is what I've got:
#--------------------------------------------------------------------------
# * Add Techniques
#--------------------------------------------------------------------------
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
my_id = tech_id
weapon_tech(my_id) #this is new
end
#--------------------------------------------------------------------------
# * Custom Weapon Set - technique interface w/ add weapon
#--------------------------------------------------------------------------
def weapon_tech(var)
m = @techniques[var].skills
if m.include?(6)
a = $data_skills[6].str_f
z = $data_skills[6].dex_f
(a..z).step(1) do |n|
add_weapon(n)
end
else
return
end
end
Here's how it works:
When a character receives a new technique, the computer checks if that technique comes with weapon proficiencies like swords.
The way I created weapon proficiencies is by creating skills titled stuff like "swords", "axes", "guns", etc. And then exploited the str_f (starting number) and dex_f (end number) to get my number range. The number range is a section of the weapon list. For example, swords might be 1-4, spears 5-8, and axes 9-12. So if my skill was called Swords, I would set str_f to 1, and dex_f to 4, and then my script:
a = $data_skills[6].str_f
z = $data_skills[6].dex_f
(a..z).step(1) do |n|
add_weapon(n)
end
adds each of these weapons. What I need to know how to do is change that "6", in here:
if m.include?(6)
a = $data_skills[6].str_f
z = $data_skills[6].dex_f
into some kind of variable like "i", so it can check not just for skill #6 (which is only swords), but a short list of skills, like 6,7,8,9,10, and maybe some stuff out of order that might come later, like 62 (giant robot weapons?), 63 (joke weapons?), and so on. I just don't know how to turn
if m.include?(6)
a = $data_skills[6].str_f
z = $data_skills[6].dex_f
into something like
if m.include?([6,7,8,9,10,11,62,63])
a = $data_skills[[6,7,8,9,10,11,62,63]].str_f
z = $data_skills[[6,7,8,9,10,11,62,63]].dex_f
Loops. 'nuff said.
#--------------------------------------------------------------------------
# * Add Techniques
#--------------------------------------------------------------------------
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
weapon_tech(tech_id)
end
#--------------------------------------------------------------------------
# * Custom Weapon Set - technique interface w/ add weapon
#--------------------------------------------------------------------------
def weapon_tech(id)
skills = @techniques[id].skills
skills.each{|s|
if [6,7,8,9,10,11,62,63].include?(s)
a = $data_skills[s].str_f
z = $data_skills[s].dex_f
for n in a..z
add_weapon(n)
end
end
}
p(@weapon_set)
end
For your array of [6,7,8,9,10,11,62,63], I'm hoping you make that more user-friendly. Unless this script is solely yours...in that case, knock yourself out.
I originally intended on only having a handful of weapon ranges, and tossed in the ones in the 60s for good measure, in case I added new ones.
I originally thought of making "classes" for the sole purpose of ripping off their weapon sets.
My next task is getting the levels of techniques to count toward attack bonuses. So if you have a level 30 sword, that's +30 to hit. Once "sword" works, I can start proof checking some other aspects, like "swords/level", which turns into "spells/level", since I don't want level 1 characters summoning "bahamut" and casting "meteo", in FF terms.
ok, so I've got these techniques that allow me to use weapons, but the techniques also have levels. What I would like to do, is something like the following pseudocode in the Game Battler:
#if using Swords... get technique level
If: wielding $data_weapons[1..4]
Check if @actor.techniques[var].skills[var] includes "6"
If true
attack_skill = @actor.techniques[var].level
else
attack_skill = 0
end
#if using Spears... get technique level
If: wielding $data_weapons[5..8]
Check if @actor.techniques[var].skills[var] includes "7"
If true
attack_skill = @actor.techniques[var].level
else
attack_skill = 0
end
#if using Axes... get technique level
If: wielding $data_weapons[5..8]
Check if @actor.techniques[var].skills[var] includes "9"
If true
attack_skill = @actor.techniques[var].level
else
attack_skill = 0
end
Basically, if I have a Technique that teaches some weapons,
and I'm attacking,
The computer checks my current equipped weapon id,
and then compares that with a small table of weapons:
[weapon id's][skill id]
[1-4]..........[6]
[5-8]..........[7]
[11-12].......[8]
[13-16].......[9]
[17-20].......[10]
[21-24].......[11]
alternatively, I realized that if you have a given weapon id, you probably have the skill related,
so what we really need to do is check to see which technique you have that has the skill id in it's array.
and most importantly, if you have more than one techniques with the same skill id (like 6 for swords),
then stick these technique.levels in an array, sort, and use the highest level.
This somehow seems easier... :???:
This is what I've got so far,
for i in 0.. @actor.techniques.size
a = @actor.techniques[i].skills
if a.include?(6)
sword_skills << @actor.techniques[i].level
else
return
end
end
and then I need some kind of sort 'sword_skills' array, which can then be sorted, and then the highest number becomes attack_skill. :D
well I've messed with it some more, and as usual, ran into some nil errors:
#--------------------------------------------------------------------------
# * Get Hit Rate
#--------------------------------------------------------------------------
def hit
if self.is_a?(Game_Actor)
sword_skills = [] # blank array
if self.techniques.size == 0
sword_skills << 0
else
for i in 0.. self.techniques.size
a = self.techniques[i].skills
p a
if a.include?(6)
sword_skills << self.techniques[i].level
else
return
end
end
end
n = 1 + sword_skills.max
#n = 100
#p self.techniques #works
else
n = 100
end
for i in @states
n *= $data_states[i].hit_rate / 100.0
end
return Integer(n)
end
basically the line it dies on is
a = self.techniques[i].skills
which is odd because I can usually get self.techniques[0,1,2,3..].skills or whatever to print.
edit: I've been getting weird results lately:
like "p self.techniques.size" spitting out 3 or 5 when my actor only has 1 technique.
Don't us a "return" nested in a loop. Use the word "next" to skip to the next iteration, or "break" if you want to exit the loop. If you are using the method as an iterator (which you're not in that example), you would use the "yield" keyword, not "return".
From what you have posted, it could be a few things, not all of which can be determined by the code. The "return" thing I just mentioned could easily be the cause, but some other things such as what the values of your techniques are and how they initialized.
I mean nothing bad by this, but I want to point out that your coding is very sloppy. Having your code poorly structured can make debugging a nightmare. My best suggestion would be to stop where you are, go back and see how you might structure it a bit better, and implement it. Having done so, you will be surprised how many less problems you have, and how much easier the ones you do get will be to find. I'm not suggesting that you start over, but I see many cases where it would benefit you greatly to subclass something or handle data differently that would make everything much easier to control.
I majored in Religious Studies, and have 0 classes in programming, I can't even tell the difference between sloppy and not. This month has been pretty good for me - I started using indents.
Meanwhile, I got a really weird semifunctional result with this one:
#--------------------------------------------------------------------------
# * Get Hit Rate
#--------------------------------------------------------------------------
def hit
if self.is_a?(Game_Actor)
sword_skills = [] # blank array
if self.techniques.size == 0
sword_skills << 0
else
for m in 0..self.techniques.size
p self.techniques[2] #prints normal data...3 times?
a = self.techniques[2].skills
if a.include?(6)
sword_skills << self.techniques[2].level
else
return
end
end
end
n = 1 + sword_skills.max
#n = 100
#p self.techniques #works
else
n = 100
end
for i in @states
n *= $data_states[i].hit_rate / 100.0
end
return Integer(n)
end
What I don't get, is why it prints 3 times when I only have one technique, and why I can't get the for loop to
1. check all techniques for skill number 6,
2. add technique to the sword_skill array
3. get the highest listed skill in sword_skill
4. use that highest skill level as the basis for my "hit"
like say I have $game_actor[2].technique[2].skill[6]... that means my actor has a technique that has "swords" as a skill.
That technique (technique[2]) has a level: $game_actor[2].technique[2].level
ok so i took out the for loop.
#--------------------------------------------------------------------------
# * Get Hit Rate
#--------------------------------------------------------------------------
def hit
if self.is_a?(Game_Actor)
sword_skills = []
if self.techniques.size == 0
sword_skills << 0
else
a = self.techniques[2].skills
if a.include?(6)
sword_skills << self.techniques[2].level
else
return
end
end
n = 1 + sword_skills.max
else
n = 100
end
for i in @states
n *= $data_states[i].hit_rate / 100.0
end
return Integer(n)
end
This script works fine. The only problem is, if my actor has a different technique that also has swords, this script will not detect it.
i need to
first; check all the actor's techniques
second: check each technique for all skills
third: compare all these skills to an integer
four: if that integer is the same, get the technique skill level
five: put the skill level in a temporary array
six: get the highest skill level in the array
seven: use the highest skill level as my "hit" score in battle.
I have never taken a programming class myself, and have never been to college, so that is not an excuse to not learn it.
To be quite honest, the sloppiness and disorganization is the problem with your script. No one starts out scripting as a master, I have made some very unorganized scripts myself. That is why I am telling you from experience, you are going to continue to have numerous problems until you look into cleaning it up a bit, plus it would help others understand enough to help you better.
Did you try removing the "return" from the for..end loop before just removing the loop altogether?
Quote from: ForeverZer0 on October 23, 2011, 09:20:28 pm
I have never taken a programming class myself, and have never been to college, so that is not an excuse to not learn it.
To be quite honest, the sloppiness and disorganization is the problem with your script. No one starts out scripting as a master, I have made some very unorganized scripts myself. That is why I am telling you from experience, you are going to continue to have numerous problems until you look into cleaning it up a bit, plus it would help others understand enough to help you better.
Did you try removing the "return" from the for..end loop before just removing the loop altogether?
yep
def hit
if self.is_a?(Game_Actor)
sword_skills = []
for i in 0.. self.techniques.size
if self.techniques.size == 0
sword_skills << 0
else
a = self.techniques[i].skills
if a.include?(6)
sword_skills << self.techniques[i].level
else
next
end
end
end
but I get a undefined method 'skills' for niNilClass referring to this:
a = self.techniques[i].skills
Which I have no idea how to get around.
I'm hoping to turn a working version of this into a method I can apply to any weapon,
i.e, something like:
def weapon_range
weapon = ($data_weapons[@weapon_id] / 4.0)
return weapon.ceil
end
...
when 1
weapon_check(6)
when 2
weapon_check(7)
when 3
weapon_check(7)
...
def weapon_check(num)
if self.is_a?(Game_Actor)
for i in 0.. self.techniques.size
a =self.techniques[i].skills
if a.include?(num)
weapon_skills << self.techniques[i].level
else
next
end
end
end
end
Your looking in the wrong place. Find where "technique" is created, and find out why it is setting one of them to nil.
Quote from: ForeverZer0 on October 23, 2011, 10:21:26 pm
Your looking in the wrong place. Find where "technique" is created, and find out why it is setting one of them to nil.
by 'setting one of them' to nil, do you mean techniques or techniques[n].skills? It detects techniques, but I'm having difficulty detecting the skills.
edit: here's the section where skills are added:
Quote
def initialize(tech_id)
tech = techniques_data(tech_id)
@tech_id = tech_id
@name = tech[0]
@level = tech[5]
@physical = tech[3]
@magical = tech[4]
@description = tech[7]
@skills = []
tech[6].each{|id|
@skills.push(id)
}
@skills.sort!
@multiplier = get_multi
@exp_list = Array.new(100)
make_exp_list
@exp = tech[2]
end
i have the @actor getting the attack skill here:
$game_actors[2].add_tech(2)
which refers to this in Game_Actor
def add_tech(tech_id)
return if @techniques[tech_id] != nil # stops if tech is already possessed
@techniques[tech_id] = Game_Technique.new(tech_id)
my_id = tech_id
weapon_tech(my_id)
end
Juts insert a "p tech[6]" and "p tech[5]" there, and make sure they are okay. If not, look through the "techniques_data" method and see why they are not.
Quote from: ForeverZer0 on October 23, 2011, 10:51:24 pm
Juts insert a "p tech[6]" and "p tech[5]" there, and make sure they are okay. If not, look through the "techniques_data" method and see why they are not.
i get nil and nil, whereas p techniques[0] and p techniques[2], produce nil, and this:
(http://img829.imageshack.us/img829/8205/swordtech.png)
before the next line produces the same undefined method 'skills' for niNilClass
I've realized I don't need "self" as part of battler, so I did some reorganizing,
if @techniques.size == 0
sword_skills << 0
else
for i in 0...@techniques.size
p @techniques[i]
a = @techniques[i].skills
if a.include?(6)
sword_skills << @techniques[i].level
else
next
end
end
end
but I noticed the result is almost identical, and unexplainable.
also produces "nil" which naturally leads to crash on nil.skills. I was about to do something amazing related to picking out what little data I could and then slamming down the the program's throat, as it were, but the whole self/@ thing messed up my train of thought... I'll keep trying though.
this appears to have worked, but I'm not sure...
def hit
if self.is_a?(Game_Actor)
sword_skills = []
if @techniques.size == 0
sword_skills << 0
else
for i in 0...@techniques.size
if @techniques[i] == nil
p "nope"
next
else
p @techniques[i]
a = @techniques[i].skills
if a.include?(6)
sword_skills << @techniques[i].level
else
next
end #if include
end #if tech = nil
end #for i in 0
end # if tech size
n = 1 + sword_skills.max
else
n = 100
end # if is actor
for i in @states
n *= $data_states[i].hit_rate / 100.0
end
return Integer(n)
end
I will have test it with multiple levels and multiple characters with swords before determining if it's actually functional... unless I've made some kind of obvious error.
edit: tried it with multiple actors, seems to work, but posts "nope" twice before posting techniques. Not sure why it gets two nils first, but it gets them for all actors.
Update:
So I broke "Get Hit Rate" into three parts, and for the most part, it works, although if for some reason your actor has a technique (in other words, the technique array isn't blank), and you are for some crazy reason wielding a weapon you don't have a technique for, it crashes where it says "weapon_skills << @techniques[ i ].level"
#--------------------------------------------------------------------------
# * Get Hit Rate I: Weapon Range
#--------------------------------------------------------------------------
def weapon_range
if self.is_a?(Game_Actor)
weapon = @weapon_id / 4.0
return weapon.ceil
else
return 0
end
end
#--------------------------------------------------------------------------
# * Get Hit Rate II: Weapon Check
#--------------------------------------------------------------------------
def weapon_check(num)
if self.is_a?(Game_Actor)
weapon_skills = []
if @techniques.size == 0
weapon_skills << 0
p weapon_skills
else
for i in 0...@techniques.size
if @techniques[i] == nil
next
else
a = @techniques[i].skills
if a.include?(num)
weapon_skills << @techniques[i].level
p weapon_skills
else
next
end #if include
end #if tech = nil
end #for i in 0
end # if tech size
p weapon_skills
n = 1 + weapon_skills.max
else
n = 100
end # if is actor
#check for states
for i in @states
n *= $data_states[i].hit_rate / 100.0
end
return Integer(n)
end
#--------------------------------------------------------------------------
# * Get Hit Rate III: Hit
#--------------------------------------------------------------------------
def hit
case weapon_range
when 0 #unarmed - will be revised later
n = 100 #default for monsters for now... add when -1 or something later
when 1 #swords (lists like this one will be expanded)
weapon_check(6)
when 2 #spears
weapon_check(7)
when 3 #axes
weapon_check(8)
when 4 #knives
weapon_check(9)
when 5 #bows
weapon_check(10)
when 6 #guns
weapon_check(11)
when 7 #maces
weapon_check(12)
when 8 #rods (canes, staves etc.)
weapon_check(13)
when 9 #asian blades (katana, wakazashi, zatoichi, shikomezui)
weapon_check(14)
when 10 #mecha blades
weapon_check(15)
end
end
I think I can fix that, but it will have to wait till the morning.
$game_actors[1].add_tech(0) #=> Aluxes gets technique with ID 0 (last time I checked, this was Endurance).
p $game_actors[1].techniques #=> DOES NOT DISPLAY an array with 0 in it. It will print out the whole technique array you have set up in Game_Technique.
'for index in 0.. @techniques.size' followed with '@techniques[index]' will be wrong. The way I have set up @techniques in Game_Actors is that the index value of the technique is located at the index value within @techniques. So if you added techniques 0, 1, and 5, '@techniques.size = 3'. @techniques[0] and @techniques[1] exist. But what the hell would @techniques[2] be? @techniques[2] is nil.
Use @techniques.each{|tech| #CODE HERE# } instead.
Edit: Upon further realization, if there is a gap between tech IDs, 'each' still runs through them. Nothing like a 'next if tech.nil?' can't fix.
Further Edit: Okay, so @techniques.size would include the nils as well...forget everything I said. Just use what I said directly above ^^^^.
Quote from: KK20 on October 24, 2011, 03:14:53 am
$game_actors[1].add_tech(0) #=> Aluxes gets technique with ID 0 (last time I checked, this was Endurance).
p $game_actors[1].techniques #=> DOES NOT DISPLAY an array with 0 in it. It will print out the whole technique array you have set up in Game_Technique.
'for index in 0.. @techniques.size' followed with '@techniques[index]' will be wrong. The way I have set up @techniques in Game_Actors is that the index value of the technique is located at the index value within @techniques. So if you added techniques 0, 1, and 5, '@techniques.size = 3'. @techniques[0] and @techniques[1] exist. But what the hell would @techniques[2] be? @techniques[2] is nil.
Use @techniques.each{|tech| #CODE HERE# } instead.
Edit: Upon further realization, if there is a gap between tech IDs, 'each' still runs through them. Nothing like a 'next if tech.nil?' can't fix.
Further Edit: Okay, so @techniques.size would include the nils as well...forget everything I said. Just use what I said directly above ^^^^.
That would explain it actually. Since we created stock techniques as a starting framework for "beginners", they would be assigning id numbers like 2 or 6 to their first techniques. Endurance is definitely tech 0, since it's going to be the "get more hit points" technique.
here's the stock list so far:
when 0 then return ["Endurance", 1, 0, true, false, 0, [1], "Hit Point Bonus"]
when 1 then return ["Dodge", 1, 0, true, false, 0, [3], "Avoid Attack"]
when 2 then return ["Swords", 1, 0, true, false, 0, [6], "Use Swords"]
when 3 then return ["Willpower", 1, 0, false, true, 0, [2], "Spell Point Bonus"]
when 4 then return ["White Magic", 1, 0, false, true, 0, [35,36,37], "Protection and Healing"]
when 5 then return ["Black Magic", 1, 0, false, true, 0, [38,39,40], "War and Death"]
when 6 then return ["Stealth", 1, 0, true, false, 0, [32], "Avoid Detection"]
when 7 then return ["Perception", 1, 0, false, true, 0, [30], "Percieve Reality"]
when 8 then return ["Guns", 1, 0, true, false, 0, [11], "Use Guns"]
when 9 then return ["Block", 1, 0, true, false, 0, [13], "Block Attacks Unarmed"]
when 10 then return ["Parry", 1, 0, true, false, 0, [14], "Block Attacks With Weapon"]
numbers may change later, but for now the goal is get at least ONE tech to do something. Two questions:
first question:
how does next if tech.nil? differ from
if @techniques[i] == nil
next
second question:
if we used that copy class weapons thing for actors like Aluxes,
@weapon_set = $data_classes[@class_id].weapon_set.clone
how can we "auto fill" some techniques, so when the battler says "hey you can use this weapon... but uh... you don't have a technique for it.. here ya go... you get tech[6 or whatever] at level 0... happy hunting"
here's something I came up with called the grandfather clause:
#--------------------------------------------------------------------------
# * Get Hit Rate IV: Grandfather Clause - adds techs for weapons you have
#--------------------------------------------------------------------------
def grandfather_tech
case @grandfather
when 0 #unarmed - will be revised later
next
when 6 #swords
#$game_actors[2].add_tech(0)
#self.add_tech(0)
add_tech(2)
when 7 #spears
add_tech(11)
when 8 #axes
add_tech(12)
when 9 #knives
add_tech(13)
when 10 #bows
add_tech(14)
when 11 #guns
add_tech(8)
when 12 #maces
add_tech(15)
when 13 #rods
add_tech(16)
when 14 #asian blades
add_tech(17)
when 36 #mecha blades
add_tech(18)
end
end
I don't know if it works yet, because I'm still deciding on which line to implement it in, but basically, when you are checking to see if player has "tech" related to their existing wielded weapons, if no technique comes up, you get an adjoining technique with levels. This is tweaky because at some point someone's going to make a kensai who can only wield one kind of weapon, and that should only be worth like 0.2 to their skill multiplier.
I was thinking of on the fly skill allocation, or a dumping bucket. All said, I don't want 40+ "skills" dedicated just to weapon proficiencies. Maybe I can make an "exotic" or "specialist" skill that's worth some points, but I don't see how I'm going to get around the "now everyone with specialist has access to that weapon".
Edit: Wait,
what if I ninja it by creating a special skill that has access to all skills, but not really? like a skill the program checks for to see if you have a 'special' weapon, or special weapons, and then if you have a technique with the "special weapon" skill, it includes that as a viable option for whatever weapon you have, and gets it's level from the technique with "special weapon' skill.
This works perfectly as long as a character only has one special weapon, but I think an array option for the technique has to be checked to see which special weapon it is.
This way, the computer would first check to see if you had a generic stock skill that matched in one of your techniques, plus the special weapon category. if the special weapon category existed, it would then check THAT skills @special category - probably a short list of array options for addenum, just like this. Much like "level" the number would be unique to the @actor with THAT technique,
thus, if Aluxes is game actor 1, "special" is skill #42 (life, universe, and everything, etc.) and "Blademaster" is a technique[21], we might have
$game_actor.techniques[21].level
$game_actor.techniques[21].skills[42]
$game_actor.techniques[21].addendum[nil,nil,2]
with the third slot of "addendum" being
which weapon in the $data_weapons list to check against, and if that's the same as the weapon they are wielding - then blamo, add $game_actor.techniques[21].level to the weapon_skills array for determining hit bonus. :???:
There is no difference. It's a matter of one line of code versus two. '== nil' is the same as '.nil?'.
For that, you will have to make another method to check that. Get the class's useable weapons, run through all the possible techniques you have that have the skill required to use that weapon, then use that technique's ID in method 'add_tech'. It's probably best that this new method is called in two spots: when the actor is initialized (aka under def setup) and rewriting or aliasing class change.
Since you posted something while I was typing this up, what you have there seems to work, assuming that you don't want this script to be easily customizable. And the use of 'next' only applies to loops. If you want 'case 0' to do nothing, you don't have to write anything.
And you lost me with all of your explanation stuff below.
it appears to work:
start to finish it looks like this:
#--------------------------------------------------------------------------
# * Get Hit Rate I: Weapon Range
#--------------------------------------------------------------------------
def weapon_range
if self.is_a?(Game_Actor)
weapon = @weapon_id / 4.0
return weapon.ceil
else
return 0
end
end
#--------------------------------------------------------------------------
# * Get Hit Rate II: Weapon Check
#--------------------------------------------------------------------------
def weapon_check(num)
if self.is_a?(Game_Actor)
weapon_skills = []
@grandfather = num
if @techniques.size == 0
weapon_skills << 0
else
for i in 0...@techniques.size
if @techniques[i] == nil
next
else
a = @techniques[i].skills
if a.include?(num)
weapon_skills << @techniques[i].level
p weapon_skills
else
grandfather_tech
weapon_skills << @techniques[i].level
next
end #if include
end #if tech = nil
end #for i in 0
end # if tech size
n = 10 + weapon_skills.max #change to other number later
else
n = 100
end # if is actor
#check for states
for i in @states
n *= $data_states[i].hit_rate / 100.0
end
return Integer(n)
end
#--------------------------------------------------------------------------
# * Get Hit Rate III: Hit
#--------------------------------------------------------------------------
def hit
case weapon_range
when 0 #unarmed - will be revised later
n = 100 #default for monsters for now... add when -1 or something later
when 1 #swords (lists like this one will be expanded)
weapon_check(6)
when 2 #spears
weapon_check(7)
when 3 #axes
weapon_check(8)
when 4 #knives
weapon_check(9)
when 5 #bows
weapon_check(10)
when 6 #guns
weapon_check(11)
when 7 #maces
weapon_check(12)
when 8 #rods (canes, staves etc.)
weapon_check(13)
when 9 #asian blades (katana, wakazashi, zatoichi, shikomezui)
weapon_check(14)
when 10 #mecha blades
weapon_check(36)
end
end
#--------------------------------------------------------------------------
# * Get Hit Rate IV: Grandfather Clause - adds techs for weapons you have
#--------------------------------------------------------------------------
def grandfather_tech
case @grandfather
when 0 #unarmed - will be revised later
next #may crash
when 6 #swords
#$game_actors[2].add_tech(0)
#self.add_tech(0)
add_tech(2)
when 7 #spears
add_tech(11)
when 8 #axes
add_tech(12)
when 9 #knives
add_tech(13)
when 10 #bows
add_tech(14)
when 11 #guns
add_tech(8)
when 12 #maces
add_tech(15)
when 13 #rods
add_tech(16)
when 14 #asian blades
add_tech(17)
when 36 #mecha blades
add_tech(18)
end
end
I'll come back to this @addendum and specialist stuff later - I have a feeling it will be useful when setting up the level ranges for martial arts and spell acquisition (i.e. how to stop a level 1 character from summoning Bahamut). For now, I need to integrate "dodge" and "hit" together with the Strategy bar in battle.
So I've integrated Dodge and Hit together, with the strategy bar system also built into it:
in Game_Battler 1
#--------------------------------------------------------------------------
# * Get Base Dodge
#--------------------------------------------------------------------------
def dodge_check
if self.is_a?(Game_Actor)
dodge_skills = []
if @techniques.size == 0
dodge_skills << 0
else
for i in 0...@techniques.size
if @techniques[i] == nil
next
else
a = @techniques[i].skills
if a.include?(3)
dodge_skills << @techniques[i].level
else
dodge_skills << 0
next
end #if include
end #if tech = nil
end #for i in 0
end # if tech size
player_dodge = 0 + dodge_skills.max
if player_dodge < self.agi
b_dodge = self.agi - player_dodge
n = player_dodge + Integer(b_dodge / 3)
else
n = player_dodge # dodge higher than agility?
end
else
n = Integer(self.agi / 3)
end # if is actor
return Integer(n)
end
and in Game_Battler 3
#--------------------------------------------------------------------------
# * Applying Normal Attack Effects
# attacker.hit : battler vs. self.dodge_check
#--------------------------------------------------------------------------
def attack_effect(attacker)
# Clear critical flag
self.critical = false
# First hit detection: high finesse (dodge) vs. low uke (hit)
if attacker.is_a?(Game_Actor)
if attacker.hit > self.dodge_check
bonus_dodge = attacker.hit - self.dodge_check
dynamic_bonus = bonus_dodge + 10 #enemies don't have strat_bars (+agg)
dynamic_dodge = self.dodge_check + rand(dynamic_bonus)
static_hit = attacker.hit - attacker.uke
hit_result = (dynamic_dodge < static_hit)
else
bonus_hit = self.dodge_check - attacker.hit
dynamic_bonus = bonus_hit - attacker.uke + 10
dynamic_hit = attacker.hit + rand(dynamic_bonus)
hit_result = (self.dodge_check < dynamic_hit)
end
else
if attacker.hit > self.dodge_check
bonus_dodge = attacker.hit - self.dodge_check
dynamic_bonus = bonus_dodge + self.agg + 10
dynamic_dodge = self.dodge_check + rand(dynamic_bonus)
hit_result = (dynamic_dodge < attacker.hit)
else
bonus_hit = self.dodge_check - attacker.hit
dynamic_bonus = bonus_hit + 10 #enemies don't hav strat_bars (-uke)
dynamic_hit = attacker.hit + rand(dynamic_bonus)
hit_result = (self.dodge_check < dynamic_hit)
end
end
# If hit occurs
if hit_result == true
# Calculate basic damage
right now it favors the actors who use strategy and favors creatures with high stats because they can default a stat at 1/3rd for their dodge skill. I'm still integrating other parts of the strategy bar, after which, I think I'll tackle hit points, then spell points (which should be a clone of hit point script), and then @addendum
which will probably be something like
@addendum = [[spell_order], [martial_order], specialist, nil, nil, nil,...]
since so far i've only confirmed unique weapons, spell levels, and martial arts levels.
I've integrated critical hit and strategy bars together, and got a nice clean 2000+ damage when critical hit was level 94. I'm using a multi-technique script, that for now works with one attribute,
#--------------------------------------------------------------------------
# * Get Base Critical/other Int based Techniques
#--------------------------------------------------------------------------
# critical = int_check(34); perception = int_check(??)
def int_check(num)
if self.is_a?(Game_Actor)
int_skills = []
if @techniques.size == 0
int_skills << 0
else
for i in 0...@techniques.size
if @techniques[i] == nil
next
else
a = @techniques[i].skills
if a.include?(num) #replace with 34 to make "critical"
int_skills << @techniques[i].level
else
int_skills << 0
next
end #if include
end #if tech = nil
end #for i in 0
end # if tech size
player_int = 0 + int_skills.max
if player_int < self.int
b_int = self.int - player_int
n = player_int + Integer(b_int / 3)
else
n = player_int # example: critical higher than intellect?
end
else
n = Integer(self.int / 3) #10 intellect is average, 3% critical
end # if is actor
return Integer(n)
end
This is in conjunction with this in part 3 of battler:
# Calculate critical damage *Plus Timing*
if self.damage > 0
critical_hit = attacker.int_check(34)
if attacker.is_a?(Game_Actor)
if rand(100) < (critical_hit + attacker.spd)
self.damage *= (1 + Integer(critical_hit / 10))
self.critical = true
end
else
if rand(100) < critical_hit #vs. danger sense/solo/precog.?
self.damage *= (1 + Integer(critical_hit /10))
self.critical = true
end
end
# Guard correction #replace this with parry or "defend other" options
if self.guarding?
self.damage /= 2
end
end
I've also started messing around with "size" as in sprites vs. dragons or giant robots. At first I was going to rewrite hit points so @actor.stamina X @actor.endurance = hit points, but I realized the actors have no stamina, which puts us at @actor.str x @actor.endurance, but then I realized monsters have no endurance, so my dilemma looks like this:
@actor.sta x @actor.end = hp
@enemy.sta x @enemy.end = hp
@actor.??? x @actor.end = hp
@enemy.??? x @enemy.??? = hp
of course, I can just assign monsters hit points, and use physical defense and magical defense and strength as the defaults for Stamina, but that seems oddly more quirky than assigning them a single new attribute to handle all of those factors.
I figure by taking the target's base strength and giving them a "size", they can have stamina that won't directly correlate 1:1.