Refactoring and tidying

This commit is contained in:
Maruno17
2021-01-11 19:30:45 +00:00
parent a5d1359dfe
commit 2586c09c3c
37 changed files with 5288 additions and 5966 deletions

View File

@@ -32,73 +32,6 @@ class Win32API
width,height = rect.unpack('l4')[2..3]
return width,height
end
=begin
# Unused
def Win32API.SetWindowText(text)
hWnd = pbFindRgssWindow
swp = Win32API.new('user32','SetWindowTextA',%(l, p),'i')
swp.call(hWnd, text.to_s)
end
# Unused
def Win32API.SetWindowPos(w, h)
hWnd = pbFindRgssWindow
windowrect = Win32API.GetWindowRect
clientsize = Win32API.client_size
xExtra = windowrect.width-clientsize[0]
yExtra = windowrect.height-clientsize[1]
swp = Win32API.new('user32','SetWindowPos',%(l,l,i,i,i,i,i),'i')
win = swp.call(hWnd,0,windowrect.x,windowrect.y,w+xExtra,h+yExtra,0)
return win
end
# Unused
def Win32API.GetWindowRect
hWnd = pbFindRgssWindow
rect = [0,0,0,0].pack('l4')
Win32API.new('user32','GetWindowRect',%w(l p),'i').call(hWnd,rect)
x,y,width,height = rect.unpack('l4')
return Rect.new(x,y,width-x,height-y)
end
# Unused
def Win32API.focusWindow
window = Win32API.new('user32','ShowWindow','LL','L')
hWnd = pbFindRgssWindow
window.call(hWnd,9)
end
# Unused
def Win32API.fillScreen
setWindowLong = Win32API.new('user32','SetWindowLong','LLL','L')
setWindowPos = Win32API.new('user32','SetWindowPos','LLIIIII','I')
metrics = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
hWnd = pbFindRgssWindow
width = metrics.call(0)
height = metrics.call(1)
setWindowLong.call(hWnd,-16,0x00000000)
setWindowPos.call(hWnd,0,0,0,width,height,0)
Win32API.focusWindow
return [width,height]
end
# Unused
def Win32API.restoreScreen
setWindowLong = Win32API.new('user32','SetWindowLong','LLL','L')
setWindowPos = Win32API.new('user32','SetWindowPos','LLIIIII','I')
metrics = Win32API.new('user32','GetSystemMetrics','I','I')
hWnd = pbFindRgssWindow
width = SCREEN_WIDTH
height = SCREEN_HEIGHT
x = [(metrics.call(0)-width)/2,0].max
y = [(metrics.call(1)-height)/2,0].max
setWindowLong.call(hWnd,-16,0x14CA0000)
setWindowPos.call(hWnd,0,x,y,width+6,height+29,0)
Win32API.focusWindow
return [width,height]
end
=end
end

View File

@@ -219,12 +219,6 @@ def pbRepositionMessageWindow(msgwindow, linecount=2)
msgwindow.opacity = 0
end
end
if $game_message
case $game_message.background
when 1 then msgwindow.opacity=0 # dim
when 2 then msgwindow.opacity=0 # transparent
end
end
end
# internal function

View File

@@ -1,30 +1,11 @@
#===============================================================================
# Message variables
#===============================================================================
class Game_Message
attr_writer :visible
attr_writer :background
def visible
return @visible || false
end
def background
return @background || 0
end
end
#===============================================================================
#
#===============================================================================
class Scene_Map
def updatemini
oldmws=$game_temp.message_window_showing
oldvis=$game_message ? $game_message.visible : false
oldvis=false
$game_temp.message_window_showing=true
$game_message.visible=true if $game_message
loop do
$game_map.update
$game_player.update
@@ -39,7 +20,6 @@ class Scene_Map
break if $game_temp.transition_processing
end
$game_temp.message_window_showing=oldmws
$game_message.visible=oldvis if $game_message
@spriteset.update if @spriteset
@message_window.update if @message_window
end
@@ -52,10 +32,6 @@ class Scene_Battle
if self.respond_to?("update_basic")
update_basic(true)
update_info_viewport # Update information viewport
if $game_message && $game_message.visible
@info_viewport.visible = false
@message_window.visible = true
end
else
oldmws=$game_temp.message_window_showing
$game_temp.message_window_showing=true
@@ -507,7 +483,6 @@ def pbCreateMessageWindow(viewport=nil,skin=nil)
msgwindow.back_opacity=MessageConfig::WindowOpacity
pbBottomLeftLines(msgwindow,2)
$game_temp.message_window_showing=true if $game_temp
$game_message.visible=true if $game_message
skin=MessageConfig.pbGetSpeechFrame() if !skin
msgwindow.setSkin(skin)
return msgwindow
@@ -515,7 +490,6 @@ end
def pbDisposeMessageWindow(msgwindow)
$game_temp.message_window_showing=false if $game_temp
$game_message.visible=false if $game_message
msgwindow.dispose
end
@@ -592,9 +566,8 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
break if text == last_text
end
colortag = ""
if ($game_message && $game_message.background>0) ||
($game_system && $game_system.respond_to?("message_frame") &&
$game_system.message_frame != 0)
if $game_system && $game_system.respond_to?("message_frame") &&
$game_system.message_frame != 0
colortag = getSkinColor(msgwindow.windowskin,0,true)
else
colortag = getSkinColor(msgwindow.windowskin,0,isDarkSkin)
@@ -674,11 +647,6 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
end
########## Position message window ##############
pbRepositionMessageWindow(msgwindow,linecount)
if $game_message && $game_message.background==1
msgback = IconSprite.new(0,msgwindow.y,msgwindow.viewport)
msgback.z = msgwindow.z-1
msgback.setBitmap("Graphics/System/MessageBack")
end
if facewindow
pbPositionNearMsgWindow(facewindow,msgwindow,:left)
facewindow.viewport = msgwindow.viewport

View File

@@ -88,27 +88,27 @@ class PokeBattle_Move
baseAcc = pbBaseAccuracy(user,target)
return true if baseAcc==0
# Calculate all multiplier effects
modifiers = []
modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 1.0
modifiers = {}
modifiers[:base_accuracy] = baseAcc
modifiers[:accuracy_stage] = user.stages[PBStats::ACCURACY]
modifiers[:evasion_stage] = target.stages[PBStats::EVASION]
modifiers[:accuracy_multiplier] = 1.0
modifiers[:evasion_multiplier] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers)
# Check if move can't miss
return true if modifiers[BASE_ACC]==0
return true if modifiers[:base_accuracy] == 0
# Calculation
accStage = [[modifiers[ACC_STAGE],-6].max,6].min + 6
evaStage = [[modifiers[EVA_STAGE],-6].max,6].min + 6
accStage = [[modifiers[:accuracy_stage], -6].max, 6].min + 6
evaStage = [[modifiers[:evasion_stage], -6].max, 6].min + 6
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion<1
accuracy = (accuracy * modifiers[:accuracy_multiplier]).round
evasion = (evasion * modifiers[:evasion_multiplier]).round
evasion = 1 if evasion < 1
# Calculation
return @battle.pbRandom(100) < modifiers[BASE_ACC] * accuracy / evasion
return @battle.pbRandom(100) < modifiers[:base_accuracy] * accuracy / evasion
end
def pbCalcAccuracyModifiers(user,target,modifiers)
@@ -135,16 +135,17 @@ class PokeBattle_Move
BattleHandlers.triggerAccuracyCalcTargetItem(target.item,
modifiers,user,target,self,@calcType)
end
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] *= 5/3.0
# Other effects, inc. ones that set accuracy_multiplier or evasion_stage to
# specific values
if @battle.field.effects[PBEffects::Gravity] > 0
modifiers[:accuracy_multiplier] *= 5 / 3.0
end
if user.effects[PBEffects::MicleBerry]
user.effects[PBEffects::MicleBerry] = false
modifiers[ACC_MULT] *= 1.2
modifiers[:accuracy_multiplier] *= 1.2
end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::Foresight] && modifiers[:evasion_stage] > 0
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[:evasion_stage] > 0
end
#=============================================================================
@@ -241,14 +242,19 @@ class PokeBattle_Move
defense = (defense.to_f*stageMul[defStage]/stageDiv[defStage]).floor
end
# Calculate all multiplier effects
multipliers = [1.0, 1.0, 1.0, 1.0]
multipliers = {
:base_damage_multiplier => 1.0,
:attack_multiplier => 1.0,
:defense_multiplier => 1.0,
:final_damage_multiplier => 1.0
}
pbCalcDamageMultipliers(user,target,numTargets,type,baseDmg,multipliers)
# Main damage calculation
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT]).round, 1].max
defense = [(defense * multipliers[DEF_MULT]).round, 1].max
baseDmg = [(baseDmg * multipliers[:base_damage_multiplier]).round, 1].max
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
defense = [(defense * multipliers[:defense_multiplier]).round, 1].max
damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
target.damageState.calcDamage = damage
end
@@ -257,9 +263,9 @@ class PokeBattle_Move
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
if @battle.pbCheckGlobalAbility(:AURABREAK)
multipliers[BASE_DMG_MULT] *= 2/3.0
multipliers[:base_damage_multiplier] *= 2 / 3.0
else
multipliers[BASE_DMG_MULT] *= 4/3.0
multipliers[:base_damage_multiplier] *= 4 / 3.0
end
end
# Ability effects that alter damage
@@ -299,154 +305,154 @@ class PokeBattle_Move
end
# Parental Bond's second attack
if user.effects[PBEffects::ParentalBond]==1
multipliers[BASE_DMG_MULT] /= 4
multipliers[:base_damage_multiplier] /= 4
end
# Other
if user.effects[PBEffects::MeFirst]
multipliers[BASE_DMG_MULT] *= 1.5
multipliers[:base_damage_multiplier] *= 1.5
end
if user.effects[PBEffects::HelpingHand] && !self.is_a?(PokeBattle_Confusion)
multipliers[BASE_DMG_MULT] *= 1.5
multipliers[:base_damage_multiplier] *= 1.5
end
if user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
multipliers[BASE_DMG_MULT] *= 2
multipliers[:base_damage_multiplier] *= 2
end
# Mud Sport
if type == :ELECTRIC
@battle.eachBattler do |b|
next if !b.effects[PBEffects::MudSport]
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
break
end
if @battle.field.effects[PBEffects::MudSportField]>0
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
end
end
# Water Sport
if type == :FIRE
@battle.eachBattler do |b|
next if !b.effects[PBEffects::WaterSport]
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
break
end
if @battle.field.effects[PBEffects::WaterSportField]>0
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
end
end
# Terrain moves
if user.affectedByTerrain?
case @battle.field.terrain
when PBBattleTerrains::Electric
multipliers[BASE_DMG_MULT] *= 1.5 if type == :ELECTRIC
multipliers[:base_damage_multiplier] *= 1.5 if type == :ELECTRIC
when PBBattleTerrains::Grassy
multipliers[BASE_DMG_MULT] *= 1.5 if type == :GRASS
multipliers[:base_damage_multiplier] *= 1.5 if type == :GRASS
when PBBattleTerrains::Psychic
multipliers[BASE_DMG_MULT] *= 1.5 if type == :PSYCHIC
multipliers[:base_damage_multiplier] *= 1.5 if type == :PSYCHIC
end
end
if @battle.field.terrain==PBBattleTerrains::Misty && target.affectedByTerrain? &&
type == :DRAGON
multipliers[BASE_DMG_MULT] /= 2
multipliers[:base_damage_multiplier] /= 2
end
# Badge multipliers
if @battle.internalBattle
if user.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_ATTACK
multipliers[ATK_MULT] *= 1.1
elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPATK
multipliers[ATK_MULT] *= 1.1
if physicalMove? && @battle.pbPlayer.numbadges >= NUM_BADGES_BOOST_ATTACK
multipliers[:attack_multiplier] *= 1.1
elsif specialMove? && @battle.pbPlayer.numbadges >= NUM_BADGES_BOOST_SPATK
multipliers[:attack_multiplier] *= 1.1
end
end
if target.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] *= 1.1
elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] *= 1.1
if physicalMove? && @battle.pbPlayer.numbadges >= NUM_BADGES_BOOST_DEFENSE
multipliers[:defense_multiplier] *= 1.1
elsif specialMove? && @battle.pbPlayer.numbadges >= NUM_BADGES_BOOST_SPDEF
multipliers[:defense_multiplier] *= 1.1
end
end
end
# Multi-targeting attacks
if numTargets>1
multipliers[FINAL_DMG_MULT] *= 0.75
multipliers[:final_damage_multiplier] *= 0.75
end
# Weather
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
if type == :FIRE
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
elsif type == :WATER
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
when PBWeather::Rain, PBWeather::HeavyRain
if type == :FIRE
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
elsif type == :WATER
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
end
when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && specialMove? && @function!="122" # Psyshock
multipliers[DEF_MULT] *= 1.5
if target.pbHasType?(:ROCK) && specialMove? && @function != "122" # Psyshock
multipliers[:defense_multiplier] *= 1.5
end
end
# Critical hits
if target.damageState.critical
if NEW_CRITICAL_HIT_RATE_MECHANICS
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
else
multipliers[FINAL_DMG_MULT] *= 2
multipliers[:final_damage_multiplier] *= 2
end
end
# Random variance
if !self.is_a?(PokeBattle_Confusion)
random = 85+@battle.pbRandom(16)
multipliers[FINAL_DMG_MULT] *= random/100.0
multipliers[:final_damage_multiplier] *= random / 100.0
end
# STAB
if type && user.pbHasType?(type)
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
multipliers[:final_damage_multiplier] *= 2
else
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
end
end
# Type effectiveness
multipliers[FINAL_DMG_MULT] *= target.damageState.typeMod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[:final_damage_multiplier] *= target.damageState.typeMod.to_f / PBTypeEffectiveness::NORMAL_EFFECTIVE
# Burn
if user.status==PBStatuses::BURN && physicalMove? && damageReducedByBurn? &&
!user.hasActiveAbility?(:GUTS)
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
# Aurora Veil, Reflect, Light Screen
if !ignoresReflect? && !target.damageState.critical &&
!user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && physicalMove?
elsif target.pbOwnSide.effects[PBEffects::Reflect] > 0 && physicalMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && specialMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
elsif target.pbOwnSide.effects[PBEffects::LightScreen] > 0 && specialMove?
if @battle.pbSideBattlerCount(target) > 1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
end
end
# Minimize
if target.effects[PBEffects::Minimize] && tramplesMinimize?(2)
multipliers[FINAL_DMG_MULT] *= 2
multipliers[:final_damage_multiplier] *= 2
end
# Move-specific base damage modifiers
multipliers[BASE_DMG_MULT] = pbBaseDamageMultiplier(multipliers[BASE_DMG_MULT],user,target)
multipliers[:base_damage_multiplier] = pbBaseDamageMultiplier(multipliers[:base_damage_multiplier], user, target)
# Move-specific final damage modifiers
multipliers[FINAL_DMG_MULT] = pbModifyDamage(multipliers[FINAL_DMG_MULT],user,target)
multipliers[:final_damage_multiplier] = pbModifyDamage(multipliers[:final_damage_multiplier], user, target)
end
#=============================================================================

View File

@@ -1035,7 +1035,7 @@ end
class PokeBattle_Move_0A9 < PokeBattle_Move
def pbCalcAccuracyMultipliers(user,target,multipliers)
super
modifiers[EVA_STAGE] = 0 # Accuracy stat stage
modifiers[:evasion_stage] = 0
end
def pbGetDefenseStats(user,target)

View File

