03-29-2021, 04:57 AM
(This post was last modified: 04-03-2021, 10:29 PM by kyonides.
Edit Reason: Better Explanation + Bug Fix
)
KSkillRunes XP
Version Beta 9
by Kyonides Arkanthes
Introduction
The following script pretends to be an alternative to a Materia System. It uses the so called Runes to let you learn new skills. You then get the need to sum up rune points in order to activate those skills permanently or to level them up.
Instructions have been included in the script.
Script
Code:
# * KSkillRunes XP
# Scripter : Kyonides Arkanthes
# 2021-04-03 - Beta 9
# This script is a Rune Based Skill Learning System vaguely similar to a
# Materia System.
# * Instructions * #
# Create Items representing the Rune Skill Gem Stones.
# Create a Temp directory and place the template TXT file here and set its
# values accordingly. Copy and Paste it into new TXT files as many times as
# needed.
# Set the ITEM_IDS_RANGE constant's value below.
# If a Hero has acquired a Rune Gem Stone, no existing skills will be
# overwritten. Every Rune Gem Stone has an activation cost (in gold pieces).
# Every Rune Skill needs Rune Points so spend them wisely.
# Game_Battler#skill_effect has been overwritten.
# * Script Calls * #
# * Open Rune Scene - Positions: 0 through 3
# $scene = KSkillRuneScene.new
# $scene = KSkillRuneScene.new(ActorIndex)
# * First Select an Actor - Positions: 0 through 3
# actor = $game_party.actors[Position]
# * Set or Increase or Decrease the Maximum Number of the Actor's Skill Runes
# actor.skill_runes_max = Number
# actor.skill_runes_max += Number
# actor.skill_runes_max -= Number
# * Manually Increase an Actor's RP (Rune Points)
# actor.rp += Number
# * Use Rune Points RP to Activate a given Skill the Rune can teach the Hero
# actor.learn_rune_skill(RuneItemID, TargetSkillID)
module KSRunes
TEMP_DIR = "Temp"
MISSED_TARGET = "Miss"
TITLE = 'Skill Runes'
STARTING_RUNE_MAX = 1
ITEM_IDS_RANGE = 40..51
BACKDROP = ''
ACTOR_BLOCKED_RUNES = {}
# * End of Setup Section * #
class Skill
attr_accessor :id, :level, :learn_skill, :skill_points
def can_learn?(pts) @skill_points == pts end
end
class Rune
def initialize
@id = 0
@name = ""
@level = 0
@level_max = 1
@blocked_rune = 0
@price = 0
@skills = {}
end
attr_accessor :id, :name, :level, :level_max, :blocked_rune, :price, :skills
end
extend self
attr_reader :runes
def scan_int(line) line.scan(/\d+/).map{|d| d.to_i } end
def parse_skill(numbers)
skill = Skill.new
skill.id = numbers.shift
skill.level = numbers.shift
skill.learn_skill = numbers.shift
skill.skill_points = numbers.shift
skill
end
def parse_file(name)
rune = Rune.new
lines = File.readlines(name)
rune.id = scan_int(lines.shift)[0]
rune.name = lines.shift.sub(/magic type: /i, "")
rune.level = scan_int(lines.shift)[0]
rune.level_max = scan_int(lines.shift)[0]
rune.blocked_rune = scan_int(lines.shift)[0] || 0
rune.price = scan_int(lines.shift)[0]
n = 0
lines.each do |line|
numbers = scan_int(line)
skill = parse_skill(numbers)
rune.skills[skill.id] = skill
end
@runes[rune.id] = rune
end
def retrieve_runes
return @runes = load_data('Data/KSkillRunes.rxdata') unless $DEBUG
@runes = {}
Dir[TEMP_DIR + '/*.txt'].sort.each{|name| parse_file(name) }
File.open('Data/KSkillRunes.rxdata', 'wb'){|f| Marshal.dump(@runes, f) }
end
retrieve_runes
end
class Game_Battler
def alive_not_dead?(skill)
(skill.scope == 3 or skill.scope == 4) and @hp == 0
end
def dead_not_alive?(skill)
(skill.scope == 5 or skill.scope == 6) and @hp >= 1
end
def calculate_skill_power
power = @skill.power
if @user.is_actor? and @user.rune_skill?(@skill.id)
rune_skill = @user.rune_skills[@skill.id]
power += @skill.variance * rune_skill.level
end
power = power + @user.atk * @skill.atk_f / 100
if power > 0
power -= self.pdef * @skill.pdef_f / 200
power -= self.mdef * @skill.mdef_f / 200
power = [power, 0].max
end
power
end
def checking_hit(hit, hit_result)
return hit unless hit_result
power = calculate_skill_power
rate = 20
rate += (@user.str * @skill.str_f / 100)
rate += (@user.dex * @skill.dex_f / 100)
rate += (@user.agi * @skill.agi_f / 100)
rate += (@user.int * @skill.int_f / 100)
@damage = power * rate / 20
@damage *= elements_correct(@skill.element_set)
@damage /= 100
@damage /= 2 if @damage > 0 and self.guarding?
if @skill.variance > 0 and @damage.abs > 0
amp = [@damage.abs * @skill.variance / 100, 1].max
@damage += rand(amp+1) + rand(amp+1) - amp
end
eva = 8 * self.agi / @user.dex + self.eva
hit = @damage < 0 ? 100 : 100 - eva * @skill.eva_f / 100
self.cant_evade? ? 100 : hit
end
def checking_effectivity(effective)
if @skill.power != 0 and @skill.atk_f > 0
remove_states_shock
effective = true
end
last_hp = @hp
self.hp -= @damage
effective |= @hp != last_hp
@state_changed = false
effective |= states_plus(@skill.plus_state_set)
effective |= states_minus(@skill.minus_state_set)
@last_damage = @damage
if @skill.power == 0
@damage = @state_changed ? "" : KSRunes::MISSED_TARGET
@last_damage = 0
end
effective
end
def skill_effect(user, skill)
@critical = false
user.last_skill = $game_temp.in_battle ? skill : nil
return false if alive_not_dead?(skill) or dead_not_alive?(skill)
@user = user
@skill = skill
effective = false
effective |= @skill.common_event_id > 0
hit = @skill.hit
hit *= @user.hit / 100 if @skill.atk_f > 0
hit_result = (rand(100) < hit)
effective |= hit < 100
hit = checking_hit(hit, hit_result)
effective |= hit < 100
hit_result = (rand(100) < hit)
if hit_result
effective = checking_effectivity(effective)
else
@damage = "Miss"
@last_damage = 0
end
unless $game_temp.in_battle
@damage = nil
@last_damage = 0
end
@skill = @user = nil
return effective
end
attr_accessor :last_skill, :last_damage
end
class Game_Actor
alias :kyon_skillrunes_gm_actor_init :initialize
def initialize(actor_id)
kyon_skillrunes_gm_actor_init(actor_id)
@skill_runes_max = KSRunes::STARTING_RUNE_MAX
@rune_skills = {}
@rp = 0
end
def item_effect(item)
item_id = item.id
return super(item) unless KSRunes::ITEM_IDS_RANGE.include?(item_id)
return false unless learn_from_rune?(item_id)
return false if rune_skill?(item_id)
return false if skill_runes_max?
rune = KSRunes.runes[item_id]
return false if $game_party.gold < rune.price
$game_party.gain_gold(-rune.price)
skills = rune.skills
learn_rune_skills(rune.blocked_rune, skills.values)
skills.each{|k,v| @rune_skills[k] ||= v.dup }
end
def learn_rune_skill(rid, sid)
rskills = @rune_skills[rid]
return "No Rune" unless rskills
skill = rskills[sid]
return "Wrong Skill ID" unless skill
return "Not Enough RP" if @rp == 0 or skill.skill_points > @rp
skill.level += 1 if skill.level < KSRunes.runes[rid].level_max
@rp -= skill.skill_points
end
def learn_from_rune?(rune_id)
blocked_runes = KSRunes::ACTOR_BLOCKED_RUNES[@actor_id]
return true unless blocked_runes
!blocked_runes.include?(rune_id)
end
def learn_rune_skill?(level, skill_id, skill)
return false if @level < level or skill_learn?(skill_id)
skill.can_learn?(@rp)
end
def learn_rune_skills(rune_id, blocked_rune, skills)
br = blocked_rune
skills = skills.map{|s| s.id if learn_rune_skill?(s.level, br, s) }
skills = skills.compact
@skills = (@skills + skills).uniq.sort
end
def rune_skill?(skill_id) @rune_skills.has_key?(skill_id) end
def skill_runes_max?() @rune_skills.size == @skill_runes_max end
def is_actor?() true end
def runes() @rune_skills.keys.sort end
attr_accessor :skill_runes_max, :rp
attr_reader :rune_skills
end
class Game_Enemy
def is_actor?() false end
end
class KSRuneSpriteset
include KSRunes
def initialize(pos)
@index = pos
@rune_index = 0
@actors = $game_party.actors
actor = @actors[@index]
@backdrop = Sprite.new
@backdrop.bitmap = RPG::Cache.title(BACKDROP)
@heading = Sprite.new
@heading.x = 160
@heading.y = 8
@heading.bitmap = b = Bitmap.new(320, 32)
b.draw_text(0, 4, 320, 24, TITLE, 1)
@name_sprite = Sprite.new
@name_sprite.x = 8
@name_sprite.y = 36
@name_sprite.bitmap = b = Bitmap.new(240, 32)
b.draw_text(0, 4, 240, 24, actor.name, 1)
@icon_names = actor.runes.map{|n| $data_items[n].icon_name }
@icons = []
@icon_labels = []
@icon_names.size.times{|n| draw_rune_icons(n) }
@sprites = [@backdrop, @heading, @name_sprite]
end
def draw_rune_icons(pos)
@icons << s = Sprite.new
s.x = 8
s.y = 64 + pos * 28
s.bitmap = RPG::Cache.icon(@icon_names[pos])
@icon_labels << l = Sprite.new
l.x = s.x + 28
l.y = s.y
l.bitmap = b = Bitmap.new(200, 24)
b.draw_text(0, 0, 200, 24, @icon_names[pos])
end
def dispose
@icon_labels.each{|s| s.dispose }
@sprites.each{|s| s.dispose }
@icons.each{|s| s.dispose }
@sprites.clear
@icons.clear
@icon_names.clear
@actors = nil
end
attr_reader :rune_index
end
class KSkillRuneScene
def initialize(pos=0) @index = pos end
def main
@run = true
@spriteset = KSRuneSpriteset.new(@index)
Graphics.transition
while @run
Graphics.update
Input.update
update
end
Graphics.freeze
@spriteset.dispose
end
def update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return @run = nil
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
end
end
end
Rune Template
Code:
ID 43
Magic Type: Frost
Character Level: 5
Skill Level Max: 3
Blocked Runes: None
Gold: 180
Skill 12 Level 5 Skill 1 Points 10
Skill 13 Level 8 Skill 12 Points 20
Skill 14 Level 11 Skill 13 Points 30
Questions & Answers
Q: Can I open a menu and set the runes on a given hero?
A: You are able to open the item menu and select the rune and assign it to a given hero... and that's it!
Q: Can I activate rune gem stones for free?
A: Actually nope, you can't. You need to pay the price in gold pieces. The cost will be subtracted from your purse automatically.
Terms & Conditions
Free to use in any non commercial game.
Contact me if you need it for a commercial game.
Send me a copy of your full game if you use 2 or more of my scripts.
Do Not Repost This Script!
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE