[SCRIPTING] [RMVX ACE] DOUBLECAST SKILL?

Posts

Pages: 1
I'm trying to make a double cast skill that works as follows:

When you pick it it immediately, as a part of skill selection, lets you choose a spell, and the targets of that spell, and then do it again. It then does both spells in the order chosen, with the parameters chosen, upon that persons turn.

That's it. I'm hoping that either the script already exists, or that there's a relatively easy way to execute this. Any ideas would be appreciated.
SunflowerGames
The most beautiful user on RMN!
13323

I think if you haven't changed anything via script you can make the action time +100%. But that lets you essentially take 2 turns, which means you could attack then cast a spell or vice versa. But that's where I would start looking.
Trihan
"It's more like a big ball of wibbly wobbly...timey wimey...stuff."
3359
I'm working on this just now.

Edit: Here's what I've got so far. It works as long as Doublecast is a Special ability with the notetag <doublecast> and Magic is the third option in the actor's battle menu. It breaks if you cancel the action at any point. I'll continue working on fixing those issues later.

$imported = {} if $imported.nil?
$imported['MSN-Doublecast'] = true

puts 'Load: MySN\'s Doublecast v1.0 by Trihan'

module MSN
  
  module REGEXP
    DOUBLECAST = /<doublecast>/i
  end
  
end

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

module DataManager  
	#--------------------------------------------------------------------------
	# ● Loads the database
	#--------------------------------------------------------------------------
	class << self
		alias_method(:msn_dc_load_database, :load_database)
	end
	def self.load_database
		msn_dc_load_database
		load_doublecast_notetags
	end  
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def self.load_doublecast_notetags
    for obj in $data_skills
      next if obj.nil?
      obj.load_doublecast_notetags
		end
		puts "Read: Doublecast Notetags"
	end
end

#===========================================================================
# ■ RPG::Skill
#===========================================================================

class RPG::Skill < RPG::UsableItem
	#--------------------------------------------------------------------------
	# ● Public instance variables
	#--------------------------------------------------------------------------
  attr_reader     :doublecast
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def load_doublecast_notetags
		@note.split(/[\r\n]+/).each do |line|
			case line
			when MSN::REGEXP::DOUBLECAST
        @doublecast = true
			end
		end
	end
end

class Game_Battler < Game_BattlerBase
  def add_action(skill_id, target_index)
    action = Game_Action.new(self, true)
    action.set_skill(skill_id)
    if target_index == -2
      action.target_index = last_target_index
    elsif target_index == -1
      action.decide_random_target
    else
      action.target_index = target_index
    end
    @actions.push(action)
  end
end

class Game_Actor < Game_Battler
  def increase_action_index
    @action_input_index += 1
  end
end

class Scene_Battle < Scene_Base
  def on_skill_ok
    @skill = @skill_window.item
    BattleManager.actor.input.set_skill(@skill.id)
    BattleManager.actor.last_skill.object = @skill
    if @skill.doublecast
      @dc_state = :choose_1
      @skill_window.stype_id = 2
      @skill_window.refresh
      @skill_window.show.activate
    elsif !@skill.need_selection?
      @skill_window.hide
      next_command
    elsif @skill.for_opponent?
      select_enemy_selection
    else
      select_actor_selection
    end
  end
  
  def on_enemy_ok
    if @dc_state == :choose_1
      BattleManager.actor.input.target_index = @enemy_window.enemy.index
      @enemy_window.hide
      
      BattleManager.actor.add_action(@skill.id, @enemy_window.enemy.index)
      BattleManager.actor.increase_action_index
      
      @skill_window.show.activate
      @dc_state = :choose_2
    else
      BattleManager.actor.input.target_index = @enemy_window.enemy.index
      @enemy_window.hide
      @skill_window.hide
      @item_window.hide
      @dc_state = nil
      next_command
    end
  end
end
EDIT: Never mind, I saw what goes wrong if you cancel.