@@ -274,7 +274,12 @@ class PokeBattle_AI
defense = pbRoughStat(target,PBStats::SPDEF,skill)
end
##### Calculate all multiplier effects #####
multipliers = [1.0, 1.0, 1.0, 1.0]
multipliers = {
:base_damage_multiplier => 1.0,
:attack_multiplier => 1.0,
:defense_multiplier => 1.0,
:final_damage_multiplier => 1.0
}
# Ability effects that alter damage
moldBreaker = false
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
@@ -349,15 +354,15 @@ class PokeBattle_AI
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
if @battle.pbCheckGlobalAbility(:AURABREAK)
multipliers[BASE_DMG_MULT] *= 2/3
multipliers[:base_damage_multiplier] *= 2 / 3.0
else
multipliers[BASE_DMG_MULT] *= 4/3
multipliers[:base_damage_multiplier] *= 4 / 3.0
end
end
end
# Parental Bond
if skill>=PBTrainerAI.mediumSkill && user.hasActiveAbility?(:PARENTALBOND)
multipliers[BASE_DMG_MULT] *= 1.25
multipliers[:base_damage_multiplier] *= 1.25
end
# Me First
# TODO
@@ -365,7 +370,7 @@ class PokeBattle_AI
# Charge
if skill>=PBTrainerAI.mediumSkill
if user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
multipliers[BASE_DMG_MULT] *= 2
multipliers[:base_damage_multiplier] *= 2
end
end
# Mud Sport and Water Sport
@@ -373,21 +378,21 @@ class PokeBattle_AI
if type == :ELECTRIC
@battle.eachBattler do |b|
next if !b.effects[PBEffects::MudSport]
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
break
end
if @battle.field.effects[PBEffects::MudSportField]>0
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
end
end
if type == :FIRE
@battle.eachBattler do |b|
next if !b.effects[PBEffects::WaterSport]
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
break
end
if @battle.field.effects[PBEffects::WaterSportField]>0
multipliers[BASE_DMG_MULT] /= 3
multipliers[:base_damage_multiplier] /= 3
end
end
end
@@ -395,16 +400,16 @@ class PokeBattle_AI
if user.affectedByTerrain? && skill>=PBTrainerAI.mediumSkill
case @battle.field.terrain
when PBBattleTerrains::Electric
multipliers[BASE_DMG_MULT] *= 1.5 if type == :ELECTRIC
multipliers[:base_damage_multiplier] *= 1.5 if type == :ELECTRIC
when PBBattleTerrains::Grassy
multipliers[BASE_DMG_MULT] *= 1.5 if type == :GRASS
multipliers[:base_damage_multiplier] *= 1.5 if type == :GRASS
when PBBattleTerrains::Psychic
multipliers[BASE_DMG_MULT] *= 1.5 if type == :PSYCHIC
multipliers[:base_damage_multiplier] *= 1.5 if type == :PSYCHIC
end
end
if target.affectedByTerrain? && skill>=PBTrainerAI.mediumSkill
if @battle.field.terrain==PBBattleTerrains::Misty && type == :DRAGON
multipliers[BASE_DMG_MULT] /= 2
multipliers[:base_damage_multiplier] /= 2
end
end
# Badge multipliers
@@ -413,10 +418,10 @@ class PokeBattle_AI
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
# won't control the player's Pokémon.
if target.pbOwnedByPlayer?
if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] *= 1.1
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] *= 1.1
if move.physicalMove?(type) && @battle.pbPlayer.numbadges >= NUM_BADGES_BOOST_DEFENSE
multipliers[:defense_multiplier] *= 1.1
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges >= NUM_BADGES_BOOST_SPDEF
multipliers[:defense_multiplier] *= 1.1
end
end
end
@@ -424,7 +429,7 @@ class PokeBattle_AI
# Multi-targeting attacks
if skill>=PBTrainerAI.highSkill
if pbTargetsMultiple?(move,user)
multipliers[FINAL_DMG_MULT] *= 0.75
multipliers[:final_damage_multiplier] *= 0.75
end
end
# Weather
@@ -432,19 +437,19 @@ class PokeBattle_AI
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
if type == :FIRE
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
elsif type == :WATER
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
when PBWeather::Rain, PBWeather::HeavyRain
if type == :FIRE
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
elsif type == :WATER
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
end
when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock
multipliers[DEF_MULT] *= 1.5
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function != "122" # Psyshock
multipliers[:defense_multiplier] *= 1.5
end
end
end
@@ -454,45 +459,45 @@ class PokeBattle_AI
if skill>=PBTrainerAI.mediumSkill
if type && user.pbHasType?(type)
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
multipliers[:final_damage_multiplier] *= 2
else
multipliers[FINAL_DMG_MULT] *= 1.5
multipliers[:final_damage_multiplier] *= 1.5
end
end
end
# Type effectiveness
if skill>=PBTrainerAI.mediumSkill
typemod = pbCalcTypeMod(type,user,target)
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[:final_damage_multiplier] *= typemod.to_f / PBTypeEffectiveness::NORMAL_EFFECTIVE
end
# Burn
if skill>=PBTrainerAI.highSkill
if user.status==PBStatuses::BURN && move.physicalMove?(type) &&
!user.hasActiveAbility?(:GUTS) &&
!(MECHANICS_GENERATION >= 6 && move.function == "07E") # Facade
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
end
# Aurora Veil, Reflect, Light Screen
if skill>=PBTrainerAI.highSkill
if !move.ignoresReflect? && !user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
if @battle.pbSideBattlerCount(target) > 1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
elsif target.pbOwnSide.effects[PBEffects::Reflect] > 0 && move.physicalMove?(type)
if @battle.pbSideBattlerCount(target) > 1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
elsif target.pbOwnSide.effects[PBEffects::LightScreen] > 0 && move.specialMove?(type)
if @battle.pbSideBattlerCount(target) > 1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[FINAL_DMG_MULT] /= 2
multipliers[:final_damage_multiplier] /= 2
end
end
end
@@ -500,7 +505,7 @@ class PokeBattle_AI
# Minimize
if skill>=PBTrainerAI.highSkill
if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(2)
multipliers[FINAL_DMG_MULT] *= 2
multipliers[:final_damage_multiplier] *= 2
end
end
# Move-specific base damage modifiers
@@ -508,11 +513,11 @@ class PokeBattle_AI
# Move-specific final damage modifiers
# TODO
##### Main damage calculation #####
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT]).round, 1].max
defense = [(defense * multipliers[DEF_MULT]).round, 1].max
baseDmg = [(baseDmg * multipliers[:base_damage_multiplier]).round, 1].max
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
defense = [(defense * multipliers[:defense_multiplier]).round, 1].max
damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
# "AI-specific calculations below"
# Increased critical hit rates
if skill>=PBTrainerAI.mediumSkill
@@ -567,26 +572,26 @@ class PokeBattle_AI
# Get the move's type
type = pbRoughType(move,user,skill)
# Calculate all modifier effects
modifiers = []
modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 1.0
modifiers = {}
modifiers[:base_accuracy] = baseAcc
modifiers[:accuracy_stage] = user.stages[PBStats::ACCURACY]
modifiers[:evasion_stage] = target.stages[PBStats::EVASION]
modifiers[:accuracy_multiplier] = 1.0
modifiers[:evasion_multiplier] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
# Check if move can't miss
return 125 if modifiers[BASE_ACC]==0
return 125 if modifiers[:base_accuracy]==0
# Calculation
accStage = [[modifiers[ACC_STAGE],-6].max,6].min + 6
evaStage = [[modifiers[EVA_STAGE],-6].max,6].min + 6
accStage = [[modifiers[:accuracy_stage], -6].max, 6].min + 6
evaStage = [[modifiers[:evasion_stage], -6].max, 6].min + 6
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT]).round
accuracy = (accuracy * modifiers[:accuracy_multiplier]).round
evasion = (evasion * modifiers[:evasion_multiplier]).round
evasion = 1 if evasion<1
return modifiers[BASE_ACC] * accuracy / evasion
return modifiers[:base_accuracy] * accuracy / evasion
end
def pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
@@ -625,35 +630,35 @@ class PokeBattle_AI
modifiers,user,target,move,type)
end
end
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
# Other effects, inc. ones that set accuracy_multiplier or evasion_stage to specific values
if skill>=PBTrainerAI.mediumSkill
if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] *= 5/3.0
if @battle.field.effects[PBEffects::Gravity] > 0
modifiers[:accuracy_multiplier] *= 5/3.0
end
if user.effects[PBEffects::MicleBerry]
modifiers[ACC_MULT] *= 1.2
modifiers[:accuracy_multiplier] *= 1.2
end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::Foresight] && modifiers[:evasion_stage] > 0
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[:evasion_stage] > 0
end
# "AI-specific calculations below"
if skill>=PBTrainerAI.mediumSkill
modifiers[EVA_STAGE] = 0 if move.function=="0A9" # Chip Away
modifiers[BASE_ACC] = 0 if ["0A5","139","13A","13B","13C", # "Always hit"
modifiers[:evasion_stage] = 0 if move.function == "0A9" # Chip Away
modifiers[:base_accuracy] = 0 if ["0A5", "139", "13A", "13B", "13C", # "Always hit"
"147"].include?(move.function)
modifiers[BASE_ACC] = 0 if user.effects[PBEffects::LockOn]>0 &&
modifiers[:base_accuracy] = 0 if user.effects[PBEffects::LockOn]>0 &&
user.effects[PBEffects::LockOnPos]==target.index
end
if skill>=PBTrainerAI.highSkill
if move.function=="006" # Toxic
modifiers[BASE_ACC] = 0 if MORE_TYPE_EFFECTS && move.statusMove? &&
modifiers[:base_accuracy] = 0 if MORE_TYPE_EFFECTS && move.statusMove? &&
user.pbHasType?(:POISON)
end
if move.function=="070" # OHKO moves
modifiers[BASE_ACC] = move.accuracy+user.level-target.level
modifiers[ACC_MULT] = 0 if target.level>user.level
modifiers[:base_accuracy] = move.accuracy + user.level - target.level
modifiers[:accuracy_multiplier] = 0 if target.level > user.level
if skill>=PBTrainerAI.bestSkill
modifiers[ACC_MULT] = 0 if target.hasActiveAbility?(:STURDY)
modifiers[:accuracy_multiplier] = 0 if target.hasActiveAbility?(:STURDY)
end
end
end

View File

@@ -478,17 +478,6 @@ end
BASE_ACC = 0
ACC_STAGE = 1
EVA_STAGE = 2
ACC_MULT = 3
EVA_MULT = 4
BASE_DMG_MULT = 0
ATK_MULT = 1
DEF_MULT = 2
FINAL_DMG_MULT = 3
def pbBattleConfusionBerry(battler,battle,item,forced,flavor,confuseMsg)
return false if !forced && !battler.canHeal?
return false if !forced && !battler.canConsumePinchBerry?(MECHANICS_GENERATION >= 7)
@@ -582,16 +571,16 @@ def pbBattleGem(user,type,move,mults,moveType)
return if moveType != type
user.effects[PBEffects::GemConsumed] = user.item_id
if MECHANICS_GENERATION >= 6
mults[BASE_DMG_MULT] *= 1.3
mults[:base_damage_multiplier] *= 1.3
else
mults[BASE_DMG_MULT] *= 1.5
mults[:base_damage_multiplier] *= 1.5
end
end
def pbBattleTypeWeakingBerry(type,moveType,target,mults)
return if moveType != type
return if PBTypeEffectiveness.resistant?(target.damageState.typeMod) && moveType != :NORMAL
mults[FINAL_DMG_MULT] /= 2
mults[:final_damage_multiplier] /= 2
target.damageState.berryWeakened = true
target.battle.pbCommonAnimation("EatBerry",target)
end

View File

@@ -768,37 +768,37 @@ BattleHandlers::MoveBaseTypeModifierAbility.add(:REFRIGERATE,
BattleHandlers::AccuracyCalcUserAbility.add(:COMPOUNDEYES,
proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] *= 1.3
mods[:accuracy_multiplier] *= 1.3
}
)
BattleHandlers::AccuracyCalcUserAbility.add(:HUSTLE,
proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] *= 0.8 if move.physicalMove?
mods[:accuracy_multiplier] *= 0.8 if move.physicalMove?
}
)
BattleHandlers::AccuracyCalcUserAbility.add(:KEENEYE,
proc { |ability,mods,user,target,move,type|
mods[EVA_STAGE] = 0 if mods[EVA_STAGE]>0 && MECHANICS_GENERATION >= 6
mods[:evasion_stage] = 0 if mods[:evasion_stage] > 0 && MECHANICS_GENERATION >= 6
}
)
BattleHandlers::AccuracyCalcUserAbility.add(:NOGUARD,
proc { |ability,mods,user,target,move,type|
mods[BASE_ACC] = 0
mods[:base_accuracy] = 0
}
)
BattleHandlers::AccuracyCalcUserAbility.add(:UNAWARE,
proc { |ability,mods,user,target,move,type|
mods[EVA_STAGE] = 0 if move.damagingMove?
mods[:evasion_stage] = 0 if move.damagingMove?
}
)
BattleHandlers::AccuracyCalcUserAbility.add(:VICTORYSTAR,
proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] *= 1.1
mods[:accuracy_multiplier] *= 1.1
}
)
@@ -808,7 +808,7 @@ BattleHandlers::AccuracyCalcUserAbility.add(:VICTORYSTAR,
BattleHandlers::AccuracyCalcUserAllyAbility.add(:VICTORYSTAR,
proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] *= 1.1
mods[:accuracy_multiplier] *= 1.1
}
)
@@ -818,20 +818,20 @@ BattleHandlers::AccuracyCalcUserAllyAbility.add(:VICTORYSTAR,
BattleHandlers::AccuracyCalcTargetAbility.add(:LIGHTNINGROD,
proc { |ability,mods,user,target,move,type|
mods[BASE_ACC] = 0 if type == :ELECTRIC
mods[:base_accuracy] = 0 if type == :ELECTRIC
}
)
BattleHandlers::AccuracyCalcTargetAbility.add(:NOGUARD,
proc { |ability,mods,user,target,move,type|
mods[BASE_ACC] = 0
mods[:base_accuracy] = 0
}
)
BattleHandlers::AccuracyCalcTargetAbility.add(:SANDVEIL,
proc { |ability,mods,user,target,move,type|
if target.battle.pbWeather==PBWeather::Sandstorm
mods[EVA_MULT] *= 1.25
mods[:evasion_multiplier] *= 1.25
end
}
)
@@ -839,33 +839,33 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:SANDVEIL,
BattleHandlers::AccuracyCalcTargetAbility.add(:SNOWCLOAK,
proc { |ability,mods,user,target,move,type|
if target.battle.pbWeather==PBWeather::Hail
mods[EVA_MULT] *= 1.25
mods[:evasion_multiplier] *= 1.25
end
}
)
BattleHandlers::AccuracyCalcTargetAbility.add(:STORMDRAIN,
proc { |ability,mods,user,target,move,type|
mods[BASE_ACC] = 0 if type == :WATER
mods[:base_accuracy] = 0 if type == :WATER
}
)
BattleHandlers::AccuracyCalcTargetAbility.add(:TANGLEDFEET,
proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] /= 2 if target.effects[PBEffects::Confusion]>0
mods[:accuracy_multiplier] /= 2 if target.effects[PBEffects::Confusion] > 0
}
)
BattleHandlers::AccuracyCalcTargetAbility.add(:UNAWARE,
proc { |ability,mods,user,target,move,type|
mods[ACC_STAGE] = 0 if move.damagingMove?
mods[:accuracy_stage] = 0 if move.damagingMove?
}
)
BattleHandlers::AccuracyCalcTargetAbility.add(:WONDERSKIN,
proc { |ability,mods,user,target,move,type|
if move.statusMove? && user.opposes?(target)
mods[BASE_ACC] = 0 if mods[BASE_ACC]>50
mods[:base_accuracy] = 0 if mods[:base_accuracy] > 50
end
}
)
@@ -876,7 +876,7 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:WONDERSKIN,
BattleHandlers::DamageCalcUserAbility.add(:AERILATE,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if move.powerBoost
mults[:base_damage_multiplier] *= 1.2 if move.powerBoost
}
)
@@ -887,29 +887,29 @@ BattleHandlers::DamageCalcUserAbility.add(:ANALYTIC,
if (target.battle.choices[target.index][0]!=:UseMove &&
target.battle.choices[target.index][0]!=:Shift) ||
target.movedThisRound?
mults[BASE_DMG_MULT] *= 1.3
mults[:base_damage_multiplier] *= 1.3
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:BLAZE,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && type == :FIRE
mults[ATK_MULT] *= 1.5
if user.hp <= user.totalhp / 3 && type == :FIRE
mults[:attack_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:DEFEATIST,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] /= 2 if user.hp<=user.totalhp/2
mults[:attack_multiplier] /= 2 if user.hp <= user.totalhp / 2
}
)
BattleHandlers::DamageCalcUserAbility.add(:FLAREBOOST,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.burned? && move.specialMove?
mults[BASE_DMG_MULT] *= 1.5
mults[:base_damage_multiplier] *= 1.5
end
}
)
@@ -917,7 +917,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLAREBOOST,
BattleHandlers::DamageCalcUserAbility.add(:FLASHFIRE,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.effects[PBEffects::FlashFire] && type == :FIRE
mults[ATK_MULT] *= 1.5
mults[:attack_multiplier] *= 1.5
end
}
)
@@ -926,7 +926,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] *= 1.5
mults[:attack_multiplier] *= 1.5
end
}
)
@@ -934,14 +934,14 @@ BattleHandlers::DamageCalcUserAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcUserAbility.add(:GUTS,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.pbHasAnyStatus? && move.physicalMove?
mults[ATK_MULT] *= 1.5
mults[:attack_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:HUGEPOWER,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] *= 2 if move.physicalMove?
mults[:attack_multiplier] *= 2 if move.physicalMove?
}
)
@@ -949,19 +949,19 @@ BattleHandlers::DamageCalcUserAbility.copy(:HUGEPOWER,:PUREPOWER)
BattleHandlers::DamageCalcUserAbility.add(:HUSTLE,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] *= 1.5 if move.physicalMove?
mults[:attack_multiplier] *= 1.5 if move.physicalMove?
}
)
BattleHandlers::DamageCalcUserAbility.add(:IRONFIST,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if move.punchingMove?
mults[:base_damage_multiplier] *= 1.2 if move.punchingMove?
}
)
BattleHandlers::DamageCalcUserAbility.add(:MEGALAUNCHER,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.5 if move.pulseMove?
mults[:base_damage_multiplier] *= 1.5 if move.pulseMove?
}
)
@@ -969,8 +969,8 @@ BattleHandlers::DamageCalcUserAbility.add(:MINUS,
proc { |ability,user,target,move,mults,baseDmg,type|
next if !move.specialMove?
user.eachAlly do |b|
next if !b.hasActiveAbility?([:MINUS,:PLUS])
mults[ATK_MULT] *= 1.5
next if !b.hasActiveAbility?([:MINUS, :PLUS])
mults[:attack_multiplier] *= 1.5
break
end
}
@@ -981,22 +981,22 @@ BattleHandlers::DamageCalcUserAbility.copy(:MINUS,:PLUS)
BattleHandlers::DamageCalcUserAbility.add(:NEUROFORCE,
proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypeEffectiveness.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] *= 1.25
mults[:final_damage_multiplier] *= 1.25
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:OVERGROW,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && type == :GRASS
mults[ATK_MULT] *= 1.5
if user.hp <= user.totalhp / 3 && type == :GRASS
mults[:attack_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:RECKLESS,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if move.recoilMove?
mults[:base_damage_multiplier] *= 1.2 if move.recoilMove?
}
)
@@ -1004,9 +1004,9 @@ BattleHandlers::DamageCalcUserAbility.add(:RIVALRY,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.gender!=2 && target.gender!=2
if user.gender==target.gender
mults[BASE_DMG_MULT] *= 1.25
mults[:base_damage_multiplier] *= 1.25
else
mults[BASE_DMG_MULT] *= 0.75
mults[:base_damage_multiplier] *= 0.75
end
end
}
@@ -1016,28 +1016,28 @@ BattleHandlers::DamageCalcUserAbility.add(:SANDFORCE,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.battle.pbWeather==PBWeather::Sandstorm &&
[:ROCK, :GROUND, :STEEL].include?(type)
mults[BASE_DMG_MULT] *= 1.3
mults[:base_damage_multiplier] *= 1.3
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:SHEERFORCE,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.3 if move.addlEffect>0
mults[:base_damage_multiplier] *= 1.3 if move.addlEffect > 0
}
)
BattleHandlers::DamageCalcUserAbility.add(:SLOWSTART,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] /= 2 if user.effects[PBEffects::SlowStart]>0 && move.physicalMove?
mults[:attack_multiplier] /= 2 if user.effects[PBEffects::SlowStart] > 0 && move.physicalMove?
}
)
BattleHandlers::DamageCalcUserAbility.add(:SOLARPOWER,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] *= 1.5
if move.specialMove? && (w == PBWeather::Sun || w == PBWeather::HarshSun)
mults[:attack_multiplier] *= 1.5
end
}
)
@@ -1045,77 +1045,77 @@ BattleHandlers::DamageCalcUserAbility.add(:SOLARPOWER,
BattleHandlers::DamageCalcUserAbility.add(:SNIPER,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.damageState.critical
mults[FINAL_DMG_MULT] *= 1.5
mults[:final_damage_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:STAKEOUT,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] *= 2 if target.battle.choices[target.index][0]==:SwitchOut
mults[:attack_multiplier] *= 2 if target.battle.choices[target.index][0] == :SwitchOut
}
)
BattleHandlers::DamageCalcUserAbility.add(:STEELWORKER,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] *= 1.5 if type == :STEEL
mults[:attack_multiplier] *= 1.5 if type == :STEEL
}
)
BattleHandlers::DamageCalcUserAbility.add(:STRONGJAW,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.5 if move.bitingMove?
mults[:base_damage_multiplier] *= 1.5 if move.bitingMove?
}
)
BattleHandlers::DamageCalcUserAbility.add(:SWARM,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && type == :BUG
mults[ATK_MULT] *= 1.5
if user.hp <= user.totalhp / 3 && type == :BUG
mults[:attack_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:TECHNICIAN,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.index!=target.index && move && move.id != :STRUGGLE &&
baseDmg*mults[BASE_DMG_MULT]<=60
mults[BASE_DMG_MULT] *= 1.5
if user.index != target.index && move && move.id != :STRUGGLE &&
baseDmg * mults[:base_damage_multiplier] <= 60
mults[:base_damage_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:TINTEDLENS,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] *= 2 if PBTypeEffectiveness.resistant?(target.damageState.typeMod)
mults[:final_damage_multiplier] *= 2 if PBTypeEffectiveness.resistant?(target.damageState.typeMod)
}
)
BattleHandlers::DamageCalcUserAbility.add(:TORRENT,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && type == :WATER
mults[ATK_MULT] *= 1.5
if user.hp <= user.totalhp / 3 && type == :WATER
mults[:attack_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:TOUGHCLAWS,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 4/3.0 if move.contactMove?
mults[:base_damage_multiplier] *= 4 / 3.0 if move.contactMove?
}
)
BattleHandlers::DamageCalcUserAbility.add(:TOXICBOOST,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.poisoned? && move.physicalMove?
mults[BASE_DMG_MULT] *= 1.5
mults[:base_damage_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:WATERBUBBLE,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] *= 2 if type == :WATER
mults[:attack_multiplier] *= 2 if type == :WATER
}
)
@@ -1126,15 +1126,15 @@ BattleHandlers::DamageCalcUserAbility.add(:WATERBUBBLE,
BattleHandlers::DamageCalcUserAllyAbility.add(:BATTERY,
proc { |ability,user,target,move,mults,baseDmg,type|
next if !move.specialMove?
mults[FINAL_DMG_MULT] *= 1.3
mults[:final_damage_multiplier] *= 1.3
}
)
BattleHandlers::DamageCalcUserAllyAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] *= 1.5
if move.physicalMove? && (w == PBWeather::Sun || w == PBWeather::HarshSun)
mults[:attack_multiplier] *= 1.5
end
}
)
@@ -1145,14 +1145,14 @@ BattleHandlers::DamageCalcUserAllyAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcTargetAbility.add(:DRYSKIN,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.25 if type == :FIRE
mults[:base_damage_multiplier] *= 1.25 if type == :FIRE
}
)
BattleHandlers::DamageCalcTargetAbility.add(:FILTER,
proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypeEffectiveness.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] *= 0.75
mults[:final_damage_multiplier] *= 0.75
end
}
)
@@ -1162,62 +1162,62 @@ BattleHandlers::DamageCalcTargetAbility.copy(:FILTER,:SOLIDROCK)
BattleHandlers::DamageCalcTargetAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[DEF_MULT] *= 1.5
if move.specialMove? && (w == PBWeather::Sun || w == PBWeather::HarshSun)
mults[:defense_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcTargetAbility.add(:FLUFFY,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] *= 2 if move.calcType == :FIRE
mults[FINAL_DMG_MULT] /= 2 if move.contactMove?
mults[:final_damage_multiplier] *= 2 if move.calcType == :FIRE
mults[:final_damage_multiplier] /= 2 if move.contactMove?
}
)
BattleHandlers::DamageCalcTargetAbility.add(:FURCOAT,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[DEF_MULT] *= 2 if move.physicalMove? || move.function=="122" # Psyshock
mults[:defense_multiplier] *= 2 if move.physicalMove? || move.function == "122" # Psyshock
}
)
BattleHandlers::DamageCalcTargetAbility.add(:GRASSPELT,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.battle.field.terrain==PBBattleTerrains::Grassy
mults[DEF_MULT] *= 1.5
if user.battle.field.terrain == PBBattleTerrains::Grassy
mults[:defense_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcTargetAbility.add(:HEATPROOF,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] /= 2 if type == :FIRE
mults[:base_damage_multiplier] /= 2 if type == :FIRE
}
)
BattleHandlers::DamageCalcTargetAbility.add(:MARVELSCALE,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.pbHasAnyStatus? && move.physicalMove?
mults[DEF_MULT] *= 1.5
mults[:defense_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcTargetAbility.add(:MULTISCALE,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] /= 2 if target.hp==target.totalhp
mults[:final_damage_multiplier] /= 2 if target.hp == target.totalhp
}
)
BattleHandlers::DamageCalcTargetAbility.add(:THICKFAT,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] /= 2 if type == :FIRE || type == :ICE
mults[:base_damage_multiplier] /= 2 if type == :FIRE || type == :ICE
}
)
BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] /= 2 if type == :FIRE
mults[:final_damage_multiplier] /= 2 if type == :FIRE
}
)
@@ -1228,7 +1228,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE,
BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR,
proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypeEffectiveness.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] *= 0.75
mults[:final_damage_multiplier] *= 0.75
end
}
)
@@ -1236,7 +1236,7 @@ BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR,
BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:SHADOWSHIELD,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.hp==target.totalhp
mults[FINAL_DMG_MULT] /= 2
mults[:final_damage_multiplier] /= 2
end
}
)
@@ -1248,15 +1248,15 @@ BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:SHADOWSHIELD,
BattleHandlers::DamageCalcTargetAllyAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[DEF_MULT] *= 1.5
if move.specialMove? && (w == PBWeather::Sun || w == PBWeather::HarshSun)
mults[:defense_multiplier] *= 1.5
end
}
)
BattleHandlers::DamageCalcTargetAllyAbility.add(:FRIENDGUARD,
proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] *= 0.75
mults[:final_damage_multiplier] *= 0.75
}
)

View File

