Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Dragon Soul System (or: Party-Shared Skill Points)

Dragon Soul SystemVersion: 1.0
By: Armor Nick

Introduction

This script emulates the Dragon Soul system from The Elder Scrolls: Skyrim.

Certain characters are 'Dragonborn' who can spend Dragon Souls to unlock special Dragon Shouts. Dragon Souls are gained by defeating certain enemies.

Dragon Souls are shared by the party but are spend on characters.
Creative Uses
  • Straight-up Skyrim Dragon Slaying!
  • Strategic skill management by learning skills based on the whole party.
  • A fairly original system to learn skills

Screenshots

afterbattle.png

sceneshouts.png

Demo

Will do if there is enough want.

Script

The script is divided in 2 parts. This was done because I couldn't add the 'Shouts' command to the main menu without breaking any CMS or other Menu Addon you might have. I suggest taking a look at the differences between your current menu and the menu I posted to see what you have to change.

Code:
 

#==============================================================================

# ** Dragon Souls

#------------------------------------------------------------------------------

# Armor Nick

# 1.0

# 2011-12-05

#------------------------------------------------------------------------------

# This script emulates the Dragon Soul system from The Elder Scrolls: Skyrim

#

# Certain characters are 'Dragonborn' who can spend Dragon Souls to unlock

# special Dragon Shouts. Dragon Souls are gained by defeating certain enemies.

#

# Dragon Souls are shared by the party but are spend on characters.

#------------------------------------------------------------------------------

# Instructions:

#

# ** Unlocking a Shout:

#     $game_party.unlock_shout(skill_id)

#

# ** Adding Souls to the party:

#     $game_party.gain_souls(n)

#

# ** Testing if we have a certain Shout/Skill:

#     $game_party.has_shout?(skill_id)

#

# ** To call the Shouts screen:

#     $scene = Scene_Shouts.new(actor_index)

#     where: actor_index = the index of the actor in your party

#------------------------------------------------------------------------------

# To edit where the menu goes when you press escape:

#   Control+F DS_MENU_RETURN and edit the method you find there.

#==============================================================================

 

  Vocab::Shouts = "Shouts"

  Vocab::Souls = "Souls"

  Vocab::ObtainSouls = "%s %s were obtained!"

  # NOTE: the above text MUST obtain '' exactly 2 times

  # unless you change display_exp_and_gold at the bottom

  # these variables are respectively the amount and Vocab::Souls

 

  #----------------------------------------------------------------------------

  # Begin ANA module

  #----------------------------------------------------------------------------

  module ANA

    

    #------------------------------------------------------------------------------

    # * Characters who can learn Dragon Skills (actor_id)

    #------------------------------------------------------------------------------

    DRAGONBORN = [1, 3, 5, 7]

    

    #------------------------------------------------------------------------------

    # * Characters who give Dragon Souls

    #------------------------------------------------------------------------------

    DRAGONS = [1]

  

  #----------------------------------------------------------------------------

  # End ANA module

  #----------------------------------------------------------------------------    

  end

  

#==============================================================================

# ** Game_Party

#==============================================================================

class Game_Party < Game_Unit

  

  #--------------------------------------------------------------------------

  # * Public Instance Variables

  #--------------------------------------------------------------------------

  attr_accessor    :souls                    # number of dragon souls

  attr_reader      :shouts                   # list of unlocked shouts

  

  #--------------------------------------------------------------------------

  # * Alias Listings

  #--------------------------------------------------------------------------

  alias armornick_dragonsouls_gmparty_initialize initialize

  

  #--------------------------------------------------------------------------

  # * Object Initialization

  #--------------------------------------------------------------------------

  def initialize

    @souls = 0

    @shouts = []

    armornick_dragonsouls_gmparty_initialize

  end

  

  #--------------------------------------------------------------------------

  # * Unlock Shout

  #     skill_id : ID of the skill (shout)

  #--------------------------------------------------------------------------  

  def unlock_shout(skill_id = 0)

    unless has_shout?(skill_id)

      @shouts.push(skill_id)

      @shouts.sort!

    end

  end

  

  #--------------------------------------------------------------------------

  # * Do we have the given shout?

  #--------------------------------------------------------------------------

  def has_shout?(skill_id)

    return @shouts.include?(skill_id)

  end

  

  #--------------------------------------------------------------------------

  # * Do we have any souls or shouts?

  #--------------------------------------------------------------------------

  def has_souls_or_shouts?

    result = @souls > 0 || @shouts.length > 0

    return result

  end

  

  #--------------------------------------------------------------------------

  # * Gain the given amount of souls

  #--------------------------------------------------------------------------  

  def gain_souls(n)

    @souls += n

  end

  