Cool! Thank you! I'm actually a programmer to, so I'll see what I can do about fixing it as well, I'm just not super great with Ruby, and I haven't mucked around with the engine enough to know where everything is in the code.

If I figure out the solution to this? I'll post it here.

So, all I have to do to start testing this is paste it into the "Materials section" of the scripting area right?

(As I said, Ruby is new to me, so I'm still figuring out how all of this works)
Trihan
"It's more like a big ball of wibbly wobbly...timey wimey...stuff."
3359
Paste it as a new script below the default scripts but above Main.
Hey, one more thing. Because it overwrites the actions with different actions, it doesn't actually have a TP cost. Where in the script would I want to put this:

if @dc_state == :choose_2
#Insert code here to lower actors TP by the cost of double cast
@dc_state = :none
end
Trihan
"It's more like a big ball of wibbly wobbly...timey wimey...stuff."
3359
The inherent problem currently is that the code we've changed doesn't affect actions actually being carried out, which is where your TP costs and such are factored in. What you could do is add an additional action for the doublecast in on_skill_ok and increase the action index again; that would cause the doublecast skill to actually be used. Just set the scope to user or something.
RIGHT! Thank you. I added cancelling to it to. And it works properly (EG, cancelling backtracks by one menu rather than cancelling the entire skill altogether).

Do you mind if I continue to use this code? Even if I make a commercial game? I will give you credit for it of course!

EDIT: The current game I'm working on isn't commercial, or at least, not intended to be at the moment.
Also question, what's the target index for the user? That's 0 right?
Seems to be working perfectly now! THANK YOU SO MUCH!

If you want, I'll post the completed code here, or send it to you.

:-D
Trihan
"It's more like a big ball of wibbly wobbly...timey wimey...stuff."
3359
If you wouldn't mind posting the completed code that would be great. As long as you credit me for the initial code you can use it for whatever you like, though if you do use it for a commercial game I expect at least a free copy of it. :)
Sure! I'd expect nothing less in your place!

Mind you, there is one thing that the scripting doesn't take into account because I solved it via states rather than scripting: If you use Doublecast to cast spells that have TP gains, you'll still gain the TP, meaning you could in theory use Doublecast and GAIN TP if the total TP gain of the pair of spells you cast is greater than the cost of Doublecast.

As far as I can tell, the code works error free... but of course I probably haven't tested every possible permutation, so if you find a glitch? I'd love to hear about it.

Here's the code:

$imported = {} if $imported.nil?
$imported['MSN-Doublecast'] = true

puts 'Load: MySN\'s Doublecast v1.0 by Trihan and MySN'

module MSN
  
  module REGEXP
    DOUBLECAST = /<doublecast>/i
  end
  
end

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

module DataManager  
	#--------------------------------------------------------------------------
	# ● Loads the database
	#--------------------------------------------------------------------------
	class << self
		alias_method(:msn_dc_load_database, :load_database)
	end
	def self.load_database
		msn_dc_load_database
		load_doublecast_notetags
	end  
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def self.load_doublecast_notetags
    for obj in $data_skills
      next if obj.nil?
      obj.load_doublecast_notetags
		end
		puts "Read: Doublecast Notetags"
	end
end

#===========================================================================
# ■ RPG::Skill
#===========================================================================

class RPG::Skill < RPG::UsableItem
	#--------------------------------------------------------------------------
	# ● Public instance variables
	#--------------------------------------------------------------------------
  attr_reader     :doublecast
	#--------------------------------------------------------------------------
	# ● Loads the note tags
	#--------------------------------------------------------------------------
	def load_doublecast_notetags
		@note.split(/[\r\n]+/).each do |line|
			case line
			when MSN::REGEXP::DOUBLECAST
        @doublecast = true
			end
		end
	end
end

class Game_Battler < Game_BattlerBase
  def add_action(skill_id, target_index)
    action = Game_Action.new(self, true)
    action.set_skill(skill_id)
    if target_index == -2
      action.target_index = last_target_index
    elsif target_index == -1
      action.decide_random_target
    else
      action.target_index = target_index
    end
    @actions.push(action)
  end
end

class Game_Actor < Game_Battler
  def increase_action_index
    @action_input_index += 1
  end

  def decrease_action_index
    @action_input_index -= 1
  end
end

class Scene_Battle < Scene_Base
  def on_skill_ok
    @skill = @skill_window.item
    BattleManager.actor.input.set_skill(@skill.id)
    BattleManager.actor.last_skill.object = @skill
    if @skill.doublecast
      @dc_state = :choose_1

      BattleManager.actor.add_action(@skill.id, 0)
      BattleManager.actor.increase_action_index

      @skill_window.stype_id = 1
      @skill_window.refresh
      @skill_window.show.activate
    elsif !@skill.need_selection?
      @skill_window.hide
      next_command
    elsif @skill.for_opponent?
      select_enemy_selection
    else
      select_actor_selection
    end
  end

  def on_skill_cancel
    @skill_window.hide
    if @dc_state == :choose_2
      @dc_state = :choose_1

      BattleManager.actor.remove_current_action
      BattleManager.actor.decrease_action_index

      @skill_window.stype_id = 1
      @skill_window.refresh
      @skill_window.show.activate
    else
      if @dc_state == :choose_1
        BattleManager.actor.remove_current_action
        BattleManager.actor.decrease_action_index
        @dc_state = nil
      end
      @actor_command_window.activate
    end
  end

  def on_enemy_ok
    if @dc_state == :choose_1
      @dc_state = :choose_2
      BattleManager.actor.input.target_index = @enemy_window.enemy.index
      @enemy_window.hide

      BattleManager.actor.add_action(@skill.id, @enemy_window.enemy.index)
      BattleManager.actor.increase_action_index

      @skill_window.show.activate
    else
      if @dc_state == :choose_2
        @dc_state = :ready
      else
        @dc_state = nil
      end
      BattleManager.actor.input.target_index = @enemy_window.enemy.index
      @enemy_window.hide
      @skill_window.hide
      @item_window.hide
      next_command
    end
  end

  def on_enemy_cancel
    @enemy_window.hide
    if @dc_state == :choose_1 || @dc_state == :choose_2
      @skill_window.stype_id = 1
      @skill_window.refresh
      @skill_window.show.activate
    else
      case @actor_command_window.current_symbol
      when :attack
        @actor_command_window.activate
      when :skill
        @skill_window.activate
      when :item
        @item_window.activate
      end
    end
  end

  def on_actor_ok
    if @dc_state == :choose_1
      @dc_state = :choose_2
      BattleManager.actor.input.target_index = @enemy_window.enemy.index
      @actor_window.hide

      BattleManager.actor.add_action(@skill.id, @enemy_window.enemy.index)
      BattleManager.actor.increase_action_index      

      @skill_window.show.activate
    else
      if @dc_state == :choose_2
        @dc_state = :ready
      else
        @dc_state = nil
      end
      BattleManager.actor.input.target_index = @actor_window.index
      @actor_window.hide
      @skill_window.hide
      @item_window.hide
      next_command
    end
  end

  def on_actor_cancel
    @actor_window.hide
    if @dc_state == :choose_1 || @dc_state == :choose_2
      @skill_window.stype_id = 1
      @skill_window.refresh
      @skill_window.show.activate
    else
      case @actor_command_window.current_symbol
      when :skill
        @skill_window.activate
      when :item
        @item_window.activate
      end
    end
  end
end
Sorry... I don't know how to format it like code in the post...
Trihan
"It's more like a big ball of wibbly wobbly...timey wimey...stuff."
3359
Click the "code" icon (it's the fourth from the right in the list) and put "ruby" as the code type.
Awesome! I've spruced up the code since then... and fixed a couple of bugs, but it's also like... all intertwined with other code now, so I'll update it later.

But that works well enough, and bug fixing it shouldn't take very long.
Trihan
"It's more like a big ball of wibbly wobbly...timey wimey...stuff."
3359
Hooray for teamwork!
Pages: 1