@@ -412,7 +412,7 @@ BattleHandlers::PriorityBracketUseItem.add(:QUICKCLAW,
BattleHandlers::AccuracyCalcUserItem.add(:WIDELENS,
proc { |item,mods,user,target,move,type|
mods[ACC_MULT] *= 1.1
mods[:accuracy_multiplier] *= 1.1
}
)
@@ -421,7 +421,7 @@ BattleHandlers::AccuracyCalcUserItem.add(:ZOOMLENS,
if (target.battle.choices[target.index][0]!=:UseMove &&
target.battle.choices[target.index][0]!=:Shift) ||
target.movedThisRound?
mods[ACC_MULT] *= 1.2
mods[:accuracy_multiplier] *= 1.2
end
}
)
@@ -432,7 +432,7 @@ BattleHandlers::AccuracyCalcUserItem.add(:ZOOMLENS,
BattleHandlers::AccuracyCalcTargetItem.add(:BRIGHTPOWDER,
proc { |item,mods,user,target,move,type|
mods[ACC_MULT] *= 0.9
mods[:accuracy_multiplier] *= 0.9
}
)
@@ -445,14 +445,14 @@ BattleHandlers::AccuracyCalcTargetItem.copy(:BRIGHTPOWDER,:LAXINCENSE)
BattleHandlers::DamageCalcUserItem.add(:ADAMANTORB,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:DIALGA) && (type == :DRAGON || type == :STEEL)
mults[BASE_DMG_MULT] *= 1.2
mults[:base_damage_multiplier] *= 1.2
end
}
)
BattleHandlers::DamageCalcUserItem.add(:BLACKBELT,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :FIGHTING
mults[:base_damage_multiplier] *= 1.2 if type == :FIGHTING
}
)
@@ -460,7 +460,7 @@ BattleHandlers::DamageCalcUserItem.copy(:BLACKBELT,:FISTPLATE)
BattleHandlers::DamageCalcUserItem.add(:BLACKGLASSES,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :DARK
mults[:base_damage_multiplier] *= 1.2 if type == :DARK
}
)
@@ -474,7 +474,7 @@ BattleHandlers::DamageCalcUserItem.add(:BUGGEM,
BattleHandlers::DamageCalcUserItem.add(:CHARCOAL,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :FIRE
mults[:base_damage_multiplier] *= 1.2 if type == :FIRE
}
)
@@ -482,13 +482,13 @@ BattleHandlers::DamageCalcUserItem.copy(:CHARCOAL,:FLAMEPLATE)
BattleHandlers::DamageCalcUserItem.add(:CHOICEBAND,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.5 if move.physicalMove?
mults[:base_damage_multiplier] *= 1.5 if move.physicalMove?
}
)
BattleHandlers::DamageCalcUserItem.add(:CHOICESPECS,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.5 if move.specialMove?
mults[:base_damage_multiplier] *= 1.5 if move.specialMove?
}
)
@@ -501,14 +501,14 @@ BattleHandlers::DamageCalcUserItem.add(:DARKGEM,
BattleHandlers::DamageCalcUserItem.add(:DEEPSEATOOTH,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:CLAMPERL) && move.specialMove?
mults[ATK_MULT] *= 2
mults[:attack_multiplier] *= 2
end
}
)
BattleHandlers::DamageCalcUserItem.add(:DRAGONFANG,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :DRAGON
mults[:base_damage_multiplier] *= 1.2 if type == :DRAGON
}
)
@@ -529,7 +529,7 @@ BattleHandlers::DamageCalcUserItem.add(:ELECTRICGEM,
BattleHandlers::DamageCalcUserItem.add(:EXPERTBELT,
proc { |item,user,target,move,mults,baseDmg,type|
if PBTypeEffectiveness.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] *= 1.2
mults[:final_damage_multiplier] *= 1.2
end
}
)
@@ -573,7 +573,7 @@ BattleHandlers::DamageCalcUserItem.add(:GRASSGEM,
BattleHandlers::DamageCalcUserItem.add(:GRISEOUSORB,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:GIRATINA) && (type == :DRAGON || type == :GHOST)
mults[BASE_DMG_MULT] *= 1.2
mults[:base_damage_multiplier] *= 1.2
end
}
)
@@ -586,7 +586,7 @@ BattleHandlers::DamageCalcUserItem.add(:GROUNDGEM,
BattleHandlers::DamageCalcUserItem.add(:HARDSTONE,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :ROCK
mults[:base_damage_multiplier] *= 1.2 if type == :ROCK
}
)
@@ -601,7 +601,7 @@ BattleHandlers::DamageCalcUserItem.add(:ICEGEM,
BattleHandlers::DamageCalcUserItem.add(:LIFEORB,
proc { |item,user,target,move,mults,baseDmg,type|
if !move.is_a?(PokeBattle_Confusion)
mults[FINAL_DMG_MULT] *= 1.3
mults[:final_damage_multiplier] *= 1.3
end
}
)
@@ -609,7 +609,7 @@ BattleHandlers::DamageCalcUserItem.add(:LIFEORB,
BattleHandlers::DamageCalcUserItem.add(:LIGHTBALL,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:PIKACHU)
mults[ATK_MULT] *= 2
mults[:attack_multiplier] *= 2
end
}
)
@@ -617,14 +617,14 @@ BattleHandlers::DamageCalcUserItem.add(:LIGHTBALL,
BattleHandlers::DamageCalcUserItem.add(:LUSTROUSORB,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:PALKIA) && (type == :DRAGON || type == :WATER)
mults[BASE_DMG_MULT] *= 1.2
mults[:base_damage_multiplier] *= 1.2
end
}
)
BattleHandlers::DamageCalcUserItem.add(:MAGNET,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :ELECTRIC
mults[:base_damage_multiplier] *= 1.2 if type == :ELECTRIC
}
)
@@ -632,7 +632,7 @@ BattleHandlers::DamageCalcUserItem.copy(:MAGNET,:ZAPPLATE)
BattleHandlers::DamageCalcUserItem.add(:METALCOAT,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :STEEL
mults[:base_damage_multiplier] *= 1.2 if type == :STEEL
}
)
@@ -640,14 +640,14 @@ BattleHandlers::DamageCalcUserItem.copy(:METALCOAT,:IRONPLATE)
BattleHandlers::DamageCalcUserItem.add(:METRONOME,
proc { |item,user,target,move,mults,baseDmg,type|
met = 1+0.2*[user.effects[PBEffects::Metronome],5].min
mults[FINAL_DMG_MULT] *= met
met = 1 + 0.2 * [user.effects[PBEffects::Metronome], 5].min
mults[:final_damage_multiplier] *= met
}
)
BattleHandlers::DamageCalcUserItem.add(:MIRACLESEED,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :GRASS
mults[:base_damage_multiplier] *= 1.2 if type == :GRASS
}
)
@@ -655,13 +655,13 @@ BattleHandlers::DamageCalcUserItem.copy(:MIRACLESEED,:MEADOWPLATE,:ROSEINCENSE)
BattleHandlers::DamageCalcUserItem.add(:MUSCLEBAND,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.1 if move.physicalMove?
mults[:base_damage_multiplier] *= 1.1 if move.physicalMove?
}
)
BattleHandlers::DamageCalcUserItem.add(:MYSTICWATER,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :WATER
mults[:base_damage_multiplier] *= 1.2 if type == :WATER
}
)
@@ -669,7 +669,7 @@ BattleHandlers::DamageCalcUserItem.copy(:MYSTICWATER,:SPLASHPLATE,:SEAINCENSE,:W
BattleHandlers::DamageCalcUserItem.add(:NEVERMELTICE,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :ICE
mults[:base_damage_multiplier] *= 1.2 if type == :ICE
}
)
@@ -683,13 +683,13 @@ BattleHandlers::DamageCalcUserItem.add(:NORMALGEM,
BattleHandlers::DamageCalcUserItem.add(:PIXIEPLATE,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :FAIRY
mults[:base_damage_multiplier] *= 1.2 if type == :FAIRY
}
)
BattleHandlers::DamageCalcUserItem.add(:POISONBARB,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :POISON
mults[:base_damage_multiplier] *= 1.2 if type == :POISON
}
)
@@ -715,7 +715,7 @@ BattleHandlers::DamageCalcUserItem.add(:ROCKGEM,
BattleHandlers::DamageCalcUserItem.add(:SHARPBEAK,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :FLYING
mults[:base_damage_multiplier] *= 1.2 if type == :FLYING
}
)
@@ -723,13 +723,13 @@ BattleHandlers::DamageCalcUserItem.copy(:SHARPBEAK,:SKYPLATE)
BattleHandlers::DamageCalcUserItem.add(:SILKSCARF,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :NORMAL
mults[:base_damage_multiplier] *= 1.2 if type == :NORMAL
}
)
BattleHandlers::DamageCalcUserItem.add(:SILVERPOWDER,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :BUG
mults[:base_damage_multiplier] *= 1.2 if type == :BUG
}
)
@@ -737,7 +737,7 @@ BattleHandlers::DamageCalcUserItem.copy(:SILVERPOWDER,:INSECTPLATE)
BattleHandlers::DamageCalcUserItem.add(:SOFTSAND,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :GROUND
mults[:base_damage_multiplier] *= 1.2 if type == :GROUND
}
)
@@ -747,10 +747,10 @@ BattleHandlers::DamageCalcUserItem.add(:SOULDEW,
proc { |item,user,target,move,mults,baseDmg,type|
next if !user.isSpecies?(:LATIAS) && !user.isSpecies?(:LATIOS)
if SOUL_DEW_POWERS_UP_TYPES
mults[FINAL_DMG_MULT] *= 1.2 if type == :PSYCHIC || type == :DRAGON
mults[:final_damage_multiplier] *= 1.2 if type == :PSYCHIC || type == :DRAGON
else
if move.specialMove? && !user.battle.rules["souldewclause"]
mults[ATK_MULT] *= 1.5
mults[:attack_multiplier] *= 1.5
end
end
}
@@ -758,7 +758,7 @@ BattleHandlers::DamageCalcUserItem.add(:SOULDEW,
BattleHandlers::DamageCalcUserItem.add(:SPELLTAG,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :GHOST
mults[:base_damage_multiplier] *= 1.2 if type == :GHOST
}
)
@@ -773,14 +773,14 @@ BattleHandlers::DamageCalcUserItem.add(:STEELGEM,
BattleHandlers::DamageCalcUserItem.add(:THICKCLUB,
proc { |item,user,target,move,mults,baseDmg,type|
if (user.isSpecies?(:CUBONE) || user.isSpecies?(:MAROWAK)) && move.physicalMove?
mults[ATK_MULT] *= 2
mults[:attack_multiplier] *= 2
end
}
)
BattleHandlers::DamageCalcUserItem.add(:TWISTEDSPOON,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.2 if type == :PSYCHIC
mults[:base_damage_multiplier] *= 1.2 if type == :PSYCHIC
}
)
@@ -794,7 +794,7 @@ BattleHandlers::DamageCalcUserItem.add(:WATERGEM,
BattleHandlers::DamageCalcUserItem.add(:WISEGLASSES,
proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] *= 1.1 if move.specialMove?
mults[:base_damage_multiplier] *= 1.1 if move.specialMove?
}
)
@@ -807,7 +807,7 @@ BattleHandlers::DamageCalcUserItem.add(:WISEGLASSES,
BattleHandlers::DamageCalcTargetItem.add(:ASSAULTVEST,
proc { |item,user,target,move,mults,baseDmg,type|
mults[DEF_MULT] *= 1.5 if move.specialMove?
mults[:defense_multiplier] *= 1.5 if move.specialMove?
}
)
@@ -850,7 +850,7 @@ BattleHandlers::DamageCalcTargetItem.add(:COLBURBERRY,
BattleHandlers::DamageCalcTargetItem.add(:DEEPSEASCALE,
proc { |item,user,target,move,mults,baseDmg,type|
if target.isSpecies?(:CLAMPERL) && move.specialMove?
mults[DEF_MULT] *= 2
mults[:defense_multiplier] *= 2
end
}
)
@@ -863,7 +863,7 @@ BattleHandlers::DamageCalcTargetItem.add(:EVIOLITE,
# affected by Eviolite.
evos = target.pokemon.species_data.evolutions
if evos.any? { |e| e[1] != PBEvolution::None && !e[3] } # Not a "None", not a prevolution
mults[DEF_MULT] *= 1.5 if evos && evos.length > 0
mults[:defense_multiplier] *= 1.5
end
}
)
@@ -889,7 +889,7 @@ BattleHandlers::DamageCalcTargetItem.add(:KEBIABERRY,
BattleHandlers::DamageCalcTargetItem.add(:METALPOWDER,
proc { |item,user,target,move,mults,baseDmg,type|
if target.isSpecies?(:DITTO) && !target.effects[PBEffects::Transform]
mults[DEF_MULT] *= 1.5
mults[:defense_multiplier] *= 1.5
end
}
)
@@ -935,7 +935,7 @@ BattleHandlers::DamageCalcTargetItem.add(:SOULDEW,
next if SOUL_DEW_POWERS_UP_TYPES
next if !target.isSpecies?(:LATIAS) && !target.isSpecies?(:LATIOS)
if move.specialMove? && !user.battle.rules["souldewclause"]
mults[DEF_MULT] *= 1.5
mults[:defense_multiplier] *= 1.5
end
}
)

View File

@@ -130,8 +130,8 @@ def pbConvertTrainerData
tr_type_names[t.id_number] = t.real_name
end
MessageTypes.setMessages(MessageTypes::TrainerTypes, tr_type_names)
pbSaveTrainerTypes
pbSaveTrainerBattles
Compiler.write_trainer_types
Compiler.write_trainers
end
def pbNewTrainer(tr_type, tr_name, tr_id, savechanges = true)

View File

@@ -406,7 +406,7 @@ class Pokemon
return @moves.length
end
# @param move [Integer, Symbol, String] ID of the move to check
# @param move_id [Integer, Symbol, String] ID of the move to check
# @return [Boolean] whether the Pokémon knows the given move
def hasMove?(move_id)
move_data = GameData::Move.try_get(move_id)
@@ -503,7 +503,7 @@ class Pokemon
@firstmoves = []
end
# @param move [Integer, Symbol, String] ID of the move to check
# @param move_id [Integer, Symbol, String] ID of the move to check
# @return [Boolean] whether the Pokémon is compatible with the given move
def compatibleWithMove?(move_id)
move_data = GameData::Move.try_get(move_id)
@@ -821,7 +821,7 @@ class Pokemon
calcStats
end
# @param species [Integer, Symbol, String] id of the species to check for
# @param check_species [Integer, Symbol, String] id of the species to check for
# @return [Boolean] whether this Pokémon is of the specified species
def isSpecies?(check_species)
return @species == check_species || @species == GameData::Species.get(check_species).species

View File

@@ -167,6 +167,7 @@ class PokemonRegionMap_Scene
return true
end
# TODO: Why is this PBS file writer here?
def pbSaveMapData
File.open("PBS/townmap.txt","wb") { |f|
f.write(0xEF.chr)
@@ -179,10 +180,11 @@ class PokemonRegionMap_Scene
next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i))
f.write(sprintf("Name=%s\r\nFilename=%s\r\n",csvQuote(map[0]),csvQuote(map[1])))
f.write(sprintf("Name = %s\r\nFilename = %s\r\n",
Compiler.csvQuote(map[0]), Compiler.csvQuote(map[1])))
for loc in map[2]
f.write("Point=")
pbWriteCsvRecord(loc,f,[nil,"uussUUUU"])
f.write("Point = ")
Compiler.pbWriteCsvRecord(loc,f,[nil,"uussUUUU"])
f.write("\r\n")
end
end

View File

@@ -1059,7 +1059,7 @@ def pbTrainerInfo(pokemonlist,trfile,rules)
yield(nil) if block_given?
save_data(trlists,"Data/trainer_lists.dat")
yield(nil) if block_given?
pbSaveTrainerLists()
Compiler.write_trainer_lists
yield(nil) if block_given?
end
@@ -1298,8 +1298,7 @@ def pbWriteCup(id,rules)
trlists[cmd][2].push(id) if !trlists[cmd][5]
save_data(trlists,"Data/trainer_lists.dat")
Graphics.update
pbSaveTrainerLists
Graphics.update
Compiler.write_trainer_lists
end
return
# Yes, use new

View File

@@ -251,11 +251,6 @@ module Mouse
@ReleaseCapture = Win32API.new('user32','ReleaseCapture','','i')
module_function
def getMouseGlobalPos
pos = [0, 0].pack('ll')
return (@GetCursorPos.call(pos)!=0) ? pos.unpack('ll') : [nil,nil]
end
def screen_to_client(x, y)
return nil unless x and y
screenToClient = Win32API.new('user32','ScreenToClient',%w(l p),'i')
@@ -264,12 +259,9 @@ module Mouse
return nil
end
def setCapture
@SetCapture.call(Win32API.pbFindRgssWindow)
end
def releaseCapture
@ReleaseCapture.call
def getMouseGlobalPos
pos = [0, 0].pack('ll')
return (@GetCursorPos.call(pos)!=0) ? pos.unpack('ll') : [nil,nil]
end
# Returns the position of the mouse relative to the game window.
@@ -283,6 +275,17 @@ module Mouse
return nil
end
# Unused
def setCapture
@SetCapture.call(Win32API.pbFindRgssWindow)
end
# Unused
def releaseCapture
@ReleaseCapture.call
end
# Unused
def del
return if @oldcursor==nil
@SetClassLong.call(Win32API.pbFindRgssWindow,-12,@oldcursor)

View File

@@ -63,16 +63,6 @@ def pbSetUpSystem
pbSetResizeFactor([$PokemonSystem.screensize, 4].min)
end
# Load constants
begin
consts = pbSafeLoad("Data/Constants.rxdata")
consts = [] if !consts
rescue
consts = []
end
for script in consts
next if !script
eval(Zlib::Inflate.inflate(script[2]),nil,script[1])
end
GameData.load_all
if LANGUAGES.length>=2
pokemonSystem.language = pbChooseLanguage if !havedata

View File

@@ -235,6 +235,22 @@ def getID(mod,constant)
return constant
end
def getConstantName(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
return c if mod.const_get(c.to_sym)==value
end
raise _INTL("Value {1} not defined by a constant in {2}",value,mod.name)
end
def getConstantNameOrValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
return c if mod.const_get(c.to_sym)==value
end
return value.inspect
end
#===============================================================================

View File

@@ -896,7 +896,7 @@ DebugMenuCommands.register("setencounters", {
end
save_data(encdata, "Data/encounters.dat")
$PokemonTemp.encountersData = nil
pbSaveEncounterData # Rewrite PBS file encounters.txt
Compiler.write_encounters # Rewrite PBS file encounters.txt
}
})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,945 @@
module ShadowText
def shadowtext(bitmap,x,y,w,h,t,disabled=false,align=0)
width=bitmap.text_size(t).width
if align==2
x+=(w-width)
elsif align==1
x+=(w/2)-(width/2)
end
pbDrawShadowText(bitmap,x,y+6,w,h,t,
disabled ? Color.new(26*8,26*8,25*8) : Color.new(12*8,12*8,12*8),
Color.new(26*8,26*8,25*8))
end
end
class UIControl
include ShadowText
attr_accessor :bitmap
attr_accessor :label
attr_accessor :x
attr_accessor :y
attr_accessor :width
attr_accessor :height
attr_accessor :changed
attr_accessor :parent
attr_accessor :disabled
def text
return self.label
end
def text=(value)
self.label=value
end
def initialize(label)
@label=label
@x=0
@y=0
@width=0
@height=0
@changed=false
@disabled=false
@invalid=true
end
def toAbsoluteRect(rc)
return Rect.new(
rc.x+self.parentX,
rc.y+self.parentY,
rc.width,rc.height)
end
def parentX
return 0 if !self.parent
return self.parent.x+self.parent.leftEdge if self.parent.is_a?(SpriteWindow)
return self.parent.x+16 if self.parent.is_a?(Window)
return self.parent.x
end
def parentY
return 0 if !self.parent
return self.parent.y+self.parent.topEdge if self.parent.is_a?(SpriteWindow)
return self.parent.y+16 if self.parent.is_a?(Window)
return self.parent.y
end
def invalid?
return @invalid
end
def invalidate # Marks that the control must be redrawn to reflect current logic
@invalid=true
end
def update # Updates the logic on the control, invalidating it if necessary
end
def refresh # Redraws the control
end
def validate # Makes the control no longer invalid
@invalid=false
end
def repaint # Redraws the control only if it is invalid
if self.invalid?
self.refresh
self.validate
end
end
end
class Label < UIControl
def text=(value)
self.label=value
refresh
end
def refresh
bitmap=self.bitmap
bitmap.fill_rect(self.x,self.y,self.width,self.height,Color.new(0,0,0,0))
size=bitmap.text_size(self.label).width
shadowtext(bitmap,self.x+4,self.y,size,self.height,self.label,@disabled)
end
end
class Button < UIControl
attr_accessor :label
def initialize(label)
super
@captured=false
@label=label
end
def update
mousepos=Mouse::getMousePos
self.changed=false
return if !mousepos
rect=Rect.new(self.x+1,self.y+1,self.width-2,self.height-2)
rect=toAbsoluteRect(rect)
if Input.triggerex?(Input::LeftMouseKey) &&
rect.contains(mousepos[0],mousepos[1]) && !@captured
@captured=true
self.invalidate
end
if Input.releaseex?(Input::LeftMouseKey) && @captured
self.changed=true if rect.contains(mousepos[0],mousepos[1])
@captured=false
self.invalidate
end
end
def refresh
bitmap=self.bitmap
x=self.x
y=self.y
width=self.width
height=self.height
color=Color.new(120,120,120)
bitmap.fill_rect(x+1,y+1,width-2,height-2,color)
ret=Rect.new(x+1,y+1,width-2,height-2)
if !@captured
bitmap.fill_rect(x+2,y+2,width-4,height-4,Color.new(0,0,0,0))
else
bitmap.fill_rect(x+2,y+2,width-4,height-4,Color.new(120,120,120,80))
end
size=bitmap.text_size(self.label).width
shadowtext(bitmap,x+4,y,size,height,self.label,@disabled)
return ret
end
end
class Checkbox < Button
attr_reader :checked
def curvalue
return self.checked
end
def curvalue=(value)
self.checked=value
end
def checked=(value)
@checked=value
invalidate
end
def initialize(label)
super
@checked=false
end
def update
super
if self.changed
@checked=!@checked
self.invalidate
end
end
def refresh
bitmap=self.bitmap
x=self.x
y=self.y
width=[self.width,32].min
height=[self.height,32].min
color=Color.new(120,120,120)
bitmap.fill_rect(x+2,y+2,self.width-4,self.height-4,Color.new(0,0,0,0))
bitmap.fill_rect(x+1,y+1,width-2,height-2,color)
ret=Rect.new(x+1,y+1,width-2,height-2)
if !@captured
bitmap.fill_rect(x+2,y+2,width-4,height-4,Color.new(0,0,0,0))
else
bitmap.fill_rect(x+2,y+2,width-4,height-4,Color.new(120,120,120,80))
end
if self.checked
shadowtext(bitmap,x,y,32,32,"X",@disabled,1)
end
size=bitmap.text_size(self.label).width
shadowtext(bitmap,x+36,y,size,height,self.label,@disabled)
return ret
end
end
class TextField < UIControl
attr_accessor :label
attr_reader :text
def text=(value)
@text=value
self.invalidate
end
def initialize(label,text)
super(label)
@frame=0
@label=label
@text=text
@cursor=text.scan(/./m).length
end
def insert(ch)
chars=self.text.scan(/./m)
chars.insert(@cursor,ch)
@text=""
for ch in chars
@text+=ch
end
@cursor+=1
@frame=0
self.changed=true
self.invalidate
end
def delete
chars=self.text.scan(/./m)
chars.delete_at(@cursor-1)
@text=""
for ch in chars
@text+=ch
end
@cursor-=1
@frame=0
self.changed=true
self.invalidate
end
def update
@frame+=1
@frame%=20
self.changed=false
self.invalidate if ((@frame%10)==0)
# Moving cursor
if Input.repeat?(Input::LEFT)
if @cursor > 0
@cursor-=1
@frame=0
self.invalidate
end
return
end
if Input.repeat?(Input::RIGHT)
if @cursor < self.text.scan(/./m).length
@cursor+=1
@frame=0
self.invalidate
end
return
end
# Backspace
if Input.repeat?(Input::BACKSPACE) || Input.repeat?(Input::DELETE)
self.delete if @cursor > 0
return
end
# Letter keys
for i in 65..90
if Input.repeatex?(i)
shift=(Input.press?(Input::SHIFT)) ? 0x41 : 0x61
insert((shift+i-65).chr)
return
end
end
# Number keys
shifted=")!@\#$%^&*("
unshifted="0123456789"
for i in 48..57
if Input.repeatex?(i)
insert((Input.press?(Input::SHIFT)) ? shifted[i-48].chr : unshifted[i-48].chr)
return
end
end
keys=[
[32," "," "],
[106,"*","*"],
[107,"+","+"],
[109,"-","-"],
[111,"/","/"],
[186,";",":"],
[187,"=","+"],
[188,",","<"],
[189,"-","_"],
[190,".",">"],
[191,"/","?"],
[219,"[","{"],
[220,"\\","|"],
[221,"]","}"],
[222,"\"","'"]
]
for i in keys
if Input.repeatex?(i[0])
insert((Input.press?(Input::SHIFT)) ? i[2] : i[1])
return
end
end
end
def refresh
bitmap=self.bitmap
x=self.x
y=self.y
width=self.width
height=self.height
color=Color.new(120,120,120)
bitmap.font.color=color
bitmap.fill_rect(x,y,width,height,Color.new(0,0,0,0))
size=bitmap.text_size(self.label).width
shadowtext(bitmap,x,y,size,height,self.label)
x+=size
width-=size
bitmap.fill_rect(x+1,y+1,width-2,height-2,color)
ret=Rect.new(x+1,y+1,width-2,height-2)
if !@captured
bitmap.fill_rect(x+2,y+2,width-4,height-4,Color.new(0,0,0,0))
else
bitmap.fill_rect(x+2,y+2,width-4,height-4,Color.new(120,120,120,80))
end
x+=4
textscan=self.text.scan(/./m)
scanlength=textscan.length
@cursor=scanlength if @cursor>scanlength
@cursor=0 if @cursor<0
startpos=@cursor
fromcursor=0
while (startpos>0)
c=textscan[startpos-1]
fromcursor+=bitmap.text_size(c).width
break if fromcursor>width-4
startpos-=1
end
for i in startpos...scanlength
c=textscan[i]
textwidth=bitmap.text_size(c).width
next if c=="\n"
# Draw text
shadowtext(bitmap,x,y, textwidth+4, 32, c)
# Draw cursor if necessary
if ((@frame/10)&1) == 0 && i==@cursor
bitmap.fill_rect(x,y+4,2,24,Color.new(120,120,120))
end
# Add x to drawn text width
x += textwidth
end
if ((@frame/10)&1) == 0 && textscan.length==@cursor
bitmap.fill_rect(x,y+4,2,24,Color.new(120,120,120))
end
return ret
end
end
class Slider < UIControl
attr_reader :minvalue
attr_reader :maxvalue
attr_reader :curvalue
attr_accessor :label
def curvalue=(value)
@curvalue=value
@curvalue=self.minvalue if self.minvalue && @curvalue<self.minvalue
@curvalue=self.maxvalue if self.maxvalue && @curvalue>self.maxvalue
self.invalidate
end
def minvalue=(value)
@minvalue=value
@curvalue=self.minvalue if self.minvalue && @curvalue<self.minvalue
@curvalue=self.maxvalue if self.maxvalue && @curvalue>self.maxvalue
self.invalidate
end
def maxvalue=(value)
@maxvalue=value
@curvalue=self.minvalue if self.minvalue && @curvalue<self.minvalue
@curvalue=self.maxvalue if self.maxvalue && @curvalue>self.maxvalue
self.invalidate
end
def initialize(label,minvalue,maxvalue,curval)
super(label)
@minvalue=minvalue
@maxvalue=maxvalue
@curvalue=curval
@label=label
@leftarrow=Rect.new(0,0,0,0)
@rightarrow=Rect.new(0,0,0,0)
self.minvalue=minvalue
self.maxvalue=maxvalue
self.curvalue=curval
end
def update
mousepos=Mouse::getMousePos
self.changed=false
if self.minvalue<self.maxvalue && self.curvalue<self.minvalue
self.curvalue=self.minvalue
end
return false if self.disabled
return false if !Input.repeatex?(Input::LeftMouseKey)
return false if !mousepos
left=toAbsoluteRect(@leftarrow)
right=toAbsoluteRect(@rightarrow)
oldvalue=self.curvalue
# Left arrow
if left.contains(mousepos[0],mousepos[1])
if Input.repeatcount(Input::LeftMouseKey)>100
self.curvalue-=10
self.curvalue=self.curvalue.floor
elsif Input.repeatcount(Input::LeftMouseKey)>50
self.curvalue-=5
self.curvalue=self.curvalue.floor
else
self.curvalue-=1
self.curvalue=self.curvalue.floor
end
self.changed=(self.curvalue!=oldvalue)
self.invalidate
end
#Right arrow
if right.contains(mousepos[0],mousepos[1])
if Input.repeatcount(Input::LeftMouseKey)>100
self.curvalue+=10
self.curvalue=self.curvalue.floor
elsif Input.repeatcount(Input::LeftMouseKey)>50
self.curvalue+=5
self.curvalue=self.curvalue.floor
else
self.curvalue+=1
self.curvalue=self.curvalue.floor
end
self.changed=(self.curvalue!=oldvalue)
self.invalidate
end
end
def refresh
bitmap=self.bitmap
x=self.x
y=self.y
width=self.width
height=self.height
color=Color.new(120,120,120)
bitmap.fill_rect(x,y,width,height,Color.new(0,0,0,0))
size=bitmap.text_size(self.label).width
leftarrows=bitmap.text_size(_INTL(" << "))
numbers=bitmap.text_size(" XXXX ").width
rightarrows=bitmap.text_size(_INTL(" >> "))
bitmap.font.color=color
shadowtext(bitmap,x,y,size,height,self.label)
x+=size
shadowtext(bitmap,x,y,leftarrows.width,height,_INTL(" << "),
self.disabled || self.curvalue==self.minvalue)
@leftarrow=Rect.new(x,y,leftarrows.width,height)
x+=leftarrows.width
if !self.disabled
bitmap.font.color=color
shadowtext(bitmap,x,y,numbers,height," #{self.curvalue} ",false,1)
end
x+=numbers
shadowtext(bitmap,x,y,rightarrows.width,height,_INTL(" >> "),
self.disabled || self.curvalue==self.maxvalue)
@rightarrow=Rect.new(x,y,rightarrows.width,height)
end
end
class OptionalSlider < Slider
def initialize(label,minvalue,maxvalue,curvalue)
@slider=Slider.new(label,minvalue,maxvalue,curvalue)
@checkbox=Checkbox.new("")
end
def curvalue
return @checkbox.checked ? @slider.curvalue : nil
end
def curvalue=(value)
slider.curvalue=value
end
def checked
return @checkbox.checked
end
def checked=(value)
@checkbox.checked=value
end
def invalid?
return @slider.invalid? || @checkbox.invalid?
end
def invalidate
@slider.invalidate
@checkbox.invalidate
end
def validate?
@slider.validate
@checkbox.validate
end
def changed
return @slider.changed || @checkbox.changed
end
def minvalue
return @slider.minvalue
end
def minvalue=(value)
slider.minvalue=value
end
def maxvalue
return @slider.maxvalue
end
def maxvalue=(value)
slider.maxvalue=value
end
def update
updatedefs
@slider.update
@checkbox.update
end
def refresh
updatedefs
@slider.refresh
@checkbox.refresh
end
private
def updatedefs
checkboxwidth=32
@slider.bitmap=self.bitmap
@slider.parent=self.parent
@checkbox.x=self.x
@checkbox.y=self.y
@checkbox.width=checkboxwidth
@checkbox.height=self.height
@checkbox.bitmap=self.bitmap
@checkbox.parent=self.parent
@slider.x=self.x+checkboxwidth+4
@slider.y=self.y
@slider.width=self.width-checkboxwidth
@slider.height=self.height
@slider.disabled=!@checkbox.checked
end
end
class ArrayCountSlider < Slider
def maxvalue
return @array.length-1
end
def initialize(array,label)
@array=array
super(label,0,canvas.animation.length-1,0)
end
end
class FrameCountSlider < Slider
def maxvalue
return @canvas.animation.length
end
def initialize(canvas)
@canvas=canvas
super(_INTL("Frame:"),1,canvas.animation.length,0)
end
end
class FrameCountButton < Button
def label
return _INTL("Total Frames: {1}",@canvas.animation.length)
end
def initialize(canvas)
@canvas=canvas
super(self.label)
end
end
class TextSlider < UIControl
attr_reader :minvalue
attr_reader :maxvalue
attr_reader :curvalue
attr_accessor :label
attr_accessor :options
attr_accessor :maxoptionwidth
def curvalue=(value)
@curvalue=value
@curvalue=self.minvalue if self.minvalue && @curvalue<self.minvalue
@curvalue=self.maxvalue if self.maxvalue && @curvalue>self.maxvalue
self.invalidate
end
def minvalue=(value)
@minvalue=value
@curvalue=self.minvalue if self.minvalue && @curvalue<self.minvalue
@curvalue=self.maxvalue if self.maxvalue && @curvalue>self.maxvalue
self.invalidate
end
def maxvalue=(value)
@maxvalue=value
@curvalue=self.minvalue if self.minvalue && @curvalue<self.minvalue
@curvalue=self.maxvalue if self.maxvalue && @curvalue>self.maxvalue
self.invalidate
end
def initialize(label,options,curval)
super(label)
@label=label
@options=options
@minvalue=0
@maxvalue=options.length-1
@curvalue=curval
@leftarrow=Rect.new(0,0,0,0)
@rightarrow=Rect.new(0,0,0,0)
self.minvalue=@minvalue
self.maxvalue=@maxvalue
self.curvalue=@curvalue
end
def update
mousepos=Mouse::getMousePos
self.changed=false
if self.minvalue<self.maxvalue && self.curvalue<self.minvalue
self.curvalue=self.minvalue
end
return false if self.disabled
return false if !Input.repeatex?(Input::LeftMouseKey)
return false if !mousepos
left=toAbsoluteRect(@leftarrow)
right=toAbsoluteRect(@rightarrow)
oldvalue=self.curvalue
# Left arrow
if left.contains(mousepos[0],mousepos[1])
if Input.repeatcount(Input::LeftMouseKey)>100
self.curvalue-=10
elsif Input.repeatcount(Input::LeftMouseKey)>50
self.curvalue-=5
else
self.curvalue-=1
end
self.changed=(self.curvalue!=oldvalue)
self.invalidate
end
# Right arrow
if right.contains(mousepos[0],mousepos[1])
if Input.repeatcount(Input::LeftMouseKey)>100
self.curvalue+=10
elsif Input.repeatcount(Input::LeftMouseKey)>50
self.curvalue+=5
else
self.curvalue+=1
end
self.changed=(self.curvalue!=oldvalue)
self.invalidate
end
end
def refresh
bitmap=self.bitmap
if @maxoptionwidth==nil
for i in 0...@options.length
w=self.bitmap.text_size(" "+@options[i]+" ").width
@maxoptionwidth=w if !@maxoptionwidth || @maxoptionwidth<w
end
end
x=self.x
y=self.y
width=self.width
height=self.height
color=Color.new(120,120,120)
bitmap.fill_rect(x,y,width,height,Color.new(0,0,0,0))
size=bitmap.text_size(self.label).width
leftarrows=bitmap.text_size(_INTL(" << "))
rightarrows=bitmap.text_size(_INTL(" >> "))
bitmap.font.color=color
shadowtext(bitmap,x,y,size,height,self.label)
x+=size
shadowtext(bitmap,x,y,leftarrows.width,height,_INTL(" << "),
self.disabled || self.curvalue==self.minvalue)
@leftarrow=Rect.new(x,y,leftarrows.width,height)
x+=leftarrows.width
if !self.disabled
bitmap.font.color=color
shadowtext(bitmap,x,y,@maxoptionwidth,height," #{@options[self.curvalue]} ",false,1)
end
x+=@maxoptionwidth
shadowtext(bitmap,x,y,rightarrows.width,height,_INTL(" >> "),
self.disabled || self.curvalue==self.maxvalue)
@rightarrow=Rect.new(x,y,rightarrows.width,height)
end
end
class OptionalTextSlider < TextSlider
def initialize(label,options,curval)
@slider=TextSlider.new(label,options,curval)
@checkbox=Checkbox.new("")
end
def curvalue
return @checkbox.checked ? @slider.curvalue : nil
end
def curvalue=(value)
slider.curvalue=value
end
def checked
return @checkbox.checked
end
def checked=(value)
@checkbox.checked=value
end
def invalid?
return @slider.invalid? || @checkbox.invalid?
end
def invalidate
@slider.invalidate
@checkbox.invalidate
end
def validate?
@slider.validate
@checkbox.validate
end
def changed
return @slider.changed || @checkbox.changed
end
def minvalue
return @slider.minvalue
end
def minvalue=(value)
slider.minvalue=value
end
def maxvalue
return @slider.maxvalue
end
def maxvalue=(value)
slider.maxvalue=value
end
def update
updatedefs
@slider.update
@checkbox.update
end
def refresh
updatedefs
@slider.refresh
@checkbox.refresh
end
private
def updatedefs
checkboxwidth=32
@slider.bitmap=self.bitmap
@slider.parent=self.parent
@checkbox.x=self.x
@checkbox.y=self.y
@checkbox.width=checkboxwidth
@checkbox.height=self.height
@checkbox.bitmap=self.bitmap
@checkbox.parent=self.parent
@slider.x=self.x+checkboxwidth+4
@slider.y=self.y
@slider.width=self.width-checkboxwidth
@slider.height=self.height
@slider.disabled=!@checkbox.checked
end
end
class ControlWindow < SpriteWindow_Base
attr_reader :controls
def initialize(x,y,width,height)
super(x,y,width,height)
self.contents=Bitmap.new(width-32,height-32)
pbSetNarrowFont(self.contents)
@controls=[]
end
def dispose
self.contents.dispose
super
end
def refresh
for i in 0...@controls.length
@controls[i].refresh
end
end
def repaint
for i in 0...@controls.length
@controls[i].repaint
end
end
def invalidate
for i in 0...@controls.length
@controls[i].invalidate
end
end
def hittest?(i)
mousepos=Mouse::getMousePos
return false if !mousepos
return false if i<0 || i>=@controls.length
rc=Rect.new(
@controls[i].parentX,
@controls[i].parentY,
@controls[i].width,
@controls[i].height
)
return rc.contains(mousepos[0],mousepos[1])
end
def addControl(control)
i=@controls.length
@controls[i]=control
@controls[i].x=0
@controls[i].y=i*32
@controls[i].width=self.contents.width
@controls[i].height=32
@controls[i].parent=self
@controls[i].bitmap=self.contents
@controls[i].invalidate
refresh
return i
end
def addLabel(label)
return addControl(Label.new(label))
end
def addButton(label)
return addControl(Button.new(label))
end
def addSlider(label,minvalue,maxvalue,curvalue)
return addControl(Slider.new(label,minvalue,maxvalue,curvalue))
end
def addOptionalSlider(label,minvalue,maxvalue,curvalue)
return addControl(OptionalSlider.new(label,minvalue,maxvalue,curvalue))
end
def addTextSlider(label,options,curvalue)
return addControl(TextSlider.new(label,options,curvalue))
end
def addOptionalTextSlider(label,options,curvalue)
return addControl(OptionalTextSlider.new(label,options,curvalue))
end
def addCheckbox(label)
return addControl(Checkbox.new(label))
end
def addSpace
return addControl(UIControl.new(""))
end
def update
super
for i in 0...@controls.length
@controls[i].update
end
repaint
end
def changed?(i)
return false if i<0
return @controls[i].changed
end
def value(i)
return false if i<0
return @controls[i].curvalue
end
end

View File

@@ -0,0 +1,444 @@
################################################################################
# Paths and interpolation
################################################################################
class ControlPointSprite < SpriteWrapper
attr_accessor :dragging
def initialize(red,viewport=nil)
super(viewport)
self.bitmap=Bitmap.new(6,6)
self.bitmap.fill_rect(0,0,6,1,Color.new(0,0,0))
self.bitmap.fill_rect(0,0,1,6,Color.new(0,0,0))
self.bitmap.fill_rect(0,5,6,1,Color.new(0,0,0))
self.bitmap.fill_rect(5,0,1,6,Color.new(0,0,0))
color=(red) ? Color.new(255,0,0) : Color.new(0,0,0)
self.bitmap.fill_rect(2,2,2,2,color)
self.x=-6
self.y=-6
self.visible=false
@dragging=false
end
def mouseover
if Input.repeatcount(Input::LeftMouseKey)==0 || !@dragging
@dragging=false
return
end
mouse=Mouse::getMousePos(true)
return if !mouse
self.x=[[mouse[0],0].max,512].min
self.y=[[mouse[1],0].max,384].min
end
def hittest?
return true if !self.visible
mouse=Mouse::getMousePos(true)
return false if !mouse
return mouse[0]>=self.x && mouse[0]<self.x+6 &&
mouse[1]>=self.y && mouse[1]<self.y+6
end
def inspect
return "[#{self.x},#{self.y}]"
end
def dispose
self.bitmap.dispose
super
end
end
class PointSprite < SpriteWrapper
def initialize(x,y,viewport=nil)
super(viewport)
self.bitmap=Bitmap.new(2,2)
self.bitmap.fill_rect(0,0,2,2,Color.new(0,0,0))
self.x=x
self.y=y
end
def dispose
self.bitmap.dispose
super
end
end
class PointPath
include Enumerable
def initialize
@points=[]
@distances=[]
@totaldist=0
end
def [](x)
return @points[x].clone
end
def each
@points.each { |o| yield o.clone }
end
def size
return @points.size
end
def length
return @points.length
end
def totalDistance
return @totaldist
end
def inspect
p=[]
for point in @points
p.push([point[0].to_i,point[1].to_i])
end
return p.inspect
end
def isEndPoint?(x,y)
return false if @points.length==0
index=@points.length-1
return @points[index][0]==x &&
@points[index][1]==y
end
def addPoint(x,y)
@points.push([x,y])
if @points.length>1
len=@points.length
dx=@points[len-2][0]-@points[len-1][0]
dy=@points[len-2][1]-@points[len-1][1]
dist=Math.sqrt(dx*dx+dy*dy)
@distances.push(dist)
@totaldist+=dist
end
end
def clear
@points.clear
@distances.clear
@totaldist=0
end
def smoothPointPath(frames,roundValues=false)
if frames<0
raise ArgumentError.new("frames out of range: #{frames}")
end
ret=PointPath.new
if @points.length==0
return ret
end
step=1.0/frames
t=0.0
(frames+2).times do
point=pointOnPath(t)
if roundValues
ret.addPoint(point[0].round,point[1].round)
else
ret.addPoint(point[0],point[1])
end
t+=step
t=[1.0,t].min
end
return ret
end
def pointOnPath(t)
if t<0 || t>1
raise ArgumentError.new("t out of range for pointOnPath: #{t}")
end
return nil if @points.length==0
ret=@points[@points.length-1].clone
if @points.length==1
return ret
end
curdist=0
distForT=@totaldist*t
i=0
for dist in @distances
curdist+=dist
if dist>0.0
if curdist>=distForT
distT=1.0-((curdist-distForT)/dist)
dx=@points[i+1][0]-@points[i][0]
dy=@points[i+1][1]-@points[i][1]
ret=[@points[i][0]+dx*distT,
@points[i][1]+dy*distT]
break
end
end
i+=1
end
return ret
end
end
def catmullRom(p1,p2,p3,p4,t)
# p1=prevPoint, p2=startPoint, p3=endPoint, p4=nextPoint, t is from 0 through 1
t2=t*t
t3=t2*t
return 0.5*(2*p2+t*(p3-p1) +
t2*(2*p1-5*p2+4*p3-p4)+
t3*(p4-3*p3+3*p2-p1))
end
def getCatmullRomPoint(src,t)
x=0,y=0
t*=3.0
if t<1.0
x=catmullRom(src[0].x,src[0].x,src[1].x,src[2].x,t)
y=catmullRom(src[0].y,src[0].y,src[1].y,src[2].y,t)
elsif t<2.0
t-=1.0
x=catmullRom(src[0].x,src[1].x,src[2].x,src[3].x,t)
y=catmullRom(src[0].y,src[1].y,src[2].y,src[3].y,t)
else
t-=2.0
x=catmullRom(src[1].x,src[2].x,src[3].x,src[3].x,t)
y=catmullRom(src[1].y,src[2].y,src[3].y,src[3].y,t)
end
return [x,y]
end
def getCurvePoint(src,t)
return getCatmullRomPoint(src,t)
end
def curveToPointPath(curve,numpoints)
if numpoints<2
return nil
end
path=PointPath.new
step=1.0/(numpoints-1)
t=0.0
numpoints.times do
point=getCurvePoint(curve,t)
path.addPoint(point[0],point[1])
t+=step
end
return path
end
def pbDefinePath(canvas)
sliderwin2=ControlWindow.new(0,0,320,320)
sliderwin2.viewport=canvas.viewport
sliderwin2.addSlider(_INTL("Number of frames:"),2,500,20)
sliderwin2.opacity=200
defcurvebutton=sliderwin2.addButton(_INTL("Define Smooth Curve"))
defpathbutton=sliderwin2.addButton(_INTL("Define Freehand Path"))
okbutton=sliderwin2.addButton(_INTL("OK"))
cancelbutton=sliderwin2.addButton(_INTL("Cancel"))
points=[]
path=nil
loop do
Graphics.update
Input.update
sliderwin2.update
if sliderwin2.changed?(0) # Number of frames
if path
path=path.smoothPointPath(sliderwin2.value(0),false)
i=0
for point in path
if i<points.length
points[i].x=point[0]
points[i].y=point[1]
else
points.push(PointSprite.new(point[0],point[1],canvas.viewport))
end
i+=1
end
for j in i...points.length
points[j].dispose
points[j]=nil
end
points.compact!
# File.open("pointpath.txt","wb") { |f| f.write(path.inspect) }
end
elsif sliderwin2.changed?(defcurvebutton)
for point in points
point.dispose
end
points.clear
30.times do
point=PointSprite.new(0,0,canvas.viewport)
point.visible=false
points.push(point)
end
curve=[
ControlPointSprite.new(true,canvas.viewport),
ControlPointSprite.new(false,canvas.viewport),
ControlPointSprite.new(false,canvas.viewport),
ControlPointSprite.new(true,canvas.viewport)
]
showline=false
sliderwin2.visible=false
# This window displays the mouse's current position
window=Window_UnformattedTextPokemon.new("")
window.x=0
window.y=320-64
window.width=128
window.height=64
window.viewport=canvas.viewport
loop do
Graphics.update
Input.update
if Input.trigger?(Input::B)
break
end
if Input.triggerex?(Input::LeftMouseKey)
for j in 0...4
next if !curve[j].hittest?
if j==1||j==2
next if !curve[0].visible || !curve[3].visible
end
curve[j].visible=true
for k in 0...4
curve[k].dragging=(k==j)
end
break
end
end
for j in 0...4
curve[j].mouseover
end
mouse = Mouse::getMousePos(true)
newtext = (mouse) ? sprintf("(%d,%d)",mouse[0],mouse[1]) : "(??,??)"
if window.text!=newtext
window.text=newtext
end
if curve[0].visible && curve[3].visible &&
!curve[0].dragging && !curve[3].dragging
for point in points
point.visible=true
end
if !showline
curve[1].visible=true
curve[2].visible=true
curve[1].x=curve[0].x+0.3333*(curve[3].x-curve[0].x)
curve[1].y=curve[0].y+0.3333*(curve[3].y-curve[0].y)
curve[2].x=curve[0].x+0.6666*(curve[3].x-curve[0].x)
curve[2].y=curve[0].y+0.6666*(curve[3].y-curve[0].y)
end
showline=true
end
if showline
step=1.0/(points.length-1)
t=0.0
for i in 0...points.length
point=getCurvePoint(curve,t)
points[i].x=point[0]
points[i].y=point[1]
t+=step
end
end
end
window.dispose
# dispose temporary path
for point in points
point.dispose
end
points.clear
if showline
path=curveToPointPath(curve,sliderwin2.value(0))
# File.open("pointpath.txt","wb") { |f| f.write(path.inspect) }
for point in path
points.push(PointSprite.new(point[0],point[1],canvas.viewport))
end
end
for point in curve
point.dispose
end
sliderwin2.visible=true
next
elsif sliderwin2.changed?(defpathbutton)
canceled=false
pointpath=PointPath.new
for point in points
point.dispose
end
points.clear
window=Window_UnformattedTextPokemon.newWithSize("",
0, 320-64, 128, 64, canvas.viewport)
sliderwin2.visible=false
loop do
Graphics.update
Input.update
if Input.trigger?(Input::ESC)
canceled=true
break
end
if Input.triggerex?(Input::LeftMouseKey)
break
end
mousepos=Mouse::getMousePos(true)
window.text = (mousepos) ? sprintf("(%d,%d)",mousepos[0],mousepos[1]) : "(??,??)"
end
while !canceled
mousepos=Mouse::getMousePos(true)
if mouse && !pointpath.isEndPoint?(mousepos[0],mousepos[1])
pointpath.addPoint(mousepos[0],mousepos[1])
points.push(PointSprite.new(mousepos[0],mousepos[1],canvas.viewport))
end
window.text = (mousepos) ? sprintf("(%d,%d)",mousepos[0],mousepos[1]) : "(??,??)"
Graphics.update
Input.update
if Input.trigger?(Input::ESC) || Input.repeatcount(Input::LeftMouseKey)==0
break
end
end
window.dispose
# dispose temporary path
for point in points
point.dispose
end
points.clear
# generate smooth path from temporary path
path=pointpath.smoothPointPath(sliderwin2.value(0),true)
# redraw path from smooth path
for point in path
points.push(PointSprite.new(point[0],point[1],canvas.viewport))
end
# File.open("pointpath.txt","wb") { |f| f.write(path.inspect) }
sliderwin2.visible=true
next
elsif sliderwin2.changed?(okbutton) && path
# File.open("pointpath.txt","wb") { |f| f.write(path.inspect) }
neededsize=canvas.currentframe+sliderwin2.value(0)
if neededsize>canvas.animation.length
canvas.animation.resize(neededsize)
end
thiscel=canvas.currentCel
celnumber=canvas.currentcel
for i in canvas.currentframe...neededsize
cel=canvas.animation[i][celnumber]
if !canvas.animation[i][celnumber]
cel=pbCreateCel(0,0,thiscel[AnimFrame::PATTERN],canvas.animation.position)
canvas.animation[i][celnumber]=cel
end
cel[AnimFrame::X]=path[i-canvas.currentframe][0]
cel[AnimFrame::Y]=path[i-canvas.currentframe][1]
end
break
elsif sliderwin2.changed?(cancelbutton) || Input.trigger?(Input::B)
break
end
end
# dispose all points
for point in points
point.dispose
end
points.clear
sliderwin2.dispose
return
end

View File

@@ -0,0 +1,144 @@
################################################################################
# Importing and exporting
################################################################################
def pbRgssChdir(dir)
RTP.eachPathFor(dir) { |path| Dir.chdir(path) { yield } }
end
def tryLoadData(file)
begin
return load_data(file)
rescue
return nil
end
end
def dumpBase64Anim(s)
return [Zlib::Deflate.deflate(Marshal.dump(s))].pack("m").gsub(/\n/,"\r\n")
end
def loadBase64Anim(s)
return Marshal.restore(StringInput.new(Zlib::Inflate.inflate(s.unpack("m")[0])))
end
def pbExportAnim(animations)
filename=pbMessageFreeText(_INTL("Enter a filename."),"",false,32)
if filename!=""
begin
filename+=".anm"
File.open(filename,"wb") { |f|
f.write(dumpBase64Anim(animations[animations.selected]))
}
failed=false
rescue
pbMessage(_INTL("Couldn't save the animation to {1}.",filename))
failed=true
end
if !failed
pbMessage(_INTL("Animation was saved to {1} in the game folder.",filename))
pbMessage(_INTL("It's a text file, so it can be transferred to others easily."))
end
end
end
def pbImportAnim(animations,canvas,animwin)
animfiles=[]
pbRgssChdir(".") {
animfiles.concat(Dir.glob("*.anm"))
}
cmdwin=pbListWindow(animfiles,320)
cmdwin.opacity=200
cmdwin.height=480
cmdwin.viewport=canvas.viewport
loop do
Graphics.update
Input.update
cmdwin.update
if (Input.trigger?(Input::C) || (cmdwin.doubleclick? rescue false)) && animfiles.length>0
begin
textdata=loadBase64Anim(IO.read(animfiles[cmdwin.index]))
throw "Bad data" if !textdata.is_a?(PBAnimation)
textdata.id=-1 # this is not an RPG Maker XP animation
pbConvertAnimToNewFormat(textdata)
animations[animations.selected]=textdata
rescue
pbMessage(_INTL("The animation is invalid or could not be loaded."))
next
end
graphic=animations[animations.selected].graphic
graphic="Graphics/Animations/#{graphic}"
if graphic && graphic!="" && !FileTest.image_exist?(graphic)
pbMessage(_INTL("The animation file {1} was not found. The animation will load anyway.",graphic))
end
canvas.loadAnimation(animations[animations.selected])
animwin.animbitmap=canvas.animbitmap
break
end
if Input.trigger?(Input::B)
break
end
end
cmdwin.dispose
return
end
################################################################################
# Format conversion
################################################################################
def pbConvertAnimToNewFormat(textdata)
needconverting=false
for i in 0...textdata.length
next if !textdata[i]
for j in 0...PBAnimation::MAX_SPRITES
next if !textdata[i][j]
needconverting=true if textdata[i][j][AnimFrame::FOCUS]==nil
break if needconverting
end
break if needconverting
end
if needconverting
for i in 0...textdata.length
next if !textdata[i]
for j in 0...PBAnimation::MAX_SPRITES
next if !textdata[i][j]
textdata[i][j][AnimFrame::PRIORITY]=1 if textdata[i][j][AnimFrame::PRIORITY]==nil
if j==0 # User battler
textdata[i][j][AnimFrame::FOCUS]=2
textdata[i][j][AnimFrame::X]=PokeBattle_SceneConstants::FOCUSUSER_X
textdata[i][j][AnimFrame::Y]=PokeBattle_SceneConstants::FOCUSUSER_Y
elsif j==1 # Target battler
textdata[i][j][AnimFrame::FOCUS]=1
textdata[i][j][AnimFrame::X]=PokeBattle_SceneConstants::FOCUSTARGET_X
textdata[i][j][AnimFrame::Y]=PokeBattle_SceneConstants::FOCUSTARGET_Y
else
textdata[i][j][AnimFrame::FOCUS]=(textdata.position || 4)
if textdata.position==1
textdata[i][j][AnimFrame::X]+=PokeBattle_SceneConstants::FOCUSTARGET_X
textdata[i][j][AnimFrame::Y]+=PokeBattle_SceneConstants::FOCUSTARGET_Y-2
end
end
end
end
end
return needconverting
end
def pbConvertAnimsToNewFormat
pbMessage(_INTL("Will convert animations now."))
count=0
animations=pbLoadBattleAnimations
if !animations || !animations[0]
pbMessage(_INTL("No animations exist."))
return
end
for k in 0...animations.length
next if !animations[k]
ret=pbConvertAnimToNewFormat(animations[k])
count+=1 if ret
end
if count>0
save_data(animations,"Data/PkmnAnimations.rxdata")
$PokemonTemp.battleAnims = nil
end
pbMessage(_INTL("{1} animations converted to new format.",count))
end

File diff suppressed because it is too large Load Diff

View File

