YO GENIUS ASS SCRIPTERS! I NEED YOU GUYS TO TAKE A LOOK AT SOMETHING.

Posts

Pages: 1
So I have this Skill Decay script, right? I'm also using Yanfly's FTB battle system as well (although that's not the script I need edited/help with, just the first one)!

http://grimoirecastle.wordpress.com/rgss3-scripts/battle-scripts/skill-decay/
http://yanflychannel.wordpress.com/rmvxa/battle-scripts/ace-battle-engine/battle-system-free-turn-battle/

It's pretty handy for what I have in mind, but SOME THANGS. For various reasons I'll make sense to you guys later, the 'Attack' command will have a 'per use' decay, meaning that every time a player attacks on the same turn (actors can act more than once a turn if there's enough 'action points' left), the power of the Attack command (and ONLY the attack command) will diminish until the next turn. Don't worry about why, I'll explain that to you guys later.

So, what I need the script edited for is this. Currently the script

1. Doesn't discriminate between who attacks, the script by default lowers the power of the tagged skill for EVERYONE. This is no beuno, I just want the 'decay' on a per actor basis, not the entire party.

2. The decay only lasts until the end of the turn, then attack strength to that actor is restored. Presently, the script doesn't reset the decay until the end of the battle. This is a no go.

I tried to fiddle around with it myself, but to no avail. I'm definitely trying to get my feet wet with scripting, so if you can help me out, that's great, but also, if you can explain how you did it, that would be even better!
I don't think this should be too difficult, but I only just started with RGSS, and Ruby in general. Is there some sort of way to access who performed the attack? I'm thinking there HAS to be, I just don't know off hand... my limited scripting experience has not involved any sort of digging through the Battler class :X

So your first bullet point shouldn't be terribly difficult, but will take some finagling. See, every time the skill-decay script adds decay to an item, it's not associating it with the actor that used the item (or skill). So there's currently no way to make the decay unique to an actor with how it's written. Just looking at the script, it looks like it creates a hash called $game_temp.current_decays at the start of the battle (in the BattleManager module). This maps a skill to a "decay" value. What you'd need to do is modify the script to map this skill/decay-value pair to an actor (so probably a hash of hashes? I'd look here for info on that: (stack overflow link))

Of course, this ALSO introduces the problem that you'll have to modify the script every time the hash is written to, which again isn't terribly difficult. Also, you'll need to check if the actor/skill/value has a key every time you access it, since just accessing it by actor will create an empty key/value pair... again, its just a bit complicated. And maybe a multi-dimensional hash isn't exactly the way to go.


Your second point should be pretty easy. Just simply reset the $game_temp.current_decays hash at the end of each turn ($game_temp.current_decays = {}). Not sure where you'd put that, since you'd probably need to put it somewhere inside Yanfly's ftb script. Also, PS, That line will probably look different if you end up using a multi-dimensional hash, just fyi.


So, given all that, my first thought is if you only need this for Attacks (not for skills/items), using this script is kinda overkill IMO, and it might be better to write a script more suited for that need, since that sounds relatively simple to accomplish all on its own. I can help you do that if you'd like! But I'd probably need the source for the yanfly script (that link's download is broken because dropbox is awful, seriously why do people use dropbox for code)

If you got any questions, I'll try to answer to the best of my ability.
LockeZ
I'd really like to get rid of LockeZ. His play style is way too unpredictable. He's always like this too. If he ran a country, he'd just kill and imprison people at random until crime stopped.
5958
Yanfly's dropbox account is suspended due to being accessed too much recently, as usual. Any way you can just paste the free turn battle script here?

The skill decay script already includes a method of making one skill undo the decay of another. I'm thinking that it should be possible to make it so that the End Turn command undoes the decay of the Attack ability - however, since End Turn presumably isn't a skill that's actually listed in the database, doing so will require a slight edit of the Free Turn Battle script.

----

As far as making it work on a per-actor basis, that'll require making it into a two-dimensional array. This is just a matter of going down through the script and searching for each place that references the $game_temp.current_decays variable, which is the variable where the decay amounts are stored. Instead of being an array of skill IDs, it'll become an array of character IDs, and each member of that array will contain an array of skill IDs.

First Line 61, where the variable is first initialized:
$game_temp.current_decays = {}

The original code initializes the current_decays variable as an empty one-dimensional array when the battle starts. Change it to this:
$game_temp.current_decays = {}
    for i in 0..$game_actors.size
      $game_temp.current_decays[i] = {}
    end

We've now made it so that a skill's decay is referenced by checking current_decays[user_id][skill_id] instead of just by checking current_decays[skill_id].


Next are lines 216 and 217. This is where it returns how decayed a skill is. Just looking at this section, I can see that this code is inside the definition of the skill, at which point there's no apparent way to tell who is using the skill. However, if the code is being called from inside a battle, Scene_Battle has a variable called @subject which contains the character or monster currently using a skill. And Scene_Battle's variables are easy to access, thanks to the global variable $scene. If the skill were being used from a menu this wouldn't work - but the script doesn't work anyway when using skills from the menu, so who cares.

Currently this method looks like this:
def decay_hit_rate(value)
    return value unless SceneManager.scene.is_a?(Scene_Battle)
    return value unless @decay_on
    return value unless @decay_hit_rate
    return value unless $game_temp.current_decays[self.id] != nil
    (value * (100.00 - $game_temp.current_decays[self.id]) / 100).round
  end

Change it to this:
def decay_hit_rate(value)
    return value unless SceneManager.scene.is_a?(Scene_Battle)
    return value unless @decay_on
    return value unless @decay_hit_rate
    return value unless $game_temp.current_decays[$scene.subject.id][self.id] != nil
    (value * (100.00 - $game_temp.current_decays[$scene.subject.id][self.id]) / 100).round
  end

Simple enough.

Line 259 and 260 are where the skill's power is reduced by the amount that it's currently decayed. That method currently looks like this:
def apply_decay(dmg, itm)
    return dmg unless itm.is_a?(RPG::Skill)
    return dmg unless itm.decay_on
    return dmg unless $game_temp.current_decays[itm.id] != nil
    (dmg * (100.00 - $game_temp.current_decays[itm.id]) / 100).round
  end

We need to do the exact same thing here we just did above:

def apply_decay(dmg, itm)
    return dmg unless itm.is_a?(RPG::Skill)
    return dmg unless itm.decay_on
    return dmg unless $game_temp.current_decays[$scene.subject.id][itm.id] != nil
    (dmg * (100.00 - $game_temp.current_decays[$scene.subject.id][itm.id]) / 100).round
  end

Line 269 is fine, it simply makes the variable public. Don't change it.

The last two places it's referenced are lines 322 and 332. That part of the script looks like this:
#--------------------------------------------------------------------------
	# ● Adds to the decay counter
	#--------------------------------------------------------------------------
  def add_decay(item)
    ary = $game_temp.current_decays
    ary[item.id] = 0 if ary[item.id].nil?
    ary[item.id] = [(ary[item.id] + item.decay_rate), item.decay_max].min
  end
	#--------------------------------------------------------------------------
	# ● Cancels skill decay
	#--------------------------------------------------------------------------
  def reverse_decay(item)
    result = item.get_decay_reversion
    return if result.nil?
    result.each {|i| $game_temp.current_decays[i] = 0}
  end

We once again need to put the ID of the user in there - but this time we're in the Scene_Battle code, so instead of accessing the skill user by $scene.subject, we can just use @subject (the @ means it's a class variable, in this case for the Scene_Battle class). We can change the code to look like this:

#--------------------------------------------------------------------------
	# ● Adds to the decay counter
	#--------------------------------------------------------------------------
  def add_decay(item)
    ary = $game_temp.current_decays[@subject.id]
    ary[item.id] = 0 if ary[item.id].nil?
    ary[item.id] = [(ary[item.id] + item.decay_rate), item.decay_max].min
  end
	#--------------------------------------------------------------------------
	# ● Cancels skill decay
	#--------------------------------------------------------------------------
  def reverse_decay(item)
    result = item.get_decay_reversion
    return if result.nil?
    result.each {|i| $game_temp.current_decays[@subject.id][i] = 0}
  end

Finally, we need to make the "subject" variable publically accessible for the above to work. It's a private variable by default, which means that it can only be referenced from inside the Scene_Battle class.

Go to line 307. It currently looks like this:
class Scene_Battle < Scene_Base

We're going to add a line after that, so it'll look like this instead:
class Scene_Battle < Scene_Base
  attr_accessor   :subject

That makes the "subject" variable accessible.

Whew! That should do it for making the skill decay actor-specific.
So this is the error I get with those modifications, Locke.



It seems to have a problem with this;

$game_temp.current_decays = {}
    for i in 0..$game_actors.size
      $game_temp.current_decays[i] = {}
    end

Oh, by the way, here's the link to Yanfly's FTB if anyone wants to take a look at that.

https://github.com/Archeia/YEARepo/blob/master/Battle/BattleSystem_FTB.rb
LockeZ
I'd really like to get rid of LockeZ. His play style is way too unpredictable. He's always like this too. If he ran a country, he'd just kill and imprison people at random until crime stopped.
5958
Oh, sorry, I could have sworn Game_Actors had a size method by default. Try changing that line to:
for i in 0..999
Is it supposed to be this?

#==============================================================================
# ■ BattleManager
#==============================================================================

module BattleManager
  #--------------------------------------------------------------------------
  # ● Setups
  #--------------------------------------------------------------------------
	class << self ; alias_method(:krx_decay_bm_setup, :setup) ; end
  def self.setup(troop_id, can_escape = true, can_lose = false)
    krx_decay_bm_setup(troop_id, can_escape, can_lose)
    $game_temp.current_decays = {}
    for i in 0..999 $game_actors.size
      $game_temp.current_decays[i] = {}
    end
  end
end

Because that gives me an 'expecting' error.
LockeZ
I'd really like to get rid of LockeZ. His play style is way too unpredictable. He's always like this too. If he ran a country, he'd just kill and imprison people at random until crime stopped.
5958
What I meant was this:

#==============================================================================
# ■ BattleManager
#==============================================================================

module BattleManager
  #--------------------------------------------------------------------------
  # ● Setups
  #--------------------------------------------------------------------------
	class << self ; alias_method(:krx_decay_bm_setup, :setup) ; end
  def self.setup(troop_id, can_escape = true, can_lose = false)
    krx_decay_bm_setup(troop_id, can_escape, can_lose)
    $game_temp.current_decays = {}
    for i in 0..999
      $game_temp.current_decays[i] = {}
    end
  end
end

The .. there is creating an array of integers ranging from the first number to the second number. For example, 1..5 is the same as {1, 2, 3, 4, 5}. So a loop that looked like:

for i in 1..5
print(i)
end

would loop five times, and the variable i would increase by 1 each time it went through the loop, so it would print the numbers 1 through 5 to the screen in order. My loop works the same basic way, except it goes up to 999 (which is the maximum number of heroes you can have in the database).



So yeah! I posted up the currently modified script so you can take a look at it yourself.



http://pastebin.com/N5ed210K
LockeZ
I'd really like to get rid of LockeZ. His play style is way too unpredictable. He's always like this too. If he ran a country, he'd just kill and imprison people at random until crime stopped.
5958
OK, sorry, I'm incompetent, this bug was caused by a difference between RMXP and RMVXA.

$scene is how you get the current scene in RMXP. IN RMVXA you get it with SceneManager.scene

So I did a find-and-replace to change that, then I tested it in a project using Yanfly Melody, and it seems to be working now.

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#  ▼ Skill Decay
#  Author: Kread-EX
#  Version 1.01
#  Release date: 28/01/2012
#
#  Big thanks to infamous bon bon.
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
 
#-------------------------------------------------------------------------------------------------
#  ▼ UPDATES
#-------------------------------------------------------------------------------------------------
# # 30/01/2012. Fixed a really stupid bug.
#-------------------------------------------------------------------------------------------------
#  ▼ TERMS OF USAGE
#-------------------------------------------------------------------------------------------------
# #  You are free to adapt this work to suit your needs.
# #  You can use this work for commercial purposes if you like it.
# #  Credit is appreciated.
# #
# # For support:
# # grimoirecastle.wordpress.com
# # OR
# # rpgmakervxace.net
# # OR
# # rpgrevolution.com
#-------------------------------------------------------------------------------------------------
#  ▼ INTRODUCTION
#-------------------------------------------------------------------------------------------------
# # Skills used in battle start to decay and lose effectiveness. The decay can
# # eventually be reverted. If several people use the same skill, the decay is
# # even faster. This can break skill-spamming strategies, if used right at
# # least.
# # Note that it only affects damage, hit rate (optional) and recovery formulas.
# # Traits don't decay.
#-------------------------------------------------------------------------------------------------
#  ▼ INSTRUCTIONS
#-------------------------------------------------------------------------------------------------
# # By default, skills don't decay at all. There are a variety of notetags you
# # will have to use in order to apply the effects.
# # <decay_on> This enables decay for the skill.
# # <decay_max: x> The maximum efficiency loss. For instance, if set to 50,
# # the skill effectiveness will never drop below 50%.
# # <decay_rate: x> The efficiency loss per use. Every time any battler uses
# # this skill, it loses x in power and/or accuracy.
# # <hit_rate_decay> Enables the accuracy decay.
# # <revert_decay: x, x, x...> Raises the given skill IDs power back to their
# # full potential.
# # <revert_all_decay> Same as above, but for absolutely every skill.
# #
# # You don't have to set the maximum and decay rate for every skill. There are
# # default values and you can find them in the config part of the script.
#-------------------------------------------------------------------------------------------------
#  ▼ COMPATIBILITY
#-------------------------------------------------------------------------------------------------
# # Works with the base Ace Battle Engine, but not tested with every add-on.
# # Feel free to report incompatiblities as they will fixed if possible.
# #
# # List of aliases and overwrites:
# #
# # DataManager
# # load_database (alias)
# # load_decay_notetags (new method)
# #
# # BattleManager
# # setup (alias)
# #
# # RPG::Skill
# # decay on (new attr method)
# # decay_max (new attr method)
# # decay_rate (new attr method)
# # decay_hit_rate (new attr method)
# # load_decay_notetags (new method)
# # get_decay_reversion (new method)
# # decay_hit_rate (new method)
# #
# # RPG::Item
# # load_decay_notetags (new method)
# # get_decay_reversion (new method)
# #
# # RPG::UsableItem::Damage
# # apply_decay (new method)
# #
# # Game_Temp
# # current_decays (new attr method)
# #
# # Game_ActionResult
# # make_damage (alias)
# #
# # Game_Battler
# # item_hit (alias)
# #
# # Scene_Battle
# # use_item (alias)
# # add_decay (new method)
# # reverse_decay (new method)
#-------------------------------------------------------------------------------------------------

$imported = {} if $imported.nil?
$imported['KRX-SkillDecay'] = true

puts 'Load: Skill Decay v1.01 by Kread-EX'

module KRX
  
  DEFAULT_DECAY_MAX = 90
  DEFAULT_DECAY_RATE = 4
  
	module REGEXP
    DECAY_ENABLE = /<decay_on>/i
    DECAY_MAX = /<decay_max:[ ]*(\d+)>/i
    DECAY_RATE = /<decay_rate:[ ]*(\d+)>/i
    DECAY_HIT = /<hit_rate_decay>/i
    REVERT_IDS = /<revert_decay:[ ]*(\d+(?:\s*,\s*\d+)*)>/i
    REVERT_ALL = /<revert_all_decay>/i
	end
	
end

#===========================================================================
# ■ DataManager
#===========================================================================

module DataManager  
	#--------------------------------------------------------------------------
	# ● Loads the database
	#--------------------------------------------------------------------------
	class << self
		alias_method(:krx_decay_dm_load_database, :load_database)
	end
	def self.load_database
		krx_decay_dm_load_database
		load_decay_notetags
	end  
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def self.load_decay_notetags
		groups = [$data_skills, $data_items]
		for group in groups
			for obj in group
				next if obj.nil?
				obj.load_decay_notetags
			end
		end
		puts "Read: Skill Decay Notetags"
	end
end

#==============================================================================
# ■ BattleManager
#==============================================================================

module BattleManager
  #--------------------------------------------------------------------------
  # ● Setups
  #--------------------------------------------------------------------------
	class << self ; alias_method(:krx_decay_bm_setup, :setup) ; end
  def self.setup(troop_id, can_escape = true, can_lose = false)
    krx_decay_bm_setup(troop_id, can_escape, can_lose)
    $game_temp.current_decays = {}
    for i in 0..999
      $game_temp.current_decays[i] = {}
    end
  end
end
#===========================================================================
# ■ RPG::Skill
#===========================================================================

class RPG::Skill < RPG::UsableItem
	#--------------------------------------------------------------------------
	# ● Public instance variables
	#--------------------------------------------------------------------------
  attr_reader     :decay_on
	attr_reader		  :decay_max
  attr_reader     :decay_rate
  attr_reader     :decay_hit_rate
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def load_decay_notetags
    @decay_max = KRX::DEFAULT_DECAY_MAX 
    @decay_rate = KRX::DEFAULT_DECAY_RATE 
    @decay_revert_ids = []
		@note.split(/[\r\n]+/).each do |line|
			case line
			when KRX::REGEXP::DECAY_ENABLE
        @decay_on = true
      when KRX::REGEXP::DECAY_MAX
        @decay_max = $1.to_i
      when KRX::REGEXP::DECAY_RATE
        @decay_rate = $1.to_i
      when KRX::REGEXP::DECAY_HIT
        @decay_hit_rate = true
      when KRX::REGEXP::REVERT_IDS
        $1.scan(/\d+/).each {|i| @decay_revert_ids.push(i.to_i)}
      when KRX::REGEXP::REVERT_ALL
        @decay_revert_all = true
			end
		end
	end
	#--------------------------------------------------------------------------
	# ● Returns the IDs of the skill which will be re-powered
	#--------------------------------------------------------------------------
  def get_decay_reversion
    return 1...$data_skills.size if @decay_revert_all
    return @decay_revert_ids if !@decay_revert_ids.empty?
    return nil
  end
	#--------------------------------------------------------------------------
	# ● Returns the decayed hit rate
	#--------------------------------------------------------------------------
 def decay_hit_rate(value)
    return value unless SceneManager.scene.is_a?(Scene_Battle)
    return value unless @decay_on
    return value unless @decay_hit_rate
    return value unless $game_temp.current_decays[SceneManager.scene.subject.id][self.id] != nil
    (value * (100.00 - $game_temp.current_decays[SceneManager.scene.subject.id][self.id]) / 100).round
  end
end

#===========================================================================
# ■ RPG::Item
#===========================================================================

class RPG::Item < RPG::UsableItem
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def load_decay_notetags
		@note.split(/[\r\n]+/).each do |line|
			case line
      when KRX::REGEXP::REVERT_IDS
        $1.scan(/\d+/).each {|i| @decay_revert_ids.push(i.to_i)}
      when KRX::REGEXP::REVERT_ALL
        @decay_revert_all = true
			end
		end
	end
	#--------------------------------------------------------------------------
	# ● Returns the IDs of the skill which will be re-powered
	#--------------------------------------------------------------------------
  def get_decay_reversion
    return 1...$data_skills.size if @decay_revert_all
    return @decay_revert_ids
  end
end
  
#===========================================================================
# ■ RPG::UsableItem::Damage
#===========================================================================

class RPG::UsableItem::Damage
	#--------------------------------------------------------------------------
	# ● Causes the decay
	#--------------------------------------------------------------------------
  def apply_decay(dmg, itm)
    return dmg unless itm.is_a?(RPG::Skill)
    return dmg unless itm.decay_on
    return dmg unless $game_temp.current_decays[SceneManager.scene.subject.id][itm.id] != nil
    (dmg * (100.00 - $game_temp.current_decays[SceneManager.scene.subject.id][itm.id]) / 100).round
  end
end

#===========================================================================
# ■ Game_Temp
#===========================================================================

class Game_Temp
  attr_accessor   :current_decays
end

#===========================================================================
# ■ Game_ActionResult
#===========================================================================

class Game_ActionResult
	#--------------------------------------------------------------------------
	# ● Finishes to calculate the damage
	#--------------------------------------------------------------------------
  alias_method(:krx_decay_gar_md, :make_damage)
  def make_damage(value, item)
    value = item.damage.apply_decay(value, item)
    krx_decay_gar_md(value, item)
  end
end

#===========================================================================
# ■ Game_Battler
#===========================================================================

class Game_Battler < Game_BattlerBase
  #--------------------------------------------------------------------------
  # ● Determine hit rate
  #--------------------------------------------------------------------------
  alias_method(:krx_decay_gb_ih, :item_hit)
  def item_hit(user, item)
    rate = krx_decay_gb_ih(user, item)
    return item.decay_hit_rate(rate) if item.is_a?(RPG::Skill)
    return rate
  end
end

#===========================================================================
# ■ Scene_Battle
#===========================================================================

class Scene_Battle < Scene_Base
  attr_accessor   :subject
	#--------------------------------------------------------------------------
	# ● Uses a skill or item
	#--------------------------------------------------------------------------
  alias_method(:krx_decay_sb_ui, :use_item)
	def use_item
    krx_decay_sb_ui
    item = @subject.current_action.item
    add_decay(item) if item.is_a?(RPG::Skill) && item.decay_on
    reverse_decay(item)
  end
  #--------------------------------------------------------------------------
	# ● Adds to the decay counter
	#--------------------------------------------------------------------------
  def add_decay(item)
    ary = $game_temp.current_decays[@subject.id]
    ary[item.id] = 0 if ary[item.id].nil?
    ary[item.id] = [(ary[item.id] + item.decay_rate), item.decay_max].min
  end
	#--------------------------------------------------------------------------
	# ● Cancels skill decay
	#--------------------------------------------------------------------------
  def reverse_decay(item)
    result = item.get_decay_reversion
    return if result.nil?
    result.each {|i| $game_temp.current_decays[@subject.id][i] = 0}
  end
end
LockeZ
I'd really like to get rid of LockeZ. His play style is way too unpredictable. He's always like this too. If he ran a country, he'd just kill and imprison people at random until crime stopped.
5958
Making the decay reset at the end of each turn should be much simpler. Unfortunately I can't test this one without figuring out a ton of stuff about how to set up the script, but I can see it's coded in a way that lets me easily stick new functionality in there at the end of the turn. Hopefully.

Just a warning, this might not work first try, just like the last one didn't work first try.

Go down to lines 448 through 455 of the Free Turn Battle script. Right now they look like this:

#--------------------------------------------------------------------------
  # alias method: on_turn_end
  #--------------------------------------------------------------------------
  alias game_battler_on_turn_end_ftb on_turn_end
  def on_turn_end
    game_battler_on_turn_end_ftb
    init_ftb_actions
  end


All you should have to do, in theory, is change that to this:


#--------------------------------------------------------------------------
  # alias method: on_turn_end
  #--------------------------------------------------------------------------
  alias game_battler_on_turn_end_ftb on_turn_end
  def on_turn_end
    game_battler_on_turn_end_ftb
    init_ftb_actions
    if self.is_a?(Game_Actor)
      $game_temp.current_decays[self.id][1] = 0
    end
  end


If you're interested, I stole that line of code out of the Skill Decay script. Specifically it's from line 335, where the decays are reset.

In the original line, it loops through all the skills that are supposed to be reset - in this one it's just resetting skill ID 1 (normal attack), so I changed the i to 1. The i variable was being used by the loop to refer to each skill ID.

I then also made it get the user's ID a different way. It's defined inside Game_Battler, which is used by both enemies and actors, so it needed to check and make sure the user was an actor. Once the battler was sure it was an actor, it could use self.id to query its own actor ID. It then resets the decay for that actor ID, for skill #1.
That seems to have worked. Thanks for the guidance, everyone.
Pages: 1