#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= # Advanced Analyze System by Blizzard # Version: 2.4 # Type: Enemy Scan Window and Skill # Date: 5.7.2006 # Date v1.1b: 31.8.2006 # Date v1.2b: 23.2.2007 # Date v1.3b: 7.7.2007 # Date v2.0b: 12.7.2007 # Date v2.1b: 6.8.2007 # Date v2.2b: 24.9.2007 # Date v2.21b: 8.4.2008 # Date v2.3b: 28.7.2009 # Date v2.4: 23.3.2019 #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= # # This work is licensed under BSD License 2.0: # # #---------------------------------------------------------------------------- # # # # Copyright (c) Boris "Blizzard" Mikić # # All rights reserved. # # # # Redistribution and use in source and binary forms, with or without # # modification, are permitted provided that the following conditions are met: # # # # 1. Redistributions of source code must retain the above copyright notice, # # this list of conditions and the following disclaimer. # # # # 2. Redistributions in binary form must reproduce the above copyright # # notice, this list of conditions and the following disclaimer in the # # documentation and/or other materials provided with the distribution. # # # # 3. Neither the name of the copyright holder nor the names of its # # contributors may be used to endorse or promote products derived from # # this software without specific prior written permission. # # # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # # POSSIBILITY OF SUCH DAMAGE. # # # #---------------------------------------------------------------------------- # # You may use this script for both non-commercial and commercial products # without limitations as long as you fulfill the conditions presented by the # above license. The "complete" way to give credit is to include the license # somewhere in your product (e.g. in the credits screen), but a "simple" way # is also acceptable. The "simple" way to give credit is as follows: # # Advanced Analyze System licensed under BSD License 2.0 # Copyright (c) Boris "Blizzard" Mikić # # Alternatively, if your font doesn't support diacritic characters, you may # use this variant: # # Advanced Analyze System licensed under BSD License 2.0 # Copyright (c) Boris "Blizzard" Mikic # # In general other similar variants are allowed as long as it is clear who # the creator is (e.g. "Advanced Analyze System created by Blizzard" is # acceptable). But if possible, prefer to use one of the two variants listed # above. # # If you fail to give credit and/or claim that this work was created by you, # this may result in legal action and/or payment of damages even though this # work is free of charge to use normally. # #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= # # Compatibility: # # 96% compatible with SDK v1.x. 70% compatible with SDK v2.x. May cause # incompatibility issues with exotic CBS-es. WILL corrupt your old savegames. # # # Features: # # - make one or more skills to be able to analyze enemies # - display of full data of enemies # - option to disable different information # - integrated support for my "Bestiary" script and option to override it and # only add analyzed enemies # - press SHIFT/ENTER to change the appearance of the analyze window # - use LEFT/RIGHT/UP/DOWN to navigate through the information database # # new in v1.1b: # - shorter, better and more simple code # - fixed the bug where trying to use a skill in the menu caused loss of SP, # no matter if the skill was used or could not be used # - updates now the spriteset while the Analyze window is visible # # new in v1.2b: # - improved coding (uses less RAM now and processes faster) # # new in v1.3b: # - increased compatibility # # new in v2.0b: # - completely overworked and fixed compatibility issues # # new in v2.1b: # - added custom info possibility # # new in v2.2b: # - rewritten conditions using classic syntax to avoid RGSS conditioning bug # - improved coding # # new in v2.21b: # - improved coding # # new in v2.3b: # - improved coding # # new in v2.4: # - added new license # - added usage and crediting instructions # # # Instructions: # # - Explanation: # # This script will allow your characters to retrieve information about # enemies during battle and show them in a window. It also has built-in # compatibility for my "Bestiary" script and allows adding enemies to it only # if enemies were analyzed at least once. This script can easily be used for # Pokémon typed games. # # - Configuration: # # Configure the part below and make one or more skills, that can analyze # enemies. Add the IDs into the array called ANALYZE_IDS and separate them # with commas. If you have one or more scripts using dummy elements (e.g. my # EQUAP Skills, SephirothSpawn's Limit Break, etc.) be sure to include every # dummy element ID in the array called ELM_DUMMIES, also separated by commas. # With advanced configuration it is possible to disable different information # display, even during the game. Also it can be set up, that an enemy is # being rendered unanalyzeable or only partially unanalyzeable (e.g. disable # display of extreme element weaknesses for an enemy, etc.). Put this script # UNDER my "Bestiary" script if you use it. # # - For scripters: # # The variable $game_system.analyzed includes an array of enemy IDs from # enemies, that were analyzed at least once during a fight. You can use this # array to make your own bestiary script working together with this script # and let only analyzed enemies be added into the bestiary. You can refer to # the global variable $advanced_analyze to check if this script is there. # # # Important notes: # # You MUST configure the part below if you have scripts that use dummy # elements! Do NOT give your enemies MORE than 12 elements/status effects of # one resistance type (e.g. 13 or more elements, that are absorbed), because # they won't be displayed. If you target anyone else than enemies, the skill # will analyze all enemies anyway. # # # If you find any bugs, please report them here: # http://forum.chaos-project.com #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START Configuration #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # basic configuration ANALYZE_IDS = [81, 82, 83] # IDs of analyzing skills ELM_DUMMIES = [] # include EVERY dummy element ID that is used by other scripts STA_DUMMIES = [] # include EVERY dummy status effect ID that you use EVASION = 'EVA' # word displayed for Evasion # set the value below to true to only ADD information of analyzed enemies into # the bestiary if you use my Bestiary script $override_bestiary = false # set this value to true if you want the custom Analyze window information to # be used in the bestiary as well, this way you use only one information for # both systems $override_bestiary_info = false # enemy IDs from enemies, that can't be analyzed (e.g. bosses) CANT_ANALYZE = [4] # overrides the IDs below and renders an enemy unanalyzeable CANT_ANALYZE_BASIC = [3] # HP, SP, EXP, Gold, Item drop + chance CANT_ANALYZE_STATS = [1] # STR, DEX, INT, AGI CANT_ANALYZE_EXTSTATS = [1, 3] # ATK, PDEF, MDEF CANT_ANALYZE_XTRWEAK = [1] # extreme element weakness CANT_ANALYZE_WEAK = [2] # element weakness CANT_ANALYZE_RESIST = [2, 3] # element resistance CANT_ANALYZE_NULLIFY = [2] # element nullification CANT_ANALYZE_ABSORB = [3] # element absorbtion CANT_ANALYZE_XTRWEAK_S = [1] # extreme status effect weakness CANT_ANALYZE_WEAK_S = [2] # status effect weakness CANT_ANALYZE_RESIST_S = [2, 3] # status effect resistance CANT_ANALYZE_NULLIFY_S = [2] # status effect nullification CANT_ANALYZE_ABSORB_S = [3] # status effect absorbtion CANT_ANALYZE_CUSTOM = [] # custom info # If a display below is disabled, the appropriate part above will be overriden. # The values below can also be changed during gameplay by just calling the # "Call script" event command and changing the values like below # DO NOT SET EVERYTHING TO true! THIS WILL BUG YOUR ANALYZE SKILL! # set to true to disable display of basic info DISABLE_BASIC = false # set to true to disable display of basic stats DISABLE_STATS = false # set to true to disable display of extended stats DISABLE_EXTSTATS = false # set to true to disable display of extreme elemental weakness DISABLE_XTRWEAK = false # set to true to disable display of elemental weakness DISABLE_WEAK = false # set to true to disable display of elemental resistance DISABLE_RESIST = false # set to true to disable display of elemental nullification DISABLE_NULLIFY = false # set to true to disable display of elemental absorbtion DISABLE_ABSORB = false # set to true to disable display of extremeal status effect weakness DISABLE_XTRWEAK_S = false # set to true to disable display of status effect weakness DISABLE_WEAK_S = false # set to true to disable display of status effect resistance DISABLE_RESIST_S = false # set to true to disable display of status effect nullification DISABLE_NULLIFY_S = false # set to true to disable display of status effect absorbtion DISABLE_ABSORB_S = false # set to false to enable custom display DISABLE_CUSTOM_ANALYZE = false #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END Configuration #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if $DUMMY_ELEMENTS == nil $DUMMY_ELEMENTS = ELM_DUMMIES.clone else $DUMMY_ELEMENTS |= ELM_DUMMIES end ELM_DUMMIES = nil if $DUMMY_STATES == nil $DUMMY_STATES = STA_DUMMIES.clone else $DUMMY_STATES |= STA_DUMMIES end STA_DUMMIES = nil $advanced_analyze = 2.4 #============================================================================== # Game_System #============================================================================== class Game_System attr_accessor :analyze_mode attr_accessor :analyzed def get_analyze_info(id) case id #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START Custom Analyze Info Database # # Use following template to add custom information about monsters: # # when ID then return "STRING" # # ID is the enemy ID and STRING is a string with the information that should be # displayed. Type all the information into one string, the script will slice # the text by itself. Note that special characters like a " (double quote) # need the use of the escape character \ (backslash). If you get and error # with your string or the character doesn't appear right on the screen, try to # use the escape character (i.e. for a " it would be \" instead of just "). # The backslash itself needs an escape character (i.e. \\). #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: when 1 then return "And I thought there were no such things as ghosts..." when 2 then return "These creatures are said to be able to have the ability to turn anything they glaze at into stone. If this rumor is true, these creatures can be considered as part of the family of \"Gorgons\"." #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END Custom Analyze Info Database #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: end return 'Unknown' end alias init_aas_later initialize def initialize init_aas_later @analyze_mode = 0 # bestiary support @analyzed = [] end end #============================================================================== # Game_Battler #============================================================================== class Game_Battler alias skill_effect_aas_later skill_effect def skill_effect(user, skill) last_sr = self.sr if $crls && self.is_a?(Game_Actor) last_hp = self.hp result = skill_effect_aas_later(user, skill) if ANALYZE_IDS.include?(skill.id) self.damage = nil self.sr = last_sr if $crls && self.is_a?(Game_Actor) self.hp = last_hp end return result end end #============================================================================== # Bitmap #============================================================================== class Bitmap def slice_text(text, width) words = text.split(' ') return words if words.size == 1 result, current_text = [], words.shift words.each_index {|i| if self.text_size("#{current_text} #{words[i]}").width > width result.push(current_text) current_text = words[i] else current_text = "#{current_text} #{words[i]}" end result.push(current_text) if i >= words.size - 1} return result end end #============================================================================== # Window_Analyze #============================================================================== class Window_Analyze < Window_Base attr_accessor :mode def initialize super(0, 0, 576, 224) @index_enemy = @index_page = 0 @d = [DISABLE_BASIC, DISABLE_STATS, DISABLE_EXTSTATS, DISABLE_XTRWEAK, DISABLE_WEAK, DISABLE_RESIST, DISABLE_NULLIFY, DISABLE_ABSORB, DISABLE_XTRWEAK_S, DISABLE_WEAK_S, DISABLE_RESIST_S, DISABLE_NULLIFY_S, DISABLE_ABSORB_S, DISABLE_CUSTOM_ANALYZE] @pages = 14 - ((0..13).find_all {|i| @d[i]}).size @mode = $game_system.analyze_mode self.contents = Bitmap.new(width - 32, height - 32) if $fontface != nil self.contents.font.name = $fontface self.contents.font.size = $fontsize elsif $defaultfonttype != nil self.contents.font.name = $defaultfonttype self.contents.font.size = $defaultfontsize end self.x, self.y = 320 - self.width / 2, 160 - self.height / 2 self.visible = self.active = false refresh end def update if Input.trigger?(Input::RIGHT) $game_system.se_play($data_system.cursor_se) @index_enemy = (@index_enemy + 1) % @enemies.size refresh elsif Input.trigger?(Input::LEFT) $game_system.se_play($data_system.cursor_se) @index_enemy = (@index_enemy + @enemies.size - 1) % @enemies.size refresh elsif Input.trigger?(Input::DOWN) $game_system.se_play($data_system.cursor_se) @index_page = (@index_page + 1) % @pages refresh elsif Input.trigger?(Input::UP) $game_system.se_play($data_system.cursor_se) @index_page = (@index_page + @pages - 1) % @pages refresh end end def refresh case @mode when 0 then self.opacity = self.back_opacity = 255 when 1 then self.back_opacity = 128 when 2 then self.opacity = 0 end self.contents.clear x = 4 ox = x + 128 ax = 100 bx = ax + 144 @enemies = [] $game_troop.enemies.each {|enemy| @enemies.push(enemy) if enemy.exist?} @enemies.each {|enemy| unless $game_system.analyzed.include?(enemy.id) $game_system.analyzed.push(enemy.id) $game_system.enable(enemy.id) if $bestiary_enabled end} $game_system.analyzed.sort! enemy = @enemies[@index_enemy] w = self.width - self.contents.text_size(enemy.name).width name = "#{enemy.name} #{make_battler_state_text(enemy, w, false)}" name = "#{@index_enemy+1}. #{name}" if @enemies.size > 1 self.contents.draw_text(0, 0, 544, 32, name, 1) unless CANT_ANALYZE.include?(enemy.id) case @index_page when (0 - ((0..0).find_all {|i| @d[i]}).size) if enemy.item_id > 0 drop = $data_items[enemy.item_id] t = "#{drop.name} (#{enemy.treasure_prob}% chance)" elsif enemy.weapon_id > 0 drop = $data_weapons[enemy.weapon_id] t = "#{drop.name} (#{enemy.treasure_prob}% chance)" elsif enemy.armor_id > 0 drop = $data_armors[enemy.armor_id] t = "#{drop.name} (#{enemy.treasure_prob}% chance)" end self.contents.draw_text(ax, 32, 128, 32, $data_system.words.hp, 2) self.contents.draw_text(ax, 64, 128, 32, $data_system.words.sp, 2) self.contents.draw_text(ax, 96, 128, 32, 'EXP', 2) self.contents.draw_text(ax, 128, 128, 32, $data_system.words.gold, 2) self.contents.draw_text(ax, 160, 128, 32, 'Drops', 2) unless CANT_ANALYZE_BASIC.include?(enemy.id) self.contents.draw_text(bx, 32, 256, 32, "#{enemy.hp} / #{enemy.maxhp}") self.contents.draw_text(bx, 64, 256, 32, "#{enemy.sp} / #{enemy.maxsp}") self.contents.draw_text(bx, 96, 256, 32, enemy.exp.to_s) self.contents.draw_text(bx, 128, 256, 32, enemy.gold.to_s) self.contents.draw_text(bx, 160, 256, 32, (drop != nil ? t : 'nothing')) else (0...5).each {|i| self.contents.draw_text(bx, 32 + i*32, 544, 32, 'Cannot analyze this')} end when (1 - ((0..1).find_all {|i| @d[i]}).size) self.contents.draw_text(ax, 32, 128, 32, $data_system.words.str, 2) self.contents.draw_text(ax, 64, 128, 32, $data_system.words.dex, 2) self.contents.draw_text(ax, 96, 128, 32, $data_system.words.agi, 2) self.contents.draw_text(ax, 128, 128, 32, $data_system.words.int, 2) unless CANT_ANALYZE_STATS.include?(enemy.id) self.contents.draw_text(bx, 32, 256, 32, enemy.str.to_s) self.contents.draw_text(bx, 64, 256, 32, enemy.dex.to_s) self.contents.draw_text(bx, 96, 256, 32, enemy.agi.to_s) self.contents.draw_text(bx, 128, 256, 32, enemy.int.to_s) else (0...4).each {|i| self.contents.draw_text(bx, 32 + i*32, 544, 32, 'Cannot analyze this')} end when (2 - ((0..2).find_all {|i| @d[i]}).size) self.contents.draw_text(ax, 32, 128, 32, $data_system.words.atk, 2) self.contents.draw_text(ax, 64, 128, 32, $data_system.words.pdef, 2) self.contents.draw_text(ax, 96, 128, 32, $data_system.words.mdef, 2) self.contents.draw_text(ax, 128, 128, 32, EVASION, 2) unless CANT_ANALYZE_EXTSTATS.include?(enemy.id) self.contents.draw_text(bx, 32, 256, 32, enemy.atk.to_s) self.contents.draw_text(bx, 64, 256, 32, enemy.pdef.to_s) self.contents.draw_text(bx, 96, 256, 32, enemy.mdef.to_s) self.contents.draw_text(bx, 128, 256, 32, enemy.eva.to_s) else (0...4).each {|i| self.contents.draw_text(bx, 32 + i*32, 544, 32, 'Cannot analyze this')} end when (3 - ((0..3).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Extremely efficient elements:') draw_elements(enemy, x, 1, CANT_ANALYZE_XTRWEAK.include?(enemy.id)) when (4 - ((0..4).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Efficient elements:') draw_elements(enemy, x, 2, CANT_ANALYZE_WEAK.include?(enemy.id)) when (5 - ((0..5).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Elemental resistances:') draw_elements(enemy, x, 4, CANT_ANALYZE_RESIST.include?(enemy.id)) when (6 - ((0..6).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Elemental nullifications:') draw_elements(enemy, x, 5, CANT_ANALYZE_NULLIFY.include?(enemy.id)) when (7 - ((0..7).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Elemental absorbtions:') draw_elements(enemy, x, 6, CANT_ANALYZE_ABSORB.include?(enemy.id)) when (8 - ((0..8).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Extremely efficient status effects:') draw_states(enemy, x, 1, CANT_ANALYZE_XTRWEAK_S.include?(enemy.id)) when (9 - ((0..9).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Efficient status effects:') draw_states(enemy, x, 2, CANT_ANALYZE_WEAK_S.include?(enemy.id)) when (10 - ((0..10).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Status effect resistances:') draw_states(enemy, x, 4, CANT_ANALYZE_RESIST_S.include?(enemy.id)) when (11 - ((0..11).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Strong status effect resistances:') draw_states(enemy, x, 5, CANT_ANALYZE_NULLIFY_S.include?(enemy.id)) when (12 - ((0..12).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Status effect immunities:') draw_states(enemy, x, 6, CANT_ANALYZE_ABSORB_S.include?(enemy.id)) when (13 - ((0..13).find_all {|i| @d[i]}).size) self.contents.draw_text(x, 32, 544, 32, 'Information:') draw_info(enemy, x, CANT_ANALYZE_CUSTOM.include?(enemy.id)) end else self.contents.draw_text(0, 64, 544, 32, 'Cannot analyze this enemy', 1) end end def draw_elements(enemy, x, index, check) unless check elements = [] (1...$data_system.elements.size).each {|id| if !$DUMMY_ELEMENTS.include?(id) && index == $data_enemies[@enemies[@index_enemy].id].element_ranks[id] elements.push($data_system.elements[id]) end} elements = ['Nothing'] if elements.size == 0 elements.each_index {|i| self.contents.draw_text(x + i/4*180, 64 + i%4*32, 176, 32, elements[i])} else self.contents.draw_text(x, 64, 544, 32, 'Cannot analyze this') end end def draw_states(enemy, x, index, check) unless check states = [] (1...$data_states.size).each {|id| if !$DUMMY_STATES.include?(id) && index == $data_enemies[@enemies[@index_enemy].id].state_ranks[id] states.push($data_states[id].name) end} states = ['Nothing'] if states.size == 0 states.each_index {|i| self.contents.draw_text(x + i/4*180, 64 + i%4*32, 176, 32, states[i])} else self.contents.draw_text(x, 64, 544, 32, 'Cannot analyze this') end end def draw_info(enemy, x, check) unless check text = self.contents.slice_text($game_system.get_analyze_info(enemy.id), 528) text.each_index {|i| self.contents.draw_text(x, 64 + i*32, 544, 32, text[i])} else self.contents.draw_text(x, 64, 544, 32, 'Cannot analyze this') end end end #============================================================================== # Scene_Battle #============================================================================== class Scene_Battle alias make_skill_action_result_aas_later make_skill_action_result def make_skill_action_result make_skill_action_result_aas_later @analyze_window = Window_Analyze.new if ANALYZE_IDS.include?(@skill.id) end alias update_phase4_step5_aas_later update_phase4_step5 def update_phase4_step5 update_phase4_step5_aas_later if @analyze_window != nil Graphics.freeze @analyze_window.visible = true Graphics.transition(10) loop do Graphics.update Input.update @analyze_window.update @spriteset.update $game_screen.update if Input.trigger?(Input::A) || Input.trigger?(Input::C) $game_system.se_play($data_system.cursor_se) Graphics.freeze case @analyze_window.mode when 0 then @analyze_window.back_opacity = 128 when 1 then @analyze_window.opacity = 0 when 2 then @analyze_window.opacity = @analyze_window.back_opacity = 255 end $game_system.analyze_mode = ($game_system.analyze_mode+1) % 3 @analyze_window.mode = $game_system.analyze_mode Graphics.transition(5) end break if Input.trigger?(Input::B) end Graphics.freeze $game_system.se_play($data_system.cancel_se) @analyze_window.dispose @analyze_window = nil Graphics.transition(10) end end end