@@ -626,7 +626,7 @@ def pbEditMetadata(map_id = 0)
GameData::MapMetadata::DATA[map_id] = GameData::MapMetadata.new(metadata_hash)
GameData::MapMetadata.save
end
pbSaveMetadata
Compiler.write_metadata
end
end
@@ -671,7 +671,7 @@ def pbItemEditor
GameData::Item::DATA.delete(item)
GameData::Item::DATA.delete(id_number)
GameData::Item.save
pbSaveItems
Compiler.write_items
pbMessage(_INTL("The item was deleted."))
end
end
@@ -708,7 +708,7 @@ def pbItemEditor
# Add item's data to records
GameData::Item::DATA[itm.id_number] = GameData::Item::DATA[itm.id] = GameData::Item.new(item_hash)
GameData::Item.save
pbSaveItems
Compiler.write_items
end
else # Add a new item
pbItemEditorNew(nil)
@@ -772,7 +772,7 @@ def pbItemEditorNew(default_name)
# Add item's data to records
GameData::Item::DATA[id_number] = GameData::Item::DATA[id.to_sym] = GameData::Item.new(item_hash)
GameData::Item.save
pbSaveItems
Compiler.write_items
pbMessage(_INTL("The item {1} was created (ID: {2}).", name, id.to_s))
pbMessage(_ISPRINTF("Put the item's graphic (item{1:s}.png or item{2:03d}.png) in Graphics/Icons, or it will be blank.",
id, id_number))
@@ -857,7 +857,7 @@ def pbPokemonEditor
GameData::Species::DATA.delete(species)
GameData::Species::DATA.delete(id_number)
GameData::Species.save
pbSavePokemonData
Compiler.write_pokemon
pbMessage(_INTL("The species was deleted."))
end
end
@@ -971,7 +971,7 @@ def pbPokemonEditor
# Add species' data to records
GameData::Species::DATA[spec.id_number] = GameData::Species::DATA[spec.id] = GameData::Species.new(species_hash)
GameData::Species.save
pbSavePokemonData
Compiler.write_pokemon
pbMessage(_INTL("Data saved."))
end
else
@@ -1178,7 +1178,7 @@ def pbRegionalDexEditorMain
when 0 # Save all changes to Dexes
save_data(dex_lists, "Data/regional_dexes.dat")
$PokemonTemp.regionalDexes = nil
pbSaveRegionalDexes
Compiler.write_regional_dexes
pbMessage(_INTL("Data saved."))
break
when 1 # Just quit

View File