end #class Game_Party < Game_Unit

 

#==============================================================================

# ** Game_Troop

#==============================================================================

 

class Game_Troop < Game_Unit

  #--------------------------------------------------------------------------

  # * Calculate Number of Souls

  #--------------------------------------------------------------------------

  def souls_total

    gold = 0

    for enemy in dead_members

      gold += 1 if ANA::DRAGONS.include?(enemy.enemy_id )

    end

    return gold

  end

  

end #class Game_Troop < Game_Unit

 

#==============================================================================

# ** Window_Shouts

#------------------------------------------------------------------------------

#  This window displays a list of the shouts the party has discovered

#==============================================================================

 

class Window_Shouts < Window_Selectable

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     x      : window x-coordinate

  #     y      : window y-coordinate

  #     width  : window width

  #     height : window height

  #--------------------------------------------------------------------------

  def initialize(x, y, width, height, actor)

    super(x, y, width, height)

    @actor = actor

    @column_max = 2

    self.index = 0

    refresh

  end

  #--------------------------------------------------------------------------

  # * Get Skill

  #--------------------------------------------------------------------------

  def shout

    return @data[self.index]

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    @data = []

    for shout in $game_party.shouts

      @data.push($data_skills[shout])

    end

    @item_max = @data.size

    create_contents

    for i in 0...@item_max

      draw_item(i)

    end

  end

  #--------------------------------------------------------------------------

  # * Draw Item

  #     index : item number

  #--------------------------------------------------------------------------

  def draw_item(index)

    rect = item_rect(index)

    self.contents.clear_rect(rect)

    shout = @data[index]

    if shout != nil

      rect.width -= 4

      enabled = $game_party.souls > 0 && !@actor.skill_learn?(shout)

      draw_item_name(shout, rect.x, rect.y, enabled)

      self.contents.draw_text(rect, @actor.calc_mp_cost(shout), 2)

    end

  end

  #--------------------------------------------------------------------------

  # * Update Help Text

  #--------------------------------------------------------------------------

  def update_help

    @help_window.set_text(shout == nil ? "" : shout.description)

  end

  

end #class Window_Shouts < Window_Selectable

 

#==============================================================================

# ** Window_Souls

#------------------------------------------------------------------------------

#  This window displays the amount of souls.

#==============================================================================

 

class Window_Souls < Window_Base

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     x : window X coordinate

  #     y : window Y coordinate

  #--------------------------------------------------------------------------

  def initialize(x, y)

    super(x, y, 160, WLH + 32)

    refresh

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    draw_souls_value($game_party.souls, 4, 0, 120)

  end

  

  #--------------------------------------------------------------------------

  # * Draw number with currency unit

  #     value : Number (gold, etc)

  #     x     : draw spot x-coordinate

  #     y     : draw spot y-coordinate

  #     width : Width

  #--------------------------------------------------------------------------

  def draw_souls_value(value, x, y, width)

    cx = contents.text_size(Vocab::Souls + "\t").width

    self.contents.font.color = normal_color

    self.contents.draw_text(x, y, width-cx-2, WLH, value, 2)

    self.contents.font.color = system_color

    self.contents.draw_text(x, y, width, WLH, Vocab::Souls, 2)

  end

 

end #class Window_Souls < Window_Base

 

#==============================================================================

# ** Window_ShoutStatus

#------------------------------------------------------------------------------

#  This window displays the skill user's status on the shouts screen.

#==============================================================================

 

class Window_ShoutStatus < Window_Base

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     x     : window X coordinate

  #     y     : window Y corrdinate

  #     actor : actor

  #--------------------------------------------------------------------------

  def initialize(x, y, actor)

    super(x, y, 384, WLH + 32)

    @actor = actor

    refresh

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    draw_actor_name(@actor, 4, 0)

    draw_actor_level(@actor, 140, 0)

  end

 

