Jump to content
kal

Ruby/RGSS3 questions that don't deserve their own thread

Recommended Posts

Are you saying if your character still needs 50xp to get to the next level, and you use an event to increase his level, that you want him to be given the 50xp? That already happens:

 

from Game_Actor class:


def change_level(level, show)
 level = [[level, max_level].min, 1].max
 change_exp(exp_for_level(level), show)
end

 

So to increase their level by 1 or x, you just call this function with 1 or x as the first argument. You don't need to worry about the xp at all.

 

Are you saying this is not happening? Or am I misunderstanding the question?

 

deeply.

 

what I am saying is that if you need 50xp to advance to level 2. and your current xp is 0 and you call, through an event: change entire party level: 1

thus meaning your current xp is now 50, your next level is what ever it is you need to get level 3 and your level is 2 everything is normal.

 

HOWEVER

 

if you change the level + 1 in that method I showed to +2 thus now meaning you need 162 xp and you call that method to change the level of every one in the the party to 2, you do not gain a level.

Share this post


Link to post
Share on other sites

For scenes inheriting from that does not overwrite dispose_all_windows all Window instance variables will automatically be disposed.

That is probably the reason for your problem, you are trying to dispose an already disposed window

 

*hugs*

Share this post


Link to post
Share on other sites

Sorry if I've missed it and am missing something extremely obvious in this regard -- I recall being able to write custom EXP curves through a script in RMVX but I can't recall if it was a custom script or default script; Is this possible in VX ACE scripts by default (I do my best to avoid playing with default scripts ><)? I know you can generate it through actors, however I like a fair bit more control over it.

Share this post


Link to post
Share on other sites

OH! I think I get it now... But that's not it. What you're thinking is that I use the dispose method when leaving the scene right? But what I want to mange is to create/dispose a window with a button, while nothing else happens. Just make a window pop-up or disappear as if you're opening the skill window while in battle.

Share this post


Link to post
Share on other sites

Sorry if I've missed it and am missing something extremely obvious in this regard -- I recall being able to write custom EXP curves through a script in RMVX but I can't recall if it was a custom script or default script; Is this possible in VX ACE scripts by default (I do my best to avoid playing with default scripts ><)? I know you can generate it through actors, however I like a fair bit more control over it.

 

It's not possible through the default scripts. It's actually nested inside of a hidden class.

 

 

 

#==============================================================================
# â–  RPG::Class
#==============================================================================

class RPG::Class < RPG::BaseItem

 #--------------------------------------------------------------------------
 # exp_for_level
 #--------------------------------------------------------------------------
 def exp_for_level(level)