@@ -1,870 +0,0 @@
#===============================================================================
# Save type data to PBS file
#===============================================================================
def pbSaveTypes
File.open("PBS/types.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
# Write each type in turn
GameData::Type.each do |type|
f.write("\#-------------------------------\r\n")
f.write("[#{type.id_number}]\r\n")
f.write("Name = #{type.real_name}\r\n")
f.write("InternalName = #{type.id.to_s}\r\n")
f.write("IsPseudoType = true\r\n") if type.pseudo_type
f.write("IsSpecialType = true\r\n") if type.special?
f.write("Weaknesses = #{type.weaknesses.join(",")}\r\n") if type.weaknesses.length > 0
f.write("Resistances = #{type.resistances.join(",")}\r\n") if type.resistances.length > 0
f.write("Immunities = #{type.immunities.join(",")}\r\n") if type.immunities.length > 0
end
}
end
#===============================================================================
# Save ability data to PBS file
#===============================================================================
def pbSaveAbilities
File.open("PBS/abilities.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
GameData::Ability.each do |a|
f.write(sprintf("%d,%s,%s,%s\r\n",
a.id_number,
csvQuote(a.id.to_s),
csvQuote(a.real_name),
csvQuoteAlways(a.real_description)
))
end
}
end
#===============================================================================
# Save move data to PBS file
#===============================================================================
def pbSaveMoveData
File.open("PBS/moves.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
current_type = -1
GameData::Move.each do |m|
if current_type != m.type
current_type = m.type
f.write("\#-------------------------------\r\n")
end
f.write(sprintf("%d,%s,%s,%s,%d,%s,%s,%d,%d,%d,%s,%d,%s,%s\r\n",
m.id_number,
csvQuote(m.id.to_s),
csvQuote(m.real_name),
csvQuote(m.function_code),
m.base_damage,
m.type.to_s,
["Physical", "Special", "Status"][m.category],
m.accuracy,
m.total_pp,
m.effect_chance,
(getConstantName(PBTargets, m.target) rescue sprintf("%d", m.target)),
m.priority,
csvQuote(m.flags),
csvQuoteAlways(m.real_description)
))
end
}
end
#===============================================================================
# Save map connection data to PBS file
#===============================================================================
def normalizeConnectionPoint(conn)
ret = conn.clone
if conn[1]<0 && conn[4]<0
elsif conn[1]<0 || conn[4]<0
ret[4] = -conn[1]
ret[1] = -conn[4]
end
if conn[2]<0 && conn[5]<0
elsif conn[2]<0 || conn[5]<0
ret[5] = -conn[2]
ret[2] = -conn[5]
end
return ret
end
def writeConnectionPoint(map1,x1,y1,map2,x2,y2)
dims1 = MapFactoryHelper.getMapDims(map1)
dims2 = MapFactoryHelper.getMapDims(map2)
if x1==0 && x2==dims2[0]
return sprintf("%d,West,%d,%d,East,%d",map1,y1,map2,y2)
elsif y1==0 && y2==dims2[1]
return sprintf("%d,North,%d,%d,South,%d",map1,x1,map2,x2)
elsif x1==dims1[0] && x2==0
return sprintf("%d,East,%d,%d,West,%d",map1,y1,map2,y2)
elsif y1==dims1[1] && y2==0
return sprintf("%d,South,%d,%d,North,%d",map1,x1,map2,x2)
end
return sprintf("%d,%d,%d,%d,%d,%d",map1,x1,y1,map2,x2,y2)
end
def pbSerializeConnectionData(conndata,mapinfos)
File.open("PBS/connections.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
for conn in conndata
if mapinfos
# Skip if map no longer exists
next if !mapinfos[conn[0]] || !mapinfos[conn[3]]
f.write(sprintf("# %s (%d) - %s (%d)\r\n",
mapinfos[conn[0]] ? mapinfos[conn[0]].name : "???",conn[0],
mapinfos[conn[3]] ? mapinfos[conn[3]].name : "???",conn[3]))
end
if conn[1].is_a?(String) || conn[4].is_a?(String)
f.write(sprintf("%d,%s,%d,%d,%s,%d",conn[0],conn[1],
conn[2],conn[3],conn[4],conn[5]))
else
ret = normalizeConnectionPoint(conn)
f.write(writeConnectionPoint(ret[0],ret[1],ret[2],ret[3],ret[4],ret[5]))
end
f.write("\r\n")
end
}
save_data(conndata,"Data/map_connections.dat")
end
def pbSaveConnectionData
data = load_data("Data/map_connections.dat") rescue nil
return if !data
pbSerializeConnectionData(data,pbLoadRxData("Data/MapInfos"))
end
#===============================================================================
# Save metadata data to PBS file
#===============================================================================
def pbSaveMetadata
File.open("PBS/metadata.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
# Write global metadata
f.write("\#-------------------------------\r\n")
f.write("[000]\r\n")
metadata = GameData::Metadata.get
schema = GameData::Metadata::SCHEMA
keys = schema.keys.sort {|a, b| schema[a][0] <=> schema[b][0] }
for key in keys
record = metadata.property_from_string(key)
next if record.nil?
f.write(sprintf("%s = ", key))
pbWriteCsvRecord(record, f, schema[key])
f.write("\r\n")
end
# Write map metadata
map_infos = pbLoadRxData("Data/MapInfos")
schema = GameData::MapMetadata::SCHEMA
keys = schema.keys.sort {|a, b| schema[a][0] <=> schema[b][0] }
GameData::MapMetadata.each do |map_data|
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%03d]\r\n", map_data.id))
if map_infos && map_infos[map_data.id]
f.write(sprintf("# %s\r\n", map_infos[map_data.id].name))
end
for key in keys
record = map_data.property_from_string(key)
next if record.nil?
f.write(sprintf("%s = ", key))
pbWriteCsvRecord(record, f, schema[key])
f.write("\r\n")
end
end
}
end
#===============================================================================
# Save item data to PBS file
#===============================================================================
def pbSaveItems
File.open("PBS/items.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
current_pocket = 0
GameData::Item.each do |i|
if current_pocket != i.pocket
current_pocket = i.pocket
f.write("\#-------------------------------\r\n")
end
move_name = (i.move) ? GameData::Move.get(i.move).id.to_s : ""
sprintf_text = "%d,%s,%s,%s,%d,%d,%s,%d,%d,%d\r\n"
sprintf_text = "%d,%s,%s,%s,%d,%d,%s,%d,%d,%d,%s\r\n" if move_name != ""
f.write(sprintf(sprintf_text,
i.id_number,
csvQuote(i.id.to_s),
csvQuote(i.real_name),
csvQuote(i.real_name_plural),
i.pocket,
i.price,
csvQuoteAlways(i.real_description),
i.field_use,
i.battle_use,
i.type,
csvQuote(move_name)
))
end
}
end
#===============================================================================
# Save berry plant data to PBS file
#===============================================================================
def pbSaveBerryPlants
File.open("PBS/berryplants.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
GameData::BerryPlant.each do |bp|
f.write(sprintf("%s = %d,%d,%d,%d\r\n",
csvQuote(bp.id.to_s),
bp.hours_per_stage,
bp.drying_per_hour,
bp.minimum_yield,
bp.maximum_yield
))
end
}
end
#===============================================================================
# Save trainer list data to PBS file
#===============================================================================
def pbSaveTrainerLists
trainerlists = load_data("Data/trainer_lists.dat") rescue nil
return if !trainerlists
File.open("PBS/trainerlists.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
for tr in trainerlists
f.write("\#-------------------------------\r\n")
f.write(((tr[5]) ? "[DefaultTrainerList]" : "[TrainerList]")+"\r\n")
f.write("Trainers = "+tr[3]+"\r\n")
f.write("Pokemon = "+tr[4]+"\r\n")
f.write("Challenges = "+tr[2].join(",")+"\r\n") if !tr[5]
pbSaveBTTrainers(tr[0],"PBS/"+tr[3])
pbSaveBattlePokemon(tr[1],"PBS/"+tr[4])
end
}
end
#===============================================================================
# Save wild encounter data to PBS file
#===============================================================================
def pbSaveEncounterData
encdata = pbLoadEncountersData
return if !encdata
mapinfos = pbLoadRxData("Data/MapInfos")
File.open("PBS/encounters.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
sortedkeys = encdata.keys.sort
for i in sortedkeys
next if !encdata[i]
e = encdata[i]
mapname = ""
if mapinfos[i]
map = mapinfos[i].name
mapname = " # #{map}"
end
f.write("\#-------------------------------\r\n")
f.write(sprintf("%03d%s\r\n",i,mapname))
f.write(sprintf("%d,%d,%d\r\n",e[0][EncounterTypes::Land],
e[0][EncounterTypes::Cave],e[0][EncounterTypes::Water]))
for j in 0...e[1].length
enc = e[1][j]
next if !enc
f.write(sprintf("%s\r\n",EncounterTypes::Names[j]))
for k in 0...EncounterTypes::EnctypeChances[j].length
next if !enc[k]
encentry = enc[k]
if encentry[1]==encentry[2]
f.write(sprintf(" %s,%d\r\n",encentry[0],encentry[1]))
else
f.write(sprintf(" %s,%d,%d\r\n",encentry[0],encentry[1],encentry[2]))
end
end
end
end
}
end
#===============================================================================
# Save trainer type data to PBS file
#===============================================================================
def pbSaveTrainerTypes
File.open("PBS/trainertypes.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
GameData::TrainerType.each do |t|
f.write(sprintf("%d,%s,%s,%d,%s,%s,%s,%s,%s,%s\r\n",
t.id_number,
csvQuote(t.id.to_s),
csvQuote(t.real_name),
t.base_money,
csvQuote(t.battle_BGM),
csvQuote(t.victory_ME),
csvQuote(t.intro_ME),
["Male", "Female", "Mixed"][t.gender],
(t.skill_level == t.base_money) ? "" : t.skill_level.to_s,
csvQuote(t.skill_code)
))
end
}
end
#===============================================================================
# Save individual trainer data to PBS file
#===============================================================================
def pbSaveTrainerBattles
data = pbLoadTrainersData
return if !data
File.open("PBS/trainers.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
for trainer in data
trtypename = trainer[0].to_s
next if !trtypename
f.write("\#-------------------------------\r\n")
# Section
trainername = trainer[1] ? trainer[1].gsub(/,/,";") : "???"
if trainer[4]==0
f.write(sprintf("[%s,%s]\r\n",trtypename,trainername))
else
f.write(sprintf("[%s,%s,%d]\r\n",trtypename,trainername,trainer[4]))
end
# Trainer's items
if trainer[2] && trainer[2].length>0
itemstring = ""
for i in 0...trainer[2].length
itemstring.concat(",") if i > 0
itemstring.concat(trainer[2][i].to_s)
end
f.write(sprintf("Items = %s\r\n",itemstring)) if itemstring!=""
end
# Lose texts
if trainer[5] && trainer[5]!=""
f.write(sprintf("LoseText = %s\r\n",csvQuoteAlways(trainer[5])))
end
# Pokémon
for poke in trainer[3]
f.write(sprintf("Pokemon = %s,%d\r\n",poke[TrainerData::SPECIES],poke[TrainerData::LEVEL]))
if poke[TrainerData::NAME] && poke[TrainerData::NAME]!=""
f.write(sprintf(" Name = %s\r\n",poke[TrainerData::NAME]))
end
if poke[TrainerData::FORM]
f.write(sprintf(" Form = %d\r\n",poke[TrainerData::FORM]))
end
if poke[TrainerData::GENDER]
f.write(sprintf(" Gender = %s\r\n",(poke[TrainerData::GENDER]==1) ? "female" : "male"))
end
if poke[TrainerData::SHINY]
f.write(" Shiny = yes\r\n")
end
if poke[TrainerData::SHADOW]
f.write(" Shadow = yes\r\n")
end
if poke[TrainerData::MOVES] && poke[TrainerData::MOVES].length>0
movestring = ""
for i in 0...poke[TrainerData::MOVES].length
movename = GameData::Move.get(poke[TrainerData::MOVES][i]).id.to_s
next if !movename
movestring.concat(",") if i>0
movestring.concat(movename)
end
f.write(sprintf(" Moves = %s\r\n",movestring)) if movestring!=""
end
if poke[TrainerData::ABILITY]
f.write(sprintf(" Ability = %s\r\n",poke[TrainerData::ABILITY].to_s))
end
if poke[TrainerData::ITEM]
f.write(sprintf(" Item = %s\r\n",poke[TrainerData::ITEM].to_s))
end
if poke[TrainerData::NATURE]
nature = getConstantName(PBNatures,poke[TrainerData::NATURE]) rescue nil
f.write(sprintf(" Nature = %s\r\n",nature)) if nature
end
if poke[TrainerData::IV] && poke[TrainerData::IV].length>0
f.write(sprintf(" IV = %d",poke[TrainerData::IV][0]))
if poke[TrainerData::IV].length>1
for i in 1...6
f.write(sprintf(",%d",(i<poke[TrainerData::IV].length) ? poke[TrainerData::IV][i] : poke[TrainerData::IV][0]))
end
end
f.write("\r\n")
end
if poke[TrainerData::EV] && poke[TrainerData::EV].length>0
f.write(sprintf(" EV = %d",poke[TrainerData::EV][0]))
if poke[TrainerData::EV].length>1
for i in 1...6
f.write(sprintf(",%d",(i<poke[TrainerData::EV].length) ? poke[TrainerData::EV][i] : poke[TrainerData::EV][0]))
end
end
f.write("\r\n")
end
if poke[TrainerData::HAPPINESS]
f.write(sprintf(" Happiness = %d\r\n",poke[TrainerData::HAPPINESS]))
end
if poke[TrainerData::BALL]
f.write(sprintf(" Ball = %d\r\n",poke[TrainerData::BALL]))
end
end
end
}
end
#===============================================================================
# Save Town Map data to PBS file
#===============================================================================
def pbSaveTownMap
mapdata = pbLoadTownMapData
return if !mapdata
File.open("PBS/townmap.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
for i in 0...mapdata.length
map = mapdata[i]
next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i))
rname = pbGetMessage(MessageTypes::RegionNames,i)
f.write(sprintf("Name = %s\r\nFilename = %s\r\n",
(rname && rname!="") ? rname : _INTL("Unnamed"),
csvQuote((map[1].is_a?(Array)) ? map[1][0] : map[1])))
for loc in map[2]
f.write("Point = ")
pbWriteCsvRecord(loc,f,[nil,"uussUUUU"])
f.write("\r\n")
end
end
}
end
#===============================================================================
# Save phone message data to PBS file
#===============================================================================
def pbSavePhoneData
data = load_data("Data/phone.dat") rescue nil
return if !data
File.open("PBS/phone.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Generics>]\r\n")
f.write(data.generics.join("\r\n")+"\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<BattleRequests>]\r\n")
f.write(data.battleRequests.join("\r\n")+"\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsMorning>]\r\n")
f.write(data.greetingsMorning.join("\r\n")+"\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsEvening>]\r\n")
f.write(data.greetingsEvening.join("\r\n")+"\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Greetings>]\r\n")
f.write(data.greetings.join("\r\n")+"\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies1>]\r\n")
f.write(data.bodies1.join("\r\n")+"\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies2>]\r\n")
f.write(data.bodies2.join("\r\n")+"\r\n")
}
end
#===============================================================================
# Save Pokémon data to PBS file
#===============================================================================
def pbSavePokemonData
File.open("PBS/pokemon.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
GameData::Species.each do |species|
next if species.form != 0
pbSetWindowText(_INTL("Writing species {1}...", species.id_number))
Graphics.update if species.id_number % 50 == 0
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n", species.id_number))
f.write(sprintf("Name = %s\r\n", species.real_name))
f.write(sprintf("InternalName = %s\r\n", species.species))
f.write(sprintf("Type1 = %s\r\n", species.type1))
f.write(sprintf("Type2 = %s\r\n", species.type2)) if species.type2 != species.type1
f.write(sprintf("BaseStats = %s\r\n", species.base_stats.join(",")))
f.write(sprintf("GenderRate = %s\r\n", getConstantName(PBGenderRates, species.gender_rate)))
f.write(sprintf("GrowthRate = %s\r\n", getConstantName(PBGrowthRates, species.growth_rate)))
f.write(sprintf("BaseEXP = %d\r\n", species.base_exp))
f.write(sprintf("EffortPoints = %s\r\n", species.evs.join(",")))
f.write(sprintf("Rareness = %d\r\n", species.catch_rate))
f.write(sprintf("Happiness = %d\r\n", species.happiness))
if species.abilities.length > 0
f.write(sprintf("Abilities = %s\r\n", species.abilities.join(",")))
end
if species.hidden_abilities.length > 0
f.write(sprintf("HiddenAbility = %s\r\n", species.hidden_abilities.join(",")))
end
if species.moves.length > 0
f.write(sprintf("Moves = %s\r\n", species.moves.join(",")))
end
if species.tutor_moves.length > 0
f.write(sprintf("TutorMoves = %s\r\n", species.tutor_moves.join(",")))
end
if species.egg_moves.length > 0
f.write(sprintf("EggMoves = %s\r\n", species.egg_moves.join(",")))
end
if species.egg_groups.length > 0
f.write("Compatibility = ")
species.egg_groups.each_with_index do |group, i|
f.write(",") if i > 0
f.write(getConstantName(PBEggGroups, group))
end
f.write("\r\n")
end
f.write(sprintf("StepsToHatch = %d\r\n", species.hatch_steps))
f.write(sprintf("Height = %.1f\r\n", species.height / 10.0))
f.write(sprintf("Weight = %.1f\r\n", species.weight / 10.0))
f.write(sprintf("Color = %s\r\n", getConstantName(PBColors, species.color)))
f.write(sprintf("Shape = %d\r\n", species.shape))
f.write(sprintf("Habitat = %s\r\n", getConstantName(PBHabitats, species.habitat))) if species.habitat != PBHabitats::None
f.write(sprintf("Kind = %s\r\n", species.real_category))
f.write(sprintf("Pokedex = %s\r\n", species.real_pokedex_entry))
f.write(sprintf("FormName = %s\r\n", species.real_form_name)) if species.real_form_name && !species.real_form_name.empty?
f.write(sprintf("Generation = %d\r\n", species.generation)) if species.generation != 0
f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common)) if species.wild_item_common
f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon)) if species.wild_item_uncommon
f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare)) if species.wild_item_rare
f.write(sprintf("BattlerPlayerX = %d\r\n", species.back_sprite_x))
f.write(sprintf("BattlerPlayerY = %d\r\n", species.back_sprite_y))
f.write(sprintf("BattlerEnemyX = %d\r\n", species.front_sprite_x))
f.write(sprintf("BattlerEnemyY = %d\r\n", species.front_sprite_y))
f.write(sprintf("BattlerAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != 0
f.write(sprintf("BattlerShadowX = %d\r\n", species.shadow_x))
f.write(sprintf("BattlerShadowSize = %d\r\n", species.shadow_size))
if species.evolutions.any? { |evo| !evo[3] }
f.write("Evolutions = ")
need_comma = false
species.evolutions.each do |evo|
next if evo[3] # Skip prevolution entries
f.write(",") if need_comma
need_comma = true
f.write(sprintf("%s,%s,", evo[0], getConstantName(PBEvolution, evo[1])))
param_type = PBEvolution.getFunction(evo[1], "parameterType")
has_param = !PBEvolution.hasFunction?(evo[1], "parameterType") || param_type != nil
next if !has_param
if param_type
if GameData.const_defined?(param_type.to_sym)
f.write(evo[2].to_s)
else
f.write(getConstantName(param_type, evo[2]))
end
else
f.write(evo[2].to_s)
end
end
f.write("\r\n")
end
f.write(sprintf("Incense = %s\r\n", species.incense)) if species.incense
end
}
Graphics.update
end
#===============================================================================
# Save Pokémon forms data to PBS file
#===============================================================================
def pbSavePokemonFormsData
File.open("PBS/pokemonforms.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
GameData::Species.each do |species|
next if species.form == 0
base_species = GameData::Species.get(species.species)
pbSetWindowText(_INTL("Writing species {1}...", species.id_number))
Graphics.update if species.id_number % 50 == 0
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%s,%d]\r\n", species.species, species.form))
f.write(sprintf("FormName = %s\r\n", species.real_form_name)) if species.real_form_name && !species.real_form_name.empty?
f.write(sprintf("PokedexForm = %d\r\n", species.pokedex_form)) if species.pokedex_form != species.form
f.write(sprintf("MegaStone = %s\r\n", species.mega_stone)) if species.mega_stone
f.write(sprintf("MegaMove = %s\r\n", species.mega_move)) if species.mega_move
f.write(sprintf("UnmegaForm = %d\r\n", species.unmega_form)) if species.unmega_form != 0
f.write(sprintf("MegaMessage = %d\r\n", species.mega_message)) if species.mega_message != 0
if species.type1 != base_species.type1 || species.type2 != base_species.type2
f.write(sprintf("Type1 = %s\r\n", species.type1))
f.write(sprintf("Type2 = %s\r\n", species.type2)) if species.type2 != species.type1
end
f.write(sprintf("BaseStats = %s\r\n", species.base_stats.join(","))) if species.base_stats != base_species.base_stats
f.write(sprintf("BaseEXP = %d\r\n", species.base_exp)) if species.base_exp != base_species.base_exp
f.write(sprintf("EffortPoints = %s\r\n", species.evs.join(","))) if species.evs != base_species.evs
f.write(sprintf("Rareness = %d\r\n", species.catch_rate)) if species.catch_rate != base_species.catch_rate
f.write(sprintf("Happiness = %d\r\n", species.happiness)) if species.happiness != base_species.happiness
if species.abilities.length > 0 && species.abilities != base_species.abilities
f.write(sprintf("Abilities = %s\r\n", species.abilities.join(",")))
end
if species.hidden_abilities.length > 0 && species.hidden_abilities != base_species.hidden_abilities
f.write(sprintf("HiddenAbility = %s\r\n", species.hidden_abilities.join(",")))
end
if species.moves.length > 0 && species.moves != base_species.moves
f.write(sprintf("Moves = %s\r\n", species.moves.join(",")))
end
if species.tutor_moves.length > 0 && species.tutor_moves != base_species.tutor_moves
f.write(sprintf("TutorMoves = %s\r\n", species.tutor_moves.join(",")))
end
if species.egg_moves.length > 0 && species.egg_moves != base_species.egg_moves
f.write(sprintf("EggMoves = %s\r\n", species.egg_moves.join(",")))
end
if species.egg_groups.length > 0 && species.egg_groups != base_species.egg_groups
f.write("Compatibility = ")
species.egg_groups.each_with_index do |group, i|
f.write(",") if i > 0
f.write(getConstantName(PBEggGroups, group))
end
f.write("\r\n")
end
f.write(sprintf("StepsToHatch = %d\r\n", species.hatch_steps)) if species.hatch_steps != base_species.hatch_steps
f.write(sprintf("Height = %.1f\r\n", species.height / 10.0)) if species.height != base_species.height
f.write(sprintf("Weight = %.1f\r\n", species.weight / 10.0)) if species.weight != base_species.weight
f.write(sprintf("Color = %s\r\n", getConstantName(PBColors, species.color))) if species.color != base_species.color
f.write(sprintf("Shape = %d\r\n", species.shape)) if species.shape != base_species.shape
if species.habitat != PBHabitats::None && species.habitat != base_species.habitat
f.write(sprintf("Habitat = %s\r\n", getConstantName(PBHabitats, species.habitat)))
end
f.write(sprintf("Kind = %s\r\n", species.real_category)) if species.real_category != base_species.real_category
f.write(sprintf("Pokedex = %s\r\n", species.real_pokedex_entry)) if species.real_pokedex_entry != base_species.real_pokedex_entry
f.write(sprintf("Generation = %d\r\n", species.generation)) if species.generation != base_species.generation
if species.wild_item_common != base_species.wild_item_common ||
species.wild_item_uncommon != base_species.wild_item_uncommon ||
species.wild_item_rare != base_species.wild_item_rare
f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common)) if species.wild_item_common
f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon)) if species.wild_item_uncommon
f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare)) if species.wild_item_rare
end
f.write(sprintf("BattlerPlayerX = %d\r\n", species.back_sprite_x)) if species.back_sprite_x != base_species.back_sprite_x
f.write(sprintf("BattlerPlayerY = %d\r\n", species.back_sprite_y)) if species.back_sprite_y != base_species.back_sprite_y
f.write(sprintf("BattlerEnemyX = %d\r\n", species.front_sprite_x)) if species.front_sprite_x != base_species.front_sprite_x
f.write(sprintf("BattlerEnemyY = %d\r\n", species.front_sprite_y)) if species.front_sprite_y != base_species.front_sprite_y
f.write(sprintf("BattlerAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != base_species.front_sprite_altitude
f.write(sprintf("BattlerShadowX = %d\r\n", species.shadow_x)) if species.shadow_x != base_species.shadow_x
f.write(sprintf("BattlerShadowSize = %d\r\n", species.shadow_size)) if species.shadow_size != base_species.shadow_size
if species.evolutions != base_species.evolutions && species.evolutions.any? { |evo| !evo[3] }
f.write("Evolutions = ")
need_comma = false
species.evolutions.each do |evo|
next if evo[3] # Skip prevolution entries
f.write(",") if need_comma
need_comma = true
f.write(sprintf("%s,%s,", evo[0], getConstantName(PBEvolution, evo[1])))
param_type = PBEvolution.getFunction(evo[1], "parameterType")
has_param = !PBEvolution.hasFunction?(evo[1], "parameterType") || param_type != nil
next if !has_param
if param_type
if GameData.const_defined?(param_type.to_sym)
f.write(evo[2].to_s)
else
f.write(getConstantName(param_type, evo[2]))
end
else
f.write(evo[2].to_s)
end
end
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save Shadow move data to PBS file
#===============================================================================
def pbSaveShadowMoves
shadow_movesets = pbLoadShadowMovesets
File.open("PBS/shadowmoves.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
GameData::Species.each do |species_data|
moveset = shadow_movesets[species_data.id]
next if !moveset || moveset.length == 0
f.write(sprintf("%s = %s\r\n", species_data.id, moveset.join(",")))
end
}
end
#===============================================================================
# Save Regional Dexes data to PBS file
#===============================================================================
def pbSaveRegionalDexes
dex_lists = pbLoadRegionalDexes
File.open("PBS/regionaldexes.txt", "wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
# Write each Dex list in turn
dex_lists.each_with_index do |list, index|
f.write("\#-------------------------------\r\n")
f.write("[#{index}]")
comma = false
current_family = nil
list.each do |species|
next if !species
if current_family && current_family.include?(species)
f.write(",") if comma
else
current_family = EvolutionHelper.all_related_species(species)
comma = false
f.write("\r\n")
end
f.write(species)
comma = true
end
f.write("\r\n")
end
}
end
#===============================================================================
# Save Battle Tower trainer data to PBS file
#===============================================================================
def pbSaveBTTrainers(bttrainers,filename)
return if !bttrainers || !filename
btTrainersRequiredTypes = {
"Type" => [0,"e",nil], # Specifies a trainer
"Name" => [1,"s"],
"BeginSpeech" => [2,"s"],
"EndSpeechWin" => [3,"s"],
"EndSpeechLose" => [4,"s"],
"PokemonNos" => [5,"*u"]
}
File.open(filename,"wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
for i in 0...bttrainers.length
next if !bttrainers[i]
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%03d]\r\n",i))
for key in btTrainersRequiredTypes.keys
schema = btTrainersRequiredTypes[key]
record = bttrainers[i][schema[0]]
next if record==nil
f.write(sprintf("%s = ",key))
if key=="Type"
f.write(record.to_s)
elsif key=="PokemonNos"
f.write(record.join(",")) # pbWriteCsvRecord somehow won't work here
else
pbWriteCsvRecord(record,f,schema)
end
f.write(sprintf("\r\n"))
end
end
}
end
#===============================================================================
# Save Battle Tower Pokémon data to PBS file
#===============================================================================
def pbSaveBattlePokemon(btpokemon,filename)
return if !btpokemon || !filename
species = {0=>""}
moves = {0=>""}
items = {0=>""}
natures = {}
File.open(filename,"wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
f.write("\#-------------------------------\r\n")
for i in 0...btpokemon.length
Graphics.update if i%500==0
pkmn = btpokemon[i]
f.write(pbFastInspect(pkmn,moves,species,items,natures))
f.write("\r\n")
end
}
end
def pbFastInspect(pkmn,moves,species,items,natures)
c1 = (species[pkmn.species]) ? species[pkmn.species] : (species[pkmn.species] = GameData::Species.get(pkmn.species).species.to_s)
c2 = (items[pkmn.item]) ? items[pkmn.item] : (items[pkmn.item] = GameData::Item.get(pkmn.item).id.to_s)
c3 = (natures[pkmn.nature]) ? natures[pkmn.nature] :
(natures[pkmn.nature] = getConstantName(PBNatures,pkmn.nature))
evlist = ""
ev = pkmn.ev
evs = ["HP","ATK","DEF","SPD","SA","SD"]
for i in 0...ev
if ((ev&(1<<i))!=0)
evlist += "," if evlist.length>0
evlist += evs[i]
end
end
c4 = (moves[pkmn.move1]) ? moves[pkmn.move1] : (moves[pkmn.move1] = GameData::Move.get(pkmn.move1).id.to_s)
c5 = (moves[pkmn.move2]) ? moves[pkmn.move2] : (moves[pkmn.move2] = GameData::Move.get(pkmn.move2).id.to_s)
c6 = (moves[pkmn.move3]) ? moves[pkmn.move3] : (moves[pkmn.move3] = GameData::Move.get(pkmn.move3).id.to_s)
c7 = (moves[pkmn.move4]) ? moves[pkmn.move4] : (moves[pkmn.move4] = GameData::Move.get(pkmn.move4).id.to_s)
return "#{c1};#{c2};#{c3};#{evlist};#{c4},#{c5},#{c6},#{c7}"
end
#===============================================================================
# Save all data to PBS files
#===============================================================================
def pbSaveAllData
pbSaveTypes; Graphics.update
pbSaveAbilities; Graphics.update
pbSaveMoveData; Graphics.update
pbSaveConnectionData; Graphics.update
pbSaveMetadata; Graphics.update
pbSaveItems; Graphics.update
pbSaveBerryPlants; Graphics.update
pbSaveTrainerLists; Graphics.update
pbSaveEncounterData; Graphics.update
pbSaveTrainerTypes; Graphics.update
pbSaveTrainerBattles; Graphics.update
pbSaveTownMap; Graphics.update
pbSavePhoneData; Graphics.update
pbSavePokemonData; Graphics.update
pbSavePokemonFormsData; Graphics.update
pbSaveShadowMoves; Graphics.update
pbSaveRegionalDexes; Graphics.update
end

View File

@@ -1,116 +0,0 @@
#===============================================================================
# String formatting, conversion of value to string
#===============================================================================
def csvQuote(str,always=false)
return "" if !str || str==""
if always || str[/[,\"]/] # || str[/^\s/] || str[/\s$/] || str[/^#/]
str = str.gsub(/[\"]/,"\\\"")
str = "\"#{str}\""
end
return str
end
def csvQuoteAlways(str)
return csvQuote(str,true)
end
def pbWriteCsvRecord(record,file,schema)
rec = (record.is_a?(Array)) ? record.clone : [record]
for i in 0...schema[1].length
chr = schema[1][i,1]
file.write(",") if i>0
if rec[i].nil?
# do nothing
elsif rec[i].is_a?(String)
file.write(csvQuote(rec[i]))
elsif rec[i].is_a?(Symbol)
file.write(csvQuote(rec[i].to_s))
elsif rec[i]==true
file.write("true")
elsif rec[i]==false
file.write("false")
elsif rec[i].is_a?(Numeric)
case chr
when "e", "E" # Enumerable
enumer = schema[2+i]
if enumer.is_a?(Array)
file.write(enumer[rec[i]])
elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
mod = Object.const_get(enumer.to_sym)
file.write(getConstantName(mod,rec[i]))
elsif enumer.is_a?(Module)
file.write(getConstantName(enumer,rec[i]))
elsif enumer.is_a?(Hash)
for key in enumer.keys
if enumer[key]==rec[i]
file.write(key)
break
end
end
end
when "y", "Y" # Enumerable or integer
enumer = schema[2+i]
if enumer.is_a?(Array)
if enumer[rec[i]]!=nil
file.write(enumer[rec[i]])
else
file.write(rec[i])
end
elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
mod = Object.const_get(enumer.to_sym)
file.write(getConstantNameOrValue(mod,rec[i]))
elsif enumer.is_a?(Module)
file.write(getConstantNameOrValue(enumer,rec[i]))
elsif enumer.is_a?(Hash)
hasenum = false
for key in enumer.keys
if enumer[key]==rec[i]
file.write(key)
hasenum = true; break
end
end
file.write(rec[i]) unless hasenum
end
else # Any other record type
file.write(rec[i].inspect)
end
else
file.write(rec[i].inspect)
end
end
return record
end
#===============================================================================
# Enum const manipulators and parsers
#===============================================================================
def getConstantName(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
return c if mod.const_get(c.to_sym)==value
end
raise _INTL("Value {1} not defined by a constant in {2}",value,mod.name)
end
def getConstantNameOrValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
return c if mod.const_get(c.to_sym)==value
end
return value.inspect
end
def setConstantName(mod,value,name)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value
end
mod.const_set(name,value)
end
def removeConstantValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value
end
end

View File

@@ -108,110 +108,6 @@ def pbMapTree
return retarray
end
#===============================================================================
# Make up internal names for things based on their actual names
#===============================================================================
module MakeshiftConsts
@@consts = []
def self.get(c,i,modname=nil)
@@consts[c] = [] if !@@consts[c]
return @@consts[c][i] if @@consts[c][i]
if modname
v = getConstantName(modname,i) rescue nil
if v
@@consts[c][i] = v
return v
end
end
trname = pbGetMessage(c,i)
trconst = trname.gsub(/é/,"e")
trconst = trconst.upcase
trconst = trconst.gsub(//,"fE")
trconst = trconst.gsub(//,"mA")
trconst = trconst.gsub(/[^A-Za-z0-9_]/,"")
if trconst.length==0
return nil if trname.length==0
trconst = sprintf("T_%03d",i)
elsif !trconst[0,1][/[A-Z]/]
trconst = "T_"+trconst
end
while @@consts[c].include?(trconst)
trconst = sprintf("%s_%03d",trconst,i)
end
@@consts[c][i] = trconst
return trconst
end
end
def pbGetEvolutionConst(i)
ret = MakeshiftConsts.get(50,i,PBEvolution)
if !ret
ret = ["None",
"Happiness","HappinessDay","HappinessNight","Level","Trade",
"TradeItem","Item","AttackGreater","AtkDefEqual","DefenseGreater",
"Silcoon","Cascoon","Ninjask","Shedinja","Beauty",
"ItemMale","ItemFemale","DayHoldItem","NightHoldItem","HasMove",
"HasInParty","LevelMale","LevelFemale","Location","TradeSpecies",
"Custom1","Custom2","Custom3","Custom4","Custom5"]
i = 0 if i>=ret.length || i<0
ret = ret[i]
end
return ret
end
def pbGetEggGroupConst(i)
ret = MakeshiftConsts.get(51,i,PBEggGroups)
if !ret
ret = ["Undiscovered",
"Monster","Water1","Bug","Flying","Field",
"Fairy","Grass","Humanlike","Water3","Mineral",
"Amorphous","Water2","Ditto","Dragon"][i]
i = 0 if i>=ret.length || i<0
ret = ret[i]
end
return ret
end
def pbGetColorConst(i)
ret = MakeshiftConsts.get(52,i,PBColors)
if !ret
ret = ["Red","Blue","Yellow","Green","Black","Brown","Purple","Gray","White","Pink"]
i = 0 if i>=ret.length || i<0
ret = ret[i]
end
return ret
end
def pbGetGenderConst(i)
ret = MakeshiftConsts.get(53,i,PBGenderRates)
if !ret
ret = ["Genderless","AlwaysMale","FemaleOneEighth","Female25Percent",
"Female50Percent","Female75Percent","FemaleSevenEighths",
"AlwaysFemale"]
i = 0 if i>=ret.length || i<0
ret = ret[i]
end
return ret
end
def pbGetHabitatConst(i)
ret = MakeshiftConsts.get(54,i,PBHabitats)
if !ret
ret = ["","Grassland","Forest","WatersEdge","Sea","Cave","Mountain",
"RoughTerrain","Urban","Rare"]
i = 0 if i>=ret.length || i<0
ret = ret[i]
end
return ret
end
#===============================================================================
# List all members of a class
#===============================================================================

View File

@@ -284,7 +284,8 @@ class MapScreenScene
def serializeConnectionData
conndata=generateConnectionData()
pbSerializeConnectionData(conndata,@mapinfos)
save_data(conndata, "Data/map_connections.dat")
Compiler.write_connections
@mapconns=conndata
end
@@ -575,7 +576,7 @@ class MapScreenScene
MapFactoryHelper.clear
save_data(@encdata,"Data/encounters.dat")
$PokemonTemp.encountersData = nil
pbSaveEncounterData
Compiler.write_encounters
end
break if pbConfirmMessage(_INTL("Exit from the editor?"))
end

View File

@@ -32,8 +32,8 @@ def pbAutoPositionAll
bitmap2.dispose if bitmap2
end
GameData::Species.save
pbSavePokemonData
pbSavePokemonFormsData
Compiler.write_pokemon
Compiler.write_pokemon_forms
end
#===============================================================================
@@ -97,8 +97,8 @@ class SpritePositioner
def pbSaveMetrics
GameData::Species.save
pbSavePokemonData
pbSavePokemonFormsData
Compiler.write_pokemon
Compiler.write_pokemon_forms
end
def update

File diff suppressed because it is too large Load Diff

View File

@@ -76,6 +76,19 @@ module Compiler
return line
end
def csvQuote(str,always=false)
return "" if !str || str==""
if always || str[/[,\"]/] # || str[/^\s/] || str[/\s$/] || str[/^#/]
str = str.gsub(/[\"]/,"\\\"")
str = "\"#{str}\""
end
return str
end
def csvQuoteAlways(str)
return csvQuote(str,true)
end
#=============================================================================
# PBS file readers
#=============================================================================
@@ -115,7 +128,7 @@ module Compiler
yield lastsection,sectionname if havesection
end
# Used for pokemon.txt
# Used for types.txt, pokemon.txt, metadata.txt
def pbEachFileSection(f)
pbEachFileSectionEx(f) { |section,name|
yield section,name.to_i if block_given? && name[/^\d+$/]
@@ -201,7 +214,7 @@ module Compiler
}
end
# Used for connections.txt, abilities.txt, moves.txt, trainertypes.txt
# Used for connections.txt, abilities.txt, moves.txt, regionaldexes.txt
def pbCompilerEachPreppedLine(filename)
File.open(filename,"rb") { |f|
FileLineData.file = filename
@@ -514,34 +527,73 @@ module Compiler
end
#=============================================================================
# Check whether a number fits in a given numerical range (all unused)
# Write values to a file using a schema
#=============================================================================
def pbCheckByte(x,valuename)
if x<0 || x>255
raise _INTL("The value \"{1}\" must be from 0 through 255 (00-FF in hex), got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
def pbWriteCsvRecord(record,file,schema)
rec = (record.is_a?(Array)) ? record.clone : [record]
for i in 0...schema[1].length
chr = schema[1][i,1]
file.write(",") if i>0
if rec[i].nil?
# do nothing
elsif rec[i].is_a?(String)
file.write(csvQuote(rec[i]))
elsif rec[i].is_a?(Symbol)
file.write(csvQuote(rec[i].to_s))
elsif rec[i]==true
file.write("true")
elsif rec[i]==false
file.write("false")
elsif rec[i].is_a?(Numeric)
case chr
when "e", "E" # Enumerable
enumer = schema[2+i]
if enumer.is_a?(Array)
file.write(enumer[rec[i]])
elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
mod = Object.const_get(enumer.to_sym)
file.write(getConstantName(mod,rec[i]))
elsif enumer.is_a?(Module)
file.write(getConstantName(enumer,rec[i]))
elsif enumer.is_a?(Hash)
for key in enumer.keys
if enumer[key]==rec[i]
file.write(key)
break
end
end
def pbCheckSignedByte(x,valuename)
if x<-128 || x>127
raise _INTL("The value \"{1}\" must be from -128 through 127, got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
end
when "y", "Y" # Enumerable or integer
enumer = schema[2+i]
if enumer.is_a?(Array)
if enumer[rec[i]]!=nil
file.write(enumer[rec[i]])
else
file.write(rec[i])
end
elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
mod = Object.const_get(enumer.to_sym)
file.write(getConstantNameOrValue(mod,rec[i]))
elsif enumer.is_a?(Module)
file.write(getConstantNameOrValue(enumer,rec[i]))
elsif enumer.is_a?(Hash)
hasenum = false
for key in enumer.keys
if enumer[key]==rec[i]
file.write(key)
hasenum = true; break
end
end
def pbCheckWord(x,valuename)
if x<0 || x>65535
raise _INTL("The value \"{1}\" must be from 0 through 65535 (0000-FFFF in hex), got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
file.write(rec[i]) unless hasenum
end
else # Any other record type
file.write(rec[i].inspect)
end
else
file.write(rec[i].inspect)
end
end
def pbCheckSignedWord(x,valuename)
if x<-32768 || x>32767
raise _INTL("The value \"{1}\" must be from -32768 through 32767, got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
end
return record
end
#=============================================================================
@@ -625,12 +677,14 @@ module Compiler
MessageTypes.loadMessageFile("Data/messages.dat")
end
if mustCompile
yield(_INTL("Compiling type data"))
compile_types # No dependencies
yield(_INTL("Compiling town map data"))
compile_town_map # No dependencies
yield(_INTL("Compiling map connection data"))
compile_connections # No dependencies
yield(_INTL("Compiling phone data"))
compile_phone
yield(_INTL("Compiling type data"))
compile_types # No dependencies
yield(_INTL("Compiling ability data"))
compile_abilities # No dependencies
yield(_INTL("Compiling move data"))
@@ -645,22 +699,20 @@ module Compiler
compile_pokemon_forms # Depends on Species, Move, Item, Type, Ability
yield(_INTL("Compiling machine data"))
compile_move_compatibilities # Depends on Species, Move
yield(_INTL("Compiling Trainer type data"))
compile_trainer_types # No dependencies
yield(_INTL("Compiling Trainer data"))
compile_trainers # Depends on Species, Item, Move
yield(_INTL("Compiling phone data"))
compile_phone
yield(_INTL("Compiling metadata"))
compile_metadata # Depends on TrainerType
yield(_INTL("Compiling battle Trainer data"))
compile_trainer_lists # Depends on TrainerType
yield(_INTL("Compiling encounter data"))
compile_encounters # Depends on Species
yield(_INTL("Compiling shadow moveset data"))
compile_shadow_movesets # Depends on Species, Move
yield(_INTL("Compiling Regional Dexes"))
compile_regional_dexes # Depends on Species
yield(_INTL("Compiling encounter data"))
compile_encounters # Depends on Species
yield(_INTL("Compiling Trainer type data"))
compile_trainer_types # No dependencies
yield(_INTL("Compiling Trainer data"))
compile_trainers # Depends on Species, Item, Move
yield(_INTL("Compiling battle Trainer data"))
compile_trainer_lists # Depends on TrainerType
yield(_INTL("Compiling metadata"))
compile_metadata # Depends on TrainerType
yield(_INTL("Compiling animations"))
compile_animations
yield(_INTL("Converting events"))
@@ -698,8 +750,7 @@ module Compiler
"trainer_lists.dat",
"trainer_types.dat",
"trainers.dat",
"types.dat",
"Constants.rxdata"
"types.dat"
]
textFiles = [
"abilities.txt",
@@ -728,7 +779,7 @@ module Compiler
# If no PBS file, create one and fill it, then recompile
if !safeIsDirectory?("PBS")
Dir.mkdir("PBS") rescue nil
pbSaveAllData
write_all
mustCompile = true
end
# Should recompile if holding Ctrl

View File

@@ -1,305 +0,0 @@
# NOTE: Everything in here is unused.
#===============================================================================
# Serial record
#===============================================================================
# Unused
module SerialRecords
class SerialRecord < Array
def bytesize
return SerialRecord.bytesize(self)
end
def encode(strm)
return SerialRecord.encode(self,strm)
end
def self.bytesize(arr)
ret = 0
return 0 if !arr
for field in arr
if field==nil || field==true || field==false
ret += 1
elsif field.is_a?(String)
ret += strSize(field)+1
elsif field.is_a?(Numeric)
ret += intSize(field)+1
end
end
return ret
end
def self.encode(arr,strm)
return if !arr
for field in arr
if field==nil
strm.write("0")
elsif field==true
strm.write("T")
elsif field==false
strm.write("F")
elsif field.is_a?(String)
strm.write("\"")
encodeString(strm,field)
elsif field.is_a?(Numeric)
strm.write("i")
encodeInt(strm,field)
end
end
end
def self.decode(strm,offset,length)
ret = SerialRecord.new
strm.pos = offset
while strm.pos<offset+length
datatype = strm.read(1)
case datatype
when "0" then ret.push(nil)
when "T" then ret.push(true)
when "F" then ret.push(false)
when "\"" then ret.push(decodeString(strm))
when "i" then ret.push(decodeInt(strm))
end
end
return ret
end
end
def self.readSerialRecords(filename)
ret = []
return ret if !pbRgssExists?(filename)
pbRgssOpen(filename,"rb") { |file|
numrec = file.fgetdw>>3
curpos = 0
numrec.times do
file.pos = curpos
offset = file.fgetdw
length = file.fgetdw
record = SerialRecord.decode(file,offset,length)
ret.push(record)
curpos += 8
end
}
return ret
end
def self.writeSerialRecords(filename,records)
File.open(filename,"wb") { |file|
totalsize = records.length*8
for record in records
file.fputdw(totalsize)
bytesize = record.bytesize
file.fputdw(bytesize)
totalsize += bytesize
end
for record in records
record.encode(file)
end
}
end
end
#===============================================================================
# Data structures
#===============================================================================
# Unused
class ByteArray
include Enumerable
def initialize(data=nil)
@a = (data) ? data.unpack("C*") : []
end
def [](i); return @a[i]; end
def []=(i,value); @a[i] = value; end
def length; @a.length; end
def size; @a.size; end
def fillNils(length,value)
for i in 0...length
@a[i] = value if !@a[i]
end
end
def each
@a.each { |i| yield i}
end
def self._load(str)
return self.new(str)
end
def _dump(_depth=100)
return @a.pack("C*")
end
end
# Unused
class WordArray
include Enumerable
def initialize(data=nil)
@a = (data) ? data.unpack("v*") : []
end
def [](i); return @a[i]; end
def []=(i,value); @a[i] = value; end
def length; @a.length; end
def size; @a.size; end
def fillNils(length,value)
for i in 0...length
@a[i] = value if !@a[i]
end
end
def each
@a.each { |i| yield i}
end
def self._load(str)
return self.new(str)
end
def _dump(_depth=100)
return @a.pack("v*")
end
end
# Unused
class SignedWordArray
include Enumerable
def initialize(data=nil)
@a = (data) ? data.unpack("v*") : []
end
def []=(i,value)
@a[i] = value
end
def [](i)
v = @a[i]
return 0 if !v
return (v<0x8000) ? v : -((~v)&0xFFFF)-1
end
def length; @a.length; end
def size; @a.size; end
def fillNils(length,value)
for i in 0...length
@a[i] = value if !@a[i]
end
end
def each
@a.each { |i| yield i}
end
def self._load(str)
return self.new(str)
end
def _dump(_depth=100)
return @a.pack("v*")
end
end
#===============================================================================
# Encoding and decoding
#===============================================================================
# Unused
def intSize(value)
return 1 if value<0x80
return 2 if value<0x4000
return 3 if value<0x200000
return 4 if value<0x10000000
return 5
end
# Unused
def encodeInt(strm,value)
num = 0
loop do
if value<0x80
strm.fputb(value)
return num+1
end
strm.fputb(0x80|(value&0x7F))
value >>= 7
num += 1
end
end
# Unused
def decodeInt(strm)
bits = 0
curbyte = 0
ret = 0
begin
curbyte = strm.fgetb
ret += (curbyte&0x7F)<<bits
bits += 7
end while ((curbyte&0x80)>0)&&bits<0x1d
return ret
end
# Unused
def strSize(str)
return str.length+intSize(str.length)
end
# Unused
def encodeString(strm,str)
encodeInt(strm,str.length)
strm.write(str)
end
# Unused
def decodeString(strm)
len = decodeInt(strm)
return strm.read(len)
end
# Unused
def frozenArrayValue(arr)
typestring = ""
for i in 0...arr.length
if i>0
typestring += ((i%20)==0) ? ",\r\n" : ","
end
typestring += arr[i].to_s
end
return "["+typestring+"].freeze"
end
#===============================================================================
# Scripted constants
#===============================================================================
# Unused
def pbFindScript(a,name)
a.each { |i|
next if !i
return i if i[1]==name
}
return nil
end
# Unused
def pbAddScript(script,sectionname)
begin
scripts = load_data("Data/Constants.rxdata")
scripts = [] if !scripts
rescue
scripts = []
end
if false # s
s = pbFindScript(scripts,sectionname)
s[2]+=Zlib::Deflate.deflate("#{script}\r\n")
else
scripts.push([rand(100000000),sectionname,Zlib::Deflate.deflate("#{script}\r\n")])
end
save_data(scripts,"Data/Constants.rxdata")
end

View File

@@ -2,96 +2,7 @@ module Compiler
module_function
#=============================================================================
# Compile metadata
#=============================================================================
def compile_metadata
GameData::Metadata::DATA.clear
GameData::MapMetadata::DATA.clear
# Read from PBS file
File.open("PBS/metadata.txt", "rb") { |f|
FileLineData.file = "PBS/metadata.txt" # For error reporting
# Read a whole section's lines at once, then run through this code.
# contents is a hash containing all the XXX=YYY lines in that section, where
# the keys are the XXX and the values are the YYY (as unprocessed strings).
pbEachFileSection(f) { |contents, map_id|
schema = (map_id == 0) ? GameData::Metadata::SCHEMA : GameData::MapMetadata::SCHEMA
# Go through schema hash of compilable data and compile this section
for key in schema.keys
FileLineData.setSection(map_id, key, contents[key]) # For error reporting
# Skip empty properties, or raise an error if a required property is
# empty
if contents[key].nil?
if map_id == 0 && ["Home", "PlayerA"].include?(key)
raise _INTL("The entry {1} is required in PBS/metadata.txt section 0.", key)
end
next
end
# Compile value for key
value = pbGetCsvRecord(contents[key], key, schema[key])
value = nil if value.is_a?(Array) && value.length == 0
contents[key] = value
end
if map_id == 0 # Global metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:home => contents["Home"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:surf_BGM => contents["SurfBGM"],
:bicycle_BGM => contents["BicycleBGM"],
:player_A => contents["PlayerA"],
:player_B => contents["PlayerB"],
:player_C => contents["PlayerC"],
:player_D => contents["PlayerD"],
:player_E => contents["PlayerE"],
:player_F => contents["PlayerF"],
:player_G => contents["PlayerG"],
:player_H => contents["PlayerH"]
}
# Add metadata's data to records
GameData::Metadata::DATA[map_id] = GameData::Metadata.new(metadata_hash)
else # Map metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:outdoor_map => contents["Outdoor"],
:announce_location => contents["ShowArea"],
:can_bicycle => contents["Bicycle"],
:always_bicycle => contents["BicycleAlways"],
:teleport_destination => contents["HealingSpot"],
:weather => contents["Weather"],
:town_map_position => contents["MapPosition"],
:dive_map_id => contents["DiveMap"],
:dark_map => contents["DarkMap"],
:safari_map => contents["SafariMap"],
:snap_edges => contents["SnapEdges"],
:random_dungeon => contents["Dungeon"],
:battle_background => contents["BattleBack"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:town_map_size => contents["MapSize"],
:battle_environment => contents["Environment"]
}
# Add metadata's data to records
GameData::MapMetadata::DATA[map_id] = GameData::MapMetadata.new(metadata_hash)
end
}
}
# Save all data
GameData::Metadata.save
GameData::MapMetadata.save
Graphics.update
end
#=============================================================================
# Compile town map points
# Compile Town Map data
#=============================================================================
def compile_town_map
nonglobaltypes = {
@@ -182,36 +93,6 @@ module Compiler
Graphics.update
end
#=============================================================================
# Compile berry plants
#=============================================================================
def compile_berry_plants
GameData::BerryPlant::DATA.clear
pbCompilerEachCommentedLine("PBS/berryplants.txt") { |line, line_no|
if line[/^\s*(\w+)\s*=\s*(.*)$/] # Of the format XXX = YYY
key = $1
value = $2
item_symbol = parseItem(key)
item_number = GameData::Item.get(item_symbol).id_number
line = pbGetCsvRecord(value, line_no, [0, "vuuv"])
# Construct berry plant hash
berry_plant_hash = {
:id => item_symbol,
:id_number => item_number,
:hours_per_stage => line[0],
:drying_per_hour => line[1],
:minimum_yield => line[2],
:maximum_yield => line[3]
}
# Add berry plant's data to records
GameData::BerryPlant::DATA[item_number] = GameData::BerryPlant::DATA[item_symbol] = GameData::BerryPlant.new(berry_plant_hash)
end
}
# Save all data
GameData::BerryPlant.save
Graphics.update
end
#=============================================================================
# Compile phone messages
#=============================================================================
@@ -251,7 +132,7 @@ module Compiler
end
#=============================================================================
# Compile types
# Compile type data
#=============================================================================
def compile_types
GameData::Type::DATA.clear
@@ -325,7 +206,7 @@ module Compiler
end
#=============================================================================
# Compile abilities
# Compile ability data
#=============================================================================
def compile_abilities
GameData::Ability::DATA.clear
@@ -359,100 +240,6 @@ module Compiler
Graphics.update
end
#=============================================================================
# Compile items
#=============================================================================
=begin
class ItemList
include Enumerable
def initialize; @list = []; end
def length; @list.length; end
def []=(x,v); @list[x] = v; end
def [](x)
if !@list[x]
defrecord = SerialRecords::SerialRecord.new
defrecord.push(0)
defrecord.push("????????")
defrecord.push(0)
defrecord.push(0)
defrecord.push("????????")
@list[x] = defrecord
return defrecord
end
return @list[x]
end
def each
for i in 0...self.length
yield self[i]
end
end
end
def readItemList(filename)
ret = ItemList.new
return ret if !pbRgssExists?(filename)
pbRgssOpen(filename,"rb") { |file|
numrec = file.fgetdw>>3
curpos = 0
numrec.times do
file.pos = curpos
offset = file.fgetdw
length = file.fgetdw
record = SerialRecords::SerialRecord.decode(file,offset,length)
ret[record[0]] = record
curpos += 8
end
}
return ret
end
=end
def compile_items
GameData::Item::DATA.clear
item_names = []
item_names_plural = []
item_descriptions = []
# Read each line of items.txt at a time and compile it into an item
pbCompilerEachCommentedLine("PBS/items.txt") { |line, line_no|
line = pbGetCsvRecord(line, line_no, [0, "vnssuusuuUN"])
item_number = line[0]
item_symbol = line[1].to_sym
if GameData::Item::DATA[item_number]
raise _INTL("Item ID number '{1}' is used twice.\r\n{2}", item_number, FileLineData.linereport)
elsif GameData::Item::DATA[item_symbol]
raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_symbol, FileLineData.linereport)
end
# Construct item hash
item_hash = {
:id_number => item_number,
:id => item_symbol,
:name => line[2],
:name_plural => line[3],
:pocket => line[4],
:price => line[5],
:description => line[6],
:field_use => line[7],
:battle_use => line[8],
:type => line[9]
}
item_hash[:move] = parseMove(line[10]) if !nil_or_empty?(line[10])
# Add item's data to records
GameData::Item::DATA[item_number] = GameData::Item::DATA[item_symbol] = GameData::Item.new(item_hash)
item_names[item_number] = item_hash[:name]
item_names_plural[item_number] = item_hash[:name_plural]
item_descriptions[item_number] = item_hash[:description]
}
# Save all data
GameData::Item.save
MessageTypes.setMessages(MessageTypes::Items, item_names)
MessageTypes.setMessages(MessageTypes::ItemPlurals, item_names_plural)
MessageTypes.setMessages(MessageTypes::ItemDescriptions, item_descriptions)
Graphics.update
end
#=============================================================================
# Compile move data
#=============================================================================
@@ -510,49 +297,83 @@ module Compiler
end
#=============================================================================
# Compile battle animations
# Compile item data
#=============================================================================
def compile_animations
begin
pbanims = load_data("Data/PkmnAnimations.rxdata")
rescue
pbanims = PBAnimations.new
def compile_items
GameData::Item::DATA.clear
item_names = []
item_names_plural = []
item_descriptions = []
# Read each line of items.txt at a time and compile it into an item
pbCompilerEachCommentedLine("PBS/items.txt") { |line, line_no|
line = pbGetCsvRecord(line, line_no, [0, "vnssuusuuUN"])
item_number = line[0]
item_symbol = line[1].to_sym
if GameData::Item::DATA[item_number]
raise _INTL("Item ID number '{1}' is used twice.\r\n{2}", item_number, FileLineData.linereport)
elsif GameData::Item::DATA[item_symbol]
raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_symbol, FileLineData.linereport)
end
move2anim = [[],[]]
=begin
anims = load_data("Data/Animations.rxdata")
for anim in anims
next if !anim || anim.frames.length==1
found = false
for i in 0...pbanims.length
if pbanims[i] && pbanims[i].id==anim.id
found = true if pbanims[i].array.length>1
break
end
end
pbanims[anim.id] = pbConvertRPGAnimation(anim) if !found
end
=end
for i in 0...pbanims.length
next if !pbanims[i]
if pbanims[i].name[/^OppMove\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[1][moveid] = i
end
elsif pbanims[i].name[/^Move\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[0][moveid] = i
end
end
end
save_data(move2anim,"Data/move2anim.dat")
save_data(pbanims,"Data/PkmnAnimations.rxdata")
# Construct item hash
item_hash = {
:id_number => item_number,
:id => item_symbol,
:name => line[2],
:name_plural => line[3],
:pocket => line[4],
:price => line[5],
:description => line[6],
:field_use => line[7],
:battle_use => line[8],
:type => line[9]
}
item_hash[:move] = parseMove(line[10]) if !nil_or_empty?(line[10])
# Add item's data to records
GameData::Item::DATA[item_number] = GameData::Item::DATA[item_symbol] = GameData::Item.new(item_hash)
item_names[item_number] = item_hash[:name]
item_names_plural[item_number] = item_hash[:name_plural]
item_descriptions[item_number] = item_hash[:description]
}
# Save all data
GameData::Item.save
MessageTypes.setMessages(MessageTypes::Items, item_names)
MessageTypes.setMessages(MessageTypes::ItemPlurals, item_names_plural)
MessageTypes.setMessages(MessageTypes::ItemDescriptions, item_descriptions)
Graphics.update
end
#=============================================================================
# Compile Pokémon
# Compile berry plant data
#=============================================================================
def compile_berry_plants
GameData::BerryPlant::DATA.clear
pbCompilerEachCommentedLine("PBS/berryplants.txt") { |line, line_no|
if line[/^\s*(\w+)\s*=\s*(.*)$/] # Of the format XXX = YYY
key = $1
value = $2
item_symbol = parseItem(key)
item_number = GameData::Item.get(item_symbol).id_number
line = pbGetCsvRecord(value, line_no, [0, "vuuv"])
# Construct berry plant hash
berry_plant_hash = {
:id => item_symbol,
:id_number => item_number,
:hours_per_stage => line[0],
:drying_per_hour => line[1],
:minimum_yield => line[2],
:maximum_yield => line[3]
}
# Add berry plant's data to records
GameData::BerryPlant::DATA[item_number] = GameData::BerryPlant::DATA[item_symbol] = GameData::BerryPlant.new(berry_plant_hash)
end
}
# Save all data
GameData::BerryPlant.save
Graphics.update
end
#=============================================================================
# Compile Pokémon data
#=============================================================================
def compile_pokemon
GameData::Species::DATA.clear
@@ -713,7 +534,7 @@ module Compiler
end
#=============================================================================
# Compile Pokémon forms
# Compile Pokémon forms data
#=============================================================================
def compile_pokemon_forms
species_names = []
@@ -930,8 +751,8 @@ module Compiler
species_hash[species_data.id].each { |move| species_data.tutor_moves.push(move) }
end
GameData::Species.save
pbSavePokemonData
pbSavePokemonFormsData
Compiler.write_pokemon
Compiler.write_pokemon_forms
begin
File.delete("PBS/tm.txt")
rescue SystemCallError
@@ -1003,7 +824,7 @@ module Compiler
end
#=============================================================================
# Compile wild encounters
# Compile wild encounter data
#=============================================================================
def compile_encounters
lines = []
@@ -1110,7 +931,7 @@ module Compiler
end
#=============================================================================
# Compile trainer types
# Compile trainer type data
#=============================================================================
def compile_trainer_types
GameData::TrainerType::DATA.clear
@@ -1155,7 +976,7 @@ module Compiler
end
#=============================================================================
# Compile individual trainers
# Compile individual trainer data
#=============================================================================
def compile_trainers
trainer_info_types = TrainerData::SCHEMA
@@ -1355,47 +1176,6 @@ module Compiler
#=============================================================================
# Compile Battle Tower and other Cups trainers/Pokémon
#=============================================================================
def compile_battle_tower_trainers(filename)
sections = []
requiredtypes = {
"Type" => [0, "e", :TrainerType],
"Name" => [1, "s"],
"BeginSpeech" => [2, "s"],
"EndSpeechWin" => [3, "s"],
"EndSpeechLose" => [4, "s"],
"PokemonNos" => [5, "*u"]
}
trainernames = []
beginspeech = []
endspeechwin = []
endspeechlose = []
if safeExists?(filename)
File.open(filename,"rb") { |f|
FileLineData.file = filename
pbEachFileSectionEx(f) { |section,name|
rsection = []
for key in section.keys
FileLineData.setSection(name,key,section[key])
schema = requiredtypes[key]
next if !schema
record = pbGetCsvRecord(section[key],0,schema)
rsection[schema[0]] = record
end
trainernames.push(rsection[1])
beginspeech.push(rsection[2])
endspeechwin.push(rsection[3])
endspeechlose.push(rsection[4])
sections.push(rsection)
}
}
end
MessageTypes.addMessagesAsHash(MessageTypes::TrainerNames,trainernames)
MessageTypes.addMessagesAsHash(MessageTypes::BeginSpeech,beginspeech)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechWin,endspeechwin)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechLose,endspeechlose)
return sections
end
def compile_trainer_lists
btTrainersRequiredTypes = {
"Trainers" => [0, "s"],
@@ -1462,4 +1242,176 @@ module Compiler
}
save_data(sections,"Data/trainer_lists.dat")
end
def compile_battle_tower_trainers(filename)
sections = []
requiredtypes = {
"Type" => [0, "e", :TrainerType],
"Name" => [1, "s"],
"BeginSpeech" => [2, "s"],
"EndSpeechWin" => [3, "s"],
"EndSpeechLose" => [4, "s"],
"PokemonNos" => [5, "*u"]
}
trainernames = []
beginspeech = []
endspeechwin = []
endspeechlose = []
if safeExists?(filename)
File.open(filename,"rb") { |f|
FileLineData.file = filename
pbEachFileSectionEx(f) { |section,name|
rsection = []
for key in section.keys
FileLineData.setSection(name,key,section[key])
schema = requiredtypes[key]
next if !schema
record = pbGetCsvRecord(section[key],0,schema)
rsection[schema[0]] = record
end
trainernames.push(rsection[1])
beginspeech.push(rsection[2])
endspeechwin.push(rsection[3])
endspeechlose.push(rsection[4])
sections.push(rsection)
}
}
end
MessageTypes.addMessagesAsHash(MessageTypes::TrainerNames,trainernames)
MessageTypes.addMessagesAsHash(MessageTypes::BeginSpeech,beginspeech)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechWin,endspeechwin)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechLose,endspeechlose)
return sections
end
#=============================================================================
# Compile metadata
#=============================================================================
def compile_metadata
GameData::Metadata::DATA.clear
GameData::MapMetadata::DATA.clear
# Read from PBS file
File.open("PBS/metadata.txt", "rb") { |f|
FileLineData.file = "PBS/metadata.txt" # For error reporting
# Read a whole section's lines at once, then run through this code.
# contents is a hash containing all the XXX=YYY lines in that section, where
# the keys are the XXX and the values are the YYY (as unprocessed strings).
pbEachFileSection(f) { |contents, map_id|
schema = (map_id == 0) ? GameData::Metadata::SCHEMA : GameData::MapMetadata::SCHEMA
# Go through schema hash of compilable data and compile this section
for key in schema.keys
FileLineData.setSection(map_id, key, contents[key]) # For error reporting
# Skip empty properties, or raise an error if a required property is
# empty
if contents[key].nil?
if map_id == 0 && ["Home", "PlayerA"].include?(key)
raise _INTL("The entry {1} is required in PBS/metadata.txt section 0.", key)
end
next
end
# Compile value for key
value = pbGetCsvRecord(contents[key], key, schema[key])
value = nil if value.is_a?(Array) && value.length == 0
contents[key] = value
end
if map_id == 0 # Global metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:home => contents["Home"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:surf_BGM => contents["SurfBGM"],
:bicycle_BGM => contents["BicycleBGM"],
:player_A => contents["PlayerA"],
:player_B => contents["PlayerB"],
:player_C => contents["PlayerC"],
:player_D => contents["PlayerD"],
:player_E => contents["PlayerE"],
:player_F => contents["PlayerF"],
:player_G => contents["PlayerG"],
:player_H => contents["PlayerH"]
}
# Add metadata's data to records
GameData::Metadata::DATA[map_id] = GameData::Metadata.new(metadata_hash)
else # Map metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:outdoor_map => contents["Outdoor"],
:announce_location => contents["ShowArea"],
:can_bicycle => contents["Bicycle"],
:always_bicycle => contents["BicycleAlways"],
:teleport_destination => contents["HealingSpot"],
:weather => contents["Weather"],
:town_map_position => contents["MapPosition"],
:dive_map_id => contents["DiveMap"],
:dark_map => contents["DarkMap"],
:safari_map => contents["SafariMap"],
:snap_edges => contents["SnapEdges"],
:random_dungeon => contents["Dungeon"],
:battle_background => contents["BattleBack"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:town_map_size => contents["MapSize"],
:battle_environment => contents["Environment"]
}
# Add metadata's data to records
GameData::MapMetadata::DATA[map_id] = GameData::MapMetadata.new(metadata_hash)
end
}
}
# Save all data
GameData::Metadata.save
GameData::MapMetadata.save
Graphics.update
end
#=============================================================================
# Compile battle animations
#=============================================================================
def compile_animations
begin
pbanims = load_data("Data/PkmnAnimations.rxdata")
rescue
pbanims = PBAnimations.new
end
move2anim = [[],[]]
=begin
anims = load_data("Data/Animations.rxdata")
for anim in anims
next if !anim || anim.frames.length==1
found = false
for i in 0...pbanims.length
if pbanims[i] && pbanims[i].id==anim.id
found = true if pbanims[i].array.length>1
break
end
end
pbanims[anim.id] = pbConvertRPGAnimation(anim) if !found
end
=end
for i in 0...pbanims.length
next if !pbanims[i]
if pbanims[i].name[/^OppMove\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[1][moveid] = i
end
elsif pbanims[i].name[/^Move\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[0][moveid] = i
end
end
end
save_data(move2anim,"Data/move2anim.dat")
save_data(pbanims,"Data/PkmnAnimations.rxdata")
end
end

View File

@@ -0,0 +1,837 @@
module Compiler
module_function
def add_PBS_header_to_file(file)
file.write(0xEF.chr)
file.write(0xBB.chr)
file.write(0xBF.chr)
file.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
end
#=============================================================================
# Save Town Map data to PBS file
#=============================================================================
def write_town_map
mapdata = pbLoadTownMapData
return if !mapdata
File.open("PBS/townmap.txt","wb") { |f|
add_PBS_header_to_file(f)
for i in 0...mapdata.length
map = mapdata[i]
next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i))
rname = pbGetMessage(MessageTypes::RegionNames,i)
f.write(sprintf("Name = %s\r\nFilename = %s\r\n",
(rname && rname!="") ? rname : _INTL("Unnamed"),
csvQuote((map[1].is_a?(Array)) ? map[1][0] : map[1])))
for loc in map[2]
f.write("Point = ")
pbWriteCsvRecord(loc,f,[nil,"uussUUUU"])
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save map connections to PBS file
#===============================================================================
def normalizeConnectionPoint(conn)
ret = conn.clone
if conn[1] < 0 && conn[4] < 0
elsif conn[1] < 0 || conn[4] < 0
ret[4] = -conn[1]
ret[1] = -conn[4]
end
if conn[2] < 0 && conn[5] < 0
elsif conn[2] < 0 || conn[5] < 0
ret[5] = -conn[2]
ret[2] = -conn[5]
end
return ret
end
def writeConnectionPoint(map1, x1, y1, map2, x2, y2)
dims1 = MapFactoryHelper.getMapDims(map1)
dims2 = MapFactoryHelper.getMapDims(map2)
if x1 == 0 && x2 == dims2[0]
return sprintf("%d,West,%d,%d,East,%d", map1, y1, map2, y2)
elsif y1 == 0 && y2 == dims2[1]
return sprintf("%d,North,%d,%d,South,%d", map1, x1, map2, x2)
elsif x1 == dims1[0] && x2 == 0
return sprintf("%d,East,%d,%d,West,%d", map1, y1, map2, y2)
elsif y1 == dims1[1] && y2 == 0
return sprintf("%d,South,%d,%d,North,%d", map1, x1, map2, x2)
end
return sprintf("%d,%d,%d,%d,%d,%d", map1, x1, y1, map2, x2, y2)
end
def write_connections
conndata = load_data("Data/map_connections.dat") rescue nil
return if !conndata
mapinfos = pbLoadRxData("Data/MapInfos")
File.open("PBS/connections.txt","wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
for conn in conndata
if mapinfos
# Skip if map no longer exists
next if !mapinfos[conn[0]] || !mapinfos[conn[3]]
f.write(sprintf("# %s (%d) - %s (%d)\r\n",
(mapinfos[conn[0]]) ? mapinfos[conn[0]].name : "???", conn[0],
(mapinfos[conn[3]]) ? mapinfos[conn[3]].name : "???", conn[3]))
end
if conn[1].is_a?(String) || conn[4].is_a?(String)
f.write(sprintf("%d,%s,%d,%d,%s,%d", conn[0], conn[1], conn[2],
conn[3], conn[4], conn[5]))
else
ret = normalizeConnectionPoint(conn)
f.write(writeConnectionPoint(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]))
end
f.write("\r\n")
end
}
Graphics.update
end
#===============================================================================
# Save phone messages to PBS file
#===============================================================================
def write_phone
data = load_data("Data/phone.dat") rescue nil
return if !data
File.open("PBS/phone.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
f.write("[<Generics>]\r\n")
f.write(data.generics.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<BattleRequests>]\r\n")
f.write(data.battleRequests.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsMorning>]\r\n")
f.write(data.greetingsMorning.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsEvening>]\r\n")
f.write(data.greetingsEvening.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Greetings>]\r\n")
f.write(data.greetings.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies1>]\r\n")
f.write(data.bodies1.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies2>]\r\n")
f.write(data.bodies2.join("\r\n") + "\r\n")
}
Graphics.update
end
#===============================================================================
# Save type data to PBS file
#===============================================================================
def write_types
File.open("PBS/types.txt", "wb") { |f|
add_PBS_header_to_file(f)
# Write each type in turn
GameData::Type.each do |type|
f.write("\#-------------------------------\r\n")
f.write("[#{type.id_number}]\r\n")
f.write("Name = #{type.real_name}\r\n")
f.write("InternalName = #{type.id.to_s}\r\n")
f.write("IsPseudoType = true\r\n") if type.pseudo_type
f.write("IsSpecialType = true\r\n") if type.special?
f.write("Weaknesses = #{type.weaknesses.join(",")}\r\n") if type.weaknesses.length > 0
f.write("Resistances = #{type.resistances.join(",")}\r\n") if type.resistances.length > 0
f.write("Immunities = #{type.immunities.join(",")}\r\n") if type.immunities.length > 0
end
}
Graphics.update
end
#===============================================================================
# Save ability data to PBS file
#===============================================================================
def write_abilities
File.open("PBS/abilities.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::Ability.each do |a|
f.write(sprintf("%d,%s,%s,%s\r\n",
a.id_number,
csvQuote(a.id.to_s),
csvQuote(a.real_name),
csvQuoteAlways(a.real_description)
))
end
}
Graphics.update
end
#===============================================================================
# Save move data to PBS file
#===============================================================================
def write_moves
File.open("PBS/moves.txt", "wb") { |f|
add_PBS_header_to_file(f)
current_type = -1
GameData::Move.each do |m|
if current_type != m.type
current_type = m.type
f.write("\#-------------------------------\r\n")
end
f.write(sprintf("%d,%s,%s,%s,%d,%s,%s,%d,%d,%d,%s,%d,%s,%s\r\n",
m.id_number,
csvQuote(m.id.to_s),
csvQuote(m.real_name),
csvQuote(m.function_code),
m.base_damage,
m.type.to_s,
["Physical", "Special", "Status"][m.category],
m.accuracy,
m.total_pp,
m.effect_chance,
(getConstantName(PBTargets, m.target) rescue sprintf("%d", m.target)),
m.priority,
csvQuote(m.flags),
csvQuoteAlways(m.real_description)
))
end
}
Graphics.update
end
#===============================================================================
# Save item data to PBS file
#===============================================================================
def write_items
File.open("PBS/items.txt", "wb") { |f|
add_PBS_header_to_file(f)
current_pocket = 0
GameData::Item.each do |i|
if current_pocket != i.pocket
current_pocket = i.pocket
f.write("\#-------------------------------\r\n")
end
move_name = (i.move) ? GameData::Move.get(i.move).id.to_s : ""
sprintf_text = "%d,%s,%s,%s,%d,%d,%s,%d,%d,%d\r\n"
sprintf_text = "%d,%s,%s,%s,%d,%d,%s,%d,%d,%d,%s\r\n" if move_name != ""
f.write(sprintf(sprintf_text,
i.id_number,
csvQuote(i.id.to_s),
csvQuote(i.real_name),
csvQuote(i.real_name_plural),
i.pocket,
i.price,
csvQuoteAlways(i.real_description),
i.field_use,
i.battle_use,
i.type,
csvQuote(move_name)
))
end
}
Graphics.update
end
#===============================================================================
# Save berry plant data to PBS file
#===============================================================================
def write_berry_plants
File.open("PBS/berryplants.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::BerryPlant.each do |bp|
f.write(sprintf("%s = %d,%d,%d,%d\r\n",
csvQuote(bp.id.to_s),
bp.hours_per_stage,
bp.drying_per_hour,
bp.minimum_yield,
bp.maximum_yield
))
end
}
Graphics.update
end
#===============================================================================
# Save Pokémon data to PBS file
#===============================================================================
def write_pokemon
File.open("PBS/pokemon.txt", "wb") { |f|
add_PBS_header_to_file(f)
GameData::Species.each do |species|
next if species.form != 0
pbSetWindowText(_INTL("Writing species {1}...", species.id_number))
Graphics.update if species.id_number % 50 == 0
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n", species.id_number))
f.write(sprintf("Name = %s\r\n", species.real_name))
f.write(sprintf("InternalName = %s\r\n", species.species))
f.write(sprintf("Type1 = %s\r\n", species.type1))
f.write(sprintf("Type2 = %s\r\n", species.type2)) if species.type2 != species.type1
f.write(sprintf("BaseStats = %s\r\n", species.base_stats.join(",")))
f.write(sprintf("GenderRate = %s\r\n", getConstantName(PBGenderRates, species.gender_rate)))
f.write(sprintf("GrowthRate = %s\r\n", getConstantName(PBGrowthRates, species.growth_rate)))
f.write(sprintf("BaseEXP = %d\r\n", species.base_exp))
f.write(sprintf("EffortPoints = %s\r\n", species.evs.join(",")))
f.write(sprintf("Rareness = %d\r\n", species.catch_rate))
f.write(sprintf("Happiness = %d\r\n", species.happiness))
if species.abilities.length > 0
f.write(sprintf("Abilities = %s\r\n", species.abilities.join(",")))
end
if species.hidden_abilities.length > 0
f.write(sprintf("HiddenAbility = %s\r\n", species.hidden_abilities.join(",")))
end
if species.moves.length > 0
f.write(sprintf("Moves = %s\r\n", species.moves.join(",")))
end
if species.tutor_moves.length > 0
f.write(sprintf("TutorMoves = %s\r\n", species.tutor_moves.join(",")))
end
if species.egg_moves.length > 0
f.write(sprintf("EggMoves = %s\r\n", species.egg_moves.join(",")))
end
if species.egg_groups.length > 0
f.write("Compatibility = ")
species.egg_groups.each_with_index do |group, i|
f.write(",") if i > 0
f.write(getConstantName(PBEggGroups, group))
end
f.write("\r\n")
end
f.write(sprintf("StepsToHatch = %d\r\n", species.hatch_steps))
f.write(sprintf("Height = %.1f\r\n", species.height / 10.0))
f.write(sprintf("Weight = %.1f\r\n", species.weight / 10.0))
f.write(sprintf("Color = %s\r\n", getConstantName(PBColors, species.color)))
f.write(sprintf("Shape = %d\r\n", species.shape))
f.write(sprintf("Habitat = %s\r\n", getConstantName(PBHabitats, species.habitat))) if species.habitat != PBHabitats::None
f.write(sprintf("Kind = %s\r\n", species.real_category))
f.write(sprintf("Pokedex = %s\r\n", species.real_pokedex_entry))
f.write(sprintf("FormName = %s\r\n", species.real_form_name)) if species.real_form_name && !species.real_form_name.empty?
f.write(sprintf("Generation = %d\r\n", species.generation)) if species.generation != 0
f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common)) if species.wild_item_common
f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon)) if species.wild_item_uncommon
f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare)) if species.wild_item_rare
f.write(sprintf("BattlerPlayerX = %d\r\n", species.back_sprite_x))
f.write(sprintf("BattlerPlayerY = %d\r\n", species.back_sprite_y))
f.write(sprintf("BattlerEnemyX = %d\r\n", species.front_sprite_x))
f.write(sprintf("BattlerEnemyY = %d\r\n", species.front_sprite_y))
f.write(sprintf("BattlerAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != 0
f.write(sprintf("BattlerShadowX = %d\r\n", species.shadow_x))
f.write(sprintf("BattlerShadowSize = %d\r\n", species.shadow_size))
if species.evolutions.any? { |evo| !evo[3] }
f.write("Evolutions = ")
need_comma = false
species.evolutions.each do |evo|
next if evo[3] # Skip prevolution entries
f.write(",") if need_comma
need_comma = true
f.write(sprintf("%s,%s,", evo[0], getConstantName(PBEvolution, evo[1])))
param_type = PBEvolution.getFunction(evo[1], "parameterType")
has_param = !PBEvolution.hasFunction?(evo[1], "parameterType") || param_type != nil
next if !has_param
if param_type
if GameData.const_defined?(param_type.to_sym)
f.write(evo[2].to_s)
else
f.write(getConstantName(param_type, evo[2]))
end
else
f.write(evo[2].to_s)
end
end
f.write("\r\n")
end
f.write(sprintf("Incense = %s\r\n", species.incense)) if species.incense
end
}
Graphics.update
end
#===============================================================================
# Save Pokémon forms data to PBS file
#===============================================================================
def write_pokemon_forms
File.open("PBS/pokemonforms.txt", "wb") { |f|
add_PBS_header_to_file(f)
GameData::Species.each do |species|
next if species.form == 0
base_species = GameData::Species.get(species.species)
pbSetWindowText(_INTL("Writing species {1}...", species.id_number))
Graphics.update if species.id_number % 50 == 0
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%s,%d]\r\n", species.species, species.form))
f.write(sprintf("FormName = %s\r\n", species.real_form_name)) if species.real_form_name && !species.real_form_name.empty?
f.write(sprintf("PokedexForm = %d\r\n", species.pokedex_form)) if species.pokedex_form != species.form
f.write(sprintf("MegaStone = %s\r\n", species.mega_stone)) if species.mega_stone
f.write(sprintf("MegaMove = %s\r\n", species.mega_move)) if species.mega_move
f.write(sprintf("UnmegaForm = %d\r\n", species.unmega_form)) if species.unmega_form != 0
f.write(sprintf("MegaMessage = %d\r\n", species.mega_message)) if species.mega_message != 0
if species.type1 != base_species.type1 || species.type2 != base_species.type2
f.write(sprintf("Type1 = %s\r\n", species.type1))
f.write(sprintf("Type2 = %s\r\n", species.type2)) if species.type2 != species.type1
end
f.write(sprintf("BaseStats = %s\r\n", species.base_stats.join(","))) if species.base_stats != base_species.base_stats
f.write(sprintf("BaseEXP = %d\r\n", species.base_exp)) if species.base_exp != base_species.base_exp
f.write(sprintf("EffortPoints = %s\r\n", species.evs.join(","))) if species.evs != base_species.evs
f.write(sprintf("Rareness = %d\r\n", species.catch_rate)) if species.catch_rate != base_species.catch_rate
f.write(sprintf("Happiness = %d\r\n", species.happiness)) if species.happiness != base_species.happiness
if species.abilities.length > 0 && species.abilities != base_species.abilities
f.write(sprintf("Abilities = %s\r\n", species.abilities.join(",")))
end
if species.hidden_abilities.length > 0 && species.hidden_abilities != base_species.hidden_abilities
f.write(sprintf("HiddenAbility = %s\r\n", species.hidden_abilities.join(",")))
end
if species.moves.length > 0 && species.moves != base_species.moves
f.write(sprintf("Moves = %s\r\n", species.moves.join(",")))
end
if species.tutor_moves.length > 0 && species.tutor_moves != base_species.tutor_moves
f.write(sprintf("TutorMoves = %s\r\n", species.tutor_moves.join(",")))
end
if species.egg_moves.length > 0 && species.egg_moves != base_species.egg_moves
f.write(sprintf("EggMoves = %s\r\n", species.egg_moves.join(",")))
end
if species.egg_groups.length > 0 && species.egg_groups != base_species.egg_groups
f.write("Compatibility = ")
species.egg_groups.each_with_index do |group, i|
f.write(",") if i > 0
f.write(getConstantName(PBEggGroups, group))
end
f.write("\r\n")
end
f.write(sprintf("StepsToHatch = %d\r\n", species.hatch_steps)) if species.hatch_steps != base_species.hatch_steps
f.write(sprintf("Height = %.1f\r\n", species.height / 10.0)) if species.height != base_species.height
f.write(sprintf("Weight = %.1f\r\n", species.weight / 10.0)) if species.weight != base_species.weight
f.write(sprintf("Color = %s\r\n", getConstantName(PBColors, species.color))) if species.color != base_species.color
f.write(sprintf("Shape = %d\r\n", species.shape)) if species.shape != base_species.shape
if species.habitat != PBHabitats::None && species.habitat != base_species.habitat
f.write(sprintf("Habitat = %s\r\n", getConstantName(PBHabitats, species.habitat)))
end
f.write(sprintf("Kind = %s\r\n", species.real_category)) if species.real_category != base_species.real_category
f.write(sprintf("Pokedex = %s\r\n", species.real_pokedex_entry)) if species.real_pokedex_entry != base_species.real_pokedex_entry
f.write(sprintf("Generation = %d\r\n", species.generation)) if species.generation != base_species.generation
if species.wild_item_common != base_species.wild_item_common ||
species.wild_item_uncommon != base_species.wild_item_uncommon ||
species.wild_item_rare != base_species.wild_item_rare
f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common)) if species.wild_item_common
f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon)) if species.wild_item_uncommon
f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare)) if species.wild_item_rare
end
f.write(sprintf("BattlerPlayerX = %d\r\n", species.back_sprite_x)) if species.back_sprite_x != base_species.back_sprite_x
f.write(sprintf("BattlerPlayerY = %d\r\n", species.back_sprite_y)) if species.back_sprite_y != base_species.back_sprite_y
f.write(sprintf("BattlerEnemyX = %d\r\n", species.front_sprite_x)) if species.front_sprite_x != base_species.front_sprite_x
f.write(sprintf("BattlerEnemyY = %d\r\n", species.front_sprite_y)) if species.front_sprite_y != base_species.front_sprite_y
f.write(sprintf("BattlerAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != base_species.front_sprite_altitude
f.write(sprintf("BattlerShadowX = %d\r\n", species.shadow_x)) if species.shadow_x != base_species.shadow_x
f.write(sprintf("BattlerShadowSize = %d\r\n", species.shadow_size)) if species.shadow_size != base_species.shadow_size
if species.evolutions != base_species.evolutions && species.evolutions.any? { |evo| !evo[3] }
f.write("Evolutions = ")
need_comma = false
species.evolutions.each do |evo|
next if evo[3] # Skip prevolution entries
f.write(",") if need_comma
need_comma = true
f.write(sprintf("%s,%s,", evo[0], getConstantName(PBEvolution, evo[1])))
param_type = PBEvolution.getFunction(evo[1], "parameterType")
has_param = !PBEvolution.hasFunction?(evo[1], "parameterType") || param_type != nil
next if !has_param
if param_type
if GameData.const_defined?(param_type.to_sym)
f.write(evo[2].to_s)
else
f.write(getConstantName(param_type, evo[2]))
end
else
f.write(evo[2].to_s)
end
end
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save Shadow movesets to PBS file
#===============================================================================
def write_shadow_movesets
shadow_movesets = pbLoadShadowMovesets
File.open("PBS/shadowmoves.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::Species.each do |species_data|
moveset = shadow_movesets[species_data.id]
next if !moveset || moveset.length == 0
f.write(sprintf("%s = %s\r\n", species_data.id, moveset.join(",")))
end
}
Graphics.update
end
#===============================================================================
# Save Regional Dexes to PBS file
#===============================================================================
def write_regional_dexes
dex_lists = pbLoadRegionalDexes
File.open("PBS/regionaldexes.txt", "wb") { |f|
add_PBS_header_to_file(f)
# Write each Dex list in turn
dex_lists.each_with_index do |list, index|
f.write("\#-------------------------------\r\n")
f.write("[#{index}]")
comma = false
current_family = nil
list.each do |species|
next if !species
if current_family && current_family.include?(species)
f.write(",") if comma
else
current_family = EvolutionHelper.all_related_species(species)
comma = false
f.write("\r\n")
end
f.write(species)
comma = true
end
f.write("\r\n")
end
}
Graphics.update
end
#===============================================================================
# Save wild encounter data to PBS file
#===============================================================================
def write_encounters
encdata = pbLoadEncountersData
return if !encdata
mapinfos = pbLoadRxData("Data/MapInfos")
File.open("PBS/encounters.txt","wb") { |f|
add_PBS_header_to_file(f)
sortedkeys = encdata.keys.sort
for i in sortedkeys
next if !encdata[i]
e = encdata[i]
mapname = ""
if mapinfos[i]
map = mapinfos[i].name
mapname = " # #{map}"
end
f.write("\#-------------------------------\r\n")
f.write(sprintf("%03d%s\r\n",i,mapname))
f.write(sprintf("%d,%d,%d\r\n",e[0][EncounterTypes::Land],
e[0][EncounterTypes::Cave],e[0][EncounterTypes::Water]))
for j in 0...e[1].length
enc = e[1][j]
next if !enc
f.write(sprintf("%s\r\n",EncounterTypes::Names[j]))
for k in 0...EncounterTypes::EnctypeChances[j].length
next if !enc[k]
encentry = enc[k]
if encentry[1]==encentry[2]
f.write(sprintf(" %s,%d\r\n",encentry[0],encentry[1]))
else
f.write(sprintf(" %s,%d,%d\r\n",encentry[0],encentry[1],encentry[2]))
end
end
end
end
}
Graphics.update
end
#===============================================================================
# Save trainer type data to PBS file
#===============================================================================
def write_trainer_types
File.open("PBS/trainertypes.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::TrainerType.each do |t|
f.write(sprintf("%d,%s,%s,%d,%s,%s,%s,%s,%s,%s\r\n",
t.id_number,
csvQuote(t.id.to_s),
csvQuote(t.real_name),
t.base_money,
csvQuote(t.battle_BGM),
csvQuote(t.victory_ME),
csvQuote(t.intro_ME),
["Male", "Female", "Mixed"][t.gender],
(t.skill_level == t.base_money) ? "" : t.skill_level.to_s,
csvQuote(t.skill_code)
))
end
}
Graphics.update
end
#===============================================================================
# Save individual trainer data to PBS file
#===============================================================================
def write_trainers
data = pbLoadTrainersData
return if !data
File.open("PBS/trainers.txt","wb") { |f|
add_PBS_header_to_file(f)
for trainer in data
trtypename = trainer[0].to_s
next if !trtypename
f.write("\#-------------------------------\r\n")
# Section
trainername = trainer[1] ? trainer[1].gsub(/,/,";") : "???"
if trainer[4]==0
f.write(sprintf("[%s,%s]\r\n",trtypename,trainername))
else
f.write(sprintf("[%s,%s,%d]\r\n",trtypename,trainername,trainer[4]))
end
# Trainer's items
if trainer[2] && trainer[2].length>0
itemstring = ""
for i in 0...trainer[2].length
itemstring.concat(",") if i > 0
itemstring.concat(trainer[2][i].to_s)
end
f.write(sprintf("Items = %s\r\n",itemstring)) if itemstring!=""
end
# Lose texts
if trainer[5] && trainer[5]!=""
f.write(sprintf("LoseText = %s\r\n",csvQuoteAlways(trainer[5])))
end
# Pokémon
for poke in trainer[3]
f.write(sprintf("Pokemon = %s,%d\r\n",poke[TrainerData::SPECIES],poke[TrainerData::LEVEL]))
if poke[TrainerData::NAME] && poke[TrainerData::NAME]!=""
f.write(sprintf(" Name = %s\r\n",poke[TrainerData::NAME]))
end
if poke[TrainerData::FORM]
f.write(sprintf(" Form = %d\r\n",poke[TrainerData::FORM]))
end
if poke[TrainerData::GENDER]
f.write(sprintf(" Gender = %s\r\n",(poke[TrainerData::GENDER]==1) ? "female" : "male"))
end
if poke[TrainerData::SHINY]
f.write(" Shiny = yes\r\n")
end
if poke[TrainerData::SHADOW]
f.write(" Shadow = yes\r\n")
end
if poke[TrainerData::MOVES] && poke[TrainerData::MOVES].length>0
movestring = ""
for i in 0...poke[TrainerData::MOVES].length
movename = GameData::Move.get(poke[TrainerData::MOVES][i]).id.to_s
next if !movename
movestring.concat(",") if i>0
movestring.concat(movename)
end
f.write(sprintf(" Moves = %s\r\n",movestring)) if movestring!=""
end
if poke[TrainerData::ABILITY]
f.write(sprintf(" Ability = %s\r\n",poke[TrainerData::ABILITY].to_s))
end
if poke[TrainerData::ITEM]
f.write(sprintf(" Item = %s\r\n",poke[TrainerData::ITEM].to_s))
end
if poke[TrainerData::NATURE]
nature = getConstantName(PBNatures,poke[TrainerData::NATURE]) rescue nil
f.write(sprintf(" Nature = %s\r\n",nature)) if nature
end
if poke[TrainerData::IV] && poke[TrainerData::IV].length>0
f.write(sprintf(" IV = %d",poke[TrainerData::IV][0]))
if poke[TrainerData::IV].length>1
for i in 1...6
f.write(sprintf(",%d",(i<poke[TrainerData::IV].length) ? poke[TrainerData::IV][i] : poke[TrainerData::IV][0]))
end
end
f.write("\r\n")
end
if poke[TrainerData::EV] && poke[TrainerData::EV].length>0
f.write(sprintf(" EV = %d",poke[TrainerData::EV][0]))
if poke[TrainerData::EV].length>1
for i in 1...6
f.write(sprintf(",%d",(i<poke[TrainerData::EV].length) ? poke[TrainerData::EV][i] : poke[TrainerData::EV][0]))
end
end
f.write("\r\n")
end
if poke[TrainerData::HAPPINESS]
f.write(sprintf(" Happiness = %d\r\n",poke[TrainerData::HAPPINESS]))
end
if poke[TrainerData::BALL]
f.write(sprintf(" Ball = %d\r\n",poke[TrainerData::BALL]))
end
end
end
}
Graphics.update
end
#===============================================================================
# Save trainer list data to PBS file
#===============================================================================
def write_trainer_lists
trainerlists = load_data("Data/trainer_lists.dat") rescue nil
return if !trainerlists
File.open("PBS/trainerlists.txt","wb") { |f|
add_PBS_header_to_file(f)
for tr in trainerlists
f.write("\#-------------------------------\r\n")
f.write(((tr[5]) ? "[DefaultTrainerList]" : "[TrainerList]")+"\r\n")
f.write("Trainers = "+tr[3]+"\r\n")
f.write("Pokemon = "+tr[4]+"\r\n")
f.write("Challenges = "+tr[2].join(",")+"\r\n") if !tr[5]
write_battle_tower_trainers(tr[0],"PBS/"+tr[3])
write_battle_tower_pokemon(tr[1],"PBS/"+tr[4])
end
}
Graphics.update
end
#===============================================================================
# Save Battle Tower trainer data to PBS file
#===============================================================================
def write_battle_tower_trainers(bttrainers, filename)
return if !bttrainers || !filename
btTrainersRequiredTypes = {
"Type" => [0, "e", nil], # Specifies a trainer
"Name" => [1, "s"],
"BeginSpeech" => [2, "s"],
"EndSpeechWin" => [3, "s"],
"EndSpeechLose" => [4, "s"],
"PokemonNos" => [5, "*u"]
}
File.open(filename,"wb") { |f|
add_PBS_header_to_file(f)
for i in 0...bttrainers.length
next if !bttrainers[i]
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%03d]\r\n",i))
for key in btTrainersRequiredTypes.keys
schema = btTrainersRequiredTypes[key]
record = bttrainers[i][schema[0]]
next if record==nil
f.write(sprintf("%s = ",key))
if key=="Type"
f.write(record.to_s)
elsif key=="PokemonNos"
f.write(record.join(",")) # pbWriteCsvRecord somehow won't work here
else
pbWriteCsvRecord(record,f,schema)
end
f.write(sprintf("\r\n"))
end
end
}
Graphics.update
end
#===============================================================================
# Save Battle Tower Pokémon data to PBS file
#===============================================================================
def write_battle_tower_pokemon(btpokemon,filename)
return if !btpokemon || !filename
species = {0=>""}
moves = {0=>""}
items = {0=>""}
natures = {}
File.open(filename,"wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
for i in 0...btpokemon.length
Graphics.update if i%500==0
pkmn = btpokemon[i]
f.write(pbFastInspect(pkmn,moves,species,items,natures))
f.write("\r\n")
end
}
Graphics.update
end
def pbFastInspect(pkmn,moves,species,items,natures)
c1 = (species[pkmn.species]) ? species[pkmn.species] : (species[pkmn.species] = GameData::Species.get(pkmn.species).species.to_s)
c2 = (items[pkmn.item]) ? items[pkmn.item] : (items[pkmn.item] = GameData::Item.get(pkmn.item).id.to_s)
c3 = (natures[pkmn.nature]) ? natures[pkmn.nature] :
(natures[pkmn.nature] = getConstantName(PBNatures,pkmn.nature))
evlist = ""
ev = pkmn.ev
evs = ["HP","ATK","DEF","SPD","SA","SD"]
for i in 0...ev
if ((ev&(1<<i))!=0)
evlist += "," if evlist.length>0
evlist += evs[i]
end
end
c4 = (moves[pkmn.move1]) ? moves[pkmn.move1] : (moves[pkmn.move1] = GameData::Move.get(pkmn.move1).id.to_s)
c5 = (moves[pkmn.move2]) ? moves[pkmn.move2] : (moves[pkmn.move2] = GameData::Move.get(pkmn.move2).id.to_s)
c6 = (moves[pkmn.move3]) ? moves[pkmn.move3] : (moves[pkmn.move3] = GameData::Move.get(pkmn.move3).id.to_s)
c7 = (moves[pkmn.move4]) ? moves[pkmn.move4] : (moves[pkmn.move4] = GameData::Move.get(pkmn.move4).id.to_s)
return "#{c1};#{c2};#{c3};#{evlist};#{c4},#{c5},#{c6},#{c7}"
end
#===============================================================================
# Save metadata data to PBS file
#===============================================================================
def write_metadata
File.open("PBS/metadata.txt", "wb") { |f|
add_PBS_header_to_file(f)
# Write global metadata
f.write("\#-------------------------------\r\n")
f.write("[000]\r\n")
metadata = GameData::Metadata.get
schema = GameData::Metadata::SCHEMA
keys = schema.keys.sort {|a, b| schema[a][0] <=> schema[b][0] }
for key in keys
record = metadata.property_from_string(key)
next if record.nil?
f.write(sprintf("%s = ", key))
pbWriteCsvRecord(record, f, schema[key])
f.write("\r\n")
end
# Write map metadata
map_infos = pbLoadRxData("Data/MapInfos")
schema = GameData::MapMetadata::SCHEMA
keys = schema.keys.sort {|a, b| schema[a][0] <=> schema[b][0] }
GameData::MapMetadata.each do |map_data|
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%03d]\r\n", map_data.id))
if map_infos && map_infos[map_data.id]
f.write(sprintf("# %s\r\n", map_infos[map_data.id].name))
end
for key in keys
record = map_data.property_from_string(key)
next if record.nil?
f.write(sprintf("%s = ", key))
pbWriteCsvRecord(record, f, schema[key])
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save all data to PBS files
#===============================================================================
def write_all
write_town_map
write_connections
write_phone
write_types
write_abilities
write_moves
write_items
write_berry_plants
write_pokemon
write_pokemon_forms
write_shadow_movesets
write_regional_dexes
write_encounters
write_trainer_types
write_trainers
write_trainer_lists
write_metadata
end
end