end #class Window_ShoutStatus < Window_Base

 

#==============================================================================

# ** Scene_Shouts

#==============================================================================

 

class Scene_Shouts < Scene_Base

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     actor_index : actor index

  #--------------------------------------------------------------------------

  def initialize(actor_index = 0)

    @actor_index = actor_index

  end

  

  #--------------------------------------------------------------------------

  # * Start processing

  #--------------------------------------------------------------------------

  def start

    super

    create_menu_background

    @actor = $game_party.members[@actor_index]

    @viewport = Viewport.new(0, 0, 544, 416)

    @help_window = Window_Help.new

    @help_window.viewport = @viewport

    @status_window = Window_ShoutStatus.new(160, 56, @actor)

    @status_window.viewport = @viewport

    @souls_window = Window_Souls.new(0,56)

    @souls_window.viewport = @viewport

    @shouts_window = Window_Shouts.new(0, 112, 544, 304, @actor)

    @shouts_window.viewport = @viewport

    @shouts_window.help_window = @help_window

  end

  

  #--------------------------------------------------------------------------

  # * Termination Processing

  #--------------------------------------------------------------------------

  def terminate

    super

    dispose_menu_background

    @help_window.dispose

    @status_window.dispose

    @shouts_window.dispose

    @souls_window.dispose

  end

  #--------------------------------------------------------------------------

  # * Return to Original Screen

  #     DS_MENU_RETURN

  #--------------------------------------------------------------------------

  def return_scene

    # Edit this method to choose where you go after pressing escape

    # $scene = Scene_Map.new    # I want to go back to the map screen

    $scene = Scene_Menu.new(6)  # I want to go back to the menu (index)

  end  

 

  #--------------------------------------------------------------------------

  # * Frame Update

  #--------------------------------------------------------------------------

  def update

    super

    update_menu_background

    @help_window.update

    @status_window.update

    @shouts_window.update

    @souls_window.update

    if @shouts_window.active

      update_skill_selection

    end

  end  

  

  #--------------------------------------------------------------------------

  # * Update Skill Selection

  #--------------------------------------------------------------------------

  def update_skill_selection

    if Input.trigger?(Input::B)

      Sound.play_cancel

      return_scene

  elsif Input.trigger?(Input::C)

      @shout = @shouts_window.shout

      if $game_party.souls > 0 and !@actor.skill_learn?(@shout)

        Sound.play_decision

        learn_shout

      else

        Sound.play_buzzer

      end

    end

  end  

 

  #--------------------------------------------------------------------------

  # * Learn Selected Shout

  #--------------------------------------------------------------------------  

  def learn_shout

    # teach the shout and remove soul

    $game_party.souls -= 1

    @actor.learn_skill(@shout.id)

    # refresh the windows

    @status_window.refresh

    @shouts_window.refresh

    @souls_window.refresh

  end

  

end #class Scene_Shouts < Scene_Base

 

#==============================================================================

# ** Scene_Battle

#------------------------------------------------------------------------------

#  This class performs battle screen processing.

#==============================================================================

 

class Scene_Battle < Scene_Base

  

  #--------------------------------------------------------------------------

  # * Alias Listings

  #--------------------------------------------------------------------------

  alias armornick_dragonsouls_sbattle_display_exp_and_gold display_exp_and_gold

  

  #--------------------------------------------------------------------------

  # * Display Gained Experience and Gold

  #--------------------------------------------------------------------------

  def display_exp_and_gold

    souls = $game_troop.souls_total

    $game_party.gain_souls(souls)

    if souls > 0

      text = sprintf(Vocab::ObtainSouls, souls, Vocab::Souls)

      $game_message.texts.push('\.' + text)

    end

    armornick_dragonsouls_sbattle_display_exp_and_gold 

  end

  

end #class Scene_Battle < Scene_Base

 

Code:
 

#==============================================================================

# ** Scene_Menu

#==============================================================================