lv = level.to_f
basis = @exp_params[0].to_f
extra = @exp_params[1].to_f
acc_a = @exp_params[2].to_f
acc_b = @exp_params[3].to_f
return (basis*((lv-1)**(0.9+acc_a/250))*lv*(lv+1)/
  (6+lv**2/50/acc_+(lv-1)*extra).round.to_i
 end

end # RPG::Class

 

 

 

You can copy/paste that somewhere above Main in the script listing and adjust the formula however.

Share this post


Link to post
Share on other sites

In a notetag, I want to do <name 1, 2, 7, ..., n>

But, the code below uses multiple lines of one value only like this: <name 1><name 2><name7>...<name n>

Here is the code:

 

  def skill_types
types = []
self.note.split(/[\r\n]+/).each { |line|
  if line =~ /<skill-types (.*)>/i
	return types if $1.nil?
	c = $1.to_i
	types.push(c) if c != nil
  end
}
return types
 end

 

How do I modify the code so that I can use <name 1, 2, 7, ..., n>?

 

EDIT : I manage to find one of YF's code and used it like this (sorry for the bother):

 

  def skill_types
types = []
self.note.split(/[\r\n]+/).each { |line|
  if line =~ /<skill-types (.*)>/i
	return types if $1.nil?
	#stype_num = $1.to_i
	$1.scan(/\d+/).each { |stype_num|
	types.push(stype_num.to_i) if stype_num.to_i > 0 && stype_num.to_i != nil}
  end
}
return types
 end

 

Edited by Seiryuki

Share this post


Link to post
Share on other sites

I am trying to do a animated HUD

But I cannot make it move correctly.

here is the code:

 

 

class Moving_Gear < Window_Base


def initialize
 super(0,0,100,100)
 @gear = Sprite.new
 @timer = 1
 gears
end

def update
 super

end


def gears
 if @timer == 1
  @timer += 1
@gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g1")
update
 end
 if @timer ==2
  @timer += 1
 @gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g2")
 update
  end
  if @timer ==3
  @timer += 1
 @gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g3")
 update
  end
  if @timer ==4
@timer = 1
 @gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g4")
  update
  end
end
end

 

any ideias?

what I am doing wrong?

Share this post


Link to post
Share on other sites

I am trying to do a animated HUD

But I cannot make it move correctly.

 

any ideias?

what I am doing wrong?

 

Where does @timer get changed? Where does gears get called, and how often?

 

It looks like gears is called once, then not again. It needs to be called in a loop (maybe in Scene_Map.update?) so that the image continues to change.

Share this post


Link to post
Share on other sites

I am trying to do a animated HUD

But I cannot make it move correctly.

here is the code:

 

 

class Moving_Gear < Window_Base


def initialize
 super(0,0,100,100)
 @gear = Sprite.new
 @timer = 1
 gears
end

def update
 super

end


def gears
 if @timer == 1
  @timer += 1
@gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g1")
update
 end
 if @timer ==2
  @timer += 1
 @gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g2")
 update
  end
  if @timer ==3
  @timer += 1
 @gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g3")
 update
  end
  if @timer ==4
@timer = 1
 @gear.bitmap = Cache.load_bitmap("Graphics/Pictures/","g4")
  update
  end
end
end

 

any ideias?

what I am doing wrong?

Just a tip, call gears in update so it constantly get's updated, second use a switch case. In ruby I believe it's like this.

case something

when something

some stuff here

end

 

instead of doing multi if statements.

 

Third since your using a switch case just set the variable to the next command, no need to add to it.

 

Now if we're going into smoother animation I would kind of look at how charsets are animated, basically every 18 steps it goes to the next frame.

 

I actually have been working on your script for awhile now, I could have replied days ago and it would have worked, but the way you have it set up is that it's just going to go to every frame every 1 step. You need not only a cur_frame variable, but a step timer.

 

Well, if ya want it smooth lol.

Share this post


Link to post
Share on other sites

EDIT

Fixed the problem... But now the following problem: what method should I use to store the amount of elements of something with the EXACT SAME structure as $game_variables?

Edited by Emerald

Share this post


Link to post
Share on other sites

#==============================================================================
#
# â–¼ Gamesfreak13563 - Item Stats Bonus
# -- Last Updated: 2011.12.27
#
#==============================================================================
#==============================================================================
# â–  Options
#==============================================================================

module GF
 module ITEMBONUS
    DEFAULT_GROWTH ={
   # ParamID => [:param, +set],
	    0 => [:maxhp,    0],
	    1 => [:maxmp,    0],
	    2 => [  :atk,    0],
	    3 => [  :def,    0],
	    4 => [  :mat,    0],
	    5 => [  :mdf,    0],
	    6 => [  :agi,    0],
	    7 => [  :luk,    0],
   } # Do not remove this.
 end #ITEMBONUS
end #GF

#==============================================================================
# â–  Tags
#==============================================================================
module GF
 module ITEMBONUS
 module BASEITEM

   GROWTH_SET = /<(.*):[ ]([\+\-]\d+)[ ](?:BONUS|bonus)>/i

 end # BASEITEM
 end # ITEMBONUS
end # GF

#===========================================================================
# â–  DataManager
#===========================================================================


module DataManager  
   #--------------------------------------------------------------------------
   # â— Loads the database
   #--------------------------------------------------------------------------
   class << self
       alias_method(:gf_itembonus_load_database, :load_database) unless $@
   end
   def self.load_database
       gf_itembonus_load_database
       load_bonus_notetags
   end  
   #--------------------------------------------------------------------------
   # â— Loads the note tags
   #--------------------------------------------------------------------------
   def self.load_bonus_notetags
       groups = [$data_weapons, $data_armors]
       classes = [RPG::Weapon, RPG::Armor]
       for group in groups
           for obj in group
               next if obj.nil?
               obj.load_bonus_notetags if classes.include?(obj.class)
           end
       end
   end
end

#==========================================================================
#  â–   RPG::Weapon
#==========================================================================

class RPG::Weapon < RPG::EquipItem

 #--------------------------------------------------------------------------
 # public instance variables
 #--------------------------------------------------------------------------
 attr_reader :level_growth

 #--------------------------------------------------------------------------
 # common cache: load_bonus_notetags
 #--------------------------------------------------------------------------
 def load_bonus_notetags
   @level_growth = GF::ITEMBONUS::DEFAULT_GROWTH.clone
   #---
   self.note.split(/[\r\n]+/).each { |line|
  case line
  #---
  when GF::ITEMBONUS::BASEITEM::GROWTH_SET
    case $1.upcase
    when "MAXHP", "MHP", "HP"
	  type = 0
    when "MAXMP", "MMP", "MP", "MAXSP", "MSP", "SP"
	  type = 1
    when "ATK", "ATTACK"
	  type = 2
    when "DEF", "DEFENSE"
	  type = 3
    when "MAT", "MAGIC ATTACK", "INT", "INTELLIGENCE", "SPI", "SPIRIT"
	  type = 4
    when "MDF", "MAGIC DEFENSE", "RES", "RESISTANCE"
	  type = 5
    when "AGI", "AGILITY"
	  type = 6
    when "LUK", "LUCK"
	  type = 7
    else; next
    end
    @level_growth[type][1] = $2.to_i
  end
   } # self.note.split
   #---
 end

end # RPG::Enemy

#==========================================================================
#  â–   RPG::Armor
#==========================================================================

class RPG::Armor < RPG::EquipItem

 #--------------------------------------------------------------------------
 # public instance variables
 #--------------------------------------------------------------------------
 attr_reader :level_growth

 #--------------------------------------------------------------------------
 # common cache: load_bonus_notetags
 #--------------------------------------------------------------------------
 def load_bonus_notetags
   @level_growth = GF::ITEMBONUS::DEFAULT_GROWTH.clone
   #---
   self.note.split(/[\r\n]+/).each { |line|
  case line
  #---
  when GF::ITEMBONUS::BASEITEM::GROWTH_SET
    case $1.upcase
    when "MAXHP", "MHP", "HP"
	  type = 0
    when "MAXMP", "MMP", "MP", "MAXSP", "MSP", "SP"
	  type = 1
    when "ATK", "ATTACK"
	  type = 2
    when "DEF", "DEFENSE"
	  type = 3
    when "MAT", "MAGIC ATTACK", "INT", "INTELLIGENCE", "SPI", "SPIRIT"
	  type = 4
    when "MDF", "MAGIC DEFENSE", "RES", "RESISTANCE"
	  type = 5
    when "AGI", "AGILITY"
	  type = 6
    when "LUK", "LUCK"
	  type = 7
    else; next
    end
    @level_growth[type][1] = $2.to_i
  end
   } # self.note.split
   #---
 end

end # RPG::Enemy

#==========================================================================
#  â–   Game_Actor
#==========================================================================


class Game_Actor < Game_Battler

 def level_up_sum
   for f in 0..5
   if @equips[f].object != nil
  item1 = @equips[f].object
  puts @equips[f].object
    for i in 0..7
	    add_param(i, item1.level_growth[i][1])
	    puts item1.level_growth[i][1]
    end
  end
   end
 end

 def level_up
   @level += 1
   level_up_sum
   self.class.learnings.each do |learning|
  learn_skill(learning.skill_id) if learning.level == @level
   end
 end

end

 

 

What the script is supposed to do is apply a perameter bonus on leveling up to a character, if the character is equipping an item that has a tag, such as <atk: +2 bonus>. In theory this should give the character a +2 attack bonus when leveling up. However, the script just lumps together all the bonuses, weapons and armor, and assigns them to -every- weapon and armor. I have a general idea of what has to be done - basicallynot assigning everything to @level_growth[1] - but I have no idea how to go around fixing this. I have very little scripting experience. If anyone could help that'd be great.

Share this post


Link to post
Share on other sites

OH! I think I get it now... But that's not it. What you're thinking is that I use the dispose method when leaving the scene right? But what I want to mange is to create/dispose a window with a button, while nothing else happens. Just make a window pop-up or disappear as if you're opening the skill window while in battle.

In that case I'd consider two options.

  • Create the window once and then change its visibility.
  • Loose the reference to the window after you dispose it. I.e.
    @my_window.dispose unless @my_window.disposed?
    @my_window = nil
    


In a notetag, I want to do <name 1, 2, 7, ..., n>

But, the code below uses multiple lines of one value only like this: <name 1><name 2><name7>...<name n>

Here is the code:

 

  def skill_types
types = []
self.note.split(/[\r\n]+/).each { |line|
  if line =~ /<skill-types (.*)>/i
	return types if $1.nil?
	c = $1.to_i
	types.push(c) if c != nil
  end
}
return types
 end

 

How do I modify the code so that I can use <name 1, 2, 7, ..., n>?

 

EDIT : I manage to find one of YF's code and used it like this (sorry for the bother):

 

  def skill_types
types = []
self.note.split(/[\r\n]+/).each { |line|
  if line =~ /<skill-types (.*)>/i
	return types if $1.nil?
	#stype_num = $1.to_i
	$1.scan(/\d+/).each { |stype_num|
	types.push(stype_num.to_i) if stype_num.to_i > 0 && stype_num.to_i != nil}
  end
}
return types
 end

 

 

Be careful about using the greedy Kleene star.

Let me give you an example. Say you have the following regular expression: regex = /<name(.*)>/i

Sure it appears to work fine for your purpose, but let me show you what happens in a couple of cases:

'<name 1, 2, 7>' =~ regex		 #=> $1 = "1, 2, 7"
'<name 1><name 2><name7>' =~ regex	 #=> $1 = "1><name 2><name7"
'<name 1><type 5>' =~ regex		 #=> $1 = "1><type 5"

Remember that you scan for all the numbers in the resulting string which is ok for the first to cases, but if you have another tag on the same line then you'll get that along. Not really what you want. You can use a non-greedy approach, /<name(.*?)>/i, or use the greedy approach for all characters except >, i.e. /<name([^>]*)>/i. The trouble with using those two is the general approach that you only consider the first match rather than all matches for each line. You can do a scan like to you do for the digits.

Do note that I have not added a space after name unlike what you have after skill-types. If I had then it would not match "<name2>" as there are no space there.

Also, what happens if try to match against "<name>" or "<name garbage>"?

Special cases that you should consider. Maybe it makes sense, maybe not. Maybe you should require at least one number.

 

*hugs*

Share this post


Link to post
Share on other sites

Remember that you scan for all the numbers in the resulting string which is ok for the first to cases, but if you have another tag on the same line then you'll get that along. Not really what you want. You can use a non-greedy approach, /<name(.*?)>/i, or use the greedy approach for all characters except >, i.e. /<name([^>]*)>/i. The trouble with using those two is the general approach that you only consider the first match rather than all matches for each line. You can do a scan like to you do for the digits.

Do note that I have not added a space after name unlike what you have after skill-types. If I had then it would not match "<name2>" as there are no space there.

 

Ah, I made a mistake when writing the examples above :P. I wrote <name 1><name 2><name7>...<name n> when I should have wrote:

<name 1>

<name 2>

<name 7>

.

.

.

<name n>

I accidentally left out the space between name and 7, and I meant to say that the code uses multiple lines like shown above.

But! Your input is helpful. I don't understand most of the regular expression codes and I just watch what others do and try to pick up a thing or two.

Very informative, thank you Zeriab. I think I understand most of what you said.

Maybe I should hug you back *hugs* :)

Edited by Seiryuki

Share this post


Link to post
Share on other sites

What the script is supposed to do is apply a perameter bonus on leveling up to a character, if the character is equipping an item that has a tag, such as <atk: +2 bonus>. In theory this should give the character a +2 attack bonus when leveling up. However, the script just lumps together all the bonuses, weapons and armor, and assigns them to -every- weapon and armor. I have a general idea of what has to be done - basicallynot assigning everything to @level_growth[1] - but I have no idea how to go around fixing this. I have very little scripting experience. If anyone could help that'd be great.

 

It looks like you ran into a pitfall with the way Ruby handles copying objects.

This line:

GF::ITEMBONUS::DEFAULT_GROWTH.clone

will retrun a new copy of the DEFAULT_GROWTH hash, but the nested arrays inside the hash are shallow copies (meaning the reference to that object is copied, and you will not get a new object). Therefore, even though each item has it's own unique copy of the DEFAULT_GROWTH hash, when you change one of the values you access the nested arrays, which are shared among all growth hashes. That's why setting one value on an item will affect all the other items too.

 

There are some tricks you can do to prevent this (for example you could serialize the hash and then deserialize it to achieve a deep copy) but in this case it's easier to just remove the nested arrays because you don't really need them. If you have a hash where both keys and values are plain old data (like numbers for example) everything will be copied when you do DEFAULT_GROWTH.clone.