class Scene_Menu < Scene_Base

  #--------------------------------------------------------------------------

  # * Create Command Window

  #--------------------------------------------------------------------------

  def create_command_window

    s1 = Vocab::item

    s2 = Vocab::skill

    s3 = Vocab::equip

    s4 = Vocab::status

    s5 = Vocab::save

    s6 = Vocab::game_end

    s7 = Vocab::Shouts

    @command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6, s7])

    @command_window.index = @menu_index

    if $game_party.members.size == 0          # If number of party members is 0

      @command_window.draw_item(0, false)     # Disable item

      @command_window.draw_item(1, false)     # Disable skill

      @command_window.draw_item(2, false)     # Disable equipment

      @command_window.draw_item(3, false)     # Disable status

    end

    if $game_system.save_disabled             # If save is forbidden

      @command_window.draw_item(4, false)     # Disable save

    end

    # disable the command if we have no souls or shouts

    if ! $game_party.has_souls_or_shouts?

      @command_window.draw_item(6, false)     

    end

  end

  

  #--------------------------------------------------------------------------

  # * Update Command Selection

  #--------------------------------------------------------------------------

  def update_command_selection

    if Input.trigger?(Input::B)

      Sound.play_cancel

      $scene = Scene_Map.new

    elsif Input.trigger?(Input::C)

      if $game_party.members.size == 0 and @command_window.index < 4

        Sound.play_buzzer

        return

      elsif $game_system.save_disabled and @command_window.index == 4

        Sound.play_buzzer

        return

      elsif ! $game_party.has_souls_or_shouts? and @command_window.index == 6

        Sound.play_buzzer

        return

      end

      Sound.play_decision

      case @command_window.index

      when 0      # Item

        $scene = Scene_Item.new

      when 1,2,3,6  # Skill, equipment, status

        start_actor_selection

      when 4      # Save

        $scene = Scene_File.new(true, false, false)

      when 5      # End Game

        $scene = Scene_End.new

      end

    end

  end

  

  #--------------------------------------------------------------------------

  # * Update Actor Selection

  #--------------------------------------------------------------------------

  def update_actor_selection

    if Input.trigger?(Input::B)

      Sound.play_cancel

      end_actor_selection

    elsif Input.trigger?(Input::C)

      $game_party.last_actor_index = @status_window.index

      Sound.play_decision

      case @command_window.index

      when 1  # skill

        $scene = Scene_Skill.new(@status_window.index)

      when 2  # equipment

        $scene = Scene_Equip.new(@status_window.index)

      when 3  # status

        $scene = Scene_Status.new(@status_window.index)

      when 6

        if ANA::DRAGONBORN.include?($game_party.members[@status_window.index].id)

          $scene = Scene_Shouts.new(@status_window.index)

        end

      end

    end

  end  

  

end

 

Instructions
To install, just insert the first or both of the scripts in the script editor above main. You should know this by now.

** Unlocking a Shout:
$game_party.unlock_shout(skill_id)

** Adding Souls to the party:
$game_party.gain_souls(n)

** Testing if we have a certain Shout/Skill:
$game_party.has_shout?(skill_id)

** To call the Shouts screen:
$scene = Scene_Shouts.new(actor_index)
where: actor_index = the index of the actor in your party

To edit where Scene_Shouts goes when you leave the menu:
Control+F DS_MENU_RETURN in the script and edit the method you find there.
Pre-defined methods for the Main Menu and the Map are available.

FAQ
Ask away.

Compatibility

Should be compatible with most scripts. Unless, of course, you use a CMS and my menu additions together in which case post a comment and I may possibly tinker something together.

Credits and Thanks

Thanks to Enterbrain for creating RPG Maker VX so I could muck about a bit.

Author's Notes

This is my first script for RPG Maker VX but I'm fairly confident so any critics are welcome.

Feel free to make requests and I may possibly tinker something together. However, I'm doing this for fun and I do have a real job so I'm not making any promises.

These are possible additions I thought of; post if you want one or more of them:
  • A different amount of Souls per enemy (fixed or variable)
  • Switches to get Souls from every enemy and/or be able to give Shouts to every actor
  • A maximum amount of Shouts and/or Souls for the actor and/or party

Terms and Conditions

Copyright (c) 2011, Nick Arnoeyts
All rights reserved.
 
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
*  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*  Neither the name of Armor Nick, Nick Arnoeyts nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top