Here's a good article where you can learn more about duplicating objects in Ruby: http://ruby.about.co.../a/deepcopy.htm

 

I went ahead and changed the script so have a look at the following to see how I did it: https://gist.github.com/1716887

 

I also made two other changes. First I changed your level_up_sum method to make it a little clearer (I prefer to use the enumerator methods (like each) to iterate over something rather than the for structure) and I removed the duplication you had in the RPG::Weapon and RPG::Armor classes. Remember duplication is evil! And in this case the solution is really simple, just put the code in their parent class RPG::EquipItem

 

So I think the script should work as you intended now, though I didn't test it extensively. ;)

Share this post


Link to post
Share on other sites

Yes, thank you, that's exactly what I was looking for!
Now I am not sure, whether an array would be created like
arrayname = array.new or simply arrayname []
and where would the $game_variables[x] have to be written?

Edited by Strauchdieb

Share this post


Link to post
Share on other sites

Thank you.

One question remains for now:

How can I basically create a custom window via script?

Which aspects are especially important when thinking about creating a custom window?

 

Basically, you need to create a class of course, and add the two basic methods for window class, the initialize and the refresh method.

 

#==============================================================================
# ** Window Yours
#==============================================================================

class Window_Yours < Window_Base
 #--------------------------------------------------------------------------
 # ** Window Initialization
 #--------------------------------------------------------------------------
 def initialize
super(x, y, width, height)
refresh
 end
 #--------------------------------------------------------------------------
 # * Refresh
 #--------------------------------------------------------------------------
 def refresh
contents.clear
 end
end

 

The initialize will define the main parameters of the window such as the coordinates and the size, and the processes that will happen when the window is created.

 

The refresh method, will refresh of course and create the contents of your window, not always is necessary, but this is created to avoid the contents are created over and over, so this clear all the contents (draws, graphics, info) and update these contents to create them again (although the window isn't update by itself).

 

In the refresh you have to put all your draw_texts, draw_icons and all the things that you want to display there.

Edited by Mephistox

Share this post


Link to post
Share on other sites

Thank you for your help!
Next question:
Is there any way to access and change the system sounds?
It appears, that the system sounds which are set in the Database GUI are linked to variables,
but I don't see a way to chage the sounds stored within.

Edited by Strauchdieb

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×