Jragyn

[XP] BlizzABS -p2

Apr 11th, 2017
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 375.41 KB | None | 0 0
  1. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  2. # Blizz-ABS by Blizzard and winkio
  3. # Version: 2.87
  4. # Type: Advanced Action Battle System
  5. # Date v1.00: 19.04.2007
  6. # Date v1.01: 30.04.2007
  7. # Date v1.02: 17.07.2007
  8. # Date v1.04: 25.07.2007
  9. # Date v1.09: 25.07.2007
  10. # Date v1.20: 29.07.2007
  11. # Date v1.23: 30.07.2007
  12. # Date v1.24:  5.08.2007
  13. # Date v1.60:  5.09.2007
  14. # Date v1.61:  6.09.2007
  15. # Date v1.62:  7.09.2007
  16. # Date v1.63: 11.09.2007
  17. # Date v1.64: 11.09.2007
  18. # Date v1.65: 12.09.2007
  19. # Date v1.66: 10.10.2007
  20. # Date v1.67: 16.10.2007
  21. # Date v1.69: 31.10.2007
  22. # Date v1.70: 13.11.2007
  23. # Date v1.71: 22.11.2007
  24. # Date v1.72: 10.12.2007
  25. # Date v1.73: 11.12.2007
  26. # Date v1.80: 18.12.2007
  27. # Date v1.89: 13.01.2008
  28. # Date v1.95: 29.02.2008
  29. # Date v1.96:  5.03.2008
  30. # Date v1.97: 28.03.2008
  31. # Date v1.98:  5.04.2008
  32. # Date v1.99:  4.08.2008
  33. # Date v2.00:  1.12.2008
  34. # Date v2.01:  1.12.2008
  35. # Date v2.02:  2.12.2008
  36. # Date v2.03:  3.12.2008
  37. # Date v2.10:  4.12.2008
  38. # Date v2.11:  5.12.2008
  39. # Date v2.12:  5.12.2008
  40. # Date v2.13:  6.12.2008
  41. # Date v2.14:  7.12.2008
  42. # Date v2.15:  8.12.2008
  43. # Date v2.20: 13.12.2008
  44. # Date v2.21: 19.12.2008
  45. # Date v2.22: 08.01.2009
  46. # Date v2.23: 25.01.2009
  47. # Date v2.30:  8.04.2009
  48. # Date v2.31:  8.04.2009
  49. # Date v2.50: 20.04.2009
  50. # Date v2.51: 20.04.2009
  51. # Date v2.52: 20.04.2009
  52. # Date v2.53:  2.05.2009
  53. # Date v2.54: 23.05.2009
  54. # Date v2.55: 28.06.2009
  55. # Date v2.56: 29.07.2009
  56. # Date v2.57: 19.08.2009
  57. # Date v2.60: 27.11.2009
  58. # Date v2.70: 28.11.2009
  59. # Date v2.71:  12.5.2010
  60. # Date v2.74:  16.5.2010
  61. # Date v2.79:  20.5.2010
  62. # Date v2.80:   4.6.2010
  63. # Date v2.81:   6.1.2011
  64. # Date v2.82:   7.1.2011
  65. # Date v2.83:  19.1.2011
  66. # Date v2.84:  23.1.2011
  67. # Date v2.84:  23.1.2011
  68. # Date v2.85:  16.5.2013
  69. # Date v2.86:  28.2.2014
  70. # Date v2.87: 24.10.2014
  71. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  72. #
  73. #                                    PART 2
  74. #
  75. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  76. #  
  77. #  This work is protected by the following license:
  78. # #----------------------------------------------------------------------------
  79. # #  
  80. # #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
  81. # #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
  82. # #  
  83. # #  You are free:
  84. # #  
  85. # #  to Share - to copy, distribute and transmit the work
  86. # #  to Remix - to adapt the work
  87. # #  
  88. # #  Under the following conditions:
  89. # #  
  90. # #  Attribution. You must attribute the work in the manner specified by the
  91. # #  author or licensor (but not in any way that suggests that they endorse you
  92. # #  or your use of the work).
  93. # #  
  94. # #  Noncommercial. You may not use this work for commercial purposes.
  95. # #  
  96. # #  Share alike. If you alter, transform, or build upon this work, you may
  97. # #  distribute the resulting work only under the same or similar license to
  98. # #  this one.
  99. # #  
  100. # #  - For any reuse or distribution, you must make clear to others the license
  101. # #    terms of this work. The best way to do this is with a link to this web
  102. # #    page.
  103. # #  
  104. # #  - Any of the above conditions can be waived if you get permission from the
  105. # #    copyright holder.
  106. # #  
  107. # #  - Nothing in this license impairs or restricts the author's moral rights.
  108. # #  
  109. # #----------------------------------------------------------------------------
  110. #
  111. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  112. #
  113. # Information:
  114. #
  115. #   This script will allow you to create games with an Action Battle System
  116. #   (ABS) (i.e. Zelda). Action Battle System means real time battle on the map.
  117. #
  118. #   If you don't read the Manual, you will not be able to use many of the great
  119. #   features this ABS supports.
  120. #
  121. #   You DID NOT get the documentation with Blizz-ABS? Please contact me under
  122. #   the URL provided below.
  123. #
  124. #
  125. # If you find any bugs, please report them here:
  126. # http://forum.chaos-project.com
  127. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  128.  
  129. #==============================================================================
  130. # BlizzABS
  131. #------------------------------------------------------------------------------
  132. #  This is the master control, configuration, utility and battle process
  133. #  module for Blizz-ABS.
  134. #==============================================================================
  135.  
  136. module BlizzABS
  137.  
  138.   # version of Blizz-ABS
  139.   VERSION = 2.87
  140.   # edition of Blizz-ABS
  141.   EDITION = 'Normal'
  142.   # constants to help the user when using the special commands
  143.   PARTY = false
  144.   TROOP = false
  145.   INCREASE = 0
  146.   DECREASE = 1
  147.   CONSTANT = 0
  148.   VARIABLE = 1
  149.   KILL = true
  150.   NO_KILL = false
  151.   ADD = true
  152.   REMOVE = false
  153.   ATTACK = 0
  154.   DEFEND = 1
  155.   ESCAPE = 2
  156.   SKILL = 3
  157.   ITEM = 4
  158.   ENEMIES = true
  159.   ACTORS = false
  160.   NONE = nil
  161.  
  162.   # action types
  163.   ACTNone = 0
  164.   ACTAttack = 1
  165.   ACTDefend = 2
  166.   ACTSkill = 3
  167.   ACTItem = 4
  168.  
  169.   # attack types
  170.   SWORD = 1
  171.   SPEAR = 2
  172.   FLAIL = 3
  173.   BOOMERANG = 4
  174.   BOW = 5
  175.   BOW_ARROW = 6
  176.   SHURIKEN = 7
  177.  
  178.   # special types
  179.   SHOOT = 1
  180.   HOMING = 2
  181.   DIRECT = 3
  182.   BEAM = 4
  183.   TRAP = 5
  184.   TIMED = 6
  185.   SUMMON = 7
  186.  
  187.   # explode types
  188.   EXPLNone = 1
  189.   EXPLTarget = 2
  190.   EXPLEnd = 3
  191.   EXPLAny = 4
  192.  
  193.   # remote types
  194.   REMReturning = 0
  195.   REMOnReturn = 1
  196.   REMNormal = 2
  197.   REMShotItem = 3
  198.   REMShotWeapon = 4
  199.   REMNormalSkill = 5
  200.   REMBreakSkill = 6
  201.   REMInitSkill = 7
  202.   REMHomingSkill = 8
  203.   REMNormalItem = 9
  204.   REMBreakItem = 10
  205.   REMInitItem = 11
  206.   REMHomingItem = 12
  207.   REMTrapSkill = 13
  208.   REMTrapItem = 14
  209.   REMTimedSkill = 15
  210.   REMTimedItem = 16
  211.  
  212.   # remote groups
  213.   REMRequest = [REMReturning, REMNormalSkill, REMBreakSkill, REMInitSkill,
  214.                 REMTrapSkill, REMNormalItem, REMBreakItem, REMHomingItem,
  215.                 REMTrapItem, REMTimedSkill, REMTimedItem]
  216.   REMSkills = [REMNormalSkill, REMBreakSkill, REMInitSkill, REMHomingSkill,
  217.                REMTrapSkill, REMTimedSkill]
  218.   REMItems = [REMNormalItem, REMBreakItem, REMInitItem, REMHomingItem,
  219.               REMTrapItem, REMTimedItem]
  220.   REMPersistent = [REMReturning, REMOnReturn, REMBreakSkill, REMBreakItem]
  221.   REMHomingBase = [REMInitSkill, REMHomingSkill, REMInitItem,
  222.                    REMHomingItem]
  223.   REMHomingExtend = [REMOnReturn, REMInitSkill, REMHomingSkill,
  224.                      REMInitItem, REMHomingItem]                
  225.  
  226.   # charge types
  227.   CHARGENone = 1
  228.   CHARGEFreeze = 2
  229.   CHARGEMove = 3
  230.   CHARGETrigger = 4
  231.  
  232.   # charge data
  233.   CHARGEAttack = 0
  234.   CHARGESkill = 1
  235.   CHARGEItem = 2
  236.  
  237.   # summon data
  238.   SUMMONNone = 1
  239.   SUMMONPet = 2
  240.   SUMMONMonster = 3
  241.  
  242.   # command types
  243.   COMScript = 1
  244.   COMWait = 2
  245.   COMMove = 3
  246.   COMTurn = 4
  247.   COMJump = 5
  248.   COMAttack = 6
  249.   COMSkill = 7
  250.   COMItem = 8
  251.   COMDefend = 9
  252.   COMCharacter = 10
  253.   COMBattler = 11
  254.   COMInput = 12
  255.   COMVariable = 13
  256.   COMCondition = 14
  257.   COMFreeze = 15
  258.   COMCompletion = 16
  259.   COMGoTo = 17
  260.   COMAbort = 18
  261.  
  262.   # direction command types
  263.   DIR90Right = 11
  264.   DIR90Left = 12
  265.   DIRForward = 13
  266.   DIRBackward = 14
  267.   DIRTowardPlayer = 15
  268.   DIRAwayPlayer = 16
  269.   DIRRandom4 = 17
  270.   DIRRandom8 = 18
  271.   DIR45Right = 19
  272.   DIR45Left = 20
  273.  
  274.   # character command types
  275.   CHSpeed = 1
  276.   CHFrequency = 2
  277.   CHSprite = 3
  278.   CHAnimation = 4
  279.   CHFix = 5
  280.   CHThrough = 6
  281.   CHOnTop = 7
  282.   CHOpacity = 8
  283.  
  284.   # variable command types
  285.   VARGame = 1
  286.   VARCombo = 2
  287.   VARCharacter = 3
  288.   VARParty = 4
  289.   VARInput = 5
  290.   VARConstant = 6
  291.   VARScript = 7
  292.  
  293.   # input trigger types
  294.   INPress = 1
  295.   INTrigger = 2
  296.   INRelease = 3
  297.  
  298.   # value command types
  299.   VALHp = 1
  300.   VALSp = 2
  301.   VALMaxHp = 3
  302.   VALMaxSp = 4
  303.   VALState = 5
  304.   VALExp = 6
  305.   VALLevel = 7
  306.   VALTile = 8
  307.   VALDirection = 9
  308.  
  309.   # trigger data
  310.   TRGLeader = 0
  311.   TRGAlly = 1
  312.   TRGSelf = 2
  313.   TRGEnemy = 3
  314.   TRGProbability = 4
  315.  
  316.   # trigger target data
  317.   TRGTargetDefault = 0
  318.   TRGTargetActivator = 1
  319.  
  320.   # trigger condition data
  321.   TRGHP = 0
  322.   TRGSP = 1
  323.   TRGState = 2
  324.   TRGLocation = 3
  325.  
  326.   # trigger comparison data
  327.   TRGEqual = 0
  328.   TRGNotEqual = 1
  329.   TRGGreater = 2
  330.   TRGGreaterEqual = 3
  331.   TRGLess = 4
  332.   TRGLessEqual = 5
  333.  
  334.   # trigger action data
  335.   TRGAttack = 0
  336.   TRGDefend = 1
  337.   TRGSkill = 2
  338.   TRGItem = 3
  339.  
  340.   # trigger location data
  341.   TRGClosest = 0
  342.   TRGFarthest = 1
  343.  
  344.   # action data
  345.   ACTNone = 0
  346.   ACTAttack = 1
  347.   ACTDefend = 2
  348.   ACTEscape = 3
  349.   ACTSkill = 4
  350.   ACTItem = 5
  351.  
  352.   # AI update data
  353.   UPDLight = 1
  354.   UPDMedium = 2
  355.   UPDHeavy = 3
  356.   UPDFull = 4
  357.  
  358.   # custom event triggers
  359.   CETNone = -1
  360.   CETActionButton = 0
  361.   CETPlayerTouch = 1
  362.   CETEventTouch = 2
  363.   CETDeath = 9
  364.   CETWeapon = 21
  365.   CETSkill = 22
  366.   CETItem = 23
  367.   CETEnemy = 24
  368.   CETDefault = CETDeath
  369.   CETSpecial = [CETWeapon, CETSkill, CETItem, CETEnemy]
  370.  
  371.   # spriteset filenames
  372.   SPRProjWeapon = 'projectile_weapon_'
  373.   SPRProjSkill = 'projectile_skill_'
  374.   SPRProjItem = 'projectile_item_'
  375.   SPRProjEnemy = 'projectile_enemy_'
  376.   SPRAttack = '_atk'
  377.   SPRWeapon = '_wpn'
  378.   SPRWeaponID = '_wpn_'
  379.   SPRDefend = '_def'
  380.   SPRSkill = '_skl'
  381.   SPRItem = '_itm'
  382.   SPRCharge = '_chr'
  383.   SPRJumping = '_jmp'
  384.   SPRRunning = '_run'
  385.   SPRSneaking = '_snk'
  386.   SPRIdle = '_idl'
  387.   SPRCorpse = '_crp'
  388.   SPRNoAction = [SPRJumping, SPRRunning, SPRSneaking, SPRIdle]
  389.  
  390.   #============================================================================
  391.   # BlizzABS::Cache
  392.   #----------------------------------------------------------------------------
  393.   #  This class holds a few bitmaps so they don't need to be drawn each time
  394.   #  which improves speed and reduces lag. It also holds damage sprites and
  395.   #  remote characters. It also holds constant data that is used in Blizz-ABS
  396.   #  to improve the performance (i.e. creating arrays of data for processing).
  397.   #============================================================================
  398.  
  399.   class Cache
  400.    
  401.     # constant cache
  402.     LoopDir8 = [1, 2, 3, 6, 9, 8, 7, 4]
  403.     Dir8 = [1, 2, 3, 4, 6, 7, 8, 9]
  404.     Dir4 = [2, 4, 6, 8]
  405.     NoDirsUpLeft = [1, 4, 7, 8, 9]
  406.     NoDirsDownLeft = [1, 2, 3, 4, 7]
  407.     NoDirsUpRight = [3, 6, 7, 8, 9]
  408.     NoDirsDownRight = [1, 2, 3, 6, 9]
  409.     NoDirsRight = [2, 3, 6, 8, 9]
  410.     NoDirsLeft = [1, 2, 4, 8, 7]
  411.     NoDirsDown = [1, 2, 3, 4, 6]
  412.     NoDirsUp = [4, 6, 7, 8, 9]
  413.     TDirs = [[0, true], [1, true], [2, true], [3, true], [4, true], [5, true],
  414.         [6, true], [7, true], [8, true], [9, true]]
  415.     FDirs = [[0, false], [1, false], [2, false], [3, false], [4, false],
  416.         [5, false], [6, false], [7, false], [8, false], [9, false]]
  417.     DirDownLeft = [2, 4]
  418.     DirLeftDown = [4, 2]
  419.     DirDownRight = [2, 6]
  420.     DirRightDown = [6, 2]
  421.     DirLeftUp = [4, 8]
  422.     DirUpLeft = [8, 4]
  423.     DirRightUp = [6, 8]
  424.     DirUpRight = [8, 6]
  425.     DirOffsets = [[0, 0], [-1, 1], [0, 1], [1, 1], [-1, 0], [0, 0], [1, 0],
  426.                   [-1, -1], [0, -1], [1, -1]]
  427.     PathDirs = [[0, 1, 2], [-1, 0, 4], [1, 0, 6], [0, -1, 8]]
  428.     Keys = 0..9
  429.     HotkeyRange = 1..10
  430.     PressTrigger = [0]
  431.     TouchTrigger = [1, 2]
  432.     BasicTrigger = [0, 1, 2]
  433.     MapLayers = [2, 1, 0]
  434.     ScopeOne = [1, 3, 5]
  435.     HotKeys = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  436.     EmptyKeys = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
  437.     FramesDefault = [3, 3, 3, 3]
  438.    
  439.     CommandsAIBehavior = ['Behavior', 'Next', 'Previous', 'Exit']
  440.     CommandsAITrigger = ['Triggers', 'Next', 'Previous', 'Exit']
  441.     CommandsTrigger = ['Edit', 'Add new', 'Delete', 'Copy', 'Move up',
  442.         'Move down', 'Exit']
  443.     CommandsPreMenu = ['Menu', 'Hotkeys', 'AI Behavior', 'AI Triggers', 'Cancel']
  444.     CommandsEdit = ['Activator', 'Condition', 'Comparison', 'Value',
  445.         'Action Type', 'Action', 'Target Type', 'Done', 'Cancel']
  446.        
  447.     WORDAll = 'All'
  448.     WORDState = 'State'
  449.     WORDTarget = 'Target'
  450.     WORDNormalState = 'Normal'
  451.     WORDLocation = 'Location'
  452.     WORDAggressive = 'Aggressive'
  453.     WORDPassive = 'Passive'
  454.     WORDOffensive = 'Offensive'
  455.     WORDDefensive = 'Defensive'
  456.    
  457.     TRGActivators = ['Leader', 'Ally', 'Self', 'Enemy', 'Probability']
  458.     TRGTargets = ['Default', 'Activator']
  459.     TRGComparators = ['==', '!=', '>', '>=', '<', '<=']
  460.     TRGLocations = ['Closest', 'Farthest']
  461.    
  462.     FontNameDamage = 'Arial Black'
  463.     FontSizeDamage = 24
  464.     FontItalicDamage = true
  465.     FontBoldDamage = false
  466.     TXTLvlUp = 'LvUp'
  467.     TXTMiss = 'Miss'
  468.     TXTDefend = load_data('Data/System.rxdata').words.guard
  469.    
  470.     DMGColors = {}
  471.     DMGColors[TXTLvlUp] = Color.new(192, 96, 255)
  472.     DMGColors[TXTMiss] = Color.new(192, 192, 192)
  473.     DMGColors[TXTDefend] = Color.new(192, 192, 192)
  474.     DMGColors[0] = Color.new(192, 192, 192)
  475.     DMGColors['Critical'] = Color.new(255, 0, 0)
  476.     DMGColors['HP-A'] = Color.new(255, 192, 64)
  477.     DMGColors['HP-E'] = Color.new(255, 0, 0)
  478.     DMGColors['HP+A'] = Color.new(0, 192, 255)
  479.     DMGColors['HP+E'] = Color.new(0, 192, 255)
  480.     DMGColors['SP-A'] = Color.new(255, 255, 0)
  481.     DMGColors['SP-E'] = Color.new(255, 255, 0)
  482.     DMGColors['SP+A'] = Color.new(0, 255, 0)
  483.     DMGColors['SP+E'] = Color.new(0, 255, 0)
  484.     DMGColors['Default'] = Color.new(255, 255, 255)
  485.     DMGColors['Shadow'] = Color.new(0, 0, 0)
  486.        
  487.     # setting all accessible variables
  488.     attr_reader :damages
  489.     attr_reader :remotes
  490.     attr_reader :beams
  491.     #--------------------------------------------------------------------------
  492.     # Initialization
  493.     #--------------------------------------------------------------------------
  494.     def initialize
  495.       # initialize image, damage sprite, beam sprite and projectile buffers
  496.       @data, @damages, @remotes, @beams = {}, [], [], []
  497.       # add image
  498.       @data['minimap_autotile'] = _minimap_autotile
  499.       # prevent "Script is hanging" error
  500.       Graphics.update
  501.       # add image
  502.       @data['menu_arrow'] = _menu_arrow
  503.       # prevent "Script is hanging" error
  504.       Graphics.update
  505.       # add image
  506.       @data['white_arrow'] = _white_arrow
  507.       # prevent "Script is hanging" error
  508.       Graphics.update
  509.       # add image
  510.       @data['green_arrow'] = _green_arrow
  511.       # prevent "Script is hanging" error
  512.       Graphics.update
  513.       # add image
  514.       @data['blue_arrow'] = @data['green_arrow'].clone
  515.       # change color
  516.       @data['blue_arrow'].hue_change(120)
  517.       # add image
  518.       @data['red_arrow'] = @data['green_arrow'].clone
  519.       # change color
  520.       @data['red_arrow'].hue_change(-120)
  521.       # add image
  522.       @data['yellow_arrow'] = @data['green_arrow'].clone
  523.       # change color
  524.       @data['yellow_arrow'].hue_change(-60)
  525.       # add image
  526.       @data['violet_arrow'] = @data['green_arrow'].clone
  527.       # change color
  528.       @data['violet_arrow'].hue_change(150)
  529.       # prevent "Script is hanging" error
  530.       Graphics.update
  531.       # add image
  532.       @data['empty_hud_white_bar'] = _empty_hud_white_bar
  533.       # prevent "Script is hanging" error
  534.       Graphics.update
  535.       # add image
  536.       @data['empty_hud_green_bar'] = _empty_hud_green_bar
  537.       # prevent "Script is hanging" error
  538.       Graphics.update
  539.       # add image
  540.       @data['empty_hud_blue_bar'] = @data['empty_hud_green_bar'].clone
  541.       # change color
  542.       @data['empty_hud_blue_bar'].hue_change(120)
  543.       # add image
  544.       @data['empty_hud_red_bar'] = @data['empty_hud_green_bar'].clone
  545.       # change color
  546.       @data['empty_hud_red_bar'].hue_change(-120)
  547.       # prevent "Script is hanging" error
  548.       Graphics.update
  549.       # add image
  550.       @data['hud_white_bar'] = _hud_white_bar
  551.       # prevent "Script is hanging" error
  552.       Graphics.update
  553.       # add image
  554.       @data['hud_green_bar'] = _hud_green_bar
  555.       # prevent "Script is hanging" error
  556.       Graphics.update
  557.       # add image
  558.       @data['hud_blue_bar'] = @data['hud_green_bar'].clone
  559.       # change color
  560.       @data['hud_blue_bar'].hue_change(120)
  561.       # add image
  562.       @data['hud_red_bar'] = @data['hud_green_bar'].clone
  563.       # change color
  564.       @data['hud_red_bar'].hue_change(-120)
  565.       # prevent "Script is hanging" error
  566.       Graphics.update
  567.       # add image
  568.       @data['empty_enemy_bar'] = _empty_enemy_bar
  569.       # prevent "Script is hanging" error
  570.       Graphics.update
  571.       # add image
  572.       @data['enemy_bar'] = _enemy_bar
  573.       # prevent "Script is hanging" error
  574.       Graphics.update
  575.       # add image
  576.       @data['beam1'] = _beam1
  577.       # prevent "Script is hanging" error
  578.       Graphics.update
  579.       # add image
  580.       @data['grid'] = _grid
  581.       # prevent "Script is hanging" error
  582.       Graphics.update
  583.     end
  584.     #--------------------------------------------------------------------------
  585.     # clean
  586.     #  Cleans the cache from remotes and damage sprites.
  587.     #--------------------------------------------------------------------------
  588.     def clean
  589.       # dispose all damage sprites
  590.       @damages.each {|sprite| sprite.dispose if sprite.is_a?(Sprite)}
  591.       # dispose all beam sprites
  592.       @beams.each {|ary| ary[0].dispose}
  593.       # create new damage sprite buffer and new projectile buffer
  594.       @damages, @remotes, @beams = [], [], []
  595.       # unfreeze all actor's actions
  596.       $BlizzABS.battlers.each {|actor| actor.freeze_action = false}
  597.       # clear observation and path request data
  598.       $BlizzABS.AI = BlizzABS::AI.new
  599.     end
  600.     #--------------------------------------------------------------------------
  601.     # image
  602.     #  key - hash key for the image
  603.     #  Returns a copy of the image.
  604.     #--------------------------------------------------------------------------
  605.     def image(key)
  606.       return @data[key].clone
  607.     end
  608.     #--------------------------------------------------------------------------
  609.     # _white_arrow
  610.     #  Creates the minimap icon for other events.
  611.     #--------------------------------------------------------------------------
  612.     def _white_arrow
  613.       b = Bitmap.new(56, 14)
  614.       c1 = Color.new(0, 0, 0)
  615.       c2 = Color.new(255, 255, 255)
  616.       b.set_pixel(23, 0, c1)
  617.       b.set_pixel(32, 0, c1)
  618.       b.set_pixel(22, 1, c1)
  619.       b.fill_rect(23, 1, 1, 12, c2)
  620.       b.fill_rect(24, 1, 1, 12, c1)
  621.       b.fill_rect(31, 1, 1, 12, c1)
  622.       b.fill_rect(32, 1, 1, 12, c2)
  623.       b.set_pixel(33, 1, c1)
  624.       b.set_pixel(21, 2, c1)
  625.       b.fill_rect(22, 2, 1, 10, c2)
  626.       b.fill_rect(33, 2, 1, 10, c2)
  627.       b.set_pixel(34, 2, c1)
  628.       b.fill_rect(1, 3, 12, 1, c1)
  629.       b.set_pixel(20, 3, c1)
  630.       b.fill_rect(21, 3, 1, 8, c2)
  631.       b.fill_rect(34, 3, 1, 8, c2)
  632.       b.set_pixel(35, 3, c1)
  633.       b.fill_rect(48, 3, 2, 1, c1)
  634.       b.set_pixel(0, 4, c1)
  635.       b.fill_rect(1, 4, 12, 1, c2)
  636.       b.set_pixel(13, 4, c1)
  637.       b.set_pixel(19, 4, c1)
  638.       b.fill_rect(20, 4, 1, 6, c2)
  639.       b.fill_rect(35, 4, 1, 6, c2)
  640.       b.set_pixel(36, 4, c1)
  641.       b.set_pixel(47, 4, c1)
  642.       b.fill_rect(48, 4, 2, 6, c2)
  643.       b.set_pixel(50, 4, c1)
  644.       b.set_pixel(1, 5, c1)
  645.       b.fill_rect(2, 5, 10, 1, c2)
  646.       b.set_pixel(12, 5, c1)
  647.       b.set_pixel(18, 5, c1)
  648.       b.fill_rect(19, 5, 1, 4, c2)
  649.       b.fill_rect(36, 5, 1, 4, c2)
  650.       b.set_pixel(37, 5, c1)
  651.       b.set_pixel(46, 5, c1)
  652.       b.fill_rect(47, 5, 1, 5, c2)
  653.       b.fill_rect(50, 5, 1, 5, c2)
  654.       b.set_pixel(51, 5, c1)
  655.       b.set_pixel(2, 6, c1)
  656.       b.fill_rect(3, 6, 8, 1, c2)
  657.       b.set_pixel(11, 6, c1)
  658.       b.fill_rect(17, 6, 1, 2, c1)
  659.       b.fill_rect(18, 6, 1, 2, c2)
  660.       b.fill_rect(37, 6, 1, 2, c2)
  661.       b.fill_rect(38, 6, 1, 2, c1)
  662.       b.set_pixel(45, 6, c1)
  663.       b.fill_rect(46, 6, 1, 4, c2)
  664.       b.fill_rect(51, 6, 1, 4, c2)
  665.       b.set_pixel(52, 6, c1)
  666.       b.set_pixel(3, 7, c1)
  667.       b.fill_rect(4, 7, 6, 1, c2)
  668.       b.set_pixel(10, 7, c1)
  669.       b.set_pixel(44, 7, c1)
  670.       b.fill_rect(45, 7, 1, 3, c2)
  671.       b.fill_rect(52, 7, 1, 3, c2)
  672.       b.set_pixel(53, 7, c1)
  673.       b.set_pixel(4, 8, c1)
  674.       b.fill_rect(5, 8, 4, 1, c2)
  675.       b.set_pixel(9, 8, c1)
  676.       b.set_pixel(18, 8, c1)
  677.       b.set_pixel(37, 8, c1)
  678.       b.set_pixel(43, 8, c1)
  679.       b.fill_rect(44, 8, 1, 2, c2)
  680.       b.fill_rect(53, 8, 1, 2, c2)
  681.       b.set_pixel(54, 8, c1)
  682.       b.set_pixel(5, 9, c1)
  683.       b.fill_rect(6, 9, 2, 1, c2)
  684.       b.set_pixel(8, 9, c1)
  685.       b.set_pixel(19, 9, c1)
  686.       b.set_pixel(36, 9, c1)
  687.       b.set_pixel(42, 9, c1)
  688.       b.set_pixel(43, 9, c2)
  689.       b.set_pixel(54, 9, c2)
  690.       b.set_pixel(55, 9, c1)
  691.       b.fill_rect(6, 10, 2, 1, c1)
  692.       b.set_pixel(20, 10, c1)
  693.       b.set_pixel(35, 10, c1)
  694.       b.fill_rect(43, 10, 12, 1, c1)
  695.       b.set_pixel(21, 11, c1)
  696.       b.set_pixel(34, 11, c1)
  697.       b.set_pixel(22, 12, c1)
  698.       b.set_pixel(33, 12, c1)
  699.       b.set_pixel(23, 13, c1)
  700.       b.set_pixel(32, 13, c1)
  701.       return b
  702.     end
  703.     #--------------------------------------------------------------------------
  704.     # _green_arrow
  705.     #  Creates the minimap icon for events.
  706.     #--------------------------------------------------------------------------
  707.     def _green_arrow
  708.       b = Bitmap.new(56, 14)
  709.       c1 = Color.new(0, 0, 0)
  710.       c2 = Color.new(255, 255, 255)
  711.       c3 = Color.new(0, 255, 0)
  712.       b.set_pixel(23, 0, c1)
  713.       b.set_pixel(32, 0, c1)
  714.       b.set_pixel(22, 1, c1)
  715.       b.fill_rect(23, 1, 1, 12, c3)
  716.       b.fill_rect(24, 1, 1, 12, c1)
  717.       b.fill_rect(31, 1, 1, 12, c1)
  718.       b.fill_rect(32, 1, 1, 12, c3)
  719.       b.set_pixel(33, 1, c1)
  720.       b.set_pixel(21, 2, c1)
  721.       b.fill_rect(22, 2, 1, 10, c3)
  722.       b.fill_rect(33, 2, 1, 10, c3)
  723.       b.set_pixel(34, 2, c1)
  724.       b.fill_rect(1, 3, 12, 1, c1)
  725.       b.set_pixel(20, 3, c1)
  726.       b.fill_rect(21, 3, 1, 8, c3)
  727.       b.fill_rect(34, 3, 1, 8, c3)
  728.       b.set_pixel(35, 3, c1)
  729.       b.fill_rect(48, 3, 2, 1, c1)
  730.       b.set_pixel(0, 4, c1)
  731.       b.fill_rect(1, 4, 12, 1, c3)
  732.       b.set_pixel(13, 4, c1)
  733.       b.set_pixel(19, 4, c1)
  734.       b.fill_rect(20, 4, 1, 6, c3)
  735.       b.fill_rect(35, 4, 1, 6, c3)
  736.       b.set_pixel(36, 4, c1)
  737.       b.set_pixel(47, 4, c1)
  738.       b.fill_rect(48, 4, 2, 6, c3)
  739.       b.set_pixel(50, 4, c1)
  740.       b.set_pixel(1, 5, c1)
  741.       b.fill_rect(2, 5, 10, 1, c3)
  742.       b.set_pixel(12, 5, c1)
  743.       b.set_pixel(18, 5, c1)
  744.       b.fill_rect(19, 5, 1, 4, c3)
  745.       b.fill_rect(36, 5, 1, 4, c3)
  746.       b.set_pixel(37, 5, c1)
  747.       b.set_pixel(46, 5, c1)
  748.       b.fill_rect(47, 5, 1, 5, c3)
  749.       b.fill_rect(50, 5, 1, 5, c3)
  750.       b.set_pixel(51, 5, c1)
  751.       b.set_pixel(2, 6, c1)
  752.       b.fill_rect(3, 6, 8, 1, c3)
  753.       b.set_pixel(11, 6, c1)
  754.       b.fill_rect(17, 6, 1, 2, c1)
  755.       b.fill_rect(18, 6, 1, 2, c3)
  756.       b.fill_rect(37, 6, 1, 2, c3)
  757.       b.fill_rect(38, 6, 1, 2, c1)
  758.       b.set_pixel(45, 6, c1)
  759.       b.fill_rect(46, 6, 1, 4, c3)
  760.       b.fill_rect(51, 6, 1, 4, c3)
  761.       b.set_pixel(52, 6, c1)
  762.       b.set_pixel(3, 7, c1)
  763.       b.fill_rect(4, 7, 6, 1, c3)
  764.       b.set_pixel(10, 7, c1)
  765.       b.set_pixel(44, 7, c1)
  766.       b.fill_rect(45, 7, 1, 3, c3)
  767.       b.fill_rect(52, 7, 1, 3, c3)
  768.       b.set_pixel(53, 7, c1)
  769.       b.set_pixel(4, 8, c1)
  770.       b.fill_rect(5, 8, 4, 1, c3)
  771.       b.set_pixel(9, 8, c1)
  772.       b.set_pixel(18, 8, c1)
  773.       b.set_pixel(37, 8, c1)
  774.       b.set_pixel(43, 8, c1)
  775.       b.fill_rect(44, 8, 1, 2, c3)
  776.       b.fill_rect(53, 8, 1, 2, c3)
  777.       b.set_pixel(54, 8, c1)
  778.       b.set_pixel(5, 9, c1)
  779.       b.fill_rect(6, 9, 2, 1, c3)
  780.       b.set_pixel(8, 9, c1)
  781.       b.set_pixel(19, 9, c1)
  782.       b.set_pixel(36, 9, c1)
  783.       b.set_pixel(42, 9, c1)
  784.       b.set_pixel(43, 9, c3)
  785.       b.set_pixel(54, 9, c3)
  786.       b.set_pixel(55, 9, c1)
  787.       b.fill_rect(6, 10, 2, 1, c1)
  788.       b.set_pixel(20, 10, c1)
  789.       b.set_pixel(35, 10, c1)
  790.       b.fill_rect(43, 10, 12, 1, c1)
  791.       b.set_pixel(21, 11, c1)
  792.       b.set_pixel(34, 11, c1)
  793.       b.set_pixel(22, 12, c1)
  794.       b.set_pixel(33, 12, c1)
  795.       b.set_pixel(23, 13, c1)
  796.       b.set_pixel(32, 13, c1)
  797.       return b
  798.     end
  799.     #--------------------------------------------------------------------------
  800.     # _menu_arrow
  801.     #  Creates the arrow displayed in the hotkey assignment menu.
  802.     #--------------------------------------------------------------------------
  803.     def _menu_arrow
  804.       b = Bitmap.new(16, 9)
  805.       c1 = Color.new(0, 0, 0)
  806.       c2 = Color.new(255, 255, 255)
  807.       c3 = Color.new(127, 127, 127)
  808.       b.fill_rect(7, 0, 2, 1, c2)
  809.       b.set_pixel(6, 1, c2)
  810.       b.fill_rect(7, 1, 1, 7, c3)
  811.       b.fill_rect(8, 1, 1, 7, c1)
  812.       b.set_pixel(9, 1, c2)
  813.       b.set_pixel(5, 2, c2)
  814.       b.fill_rect(6, 2, 1, 6, c3)
  815.       b.fill_rect(9, 2, 1, 6, c1)
  816.       b.set_pixel(10, 2, c2)
  817.       b.set_pixel(4, 3, c2)
  818.       b.fill_rect(5, 3, 1, 5, c3)
  819.       b.fill_rect(10, 3, 1, 5, c1)
  820.       b.set_pixel(11, 3, c2)
  821.       b.set_pixel(3, 4, c2)
  822.       b.fill_rect(4, 4, 1, 4, c3)
  823.       b.fill_rect(11, 4, 1, 4, c1)
  824.       b.set_pixel(12, 4, c2)
  825.       b.set_pixel(2, 5, c2)
  826.       b.fill_rect(3, 5, 1, 3, c3)
  827.       b.fill_rect(12, 5, 1, 3, c1)
  828.       b.set_pixel(13, 5, c2)
  829.       b.set_pixel(1, 6, c2)
  830.       b.fill_rect(2, 6, 1, 2, c3)
  831.       b.fill_rect(13, 6, 1, 2, c1)
  832.       b.set_pixel(14, 6, c2)
  833.       b.set_pixel(0, 7, c2)
  834.       b.set_pixel(1, 7, c3)
  835.       b.set_pixel(14, 7, c1)
  836.       b.set_pixel(15, 7, c2)
  837.       b.fill_rect(1, 8, 14, 1, c2)
  838.       return b
  839.     end
  840.     #--------------------------------------------------------------------------
  841.     # _minimap_autotile
  842.     #  Creates the minimap autotile for passability.
  843.     #--------------------------------------------------------------------------
  844.     def _minimap_autotile
  845.       b = Bitmap.new(24, 32)
  846.       c1 = Color.new(191, 191, 191)
  847.       c2 = Color.new(255, 255, 255)
  848.       b.fill_rect(2, 0, 4, 1, c2)
  849.       b.set_pixel(1, 1, c2)
  850.       b.fill_rect(2, 1, 4, 6, c1)
  851.       b.set_pixel(6, 1, c2)
  852.       b.fill_rect(0, 2, 1, 4, c2)
  853.       b.fill_rect(1, 2, 1, 4, c1)
  854.       b.fill_rect(6, 2, 1, 4, c1)
  855.       b.fill_rect(7, 2, 1, 4, c2)
  856.       b.set_pixel(1, 6, c2)
  857.       b.set_pixel(6, 6, c2)
  858.       b.fill_rect(2, 7, 4, 1, c2)
  859.       b.fill_rect(7, 8, 10, 1, c2)
  860.       b.set_pixel(6, 9, c2)
  861.       b.fill_rect(7, 9, 10, 22, c1)
  862.       b.set_pixel(17, 9, c2)
  863.       b.set_pixel(5, 10, c2)
  864.       b.fill_rect(6, 10, 1, 20, c1)
  865.       b.fill_rect(17, 10, 1, 20, c1)
  866.       b.set_pixel(18, 10, c2)
  867.       b.set_pixel(4, 11, c2)
  868.       b.fill_rect(5, 11, 1, 18, c1)
  869.       b.fill_rect(18, 11, 1, 18, c1)
  870.       b.set_pixel(19, 11, c2)
  871.       b.set_pixel(3, 12, c2)
  872.       b.fill_rect(4, 12, 1, 16, c1)
  873.       b.fill_rect(19, 12, 1, 16, c1)
  874.       b.set_pixel(20, 12, c2)
  875.       b.set_pixel(2, 13, c2)
  876.       b.fill_rect(3, 13, 1, 14, c1)
  877.       b.fill_rect(20, 13, 1, 14, c1)
  878.       b.set_pixel(21, 13, c2)
  879.       b.set_pixel(1, 14, c2)
  880.       b.fill_rect(2, 14, 1, 12, c1)
  881.       b.fill_rect(21, 14, 1, 12, c1)
  882.       b.set_pixel(22, 14, c2)
  883.       b.fill_rect(0, 15, 1, 10, c2)
  884.       b.fill_rect(1, 15, 1, 10, c1)
  885.       b.fill_rect(22, 15, 1, 10, c1)
  886.       b.fill_rect(23, 15, 1, 10, c2)
  887.       b.set_pixel(1, 25, c2)
  888.       b.set_pixel(22, 25, c2)
  889.       b.set_pixel(2, 26, c2)
  890.       b.set_pixel(21, 26, c2)
  891.       b.set_pixel(3, 27, c2)
  892.       b.set_pixel(20, 27, c2)
  893.       b.set_pixel(4, 28, c2)
  894.       b.set_pixel(19, 28, c2)
  895.       b.set_pixel(5, 29, c2)
  896.       b.set_pixel(18, 29, c2)
  897.       b.set_pixel(6, 30, c2)
  898.       b.set_pixel(17, 30, c2)
  899.       b.fill_rect(7, 31, 10, 1, c2)
  900.       return b
  901.     end
  902.     #--------------------------------------------------------------------------
  903.     # _empty_hud_white_bar
  904.     #  Creates the bitmap used for the empty HUD bars.
  905.     #--------------------------------------------------------------------------
  906.     def _empty_hud_white_bar
  907.       b = Bitmap.new(1, 12)
  908.       (1..6).each {|i| b.fill_rect(0, i-1, 1, 14-i*2, Color.new(40*i/3, 40*i/3, 40*i/3))}
  909.       return b
  910.     end
  911.     #--------------------------------------------------------------------------
  912.     # _empty_hud_green_bar
  913.     #  Creates the bitmap used for the empty HUD bars.
  914.     #--------------------------------------------------------------------------
  915.     def _empty_hud_green_bar
  916.       b = Bitmap.new(1, 12)
  917.       (1..6).each {|i| b.fill_rect(0, i-1, 1, 14-i*2, Color.new(0, 40*i/3, 0))}
  918.       return b
  919.     end
  920.     #--------------------------------------------------------------------------
  921.     # _hud_white_bar
  922.     #  Creates the bitmap used for the HUD bars.
  923.     #--------------------------------------------------------------------------
  924.     def _hud_white_bar
  925.       b = Bitmap.new(1, 12)
  926.       (1..6).each {|i| b.fill_rect(0, i-1, 1, 14-i*2, Color.new(40*i, 40*i, 40*i))}
  927.       return b
  928.     end
  929.     #--------------------------------------------------------------------------
  930.     # _hud_green_bar
  931.     #  Creates the bitmap used for the HUD bars.
  932.     #--------------------------------------------------------------------------
  933.     def _hud_green_bar
  934.       b = Bitmap.new(1, 12)
  935.       (1..6).each {|i| b.fill_rect(0, i-1, 1, 14-i*2, Color.new(0, 40*i, 0))}
  936.       return b
  937.     end
  938.     #--------------------------------------------------------------------------
  939.     # _empty_enemy_bar
  940.     #  Creates the bitmap used for the empty enemy bars.
  941.     #--------------------------------------------------------------------------
  942.     def _empty_enemy_bar
  943.       b = Bitmap.new(1, 6)
  944.       (1..3).each {|i| b.fill_rect(0, i-1, 1, 8-i*2, Color.new(0, 80*i/3, 0))}
  945.       return b
  946.     end
  947.     #--------------------------------------------------------------------------
  948.     # _enemy_bar
  949.     #  Creates the bitmap used for the enemy bars.
  950.     #--------------------------------------------------------------------------
  951.     def _enemy_bar
  952.       b = Bitmap.new(1, 6)
  953.       (1..3).each {|i| b.fill_rect(0, i-1, 1, 8-i*2, Color.new(0, 80*i, 0))}
  954.       return b
  955.     end
  956.     #--------------------------------------------------------------------------
  957.     # _beam1
  958.     #  Creates the bitmap used for the beam animation.
  959.     #--------------------------------------------------------------------------
  960.     def _beam1
  961.       b = Bitmap.new(24, 1)
  962.       (1...12).each {|i|
  963.           b.fill_rect(i, 0, 1, 1, Color.new(255, 255, 255, i**2*3))
  964.           b.fill_rect(23-i, 0, 1, 1, Color.new(255, 255, 255, i**2*3))}
  965.       return b
  966.     end
  967.     #--------------------------------------------------------------------------
  968.     # _grid
  969.     #  Creates the bitmap used for the AI behavior grid.
  970.     #--------------------------------------------------------------------------
  971.     def _grid
  972.       b = Bitmap.new(360, 360)
  973.       c1, c2 = Color.new(255, 255, 255), Color.new(0, 0, 0)
  974.       b.fill_rect(0, 0, 48, 48, c1)
  975.       b.fill_rect(24, 0, 24, 24, c2)
  976.       b.fill_rect(0, 24, 24, 24, c2)
  977.       c1.alpha = c2.alpha = 128
  978.       b.fill_rect(1, 25, 22, 22, c1)
  979.       b.fill_rect(25, 1, 22, 22, c1)
  980.       b.fill_rect(1, 1, 22, 22, c2)
  981.       b.fill_rect(25, 25, 22, 22, c2)
  982.       b.blt(48, 0, b, Rect.new(0, 0, 48, 48))
  983.       b.blt(0, 48, b, Rect.new(0, 0, 96, 48))
  984.       b.blt(96, 0, b, Rect.new(0, 0, 96, 96))
  985.       b.blt(0, 96, b, Rect.new(0, 0, 192, 96))
  986.       b.blt(192, 0, b, Rect.new(0, 0, 192, 192))
  987.       b.blt(0, 192, b, Rect.new(0, 0, 384, 192))
  988.       return b
  989.     end
  990.   end
  991.  
  992. end
  993.  
  994. module BlizzABS
  995.  
  996.   #============================================================================
  997.   # BlizzABS::Combo
  998.   #----------------------------------------------------------------------------
  999.   #  This class represents a Blizz-ABS combo and provides methods for handling.
  1000.   #============================================================================
  1001.  
  1002.   class Combo
  1003.    
  1004.     attr_accessor :id # combo ID
  1005.     attr_accessor :aid # current action ID
  1006.     attr_accessor :ch # character using the combo
  1007.    
  1008.     attr_accessor :time # current time of the current action
  1009.    
  1010.     attr_accessor :player # is the player performing this combo
  1011.     attr_accessor :actor # is an actor performing this combo
  1012.     attr_accessor :enemy # is an enemy performing this combo
  1013.    
  1014.     attr_accessor :commands # stores commands for this combo
  1015.     attr_accessor :moves # stores move commands for this combo
  1016.     attr_accessor :inputs # stores input windows for this combo
  1017.     attr_accessor :variables # stores variables for this combo
  1018.    
  1019.     attr_accessor :total_actions # total number of actions
  1020.     attr_accessor :animation # animation id of the current action
  1021.     attr_accessor :sprite # sprite extension for overlay of the current action
  1022.     attr_accessor :extension # is the sprite name an extension of the character
  1023.     attr_accessor :animation_frames # sprite animation frames
  1024.    
  1025.     attr_accessor :freeze_character # flag to freeze external input on character
  1026.     attr_accessor :ended # has the combo ended
  1027.    
  1028.     #--------------------------------------------------------------------------
  1029.     # Initialization
  1030.     #--------------------------------------------------------------------------
  1031.     def initialize(id, ch)
  1032.       # id of the combo
  1033.       @id = id
  1034.       # id of the current action
  1035.       @aid = 0
  1036.       # character performing combo
  1037.       @ch = nil
  1038.       # initialize variables
  1039.       @variables = []
  1040.       # 10 variables
  1041.       10.times {@variables.push(0)}
  1042.       # initialize inputs
  1043.       @inputs = []
  1044.       # 10 inputs
  1045.       10.times {@inputs.push([[0], 0, 0, true])}
  1046.       # set total number of actions
  1047.       @total_actions = Combos.total_actions(self)
  1048.       # set flag if combo performed by player
  1049.       @player = true#@ch.is_a?(Game_Player)
  1050.       # set flag if combo performed by actor
  1051.       @actor = @ch.is_a?(Game_Actor)
  1052.       # set flag if combo performed by enemy
  1053.       @enemy = @ch.is_a?(Game_Enemy)
  1054.       # begin combo
  1055.       begin_combo(ch)
  1056.     end
  1057.     #--------------------------------------------------------------------------
  1058.     # update
  1059.     #  Updates the combo while it is active
  1060.     #--------------------------------------------------------------------------
  1061.     def update
  1062.       # increase frame counter
  1063.       @time += 1
  1064.       # update commands
  1065.       update_command
  1066.       # update movement
  1067.       update_move
  1068.       # update input
  1069.       update_input
  1070.       # update character
  1071.       update_character
  1072.       # end combo if reached end of commands
  1073.       @ended = true if @commands.size == 0
  1074.     end
  1075.     #--------------------------------------------------------------------------
  1076.     # update_move
  1077.     #  Updates the active movement route
  1078.     #--------------------------------------------------------------------------
  1079.     def update_move
  1080.       if !@ch.moving? && @moves.size > 0
  1081.         @moves.shift if proccess_move(@moves[0])
  1082.       end
  1083.     end
  1084.     #--------------------------------------------------------------------------
  1085.     # update_command
  1086.     #  Updates the active command list
  1087.     #--------------------------------------------------------------------------
  1088.     def update_command
  1089.       while @commands.size > 0 && proccess_command(@commands[0])
  1090.         @commands.shift
  1091.       end
  1092.     end
  1093.     #--------------------------------------------------------------------------
  1094.     # update_input
  1095.     #  Updates the active input windows
  1096.     #--------------------------------------------------------------------------
  1097.     def update_input
  1098.       @inputs.each {|i|
  1099.         # else if not succeeded
  1100.         if !i[3]
  1101.           # decrease counter
  1102.           i[2] -= 1 if i[2] > 0
  1103.           # initialize success
  1104.           i[3] = true
  1105.           i[0].each {|k|
  1106.             # check for success based on trigger type
  1107.             case i[1]
  1108.             when INPress then i[3] = i[3] && Input.press?(k)
  1109.             when INTrigger then i[3] = i[3] && Input.trigger?(k)
  1110.             when INRelease then i[3] = i[3] && Input.release?(k)
  1111.             end}
  1112.         end}
  1113.     end
  1114.     #--------------------------------------------------------------------------
  1115.     # update_character
  1116.     #  Updates the character
  1117.     #--------------------------------------------------------------------------
  1118.     def update_character
  1119.       # freeze character input if flag is set
  1120.       @ch.set_action(1) if @freeze_character
  1121.     end
  1122.     #--------------------------------------------------------------------------
  1123.     # begin_combo
  1124.     #  Begins the combo
  1125.     #--------------------------------------------------------------------------
  1126.     def begin_combo(ch)
  1127.       # set character
  1128.       @ch = ch
  1129.       # setup first action
  1130.       setup_action(1)
  1131.     end
  1132.     #--------------------------------------------------------------------------
  1133.     # setup_action
  1134.     #  Loads data and prepares the character to perform the current action in
  1135.     #  the combo
  1136.     #--------------------------------------------------------------------------
  1137.     def setup_action(id)
  1138.       # set action id
  1139.       @aid = id
  1140.       # set time to zero
  1141.       @time = 0
  1142.       # get commands
  1143.       @commands = Combos.commands(self)
  1144.       # reset movement commands and input windows
  1145.       @moves = []
  1146.       # set animation data
  1147.       @animation, @animation_frames, @sprite, @extension = Combos.anim_data(self)
  1148.       # request combo sprite from player if needed
  1149.       @ch.new_combo_sprite = true if @animation != 0 || @sprite != ''
  1150.     end
  1151.     #--------------------------------------------------------------------------
  1152.     # proccess_command
  1153.     #  Processess a command
  1154.     #  Returns true if command processed, false if not
  1155.     #--------------------------------------------------------------------------
  1156.     def proccess_command(command)
  1157.       # branch based on command type
  1158.       case command[0]
  1159.       when COMScript # script [code]
  1160.         # evaluate script
  1161.         result = eval(command[1])
  1162.       when COMWait # wait [int]
  1163.         # decrease wait counter by 1
  1164.         command[1] -= 1
  1165.         # proceed if wait time is up
  1166.         return command[1] <= 0
  1167.       when COMMove # move [int, int]
  1168.         # add to move commands
  1169.         @moves.push(command)
  1170.       when COMTurn # turn [int]
  1171.         # add to move commands
  1172.         @moves.push(command)
  1173.       when COMJump # jump [int, int]
  1174.         # add to move commands
  1175.         @moves.push(command)
  1176.       when COMAttack # attack
  1177.         # use attack
  1178.         @ch.use_attack
  1179.       when COMSkill # skill [int]
  1180.         # use skill
  1181.         @ch.use_skill($data_skills[command[1]], true)
  1182.       when COMItem # item [int]
  1183.         # use item
  1184.         @ch.use_item($data_items[command[1]], true)
  1185.       when COMDefend # defend [int]
  1186.         # decrease time
  1187.         time = command[1] - 1
  1188.         # use defend
  1189.         @ch.use_defend
  1190.         # set penalty
  1191.         @ch.set_action(1)
  1192.         # if not done with command
  1193.         if time > 0
  1194.           # update the command counter
  1195.           command[1] = time
  1196.           # do not proceed
  1197.           return false
  1198.         end
  1199.       when COMCharacter # character [CH, value]
  1200.         # handle based on sub-command
  1201.         case command[1]
  1202.         when CHSpeed # move speed
  1203.           # set movement speed
  1204.           @ch.move_speed = command[2]
  1205.         when CHFrequency # move frequency
  1206.           # set movement frequency
  1207.           @ch.move_frequency = command[2]
  1208.         when CHSprite # change sprite
  1209.           # set sprite
  1210.           @ch.character_name = @ch.character_name_org = command[2]
  1211.         when CHAnimation # play animation
  1212.           # set animation
  1213.           @ch.animation_id = command[2]
  1214.         when CHFix # direction fix
  1215.           # set direction fix flag
  1216.           @ch.direction_fix = command[2]
  1217.         when CHThrough # through
  1218.           # set through flag
  1219.           @ch.through = command[2]
  1220.         when CHOnTop # always on top
  1221.           # set always on top flag
  1222.           @ch.always_on_top = command[2]
  1223.         when CHOpacity # opacity
  1224.           # set opacity
  1225.           @ch.opacity = command[2]  
  1226.         end
  1227.       when COMInput # create input window [int, [keys], IN, int]
  1228.         # create new input window
  1229.         @inputs[command[1]] = [command[2], command[3], command[4], false]
  1230.       when COMVariable # variable [VAR, value1, '=', VAR, value2]
  1231.         val1 = get_variable(command[1], command[2])
  1232.         val2 = get_variable(command[4], command[5])
  1233.         # branch handling based on operator type
  1234.         case command[3]
  1235.         when '+=' then val2 = val1 + val2 # add
  1236.         when '-=' then val2 = val1 - val2 # subtract
  1237.         when '*=' then val2 = val1 * val2 # multiply
  1238.         when '/=' then val2 = val1 / val2 # divide
  1239.         when '%=' then val2 = val1 % val2 # modulo
  1240.         end
  1241.         # set the variable
  1242.         set_variable(command[1], command[2], val2)
  1243.       when COMCondition # condition [VAR, value1, '==', VAR, value2]
  1244.         # initialize result
  1245.         result = false
  1246.         # initialize values
  1247.         val1 = get_variable(command[1], command[2])
  1248.         val2 = get_variable(command[4], command[5])
  1249.         # branch handling based on operator type
  1250.         case command[3]
  1251.         when '==' # equal to
  1252.           # result is value 1 equal to value 2
  1253.           result = val1 == val2
  1254.         when '!=' # not equal to
  1255.           # result is value 1 not equal to value 2
  1256.           result = val1 != val2
  1257.         when '>' # greater than
  1258.           # result is value 1 greater than to value 2
  1259.           result = val1 > val2
  1260.         when '>=' # greater than or equal to
  1261.           # result is value 1 greater than or equal to value 2
  1262.           result = val1 >= val2
  1263.         when '<' # less than
  1264.           # result is less than value 2
  1265.           result = val1 < val2
  1266.         when '<=' # less than or equal to
  1267.           # result is value 1 less than or equal to value 2
  1268.           result = val1 <= val2
  1269.         end  
  1270.         # if input or script
  1271.         if command[1] == VARInput || command[1] == VARScript
  1272.           # value 1 contains the result
  1273.           result = val1
  1274.           # do not proceed if waiting on an input window
  1275.           if command[1] == VARInput && @inputs[command[2]][2] > 0 && !result
  1276.             return false
  1277.           end
  1278.         end
  1279.         # skip next command if exists and condition not met
  1280.         @commands.delete_at(1) if !result && @commands.size > 1
  1281.       when COMFreeze # freeze input [bool]
  1282.         # set freeze input flag
  1283.         @freeze_character = command[1]
  1284.       when COMCompletion # wait for move completion
  1285.         # proceed if no more moves and character no longer moving
  1286.         return @moves.size == 0 && !@ch.moving?
  1287.       when COMGoTo # go to action [int]
  1288.         raise 'ERROR: Invalid action' if !is_valid_action?(command[1])
  1289.         # setup the action
  1290.         setup_action(command[1])
  1291.         # do not proceed - new set of commands
  1292.         return false
  1293.       when COMAbort # abort
  1294.         # set ended flag
  1295.         @ended = true
  1296.       end
  1297.       return true
  1298.     end
  1299.     #--------------------------------------------------------------------------
  1300.     # proccess_move
  1301.     #  Processess a move command
  1302.     #  Returns true if command fully processed, false if not
  1303.     #--------------------------------------------------------------------------
  1304.     def proccess_move(command)
  1305.       # branch based on command type
  1306.       case command[0]
  1307.       # move
  1308.       when COMMove
  1309.         # get direction
  1310.         dir = get_direction(command[1])
  1311.         # get number of steps remaining
  1312.         steps = command[2] - 1
  1313.         # make character move depending on direction
  1314.         case dir
  1315.         when 1 then @ch.move_lower_left
  1316.         when 2 then @ch.move_down(dir)
  1317.         when 3 then @ch.move_lower_right
  1318.         when 4 then @ch.move_left(dir)
  1319.         when 6 then @ch.move_right(dir)
  1320.         when 7 then @ch.move_upper_left
  1321.         when 8 then @ch.move_up(dir)
  1322.         when 9 then @ch.move_upper_right
  1323.         end
  1324.         # proceed if no more steps
  1325.         return true if steps == 0
  1326.         # update steps counter
  1327.         command[2] = steps
  1328.         # do not proceed as there are more steps to be executed
  1329.         return false
  1330.       # turn
  1331.       when COMTurn
  1332.         # make character turn to face direction
  1333.         @ch.direction = get_direction(command[1])
  1334.       # jump
  1335.       when COMJump
  1336.         # get direction
  1337.         dir = get_direction(command[1])
  1338.         # get range
  1339.         range = command[2]
  1340.         # set jumping direction
  1341.         x, y = BlizzABS::Cache::DirOffsets[dir]
  1342.         # jump into direction with range
  1343.         @ch.jump(x*range, y*range, dir)
  1344.       end
  1345.       # proceed
  1346.       return true
  1347.     end
  1348.     #--------------------------------------------------------------------------
  1349.     # get_variable
  1350.     #  type - variable type
  1351.     #  value - value type
  1352.     #  Returns the variable from the given command data
  1353.     #--------------------------------------------------------------------------
  1354.     def get_variable(type, value)
  1355.       # initialize
  1356.       var = 0
  1357.       # branch handling based on variable type
  1358.       case type
  1359.       when VARGame # game variable
  1360.         # variable is the game variable
  1361.         var = $game_variables[value]
  1362.       when VARCombo # combo variable
  1363.         # variable is the combo variable
  1364.         var = @variables[value]
  1365.       when VARCharacter # character variable
  1366.         # branch handling based on value type
  1367.         case value
  1368.         when VALHp # battler hp
  1369.           # variable is the battler's hp
  1370.           var = @ch.battler.hp
  1371.         when VALSp # battler sp
  1372.           # variable is the battler's hp
  1373.           var = @ch.battler.sp
  1374.         when VALMaxHp # battler max hp
  1375.           # variable is the battler's max hp
  1376.           var = @ch.battler.maxhp
  1377.         when VALMaxSp # battler max sp
  1378.           # variable is the battler's max sp
  1379.           var = @ch.battler.maxsp
  1380.         when VALState # battler states
  1381.           # variable is the amount of states on battler
  1382.           var = @ch.battler.states.size
  1383.         when VALExp # battler exp
  1384.           # variable is the battler's exp
  1385.           var = @ch.battler.exp
  1386.         when VALLevel # battler level
  1387.           # variable is the battler's level
  1388.           var = @ch.battler.level
  1389.         when VALTile # tile id
  1390.           # variable is the character's current tile
  1391.           var = @ch.tile_id
  1392.         when VALDirection # battler direction
  1393.           # variable is the character's current direction
  1394.           var = @ch.direction
  1395.         end
  1396.       when VARInput # input
  1397.         # variable is input success
  1398.         var = @inputs[value][3]
  1399.       when VARConstant # constant
  1400.         # variable is just the value given
  1401.         var = value
  1402.       when VARScript # script
  1403.         # variable is just the script given
  1404.         var = eval(value)
  1405.       end
  1406.       return var
  1407.     end
  1408.     #--------------------------------------------------------------------------
  1409.     # set_variable
  1410.     #  type - variable type
  1411.     #  value - value type
  1412.     #  setvalue - value to set to
  1413.     #  sets the variable from the given command data
  1414.     #--------------------------------------------------------------------------
  1415.     def set_variable(type, value, setvalue)
  1416.       # branch handling based on variable type
  1417.       case type
  1418.       when VARGame # game variable
  1419.         # set game variable to value
  1420.         $game_variables[value] = setvalue
  1421.       when VARCombo # combo variable
  1422.         # set combo variable to value
  1423.         @variables[value] = setvalue
  1424.       when VARCharacter # character variable
  1425.         # branch handling based on value type
  1426.         case value
  1427.         when VALHp # battler hp
  1428.           # set battler's hp to value
  1429.           @ch.battler.hp = setvalue
  1430.         when VALSp # battler sp
  1431.           # set battler's hp to value
  1432.           @ch.battler.sp = setvalue
  1433.         when VALMaxHp # battler max hp
  1434.           # set battler's max hp to value
  1435.           @ch.battler.maxhp = setvalue
  1436.         when VALMaxSp # battler max sp
  1437.           # set battler's max sp to value
  1438.           @ch.battler.maxsp = setvalue
  1439.         when VALExp # battler exp
  1440.           # set battler's exp to value
  1441.           @ch.battler.exp = setvalue
  1442.         when VALLevel # battler level
  1443.           # set battler's level to value
  1444.           @ch.battler.level = setvalue
  1445.         when VALDirection # battler direction to value
  1446.           # set character's current direction
  1447.           @ch.direction = setvalue
  1448.         end
  1449.       end
  1450.     end
  1451.     #--------------------------------------------------------------------------
  1452.     # get_direction
  1453.     #  data - command data
  1454.     #  Returns the 0-10 direction from the given command data
  1455.     #--------------------------------------------------------------------------
  1456.     def get_direction(data)
  1457.       # default direction
  1458.       dir = 0
  1459.       # handle special directions
  1460.       case data
  1461.       when DIR90Right
  1462.         # go back two indices in circle
  1463.         dir = Cache::LoopDir8[(Cache::LoopDir8.index(@ch.direction) + 6) % 8]
  1464.       # when 90 degrees left
  1465.       when DIR90Left
  1466.         # go forward two indices in circle
  1467.         dir = Cache::LoopDir8[(Cache::LoopDir8.index(@ch.direction) + 2) % 8]
  1468.       # when forward
  1469.       when DIRForward
  1470.         # character's direction
  1471.         dir = @ch.direction
  1472.       # when backward
  1473.       when DIRBackward
  1474.         # character's direction
  1475.         dir = 10 - @ch.direction
  1476.       # when toward player
  1477.       when DIRTowardPlayer
  1478.         # get distance to player
  1479.         dx = $game_player.x - @ch.x
  1480.         dy = $game_player.y - @ch.y
  1481.         # direction toward player
  1482.         dir = $BlizzABS.util.get_direction(dx, dy)
  1483.       # when away from player
  1484.       when DIRAwayPlayer
  1485.         # get from to player
  1486.         dx = @ch.x - $game_player.x
  1487.         dy = @ch.y - $game_player.y
  1488.         # direction away from player
  1489.         dir = $BlizzABS.util.get_direction(dx, dy)
  1490.       # Random 4 way direction
  1491.       when DIRRandom4
  1492.         # Random 4 way direction
  1493.         dir = Cache::Dir4[rand(4)]
  1494.       # Random 8 way direction
  1495.       when DIRRandom8
  1496.         # Random 8 way direction
  1497.         dir = Cache::Dir8[rand(8)]
  1498.       # when 45 degrees right
  1499.       when DIR45Right
  1500.         # go to previous index in circle
  1501.         dir = Cache::LoopDir8[(Cache::LoopDir8.index(@ch.direction) + 7) % 8]
  1502.       # when 45degrees left
  1503.       when DIR45Left
  1504.         # go to next index in circle
  1505.         dir = Cache::LoopDir8[(Cache::LoopDir8.index(@ch.direction) + 1) % 8]
  1506.       # no special direction
  1507.       else
  1508.         # set to 0-10 direction
  1509.         dir = data
  1510.       end
  1511.       return dir
  1512.     end
  1513.     #--------------------------------------------------------------------------
  1514.     # is_valid_action?
  1515.     #  aid - id of action
  1516.     #  Tests if aid is a valid action for this combo.
  1517.     #--------------------------------------------------------------------------
  1518.     def is_valid_action?(aid)
  1519.       return aid > 0 && aid <= @total_actions
  1520.     end
  1521.    
  1522.   end
  1523.  
  1524. end
  1525.  
  1526. module BlizzABS
  1527.  
  1528.   #============================================================================
  1529.   # BlizzABS::Processor
  1530.   #----------------------------------------------------------------------------
  1531.   #  This class provides methods for Blizz-ABS handling.
  1532.   #============================================================================
  1533.  
  1534.   class Processor
  1535.    
  1536.     # setting all accessible variables
  1537.     attr_accessor :actors
  1538.     attr_accessor :pets
  1539.     attr_accessor :monsters
  1540.     attr_accessor :AI
  1541.     attr_reader   :player
  1542.     attr_reader   :cache
  1543.     attr_reader   :util
  1544.     attr_reader   :controls
  1545.     #--------------------------------------------------------------------------
  1546.     # Initialization
  1547.     #--------------------------------------------------------------------------
  1548.     def initialize
  1549.       # load player controller
  1550.       @player = Controller.new
  1551.       # create Blizz-ABS Cache
  1552.       @cache = Cache.new
  1553.       # utilities
  1554.       @util = Utility.new
  1555.       # refresh passability data
  1556.       @util.check_map_data if $DEBUG
  1557.       # create handler for player battle input
  1558.       @controls = Controls.new
  1559.       # map actors, summoned pets and summoned monsters
  1560.       @actors, @pets, @monsters = [], [], []
  1561.       # counters for pets and monsters
  1562.       @summon_time = {}
  1563.     end
  1564.     #--------------------------------------------------------------------------
  1565.     # battlers
  1566.     #  Returns actors and all summons from the party.
  1567.     #--------------------------------------------------------------------------
  1568.     def battlers
  1569.       return (@actors + @pets + @monsters)
  1570.     end
  1571.     #--------------------------------------------------------------------------
  1572.     # summons
  1573.     #  Returns only summons from the party.
  1574.     #--------------------------------------------------------------------------
  1575.     def summons
  1576.       return (@pets + @monsters)
  1577.     end
  1578.     #--------------------------------------------------------------------------
  1579.     # update
  1580.     #  Updates Blizz-ABS processes.
  1581.     #--------------------------------------------------------------------------
  1582.     def update
  1583.       # update player battle input
  1584.       @controls.update
  1585.       # update each projectile and trap
  1586.       $BlizzABS.cache.remotes.each {|remote| remote.update}
  1587.       # update summons
  1588.       update_summons
  1589.       # stop if scene is not Scene_Map
  1590.       return if !$scene.is_a?(Scene_Map)
  1591.       # update killed events
  1592.       update_killed
  1593.       # remove expired events from the map
  1594.       event_removal
  1595.       # remove expired summons from the map
  1596.       summon_removal
  1597.       # check special status effects
  1598.       check_special_states
  1599.     end
  1600.     #--------------------------------------------------------------------------
  1601.     # update_summons
  1602.     #  Updates all summons.
  1603.     #--------------------------------------------------------------------------
  1604.     def update_summons
  1605.       # for each summoned battler
  1606.       @summon_time.keys.each {|summon|
  1607.           # decrease counter
  1608.           @summon_time[summon] -= 1
  1609.           # if counter expired
  1610.           remove_summon(summon) if @summon_time[summon] <= 0}
  1611.     end
  1612.     #--------------------------------------------------------------------------
  1613.     # summon_pet
  1614.     #  pet  - the pet to summon
  1615.     #  time - the time to remain
  1616.     #  Executes the summoning of a pet.
  1617.     #--------------------------------------------------------------------------
  1618.     def summon_pet(pet, time)
  1619.       # add pet
  1620.       @pets.push(pet)
  1621.       # set timer
  1622.       @summon_time[pet] = time * 40
  1623.       # stop if scene not Scene_Map or spriteset doesn't exist
  1624.       return if !$scene.is_a?(Scene_Map) || $scene.spriteset == nil
  1625.       # create sprite
  1626.       sprite = Sprite_Character.new($scene.spriteset.viewport1, pet)
  1627.       # add to spriteset handler
  1628.       $scene.spriteset.character_sprites.push(sprite)
  1629.     end
  1630.     #--------------------------------------------------------------------------
  1631.     # summon_monster
  1632.     #  monster - the monster to summon
  1633.     #  time    - the time to remain
  1634.     #  Executes the summoning of a monster.
  1635.     #--------------------------------------------------------------------------
  1636.     def summon_monster(monster, time)
  1637.       # add monster
  1638.       @monsters.push(monster)
  1639.       # set timer
  1640.       @summon_time[monster] = time * 40
  1641.       # stop if scene not Scene_Map or spriteset doesn't exist
  1642.       return if !$scene.is_a?(Scene_Map) || $scene.spriteset == nil
  1643.       # create sprite
  1644.       sprite = Sprite_Character.new($scene.spriteset.viewport1, monster)
  1645.       # add to spriteset handler
  1646.       $scene.spriteset.character_sprites.push(sprite)
  1647.     end
  1648.     #--------------------------------------------------------------------------
  1649.     # remove_summon
  1650.     #  summon - the summoned pet or monster to remove
  1651.     #  Removes the summon from the game.
  1652.     #--------------------------------------------------------------------------
  1653.     def remove_summon(summon)
  1654.       # remove this counter
  1655.       @summon_time.delete(summon)
  1656.       # make it "die"
  1657.       summon.battler.hp = 0
  1658.       # delete from events in case an enemy summoned this summon
  1659.       $game_map.events.delete(summon)
  1660.     end
  1661.     #--------------------------------------------------------------------------
  1662.     # summoned?
  1663.     #  character - the character to check
  1664.     #  Checks if the character was summoned.
  1665.     #--------------------------------------------------------------------------
  1666.     def summoned?(character)
  1667.       return (@pets + @monsters).include?(character)
  1668.     end
  1669.     #--------------------------------------------------------------------------
  1670.     # summoned_actor?
  1671.     #  id - the actor ID
  1672.     #  Checks if the actor was summoned.
  1673.     #--------------------------------------------------------------------------
  1674.     def summoned_actor?(id)
  1675.       return (@pets + @monsters).any? {|character| character.battler.id == id}
  1676.     end
  1677.     #--------------------------------------------------------------------------
  1678.     # update_killed
  1679.     #  Updates data regarding killed battlers.
  1680.     #--------------------------------------------------------------------------
  1681.     def update_killed
  1682.       # deleted killed
  1683.       deleted_killed = []
  1684.       # iterate through all killed
  1685.       $game_system.killed.keys.each {|key|
  1686.           # decrease respawn counter
  1687.           $game_system.killed[key] -= 1
  1688.           # if dead enemy has event code to be executed
  1689.           if key.execute
  1690.             # update interpreter
  1691.             key.update
  1692.           # if respawn counter reached 0
  1693.           elsif $game_system.killed[key] <= 0
  1694.             # remove from map
  1695.             $game_map.events.delete(key.id)
  1696.             # if respawning available
  1697.             if !key.ai.lifeless? &&
  1698.               ($game_system.respawn_time > 0 || key.respawn_point != nil)
  1699.               # add new enemy on old enemy's place
  1700.               $game_map.events[key.id] = respawn_enemy(key)
  1701.             end
  1702.             # this enemy is not "killed" anymore
  1703.             deleted_killed.push(key)
  1704.           end}
  1705.       # remove deleted values
  1706.       deleted_killed.each {|key| $game_system.killed.delete(key)}
  1707.     end
  1708.     #--------------------------------------------------------------------------
  1709.     # event_removal
  1710.     #  Removes expired events from the map including battlers and dropped
  1711.     #  items.
  1712.     #--------------------------------------------------------------------------
  1713.     def event_removal
  1714.       # iterate through all events on the map
  1715.       $game_map.events.values.each {|event|
  1716.           # if event is Map_Enemy
  1717.           if event.is_a?(Map_Enemy)
  1718.             # if event is actually on the map
  1719.             if event.precondition
  1720.               # start removing the enemy if he's dead
  1721.               remove_enemy(event) if !event.valid?
  1722.               # if enemy spriteset missing
  1723.               if event.character_name == '' && event.tile_id < 384
  1724.                 # remove completely
  1725.                 $game_map.events.delete(event.id)
  1726.               end
  1727.             end
  1728.           # if event is dropped item and either item taken or stay time expired
  1729.           elsif event.dropped? && event.terminate
  1730.             # remove completely
  1731.             $game_map.events.delete(event.id)
  1732.           end}
  1733.     end
  1734.     #--------------------------------------------------------------------------
  1735.     # summon_removal
  1736.     #  Removes expired summons from the map.
  1737.     #--------------------------------------------------------------------------
  1738.     def summon_removal
  1739.       # remove all expired pets
  1740.       @pets.clone.each {|p| @pets.delete(p) if p.terminate}
  1741.       # remove all expired monsters
  1742.       @monsters.clone.each {|m| @monsters.delete(m) if m.terminate}
  1743.     end
  1744.     #--------------------------------------------------------------------------
  1745.     # battlers_refresh
  1746.     #  Replaces correctly named events with Blizz-ABS battlers and other
  1747.     #  Blizz-ABS specific events.
  1748.     #--------------------------------------------------------------------------
  1749.     def battlers_refresh
  1750.       # killed battlers array
  1751.       $game_system.reset_abs_data
  1752.       # for all events
  1753.       $game_map.events.keys.each {|i|
  1754.           # execute substitution based on names if the event exists
  1755.           check_event_name(i) if $game_map.events[i] != nil}
  1756.       # now that enemies are created, check connections
  1757.       $game_map.events.keys.each {|i|
  1758.           check_enemy_multi_body(i) if $game_map.events[i].is_a?(Map_Battler)}
  1759.     end
  1760.     #--------------------------------------------------------------------------
  1761.     # check_event_name
  1762.     #  event_id - event ID
  1763.     #  Checks and replaces the event.
  1764.     #--------------------------------------------------------------------------
  1765.     def check_event_name(event_id)
  1766.       # temporary variable
  1767.       event = $game_map.map.events[event_id]
  1768.       # initialize
  1769.       enemy, time, attr, id, group, lock, drop = 0, 5, 0x00, nil, nil, nil, nil
  1770.       hwidth, hheight = 32, 32
  1771.       move = immortal = object = full_passable = no_jump = center_sprite = false
  1772.       no_dmg = false
  1773.       # if lock setting exists
  1774.       if event.name.clone.gsub!(/\\lock\[(\d+)\]/) {"#[$1]"}
  1775.         # get lock setting
  1776.         lock = $1.to_i if event.name.clone.gsub!(/\\lock\[(\d+)\]/) {"#[$1]"}
  1777.       end
  1778.       # set allow jump flag if allow jump disabled
  1779.       no_jump = true if event.name.clone.gsub!('\\nojump') {''}
  1780.       # set center sprite flag if allow jump disabled
  1781.       center_sprite = true if event.name.clone.gsub!('\\cspr') {''}
  1782.       # set center sprite flag if allow jump disabled
  1783.       no_dmg = true if event.name.clone.gsub!('\\nodmg') {''}
  1784.       # if hitbox command exists
  1785.       if event.name.clone.gsub!(/\\hsize\[(\d+),(\d+)\]/) {"#[$1,$2]"}
  1786.         # set hitbox size
  1787.         hwidth = $1.to_i
  1788.         hheight = $2.to_i
  1789.       end
  1790.       # set internal variable to ID (enemy)
  1791.       if event.name.clone.gsub!(/\\[Ee]\[(\d+)\]/) {"#[$1]"}
  1792.         # temporary variable for ID
  1793.         id = $1.to_i
  1794.         # set internal variable to ID (enemy)
  1795.         if event.name.clone.gsub!(/\\[Gg]\[(\d+)\]/) {"#[$1]"}
  1796.           # temporary variable for group
  1797.           group = $1.to_i
  1798.         else
  1799.           # default enemy group
  1800.           group = BlizzABS::Alignments::ENEMY_GROUP
  1801.         end
  1802.       # set internal variable to array of IDs (Respawn Point)
  1803.       elsif event.name.clone.gsub!(/\\respawn\[([\d, ]+)\]/) {"#[$1]"}
  1804.         # temporary variable for array of IDs
  1805.         id = eval("[#{$1}]")
  1806.         # if time setting exists
  1807.         if event.name.clone.gsub!(/\\time\[(\d+)\]/) {"#[$1]"}
  1808.           # get time setting
  1809.           time = $1.to_i
  1810.         end
  1811.       # dropped item
  1812.       elsif event.name.clone.gsub!(/\\drop\[(\d+)\]/) {"#[$1]"}
  1813.         # temporary variable for time
  1814.         drop = $1.to_i
  1815.       end
  1816.       # if id is valid and enemy exists in database
  1817.       if id.is_a?(Numeric) && $data_enemies[id] != nil
  1818.         # set move flag if moving disabled
  1819.         move = true if event.name.clone.gsub!('\\move') {''}
  1820.         # set immortal flag if immortal enemy
  1821.         immortal = true if event.name.clone.gsub!('\\immortal') {''}
  1822.         # set full passability if passable enemy
  1823.         full_passable = true if event.name.clone.gsub!('\\pass') {''}
  1824.         # get AI setup
  1825.         attr, delay, view, hear = setup_enemy_ai(id)
  1826.         # custom AI setup exists
  1827.         custom = (event.name.clone.gsub!(/\\ai\[(\d+)\]/) {"#[$1]"} != nil)
  1828.         # add AI attribute setup if custom
  1829.         attr = eval("0b#{$1}") if custom
  1830.         # replace the real event with the new enemy
  1831.         $game_map.events[event_id] = Map_Enemy.new($game_map.map_id, event,
  1832.             id, group, attr, move, immortal, full_passable, custom,
  1833.             delay, view, hear, no_jump)
  1834.         # increase original enemy count
  1835.         $game_system.add_battler_number(group, 1)
  1836.         # if hide command exists
  1837.         if event.name.clone.gsub!('\\hide') {''}
  1838.           # set flag to hide energy bar
  1839.           $game_map.events[event_id].hide_health = true
  1840.         end
  1841.       # if Respawn Point
  1842.       elsif id.is_a?(Array)
  1843.         # make this event a Respawn Point
  1844.         $game_map.events[event_id].respawn_ids = id
  1845.         # set respawn time
  1846.         $game_map.events[event_id].respawn_time = time
  1847.         # for convenience and easier reference
  1848.         $game_map.respawns.push($game_map.events[event_id])
  1849.       # if dropped item
  1850.       elsif drop != nil
  1851.         # modify event to semi-drop event
  1852.         $game_map.events[event_id].activate_drop_mode(drop * 40)
  1853.       else
  1854.         # if special event renamed back to normal event
  1855.         if !$game_map.events[event_id].is_a?(Game_Event)
  1856.           # create normal event again
  1857.           $game_map.events[event_id] = Game_Event.new($game_map.map_id, event)
  1858.         end
  1859.         # if lock setting doesn't exist
  1860.         if lock == nil
  1861.           # set execution lock time to default
  1862.           $game_map.events[event_id].lock_time = BlizzABS::Config::EVENT_LOCK
  1863.         else
  1864.           # set execution lock time
  1865.           $game_map.events[event_id].lock_time = lock
  1866.         end
  1867.       end
  1868.       $game_map.events[event_id].no_dmg_sprites = no_dmg
  1869.       $game_map.events[event_id].no_jump = no_jump
  1870.       $game_map.events[event_id].center_sprite = center_sprite
  1871.       $game_map.events[event_id].hitbox_width = hwidth
  1872.       $game_map.events[event_id].hitbox_height = hheight
  1873.     end
  1874.     #--------------------------------------------------------------------------
  1875.     # check_enemy_multi_body
  1876.     #  event_id - event ID
  1877.     #  Checks the multi-body setup.
  1878.     #--------------------------------------------------------------------------
  1879.     def check_enemy_multi_body(event_id)
  1880.       # get event
  1881.       event = $game_map.events[event_id]
  1882.       # if event is connected to a body
  1883.       if event.name.clone.gsub!(/\\connect\[(\d+)\]/) {"#[$1]"}
  1884.         # event id
  1885.         id = $1.to_i
  1886.         # body event
  1887.         body = $game_map.events[id]
  1888.         # if body event exists
  1889.         if body != nil
  1890.           # reset ai to body ai
  1891.           attr, delay, view, hear =
  1892.               setup_enemy_ai($game_map.events[id].battler_id)
  1893.           # keep group, move flag, and immortal
  1894.           group, custom, immortal = body.ai.group, body.ai.custom, body.immortal
  1895.           # keep ai and no jump
  1896.           move, nojump = event.move_flag, event.no_jump
  1897.           # create new enemy like body
  1898.           $game_map.events[event_id] = Map_Enemy.new(
  1899.               $game_map.map_id, event, $game_map.events[id].battler_id, group,
  1900.               attr, move, immortal, $game_map.events[id].full_passable, custom,
  1901.               delay, view, hear, nojump)
  1902.           #($game_map.map_id, event,
  1903.           #id, group, attr, move, immortal, full_passable, custom,
  1904.           #delay, view, hear, no_jump)
  1905.           # set battler to body battler
  1906.           $game_map.events[event_id].battler = $game_map.events[id].battler
  1907.           # set body to body event
  1908.           $game_map.events[event_id].body = body
  1909.         end
  1910.       end
  1911.     end
  1912.     #--------------------------------------------------------------------------
  1913.     # setup_enemy_ai
  1914.     #  id - enemy ID
  1915.     #  Returns the AI setup.
  1916.     #--------------------------------------------------------------------------
  1917.     def setup_enemy_ai(id)
  1918.       # get attributes
  1919.       attr = BlizzABS::Enemies.ai(id)
  1920.       # if unique AI setup exists
  1921.       if attr != nil
  1922.         # add AI attribute setup
  1923.         attr = eval("0b#{attr}")
  1924.       else
  1925.         # default AI attribute setup
  1926.         attr = eval("0b#{BlizzABS::Config::AI_DEFAULT_ATTRIBUTES}")
  1927.       end
  1928.       # get unique AI Delay Time
  1929.       delay = BlizzABS::Enemies.delay(id)
  1930.       # get default if not existent
  1931.       delay = BlizzABS::Config::AI_DELAY_TIME if delay == nil
  1932.       # get unique Perception
  1933.       view = BlizzABS::Enemies.perception(id)
  1934.       # if unique perception exists
  1935.       if view != nil
  1936.         # split up
  1937.         view, hear = view
  1938.       else
  1939.         # get defaults
  1940.         view = BlizzABS::Config::VIEW_RANGE
  1941.         hear = BlizzABS::Config::HEARING_RANGE_RATIO
  1942.       end
  1943.       # result
  1944.       return [attr, delay, view, hear]
  1945.     end
  1946.     #--------------------------------------------------------------------------
  1947.     # remove_enemy
  1948.     #  enemy - the killed enemy event
  1949.     #  Processes the after-death period of enemies.
  1950.     #--------------------------------------------------------------------------
  1951.     def remove_enemy(enemy)
  1952.       p enemy.opacity if enemy.battler.dead? && enemy.opacity != 0
  1953.       # stop except if enemy event code is to be executed or enemy is erased
  1954.       return if enemy.execute || enemy.erased || enemy.body != nil
  1955.       # start event code if there is some
  1956.       enemy.start if enemy.trigger == BlizzABS::CETDeath
  1957.       # remove except if code needs to be executed
  1958.       $game_map.events.delete(enemy.id) unless enemy.execute
  1959.       # get all dropped items on the map
  1960.       items = drop_items(enemy)
  1961.       # if not dropping
  1962.       if !BlizzABS::Config::ITEM_DROP
  1963.         # add items into inventory
  1964.         items.each {|item|
  1965.             case item
  1966.             when RPG::Weapon then $game_party.gain_weapon(item.id, 1)
  1967.             when RPG::Armor then $game_party.gain_armor(item.id, 1)
  1968.             when RPG::Item then $game_party.gain_item(item.id, 1)
  1969.             end}
  1970.         # clear items
  1971.         items = []
  1972.       end
  1973.       # experience result
  1974.       exp_result(enemy)
  1975.       # gold result
  1976.       gold = gold_result(enemy)
  1977.       # if not using drop gold mode
  1978.       if BlizzABS::Config::GOLD_DROP == ''
  1979.         # just increase gold
  1980.         $game_party.gain_gold(gold)
  1981.       # if dropping any gold
  1982.       elsif gold > 0
  1983.         # add gold to items
  1984.         items = [gold] + items
  1985.       end
  1986.       # execute all additional enemy results
  1987.       additional_result(enemy)
  1988.       # if using corpses
  1989.       if BlizzABS::Config::CORPSES
  1990.         # if using empty corpses or any drop exists
  1991.         if BlizzABS::Config::EMPTY_CORPSES || items.size > 0
  1992.           # create a corpse dropped items
  1993.           drop_event(items, enemy.real_x, enemy.real_y, enemy)
  1994.         end
  1995.       else
  1996.         # create all necessary dropped items
  1997.         items.each {|item| drop_event([item], enemy.real_x, enemy.real_y)}
  1998.       end
  1999.     end
  2000.     #--------------------------------------------------------------------------
  2001.     # drop_items
  2002.     #  enemy - the killed enemy event
  2003.     #  Returns array of items that will be dropped.
  2004.     #--------------------------------------------------------------------------
  2005.     def drop_items(enemy)
  2006.       # initialize array
  2007.       items = []
  2008.       # if using Multi-Drop from Tons of Add-ons
  2009.       if $tons_version != nil && $tons_version >= 5.98 &&
  2010.           TONS_OF_ADDONS::MULTI_DROP
  2011.         # gets all dropped items
  2012.         items += BlizzCFG.dropped_items(enemy.battler)
  2013.       # if got item
  2014.       elsif rand(100) < enemy.battler.treasure_prob
  2015.         # if enemy drops item
  2016.         if enemy.battler.item_id > 0
  2017.           # set ID
  2018.           items.push($data_items[enemy.battler.item_id])
  2019.         # if enemy drops weapon
  2020.         elsif enemy.battler.weapon_id > 0
  2021.           # set ID
  2022.           items.push($data_weapons[enemy.battler.weapon_id])
  2023.         # if enemy drops armor
  2024.         elsif enemy.battler.armor_id > 0
  2025.           # set ID
  2026.           items.push($data_armors[enemy.battler.armor_id])
  2027.         end
  2028.       end
  2029.       # result
  2030.       return items
  2031.     end
  2032.     #--------------------------------------------------------------------------
  2033.     # exp_result
  2034.     #  enemy - the killed enemy event
  2035.     #  Processes EXP gain after the death of an enemy.
  2036.     #--------------------------------------------------------------------------
  2037.     def exp_result(enemy)
  2038.       # stop if enemy gives no EXP
  2039.       return 0 if enemy.exp == 0
  2040.       # get EXP
  2041.       exp = enemy.exp
  2042.       # if Tons is there
  2043.       if $tons_version != nil
  2044.         # if version is correct and using Different Difficulties
  2045.         if $tons_version >= 6.4 && TONS_OF_ADDONS::DIFFICULTY
  2046.           # multiply gained gold
  2047.           exp = exp * $game_system.exp_rate / 100
  2048.         end
  2049.         # if version is correct and using Passive Skills
  2050.         if $tons_version >= 6.5 && $game_system.PASSIVE_SKILLS
  2051.           # multiply gained gold with each actor's rate
  2052.           $game_party.actors.each {|actor| exp *= actor.exp_rate}
  2053.           exp = exp.to_i
  2054.         end
  2055.       end
  2056.       # bonus exp if bonus or unshared and last attacked battler exists
  2057.       if Config::EXP_MODE > 0 && enemy.last_hit_by != nil
  2058.         bat = enemy.last_hit_by
  2059.         bat.exp += exp if bat.is_a?(Game_Actor) && !bat.cant_get_exp?
  2060.       end
  2061.       # shared exp if bonus or shared, but exp is split evenly among party
  2062.       if Config::EXP_MODE < 2
  2063.         ind_exp = exp / $game_party.actors.size
  2064.         # iterate through all actors and pets
  2065.         ($BlizzABS.actors + $BlizzABS.pets).each {|b|
  2066.             # increase EXP if actor is valid and actor can get EXP
  2067.             b.battler.exp += ind_exp if b.valid? && !b.battler.cant_get_exp?}
  2068.       end
  2069.       # return exp value for further processing
  2070.       return exp
  2071.     end
  2072.     #--------------------------------------------------------------------------
  2073.     # gold_result
  2074.     #  enemy - the killed enemy event
  2075.     #  Processes gold gain after the death of an enemy.
  2076.     #--------------------------------------------------------------------------
  2077.     def gold_result(enemy)
  2078.       # stop if enemy drops no gold
  2079.       return 0 if enemy.gold == 0
  2080.       # get gold
  2081.       gold = enemy.gold
  2082.       # if Tons is there
  2083.       if $tons_version != nil
  2084.         # if version is correct and using Different Difficulties
  2085.         if $tons_version >= 6.4 && TONS_OF_ADDONS::DIFFICULTY
  2086.           # multiply gained gold
  2087.           gold = gold * $game_system.gold_rate / 100
  2088.         end
  2089.         # if version is correct and using Passive Skills
  2090.         if $tons_version >= 6.5 && $game_system.PASSIVE_SKILLS
  2091.           # multiply gained gold with each actor's rate
  2092.           $game_party.actors.each {|actor| gold *= actor.gold_rate}
  2093.           gold = gold.to_i
  2094.         end
  2095.       end
  2096.       # return gold value for further processing
  2097.       return gold
  2098.     end
  2099.     #--------------------------------------------------------------------------
  2100.     # additional_result
  2101.     #  enemy - the killed enemy event
  2102.     #  Processes additional gains after the death of an enemy.
  2103.     #--------------------------------------------------------------------------
  2104.     def additional_result(enemy)
  2105.       # if Tons of Add-ons there and EQUAP active
  2106.       if $tons_version != nil && $tons_version >= 7.32 &&
  2107.           TONS_OF_ADDONS::EQUAP_SKILLS
  2108.         # get AP result
  2109.         ap = BlizzCFG.gainap(enemy.id)
  2110.         # for each actor
  2111.         $BlizzABS.battlers.each {|battler|
  2112.             # if actor can gain AP
  2113.             if battler.valid? && (!battler.battler.dead? || GAIN_DEAD)
  2114.               # add AP
  2115.               battler.battler.add_ap(ap)
  2116.             end}
  2117.       end
  2118.     end
  2119.     #--------------------------------------------------------------------------
  2120.     # respawn_enemy
  2121.     #  enemy - the killed enemy event
  2122.     #  Processes the respawn of a dead enemy.
  2123.     #--------------------------------------------------------------------------
  2124.     def respawn_enemy(enemy)
  2125.       # create new enemy on old enemy's template
  2126.       new_enemy = Map_Enemy.new($game_map.map_id, enemy)
  2127.       # gets the respawn coordinates
  2128.       x, y = get_respawn_coordinates(enemy)
  2129.       # no respawn position found
  2130.       return nil if x == nil || y == nil
  2131.       # move enemy to position
  2132.       new_enemy.moveto(x, y)
  2133.       # if scene is Scene_Map and spriteset exists
  2134.       if $scene.is_a?(Scene_Map) && $scene.spriteset != nil
  2135.         # create sprite for respawned enemy
  2136.         sprite = Sprite_Character.new($scene.spriteset.viewport1, new_enemy)
  2137.         # set respawning flag
  2138.         sprite.respawning = true
  2139.         # add new sprite into spriteset
  2140.         $scene.spriteset.character_sprites.push(sprite)
  2141.       end
  2142.       # enemy is invisible at first
  2143.       new_enemy.opacity = 0
  2144.       # return new enemy
  2145.       return new_enemy
  2146.     end
  2147.     #--------------------------------------------------------------------------
  2148.     # get_respawn_coordinates
  2149.     #  enemy - the killed enemy event
  2150.     #  Gets the respawning coordinates for the new enemy.
  2151.     #--------------------------------------------------------------------------
  2152.     def get_respawn_coordinates(enemy)
  2153.       # if fixed Respawn Point exists
  2154.       if enemy.respawn_point != nil
  2155.         # coordinates of the Respawn Point
  2156.         return [enemy.respawn_point.x, enemy.respawn_point.y]
  2157.       end
  2158.       # get virtual map passability
  2159.       v_map, passables = $game_map.virtual_passability, []
  2160.       # get pixel movement rate
  2161.       pix = $BlizzABS.pixel
  2162.       # find all passable tiles
  2163.       (0...v_map.xsize).each {|x| (0...v_map.ysize).each {|y|
  2164.           # if passable and enemy may respawn and no event on position
  2165.           if v_map[x, y] != 0x00 && !BlizzABS::Config::NO_ENEMY_TAGS.include?(
  2166.               $game_map.terrain_tag(x, y)) && $game_map.event_passable?(x, y)
  2167.             passables.push([x, y])
  2168.           end}}
  2169.       # random possibnle coordinates on the map
  2170.       return passables[rand(passables.size)]
  2171.     end
  2172.     #--------------------------------------------------------------------------
  2173.     # check_special_states
  2174.     #  Checks for several Tons of Add-ons effects.
  2175.     #--------------------------------------------------------------------------
  2176.     def check_special_states
  2177.       # if Tons of Add-ons is there
  2178.       if $tons_version != nil
  2179.         # if version is sufficient and using Auto-Revive
  2180.         if $tons_version >= 1.6 && $game_system.AUTO_REVIVE
  2181.           # for each actor
  2182.           $BlizzABS.battlers.each {|actor|
  2183.               # if battler exists and dead and having Auto-Revive
  2184.               if actor.battler != nil && actor.battler.hp == 0 &&
  2185.                   AUTO_REVIVE_IDS.any? {|i| actor.battler.states.include?(i)}
  2186.                 # execute
  2187.                 actor.battler.hp += actor.battler.maxhp / 5
  2188.                 # remove Auto-Revive and Dead
  2189.                 (AUTO_REVIVE_IDS + [DEAD_ID]).each {|i|
  2190.                     actor.battler.remove_state(i)}
  2191.                 # set animation
  2192.                 actor.animation_id = REVIVE_ANIMATION_ID
  2193.                 # set revival text
  2194.                 actor.battler.damage = REVIVE_TEXT
  2195.                 # display text
  2196.                 actor.battler.damage_pop = true
  2197.               end}
  2198.         end
  2199.         # if version is sufficient and using Fury Status
  2200.         if $tons_version >= 6.41 && $game_system.FURY_STATUS
  2201.           # execute Fury Status change
  2202.           BlizzCFG.fury_execution
  2203.         end
  2204.       end
  2205.     end
  2206.     #--------------------------------------------------------------------------
  2207.     # pixel
  2208.     #  Safe method to retreive the pixel movement rate.
  2209.     #  (how many movement tiles fit into a 32x32 tile)
  2210.     #--------------------------------------------------------------------------
  2211.     def pixel
  2212.       return ($game_system == nil ? 1 : 2 ** $game_system.pixel_rate)
  2213.     end
  2214.     #--------------------------------------------------------------------------
  2215.     # init_caterpillar
  2216.     #  Serves for initialization of the caterpillar.
  2217.     #--------------------------------------------------------------------------
  2218.     def init_caterpillar
  2219.       # add player controlled character
  2220.       @actors = [$game_player]
  2221.       # MAX-PARTY size - 1 times create actor
  2222.       (1...Config::MAX_PARTY).each {|i| @actors.push(Map_Actor.new(i))}
  2223.       # refresh all battlers
  2224.       $game_player.refresh
  2225.       # if not very beginning of the game
  2226.       if $game_map.map_id != nil && $game_map.map_id > 0
  2227.         # move all actors to the player's position
  2228.         $game_player.moveto($game_player.x / pixel, $game_player.y / pixel)
  2229.       end
  2230.     end
  2231.     #--------------------------------------------------------------------------
  2232.     # can_execute?
  2233.     #  ch     - the character in action
  2234.     #  target - target
  2235.     #  act    - action data
  2236.     #  Returns whether a target is in attack/skill/item range.
  2237.     #--------------------------------------------------------------------------
  2238.     def can_execute?(ch, target = false, act = false)
  2239.       # no if paralyzed or charging
  2240.       return false if ch.restriction == 4
  2241.       # argument correction
  2242.       act = ch.ai.act if act == false
  2243.       target = ch.ai.target if target == false
  2244.       # stop if defend action
  2245.       return true if act.defend?
  2246.       # stop if no target exists or target is invalid
  2247.       return false if target == nil || !target.valid?
  2248.       # if attack
  2249.       if act.attack?
  2250.         # target enemy and non-dead
  2251.         enemy, dead = true, false
  2252.       else
  2253.         # get scope
  2254.         scope = (act.skill? ? $data_skills : $data_items)[act.id].scope
  2255.         # execute allowed if targeting self
  2256.         return true if scope == 0 || scope == 7
  2257.         # determine target alignment, dead flag and all flag
  2258.         enemy, dead, all = $BlizzABS.util.get_scope_data(scope)
  2259.       end
  2260.       # temporary variables
  2261.       ai, d = ch.ai, act.range
  2262.       # determine whether actor or enemy for easier reference
  2263.       if ch.is_a?(Map_Actor)
  2264.         # decide target group
  2265.         group = (ch != $game_player && ((ch.restriction == 3) == enemy)) ?
  2266.             ai.positive : ai.negative
  2267.       else
  2268.         # determine target class group on confusion
  2269.         group = (((ch.restriction == 3) == enemy) ? ai.positive : ai.negative)
  2270.       end
  2271.       # if attack
  2272.       if act.attack?
  2273.         # get attack affection area
  2274.         area = $BlizzABS.util.get_attack_area(ch, d, act.type)
  2275.       else
  2276.         # get skill/item affection area
  2277.         area = $BlizzABS.util.get_skillitem_area(ch, d, act.type, scope)
  2278.       end
  2279.       # can target be hit considering all conditions
  2280.       return ((dead == target.battler.dead?) && @util.intersection(area,
  2281.           target.hitbox))
  2282.     end
  2283.     #--------------------------------------------------------------------------
  2284.     # attack_process
  2285.     #  ch - the character in action
  2286.     #  Processes ABS attack setup and handling for actors and enemies.
  2287.     #--------------------------------------------------------------------------
  2288.     def attack_process(ch)
  2289.       # temporary variable
  2290.       ai = ch.ai
  2291.       # determine whether actor or enemy for easier reference
  2292.       if ch.is_a?(Map_Actor)
  2293.         # decide target group
  2294.         group = ((ch != $game_player && ch.restriction == 3)) ?
  2295.             ai.positive : ai.negative
  2296.         # determine range
  2297.         d = Weapons.range(ch.battler.weapon_id)
  2298.         d = 1 if d < 1
  2299.         # determine type
  2300.         type = Weapons.type(ch.battler.weapon_id)
  2301.         # determine charge
  2302.         charge = Weapons.charge(ch.battler.weapon_id)
  2303.         # determine projectile speed
  2304.         projectile_speed = Weapons.projectile_speed(ch.battler.weapon_id)
  2305.       else
  2306.         # determine target group depending on confusion
  2307.         group = (ch.restriction == 3 ? ai.positive : ai.negative)
  2308.         # determine range
  2309.         d = Enemies.range(ch.battler_id)
  2310.         d = 1 if d < 1
  2311.         # determine type
  2312.         type = Enemies.type(ch.battler_id)
  2313.         # determine charge
  2314.         charge = Enemies.charge(ch.battler_id)
  2315.         # determine charge
  2316.         charge[0] = BlizzABS::CHARGEMove if charge[0] == BlizzABS::CHARGETrigger
  2317.         # determine projectile speed
  2318.         projectile_speed = Weapons.projectile_speed(ch.battler_id)
  2319.       end
  2320.       # if item shooting type
  2321.       if type == BOW_ARROW
  2322.         # temporary variable
  2323.         ids = Weapons.consume(ch.battler.weapon_id)
  2324.         # if no more items
  2325.         if !ids.include?(ch.battler.item) ||
  2326.             $game_party.item_number(ch.battler.item) == 0
  2327.           # can't use
  2328.           return false
  2329.         end
  2330.       end
  2331.       # if not charging already
  2332.       if charge[0] != CHARGENone && !ch.charging?
  2333.         # setup charging
  2334.         ch.setup_charge(ch, charge)
  2335.         # not used yet
  2336.         return false
  2337.       end
  2338.       # create affection area depending on attack type
  2339.       case type
  2340.       when SWORD, SPEAR, FLAIL # sword attack
  2341.         # get attack affection area
  2342.         area = $BlizzABS.util.get_attack_area(ch, d, type)
  2343.       when BOOMERANG # returning projectile attack
  2344.         # decide spriteset
  2345.         spriteset = ch.is_a?(Map_Actor) ?
  2346.             BlizzABS::SPRProjWeapon + ch.battler.weapon_id.to_s :
  2347.             BlizzABS::SPRProjEnemy + ch.battler_id.to_s
  2348.         # create returning projectile
  2349.         proj = Map_Projectile.new(spriteset, ch, 0, d, projectile_speed,
  2350.             REMReturning, group)
  2351.       when BOW # projectile attack
  2352.         # decide spriteset
  2353.         spriteset = ch.is_a?(Map_Actor) ?
  2354.             BlizzABS::SPRProjWeapon + ch.battler.weapon_id.to_s :
  2355.             BlizzABS::SPRProjEnemy + ch.battler_id.to_s
  2356.         # create returning projectile
  2357.         proj = Map_Projectile.new(spriteset, ch, 0, d, projectile_speed,
  2358.             REMNormal, group)
  2359.       when BOW_ARROW # item consuming projectile
  2360.         # remove one item from inventory
  2361.         $game_party.lose_item(ch.battler.item, 1)
  2362.         # temporary variable
  2363.         item = $data_items[ch.battler.item]
  2364.         # get item explosion data
  2365.         explode = Items.type(item.id)
  2366.         # if explosion exists
  2367.         if explode[1] != EXPLNone
  2368.           # fix the missing explosion animation error
  2369.           explode[2] = 0 if explode[2] == nil
  2370.           # create projectile from exploding item with weapon attack effect
  2371.           proj = Map_Projectile.new(BlizzABS::SPRProjItem + item.id.to_s, ch,
  2372.               item.id, d, projectile_speed, REMShotItem, group, false,
  2373.               explode[1, 3])
  2374.         else
  2375.           # create projectile from item with weapon attack effect
  2376.           proj = Map_Projectile.new(BlizzABS::SPRProjItem + item.id.to_s, ch,
  2377.               item.id, d, projectile_speed, REMShotItem, group)
  2378.         end
  2379.       when SHURIKEN # self consuming weapon
  2380.         # temporary variable
  2381.         weapon = $data_weapons[ch.battler.weapon_id]
  2382.         # unequip last weapon if no more weapons in inventory
  2383.         ch.battler.equip(0, 0) if $game_party.weapon_number(weapon.id) == 0
  2384.         # remove one weapon from inventory
  2385.         $game_party.lose_weapon(weapon.id, 1)
  2386.         # self shooting weapon, create projectile from weapon
  2387.         proj = Map_Projectile.new(BlizzABS::SPRProjWeapon + weapon.id.to_s, ch,
  2388.             weapon.id, d, projectile_speed, REMShotWeapon, group)
  2389.       end
  2390.       # if projectile fired
  2391.       if proj != nil
  2392.         # add projectile to buffer
  2393.         $BlizzABS.cache.remotes.push(proj)
  2394.         # used
  2395.         return true
  2396.       end
  2397.       # iterate through all battlers
  2398.       ($game_map.battlers + $BlizzABS.battlers).each {|battler|
  2399.           # if target can be hit considering all conditions
  2400.           if battler.battler != nil && group.include?(battler.ai.group) &&
  2401.               (battler != ch || group == ai.positive) &&
  2402.               !battler.battler.dead? && @util.intersection(area,
  2403.               battler.hitbox)
  2404.             # execute attack
  2405.             battler.attack_effect(ch, ch.battler)
  2406.             # clear damage displays
  2407.             battler.battler.damage, battler.battler.damage_pop = nil, false
  2408.           end}
  2409.       # enemies were attacked
  2410.       return true
  2411.     end
  2412.     #--------------------------------------------------------------------------
  2413.     # skillitem_process
  2414.     #  ch - the skill/item using character
  2415.     #  object - the skill or item that is being used
  2416.     #  Processes skill and item use in Blizz-ABS on the map. One method is
  2417.     #  used for both since the process is almost identical for both objects.
  2418.     #--------------------------------------------------------------------------
  2419.     def skillitem_process(ch, object)
  2420.       # determine whether skill or item for easier reference
  2421.       case object
  2422.       when RPG::Skill
  2423.         skill, d, time = true, Skills.range(object.id), Skills.trap(object.id)
  2424.         type, charge = Skills.type(object.id), Skills.charge(object.id)
  2425.         projectile_speed = Skills.projectile_speed(object.id)
  2426.         spriteset = BlizzABS::SPRProjSkill
  2427.       when RPG::Item
  2428.         skill, d, time = false, Items.range(object.id), Items.trap(object.id)
  2429.         type, charge = Items.type(object.id), Items.charge(object.id)
  2430.         projectile_speed = Items.projectile_speed(object.id)
  2431.         spriteset = BlizzABS::SPRProjItem
  2432.       end
  2433.       # fix the missing explosion animation error
  2434.       type[2] = 0 if type[1] != EXPLNone && type[2] == nil
  2435.       # if enemy
  2436.       if ch.is_a?(Map_Enemy) && charge[0] == CHARGETrigger
  2437.         # correct charge type
  2438.         charge[0] = CHARGEMove
  2439.       end
  2440.       # if not charging already and no selection data
  2441.       if charge[0] != CHARGENone && !ch.charging? &&
  2442.           $game_temp.select_data == nil
  2443.         # setup charging
  2444.         ch.setup_charge(object, charge)
  2445.         # not used yet
  2446.         return false
  2447.       end
  2448.       # if summoning
  2449.       if type[0] == SUMMON
  2450.         # nobody except actors can summon with caterpillar turned on
  2451.         return false unless ch.is_a?(Map_Actor) && $game_system.caterpillar
  2452.         # get summoning data
  2453.         summon = (skill ? Skills.summon(object.id) : Items.summon(object.id))
  2454.         # if summon ID or time is 0
  2455.         if summon[0] == SUMMONNone || summon[1] == 0 || summon[2] == 0
  2456.           # no summoning
  2457.           return false
  2458.         end
  2459.         # no summoning if already summoned
  2460.         return false if (@pets + @monsters).any? {|b| b.battler_id == summon[1]}
  2461.         # if any summon limit reached
  2462.         if summon[0] == SUMMONPet && @pets.size >= BlizzABS::Config::MAX_PETS ||
  2463.             summon[0] == SUMMONMonster &&
  2464.             @monsters.size >= BlizzABS::Config::MAX_MONSTERS ||
  2465.              @pets.size + @monsters.size >= BlizzABS::Config::MAX_SUMMONS
  2466.           # no summoning
  2467.           return false
  2468.         end
  2469.         # create new map actor
  2470.         new_battler = Map_Actor.new(summon[1])
  2471.         # if pet
  2472.         if summon[0] == SUMMONPet
  2473.           # summon pet
  2474.           summon_pet(new_battler, summon[2])
  2475.         # if monster
  2476.         elsif summon[0] == SUMMONMonster
  2477.           # summon monster
  2478.           summon_monster(new_battler, summon[2])
  2479.         else
  2480.           # something's not right here, no summoning
  2481.           return false
  2482.         end
  2483.         # get pixel movement rate
  2484.         pix = $BlizzABS.pixel
  2485.         # move to correct position
  2486.         new_battler.moveto(ch.x / pix, ch.y / pix)
  2487.         # set correct battler
  2488.         new_battler.battler = $game_actors[summon[1]]
  2489.         # heal the battler completely
  2490.         new_battler.battler.recover_all
  2491.         # return to caterpillar first
  2492.         new_battler.cindex, new_battler.ai.state = nil, AI::Return
  2493.         # refresh display
  2494.         new_battler.refresh
  2495.         # set animation
  2496.         new_battler.animation_id = object.animation2_id
  2497.         # summon successful
  2498.         return true
  2499.       end
  2500.       # skill/item used (can be a common event call) if no target scope
  2501.       return true if object.scope == 0
  2502.       # if targeting self
  2503.       if object.scope == 7
  2504.         # if skill
  2505.         if skill
  2506.           # execute skill upon user
  2507.           ch.skill_effect(ch, ch.battler, object)
  2508.           # check special skill effects
  2509.           self.check_special_skills(ch, [ch], object)
  2510.         else
  2511.           # execute item upon user
  2512.           ch.item_effect(ch, ch.battler, object)
  2513.         end
  2514.         # clear damage displays
  2515.         ch.battler.damage, ch.battler.damage_pop = nil, false
  2516.         # skill/item used
  2517.         return true
  2518.       end
  2519.       # correct range
  2520.       d = 1 if d < 1
  2521.       # determine target alignment, dead flag and all flag
  2522.       enemy, dead, all = $BlizzABS.util.get_scope_data(object.scope)
  2523.       # doesn't target all and no death roulette initially
  2524.       target_all = false
  2525.       # if Tons is there and skill process
  2526.       if $tons_version != nil && $tons_version >= 6.02 && skill
  2527.         # if version is correct and Target 'em all! is being used for this skill
  2528.         if $game_system.TARGET_EM_ALL && FULL_TARGET_IDS.include?(object.id)
  2529.           # targets all and forces all flag
  2530.           target_all = all = true
  2531.         end
  2532.       end
  2533.       # temporary variable
  2534.       ai = ch.ai
  2535.       # determine whether actor or enemy for easier reference
  2536.       if ch.is_a?(Map_Actor)
  2537.         # decide target group
  2538.         group = (((ch == $game_player || ch.restriction != 3) == enemy) ?
  2539.             ai.negative : ai.positive)
  2540.       else
  2541.         # determine target group depending on confusion
  2542.         group = (((ch.restriction == 3) == enemy) ? ai.positive : ai.negative)
  2543.       end
  2544.       # selection only if player using selectable skill/item and not charging
  2545.       if ch == $game_player && $game_temp.select_data == nil &&
  2546.           (charge[0] == CHARGENone || charge[0] != CHARGENone &&
  2547.           ch.charged?) && (target_all || type[0] == HOMING ||
  2548.           type[0] == DIRECT || type[0] == BEAM && all)
  2549.         # temporary variable, selection skill/item
  2550.         handling = 0
  2551.       else
  2552.         # set handling for projectile skill/item or direct skill/item
  2553.         handling = ((type[0] == SHOOT || type[0] == HOMING ||
  2554.             type[0] == TRAP || type[0] == TIMED) ? 1 : 2)
  2555.       end
  2556.       # depending on handling
  2557.       case handling
  2558.       when 0 # selection
  2559.         # create circle shape data
  2560.         area = $BlizzABS.util.get_circle_area(ch, d)
  2561.         # create fullscreen rectangle
  2562.         screen = $BlizzABS.util.get_fullscreen_area
  2563.         # no use if scene not Scene_Map or spriteset doesn't exist
  2564.         return false if !$scene.is_a?(Scene_Map) || $scene.spriteset == nil
  2565.         # get all selectable map battlers
  2566.         available = $scene.spriteset.character_sprites.find_all {|sprite|
  2567.             sprite.character.is_a?(Map_Battler) &&
  2568.             !sprite.character.is_a?(Map_Remote) &&
  2569.             group.include?(sprite.character.ai.group) &&
  2570.             (sprite.character != ch || group == ai.positive) &&
  2571.             can_be_hit(sprite.character, dead, type, all, screen, area)}
  2572.         # no use if no selectable targets
  2573.         return false if available.size == 0
  2574.         # sort selectable targets by coordinates
  2575.         available.sort {|a, b| b.y > a.y ? 1 : b.y < a.y ? -1 : (b.x <=> a.x)}
  2576.         # setup select interuption
  2577.         $game_temp.select_data = [object, d * 32, type[0], available]
  2578.         # don't use skill/item yet
  2579.         return false
  2580.       when 1 # projectile
  2581.         # decide process branch depending on skill type
  2582.         case type[0]
  2583.         # set normal or break-through projectile data
  2584.         when SHOOT
  2585.           # if break-through
  2586.           if all
  2587.             # set break-through projectile skill or item
  2588.             projectype = (skill ? REMBreakSkill : REMBreakSkill)
  2589.           else
  2590.             # set normal projectile skill or item
  2591.             projectype = (skill ? REMNormalSkill : REMNormalItem)
  2592.           end
  2593.           # set range
  2594.           targets = [d]
  2595.         # homing skill/item
  2596.         when HOMING
  2597.           # get circle area
  2598.           area = $BlizzABS.util.get_circle_area(ch, d)
  2599.           # create fullscreen rectangle
  2600.           screen = $BlizzABS.util.get_fullscreen_area
  2601.           # get all targets that can be hit
  2602.           targets = ($game_map.battlers + $BlizzABS.battlers).find_all {|b|
  2603.               can_be_hit(b, dead, type, all, screen, area)}
  2604.           # if targetting everybody
  2605.           if target_all
  2606.             # reflection possible on everybody
  2607.             other = targets.clone
  2608.           else
  2609.             # reflection possible on non-target group
  2610.             other = targets.find_all {|b| !group.include?(b.ai.group)}
  2611.             # if predefined target exists
  2612.             if !all && ai.target != nil
  2613.               # set predefined target
  2614.               targets = [ai.target]
  2615.             else
  2616.               # set possible targets
  2617.               targets = targets.find_all {|b| group.include?(b.ai.group)}
  2618.             end
  2619.           end
  2620.           # set homing projectile type
  2621.           projectype = (skill ? REMInitSkill : REMInitItem)
  2622.         # homing skill/item
  2623.         when TRAP
  2624.           # targets for selection, other targets
  2625.           targets, other = [], []
  2626.           # set homing projectile type
  2627.           projectype = (skill ? REMTrapSkill : REMTrapItem)
  2628.         # homing skill/item
  2629.         when TIMED
  2630.           # targets for selection, other targets
  2631.           targets, other = [], []
  2632.           # set homing projectile type
  2633.           projectype = (skill ? REMTimedSkill : REMTimedItem)
  2634.         end
  2635.       when 2 # direct
  2636.         # if direct skill or shockwave skill
  2637.         if type[0] == DIRECT
  2638.           # get circle area
  2639.           area = $BlizzABS.util.get_circle_area(ch, d)
  2640.         # if beam skill (fullscreen skill that does not target all)
  2641.         elsif !all
  2642.           # get affection area rectangle
  2643.           area = $BlizzABS.util.get_front_area(ch, d)
  2644.           # initialize
  2645.           this = nil
  2646.           # if scene is Scene_Map and spriteset exists
  2647.           if $scene.is_a?(Scene_Map) && $scene.spriteset != nil
  2648.             # find the sprite of this character
  2649.             $scene.spriteset.character_sprites.each {|spr|
  2650.                 if spr.character == ch
  2651.                   this = spr
  2652.                   break
  2653.                 end}
  2654.           end
  2655.           # if sprite exists
  2656.           if this != nil
  2657.             # create sprite
  2658.             sprite = Sprite.new($scene.spriteset.viewport1)
  2659.             # try to
  2660.             begin
  2661.               # load the characterset file
  2662.               sprite.bitmap = RPG::Cache.character(object.icon_name, 0)
  2663.               # temporary variables
  2664.               w1, h = sprite.bitmap.width, sprite.bitmap.height
  2665.             # if failed
  2666.             rescue
  2667.               # get width and height
  2668.               w1, h = 24, d*32
  2669.               # create bitmap
  2670.               sprite.bitmap = Bitmap.new(w1, h)
  2671.               # get image from cache
  2672.               b = $BlizzABS.cache.image('beam1')
  2673.               # copy the beam image
  2674.               (0...h).each {|i|
  2675.                   a = (i < h/2 ? i**2*2 : (h-i-1)**2*2)
  2676.                   a = 255 if a > 255
  2677.                   sprite.bitmap.blt(0, i, b, Rect.new(0, 0, b.width, b.height), a)}
  2678.             end
  2679.               w2 = case ch.direction
  2680.               when 6 then 16-w1/2
  2681.               else
  2682.                 w1/2+16
  2683.               end
  2684.             # set sprite position, rotation and offsets depending on facing
  2685.             case ch.direction
  2686.             when 2
  2687.               sprite.angle, sprite.ox = 0, w1/2
  2688.               sprite.x, sprite.y, sprite.z = this.x, this.y, this.z+1
  2689.             when 4
  2690.               sprite.angle, sprite.ox, sprite.oy = 270, w2, w1/2+16
  2691.               sprite.x, sprite.y, sprite.z = this.x-w1-16, this.y, this.z-1
  2692.             when 6
  2693.               sprite.angle, sprite.ox, sprite.oy = 90, -w2, -w1/2+16
  2694.               sprite.x, sprite.y, sprite.z = this.x+16, this.y, this.z-1
  2695.             when 8
  2696.               sprite.angle, sprite.ox, sprite.oy = 180, w1/2, h+16
  2697.               sprite.x, sprite.y, sprite.z = this.x, this.y-h-32, this.z-32
  2698.             end
  2699.             # add sprite for handling
  2700.             $BlizzABS.cache.beams.push([sprite, 20])
  2701.             # set beam flag
  2702.             beam = true
  2703.           end
  2704.         end
  2705.         # create fullscreen rectangle
  2706.         screen = $BlizzABS.util.get_fullscreen_area
  2707.         # get all targets that can be hit
  2708.         targets = ($game_map.battlers + $BlizzABS.battlers).find_all {|b|
  2709.             can_be_hit(b, dead, type, all, screen, area)}
  2710.         # if targetting everybody
  2711.         if target_all
  2712.           # reflection possible on everybody
  2713.           other = targets.clone
  2714.         else
  2715.           # reflection possible on non-target group
  2716.           other = targets.find_all {|b| !group.include?(b.ai.group)}
  2717.           # if predefined target exists
  2718.           if !all && ai.target != nil
  2719.             # set predefined target
  2720.             targets = [ai.target]
  2721.           else
  2722.             # set possible targets
  2723.             targets = targets.find_all {|b| group.include?(b.ai.group)}
  2724.           end
  2725.         end
  2726.       end
  2727.       # if no selectable targets and not trap
  2728.       if targets.size == 0 && projectype != REMTrapSkill &&
  2729.           projectype != REMTrapItem && projectype != REMTimedSkill &&
  2730.           projectype != REMTimedItem
  2731.         # no use
  2732.         return (beam == true)
  2733.       end
  2734.       # if Full Reflection System is being used and not breaking reflection skill
  2735.       if $full_reflection_system != nil && $full_reflection_system >= 3.01 &&
  2736.           targets[0].is_a?(Map_Battler) && skill && !beam &&
  2737.           !BlizzCFG::BREAK_REFLECT.include?(object.id) &&
  2738.           projectype != REMTrapSkill && projectype != REMTrapItem &&
  2739.           projectype != REMTimedSkill && projectype != REMTimedItem
  2740.         # execute reflection effect in Blizz-ABS
  2741.         BlizzCFG.reflection_effect_blizzabs(ch, targets, other, object)
  2742.       end
  2743.       # get a random target if not targeting all and no beam or death roulette
  2744.       targets = [targets[rand(targets.size)]] if !all && !beam
  2745.       # if projectile data is available and projectile should be created
  2746.       if projectype != nil
  2747.         # temporary variable
  2748.         explode = (type[1] != EXPLNone ? type[1, 3] : nil)
  2749.         # if trap
  2750.         if projectype == REMTrapSkill || projectype == REMTrapItem
  2751.           # create trap
  2752.           proj = Map_Trap.new(spriteset + object.id.to_s, ch, object.id, d,
  2753.               time, projectype, group, dead, explode)
  2754.           # add trap to buffer
  2755.           $BlizzABS.cache.remotes.push(proj)
  2756.         # if timed trap
  2757.         elsif projectype == REMTimedSkill || projectype == REMTimedItem
  2758.           # create timed trap
  2759.           proj = Map_Timed.new(spriteset + object.id.to_s, ch, object.id, d,
  2760.               time, projectype, group, dead, explode)
  2761.           # add timed trap to buffer
  2762.           $BlizzABS.cache.remotes.push(proj)
  2763.         else
  2764.           # iterate through all targets
  2765.           targets.each {|target|
  2766.               # create projectile
  2767.               proj = Map_Projectile.new(spriteset + object.id.to_s, ch,
  2768.                   object.id, target, projectile_speed, projectype, group, dead,
  2769.                   explode)
  2770.               # add projectile to buffer
  2771.               $BlizzABS.cache.remotes.push(proj)}
  2772.         end
  2773.       # if skill
  2774.       elsif skill
  2775.         # execute skill effect upon all targets
  2776.         targets.each {|target| target.skill_effect(ch, ch.battler, object)}
  2777.         # check special skill effects
  2778.         self.check_special_skills(ch, targets, object)
  2779.         # clear damage displays upon all targets
  2780.         targets.each {|target|
  2781.             target.battler.damage, target.battler.damage_pop = nil, false}
  2782.       else
  2783.         # upon all targets
  2784.         targets.each {|target|
  2785.             # execute item effect
  2786.             target.item_effect(ch, ch.battler, object)
  2787.             # clear damage displays
  2788.             target.battler.damage, target.battler.damage_pop = nil, false}
  2789.       end
  2790.       # skill/item use successful
  2791.       return true
  2792.     end
  2793.     #--------------------------------------------------------------------------
  2794.     # can_be_hit
  2795.     #  char       - current map battler
  2796.     #  dead       - dead flag
  2797.     #  type       - object type
  2798.     #  all        - targeting all
  2799.     #  screen     - screen rectangle
  2800.     #  area       - affection area data
  2801.     #  Determines whether a map battler is affected by an area.
  2802.     #--------------------------------------------------------------------------
  2803.     def can_be_hit(char, dead, type, all, screen, area)
  2804.       return (char.battler != nil && dead == char.battler.dead? &&
  2805.           @util.intersection(screen, char.hitbox) && (type[0] == BEAM && all ||
  2806.           @util.intersection(area, char.hitbox)))
  2807.     end
  2808.     #--------------------------------------------------------------------------
  2809.     # check_special_skills(battler, targets, skill)
  2810.     #  ch      - the character
  2811.     #  targets - all targets
  2812.     #  skill   - the used skill
  2813.     #  Addition to process special skill effects.
  2814.     #--------------------------------------------------------------------------
  2815.     def check_special_skills(ch, targets, skill)
  2816.       # if Tons of Add-ons is being used
  2817.       if $tons_version != nil && $tons_version >= 6.4
  2818.         # damage sprite character
  2819.         dmgchar = (ch.body == nil ? ch : ch.body)
  2820.         # if using absorbing skills
  2821.         if $game_system.ABSORB_HP_SP
  2822.           # set damage accumulation to 0
  2823.           damages = 0
  2824.           # if skill absorbs HP
  2825.           if SKILL_IDS_HP.include?(skill.id)
  2826.             # for each target
  2827.             targets.each {|target|
  2828.                 # if damage was done
  2829.                 if target.battler.damage.is_a?(Numeric)
  2830.                   # accumulate damage
  2831.                   damages += target.battler.damage
  2832.                 end}
  2833.             # change battler HP
  2834.             ch.battler.hp += damages
  2835.             # request damage sprite
  2836.             $BlizzABS.util.request_damage_sprite(dmgchar)
  2837.           # if skill absorbs SP
  2838.           elsif SKILL_IDS_SP.include?(skill.id)
  2839.             # for each target
  2840.             targets.each {|target|
  2841.                 # if damage was done
  2842.                 if target.battler.damage.is_a?(Numeric)
  2843.                   # accumulate damage
  2844.                   damages += target.battler.spdamage
  2845.                   # remove damage
  2846.                   target.battler.damage = nil
  2847.                   # make SP damage text
  2848.                   target.check_spdamage
  2849.                 end}
  2850.             # change battler SP
  2851.             ch.battler.sp += damages
  2852.             # request damage sprite
  2853.             $BlizzABS.util.request_damage_sprite(dmgchar)
  2854.           end
  2855.         end
  2856.         # if using Destructor Skill and battler should die
  2857.         if $game_system.DESTRUCTOR_SKILL && ch.battler.set_to_die
  2858.           # kill
  2859.           ch.battler.hp = 0
  2860.         end
  2861.         # if using Blus Magic Skills
  2862.         if $game_system.BLUE_MAGIC_SKILL && BLUE_MAGIC_IDS.include?(skill.id)
  2863.           # remove damage for all targets
  2864.           targets.each {|target| target.battler.damage = nil}
  2865.           # get a random target
  2866.           target = targets[rand(targets.size)]
  2867.           # try to learn
  2868.           if rand(100) < skill.hit
  2869.             # if enemy
  2870.             if target.battler.is_a?(Game_Enemy)
  2871.               # initialize array
  2872.               ids = []
  2873.               # get all skill IDs of the target
  2874.               target.battler.actions.each {|act|
  2875.                   ids.push(act.skill_id) if act.kind == 1}
  2876.             # if actor
  2877.             elsif target.battler.is_a?(Game_Actor)
  2878.               # get all skill IDs of the target
  2879.               ids = target.battler.skills.clone
  2880.             end
  2881.             # if any ID exists
  2882.             if ids.size > 0
  2883.               # get skill
  2884.               newskill = $data_skills[ids[rand(ids.size)]]
  2885.               # if already knowing that skill
  2886.               if ch.battler.skills.include?(newskill.id)
  2887.                 # make damage text
  2888.                 target.battler.damage = "#{newskill.name} known"
  2889.               else
  2890.                 # learn skill
  2891.                 target.battler.learn_skill(newskill.id)
  2892.                 # make damage text
  2893.                 target.battler.damage = "#{newskill.name} learned"
  2894.               end
  2895.             else
  2896.               # no skills available
  2897.               target.battler.damage = 'None available'
  2898.             end
  2899.           else
  2900.             # not successful
  2901.             target.battler.damage = 'Miss'
  2902.           end
  2903.         end
  2904.       end
  2905.     end
  2906.     #--------------------------------------------------------------------------
  2907.     # drop_event
  2908.     #  items   - array of items which the event contains
  2909.     #  real_x  - real x-coordinate
  2910.     #  real_y  - real y-coordinate
  2911.     #  dropper - the enemy that dropped the loot
  2912.     #  time    - timer setting
  2913.     #  Creates an event that contains loot that can be picked up.
  2914.     #--------------------------------------------------------------------------
  2915.     def drop_event(items, real_x, real_y, dropper = nil, time = nil)
  2916.       # map coordinates
  2917.       x, y, icon = real_x / 128, real_y / 128, false
  2918.       # if gold dropped and no corpses used
  2919.       if dropper == nil && items[0].is_a?(Numeric) &&
  2920.           !BlizzABS::Config::CORPSES
  2921.         # set up everything for map display
  2922.         event = create_drop_event(x, y, BlizzABS::Config::GOLD_DROP)
  2923.         # setup the event commands
  2924.         setup_drop_event(event, items, BlizzABS::Config::GOLD_PICKUP_SOUND_FILE)
  2925.       else
  2926.         # if not dropped by enemy
  2927.         if dropper == nil
  2928.           # create drop event with icon spriteset
  2929.           event = create_drop_event(x, y, items[0].icon_name)
  2930.           # event with icon spriteset
  2931.           icon = !Items.drop_sprite(items[0].id)
  2932.         # if using corpses
  2933.         elsif BlizzABS::Config::CORPSES
  2934.           # create drop event
  2935.           event = create_drop_event(x, y, dropper.character_name_org +
  2936.               BlizzABS::SPRCorpse, dropper.character_hue, 0)
  2937.         else
  2938.           # create drop event
  2939.           event = create_drop_event(x, y, dropper.character_name_org,
  2940.               dropper.character_hue)
  2941.         end
  2942.         # setup the event commands
  2943.         setup_drop_event(event, items)
  2944.       end
  2945.       # call superclass method
  2946.       drop = Game_Event.new($game_map.map_id, event)
  2947.       # mark created event as icon event
  2948.       drop.icondrop = icon
  2949.       # refresh
  2950.       drop.refresh
  2951.       # set up drop mode
  2952.       drop.activate_drop_mode(BlizzABS::Config::DROP_TIME * 40)
  2953.       # add into map events
  2954.       $game_map.events[event.id] = drop
  2955.       # stop if scene not Scene_Map or spriteset doesn't exist
  2956.       return if !$scene.is_a?(Scene_Map) || $scene.spriteset == nil
  2957.       # create own sprite as dropped
  2958.       sprite = Sprite_Character.new($scene.spriteset.viewport1, drop)
  2959.       # add to spriteset handler
  2960.       $scene.spriteset.character_sprites.push(sprite)
  2961.     end
  2962.     #--------------------------------------------------------------------------
  2963.     # create_drop_event
  2964.     #  x              - x-coordinate
  2965.     #  y              - y-coordinate
  2966.     #  character_name - spriteset name
  2967.     #  character_hue  - spriteset hue
  2968.     #  trigger        - event trigger
  2969.     #  Sets up everything so the item can be displayed correctly.
  2970.     #--------------------------------------------------------------------------
  2971.     def create_drop_event(x, y, character_name, character_hue = 0, trigger = 1)
  2972.       # create new event
  2973.       event = RPG::Event.new(0, 0)
  2974.       # if no floor beneath
  2975.       if BlizzABS::Config::NO_FLOOR_TAGS.include?($game_map.terrain_tag(x, y))
  2976.         # find closest coordinates that have a floor
  2977.         event.x, event.y = $BlizzABS.util.closest_floor(x, y)
  2978.       else
  2979.         # set coordinates
  2980.         event.x, event.y = x, y
  2981.       end
  2982.       # get keys
  2983.       keys = $game_map.events.keys
  2984.       # set new ID
  2985.       event.id = (keys.size == 0 ? 1 : keys.max + 1)
  2986.       # set own event name DROP + ID
  2987.       event.name = "DROP#{event.id}"
  2988.       # set up all necessary event page settings
  2989.       event.pages[0].graphic.character_name = character_name
  2990.       event.pages[0].graphic.character_hue = character_hue
  2991.       event.pages[0].through = event.pages[0].direction_fix = true
  2992.       event.pages[0].walk_anime = event.pages[0].step_anime = false
  2993.       event.pages[0].trigger = trigger
  2994.       # return the created event
  2995.       return event
  2996.     end
  2997.     #--------------------------------------------------------------------------
  2998.     # setup_drop_event
  2999.     #  event     - the event
  3000.     #  items     - the dropped items
  3001.     #  soundfile - the sound file to be played
  3002.     #  Sets up everything so that the right items are obtained when picking up
  3003.     #  the event.
  3004.     #--------------------------------------------------------------------------
  3005.     def setup_drop_event(event, items,
  3006.                          soundfile = BlizzABS::Config::ITEM_PICKUP_SOUND_FILE)
  3007.       # if there are no items
  3008.       if items.size == 0
  3009.         # create the event commands
  3010.         event.pages[0].list.push(RPG::EventCommand.new)
  3011.         # erase event command
  3012.         event.pages[0].list[0].code = 116
  3013.         # abort
  3014.         return
  3015.       end
  3016.       # create the event commands
  3017.       (items.size + 2).times {event.pages[0].list.push(RPG::EventCommand.new)}
  3018.       # play sound effect
  3019.       event.pages[0].list[items.size].code = 250
  3020.       # set file to be played
  3021.       event.pages[0].list[items.size].parameters = [soundfile]
  3022.       # erase event command
  3023.       event.pages[0].list[items.size + 1].code = 116
  3024.       # for each dropped item
  3025.       items.each_index {|i|
  3026.           # deteremine code and parameters
  3027.           case items[i]
  3028.           when Numeric then code, parameters = 125, [0, 0, items[i]]
  3029.           when RPG::Item then code, parameters = 126, [items[i].id, 0, 0, 1]
  3030.           when RPG::Weapon then code, parameters = 127, [items[i].id, 0, 0, 1]
  3031.           when RPG::Armor then code, parameters = 128, [items[i].id, 0, 0, 1]
  3032.           end
  3033.           # which event command
  3034.           event.pages[0].list[i].code = code
  3035.           # increase quantity by number command
  3036.           event.pages[0].list[i].parameters = parameters}
  3037.     end
  3038.     #--------------------------------------------------------------------------
  3039.     # get_enemies
  3040.     #  id - event ID or false for troop
  3041.     #  Gets the requested target enemies.
  3042.     #--------------------------------------------------------------------------
  3043.     def get_enemies(id)
  3044.       # get targets
  3045.       return (id ? [$game_map.events[id]].compact : $game_map.battlers)
  3046.     end
  3047.     #--------------------------------------------------------------------------
  3048.     # get_actors
  3049.     #  id - party position ID or false for party
  3050.     #  Gets the requested target actors.
  3051.     #--------------------------------------------------------------------------
  3052.     def get_actors(id)
  3053.       # get targets
  3054.       return (id ? [$BlizzABS.actors[id]].compact : $BlizzABS.actors.clone)
  3055.     end
  3056.     #--------------------------------------------------------------------------
  3057.     # get_targets
  3058.     #  target_type - enemies or actors
  3059.     #  target      - which target
  3060.     #  Gets the requested targets.
  3061.     #--------------------------------------------------------------------------
  3062.     def get_targets(target_type, target)
  3063.       return case target_type
  3064.       when ENEMIES then return get_enemies(target)
  3065.       when ACTORS then return get_actors(target)
  3066.       when NONE then return nil
  3067.       end
  3068.     end
  3069.     #--------------------------------------------------------------------------
  3070.     # enemy_change_hp
  3071.     #  id           - event ID or false for troop
  3072.     #  operation    - increase flag
  3073.     #  operand_type - variable or constant
  3074.     #  operand      - value or variable ID
  3075.     #  allow_kill   - allow to kill
  3076.     #  Part of the battleflow control on the map and allows users to change the
  3077.     #  HP of enemies on the map.
  3078.     #--------------------------------------------------------------------------
  3079.     def enemy_change_hp(id, operation, operand_type, operand, allow_kill)
  3080.       # creating an interpreter
  3081.       interpreter = Interpreter.new
  3082.       # get value from data
  3083.       value = interpreter.operate_value(operation, operand_type, operand)
  3084.       # for all target enemies
  3085.       get_enemies(id).each {|enemy|
  3086.           # if actually existing enemy
  3087.           if enemy.battler != nil
  3088.             # if not allowed to kill and change would kill
  3089.             if !allow_kill && enemy.battler.hp <= -value
  3090.               # set to 1 HP
  3091.               enemy.battler.hp = 1
  3092.             else
  3093.               # change HP
  3094.               enemy.battler.hp += value
  3095.             end
  3096.           end}
  3097.     end
  3098.     #--------------------------------------------------------------------------
  3099.     # enemy_change_sp
  3100.     #  id           - event ID or false for troop
  3101.     #  operation    - increase flag
  3102.     #  operand_type - variable or constant
  3103.     #  operand      - value or variable ID
  3104.     #  Part of the battleflow control on the map and allows users to change the
  3105.     #  SP of enemies on the map.
  3106.     #--------------------------------------------------------------------------
  3107.     def enemy_change_sp(id, operation, operand_type, operand)
  3108.       # creating an interpreter
  3109.       interpreter = Interpreter.new
  3110.       # get value from data
  3111.       value = interpreter.operate_value(operation, operand_type, operand)
  3112.       # change SP of all existing target enemies
  3113.       get_enemies(id).each {|e| e.battler.sp += value if e.battler != nil}
  3114.     end
  3115.     #--------------------------------------------------------------------------
  3116.     # enemy_change_state
  3117.     #  id       - event ID or false for troop
  3118.     #  add      - add/remove flag
  3119.     #  state_id - status effect ID
  3120.     #  Part of the battleflow control on the map and allows users to change the
  3121.     #  states of enemies on the map.
  3122.     #--------------------------------------------------------------------------
  3123.     def enemy_change_state(id, add, state_id)
  3124.       # for all target enemies
  3125.       get_enemies(id).each {|enemy|
  3126.           # if actually existing enemy
  3127.           if enemy.battler != nil
  3128.             # clear immortal flag if state is dead state
  3129.             enemy.battler.immortal = false if $data_states[state_id].zero_hp
  3130.             # add or remove state
  3131.             add ? enemy.battler.add_state(state_id) :
  3132.                 enemy.battler.remove_state(state_id)
  3133.           end}
  3134.     end
  3135.     #--------------------------------------------------------------------------
  3136.     # enemy_recover_all
  3137.     #  id - event ID or false for troop
  3138.     #  Part of the battleflow control on the map and allows users to let
  3139.     #  enemies recover on the map.
  3140.     #--------------------------------------------------------------------------
  3141.     def enemy_recover_all(id)
  3142.       # recover all existing target enemies
  3143.       get_enemies(id).each {|e| e.battler.recover_all if e.battler != nil}
  3144.     end
  3145.     #--------------------------------------------------------------------------
  3146.     # enemy_transform
  3147.     #  id       - event ID or false for troop
  3148.     #  enemy_id - enemy ID in the database
  3149.     #  Part of the battleflow control on the map and allows users to transform
  3150.     #  enemies on the map.
  3151.     #--------------------------------------------------------------------------
  3152.     def enemy_transform(id, enemy_id)
  3153.       # transform all existing target enemies
  3154.       get_enemies(id).each {|e| e.transform(enemy_id) if e.battler != nil}
  3155.     end
  3156.     #--------------------------------------------------------------------------
  3157.     # enemy_change_group
  3158.     #  id       - event ID or false for troop
  3159.     #  group_id - alignment group ID
  3160.     #  Part of the battleflow control on the map and allows users to change the
  3161.     #  alignment group of enemies.
  3162.     #--------------------------------------------------------------------------
  3163.     def enemy_change_group(id, group_id)
  3164.       # transform all existing target enemies
  3165.       get_enemies(id).each {|e| e.ai.setup_group(group_id) if e.battler != nil}
  3166.     end
  3167.     #--------------------------------------------------------------------------
  3168.     # enemy_affect_group
  3169.     #  id       - event ID or false for troop
  3170.     #  group_id - alignment group ID
  3171.     #  Part of the battleflow control on the map and allows users to cause
  3172.     #  a negative effect on the enemy alignment group from another group.
  3173.     #--------------------------------------------------------------------------
  3174.     def enemy_affect_group(id, group_id)
  3175.       # transform all existing target enemies
  3176.       get_enemies(id).each {|e| e.alignment_effect(group_id) if e.battler != nil}
  3177.     end
  3178.     #--------------------------------------------------------------------------
  3179.     # enemy_deal_damage
  3180.     #  id           - event ID or false for troop
  3181.     #  operand_type - variable or constant
  3182.     #  operand      - value or variable ID
  3183.     #  Part of the battleflow control on the map and allows users to deal
  3184.     #  damage to enemies on the map.
  3185.     #--------------------------------------------------------------------------
  3186.     def enemy_deal_damage(id, operand_type, operand)
  3187.       # execute requested command
  3188.       battler_deal_damage(get_enemies(id), operand_type, operand)
  3189.     end
  3190.     #--------------------------------------------------------------------------
  3191.     # actor_deal_damage
  3192.     #  id           - actor position ID or false for party
  3193.     #  operand_type - variable or constant
  3194.     #  operand      - value or variable ID
  3195.     #  Part of the battleflow control on the map and allows users to deal
  3196.     #  damage to actors on the map.
  3197.     #--------------------------------------------------------------------------
  3198.     def actor_deal_damage(id, operand_type, operand)
  3199.       # execute requested command
  3200.       battler_deal_damage(get_actors(id), operand_type, operand)
  3201.     end
  3202.     #--------------------------------------------------------------------------
  3203.     # battler_deal_damage
  3204.     #  targets - targets
  3205.     #  operand_type - variable or constant
  3206.     #  operand      - value or variable ID
  3207.     #  Deals damage to the given targets.
  3208.     #--------------------------------------------------------------------------
  3209.     def battler_deal_damage(targets, operand_type, operand)
  3210.       # creating an interpreter
  3211.       interpreter = Interpreter.new
  3212.       # if number
  3213.       if operand.is_a?(Numeric)
  3214.         # get value from data
  3215.         value = interpreter.operate_value(CONSTANT, operand_type, operand)
  3216.       else
  3217.         # set direct value
  3218.         value = operand
  3219.       end
  3220.       # for all target enemies
  3221.       targets.each {|battler|
  3222.           # if actually existing battler
  3223.           if battler.valid?
  3224.             # damage sprite character
  3225.             dmgchar = (battler.body == nil ? battler : battler.body)
  3226.             # change HP if numeric value
  3227.             battler.battler.hp -= value if value.is_a?(Numeric)
  3228.             # set damage
  3229.             battler.battler.damage = value
  3230.             # request damage sprite
  3231.             $BlizzABS.util.request_damage_sprite(dmgchar)
  3232.             # reset damage
  3233.             battler.battler.damage = nil
  3234.             # reset hpdamage and spdamage
  3235.             battler.battler.hpdamage = battler.battler.spdamage = 0
  3236.           end}
  3237.     end
  3238.     #--------------------------------------------------------------------------
  3239.     # enemy_force_action
  3240.     #  id          - event ID or false for troop
  3241.     #  target_type - enemies or actors
  3242.     #  target      - which target
  3243.     #  action_type - attack, defend, escape or skill
  3244.     #  data        - defend time, runaway time or skill ID
  3245.     #  Part of the battleflow control on the map and allows users to enforce
  3246.     #  enemies to make an action.
  3247.     #--------------------------------------------------------------------------
  3248.     def enemy_force_action(id, target_type, target, action_type, data)
  3249.       # abort if trying to force an enemy to use an item
  3250.       return if action_type == ITEM
  3251.       # decide targets depending on target battler type
  3252.       to_target = get_targets(target_type, target)
  3253.       # for all enemies
  3254.       get_enemies(id).each {|enemy|
  3255.           # if actually existing enemy
  3256.           if enemy.battler != nil
  3257.             # setup action for enemy
  3258.             $BlizzABS.AI.normal_action(enemy, to_target, to_target,
  3259.                 (action_type < SKILL), action_type, data, data, data,
  3260.                 (action_type != ITEM), (to_target == NONE), true)
  3261.             # make actually aggressive if action exists
  3262.             enemy.ai.aggressive = true if enemy.ai.act.valid?
  3263.           end}
  3264.     end
  3265.     #--------------------------------------------------------------------------
  3266.     # actor_force_action
  3267.     #  id          - actor position ID or false for party
  3268.     #  target_type - enemies or actors
  3269.     #  target      - which target
  3270.     #  action_type - attack, defend, escape or skill
  3271.     #  data        - defend time, skill ID or item ID
  3272.     #  Part of the battleflow control on the map and allows users to enforce
  3273.     #  enemies to make an action.
  3274.     #--------------------------------------------------------------------------
  3275.     def actor_force_action(id, target_type, target, action_type, data)
  3276.       # abort if trying to force an actor to run away
  3277.       return if action_type == ESCAPE
  3278.       # decide targets depending on target battler type
  3279.       to_target = get_targets(target_type, target)
  3280.       # for all actors
  3281.       get_actors(id).each {|actor|
  3282.           # if actually existing actor
  3283.           if actor.valid?
  3284.             # setup action for enemy
  3285.             $BlizzABS.AI.normal_action(actor, to_target, to_target,
  3286.                 (action_type < SKILL), action_type, data, data, data,
  3287.                 (action_type != ITEM), (to_target == NONE), true)
  3288.           end}
  3289.     end
  3290.     #--------------------------------------------------------------------------
  3291.     # get_enemy
  3292.     #  id   - event ID
  3293.     #  Returns the battler instance of an enemy.
  3294.     #--------------------------------------------------------------------------
  3295.     def get_enemy(id)
  3296.       # get enemies
  3297.       enemies = get_enemies(id)
  3298.       # return result
  3299.       return enemies[0].battler
  3300.     end
  3301.     #--------------------------------------------------------------------------
  3302.     # is_enemy?
  3303.     #  id   - event ID
  3304.     #  Checks whether the given event is an enemy.
  3305.     #--------------------------------------------------------------------------
  3306.     def is_enemy?(id)
  3307.       # get enemies
  3308.       enemies = get_enemies(id)
  3309.       # return result
  3310.       return (enemies.size > 0 && enemies[0].is_a?(Map_Battler))
  3311.     end
  3312.     #--------------------------------------------------------------------------
  3313.     # enemy_has_state?
  3314.     #  id   - event ID or false for troop
  3315.     #  s_id - state ID
  3316.     #  Checks whether the given enemy has a specific state.
  3317.     #--------------------------------------------------------------------------
  3318.     def enemy_has_state?(id, s_id)
  3319.       # get enemies
  3320.       enemies = get_enemies(id)
  3321.       # return result
  3322.       return (enemies.any? {|e| e.states.include?(s_id)})
  3323.     end
  3324.     #--------------------------------------------------------------------------
  3325.     # enemy_can_see?
  3326.     #  id          - event ID
  3327.     #  target_type - enemies or actors
  3328.     #  target      - which target
  3329.     #  Checks is the given enemy can see a specific battler.
  3330.     #--------------------------------------------------------------------------
  3331.     def enemy_can_see?(id, target_type, target)
  3332.       # get enemies
  3333.       enemies = get_enemies(id)
  3334.       # can't see if not a battler
  3335.       return false unless enemies[0].is_a?(Map_Battler)
  3336.       # get targets to check
  3337.       targets = get_targets(target_type, target)
  3338.       # return result
  3339.       return (enemies.any? {|e| (targets & e.ai.sight).size > 0})
  3340.     end
  3341.     #--------------------------------------------------------------------------
  3342.     # enemy_can_hear?
  3343.     #  id          - event ID
  3344.     #  target_type - enemies or actors
  3345.     #  target      - which target
  3346.     #  Checks is the given enemy can see a specific battler.
  3347.     #--------------------------------------------------------------------------
  3348.     def enemy_can_hear?(id, target_type, target)
  3349.       # get enemies
  3350.       enemies = get_enemies(id)
  3351.       # can't see if not a battler
  3352.       return false unless enemies[0].is_a?(Map_Battler)
  3353.       # get targets to check
  3354.       targets = get_targets(target_type, target)
  3355.       # return result
  3356.       return (targets.any? {|t| enemies.any? {|e|
  3357.           $BlizzABS.AI.can_hear_char?(e, t.real_x, t.real_y)}})
  3358.     end
  3359.     #--------------------------------------------------------------------------
  3360.     # enemy_can_perceive?
  3361.     #  id          - event ID
  3362.     #  target_type - enemies or actors
  3363.     #  target      - which target
  3364.     #  Checks is the given enemy can see a specific battler.
  3365.     #--------------------------------------------------------------------------
  3366.     def enemy_can_perceive?(id, target_type, target)
  3367.       # get enemies
  3368.       enemies = get_enemies(id)
  3369.       # can't see if not a battler
  3370.       return false unless enemies[0].is_a?(Map_Battler)
  3371.       # get targets to check
  3372.       targets = get_targets(target_type, target)
  3373.       # return result
  3374.       return (targets.any? {|t| enemies.any? {|e|
  3375.           $BlizzABS.AI.can_perceive_char?(e, t.real_x, t.real_y)}})
  3376.     end
  3377.     #--------------------------------------------------------------------------
  3378.     # enemy_has_memorized?
  3379.     #  id          - event ID
  3380.     #  target_type - enemies or actors
  3381.     #  target      - which target
  3382.     #  Checks is the given enemy can see a specific battler.
  3383.     #--------------------------------------------------------------------------
  3384.     def enemy_has_memorized?(id, target_type, target)
  3385.       # get enemies
  3386.       enemies = get_enemies(id)
  3387.       # can't see if not a battler
  3388.       return false unless enemies[0].is_a?(Map_Battler)
  3389.       # get targets to check
  3390.       targets = get_targets(target_type, target)
  3391.       # return result
  3392.       return (enemies.any? {|e| targets.size > 0 || e.ai.memory.keys.size > 0})
  3393.     end
  3394.     #--------------------------------------------------------------------------
  3395.     # create_event
  3396.     #  x - x-coordinate
  3397.     #  y - y-coordinate
  3398.     #  name - event name
  3399.     #  page_data - contains data for each page
  3400.     #  Creates an event on the map.
  3401.     #--------------------------------------------------------------------------
  3402.     def create_event(x, y, name, page_data)
  3403.       # create event
  3404.       event = RPG::Event.new(x, y)
  3405.       # get keys
  3406.       keys = $game_map.events.keys
  3407.       # set new ID
  3408.       event.id = (keys.size == 0 ? 1 : keys.max + 1)
  3409.       # set own event name DROP + ID
  3410.       event.name = name
  3411.       if page_data.size > 0
  3412.         # clear page data
  3413.         event.pages.clear
  3414.         # set page data
  3415.         page_data.each {|p| event.pages.push(create_event_page(p))}
  3416.       end
  3417.       # add to map
  3418.       $game_map.map.events[event.id] = event
  3419.       $game_map.events[event.id] = Game_Event.new($game_map.map_id, event)
  3420.       # update name
  3421.       check_event_name(event.id)
  3422.       # create spriteset
  3423.       sprite = Sprite_Character.new($scene.spriteset.viewport1, $game_map.events[event.id])
  3424.       # add to spriteset handler
  3425.       $scene.spriteset.character_sprites.push(sprite)
  3426.       # refresh map
  3427.       $game_map.need_refresh = true
  3428.       # return event id
  3429.       return event.id
  3430.     end
  3431.     #--------------------------------------------------------------------------
  3432.     # create_event_page
  3433.     #  data - event page data
  3434.     #  Creates an event page.
  3435.     #--------------------------------------------------------------------------
  3436.     def create_event_page(data)
  3437.       # create new page
  3438.       page = RPG::Event::Page.new
  3439.       # return if empty page
  3440.       return page if data.size == 0
  3441.       # set page data
  3442.       page.condition = create_event_page_condition(data[0])
  3443.       page.graphic = create_event_page_graphic(data[1])
  3444.       page.move_type = data[2]
  3445.       page.move_speed = data[3]
  3446.       page.move_frequency = data[4]
  3447.       page.move_route = create_move_route(data[5])
  3448.       page.walk_anime = data[6]
  3449.       page.step_anime = data[7]
  3450.       page.direction_fix = data[8]
  3451.       page.through = data[9]
  3452.       page.always_on_top = data[10]
  3453.       page.trigger = data[11]
  3454.       if data[12].size > 0
  3455.         page.list = []
  3456.         data[12].each {|d| page.list.push(create_event_command(d))}
  3457.       end
  3458.       # return completed page
  3459.       return page
  3460.     end
  3461.     #--------------------------------------------------------------------------
  3462.     # create_event_page_condition
  3463.     #  data - event page condition data
  3464.     #  Creates an event page condition.
  3465.     #--------------------------------------------------------------------------
  3466.     def create_event_page_condition(data)
  3467.       # create new condition
  3468.       condition = RPG::Event::Page::Condition.new
  3469.       # return if empty condition
  3470.       return condition if data.size == 0
  3471.       # set condition data
  3472.         condition.switch1_valid = data[0]
  3473.         condition.switch2_valid = data[1]
  3474.         condition.variable_valid = data[2]
  3475.         condition.self_switch_valid = data[3]
  3476.         condition.switch1_id = data[4]
  3477.         condition.switch2_id = data[5]
  3478.         condition.variable_id = data[6]
  3479.         condition.variable_value = data[7]
  3480.         condition.self_switch_ch = data[8]
  3481.       # return completed condition
  3482.       return condition
  3483.     end
  3484.     #--------------------------------------------------------------------------
  3485.     # create_event_page_graphic
  3486.     #  data - event page graphic data
  3487.     #  Creates an event page graphic.
  3488.     #--------------------------------------------------------------------------
  3489.     def create_event_page_graphic(data)
  3490.       # create new graphic
  3491.       graphic = RPG::Event::Page::Graphic.new
  3492.       # return if empty graphic
  3493.       return graphic if data.size == 0
  3494.       # set graphic data
  3495.         graphic.tile_id = data[0]
  3496.         graphic.character_name = data[1]
  3497.         graphic.character_hue = data[2]
  3498.         graphic.direction = data[3]
  3499.         graphic.pattern = data[4]
  3500.         graphic.opacity = data[5]
  3501.         graphic.blend_type = data[6]
  3502.       # return completed graphic
  3503.       return graphic
  3504.     end
  3505.     #--------------------------------------------------------------------------
  3506.     # create_move_route
  3507.     #  data - move route data
  3508.     #  Creates a move route.
  3509.     #--------------------------------------------------------------------------
  3510.     def create_move_route(data)
  3511.       # create new move route
  3512.       move_route = RPG::MoveRoute.new
  3513.       # return if empty move route
  3514.       return move_route if data.size == 0
  3515.       # set move route data
  3516.         move_route.repeat = data[0]
  3517.         move_route.skippable = data[1]
  3518.         if move_route.list.size > 0
  3519.           move_route.list = []
  3520.           data[2].each {|d| move_route.list.push(create_move_command(d))}
  3521.         end
  3522.       # return completed move route
  3523.       return move_route
  3524.     end
  3525.     #--------------------------------------------------------------------------
  3526.     # create_move_command
  3527.     #  data - move command data
  3528.     #  Creates a move command.
  3529.     #--------------------------------------------------------------------------
  3530.     def create_move_command(data)
  3531.       # create new command
  3532.       command = RPG::MoveCommand.new
  3533.       # return if empty command
  3534.       return command if data.size == 0
  3535.       # set command data
  3536.         command.code = data[0]
  3537.         command.parameters = data[1]
  3538.       # return completed command
  3539.       return command
  3540.     end
  3541.     #--------------------------------------------------------------------------
  3542.     # create_event_command
  3543.     #  data - event command data
  3544.     #  Creates an event command.
  3545.     #--------------------------------------------------------------------------
  3546.     def create_event_command(data)
  3547.       # create new command
  3548.       command = RPG::EventCommand.new
  3549.       # return if empty command
  3550.       return command if data.size == 0
  3551.       # set command data
  3552.         command.code = data[0]
  3553.         command.indent = data[1]
  3554.         command.parameters = data[2]
  3555.       # return completed command
  3556.       return command
  3557.     end
  3558.   end
  3559.  
  3560. end
  3561.  
  3562. module BlizzABS
  3563.  
  3564.   #============================================================================
  3565.   # BlizzABS::Controller
  3566.   #----------------------------------------------------------------------------
  3567.   #  This class is a special controller that controls the party leader.  Some
  3568.   #  input is processed instantly, while some is converted into commands to be
  3569.   #  given to the player character.
  3570.   #============================================================================
  3571.  
  3572.   class Controller
  3573.    
  3574.     # Center screen x-coordinate * 4
  3575.     CX = (320 - 16) * 4
  3576.     # Center screen y-coordinate * 4
  3577.     CY = (240 - 16) * 4
  3578.    
  3579.     # set all accessible variables
  3580.     attr_accessor :encounter_count
  3581.     #--------------------------------------------------------------------------
  3582.     # Initialization
  3583.     #--------------------------------------------------------------------------
  3584.     def initialize
  3585.       # set memory jump
  3586.       @memory_jump = false
  3587.     end
  3588.     #--------------------------------------------------------------------------
  3589.     # player
  3590.     #  Makes the code easier to read.
  3591.     #--------------------------------------------------------------------------
  3592.     def player
  3593.       return $BlizzABS.actors[0]
  3594.     end
  3595.     #--------------------------------------------------------------------------
  3596.     # update_control
  3597.     #  Processes player control.
  3598.     #--------------------------------------------------------------------------
  3599.     def update_control
  3600.       # get pixel movement rate
  3601.       pix = $BlizzABS.pixel
  3602.       # reset move speed if not moving
  3603.       player.move_speed = player.normal_speed
  3604.       # reset spriteset name
  3605.       player.character_name = player.character_name_org
  3606.       # if allowed to change speed
  3607.       unless $game_system.map_interpreter.running? ||
  3608.           player.move_route_forcing || $game_temp.message_window_showing
  3609.         # if run button works and running
  3610.         if $game_system.running_button && Input.press?(Input::Run)
  3611.           # set running speed
  3612.           player.move_speed = Config::RUN_SPEED
  3613.         # if sneak button works and sneaking
  3614.         elsif $game_system.sneaking_button && Input.press?(Input::Sneak) ||
  3615.             Config::SNEAK_SPEED > 0 && Config::SNEAK_ON_CHARGE && player.charging?
  3616.           # set sneaking speed
  3617.           player.move_speed = Config::SNEAK_SPEED
  3618.         end
  3619.       end
  3620.       # if battler exists and either dead or select triggered
  3621.       if player.battler != nil && ($game_system.select_button &&
  3622.           Input.trigger?(Input::Select) || player.battler.dead?)
  3623.         # switch to next valid actor
  3624.         switch_leader
  3625.       end
  3626.       # setup sprite animation
  3627.       player.sprite_animation_setup
  3628.       # update action
  3629.       player.update_action
  3630.       # if allowed to turn and pressed turning button or defending
  3631.       if ((player.ai.act.defend? && player.attacked == 0) ||
  3632.           $game_system.turn_button && Input.press?(Input::Turn)) &&
  3633.           !player.moving? && !$game_system.map_interpreter.running? &&
  3634.           !player.move_route_forcing && !$game_temp.message_window_showing
  3635.         # get input depending on confusion
  3636.         input = (player.restriction == 3 ? 10 - Input.dir4 : Input.dir4)
  3637.         # depending on input turn
  3638.         case input
  3639.         when 2 then player.turn_down
  3640.         when 4 then player.turn_left
  3641.         when 6 then player.turn_right
  3642.         when 8 then player.turn_up
  3643.         end
  3644.         # updates any attacked action
  3645.         player.update_attacked
  3646.         # abort method
  3647.         return nil
  3648.       end
  3649.       # updates any attacked action
  3650.       player.update_attacked
  3651.       # if acting
  3652.       if player.in_action > 0
  3653.         # decrease action counter if in_action is greater than 0
  3654.         player.in_action -= 1 if player.in_action > 0
  3655.         # return data
  3656.         return [player.moving?, player.real_x, player.real_y]
  3657.       end
  3658.       # if allowed to move
  3659.       unless $game_system.map_interpreter.running? ||
  3660.           player.move_route_forcing || $game_temp.message_window_showing
  3661.         # if jump button was pressed and not already jumping
  3662.         if $game_system.jumping_button && Input.trigger?(Input::Jump) &&
  3663.             !player.jumping? && player.restriction < 4
  3664.           # set to jump
  3665.           @memory_jump = true
  3666.         end
  3667.         # if not moving
  3668.         unless player.moving?
  3669.           # get jumping range
  3670.           range = Config::JUMPING
  3671.           # if jumping turned on and not jumping and jumped
  3672.           if range > 0 && !player.jumping? && @memory_jump
  3673.             # if sneaking or running is possible
  3674.             if Config::RUN_SPEED > 0 || Config::SNEAK_SPEED > 0
  3675.               # get difference between current speed and normal speed
  3676.               dplus = player.move_speed - player.normal_speed
  3677.             else
  3678.               # difference is 0
  3679.               dplus = 0
  3680.             end
  3681.             # get direction
  3682.             direction = $game_system._8_way ? Input.dir8 : Input.dir4
  3683.             # set jumping direction
  3684.             x, y = Cache::DirOffsets[direction]
  3685.             # jump into direction with considering running/sneaking
  3686.             player.jump(x*range + x*dplus, y*range + y*dplus, direction)
  3687.           # if not already jumping
  3688.           elsif !player.jumping?
  3689.             # move
  3690.             move($game_system._8_way ? Input.dir8 : Input.dir4)
  3691.             # allow idle if no movement
  3692.             player.idle_allowed = !player.moving?
  3693.           end
  3694.           # not jumping anymore
  3695.           @memory_jump = false
  3696.         end
  3697.       end
  3698.       # return data
  3699.       return [player.moving?, player.real_x, player.real_y]
  3700.     end
  3701.     #--------------------------------------------------------------------------
  3702.     # switch_leader
  3703.     #  Switches to the next valid actor as leader.
  3704.     #--------------------------------------------------------------------------
  3705.     def switch_leader
  3706.       # store the old party leader
  3707.       leader = player
  3708.       # iterate "number of party members" times
  3709.       $game_party.actors.size.times {
  3710.           # change party leader
  3711.           $game_party.add_actor($game_party.actors.shift.id)
  3712.           # until finding one who's not dead
  3713.           break if $game_party.actors[0] != nil && !$game_party.actors[0].dead?}
  3714.       # stop if party leader has not changed
  3715.       return if leader == player
  3716.       # enforce emptying moving buffer and add special command
  3717.       update_buffer(nil)
  3718.       # center screen display on new player controlled character
  3719.       center(player.x, player.y, true) if $game_system.caterpillar
  3720.       # except if charging
  3721.       unless player.charging?
  3722.         # reset player action
  3723.         player.reset_action
  3724.         # reset player action counter
  3725.         player.in_action = 0
  3726.       end
  3727.       # except if charging
  3728.       unless leader.charging?
  3729.         # reset old leader action
  3730.         leader.reset_action
  3731.         # reset old leader action counter
  3732.         leader.in_action = 0
  3733.       end
  3734.       # set flag for HUD update
  3735.       $game_temp.hud_refresh = true
  3736.     end
  3737.     #--------------------------------------------------------------------------
  3738.     # move
  3739.     #  dir - direction
  3740.     #  Make the code easier to read. It moves the player in the appropriate
  3741.     #  direction then.
  3742.     #--------------------------------------------------------------------------
  3743.     def move(dir)
  3744.       return case (player.restriction == 3 ? 10 - dir : dir)
  3745.       when 1 then player.move_lower_left
  3746.       when 2 then player.move_down
  3747.       when 3 then player.move_lower_right
  3748.       when 4 then player.move_left
  3749.       when 6 then player.move_right
  3750.       when 7 then player.move_upper_left
  3751.       when 8 then player.move_up
  3752.       when 9 then player.move_upper_right
  3753.       end
  3754.     end
  3755.     #--------------------------------------------------------------------------
  3756.     # update_moving
  3757.     #  Processes player control.
  3758.     #--------------------------------------------------------------------------
  3759.     def update_moving(data)
  3760.       # if control update was not aborted
  3761.       if data != nil
  3762.         # get data
  3763.         moved, x, y = data
  3764.         # if moved down
  3765.         if player.real_y > y && player.real_y - $game_map.display_y > CY
  3766.           # scroll screen down
  3767.           $game_map.scroll_down(player.real_y - y)
  3768.         end
  3769.         # if moved left
  3770.         if player.real_x < x && player.real_x - $game_map.display_x < CX
  3771.           # scroll screen left
  3772.           $game_map.scroll_left(x - player.real_x)
  3773.         end
  3774.         # if moved right
  3775.         if player.real_x > x && player.real_x - $game_map.display_x > CX
  3776.           # scroll screen right
  3777.           $game_map.scroll_right(player.real_x - x)
  3778.         end
  3779.         # if moved up
  3780.         if player.real_y < y && player.real_y - $game_map.display_y < CY
  3781.           # scroll screen up
  3782.           $game_map.scroll_up(y - player.real_y)
  3783.         end
  3784.         # if not moving
  3785.         unless player.moving?
  3786.           # if last moving, not activated, not override and countdown
  3787.           if moved && !check_event_trigger_here(Cache::TouchTrigger) &&
  3788.               !($DEBUG && Input.press?(Input::CTRL)) && @encounter_count > 0
  3789.             # set battle-encounter countdown
  3790.             @encounter_count -= 2 ** (5 - $game_system.pixel_rate)
  3791.             @encounter_count = 0 if @encounter_count < 0
  3792.           end
  3793.           # if pressed C button
  3794.           if Input.trigger?(Input::C)
  3795.             # check event here
  3796.             check_event_trigger_here(Cache::PressTrigger)
  3797.             # check event there
  3798.             check_event_trigger_there(Cache::BasicTrigger)
  3799.           end
  3800.         end
  3801.       end
  3802.       # update each other actor except the player
  3803.       ($BlizzABS.battlers - [player]).each {|actor| actor.update}
  3804.     end
  3805.     #--------------------------------------------------------------------------
  3806.     # update_buffer
  3807.     #  move - new command
  3808.     #  Updates the buffer of the last moving commands.
  3809.     #--------------------------------------------------------------------------
  3810.     def update_buffer(move)
  3811.       # if new command requires so
  3812.       if move == nil || move == false
  3813.         # empty each actor's buffer
  3814.         $BlizzABS.battlers.each {|actor| actor.force_move = []}
  3815.       end
  3816.       # add new command or enforce emptying whether move is reset for each actor
  3817.       $BlizzABS.battlers.each {|actor| actor.update_buffer(move == 'reset' ? nil : move)}
  3818.     end
  3819.     #--------------------------------------------------------------------------
  3820.     # refresh
  3821.     #  Refreshes the character.
  3822.     #--------------------------------------------------------------------------
  3823.     def refresh
  3824.       # test on changes in the inner structure of $game_party.actors
  3825.       if $BlizzABS.actors.any? {|actor|
  3826.           actor.battler(true) == nil && $game_party.actors[actor.index] != nil ||
  3827.           actor.battler(true) != $game_party.actors[actor.index]}
  3828.         # if caterpillar is on
  3829.         if $game_system.caterpillar
  3830.           # store old array, create 2 new arrays
  3831.           old, tmp, $BlizzABS.actors = $BlizzABS.actors, [], []
  3832.           # for each old actor
  3833.           old.each {|a|
  3834.               # if battler exists and in party
  3835.               if a.battler(true) != nil && a.battler(true).index != nil &&
  3836.                   a.battler(true).index < BlizzABS::Config::MAX_PARTY
  3837.                 # add actor on position
  3838.                 $BlizzABS.actors[a.battler(true).index] = a
  3839.               end}
  3840.           # for the rest of the old actors
  3841.           (old - $BlizzABS.actors).each {|a|
  3842.               # if not in party
  3843.               if a.battler(true) != nil && (a.battler(true).index == nil ||
  3844.                   a.battler(true).index >= BlizzABS::Config::MAX_PARTY)
  3845.                 # remove battler
  3846.                 a.battler = nil
  3847.               end
  3848.               # add actor
  3849.               tmp.push(a)}
  3850.           # fill the empty places between
  3851.           $BlizzABS.actors.each_index {|i|
  3852.               $BlizzABS.actors[i] = tmp.shift if $BlizzABS.actors[i] == nil}
  3853.           # add rest of actors
  3854.           $BlizzABS.actors += tmp
  3855.           # for each actor
  3856.           $BlizzABS.actors.each {|a|
  3857.               # if no battler assigned, but in the party is a battler
  3858.               if a.battler(true) == nil && $game_party.actors[a.index] != nil
  3859.                 # assign battler
  3860.                 a.battler = $game_party.actors[a.index]
  3861.               end}
  3862.         else
  3863.           # set the correct battlers
  3864.           $BlizzABS.actors.each_index {|i|
  3865.               $BlizzABS.actors[i].battler = $game_party.actors[i]}
  3866.         end
  3867.       end
  3868.       # each actor
  3869.       $BlizzABS.battlers.each {|actor|
  3870.           # refresh spriteset
  3871.           actor.refresh(true)
  3872.           # set to return to caterpillar for convenience
  3873.           actor.ai.state = AI::Return
  3874.           # if actor not valid
  3875.           unless actor.valid?
  3876.             # reset action
  3877.             actor.ai.target = nil
  3878.             actor.ai.act.set
  3879.           end}
  3880.       # set new $game_player character
  3881.       $game_player = player
  3882.     end
  3883.     #--------------------------------------------------------------------------
  3884.     # moveto
  3885.     #  x - x-coordinate
  3886.     #  y - y-coordinate
  3887.     #  Moves the player instantly to a position, moves all actors and centers
  3888.     #  the screen upon the player.
  3889.     #--------------------------------------------------------------------------
  3890.     def moveto(x, y)
  3891.       # center screen upon player
  3892.       center(x, y)
  3893.       # for each actor
  3894.       ($BlizzABS.battlers - [player]).each {|actor|
  3895.           # return to caterpillar if not in caterpillar
  3896.           actor.return_to_caterpillar if actor.cindex == nil}
  3897.       # empty movement command buffer
  3898.       update_buffer(nil)
  3899.       # move each actor to the same position
  3900.       ($BlizzABS.battlers - [player]).each {|actor| actor.moveto(x, y)}
  3901.       # create battle-encounter countdown
  3902.       player.make_encounter_count
  3903.     end
  3904.     #--------------------------------------------------------------------------
  3905.     # center
  3906.     #  x - x-coordinate
  3907.     #  y - y-coordinate
  3908.     #  Centers the screen upon the player. (pixel movement)
  3909.     #--------------------------------------------------------------------------
  3910.     def center(x, y, flag = false)
  3911.       # set pix value
  3912.       pix = flag ? $BlizzABS.pixel : 1
  3913.       # resize coordinates
  3914.       x, y = x * 128 / pix, y * 128 / pix
  3915.       # get maximum coordinates of map
  3916.       m_x, m_y = ($game_map.width - 20) * 128, ($game_map.height - 15) * 128
  3917.       ox, oy = x - CX, y - CY
  3918.       # set new display coordinates
  3919.       if ox > m_x
  3920.         $game_map.display_x = m_x
  3921.       elsif ox < 0
  3922.         $game_map.display_x = 0
  3923.       else
  3924.         $game_map.display_x = ox
  3925.       end
  3926.       if oy > m_y
  3927.         $game_map.display_y = m_y
  3928.       elsif oy < 0
  3929.         $game_map.display_y = 0
  3930.       else
  3931.         $game_map.display_y = oy
  3932.       end
  3933.     end
  3934.     #--------------------------------------------------------------------------
  3935.     # check_event_trigger_here
  3936.     #  triggers - possible event triggers
  3937.     #  Checks if there are events to be triggered. (pixel movement)
  3938.     #--------------------------------------------------------------------------
  3939.     def check_event_trigger_here(triggers)
  3940.       # not started if already running
  3941.       return false if $game_system.map_interpreter.running?
  3942.       # get pixel movement rate
  3943.       pix = $BlizzABS.pixel
  3944.       # initialize result
  3945.       result = false
  3946.       # iterate through all events
  3947.       $game_map.events.values.each {|event|
  3948.           # if coordinates fit and can be triggered and not jumping
  3949.           if event.x == (player.x+pix/2)/pix &&
  3950.              event.y == (player.y+pix/2)/pix &&
  3951.               triggers.include?(event.trigger) && !event.jumping? &&
  3952.               event.over_trigger?
  3953.             # start event
  3954.             event.start
  3955.             # events were started
  3956.             result = true
  3957.           end}
  3958.       # return result
  3959.       return result
  3960.     end
  3961.     #--------------------------------------------------------------------------
  3962.     # check_event_trigger_there
  3963.     #  triggers - possible event triggers
  3964.     #  Checks if there are events to be triggered. (pixel movement)
  3965.     #--------------------------------------------------------------------------
  3966.     def check_event_trigger_there(triggers)
  3967.       # not started if already running
  3968.       return false if $game_system.map_interpreter.running?
  3969.       # get pixel movement rate
  3970.       pix = $BlizzABS.pixel
  3971.       # calculate new coordinates
  3972.       nx = player.x + (player.direction == 6 ? 1 : player.direction == 4 ? -1 : 0)*pix
  3973.       ny = player.y + (player.direction == 2 ? 1 : player.direction == 8 ? -1 : 0)*pix
  3974.       # initialize result
  3975.       result = false
  3976.       # iterate through all events
  3977.       $game_map.events.values.each {|event|
  3978.           # if triggered by touch and trigger started the event
  3979.           if triggers.include?(event.trigger) &&
  3980.               event.check_event_trigger_at(nx, ny)
  3981.             # events were started
  3982.             result = true
  3983.           end}
  3984.       # if event was not started and counter
  3985.       if !result && $game_map.pixel_counter?(nx, ny)
  3986.         # change new coordinates
  3987.         nx += (player.direction == 6 ? 1 : player.direction == 4 ? -1 : 0)*pix
  3988.         ny += (player.direction == 2 ? 1 : player.direction == 8 ? -1 : 0)*pix
  3989.         # iterate through all events
  3990.         $game_map.events.values.each {|event|
  3991.             # if triggered by touch and trigger started the event
  3992.             if triggers.include?(event.trigger) &&
  3993.                 event.check_event_trigger_at(nx, ny)
  3994.               # events were started
  3995.               result = true
  3996.             end}
  3997.       end
  3998.       # return result
  3999.       return result
  4000.     end
  4001.     #--------------------------------------------------------------------------
  4002.     # check_event_trigger_touch
  4003.     #  x - x-coordinate
  4004.     #  y - y-coordinate
  4005.     #  Checks if there are events that were triggered by touch. (pixel movement)
  4006.     #--------------------------------------------------------------------------
  4007.     def check_event_trigger_touch(x, y)
  4008.       # not started if already running
  4009.       return false if $game_system.map_interpreter.running?
  4010.       # get pixel movement rate
  4011.       pix = $BlizzABS.pixel
  4012.       # initialize result
  4013.       result = false
  4014.       # iterate through all events
  4015.       $game_map.events.values.each {|event|
  4016.           # if triggered by touch and trigger started the event
  4017.           if Cache::TouchTrigger.include?(event.trigger) &&
  4018.               event.check_event_trigger_at(x, y)
  4019.             # events were started
  4020.             result = true
  4021.           end}
  4022.       # return result
  4023.       return result
  4024.     end
  4025.     #--------------------------------------------------------------------------
  4026.     # cancel_path_request?
  4027.     #  Decides if player is trying to cancel path request.
  4028.     #--------------------------------------------------------------------------
  4029.     def cancel_path_request?
  4030.       # true if directional input, turn, jump, or battle action
  4031.       return Input.dir4 != 0 ||
  4032.         ($game_system.select_button && Input.press?(Input::Select)) ||
  4033.         ($game_system.turn_button && Input.press?(Input::Turn)) ||
  4034.         ($game_system.jumping_button && Input.press?(Input::Jump)) ||
  4035.         ($game_system.attack_button && Input.press?(Input::Attack) ||
  4036.         ($game_system.defend_button && Input.press?(Input::Defend)) ||
  4037.         ($game_system.skill_button && Input.press?(Input::Skill)) ||
  4038.         ($game_system.item_button && Input.press?(Input::Item)))
  4039.     end
  4040.   end
  4041.  
  4042. end
  4043.  
  4044. module BlizzABS
  4045.  
  4046.   #============================================================================
  4047.   # BlizzABS::Trigger
  4048.   #----------------------------------------------------------------------------
  4049.   #  This class provides a data interface for AI Trigger data packs.
  4050.   #============================================================================
  4051.  
  4052.   class Trigger
  4053.    
  4054.     # setting all accessible variables
  4055.     attr_accessor :activator
  4056.     attr_accessor :condition
  4057.     attr_accessor :comparator
  4058.     attr_accessor :value
  4059.     attr_accessor :action_type
  4060.     attr_accessor :action_data
  4061.     attr_accessor :target
  4062.     #--------------------------------------------------------------------------
  4063.     # Initialization
  4064.     #  activator   - the battler type that activates the trigger
  4065.     #  condition   - conditional operand A
  4066.     #  comparator  - comparison operator
  4067.     #  value       - conditional operand B
  4068.     #  action_type - action type
  4069.     #  action_data - data supporting the action type
  4070.     #  target      - target type
  4071.     #--------------------------------------------------------------------------
  4072.     def initialize(activator = TRGLeader, condition = TRGHP,
  4073.                    comparator = TRGEqual, value = 100, action_type = TRGAttack,
  4074.                    action_data = 0, target = TRGTargetDefault)
  4075.       @activator = activator
  4076.       @condition = condition
  4077.       @comparator = comparator
  4078.       @value = value
  4079.       @action_type = action_type
  4080.       @action_data = action_data
  4081.       @target = target
  4082.     end
  4083.     #--------------------------------------------------------------------------
  4084.     # battler_activator?
  4085.     #  Checks if the trigger is activated by a battler type.
  4086.     #--------------------------------------------------------------------------
  4087.     def battler_activator?
  4088.       return (@activator != TRGProbability)
  4089.     end
  4090.     #--------------------------------------------------------------------------
  4091.     # get_a_target
  4092.     #  char    - the hosting actor
  4093.     #  targets - possible targets
  4094.     #  Checks the condition of the trigger with the given targets and returns
  4095.     #  the chosen target.
  4096.     #--------------------------------------------------------------------------
  4097.     def get_a_target(char, targets)
  4098.       # check trigger condition
  4099.       case @condition
  4100.       when TRGHP # HP condition
  4101.         # for each possible target
  4102.         targets.each {|b|
  4103.             # get comparator string
  4104.             comparator = Cache::TRGComparators[@comparator]
  4105.             # evaluate condition
  4106.             if eval("b.battler.hp * 100 / b.battler.maxhp #{comparator} @value")
  4107.               # this target fulfills the condition
  4108.               return b
  4109.             end}
  4110.       when TRGSP # SP condition
  4111.         # for each possible target
  4112.         targets.each {|b|
  4113.             # get comparator string
  4114.             comparator = Cache::TRGComparators[@comparator]
  4115.             # evaluate condition
  4116.             if eval("b.battler.sp * 100 / b.battler.maxsp #{comparator} @value")
  4117.               # this target fulfills the condition
  4118.               return b
  4119.             end}
  4120.       when TRGState # State condition
  4121.         # if no state condition
  4122.         if @value == 0
  4123.           # find a target that has no states
  4124.           targets.each {|b| return b if b.battler.states.size == 0}
  4125.         else
  4126.           # find a target with the condition state
  4127.           targets.each {|b| return b if b.battler.states.include?(@value)}
  4128.         end
  4129.       when TRGLocation # Location condition
  4130.         # temporary variable
  4131.         pix = $BlizzABS.pixel
  4132.         # sort all targets by relative distance ascending
  4133.         targets.sort! {|a, b|
  4134.             Math.hypot(char.x / pix - a.x / pix, char.y / pix - a.y / pix) <=>
  4135.             Math.hypot(char.x / pix - b.x / pix, char.y / pix - b.y / pix)}
  4136.         # return the requested battler
  4137.         return case @value
  4138.         when TRGClosest then targets[0]
  4139.         when TRGFarthest then targets[targets.size - 1]
  4140.         end
  4141.       end
  4142.       # this trigger has not been activated
  4143.       return nil
  4144.     end
  4145.    
  4146.   end
  4147.  
  4148.   #============================================================================
  4149.   # BlizzABS::Action
  4150.   #----------------------------------------------------------------------------
  4151.   #  This class provides a data interface for action data packs.
  4152.   #============================================================================
  4153.  
  4154.   class Action
  4155.    
  4156.     # setting all accessible variables
  4157.     attr_accessor :range
  4158.     attr_accessor :kind
  4159.     attr_accessor :id
  4160.     attr_accessor :type
  4161.     attr_accessor :delay
  4162.     attr_accessor :forced
  4163.     #--------------------------------------------------------------------------
  4164.     # Initialization
  4165.     #  range - range of the action
  4166.     #  kind  - action kind
  4167.     #  id    - action id
  4168.     #  type  - action type
  4169.     #  delay - delay time
  4170.     #  forced - forced action
  4171.     #--------------------------------------------------------------------------
  4172.     def initialize(range = 0, kind = 0, id = 0, type = 0, delay = 0,
  4173.                    forced = false)
  4174.       set(range, kind, id, type, delay, forced)
  4175.     end
  4176.     #--------------------------------------------------------------------------
  4177.     # set
  4178.     #  range - range of the action
  4179.     #  kind  - action kind
  4180.     #  id    - action id
  4181.     #  type  - action type
  4182.     #  delay - delay time
  4183.     #  forced - forced action
  4184.     #  Sets all action's parameters at once.
  4185.     #--------------------------------------------------------------------------
  4186.     def set(range = 0, kind = 0, id = 0, type = 0, delay = 0, forced = false)
  4187.       @range = range
  4188.       @kind = kind
  4189.       @id = id
  4190.       @type = type
  4191.       @delay = delay
  4192.       @forced = forced
  4193.     end
  4194.     #--------------------------------------------------------------------------
  4195.     # valid?
  4196.     #  Checks if the action is actually an action.
  4197.     #--------------------------------------------------------------------------
  4198.     def valid?
  4199.       return (@kind != ACTNone)
  4200.     end
  4201.     #--------------------------------------------------------------------------
  4202.     # basic?
  4203.     #  Checks if the action is a basic action.
  4204.     #--------------------------------------------------------------------------
  4205.     def basic?
  4206.       return (attack? || defend? || escape?)
  4207.     end
  4208.     #--------------------------------------------------------------------------
  4209.     # attack?
  4210.     #  Checks if the action is an attack.
  4211.     #--------------------------------------------------------------------------
  4212.     def attack?
  4213.       return (@kind == ACTAttack)
  4214.     end
  4215.     #--------------------------------------------------------------------------
  4216.     # defend?
  4217.     #  Checks if the action is a defending action.
  4218.     #--------------------------------------------------------------------------
  4219.     def defend?
  4220.       return (@kind == ACTDefend)
  4221.     end
  4222.     #--------------------------------------------------------------------------
  4223.     # escape?
  4224.     #  Checks if the action is an escaping action.
  4225.     #--------------------------------------------------------------------------
  4226.     def escape?
  4227.       return (@kind == ACTEscape)
  4228.     end
  4229.     #--------------------------------------------------------------------------
  4230.     # skill?
  4231.     #  Checks if the action is a skill.
  4232.     #--------------------------------------------------------------------------
  4233.     def skill?
  4234.       return (@kind == ACTSkill)
  4235.     end
  4236.     #--------------------------------------------------------------------------
  4237.     # item?
  4238.     #  Checks if the action is an item use.
  4239.     #--------------------------------------------------------------------------
  4240.     def item?
  4241.       return (@kind == ACTItem)
  4242.     end
  4243.     #--------------------------------------------------------------------------
  4244.     # ready?
  4245.     #  Checks if the action is ready to be executed.
  4246.     #--------------------------------------------------------------------------
  4247.     def ready?
  4248.       return (@delay <= 0)
  4249.     end
  4250.    
  4251.   end
  4252.  
  4253.   #============================================================================
  4254.   # BlizzABS::ChargeData
  4255.   #----------------------------------------------------------------------------
  4256.   #  This class provides a data interface for action charges.
  4257.   #============================================================================
  4258.  
  4259.   class ChargeData
  4260.    
  4261.     # setting all accessible variables
  4262.     attr_accessor :type
  4263.     attr_accessor :time
  4264.     attr_accessor :action
  4265.     attr_accessor :id
  4266.     #--------------------------------------------------------------------------
  4267.     # Initialization
  4268.     #  type   - charge type
  4269.     #  time   - time to charge up
  4270.     #  action - action type
  4271.     #  id     - action ID
  4272.     #--------------------------------------------------------------------------
  4273.     def initialize(type, time, action, id)
  4274.       @type, @time, @action, @id = type, time, action, id
  4275.     end
  4276.     #--------------------------------------------------------------------------
  4277.     # charged?
  4278.     #  Checks if the action has been charged.
  4279.     #--------------------------------------------------------------------------
  4280.     def charged?
  4281.       return (@time <= 0)
  4282.     end
  4283.    
  4284.   end
  4285.  
  4286.   #============================================================================
  4287.   # BlizzABS::MemoryData
  4288.   #----------------------------------------------------------------------------
  4289.   #  This class provides a data interface for enemy memory data about other
  4290.   #  battlers one the map.
  4291.   #============================================================================
  4292.  
  4293.   class MemoryData
  4294.    
  4295.     # setting all accessible variables
  4296.     attr_accessor :x
  4297.     attr_accessor :y
  4298.     #--------------------------------------------------------------------------
  4299.     # Initialization
  4300.     #  x    - x-coordinate of memorized battler
  4301.     #  y    - y-coordinate of memorized battler
  4302.     #--------------------------------------------------------------------------
  4303.     def initialize(x, y)
  4304.       @x, @y = x, y
  4305.     end
  4306.    
  4307.   end
  4308.  
  4309.   #============================================================================
  4310.   # BlizzABS::ObserveData
  4311.   #----------------------------------------------------------------------------
  4312.   #  This class provides a data interface for observation logs.
  4313.   #============================================================================
  4314.  
  4315.   class ObserveData
  4316.    
  4317.     # setting all accessible variables
  4318.     attr_accessor :damage
  4319.     attr_accessor :time
  4320.     #--------------------------------------------------------------------------
  4321.     # Initialization
  4322.     #  damage - the damage value
  4323.     #  time   - the moment in time when the damage was done
  4324.     #--------------------------------------------------------------------------
  4325.     def initialize(damage, time)
  4326.       @damage, @time = damage, time
  4327.     end
  4328.    
  4329.   end
  4330.  
  4331.   #============================================================================
  4332.   # BlizzABS::DamageRequest
  4333.   #----------------------------------------------------------------------------
  4334.   #  This class provides a data interface for damage sprite requests.
  4335.   #============================================================================
  4336.  
  4337.   class DamageRequest
  4338.    
  4339.     # setting all accessible variables
  4340.     attr_reader :x
  4341.     attr_reader :y
  4342.     attr_reader :damage
  4343.     attr_reader :critical
  4344.     attr_reader :color
  4345.     attr_reader :width
  4346.     attr_reader :height
  4347.     #--------------------------------------------------------------------------
  4348.     # Initialization
  4349.     #  char     - reference character for position
  4350.     #  damage   - the damage value
  4351.     #  color    - damage text color
  4352.     #  critical - critical flag
  4353.     #--------------------------------------------------------------------------
  4354.     def initialize(char, damage, color, critical = false)
  4355.       # set coordinates
  4356.       @x, @y = char.real_x / 4 + 16, char.real_y / 4 + 16
  4357.       # set damage text value
  4358.       @damage = (damage.is_a?(Numeric) ? damage.abs.to_s : damage.to_s)
  4359.       # set color and critical flag
  4360.       @color, @critical = color, critical
  4361.       # create dummy bitmap
  4362.       bitmap = Bitmap.new(1, 1)
  4363.       # set font
  4364.       bitmap.font.name = Cache::FontNameDamage
  4365.       # set font size
  4366.       bitmap.font.size = Cache::FontSizeDamage
  4367.       # get size rectangle
  4368.       size_rect = bitmap.text_size(@damage)
  4369.       # get text width and height
  4370.       @width, @height = (size_rect.width + 4) / 2 * 2, size_rect.height
  4371.       @width = 1 if @width < 1
  4372.       @height = 1 if @height < 1
  4373.     end
  4374.    
  4375.   end
  4376.  
  4377.   #============================================================================
  4378.   # BlizzABS::PathRequest
  4379.   #----------------------------------------------------------------------------
  4380.   #  This class provides a data interface for path requests.
  4381.   #============================================================================
  4382.  
  4383.   class PathRequest
  4384.    
  4385.     # setting all accessible variables
  4386.     attr_reader :open
  4387.     attr_reader :closed
  4388.     attr_reader :sx
  4389.     attr_reader :sy
  4390.     attr_reader :tx
  4391.     attr_reader :ty
  4392.     attr_reader :jd
  4393.     #--------------------------------------------------------------------------
  4394.     # Initialization
  4395.     #  ox - real x-coordinate of starting point
  4396.     #  oy - real y-coordinate of starting point
  4397.     #  tx - x-coordinate of target point
  4398.     #  ty - y-coordinate of target point
  4399.     #  jd - jump distance (optional)
  4400.     #--------------------------------------------------------------------------
  4401.     def initialize(ox, oy, tx, ty, jd = 0)
  4402.       # pixel movement rate
  4403.       pix = $BlizzABS.pixel
  4404.       # coordinates
  4405.       @sx, @sy, @tx, @ty, @jd = ox / pix, oy / pix, tx / pix, ty / pix, jd / pix
  4406.       # additional data
  4407.       @x_off, @y_off = ox - @sx * pix, oy - @sy * pix
  4408.       # nodes yet to check
  4409.       @open = {[@sx, @sy] => -1}
  4410.       # checked nodes
  4411.       @closed = Table.new($game_map.width, $game_map.height)
  4412.     end
  4413.     #--------------------------------------------------------------------------
  4414.     # backtrack
  4415.     #  Finds the way back from the target to the start to create a path.
  4416.     #--------------------------------------------------------------------------
  4417.     def backtrack
  4418.       # get pixel movement rate
  4419.       pix = $BlizzABS.pixel
  4420.       # current x, y, target x, y and resulting path
  4421.       cx, cy, x, y, result = @tx, @ty, 0, 0, []
  4422.       # find the way back from destination to start
  4423.       loop do
  4424.         # change current coordinates
  4425.         cx, cy = cx - x, cy - y
  4426.         # stop if reached corrected start position
  4427.         break if cx == @sx && cy == @sy
  4428.         # add movement command
  4429.         pix.times {result.unshift(Cache::TDirs[@closed[cx, cy]])}
  4430.         # track back next node
  4431.         x, y = Cache::DirOffsets[@closed[cx, cy]]
  4432.       end
  4433.       # modify found path if pixel movement is being used
  4434.       modify(result) if pix > 1
  4435.       # return result
  4436.       return result
  4437.     end
  4438.     #--------------------------------------------------------------------------
  4439.     # modify
  4440.     #  result - found path
  4441.     #  Modifies the path so it works with pixel movement
  4442.     #--------------------------------------------------------------------------
  4443.     def modify(result)
  4444.       # add correction movement commands for x and y
  4445.       @x_off.times {result.unshift(Cache::TDirs[4])}
  4446.       @y_off.times {result.unshift(Cache::TDirs[8])}
  4447.       # stop if not using 8 way movement
  4448.       return if !$game_system._8_way
  4449.       # add diagonal moving commands at positions where possible
  4450.       result.each_index {|i|
  4451.           # if both exist
  4452.           if result[i] != nil && result[i + 1] != nil
  4453.             # exchange of corner commands
  4454.             case [result[i][0], result[i + 1][0]]
  4455.             when Cache::DirDownLeft, Cache::DirLeftDown
  4456.               result[i], result[i + 1] = Cache::TDirs[1], nil
  4457.             when Cache::DirDownRight, Cache::DirRightDown
  4458.               result[i], result[i + 1] = Cache::TDirs[3], nil
  4459.             when Cache::DirLeftUp, Cache::DirUpLeft
  4460.               result[i], result[i + 1] = Cache::TDirs[7], nil
  4461.             when Cache::DirRightUp, Cache::DirUpRight
  4462.               result[i], result[i + 1] = Cache::TDirs[9], nil
  4463.             end
  4464.           end}
  4465.       # remove nils
  4466.       result.compact!
  4467.     end
  4468.    
  4469.   end
  4470.  
  4471.   #============================================================================
  4472.   # BlizzABS::AlignmentData
  4473.   #----------------------------------------------------------------------------
  4474.   #  This class provides a data interface for alignment groups.
  4475.   #============================================================================
  4476.  
  4477.   class AlignmentData
  4478.    
  4479.     # setting all accessible variables
  4480.     attr_accessor :id
  4481.     attr_accessor :enemies
  4482.     attr_accessor :allies
  4483.     attr_accessor :neutral
  4484.     #--------------------------------------------------------------------------
  4485.     # Initialization
  4486.     #--------------------------------------------------------------------------
  4487.     def initialize(id)
  4488.       @id = id
  4489.       @enemies = BlizzABS::Alignments.enemies(id)
  4490.       @allies = BlizzABS::Alignments.allies(id)
  4491.       @neutral = BlizzABS::Alignments.neutral(id)
  4492.     end
  4493.     #--------------------------------------------------------------------------
  4494.     # enemy?
  4495.     #  id - group ID
  4496.     #  Checks if a group is an enemy.
  4497.     #--------------------------------------------------------------------------
  4498.     def enemy?(id)
  4499.       return @enemies.include?(id)
  4500.     end
  4501.     #--------------------------------------------------------------------------
  4502.     # ally?
  4503.     #  id - group ID
  4504.     #  Checks if a group is an ally.
  4505.     #--------------------------------------------------------------------------
  4506.     def ally?(id)
  4507.       return @allies.include?(id)
  4508.     end
  4509.     #--------------------------------------------------------------------------
  4510.     # neutral?
  4511.     #  id - group ID
  4512.     #  Checks if a group is always neutral.
  4513.     #--------------------------------------------------------------------------
  4514.     def neutral?(id)
  4515.       return @neutral.include?(id)
  4516.     end
  4517.    
  4518.   end
  4519.  
  4520. end
  4521.  
  4522. module BlizzABS
  4523.  
  4524.   #============================================================================
  4525.   # BlizzABS::Controls
  4526.   #----------------------------------------------------------------------------
  4527.   #  This class handles player input for battle on the map.  Some input is
  4528.   #  processed instantly, while some is converted into commands to be given to
  4529.   #  the player character.
  4530.   #============================================================================
  4531.  
  4532.   class Controls
  4533.    
  4534.     attr_accessor :down_key
  4535.     attr_accessor :left_key
  4536.     attr_accessor :right_key
  4537.     attr_accessor :up_key
  4538.     attr_accessor :confirm_key
  4539.     attr_accessor :cancel_key
  4540.     attr_accessor :attack_key
  4541.     attr_accessor :prevpage_key
  4542.     attr_accessor :nextpage_key
  4543.     attr_accessor :defend_key
  4544.     attr_accessor :skill_key
  4545.     attr_accessor :item_key
  4546.     attr_accessor :select_key
  4547.     attr_accessor :hud_key
  4548.     attr_accessor :minimap_key
  4549.     attr_accessor :hotkey_key
  4550.     attr_accessor :run_key
  4551.     attr_accessor :sneak_key
  4552.     attr_accessor :jump_key
  4553.     attr_accessor :turn_key
  4554.    
  4555.     #--------------------------------------------------------------------------
  4556.     # update
  4557.     #  Processes the player's input.
  4558.     #--------------------------------------------------------------------------
  4559.     def update
  4560.       # if not allowed to act
  4561.       if !$game_temp.in_battle || $game_player.jumping? ||
  4562.           $game_player.freeze_action || $game_player.move_route_forcing ||
  4563.           $game_player.in_action > 0 && !$game_player.ai.act.defend? ||
  4564.           !$game_player.valid?
  4565.         # freeze battle controls
  4566.         return
  4567.       end
  4568.       # stop update if defending
  4569.       return if update_defend
  4570.       # if defending before
  4571.       if $game_player.ai.act.defend?
  4572.         # override defending reset
  4573.         $game_player.ai.act.set
  4574.         # reset action
  4575.         $game_player.reset_action
  4576.         # reset sprites
  4577.         $game_player.reset_sprites
  4578.       end
  4579.       # stop update if attacking
  4580.       return if update_attack
  4581.       # stop update if using skill
  4582.       return if update_skill
  4583.       # stop update if using item
  4584.       return if update_item
  4585.     end
  4586.     #--------------------------------------------------------------------------
  4587.     # update_defend
  4588.     #  Processes the player's defend input.
  4589.     #--------------------------------------------------------------------------
  4590.     def update_defend
  4591.       # continue input update if defend button not pressed
  4592.       return false if !self.check_defend_condition?
  4593.       # player defends
  4594.       $game_player.use_defend
  4595.       # setup action data
  4596.       $game_player.ai.act.set(0, BlizzABS::ACTDefend, 0, 0, 1)
  4597.       # stop input update
  4598.       return true
  4599.     end
  4600.     #--------------------------------------------------------------------------
  4601.     # update_attack
  4602.     #  Processes the player's attack input.
  4603.     #--------------------------------------------------------------------------
  4604.     def update_attack
  4605.       # continue input update if attack should not be used
  4606.       return false if !self.check_attack_condition?
  4607.       # if attack not successful
  4608.       if !$game_player.use_attack
  4609.         # play buzzer, can't use
  4610.         $game_system.se_play($data_system.buzzer_se)
  4611.       end
  4612.       # stop input update
  4613.       return true
  4614.     end
  4615.     #--------------------------------------------------------------------------
  4616.     # update_skill
  4617.     #  Processes the player's skill input.
  4618.     #--------------------------------------------------------------------------
  4619.     def update_skill
  4620.       # continue input update if skill should be used
  4621.       return false if !self.check_skill_condition?
  4622.       # if skill not usable or skill use process not executed and no selection
  4623.       if $game_player.battler.skill == 0 ||
  4624.           !$game_player.use_skill($data_skills[$game_player.battler.skill]) &&
  4625.           $game_temp.select_data == nil
  4626.         # play buzzer, can't use
  4627.         $game_system.se_play($data_system.buzzer_se)
  4628.       end
  4629.       # stop input update
  4630.       return true
  4631.     end
  4632.     #--------------------------------------------------------------------------
  4633.     # update_item
  4634.     #  Processes the player's item input.
  4635.     #--------------------------------------------------------------------------
  4636.     def update_item
  4637.       # continue input if item should be used
  4638.       return false if !self.check_item_condition?
  4639.       # if item not usable or item use process not executed and no selection
  4640.       if $game_player.battler.item == 0 ||
  4641.           !$game_player.use_item($data_items[$game_player.battler.item]) &&
  4642.           $game_temp.select_data == nil
  4643.         # play buzzer, can't use
  4644.         $game_system.se_play($data_system.buzzer_se)
  4645.       end
  4646.       # stop input update
  4647.       return true
  4648.     end
  4649.     #--------------------------------------------------------------------------
  4650.     # check_defend_condition?
  4651.     #  Checks whether defend should be executed or not.
  4652.     #--------------------------------------------------------------------------
  4653.     def check_defend_condition?
  4654.       # defend button enabled and defend button is pressed
  4655.       return ($game_system.defend_button && Input.press?(Input::Defend))
  4656.     end
  4657.     #--------------------------------------------------------------------------
  4658.     # check_attack_condition?
  4659.     #  Checks whether attack should be executed or not.
  4660.     #--------------------------------------------------------------------------
  4661.     def check_attack_condition?
  4662.       # attack button enabled and attack button is pressed
  4663.       return ($game_system.attack_button && Input.trigger?(Input::Attack))
  4664.     end
  4665.     #--------------------------------------------------------------------------
  4666.     # check_skill_condition?
  4667.     #  Checks whether a skill should be executed or not.
  4668.     #--------------------------------------------------------------------------
  4669.     def check_skill_condition?
  4670.       # disallow usage if skill button disabled
  4671.       return false if !$game_system.skill_button
  4672.       # disallow usage
  4673.       skill_condition = false
  4674.       # if using direct hotkeys
  4675.       if BlizzABS::Config::DIRECT_HOTKEYS
  4676.         # check direct hotkeys
  4677.         skill_condition = self.skill_hotkeys?
  4678.       # if skill button pressed
  4679.       elsif Input.trigger?(Input::Skill)
  4680.         # allow usage
  4681.         skill_condition = true
  4682.       end
  4683.       # return result
  4684.       return skill_condition
  4685.     end
  4686.     #--------------------------------------------------------------------------
  4687.     # check_item_condition?
  4688.     #  Checks whether a item should be executed or not.
  4689.     #--------------------------------------------------------------------------
  4690.     def check_item_condition?
  4691.       # disallow usage if item button disabled
  4692.       return false if !$game_system.item_button
  4693.       # disallow usage
  4694.       item_condition = false
  4695.       # if using direct hotkeys
  4696.       if BlizzABS::Config::DIRECT_HOTKEYS
  4697.         # check direct hotkeys
  4698.         item_condition = self.item_hotkeys?
  4699.       # if item button pressed
  4700.       elsif Input.trigger?(Input::Item)
  4701.         # allow usage
  4702.         item_condition = true
  4703.       end
  4704.       # return result
  4705.       return item_condition
  4706.     end
  4707.     #--------------------------------------------------------------------------
  4708.     # skill_hotkeys?
  4709.     #  Checks direct hotkey usage for skills.
  4710.     #--------------------------------------------------------------------------
  4711.     def skill_hotkeys?
  4712.       # find all triggered keys
  4713.       triggered = BlizzABS::Cache::Keys.find_all {|i|
  4714.           (Input.trigger?(Input::Key[i.to_s]) ||
  4715.           Input.trigger?(Input::Key["NumberPad " + i.to_s])) &&
  4716.           $game_player.skill_hotkeys[i] != 0}
  4717.       # no usage if usage invalid
  4718.       return false if triggered.size == 0
  4719.       # set as usable item
  4720.       $game_player.battler.skill = $game_player.skill_hotkeys[triggered[0]]
  4721.       # allow usage
  4722.       return true
  4723.     end
  4724.     #--------------------------------------------------------------------------
  4725.     # item_hotkeys?
  4726.     #  Checks direct hotkey usage for item.
  4727.     #--------------------------------------------------------------------------
  4728.     def item_hotkeys?
  4729.       # find all triggered keys
  4730.       triggered = BlizzABS::Cache::Keys.find_all {|i|
  4731.           (Input.trigger?(Input::Key[i.to_s]) ||
  4732.           Input.trigger?(Input::Key["NumberPad " + i.to_s])) &&
  4733.           $game_player.item_hotkeys[i] != 0}
  4734.       # no usage if usage invalid
  4735.       return false if triggered.size == 0
  4736.       # set as usable item
  4737.       $game_player.battler.item = $game_player.item_hotkeys[triggered[0]]
  4738.       # allow usage
  4739.       return true
  4740.     end
  4741.    
  4742.   end
  4743.  
  4744. end
  4745.  
  4746. module BlizzABS
  4747.  
  4748.   #============================================================================
  4749.   # BlizzABS::Utility
  4750.   #----------------------------------------------------------------------------
  4751.   #  This class provides methods for Blizz-ABS's additional capabilities that
  4752.   #  can't be categorized elsewhere.
  4753.   #============================================================================
  4754.  
  4755.   class Utility
  4756.    
  4757.     # constants
  4758.     SQRT_2 = Math.sqrt(2)
  4759.    
  4760.     #--------------------------------------------------------------------------
  4761.     # request_path
  4762.     #  x1 - x target coordinate of start
  4763.     #  y1 - y target coordinate or start
  4764.     #  x2 - x target coordinate of end
  4765.     #  y2 - y target coordinate or end
  4766.     #  Finds a path between points.
  4767.     #--------------------------------------------------------------------------
  4768.     def request_path(x1, y1, x2, y2)
  4769.       return PathRequest.new(x1*pix, y1*pix, x2*pix, y2*pix)
  4770.     end
  4771.     #--------------------------------------------------------------------------
  4772.     # get_weapon_area
  4773.     #  ch   - map character
  4774.     #  d    - distance
  4775.     #  type - area affection type
  4776.     #  Returns area data for the given character, range and type.
  4777.     #--------------------------------------------------------------------------
  4778.     def get_attack_area(ch, d, type)
  4779.       return case type
  4780.       when SWORD then get_circle_area(ch, d, ch.direction)
  4781.       when SPEAR then get_front_area(ch, d)
  4782.       when FLAIL then get_skipped_front_area(ch, d)
  4783.       when BOOMERANG, BOW, BOW_ARROW, SHURIKEN then get_projectile_area(ch, d)
  4784.       end
  4785.     end
  4786.     #--------------------------------------------------------------------------
  4787.     # get_skillitem_area
  4788.     #  ch    - map character
  4789.     #  d     - distance
  4790.     #  type  - area affection type
  4791.     #  scope - object scope
  4792.     #  Returns area data for the given character, range and type.
  4793.     #--------------------------------------------------------------------------
  4794.     def get_skillitem_area(ch, d, type, scope)
  4795.       # all flag
  4796.       all = (scope == 2 || scope == 4 || scope == 6)
  4797.       # if circle skill
  4798.       if type == HOMING || type == DIRECT || type != SHOOT &&
  4799.           type != BEAM && all
  4800.         # create circle area
  4801.         area = get_circle_area(ch, d)
  4802.       # if fullscreen skill
  4803.       elsif type == BEAM && all
  4804.         # create fullscreen rectangle shape
  4805.         area = get_fullscreen_area
  4806.       # if beam
  4807.       elsif type == BEAM
  4808.         # determine affection area depending on facing direction for beam area
  4809.         area = get_front_area(ch, d)
  4810.       else
  4811.         # create affection area rectangle for projectiles
  4812.         area = get_projectile_area(ch, d)
  4813.       end
  4814.       # return result
  4815.       return area
  4816.     end
  4817.     #--------------------------------------------------------------------------
  4818.     # get_circle_area
  4819.     #  ch  - map character
  4820.     #  d   - distance
  4821.     #  dir - direction of the circle slice if necessary
  4822.     #  Returns area data for the given character and range for circle area.
  4823.     #--------------------------------------------------------------------------
  4824.     def get_circle_area(ch, d, dir = 0)
  4825.       return Circle.new(ch.real_x / 4 + 16, ch.real_y / 4 + 16, d * 32, dir)
  4826.     end
  4827.     #--------------------------------------------------------------------------
  4828.     # get_projectile_area
  4829.     #  ch - map character
  4830.     #  d  - distance
  4831.     #  Returns area data for the given character and range for projectiles.
  4832.     #--------------------------------------------------------------------------
  4833.     def get_projectile_area(ch, d)
  4834.       return case ch.direction
  4835.       when 2 then Rect.new(ch.real_x / 4 + 8, ch.real_y / 4 + 16, 16, d * 32)
  4836.       when 4 then Rect.new(ch.real_x / 4 + 16 - d * 32, ch.real_y / 4 + 8, d * 32, 16)
  4837.       when 6 then Rect.new(ch.real_x / 4 + 16, ch.real_y / 4 + 8, d * 32, 16)
  4838.       when 8 then Rect.new(ch.real_x / 4 + 8, ch.real_y / 4 + 16 - d * 32, 16, d * 32)
  4839.       end
  4840.     end
  4841.     #--------------------------------------------------------------------------
  4842.     # get_projectile_hit_area
  4843.     #  ch - projectile character
  4844.     #  Returns area data for the given projectile.
  4845.     #--------------------------------------------------------------------------
  4846.     def get_projectile_hit_area(ch)
  4847.       pix = $BlizzABS.pixel
  4848.       return case ch.direction
  4849.       when 2
  4850.         Rect.new(ch.real_x / 4 + 8, ch.real_y / 4 + 8, 16, ch.y * 32 / pix - ch.real_y / 4 + 24)
  4851.       when 4
  4852.         Rect.new(ch.x * 32 / pix + 8, ch.y * 32 / pix + 8, ch.real_x / 4 - ch.x * 32 / pix + 24, 16)
  4853.       when 6
  4854.         Rect.new(ch.real_x / 4 + 8, ch.real_y / 4 + 8, ch.x * 32 / pix-ch.real_x / 4 + 24, 16)
  4855.       when 8
  4856.         Rect.new(ch.x * 32 / pix + 8, ch.y * 32 / pix + 8, 16, ch.real_y / 4 - ch.y * 32 / pix + 24)
  4857.       end
  4858.     end
  4859.     #--------------------------------------------------------------------------
  4860.     # get_front_area
  4861.     #  ch - map character
  4862.     #  d  - distance
  4863.     #  Returns area data for the given character and range of the front area.
  4864.     #--------------------------------------------------------------------------
  4865.     def get_front_area(ch, d)
  4866.       return case ch.direction
  4867.       when 2 then Rect.new(ch.real_x / 4, ch.real_y / 4 + 16, 32, d * 32)
  4868.       when 4 then Rect.new(ch.real_x / 4 + 16 - d * 32, ch.real_y / 4, d * 32, 32)
  4869.       when 6 then Rect.new(ch.real_x / 4 + 16, ch.real_y / 4, d * 32, 32)
  4870.       when 8 then Rect.new(ch.real_x / 4, ch.real_y / 4 + 16 - d * 32, 32, d * 32)
  4871.       end
  4872.     end
  4873.     #--------------------------------------------------------------------------
  4874.     # get_skipped_front_area
  4875.     #  ch - map character
  4876.     #  d  - distance
  4877.     #  Returns area data for the given character and range of second half of
  4878.     #  the front area.
  4879.     #--------------------------------------------------------------------------
  4880.     def get_skipped_front_area(ch, d)
  4881.       return case ch.direction
  4882.       when 2 then Rect.new(ch.real_x / 4, ch.real_y / 4 + 16 + d * 16, 32, d * 16)
  4883.       when 4 then Rect.new(ch.real_x / 4 + 16 - d * 32, ch.real_y / 4, d * 16, 32)
  4884.       when 6 then Rect.new(ch.real_x / 4 + 16 + d * 16, ch.real_y / 4, d * 16, 32)
  4885.       when 8 then Rect.new(ch.real_x / 4, ch.real_y / 4 + 16 - d * 32, 32, d * 16)
  4886.       end
  4887.     end
  4888.     #--------------------------------------------------------------------------
  4889.     # get_fullscreen_area
  4890.     #  Returns area data for the entire screen.
  4891.     #--------------------------------------------------------------------------
  4892.     def get_fullscreen_area
  4893.       return Rect.new($game_map.display_x / 4, $game_map.display_y / 4, 640, 480)
  4894.     end
  4895.     #--------------------------------------------------------------------------
  4896.     # get_scope_data
  4897.     #  scope - the targeting scope
  4898.     #  Returns the data for scopes "enemy, dead, all".
  4899.     #--------------------------------------------------------------------------
  4900.     def get_scope_data(scope)
  4901.       return case scope
  4902.       when 0 then [false, false, false]
  4903.       when 1 then [true, false, false]
  4904.       when 2 then [true, false, true]
  4905.       when 3 then [false, false, false]
  4906.       when 4 then [false, false, true]
  4907.       when 5 then [false, true, false]
  4908.       when 6 then [false, true, true]
  4909.       when 7 then [false, false, false]
  4910.       else
  4911.         [false, false, false]
  4912.       end
  4913.     end
  4914.     #--------------------------------------------------------------------------
  4915.     # get_player_radius
  4916.     #  Returns the distance of the farthest point from the player on the
  4917.     #  screen.
  4918.     #--------------------------------------------------------------------------
  4919.     def get_player_radius
  4920.       # if in the right half of the screen
  4921.       if $game_player.screen_x > 320
  4922.         # get screen x
  4923.         x_max = $game_player.screen_x
  4924.       else
  4925.         # get other screen x
  4926.         x_max = 640 - $game_player.screen_x
  4927.       end
  4928.       # if in the lower half of the screen
  4929.       if $game_player.screen_y > 240
  4930.         # get screen y
  4931.         y_max = $game_player.screen_y
  4932.       else
  4933.         # get other screen y
  4934.         y_max = 480 - $game_player.screen_y
  4935.       end
  4936.       # return distance
  4937.       return Math.hypot(x_max, y_max) / 32
  4938.     end
  4939.     #--------------------------------------------------------------------------
  4940.     # get_damage_data
  4941.     #  battler - battler or direct damage string
  4942.     #  Returns an array of colors for each damage sprite.
  4943.     #--------------------------------------------------------------------------
  4944.     def get_damage_data(battler)
  4945.       # if not a battler
  4946.       if !battler.is_a?(Game_Battler)
  4947.         # if a color exists for this object
  4948.         if Cache::DMGColors.has_key?(battler)
  4949.           # return color and string
  4950.           return [[Cache::DMGColors[battler]], [battler.to_s]]
  4951.         else
  4952.           # return color and string
  4953.           return [[Cache::DMGColors['Default']], [battler.to_s]]
  4954.         end
  4955.       end
  4956.       # if color cache exists
  4957.       if Cache::DMGColors.has_key?(battler.damage)
  4958.         # get color
  4959.         colors = [Cache::DMGColors[battler.damage]]
  4960.         # get string
  4961.         damages = [battler.damage.to_s]
  4962.       # normal damage
  4963.       elsif battler.damage.is_a?(Numeric)
  4964.         # no colors and no strings
  4965.         colors, damages = [], []
  4966.       else
  4967.         # default color
  4968.         colors = [Cache::DMGColors['Default']]
  4969.         # get string
  4970.         damages = [battler.damage.to_s]
  4971.       end
  4972.       # color key sign
  4973.       sign = (battler.is_a?(Game_Enemy) ? 'E' : 'A')
  4974.       # if HP change
  4975.       if battler.hpdamage != 0
  4976.         # if critical
  4977.         if battler.critical
  4978.           # critical damage color
  4979.           colors.push(Cache::DMGColors['Critical'])
  4980.         # if losing HP
  4981.         elsif battler.hpdamage > 0
  4982.           # normal color
  4983.           colors.push(Cache::DMGColors['HP-' + sign])
  4984.         elsif battler.hpdamage < 0
  4985.           # normal color
  4986.           colors.push(Cache::DMGColors['HP+' + sign])
  4987.         end
  4988.         # create damage for HP change
  4989.         damages.push(battler.hpdamage.abs.to_s)
  4990.       end
  4991.       # if SP change
  4992.       if battler.spdamage != 0
  4993.         # if critical
  4994.         if battler.critical
  4995.           # critical damage color
  4996.           colors.push(Cache::DMGColors['Critical'])
  4997.         # if losing SP
  4998.         elsif battler.spdamage > 0
  4999.           # normal color
  5000.           colors.push(Cache::DMGColors['SP-' + sign])
  5001.         # if restoring SP
  5002.         elsif battler.spdamage < 0
  5003.           # normal color
  5004.           colors.push(Cache::DMGColors['SP+' + sign])
  5005.         end
  5006.         # create damage for SP change
  5007.         damages.push("#{battler.spdamage.abs} #{$data_system.words.sp}")
  5008.       end
  5009.       # return colors
  5010.       return [colors, damages]
  5011.     end
  5012.     #--------------------------------------------------------------------------
  5013.     # request_damage_sprite
  5014.     #  char - map character
  5015.     #  Requests a sprite for damage display.
  5016.     #--------------------------------------------------------------------------
  5017.     def request_damage_sprite(char, damage = nil)
  5018.       # stop if no damage sprites flag
  5019.       return if char.no_dmg_sprites
  5020.       # if map battler
  5021.       if damage != nil
  5022.         # get damage text colors and strings
  5023.         colors, damages = self.get_damage_data(damage)
  5024.       else
  5025.         # get damage text colors and strings
  5026.         colors, damages = self.get_damage_data(char.battler)
  5027.       end
  5028.       # for each existing color
  5029.       colors.each_index {|i|
  5030.           # create one damage sprite request
  5031.           $BlizzABS.cache.damages.push(DamageRequest.new(char, damages[i],
  5032.               colors[i], char.battler.critical))}
  5033.     end
  5034.     #----------------------------------------------------------------------------
  5035.     # reset_alignment_group
  5036.     #  id - group ID
  5037.     #  Resets the given alignment groups setup to default.
  5038.     #----------------------------------------------------------------------------
  5039.     def reset_alignment_group(id)
  5040.       # create new alignment data
  5041.       $game_system.alignments[id] = BlizzABS::AlignmentData.new(id)
  5042.       # for all battlers of this group on the map
  5043.       $game_map.battlers_group(id).each {|b|
  5044.           # reset the alignment setup
  5045.           b.ai.setup_group(id)
  5046.           # delete moving commands
  5047.           b.force_move = []
  5048.           # reset the alignment setup
  5049.           b.reset_action}
  5050.     end
  5051.     #--------------------------------------------------------------------------
  5052.     # display_levelup
  5053.     #  actor - the actor that leveled up.
  5054.     #  Creates a damage sprite request for level up display.
  5055.     #--------------------------------------------------------------------------
  5056.     def display_levelup(actor)
  5057.       # get damage text colors and strings
  5058.       colors, damages = self.get_damage_data(Cache::TXTLvlUp)
  5059.       # for each existing color
  5060.       colors.each_index {|i|
  5061.           # create one damage sprite request
  5062.           $BlizzABS.cache.damages.push(DamageRequest.new(actor, damages[i],
  5063.               colors[i]))}
  5064.     end
  5065.     #--------------------------------------------------------------------------
  5066.     # intersection
  5067.     #  shape - either rectangle or a data array with circle data
  5068.     #  rect  - rectangle
  5069.     #  Processes and test intersection of rectangles, a rectangle with a full
  5070.     #  circle and a rectangle with a fourth of a circle in which the user of an
  5071.     #  attack/skill/item is facing. The shapes get tested on whether at least
  5072.     #  one point of the rectangle is within the shape and if not, then this
  5073.     #  method checks whether the shape's characteristic lines determined by the
  5074.     #  center points and a few point on the borders intersect with the
  5075.     #  rectangle. This polygon intersection determination is a simplified
  5076.     #  version, sufficient for Blizz-ABS that needs less CPU time than a full
  5077.     #  determination algorithm.
  5078.     #--------------------------------------------------------------------------
  5079.     def intersection(shape, rect)
  5080.       # if both are rectangles return rectangle intersection result
  5081.       return rect_intersection(shape, rect) if shape.is_a?(Rect)
  5082.       # temporary variables
  5083.       x, y, r, d = shape.x, shape.y, shape.radius, shape.direction
  5084.       # iterate through all of rectangle's points
  5085.       [rect.x, rect.x+rect.width-1].each {|i| [rect.y, rect.y+rect.height-1].each {|j|
  5086.           # if within special circle radius
  5087.           if Math.hypot(x - i, y - j) < r ||
  5088.               Math.hypot(x - i - 1, y - j) < r ||
  5089.               Math.hypot(x - i, y - j - 1) < r ||
  5090.               Math.hypot(x - i - 1, y - j - 1) < r
  5091.             case d
  5092.             when 2 then return true if j - y >= 0 && i - x <= j - y && x - i - 1 <= j - y
  5093.             when 4 then return true if x - i - 1 >= 0 && j - y <= x - i - 1 && y - j - 1 <= x - i - 1
  5094.             when 6 then return true if i - x >= 0 && j - y <= i - x && y - j - 1 <= i - x
  5095.             when 8 then return true if y - j -1 >= 0 && i - x <= y - j - 1 && x - i - 1 <= y - j - 1
  5096.             else
  5097.               # full circle, intersection exists
  5098.               return true
  5099.             end
  5100.           end}}
  5101.       # initialize arrays
  5102.       rects, coos, rad = [], [], (r / SQRT_2).to_i
  5103.       # radius line end coordinates and rectangles depending on which circle part
  5104.       case d
  5105.       when 2
  5106.         coos.push([x - 1 - rad, y + rad])
  5107.         coos.push([2 * x - coos[0][0] - 1, coos[0][1]])
  5108.         rects.push(Rect.new(x - 1, y, 2, r))
  5109.       when 4
  5110.         coos.push([x - 1 - rad, y - 1 - rad])
  5111.         coos.push([coos[0][0], 2 * y - coos[0][1] - 1])
  5112.         rects.push(Rect.new(x - r, y - 1, r, 2))
  5113.       when 6
  5114.         coos.push([x+rad.to_i, y - 1 - rad])
  5115.         coos.push([coos[0][0], 2 * y - coos[0][1] - 1])
  5116.         rects.push(Rect.new(x, y - 1, r, 2))
  5117.       when 8
  5118.         coos.push([x - 1 - rad, y - 1 - rad])
  5119.         coos.push([2 * x - coos[0][0] - 1, coos[0][1]])
  5120.         rects.push(Rect.new(x - 1, y - r, 2, r))
  5121.       else
  5122.         rects.push(Rect.new(x - 1, y, 2, r), Rect.new(x - r - 1, y - 1, r, 2),
  5123.             Rect.new(x, y - 1, r, 2), Rect.new(x - 1, y - r - 1, 2, r))
  5124.       end
  5125.       # intersection exists if intersecting with any of the radius rectangles
  5126.       return true if rects.any? {|rec| rect_intersection(rect, rec)}
  5127.       # rectangle's border lines
  5128.       top_left = [rect.x, rect.y]
  5129.       bottom_right = [rect.x + rect.width - 1, rect.y + rect.height - 1]
  5130.       bottom_left = [rect.x, rect.y + rect.height - 1]
  5131.       top_right = [rect.x + rect.width - 1, rect.y]
  5132.       # iterate through rectangle's border lines
  5133.       [top_left, bottom_right].each {|i| [bottom_left, top_right].each {|j|
  5134.           # iterate through the characteristic lines
  5135.           coos.each {|c|
  5136.               # if borderline of rectangle intersects with diagonal radius line
  5137.               if line_intersection(i[0], i[1], j[0], j[1], c[0], c[1], x, y)
  5138.                 # intersection exists
  5139.                 return true
  5140.               end}}}
  5141.       # intersection does not exist
  5142.       return false
  5143.     end
  5144.     #--------------------------------------------------------------------------
  5145.     # rect_intersection
  5146.     #  r1 - rectangle 1
  5147.     #  r2 - rectangle 2
  5148.     #  Quickly determines intersection of two rectangles. It is faster than the
  5149.     #  algorithm to determine line intersection as both rectangles are always
  5150.     #  rectangles with a rotation angle of 0, 90, 180 or 270.
  5151.     #--------------------------------------------------------------------------
  5152.     def rect_intersection(r1, r2)
  5153.       return (r1.x + r1.width > r2.x && r1.x < r2.x + r2.width &&
  5154.               r1.y + r1.height > r2.y && r1.y < r2.y + r2.height)
  5155.     end
  5156.     #--------------------------------------------------------------------------
  5157.     # line_intersection
  5158.     #  x1 - x-coordinate of the line 1's first point
  5159.     #  y1 - y-coordinate of the line 1's first point
  5160.     #  x1 - x-coordinate of the line 1's second point
  5161.     #  y1 - y-coordinate of the line 1's second point
  5162.     #  x1 - x-coordinate of the line 2's first point
  5163.     #  y1 - y-coordinate of the line 2's first point
  5164.     #  x1 - x-coordinate of the line 2's second point
  5165.     #  y1 - y-coordinate of the line 2's second point
  5166.     #  Uses a quick algorithm to test whether two lines intersect.
  5167.     #--------------------------------------------------------------------------
  5168.     def line_intersection(x1, y1, x2, y2, x3, y3, x4, y4)
  5169.       # calculate vector products
  5170.       d1 = (x3 - x1) * (y4 - y1) - (x4 - x1) * (y3 - y1)
  5171.       d2 = (x3 - x2) * (y4 - y2) - (x4 - x2) * (y3 - y2)
  5172.       d3 = (x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3)
  5173.       d4 = (x1 - x4) * (y2 - y4) - (x2 - x4) * (y1 - y4)
  5174.       # check vector product results
  5175.       if (d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) &&
  5176.           (d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0)
  5177.         # intersection exists
  5178.         return true
  5179.       end
  5180.       # if at least one point of one line lies on the other line
  5181.       if d1 == 0 && (x3 < x4 ? x3 : x4) <= x1 && x1 <= (x3 > x4 ? x3 : x4) &&
  5182.                      (y3 < y4 ? y3 : y4) <= y1 && y1 <= (y3 > y4 ? y3 : y4) ||
  5183.           d2 == 0 && (x3 < x4 ? x3 : x4) <= x2 && x2 <= (x3 > x4 ? x3 : x4) &&
  5184.                      (y3 < y4 ? y3 : y4) <= y2 && y2 <= (y3 > y4 ? y3 : y4) ||
  5185.           d3 == 0 && (x1 < x2 ? x1 : x2) <= x3 && x3 <= (x1 > x2 ? x1 : x2) &&
  5186.                      (y1 < y2 ? y1 : y2) <= y3 && y3 <= (y1 > y2 ? y1 : y2) ||
  5187.           d4 == 0 && (x1 < x2 ? x1 : x2) <= x4 && x4 <= (x1 > x2 ? x1 : x2) &&
  5188.                      (y1 < y2 ? y1 : y2) <= y4 && y4 <= (y1 > y2 ? y1 : y2)
  5189.         # intersection exists
  5190.         return true
  5191.       end
  5192.       # intersection does not exist
  5193.       return false
  5194.     end
  5195.     #--------------------------------------------------------------------------
  5196.     # get_direction
  5197.     #  x - the x component
  5198.     #  y - the y component
  5199.     #  Returns the 0-9 direction corresponding to the x and y components.
  5200.     #--------------------------------------------------------------------------
  5201.     def get_direction(x, y)
  5202.       return 0 if x == 0 && y == 0 # center
  5203.       theta = (Math.atan2(y, x) * 4 / Math::PI).round
  5204.       case theta
  5205.       when -4 then return 4 # left
  5206.       when -3 then return 1 # down left
  5207.       when -2 then return 2 # down
  5208.       when -1 then return 3 # down right
  5209.       when 0 then return 6 # right
  5210.       when 1 then return 9 # up right
  5211.       when 2 then return 8 # up
  5212.       when 3 then return 7 # up left
  5213.       when 4 then return 4 # left
  5214.       end
  5215.       return 0
  5216.     end
  5217.     #--------------------------------------------------------------------------
  5218.     # range_array_union
  5219.     #  a - this array of intervals
  5220.     #  b - other array of intervals
  5221.     #  Returns an array of time intervals that is the union of two other
  5222.     #  arrays. Both arrays' intervals are united.
  5223.     #--------------------------------------------------------------------------
  5224.     def range_array_union(a, b)
  5225.       # convert starting numbers to ranges
  5226.       a[a.size-1] = a[a.size-1]..Graphics.frame_count if a[a.size-1].is_a?(Numeric)
  5227.       b[b.size-1] = b[b.size-1]..Graphics.frame_count if b[b.size-1].is_a?(Numeric)
  5228.       # initialize indices
  5229.       i = j = 0
  5230.       # stop if either interval doesn't exist
  5231.       return if a[i] == nil || b[j] == nil
  5232.       # start iteration
  5233.       loop do
  5234.         # if both arrays' last element
  5235.         if a[i + 1] == nil && b[j + 1] == nil
  5236.           # if not intersecting intervals
  5237.           if a[i].first > b[j].last + 1 || b[j].first > a[i].last + 1
  5238.             # add both ranges sorted
  5239.             a[i].first < b[j].first ? a[i + 1] = b[j] : (a[i + 1], a[i] = a[i], b[j])
  5240.           else
  5241.             # get range borders
  5242.             min_pos = (a[i].first < b[j].first ? a[i].first : b[j].first)
  5243.             max_pos = (a[i].last > b[j].last ? a[i].last : b[j].last)
  5244.             # interval union is the last element
  5245.             a[i] = min_pos..max_pos
  5246.           end
  5247.           # abort iteration
  5248.           break
  5249.         # if no more elements in this array
  5250.         elsif a[i] == nil
  5251.           # add all elements from other array
  5252.           a += b[j, b.size - j]
  5253.           # abort iteration
  5254.           break
  5255.         # if no more elements in other array
  5256.         elsif b[j] == nil
  5257.           # abort iteration
  5258.           break
  5259.         # if other intervals is after this interval
  5260.         elsif b[j].first > a[i].last + 1
  5261.           # check next interval of this array
  5262.           i += 1
  5263.         # if array is after other array or other interval is within this one
  5264.         elsif a[i].first > b[j].last + 1
  5265.           # add other interval into this array
  5266.           a.insert(i, b[j])
  5267.           # check next interval of this array
  5268.           i += 1
  5269.           # check next interval of other array
  5270.           j += 1
  5271.         elsif a[i].first >= b[j].first && a[i].last <= b[j].last
  5272.           # check next interval of other array
  5273.           j += 1
  5274.         # if other interval starts before and ends before this interval
  5275.         elsif a[i].first < b[j].first && a[i].last > b[j].last
  5276.           # unite intervals
  5277.           a[i] = b[j].first..a[i].last
  5278.           # check next interval of other array
  5279.           j += 1
  5280.         # if other interval ends after this interval
  5281.         else
  5282.           # get range borders
  5283.           min_pos = (a[i].first < b[j].first ? a[i].first : b[j].first)
  5284.           # unite intervals
  5285.           a[i] = min_pos..b[j].last
  5286.           # as longs as intervals of this array intersect with this interval
  5287.           while a[i + 1] != nil && a[i].last + 1 >= a[i + 1].first
  5288.             # get range borders
  5289.             max_pos = (a[i].last > a[i + 1].last ? a[i].last : a[i + 1].last)
  5290.             # unite this interval and next interval of this array
  5291.             a[i] = a[i].first..max_pos
  5292.             # delete next interval of this array
  5293.             a.delete_at(i + 1)
  5294.           end
  5295.           # check next interval of other array
  5296.           j += 1
  5297.         end
  5298.       end
  5299.       # if last range is a converted start number
  5300.       if a.size > 0 && a[a.size - 1].last == Graphics.frame_count
  5301.         # convert back
  5302.         a[a.size - 1] = a[a.size - 1].first
  5303.       end
  5304.     end
  5305.     #--------------------------------------------------------------------------
  5306.     # closest_floor
  5307.     #  x - x start coordinate
  5308.     #  y - y start coordinate
  5309.     #  Finds the closest tile relative to the starting coordinates that does
  5310.     #  not have a terrain tag indicating that there is no floor beneath. If
  5311.     #  none is found, the method returns the starting coordinates.
  5312.     #--------------------------------------------------------------------------
  5313.     def closest_floor(x, y)
  5314.       # create mark table and pending array
  5315.       table, pending = Table.new($game_map.width, $game_map.height), [[x, y]]
  5316.       # as long as there are pending coordinates
  5317.       while pending.size > 0
  5318.         # current coordinates
  5319.         cx, cy = pending.shift
  5320.         # if floor beneath
  5321.         if !Config::NO_FLOOR_TAGS.include?($game_map.terrain_tag(cx, cy))
  5322.           # return found coordinates
  5323.           return [cx, cy]
  5324.         end
  5325.         # mark current coordinates as checked
  5326.         table[cx, cy] = 1
  5327.         # add tiles around current coordinates if they were not marked yet
  5328.         pending.push([cx, cy+1]) if table[cx, cy+1] == 0
  5329.         pending.push([cx-1, cy]) if table[cx-1, cy] == 0
  5330.         pending.push([cx+1, cy]) if table[cx+1, cy] == 0
  5331.         pending.push([cx, cy-1]) if table[cx, cy-1] == 0
  5332.       end
  5333.       return [x, y]
  5334.     end
  5335.     #--------------------------------------------------------------------------
  5336.     # get_actor_skills
  5337.     #  actor - the actor
  5338.     #  Safe method to return all skills that an actor can use. It's main
  5339.     #  purpose is overriding so other scripts (like CRLS) can add their own
  5340.     #  skill sets without changing vital parts of Blizz-ABS.
  5341.     #--------------------------------------------------------------------------
  5342.     def get_actor_skills(actor)
  5343.       return actor.skills.clone
  5344.     end
  5345.     #--------------------------------------------------------------------------
  5346.     # decode_triggers
  5347.     #  list - event commands list
  5348.     #  Returns specified custom event triggers.
  5349.     #--------------------------------------------------------------------------
  5350.     def get_triggers(list)
  5351.       # initialize
  5352.       triggers, special = [], {}
  5353.       # iteratre through all event commands
  5354.       (0...list.size).each {|i|
  5355.           # as long as they are comments
  5356.           break if list[i].code != 108
  5357.           # no ID
  5358.           id = nil
  5359.           # get the comment
  5360.           comment = list[i].parameters[0].clone
  5361.           # stop if not a trigger setup comment
  5362.           break if comment.gsub!('Trigger:') {''} == nil
  5363.           # get possible ID
  5364.           if comment.clone.gsub!(/=(\d+)/) {"$1"} != nil
  5365.             # remove the ID from the comment
  5366.             comment.gsub!(/=(\d+)/) {''}
  5367.             # get the ID
  5368.             id = $1.to_i
  5369.           end
  5370.           # get actual trigger number
  5371.           trigger = eval('BlizzABS::CET' + comment)
  5372.           # if special trigger
  5373.           if BlizzABS::CETSpecial.include?(trigger)
  5374.             # if no ID specified
  5375.             if id == nil
  5376.               # any ID trigger
  5377.               special[trigger] = []
  5378.             # if first trigger of this kind
  5379.             elsif !special.has_key?(trigger)
  5380.               # create this special trigger with the ID
  5381.               special[trigger] = [id]
  5382.             # if already ecisting
  5383.             elsif special[trigger].size > 0
  5384.               # add this ID
  5385.               special[trigger].push(id)
  5386.             end
  5387.           # if no normal trigger exists yet
  5388.           elsif triggers.size == 0
  5389.             # add the normal trigger
  5390.             triggers.push(trigger)
  5391.           end}
  5392.       # if not triggers specified
  5393.       if triggers.size == 0 && special.keys.size == 0
  5394.         # return default trigger
  5395.         return [BlizzABS::CETDefault, {}]
  5396.       end
  5397.       # add NONE trigger if no normal trigger exists
  5398.       triggers.push(BlizzABS::CETNone) if triggers.size == 0
  5399.       # remove duplicates
  5400.       special.keys.each {|key| special[key] = (special[key] | special[key])}
  5401.       # add special triggers
  5402.       triggers.push(special)
  5403.       # return triggers
  5404.       return triggers
  5405.     end
  5406.     #--------------------------------------------------------------------------
  5407.     # add_weapon_text
  5408.     #  text - original text
  5409.     #  id   - weapon ID
  5410.     #  type - name or description
  5411.     #  Generates additional data display for weapons.
  5412.     #--------------------------------------------------------------------------
  5413.     def add_weapon_text(text, id, type)
  5414.       # return normal text if range is 0 or the option isn't for this type
  5415.       return text if Weapons.range(id) == 0
  5416.       # iterate through configuration
  5417.       Config::WEAPON_DATA_MODE.each_index {|i|
  5418.           # if current option was set up for this type
  5419.           if Config::WEAPON_DATA_MODE[i] == type
  5420.             # add extra information to result text
  5421.             case i
  5422.             when 0
  5423.               text += case Weapons.type(id)
  5424.               when SWORD then ' (Melee)'
  5425.               when SPEAR then ' (Thrusting)'
  5426.               when FLAIL then ' (Flail)'
  5427.               when BOOMERANG then ' (Returning Projectile)'
  5428.               when BOW then ' (Projectile)'
  5429.               when BOW_ARROW then ' (Shooter)'
  5430.               when SHURIKEN then ' (Throwing)'
  5431.               end
  5432.             when 1
  5433.               number = Weapons.range(id)
  5434.               number = 1 if number < 1
  5435.               text += " R: #{number}"
  5436.             end
  5437.           end}
  5438.       # return result text
  5439.       return text
  5440.     end
  5441.     #--------------------------------------------------------------------------
  5442.     # add_skill_text
  5443.     #  text - original text
  5444.     #  id   - skill ID
  5445.     #  type - name or description
  5446.     #  Generates additional data display for skills.
  5447.     #--------------------------------------------------------------------------
  5448.     def add_skill_text(text, id, type)
  5449.       # return normal text if range is 0 or the option isn't used for this type
  5450.       return text if Skills.range(id) == 0
  5451.       # get scope
  5452.       scope = $data_skills[id].scope
  5453.       # iterate through configuration
  5454.       Config::SKILL_DATA_MODE.each_index {|i|
  5455.           # if current option was set up for this type
  5456.           if Config::SKILL_DATA_MODE[i] == type
  5457.             # add extra information to result text
  5458.             case i
  5459.             when 0
  5460.               next if scope == 0 || scope == 7
  5461.               text += case Skills.type(id)[0]
  5462.               when SHOOT then Cache::ScopeOne.include?(scope) ? ' (Shooter)' : ' (Thruster)'
  5463.               when HOMING then Cache::ScopeOne.include?(scope) ? ' (Homing)' : ' (S. Homing)'
  5464.               when DIRECT then Cache::ScopeOne.include?(scope) ? ' (Selector)' : ' (Shockwave)'
  5465.               when BEAM then Cache::ScopeOne.include?(scope) ? ' (Beam)' : ' (Fullscreen)'
  5466.               when TRAP then ' (Trap)'
  5467.               when TIMED then ' (Timed)'
  5468.               when SUMMON then ' (Summoner)'
  5469.               end
  5470.             when 1 then text += ' (explodes)' if Skills.type(id)[1] > 1
  5471.             when 2
  5472.               number = Skills.range(id)
  5473.               number = 1.0 if number < 1.0
  5474.               text += " R: #{number}"
  5475.             end
  5476.           end}
  5477.       # return result text
  5478.       return text
  5479.     end
  5480.     #--------------------------------------------------------------------------
  5481.     # add_item_text
  5482.     #  text - original text
  5483.     #  id   - item ID
  5484.     #  type - name or description
  5485.     #  Generates additional data display for items.
  5486.     #--------------------------------------------------------------------------
  5487.     def add_item_text(text, id, type)
  5488.       # return normal text if range is 0 or the option isn't used for this type
  5489.       return text if Items.range(id) == 0
  5490.       # get scope
  5491.       scope = $data_items[id].scope
  5492.       # iterate through configuration
  5493.       Config::ITEM_DATA_MODE.each_index {|i|
  5494.           # if current option was set up for this type
  5495.           if Config::ITEM_DATA_MODE[i] == type
  5496.             # add extra information to result text
  5497.             case i
  5498.             when 0
  5499.               next if scope == 0 || scope == 7
  5500.               text += case Items.type(id)[0]
  5501.               when SHOOT then Cache::ScopeOne.include?(scope) ? ' (Shooter)' : ' (Thruster)'
  5502.               when HOMING then Cache::ScopeOne.include?(scope) ? ' (Homing)' : ' (S. Homing)'
  5503.               when DIRECT then Cache::ScopeOne.include?(scope) ? ' (Selector)' : ' (Shockwave)'
  5504.               when BEAM then Cache::ScopeOne.include?(scope) ? ' (Beam)' : ' (Fullscreen)'
  5505.               when TRAP then ' (Trap)'
  5506.               when TIMED then ' (Timed)'
  5507.               when SUMMON then ' (Summoner)'
  5508.               end
  5509.             when 1 then text += ' (explodes)' if Items.type(id)[1] > 1
  5510.             when 2
  5511.               number = Items.range(id)
  5512.               number = 1.0 if number < 1.0
  5513.               text += " R: #{number}"
  5514.             end
  5515.           end}
  5516.       # return result text
  5517.       return text
  5518.     end
  5519.     #--------------------------------------------------------------------------
  5520.     # animations_size_down
  5521.     #  Sizes down all the animations to 50%.
  5522.     #--------------------------------------------------------------------------
  5523.     def animations_size_down
  5524.       # iterate through all animations
  5525.       $data_animations[1, $data_animations.size-1].each {|animation|
  5526.           # iterate through all frames and all cells
  5527.           animation.frames.each {|frame| (0...frame.cell_data.xsize).each {|i|
  5528.               # if cell contains image
  5529.               if frame.cell_data[i, 0] != nil && frame.cell_data[i, 0] != -1
  5530.                 # size down x position, y position and zoom by half
  5531.                 (1..3).each {|j| frame.cell_data[i, j] /= 2}
  5532.               end}}}
  5533.     end
  5534.     #--------------------------------------------------------------------------
  5535.     # rotate
  5536.     #  old_bitmap - bitmap to rotate
  5537.     #  Returns a bitmap rotated by 90° counterclockwise.
  5538.     #--------------------------------------------------------------------------
  5539.     def rotate(old_bitmap)
  5540.       # abort if no bitmap
  5541.       return nil unless old_bitmap.is_a?(Bitmap)
  5542.       # create new bitmap
  5543.       bitmap = Bitmap.new(old_bitmap.height, old_bitmap.width)
  5544.       # draw rotated
  5545.       (0...old_bitmap.width).each {|x| (0...old_bitmap.height).each {|y|
  5546.           # get pixel
  5547.           pixel = old_bitmap.get_pixel(x, y)
  5548.           # draw pixel if pixel is visible
  5549.           bitmap.set_pixel(y, bitmap.height-x-1, pixel) if pixel.alpha > 0}}
  5550.       # return rotated bitmap
  5551.       return bitmap
  5552.     end
  5553.     #--------------------------------------------------------------------------
  5554.     # setup_passability
  5555.     #  map - database map
  5556.     #  Returns a data hash with coordinates for the minimap drawing.
  5557.     #--------------------------------------------------------------------------
  5558.     def setup_passability(map)
  5559.       # set map for further use and initialize
  5560.       @map, result = map, Table.new(map.width, map.height)
  5561.       # iterate through all each horizontal element
  5562.       (0...@map.height).each {|y|
  5563.           # prevent "Script is hanging" error if large map
  5564.           Graphics.update if @map.height * @map.width >= 19200 && y % 10 == 0
  5565.           # iterate through all each vertical element
  5566.           (0...@map.width).each {|x|
  5567.               # initialize value
  5568.               val = 0x00
  5569.               # add to value if virtually passable in each direction
  5570.               val |= 0x01 if passable?(x, y, 2) && passable?(x, y+1, 8)
  5571.               val |= 0x02 if passable?(x, y, 4) && passable?(x-1, y, 6)
  5572.               val |= 0x04 if passable?(x, y, 6) && passable?(x+1, y, 4)
  5573.               val |= 0x08 if passable?(x, y, 8) && passable?(x, y-1, 2)
  5574.               # add coordinate if passable anyhow
  5575.               result[x, y] = val if val != 0x00}}
  5576.       # remove map from memory
  5577.       @map = nil
  5578.       # return passable coordinates
  5579.       return result
  5580.     end
  5581.     #--------------------------------------------------------------------------
  5582.     # passable?
  5583.     #  x - x-coordinate
  5584.     #  y - y-coordinate
  5585.     #  d - direction
  5586.     #  Checks virtual passability for the minimap.
  5587.     #--------------------------------------------------------------------------
  5588.     def passable?(x, y, d)
  5589.       # "passable" if out of map border
  5590.       return true if x < 0 || x >= @map.width || y < 0 || y >= @map.height
  5591.       # set bit
  5592.       bit = (1 << (d / 2 - 1)) & 0x0f
  5593.       # iterate through all layers
  5594.       Cache::MapLayers.each {|i|
  5595.           # get tile ID
  5596.           tile_id = @map.data[x, y, i]
  5597.           # if tile ID not valid
  5598.           if tile_id == nil
  5599.             # impassable
  5600.             return false
  5601.           # if obstacle bit is set
  5602.           elsif $data_tilesets[@map.tileset_id].passages[tile_id] & bit != 0
  5603.             # impassable
  5604.             return false
  5605.           # if obstacle bit is set in all directions
  5606.           elsif $data_tilesets[@map.tileset_id].passages[tile_id] & 0x0F == 0x0F
  5607.             # impassable
  5608.             return false
  5609.           # if priority is 0
  5610.           elsif $data_tilesets[@map.tileset_id].priorities[tile_id] == 0
  5611.             # passable
  5612.             return true
  5613.           end}
  5614.       # passable
  5615.       return true
  5616.     end
  5617.     #--------------------------------------------------------------------------
  5618.     # check_map_data
  5619.     #  Updates the passability file.
  5620.     #--------------------------------------------------------------------------
  5621.     def check_map_data
  5622.       # stop if not using intelligent passability mode
  5623.       return unless BlizzABS::Config::INTELLIGENT_PASSABILITY
  5624.       # load tileset data
  5625.       $data_tilesets = load_data('Data/Tilesets.rxdata')
  5626.       # get current map states
  5627.       new_data = load_data('Data/MapInfos.rxdata')
  5628.       # if first time intelligent passability is being used
  5629.       if !File.exist?('Data/Map_Data.abs')
  5630.         # initialize
  5631.         data, dates = {}, {}
  5632.         # all map IDs
  5633.         ids = new_data.keys.sort
  5634.       else
  5635.         # get passability data and "modified time" data from old data file
  5636.         data, dates = load_data('Data/Map_Data.abs')
  5637.         # get a sorted array of all map IDs
  5638.         keys = new_data.keys.sort
  5639.         # iterate through all current map IDs
  5640.         keys.each_index {|i|
  5641.             # if game not encrypted
  5642.             if File.exist?(sprintf('Data/Map%03d.rxdata', keys[i]))
  5643.               # open map file for reading
  5644.               file = File.open(sprintf('Data/Map%03d.rxdata', keys[i]), 'r')
  5645.               # if map was edited
  5646.               if dates[keys[i]] != file.mtime
  5647.                 # remove map ID from data
  5648.                 data.delete(keys[i])
  5649.                 # remove map ID from dates
  5650.                 dates.delete(keys[i])
  5651.               end
  5652.               # close file
  5653.               file.close
  5654.             end
  5655.             # prevent "Script is hanging" error
  5656.             Graphics.update if i % 20 == 0}
  5657.         # iterate through all map IDs that were deleted
  5658.         (data.keys - keys).each {|id|
  5659.               # remove map ID from data
  5660.               data.delete(keys[id])
  5661.               # remove map ID from dates
  5662.               dates.delete(keys[id])}
  5663.         # get all map IDs that need to be updated
  5664.         ids = keys - data.keys
  5665.       end
  5666.       # iterate through all IDs
  5667.       ids.each {|id|
  5668.           # load map
  5669.           map = load_data(sprintf('Data/Map%03d.rxdata', id))
  5670.           # create one map data pack
  5671.           data[id] = setup_passability(map)
  5672.           # if game not encrypted
  5673.           if File.exist?(sprintf('Data/Map%03d.rxdata', id))
  5674.             # open map file for reading
  5675.             f = File.open(sprintf('Data/Map%03d.rxdata', id), 'r')
  5676.             # get map file modified time
  5677.             dates[id] = f.mtime
  5678.             # close file
  5679.             f.close
  5680.           end
  5681.           # prevent "Script is hanging" error
  5682.           Graphics.update}
  5683.       # open new file
  5684.       file = File.open('Data/Map_Data.abs', 'wb')
  5685.       # save all data to file
  5686.       Marshal.dump([data, dates], file)
  5687.       # save and close file
  5688.       file.close
  5689.       # remove variables from memory completely
  5690.       $data_tilesets = nil
  5691.     end
  5692.   end
  5693.  
  5694. end
  5695.  
  5696. module BlizzABS
  5697.  
  5698.   #============================================================================
  5699.   # BlizzABS::AI
  5700.   #----------------------------------------------------------------------------
  5701.   #  This class processes Map_Enemy AI based upon AI Data, character position
  5702.   #  and battler status. It includes complete AI control for both actors and
  5703.   #  enemies.
  5704.   #============================================================================
  5705.  
  5706.   class AI
  5707.    
  5708.     # possible AI states
  5709.     Idle = 0
  5710.     Request = 1
  5711.     Ready = 2
  5712.     Return = 3
  5713.     MoveOnly = 4
  5714.     Defend = 21
  5715.     Escape = 22
  5716.     Knockback = 30
  5717.     Abort = 90
  5718.     Invalid = 99
  5719.    
  5720.     #==========================================================================
  5721.     # BlizzABS::AI::Data
  5722.     #--------------------------------------------------------------------------
  5723.     #  This class serves as superclass for Data classes.
  5724.     #==========================================================================
  5725.    
  5726.     class Data
  5727.      
  5728.       # setting all accessible variables
  5729.       attr_accessor :state
  5730.       attr_accessor :host
  5731.       attr_accessor :in_action
  5732.       attr_accessor :attacked
  5733.       attr_accessor :aggressive
  5734.       attr_accessor :sight
  5735.       attr_accessor :memory
  5736.       attr_accessor :minions
  5737.       attr_accessor :lead
  5738.       attr_accessor :act
  5739.       attr_accessor :target
  5740.       attr_accessor :group
  5741.       attr_accessor :negative
  5742.       attr_accessor :positive
  5743.       attr_accessor :neutral
  5744.       attr_accessor :altered_alignment
  5745.       attr_reader   :attributes
  5746.       attr_reader   :custom
  5747.       attr_reader   :delay_time
  5748.       attr_reader   :view_range
  5749.       attr_reader   :hearing_range_ratio
  5750.       attr_writer   :observation
  5751.       #------------------------------------------------------------------------
  5752.       # AI initialization
  5753.       #------------------------------------------------------------------------
  5754.       def initialize(host, group, custom, delay, view, hear)
  5755.         # set AI timers
  5756.         @custom, @delay_time = custom, delay
  5757.         # set Perception Range
  5758.         @view_range, @hearing_range_ratio, @attributes = view, hear, 0x00
  5759.         # the data carrier, battlers in sight and battler data in memory
  5760.         @host, @sight, @memory = host, [], {}
  5761.         # AI state for convenience and Blizz-ABS action data
  5762.         @state, @act = BlizzABS::AI::Idle, BlizzABS::Action.new
  5763.         # set alignment group
  5764.         setup_group(group)
  5765.       end
  5766.       #------------------------------------------------------------------------
  5767.       # setup_group
  5768.       #  Extra method for alignment setup.
  5769.       #------------------------------------------------------------------------
  5770.       def setup_group(new_group)
  5771.         # original alignment
  5772.         @altered_alignment = false
  5773.         # set new own group
  5774.         @group = new_group
  5775.         # set up enemy groups
  5776.         @negative = $game_system.alignments[@group].enemies.clone
  5777.         # set up ally groups
  5778.         @positive = $game_system.alignments[@group].allies.clone
  5779.         # set up always-neutral groups
  5780.         @neutral = $game_system.alignments[@group].neutral.clone
  5781.       end
  5782.       #------------------------------------------------------------------------
  5783.       # add_to_memory
  5784.       #  bs - the battlers to memorize
  5785.       #  Memorizes all battlers and creates memory data.
  5786.       #------------------------------------------------------------------------
  5787.       def add_to_memory(bs)
  5788.         # if array of battlers
  5789.         if bs.is_a?(Array)
  5790.           # add memory data for each battler
  5791.           bs.each {|b| @memory[b] = MemoryData.new(b.x, b.y)}
  5792.         else
  5793.           # add memory data for battler
  5794.           @memory[bs] = MemoryData.new(bs.x, bs.y)
  5795.         end
  5796.       end
  5797.       #------------------------------------------------------------------------
  5798.       # lifeless?
  5799.       #  Encapsulation method for lifeless groups.
  5800.       #------------------------------------------------------------------------
  5801.       def lifeless?
  5802.         return BlizzABS::Alignments::LIFELESS_GROUPS.include?(@group)
  5803.       end
  5804.       #------------------------------------------------------------------------
  5805.       # linked?
  5806.       #  Encapsulation method for linked groups.
  5807.       #------------------------------------------------------------------------
  5808.       def linked?
  5809.         return BlizzABS::Alignments::LINKED_GROUPS.include?(@group)
  5810.       end
  5811.       #------------------------------------------------------------------------
  5812.       # permanent?
  5813.       #  Encapsulation method for permanently linked groups.
  5814.       #------------------------------------------------------------------------
  5815.       def permanent?
  5816.         return BlizzABS::Alignments::PERMANENT_GROUPS.include?(@group)
  5817.       end
  5818.       #------------------------------------------------------------------------
  5819.       # origin_aggressive
  5820.       #  Encapsulation method for the "aggressive" attribute.
  5821.       #------------------------------------------------------------------------
  5822.       def origin_aggressive
  5823.         return (@attributes & 0x80 == 0x00)
  5824.       end
  5825.       #------------------------------------------------------------------------
  5826.       # actions
  5827.       #  Encapsulation method for the "actions" attribute.
  5828.       #------------------------------------------------------------------------
  5829.       def actions
  5830.         return (@attributes & 0x40 == 0x40)
  5831.       end
  5832.       #------------------------------------------------------------------------
  5833.       # observe
  5834.       #  Encapsulation method for the "observe" attribute.
  5835.       #------------------------------------------------------------------------
  5836.       def observe
  5837.         return (@attributes & 0x20 == 0x20)
  5838.       end
  5839.       #------------------------------------------------------------------------
  5840.       # defensive
  5841.       #  Encapsulation method for the "defensive" attribute.
  5842.       #------------------------------------------------------------------------
  5843.       def defensive
  5844.         return (@attributes & 0x10 == 0x10)
  5845.       end
  5846.       #------------------------------------------------------------------------
  5847.       # leader
  5848.       #  Encapsulation method for the "leader" attribute.
  5849.       #------------------------------------------------------------------------
  5850.       def leader
  5851.         return (@attributes & 0x08 == 0x08)
  5852.       end
  5853.       #------------------------------------------------------------------------
  5854.       # call_help
  5855.       #  Encapsulation method for the "call_help" attribute.
  5856.       #------------------------------------------------------------------------
  5857.       def call_help
  5858.         return (@attributes & 0x04 == 0x04)
  5859.       end
  5860.       #------------------------------------------------------------------------
  5861.       # healer
  5862.       #  Encapsulation method for the "healer" attribute.
  5863.       #------------------------------------------------------------------------
  5864.       def healer
  5865.         return (@attributes & 0x02 == 0x02)
  5866.       end
  5867.       #------------------------------------------------------------------------
  5868.       # full_power
  5869.       #  Encapsulation method for the "full_power" attribute.
  5870.       #------------------------------------------------------------------------
  5871.       def full_power
  5872.         return (@attributes & 0x01 == 0x01)
  5873.       end
  5874.      
  5875.     end
  5876.    
  5877.     #==========================================================================
  5878.     # BlizzABS::AI::Data_Actor
  5879.     #--------------------------------------------------------------------------
  5880.     #  This class holds all data important for the actor AI.
  5881.     #==========================================================================
  5882.    
  5883.     class Data_Actor < Data
  5884.      
  5885.       #------------------------------------------------------------------------
  5886.       # Initialization
  5887.       #------------------------------------------------------------------------
  5888.       def initialize(host)
  5889.         # call superclass method
  5890.         super(host, BlizzABS::Alignments::ACTOR_GROUP, false, 0, 5, 100)
  5891.       end
  5892.       #------------------------------------------------------------------------
  5893.       # negative
  5894.       #  Encapsulation method since the player can attack any opponent group
  5895.       #  while normal actors can't.
  5896.       #------------------------------------------------------------------------
  5897.       def negative
  5898.         # return player group enemies if self is player
  5899.         return BlizzABS::Alignments::GROUPS - [@group] if @host == $game_player
  5900.         # normal enemy group
  5901.         return @negative
  5902.       end
  5903.       #------------------------------------------------------------------------
  5904.       # offensive
  5905.       #  Encapsulation that allows the override of the offensive attribute.
  5906.       #------------------------------------------------------------------------
  5907.       def offensive
  5908.         return (@host.battler == nil ? false : (@host.battler.force_offensive > 0 ?
  5909.             @host.battler.force_offensive : @host.battler.offensive))
  5910.       end
  5911.       #------------------------------------------------------------------------
  5912.       # aggressive
  5913.       #  Encapsulation that allows the override of the aggressive attribute.
  5914.       #------------------------------------------------------------------------
  5915.       def aggressive
  5916.         return (@host.battler == nil ? false : (@host.battler.force_aggressive > 0 ?
  5917.             @host.battler.force_aggressive : @host.battler.aggressive))
  5918.       end
  5919.       #------------------------------------------------------------------------
  5920.       # delay_time
  5921.       #  Encapsulation that allows the override of the delay_time attribute.
  5922.       #  Passive allies have a higher delay.
  5923.       #------------------------------------------------------------------------
  5924.       def delay_time
  5925.         return (self.aggressive == false ? 0 : (15 - self.aggressive) * 3)
  5926.       end
  5927.       #------------------------------------------------------------------------
  5928.       # defensive
  5929.       #  Defensive actors will defend more often.
  5930.       #------------------------------------------------------------------------
  5931.       def defensive
  5932.         return (self.offensive && self.offensive < 8)
  5933.       end
  5934.       #------------------------------------------------------------------------
  5935.       # healer
  5936.       #  Defensive actors will heal more often.
  5937.       #------------------------------------------------------------------------
  5938.       def healer
  5939.         return (self.offensive && self.offensive < 5)
  5940.       end
  5941.      
  5942.     end
  5943.    
  5944.     #==========================================================================
  5945.     # BlizzABS::AI::Data_Enemy
  5946.     #--------------------------------------------------------------------------
  5947.     #  This class holds all data important for the enemy AI.
  5948.     #==========================================================================
  5949.    
  5950.     class Data_Enemy < Data
  5951.      
  5952.       #------------------------------------------------------------------------
  5953.       # AI initialization
  5954.       #------------------------------------------------------------------------
  5955.       def initialize(host, group, attributes, custom, delay, view, hear)
  5956.         # call superclass method
  5957.         super(host, group, custom, delay, view, hear)
  5958.         # determines if enemy has an aggressive or a passive nature
  5959.         @aggressive = (attributes & 0x80 == 0x00)
  5960.         # set attributes and initialize minions array and observation data
  5961.         @attributes, @minions, @observation = attributes, [], {}
  5962.       end
  5963.       #------------------------------------------------------------------------
  5964.       # sight
  5965.       #  Encapsulation method for sight data.
  5966.       #------------------------------------------------------------------------
  5967.       def sight
  5968.         return (@lead != nil ? @lead.ai.sight : @sight)
  5969.       end
  5970.       #------------------------------------------------------------------------
  5971.       # memory
  5972.       #  Encapsulation method for memorized battlers.
  5973.       #------------------------------------------------------------------------
  5974.       def memory
  5975.         return (@lead != nil ? @lead.ai.memory : @memory)
  5976.       end
  5977.       #------------------------------------------------------------------------
  5978.       # observation
  5979.       #  Encapsulation method for observation data.
  5980.       #------------------------------------------------------------------------
  5981.       def observation
  5982.         return (@lead != nil ? @lead.ai.observation : @observation)
  5983.       end
  5984.      
  5985.     end
  5986.  
  5987.     #--------------------------------------------------------------------------
  5988.     # wall?
  5989.     #  char - the character
  5990.     #  x    - x-coordinate
  5991.     #  y    - y-coordinate
  5992.     #  Checks if between the char and the target is a "wall". Walls prevent
  5993.     #  perception.
  5994.     #--------------------------------------------------------------------------
  5995.     def wall?(char, x, y)
  5996.       # abort instantly if not using this option
  5997.       return false if Config::WALL_TAGS.size == 0
  5998.       # get pixel movement rate
  5999.       pix = $BlizzABS.pixel
  6000.       # get coordinate difference
  6001.       dx, dy = (x-char.x)/pix, (y-char.y)/pix
  6002.       # if x difference is not 0 and x difference is greater
  6003.       if dx != 0 && dx.abs > dy.abs
  6004.         # return any wall tile between
  6005.         return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
  6006.             terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx).round))}
  6007.       # if y difference is not 0 and y difference is greater
  6008.       elsif dy != 0 && dy.abs > dx.abs
  6009.         # return any wall tile between
  6010.         return (0..dy.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
  6011.             terrain_tag(char.x/pix+(i.to_f*dx/dy).round, char.y/pix+dy.sgn*i))}
  6012.       end
  6013.       # no wall between
  6014.       return false
  6015.     end
  6016.     #--------------------------------------------------------------------------
  6017.     # can_see_char?
  6018.     #  char   - the character
  6019.     #  real_x - x-coordinate
  6020.     #  real_y - y-coordinate
  6021.     #  Checks if the player can be seen.
  6022.     #--------------------------------------------------------------------------
  6023.     def can_see_char?(char, real_x, real_y)
  6024.       # calculate differences of x and y and get inner perception range
  6025.       dx, dy = real_x - char.real_x, real_y - char.real_y
  6026.       # check facing direction and determine whether can see or not
  6027.       case char.direction
  6028.       when 2 then return (dy >= 0 && dx.abs <= dy.abs)
  6029.       when 4 then return (dx <= 0 && dx.abs >= dy.abs)
  6030.       when 6 then return (dx >= 0 && dx.abs >= dy.abs)
  6031.       when 8 then return (dy <= 0 && dx.abs <= dy.abs)
  6032.       end
  6033.       # can't see
  6034.       return false
  6035.     end
  6036.     #--------------------------------------------------------------------------
  6037.     # can_hear_char?
  6038.     #  char   - the character
  6039.     #  real_x - x-coordinate
  6040.     #  real_y - y-coordinate
  6041.     #  Checks if the player can be heard while being close.
  6042.     #--------------------------------------------------------------------------
  6043.     def can_hear_char?(char, real_x, real_y)
  6044.       # calculate differences of x and y and get inner perception range
  6045.       dx, dy = real_x - char.real_x, real_y - char.real_y
  6046.       r = char.ai.view_range * 128 * char.ai.hearing_range_ratio / 100
  6047.       # can't be heard if out of range
  6048.       return false if dx * dx + dy * dy > r * r
  6049.       # check facing direction and determine whether can hear or not
  6050.       case char.direction
  6051.       when 2 then return (dy >= 0)
  6052.       when 4 then return (dx <= 0)
  6053.       when 6 then return (dx >= 0)
  6054.       when 8 then return (dy <= 0)
  6055.       end
  6056.       # can't see
  6057.       return false
  6058.     end
  6059.     #--------------------------------------------------------------------------
  6060.     # can_perceive_char?
  6061.     #  char   - the character
  6062.     #  real_x - x-coordinate
  6063.     #  real_y - y-coordinate
  6064.     #  Checks if the player can be heard while being close.
  6065.     #--------------------------------------------------------------------------
  6066.     def can_perceive_char?(char, real_x, real_y)
  6067.       # calculate differences of x and y and get perception range
  6068.       dx, dy = real_x - char.real_x, real_y - char.real_y
  6069.       r = char.ai.view_range * 128
  6070.       # can't be perceived if out of range
  6071.       return (dx * dx + dy * dy <= r * r)
  6072.     end
  6073.     #--------------------------------------------------------------------------
  6074.     # update
  6075.     #  char - the map character
  6076.     #  This is the first phase of the AI update. It determines whether a
  6077.     #  character is able to act at all or if an exception has occured and
  6078.     #  needs to expire first.
  6079.     #--------------------------------------------------------------------------
  6080.     def prepare(char)
  6081.       # temporary variables
  6082.       x, y, ai = char.x, char.y, char.ai
  6083.       # if char was attacked
  6084.       if char.attacked > 0
  6085.         # set state
  6086.         ai.state = Knockback
  6087.         # stop if force moving knockback already
  6088.         return if char.moving?
  6089.         # if forced to move
  6090.         if char.move_type == 3
  6091.           # delete pending movement commands
  6092.           char.force_move = []
  6093.         # if not moving already
  6094.         elsif !char.moving?
  6095.           # add throw back moving commands
  6096.           char.force_move = [Cache::FDirs[10 - char.direction]]
  6097.         end
  6098.         # cancel action
  6099.         char.in_action = 0
  6100.         # decrease attacked counter
  6101.         char.attacked -= 1
  6102.       # if char in action
  6103.       elsif char.in_action > 0
  6104.         # set state
  6105.         ai.state = Abort
  6106.         # if defending
  6107.         if char.ai.act.defend?
  6108.           # decrease shock count
  6109.           char.in_action -= 1
  6110.           # set state
  6111.           ai.state = Defend
  6112.         # if not freeze action and no action sprite
  6113.         elsif !char.freeze_action && char.current_sprite == ''
  6114.           # decrease shock count
  6115.           char.in_action -= 1
  6116.         end
  6117.       # if char is moving or restricted to move
  6118.       elsif char.moving? || char.restriction == 4
  6119.         # set state
  6120.         ai.state = (char.ai.act.escape? ? Escape : Abort)
  6121.       # if char needs to move
  6122.       elsif char.force_move.size > 0
  6123.         # set state
  6124.         ai.state = (char.ai.act.escape? ? Escape : MoveOnly)
  6125.       # if target exists
  6126.       elsif ai.target != nil
  6127.         # set pre-state
  6128.         ai.state = Ready
  6129.       else
  6130.         # set pre-state
  6131.         ai.state = Return
  6132.       end
  6133.     end
  6134.     #--------------------------------------------------------------------------
  6135.     # perception
  6136.     #  char            - the map character
  6137.     #  update_priority - determines the update priority
  6138.     #  This is the second phase of the AI update. It updates the character's
  6139.     #  perception.
  6140.     #--------------------------------------------------------------------------
  6141.     def perception(char, update_priority = BlizzABS::UPDFull)
  6142.       # temporary variables
  6143.       dir, x, y, ai, in_range = char.direction, char.x, char.y, char.ai, []
  6144.       # if enemy
  6145.       if char.is_a?(Map_Enemy)
  6146.         # if heavy update required
  6147.         if update_priority >= BlizzABS::UPDHeavy
  6148.           # find all battlers within perception range
  6149.           in_range = ($game_map.battlers + $BlizzABS.battlers - [char]).
  6150.               find_all {|b| b.valid? && !b.battler.dead? && ai.view_range * 128 >=
  6151.               Math.hypot(b.real_x-char.real_x, b.real_y-char.real_y) &&
  6152.               !wall?(char, b.x, b.y)}
  6153.           # find all who are in sight
  6154.           ai.sight = in_range.find_all {|b| b.in_action > 0 ||
  6155.               can_see_char?(char, b.real_x, b.real_y) ||
  6156.               can_hear_char?(char, b.real_x, b.real_y)}
  6157.           # if full update required
  6158.           if update_priority == BlizzABS::UPDFull
  6159.             # memorize all unmemorized, seen battlers
  6160.             ai.add_to_memory(ai.sight - ai.memory.keys)
  6161.           end
  6162.         end
  6163.         # if medium update required
  6164.         if update_priority >= BlizzABS::UPDMedium
  6165.           # if observing attribute is active
  6166.           if ai.observe
  6167.             # valid and lost actors
  6168.             valid_actors, lost_actors = [], []
  6169.             # for each battler in sight
  6170.             ai.sight.each {|b|
  6171.                 # if actor
  6172.                 if b.is_a?(Map_Actor)
  6173.                   # add the appropriate array
  6174.                   (b.valid? ? valid_actors : lost_actors).push(b)
  6175.                 end}
  6176.             # add all actors lost out of sight
  6177.             lost_actors |= (ai.memory.keys - ai.sight).find_all {|b|
  6178.                 b.is_a?(Map_Actor)}
  6179.             # for each actor in sight
  6180.             valid_actors.each {|key|
  6181.                 # get observation logs
  6182.                 data = ai.observation[key.battler]
  6183.                 # if no observation log exists
  6184.                 if data == nil
  6185.                   # create an observation log
  6186.                   ai.observation[key.battler] = [Graphics.frame_count]
  6187.                 # if interval not started yet
  6188.                 elsif !data[data.size - 1].is_a?(Numeric)
  6189.                   # start observation interval right now
  6190.                   data.push(Graphics.frame_count)
  6191.                 end}
  6192.             # for all actors that need to be forgotten
  6193.             lost_actors.each {|key|
  6194.                 # get observation logs
  6195.                 data = ai.observation[key.battler]
  6196.                 # if logs exist, last log is a number and time has passed
  6197.                 if data != nil && data[data.size-1].is_a?(Numeric) &&
  6198.                     data[data.size-1] < Graphics.frame_count
  6199.                   # convert number into inteval
  6200.                   data.push(data.pop..Graphics.frame_count)
  6201.                 end}
  6202.           end
  6203.         end
  6204.       # if actor
  6205.       elsif char.is_a?(Map_Actor)
  6206.         # in sight are all battlers in range
  6207.         ai.sight = ($game_map.battlers + $BlizzABS.battlers - [char]).
  6208.             find_all {|b| b.valid? && b.in_screen?}
  6209.       end
  6210.       # get alignment setup
  6211.       negative, positive = ai.negative, ai.positive
  6212.       # invert setup if confused
  6213.       negative, positive = positive, negative if char.restriction == 3
  6214.       # if a target exists
  6215.       if ai.target != nil
  6216.         # if force moving
  6217.         if char.move_type == 3
  6218.           # if delay counter expired
  6219.           if ai.act.ready?
  6220.             # execute action
  6221.             try_execute(char)
  6222.             # if nobody around
  6223.             if ai.memory.keys.size == 0 && ai.sight.size == 0
  6224.               # reset action
  6225.               char.reset_action
  6226.             # if about to move and target exists
  6227.             elsif char.force_move.size == 0 && ai.target != nil
  6228.               # get pixel movement rate and initialize flag
  6229.               pix, found = $BlizzABS.pixel, false
  6230.               # find the target in memory
  6231.               ai.memory.keys.each {|key|
  6232.                   # if this is the target
  6233.                   if key == ai.target
  6234.                     # if lost target completely
  6235.                     if ai.memory[key].x / pix == char.x / pix &&
  6236.                         ai.memory[key].y / pix == char.y / pix
  6237.                       # reset action
  6238.                       char.reset_action
  6239.                       # abort method
  6240.                       return
  6241.                     end
  6242.                     # found the target
  6243.                     found = true
  6244.                     break
  6245.                   end}
  6246.               # reset action if not found in memory
  6247.               char.reset_action unless found
  6248.             end
  6249.           end
  6250.         else
  6251.           # face the target
  6252.           char.turn_toward(ai.target)
  6253.           # if running away
  6254.           if char.ai.act.escape?
  6255.             # move away from reference target
  6256.             char.move_away_random(ai.target, true, ai.act.range)
  6257.           # if delay counter expired
  6258.           elsif ai.act.ready?
  6259.             # execute action
  6260.             try_execute(char)
  6261.             # if nobody around
  6262.             if ai.memory.keys.size == 0 && ai.sight.size == 0
  6263.               # reset action
  6264.               char.reset_action
  6265.             # if about to move and target exists
  6266.             elsif char.force_move.size == 0 && ai.target != nil
  6267.               # if within sight
  6268.               if ai.sight.include?(ai.target)
  6269.                 # request path to target
  6270.                 request_path(char, ai.target)
  6271.               else
  6272.                 # get pixel movement rate and initialize flag
  6273.                 pix, found = $BlizzABS.pixel, false
  6274.                 # find the target in memory
  6275.                 ai.memory.keys.each {|key|
  6276.                     # if this is the target
  6277.                     if key == ai.target
  6278.                       # temporary variables
  6279.                       x, y = ai.memory[key].x / pix, ai.memory[key].y / pix
  6280.                       # if lost target completely
  6281.                       if x == char.x / pix && y == char.y / pix
  6282.                         # reset action
  6283.                         char.reset_action
  6284.                         # abort method
  6285.                         return
  6286.                       end
  6287.                       # find path to last known coordinates
  6288.                       request_path(char, x, y)
  6289.                       found = true
  6290.                       break
  6291.                     end}
  6292.                 # reset action if not found in memory
  6293.                 char.reset_action unless found
  6294.               end
  6295.             end
  6296.           # if negative action and too close
  6297.           elsif negative.include?(ai.target.ai.group) &&
  6298.               Math.hypot(char.real_x-ai.target.real_x,
  6299.               char.real_y-ai.target.real_y) < 384
  6300.             # delete movement commands
  6301.             char.force_move = []
  6302.             # back off from reference target
  6303.             char.move_away_random(ai.target, false, ai.act.range)
  6304.           end
  6305.           # exit method
  6306.           return
  6307.         end
  6308.       end
  6309.       # if not actor
  6310.       unless char.is_a?(Map_Actor)
  6311.         # call for help
  6312.         call_for_help(char, in_range, negative, positive)
  6313.       end
  6314.     end
  6315.     #--------------------------------------------------------------------------
  6316.     # call_for_help
  6317.     #  char     - the map character
  6318.     #  in_range - array of battlers in range
  6319.     #  negative - perceived enemies
  6320.     #  positive - perceived allies
  6321.     #  Executes calling for help procedure.
  6322.     #--------------------------------------------------------------------------
  6323.     def call_for_help(char, in_range, negative, positive)
  6324.       # temporary variable
  6325.       ai = char.ai
  6326.       # stop if confused, not help calling enemy or not newly sighted enemies
  6327.       return if !ai.call_help || char.restriction == 3 || ai.target != nil
  6328.       # get all enemies in sight
  6329.       in_sight_e = ai.sight.find_all {|b| negative.include?(b.ai.group)}
  6330.       # stop if no sighted enemies
  6331.       return if in_sight_e.size == 0
  6332.       # find all allied battlers
  6333.       allies = in_range.find_all {|b| ai.positive.include?(b.ai.group)}
  6334.       # stop if no allies exist
  6335.       return if allies.size == 0
  6336.       # iterate through all allies
  6337.       allies.each {|ally|
  6338.           # ally memorizes each battler in sight not in ally's memory already
  6339.           ally.ai.add_to_memory(ai.sight - ally.ai.memory.keys)
  6340.           # for each memorized battler
  6341.           ai.memory.keys.each {|key|
  6342.               # if not memorized by ally yet
  6343.               if ally.ai.memory[key] == nil
  6344.                 # copy memory data for battler
  6345.                 ally.ai.memory[key] = ai.memory[key].clone
  6346.               end}
  6347.           # copy real negative group to ally's negative group
  6348.           ally.ai.negative = ally.ai.negative | ai.negative}
  6349.       # if using help calling animation
  6350.       if Config::CALL_HELP_ANIMATION_ID > 0
  6351.         # setup help calling animation
  6352.         char.animation_id = Config::CALL_HELP_ANIMATION_ID
  6353.       end
  6354.     end
  6355.     #--------------------------------------------------------------------------
  6356.     # decide_action
  6357.     #  char - the map character
  6358.     #  This is the fourth phase of the AI update. When a character is ready to
  6359.     #  act and has no action defined yet, this method decides a new action.
  6360.     #--------------------------------------------------------------------------
  6361.     def decide_action(char)
  6362.       # temporary variables
  6363.       dir, x, y, ai = char.direction, char.x, char.y, char.ai
  6364.       pix = $BlizzABS.pixel
  6365.       # get alignment setup
  6366.       negative, positive = ai.negative, ai.positive
  6367.       # invert setup if confused
  6368.       negative, positive = positive, negative if char.restriction == 3
  6369.       # get all enemies in sight
  6370.       in_sight_e = ai.sight.find_all {|b| negative.include?(b.ai.group)}
  6371.       # if no enemies are available
  6372.       if in_sight_e.size == 0
  6373.         # initialize
  6374.         in_sight_a, in_range = [], ai.memory.keys
  6375.         # get all allies and enemies in range
  6376.         in_range.each {|b|
  6377.             in_sight_a.push(b) if positive.include?(b.ai.group)
  6378.             in_sight_e.push(b) if negative.include?(b.ai.group)}
  6379.         # if still no enemies are available
  6380.         if in_sight_e.size == 0
  6381.           # initialize again
  6382.           in_sight_a = []
  6383.           # get all allies and enemies from memory
  6384.           ai.memory.keys.each {|b|
  6385.               in_sight_a.push(b) if positive.include?(b.ai.group)
  6386.               in_sight_e.push(b) if negative.include?(b.ai.group)}
  6387.         end
  6388.       else
  6389.         # get all allies in sight
  6390.         in_sight_a = ai.sight.find_all {|b| positive.include?(b.ai.group)}
  6391.       end
  6392.       # exit if no enemies are in sight
  6393.       return if in_sight_e.size == 0
  6394.       # if actor
  6395.       if char.is_a?(Map_Actor)
  6396.         # exit if "no enemies" are in sight
  6397.         return if in_sight_e.size == 0
  6398.         # get radius reach of player
  6399.         rad = $BlizzABS.util.get_player_radius
  6400.         # find all enemies within radius according to aggressiveness
  6401.         in_radius = in_sight_e.find_all {|e|
  6402.             Math.hypot(char.x / pix - e.x / pix, char.y / pix - e.y / pix) <=
  6403.                 rad * char.ai.aggressive / 15}
  6404.         # check next trigger if action can't be executed
  6405.         return if in_radius.size == 0
  6406.         # add self as ally
  6407.         in_sight_a.push(char)
  6408.         # if confused or no trigger action was set up
  6409.         if char.restriction == 3 ||
  6410.             !trigger_actor_action(char, in_sight_a, in_sight_e)
  6411.           # set up advanced action based on Blizz-ABS AI
  6412.           advanced_actor_action(char)
  6413.         end
  6414.       # if enemy
  6415.       elsif char.is_a?(Map_Enemy)
  6416.         # if action attribute is not active
  6417.         if !ai.actions
  6418.           # decide normal action
  6419.           char.battler.make_action
  6420.           # temporary variable
  6421.           act = char.battler.current_action
  6422.           # set up the action in Blizz-ABS as normal action
  6423.           normal_action(char, in_sight_a, in_sight_e, (act.kind == 0),
  6424.               act.basic, rand(31) + 70, 80, act.skill_id)
  6425.         else
  6426.           # set up advanced action based on Blizz-ABS AI
  6427.           advanced_enemy_action(char)
  6428.         end
  6429.       end
  6430.       # if target doesn't exist or forced moving
  6431.       if ai.target == nil || !ai.target.valid?
  6432.         # reset action
  6433.         char.reset_action
  6434.       # if not being force moved
  6435.       elsif char.is_a?(Map_Enemy) && char.move_type != 3
  6436.         # set path request state
  6437.         ai.state = Request
  6438.         # turn toward the target not to lose it out of sight
  6439.         char.turn_toward(ai.target)
  6440.         # request a path
  6441.         request_path(char, ai.target)
  6442.       end
  6443.     end
  6444.     #--------------------------------------------------------------------------
  6445.     # trigger_actor_action
  6446.     #  char - the map actor
  6447.     #  Analyzes what the enemy is capable of and uses that data to determine an
  6448.     #  action.
  6449.     #--------------------------------------------------------------------------
  6450.     def trigger_actor_action(char, in_sight_a, in_sight_e)
  6451.       # make copies of the original perception arrays
  6452.       in_sight_a_org, in_sight_e_org = in_sight_a, in_sight_e
  6453.       # check each trigger
  6454.       char.battler.triggers.each {|trigger|
  6455.           # restore percepted battlers
  6456.           in_sight_a, in_sight_e = in_sight_a_org.clone, in_sight_e_org.clone
  6457.           # reset target
  6458.           target = nil
  6459.           # get triggering battlers
  6460.           activators = case trigger.activator
  6461.           when TRGLeader then [$game_player]
  6462.           when TRGAlly then $BlizzABS.battlers.find_all {|b| b.valid?}
  6463.           when TRGSelf then [char]
  6464.           when TRGEnemy then in_sight_e.clone
  6465.           when TRGProbability then nil
  6466.           end
  6467.           # if battler activator
  6468.           if trigger.battler_activator?
  6469.             # if any trigger exists
  6470.             if activators.size > 0
  6471.               # get a target from the trigger
  6472.               target = trigger.get_a_target(char, activators)
  6473.             end
  6474.           # if probability worked
  6475.           elsif rand(100) < trigger.value
  6476.             # default target flag
  6477.             target = true
  6478.           end
  6479.           # check next trigger if this one hasn't been activated
  6480.           next if target == nil
  6481.           # temporary variables
  6482.           basic, type, skill, scope, id = nil, 0, false, 0, trigger.action_data
  6483.           # check trigger action type
  6484.           case trigger.action_type
  6485.           when TRGAttack
  6486.             # set attack data for later processing if can attack
  6487.             basic, type, scope = true, 0, 1 if char.attack_can_use?
  6488.           when TRGDefend
  6489.             # set defend data for later processing
  6490.             basic, type, scope = true, 1, 0
  6491.           when TRGSkill
  6492.             # if can use skill
  6493.             if char.skill_can_use?(id)
  6494.               # set skill data for later processing
  6495.               basic, skill, scope = false, true, $data_skills[id].scope
  6496.             end
  6497.           when TRGItem
  6498.             # if can use item
  6499.             if char.item_can_use?(id)
  6500.               # set item data for later processing
  6501.               basic, scope = false, $data_items[id].scope
  6502.             end
  6503.           end
  6504.           # check next trigger if action can't be executed
  6505.           next if basic == nil
  6506.           # get targeting scope data
  6507.           enemy, dead, all = $BlizzABS.util.get_scope_data(scope)
  6508.           # if actual target exists and not targeting multiple battlers
  6509.           if target != true && !all
  6510.             # if targeting enemies
  6511.             if enemy
  6512.               # if chosen target is not part of enemy group
  6513.               unless in_sight_e.include?(target)
  6514.                 # get a new target
  6515.                 target = in_sight_e[rand(in_sight_e.size)]
  6516.               end
  6517.             else
  6518.               # filter all dead allies if targeting dead allies
  6519.               in_sight_a = in_sight_a.find_all {|a| a.battler.dead?} if dead
  6520.               # if chosen target is not part of ally group
  6521.               unless in_sight_a.include?(target)
  6522.                 # get a new target
  6523.                 target = in_sight_a[rand(in_sight_a.size)]
  6524.               end
  6525.             end
  6526.             # force this target to be the only one targetable
  6527.             in_sight_a, in_sight_e = [target], [target]
  6528.           end
  6529.           # set up action data
  6530.           normal_action(char, in_sight_a, in_sight_e, basic, type,
  6531.               (15 - char.ai.offensive) * 10, 0, id, skill, false)
  6532.           # trigger has been activated, abort
  6533.           return true}
  6534.       # no trigger has been activated
  6535.       return false
  6536.     end
  6537.     #--------------------------------------------------------------------------
  6538.     # advanced_actor_action
  6539.     #  char - the map actor
  6540.     #  Analyzes what the actor is capable of and uses that data to determine an
  6541.     #  action.
  6542.     #--------------------------------------------------------------------------
  6543.     def advanced_actor_action(char)
  6544.       # initialize skill action
  6545.       dmg, heal, neutral = [], [], []
  6546.       # iterate through all actions
  6547.       $BlizzABS.util.get_actor_skills(char.battler).each {|id|
  6548.           # if skill can be used
  6549.           if char.skill_can_use?(id)
  6550.             # if damaging skill
  6551.             if $data_skills[id].power > 0
  6552.               # add to array of damaging skills
  6553.               dmg.push(id)
  6554.             # if healing skill
  6555.             elsif $data_skills[id].power < 0
  6556.               # add to array of healing skills
  6557.               heal.push(id)
  6558.             else
  6559.               # add to array of neutral skills
  6560.               neutral.push(id)
  6561.             end
  6562.           end}
  6563.       # decide a target
  6564.       decide_target(char, dmg, heal, neutral, true, true, false)
  6565.     end
  6566.     #--------------------------------------------------------------------------
  6567.     # advanced_enemy_action
  6568.     #  char - the map enemy
  6569.     #  Analyzes what the enemy is capable of and uses that data to determine an
  6570.     #  action.
  6571.     #--------------------------------------------------------------------------
  6572.     def advanced_enemy_action(char)
  6573.       # initialize basic action
  6574.       attack = defend = escape = false
  6575.       # initialize skill action
  6576.       dmg, heal, neutral = [], [], []
  6577.       # iterate through all actions
  6578.       char.battler.actions.each {|action|
  6579.           # conditions
  6580.           n = $game_temp.battle_turn
  6581.           a = action.condition_turn_a
  6582.           b = action.condition_turn_b
  6583.           # skip if conditions are not fulfilled
  6584.           next if b == 0 && n != a || b > 0 && (n < 1 || n < a || n % b != a % b)
  6585.           next if char.battler.hp * 100.0 / char.battler.maxhp > action.condition_hp
  6586.           next if $game_party.max_level < action.condition_level
  6587.           switch_id = action.condition_switch_id
  6588.           next if switch_id > 0 && !$game_switches[switch_id]
  6589.           # depending on which basic type of action
  6590.           case action.kind
  6591.           when 0 # basic action
  6592.             case action.basic
  6593.             when 0 then attack = true
  6594.             when 1 then defend = true
  6595.             when 2 then escape = true
  6596.             end
  6597.           when 1 # skill action
  6598.             # if skill can be used
  6599.             if char.skill_can_use?(action.skill_id)
  6600.               # if damaging skill
  6601.               if $data_skills[action.skill_id].power > 0
  6602.                 # add to array of damaging skills
  6603.                 dmg.push(action.skill_id)
  6604.               # if healing skill
  6605.               elsif $data_skills[action.skill_id].power < 0
  6606.                 # add to array of healing skills
  6607.                 heal.push(action.skill_id)
  6608.               else
  6609.                 # add to array of neutral skills
  6610.                 neutral.push(action.skill_id)
  6611.               end
  6612.             end
  6613.           end}
  6614.       # decide a target
  6615.       decide_target(char, dmg, heal, neutral, attack, defend, escape)
  6616.     end
  6617.     #--------------------------------------------------------------------------
  6618.     # normal_action
  6619.     #  char       - the map character
  6620.     #  in_sight_a - allies in sight
  6621.     #  in_sight_e - enemies in sight
  6622.     #  basic      - basic type or not
  6623.     #  type       - which type
  6624.     #  def_time   - defending time
  6625.     #  run_time   - running away time
  6626.     #  object_id  - skill ID or item ID to use
  6627.     #  skill      - whether skill or item
  6628.     #  self_flag  - can target self
  6629.     #  Used to setup the action handling depending on which action was decided
  6630.     #  by using the normal way without the action attribute.
  6631.     #--------------------------------------------------------------------------
  6632.     def normal_action(char, in_sight_a, in_sight_e, basic, type, def_time,
  6633.                       run_time, object_id, skill = true, self_flag = true,
  6634.                       forced = false)
  6635.       # temporary variables
  6636.       x, y, ai = char.x, char.y, char.ai
  6637.       # if no data exists
  6638.       if in_sight_a == nil || in_sight_e == nil
  6639.         # get alignment setup
  6640.         negative, positive = ai.negative, ai.positive
  6641.         # invert setup if confused
  6642.         negative, positive = positive, negative if char.restriction == 3
  6643.         # if not basic action
  6644.         unless basic
  6645.           # get all allies in sight
  6646.           in_sight_a = ai.sight.find_all {|b| positive.include?(b.ai.group)}
  6647.         end
  6648.         # get all enemies in sight
  6649.         in_sight_e = ai.sight.find_all {|b| negative.include?(b.ai.group)}
  6650.       end
  6651.       # if basic action type
  6652.       if basic
  6653.         # depending on which enhanced type
  6654.         case type
  6655.         when ATTACK
  6656.           # set AI state
  6657.           ai.state = Ready
  6658.           # if skill
  6659.           if char.is_a?(Map_Actor)
  6660.             # get weapon data
  6661.             range = Weapons.range(char.battler.weapon_id)
  6662.             type = Weapons.type(char.battler.weapon_id)
  6663.           else
  6664.             # get enemy attack data
  6665.             range = Enemies.range(char.battler_id)
  6666.             type = Enemies.type(char.battler_id)
  6667.           end
  6668.           # set action data
  6669.           ai.act.set(range, ACTAttack, 0, type, ai.delay_time)
  6670.           # determine a random target from all enemies in sight
  6671.           ai.target = in_sight_e[rand(in_sight_e.size)]
  6672.           # if being forced
  6673.           if forced
  6674.             # turn toward the target if target exists and not being force moved
  6675.             char.turn_toward(ai.target) if ai.target != nil && char.move_type != 3
  6676.             # use attack action
  6677.             char.use_attack
  6678.             # reset action
  6679.             char.reset_action
  6680.             # reset action
  6681.             char.battler.current_action.clear
  6682.           end
  6683.         when DEFEND
  6684.           # set AI state
  6685.           ai.state = Defend
  6686.           # target the closest enemy
  6687.           ai.target = in_sight_e.min {|a, b|
  6688.               Math.hypot(x - b.x, y - b.y) <=> Math.hypot(x - a.x, y - a.y)}
  6689.           # turn toward the target if target exists and not being force moved
  6690.           char.turn_toward(ai.target) if ai.target != nil && char.move_type != 3
  6691.           # use defend action
  6692.           char.use_defend
  6693.           # set action data
  6694.           ai.act.set(3, ACTDefend, 0, 0, def_time)
  6695.         when ESCAPE
  6696.           # get a reference target from which to run away
  6697.           ai.target = in_sight_e[rand(in_sight_e.size)]
  6698.           # if reference target exists
  6699.           if ai.target != nil
  6700.             # set AI state
  6701.             ai.state = Escape
  6702.             # set action data
  6703.             ai.act.set(ai.view_range - 1, ACTEscape, 0, 0, run_time)
  6704.             # stop execution
  6705.             return
  6706.           end
  6707.         end
  6708.       else
  6709.         # if skill
  6710.         if skill
  6711.           # get skill data
  6712.           range, type = Skills.range(object_id), Skills.type(object_id)[0]
  6713.           # get skill and action
  6714.           object, action = $data_skills[object_id], ACTSkill
  6715.         else
  6716.           # get item data
  6717.           range, type = Items.range(object_id), Items.type(object_id)[0]
  6718.           # get item and action
  6719.           object, action = $data_items[object_id], ACTItem
  6720.         end
  6721.         # set action data
  6722.         ai.act.set(range, action, object.id, type, ai.delay_time)
  6723.         # if instant object
  6724.         if forced || ai.act.type == SUMMON || ai.act.type != SHOOT &&
  6725.             (object.scope == 0 || object.scope == 2 || object.scope == 4 ||
  6726.             object.scope == 6 || object.scope == 7)
  6727.           # instant execution of the skill or item
  6728.           skill ? char.use_skill(object, forced) : char.use_item(object, forced)
  6729.           # reset action
  6730.           char.reset_action
  6731.           # reset action
  6732.           char.battler.current_action.clear
  6733.         # if targeting enemies
  6734.         elsif object.scope == 1 || object.scope == 2 && ai.act.type == SHOOT
  6735.           # set an enemy target
  6736.           ai.target = in_sight_e[rand(in_sight_e.size)]
  6737.         # if targeting allies
  6738.         elsif object.scope == 3
  6739.           # add self if allowed to consider self as ally
  6740.           in_sight_a += [char] if self_flag
  6741.           # set an ally target
  6742.           ai.target = in_sight_a[rand(in_sight_a.size)]
  6743.         # if targeting dead allies
  6744.         elsif object.scope == 5 && in_sight_a[0].is_a?(Map_Actor)
  6745.           # set a dead ally target
  6746.           ai.target = in_sight_a[rand(in_sight_a.size)]
  6747.         end
  6748.       end
  6749.       ### 2DO
  6750.       # if player with valid target
  6751.       if char == $game_player && ai.target != nil
  6752.         # force in_battle flag
  6753.         in_battle, $game_temp.in_battle = $game_temp.in_battle, true
  6754.         # force selection override
  6755.         $game_temp.select_data = true
  6756.         # no delay
  6757.         self.try_execute(char)
  6758.         # restore flag
  6759.         $game_temp.in_battle = in_battle
  6760.         # remove dummy selection data
  6761.         $game_temp.select_data = nil
  6762.       end
  6763.       # if target doesn't exist or forced moving
  6764.       if ai.target == nil || !ai.target.valid?
  6765.         # reset action
  6766.         char.reset_action
  6767.       # if not being force moved
  6768.       elsif char.move_type != 3
  6769.         # set path request state
  6770.         ai.state = Request
  6771.         # turn toward the target not to lose it out of sight
  6772.         char.turn_toward(ai.target)
  6773.         # request a path
  6774.         request_path(char, ai.target)
  6775.       end
  6776.     end
  6777.     #--------------------------------------------------------------------------
  6778.     # decide_target
  6779.     #  char    - the map character
  6780.     #  dmg     - damaging actions
  6781.     #  heal    - healing actions
  6782.     #  neutral - actions without healing or damage
  6783.     #  attack  - can the character attack
  6784.     #  defend  - can the character defend
  6785.     #  escape  - can the character escape
  6786.     #  This is the fifth phase of the AI update. After a character has chosen
  6787.     #  to perform an action, this method finds an appropriate target for the
  6788.     #  character.
  6789.     #--------------------------------------------------------------------------
  6790.     def decide_target(char, dmg, heal, neutral, attack, defend, escape)
  6791.       # temporary variables
  6792.       x, y, ai = char.x, char.y, char.ai
  6793.       # get alignment setup
  6794.       negative, positive = ai.negative, ai.positive
  6795.       # invert setup if confused
  6796.       negative, positive = positive, negative if char.restriction == 3
  6797.       # initialize arrays
  6798.       allies, enemies = [char], []
  6799.       # if enemy
  6800.       if char.is_a?(Map_Enemy)
  6801.         # find all allies and all enemies in memory
  6802.         ai.memory.keys.each {|b|
  6803.             allies.push(b) if positive.include?(b.ai.group)
  6804.             enemies.push(b) if negative.include?(b.ai.group)}
  6805.       # if actor
  6806.       elsif char.is_a?(Map_Actor)
  6807.         # find all allies and all enemies in sight
  6808.         ai.sight.each {|b|
  6809.             allies.push(b) if positive.include?(b.ai.group)
  6810.             enemies.push(b) if negative.include?(b.ai.group)}
  6811.       end
  6812.       # find all allies who need healing
  6813.       to_heal = allies.find_all {|b| b.valid? && b.battler.hp < b.battler.maxhp}
  6814.       # if decided to heal
  6815.       if (heal.size > 0 && to_heal.size > 0 && (ai.healer || rand(3) == 0) &&
  6816.           rand(5) == 0)
  6817.         # find all skills that heal all allies
  6818.         allheal = heal.find_all {|id|
  6819.             $data_skills[id].scope == 2 || $data_skills[id].scope == 4 ||
  6820.             $data_skills[id].scope == 6}
  6821.         # test again flag
  6822.         test_again = true
  6823.         # if more than 1 ally who needs healing exists and allheal skills exist
  6824.         if to_heal.size > 1 && allheal.size > 0
  6825.           # initialize data
  6826.           decided, now, new = nil, [], []
  6827.           # iterate through all all-healing skills
  6828.           allheal.each {|id|
  6829.               # fake Blizz-ABS action setup
  6830.               ai.act.set(Skills.range(id), ACTSkill, id, Skills.type(id)[0],
  6831.                   ai.delay_time)
  6832.               # all allies who can be targeted by this skill
  6833.               new = to_heal.find_all {|b| $BlizzABS.can_execute?(char, b, ai.act)}
  6834.               # if not decided yet
  6835.               if decided == nil
  6836.                 # decide this skill and those allies
  6837.                 decided, now = id, new
  6838.               # 50% chance
  6839.               elsif rand(2) == 0
  6840.                 # intialize damage counters
  6841.                 dmg1 = dmg2 = 0
  6842.                 # sum up all damage for last decided targets
  6843.                 now.each {|b| dmg1 += b.battler.maxhp - b.battler.hp}
  6844.                 # sum up all damage for new targets
  6845.                 new.each {|b| dmg2 += b.battler.maxhp - b.battler.hp}
  6846.                 # decide this skill if it contains battlers with more damaged HP
  6847.                 decided, now = id, new if dmg2 > dmg1
  6848.               # if more battlers would be affected by this skill
  6849.               elsif new.size > now.size
  6850.                 # decide this skill and those allies
  6851.                 decided, now = id, new
  6852.               end}
  6853.           # if more than one battler can be healed
  6854.           if now.size > 1
  6855.             # setup Blizz-ABS action
  6856.             ai.act.set(Skills.range(decided), ACTSkill, decided,
  6857.                 Skills.type(decided)[0], ai.delay_time / 2)
  6858.             # don't test for one battler
  6859.             test_again = false
  6860.           end
  6861.         end
  6862.         # if should test for one battler
  6863.         if test_again
  6864.           # find all skills that heal one ally
  6865.           oneheal = heal.find_all {|id|
  6866.               $data_skills[id].scope == 1 || $data_skills[id].scope == 3 ||
  6867.               $data_skills[id].scope == 5}
  6868.           # if any skill exists
  6869.           if oneheal.size > 0
  6870.             # decided action
  6871.             decided = oneheal[rand(oneheal.size)]
  6872.             # decided target
  6873.             ai.target = to_heal[rand(to_heal.size)]
  6874.           else
  6875.             # decided action
  6876.             decided = heal[rand(heal.size)]
  6877.           end
  6878.           # stop execution if no skill decided
  6879.           return false if decided == nil
  6880.           # setup Blizz-ABS action
  6881.           ai.act.set(Skills.range(decided), ACTSkill, decided,
  6882.               Skills.type(decided)[0], ai.delay_time / 2)
  6883.         end
  6884.         # confirm execution
  6885.         return true
  6886.       end
  6887.       # not decided to escape yet
  6888.       escaping = false
  6889.       # if able to run away
  6890.       if escape && rand(5) == 0
  6891.         # if observation attribute is active
  6892.         if ai.observe && char.restriction != 3
  6893.           # iterate through all enemies
  6894.           enemies.each {|b|
  6895.               # if actor
  6896.               if b.is_a?(Map_Actor) && ai.observation[b.battler] != nil
  6897.                 # get damage per second rate
  6898.                 dps = get_observation(b.battler, ai.observation[b.battler].clone)
  6899.                 # 20% chance or damage per second-distance rate high enough
  6900.                 if rand(5) == 0 || dps * 128 / Math.hypot(b.real_x-
  6901.                     char.real_x, b.real_y-char.real_y) > char.battler.hp / 2
  6902.                   # set this battler as escape reference
  6903.                   ai.target = b
  6904.                   # running away
  6905.                   escaping = true
  6906.                   # abort iteration
  6907.                   break
  6908.                 end
  6909.               end}
  6910.         # 20% chance
  6911.         elsif rand(5) == 0
  6912.           # initialize minimum range
  6913.           min = nil
  6914.           # iterate through all enemies
  6915.           enemies.each {|b|
  6916.               # if closer than anybody else
  6917.               if (b.is_a?(Map_Actor) && (min == nil ||
  6918.                   Math.hypot(b.real_x-char.real_x, b.real_y-char.real_y) < min))
  6919.                 # set this battler as escape reference
  6920.                 ai.target = b
  6921.                 # set new minimum range
  6922.                 min = Math.hypot(b.real_x-char.real_x, b.real_y-char.real_y)
  6923.                 # running away
  6924.                 escaping = true
  6925.                 # abort iteration
  6926.                 break
  6927.               end}
  6928.         end
  6929.       end
  6930.       # if decided to escape
  6931.       if escaping
  6932.         # set AI state
  6933.         ai.state = Escape
  6934.         # set action data
  6935.         ai.act.set(ai.view_range - 1, ACTEscape, 0, 0, 80)
  6936.         # confirm execution
  6937.         return true
  6938.       end
  6939.       # not decided to defend yet
  6940.       defending = false
  6941.       # if able to defend
  6942.       if defend && rand(5) == 0
  6943.         # probability factor if higher if defensive and reset defend flag
  6944.         factor = rand(ai.defensive ? 10 : 30)
  6945.         # if decided to defend
  6946.         if char.battler.hp * 100 / char.battler.maxhp < factor
  6947.           # if observation attribute is active
  6948.           if ai.observe && char.restriction != 3
  6949.             # iterate through all enemies
  6950.             enemies.each {|b|
  6951.                 # if actor
  6952.                 if b.is_a?(Map_Actor) && ai.observation[b.battler] != nil
  6953.                   # get damage per second rate
  6954.                   dps = get_observation(b.battler,
  6955.                       ai.observation[b.battler].clone)
  6956.                   # 20% chance or damage per second-distance rate high enough
  6957.                   if rand(5) == 0 || dps * 128 / Math.hypot(b.real_x-
  6958.                       char.real_x, b.real_y-char.real_y) > char.battler.hp / 3
  6959.                     # defending
  6960.                     defending = true
  6961.                     # abort iteration
  6962.                     break
  6963.                   end
  6964.                 end}
  6965.           # 33% chance
  6966.           elsif enemies.size > 0 && rand(5) == 0
  6967.             # decided to defend
  6968.             defending = true
  6969.           end
  6970.         end
  6971.       end
  6972.       # if decided to defend
  6973.       if defending
  6974.         # set AI state
  6975.         ai.state = Defend
  6976.         # target the closest enemy
  6977.         ai.target = enemies.min {|a, b|
  6978.             Math.hypot(x-b.x, y-b.y) <=> Math.hypot(x-a.x, y-a.y)}
  6979.         # turn toward the target if target exists and not being force moved
  6980.         char.turn_toward(ai.target) if ai.target != nil && char.move_type != 3
  6981.         # use defend action
  6982.         char.use_defend
  6983.         # set action data
  6984.         ai.act.set(3, ACTDefend, 0, 0, rand(31) + 70)
  6985.         # confirm execution
  6986.         return true
  6987.       end
  6988.       # number of skills
  6989.       skill_number = dmg.size + heal.size + neutral.size
  6990.       # if able to attack and chosen to attack
  6991.       if attack && (skill_number == 0 || rand(skill_number) == 0)
  6992.         # if enemy
  6993.         if char.is_a?(Map_Enemy)
  6994.           # set AI state
  6995.           ai.state = Ready
  6996.           # setup Blizz-ABS action
  6997.           ai.act.set(Enemies.range(char.battler_id), ACTAttack, 0,
  6998.               Enemies.type(char.battler_id), ai.delay_time)
  6999.           # if observing attribute and not confused
  7000.           if ai.observe && char.restriction != 3
  7001.             # decide a target based upon observation experience
  7002.             observation_target(char, ai, enemies)
  7003.           end
  7004.         # if actor
  7005.         elsif char.is_a?(Map_Actor)
  7006.           # set AI state
  7007.           ai.state = Ready
  7008.           # setup Blizz-ABS action
  7009.           ai.act.set(Weapons.range(char.battler.weapon_id), ACTAttack, 0,
  7010.               Weapons.type(char.battler.weapon_id), ai.delay_time)
  7011.         end
  7012.         # if no target exists
  7013.         if ai.target == nil || !ai.target.valid?
  7014.           # get any enemy
  7015.           ai.target = enemies[rand(enemies.size)]
  7016.         end
  7017.         # confirm execution
  7018.         return true
  7019.       end
  7020.       # decide a random skill action
  7021.       decided = (dmg + neutral)[rand(dmg.size + neutral.size)]
  7022.       # if action exists
  7023.       if decided != nil
  7024.         # if observing
  7025.         if ai.observe && char.restriction != 3
  7026.           # decide a target based upon observation experience
  7027.           observation_target(char, ai, enemies)
  7028.         end
  7029.         # if no target was decided
  7030.         if ai.target == nil || !ai.target.valid?
  7031.           # if targeting enemies
  7032.           if $data_skills[decided].scope == 0 ||
  7033.               $data_skills[decided].scope == 1 ||
  7034.               $data_skills[decided].scope == 2
  7035.             # select a random enemy target
  7036.             ai.target = enemies[rand(enemies.size)]
  7037.           else
  7038.             # select a random ally target
  7039.             ai.target = allies[rand(allies.size)]
  7040.           end
  7041.         end
  7042.       end
  7043.       # stop execution if no target selected
  7044.       return false if ai.target == nil || !ai.target.valid?
  7045.       # setup Blizz-ABS action
  7046.       ai.act.set(Skills.range(decided), ACTSkill, decided,
  7047.           Skills.type(decided)[0], ai.delay_time)
  7048.       # confirm execution
  7049.       return true
  7050.     end
  7051.     #--------------------------------------------------------------------------
  7052.     # observation_target
  7053.     #  char    - the map character
  7054.     #  ai      - ai of the map character
  7055.     #  enemies - array of enemies
  7056.     #  The method decide_target calls this method to decide a target based
  7057.     #  upon observation experience.
  7058.     #--------------------------------------------------------------------------
  7059.     def observation_target(char, ai, enemies)
  7060.       # initialize dps array
  7061.       dps = {}
  7062.       # iterate through all enemies
  7063.       enemies.each {|b|
  7064.           # if being observed
  7065.           if b.is_a?(Map_Actor) && ai.observation[b.battler] != nil
  7066.             # associate battler with his dps within observation intervals
  7067.             dps[b] = get_observation(b.battler, ai.observation[b.battler].clone)
  7068.           end}
  7069.       # find the battler closest to a dps of 1/5 of the maxhp
  7070.       ai.target = dps.keys.min {|a, b|
  7071.           (char.battler.maxhp/5 - dps[a]).abs <=> (char.battler.maxhp/5 - dps[b]).abs}
  7072.     end
  7073.     #--------------------------------------------------------------------------
  7074.     # try_execute
  7075.     #  char - the map character
  7076.     #  If a character has a target defined or is about to execute a static
  7077.     #  action, this method controls it. It is called over and over until the
  7078.     #  target is within range.
  7079.     #--------------------------------------------------------------------------
  7080.     def try_execute(char)
  7081.       # temporary variables
  7082.       x, y, ai = char.x, char.y, char.ai
  7083.       # if battler doesn't exist or action is not valid
  7084.       if !ai.target.valid? || !ai.act.valid?
  7085.         # reset movement
  7086.         char.force_move = []
  7087.         # reset action
  7088.         char.reset_action
  7089.         # abort state
  7090.         ai.state = Abort
  7091.       # if charging and not charged yet
  7092.       elsif char.charging? && !char.charged?
  7093.         # abort state
  7094.         ai.state = Abort
  7095.       # if character can execute action
  7096.       elsif $BlizzABS.can_execute?(char)
  7097.         # if attack
  7098.         if ai.act.attack?
  7099.           # use attack
  7100.           char.use_attack
  7101.         # if skill
  7102.         elsif ai.act.skill?
  7103.           # use skill
  7104.           char.use_skill($data_skills[ai.act.id])
  7105.         # if item
  7106.         elsif ai.act.item?
  7107.           # use item
  7108.           char.use_item($data_items[ai.act.id])
  7109.         end
  7110.         # reset movement
  7111.         char.force_move = []
  7112.         # reset action
  7113.         char.reset_action
  7114.         # abort state
  7115.         ai.state = Abort
  7116.       end
  7117.     end
  7118.     #--------------------------------------------------------------------------
  7119.     # evade_projectiles
  7120.     #  char - the character
  7121.     #  Checks whether there are projectiles that could hit the character and
  7122.     #  determines the reaction of the character at the threat.
  7123.     #--------------------------------------------------------------------------
  7124.     def evade_projectiles(char)
  7125.       # temporary variable and get pixel movement rate
  7126.       ai, pix = char.ai, $BlizzABS.pixel
  7127.       # find all projectiles within sight or close hearing that can hit char
  7128.       projectiles = $BlizzABS.cache.remotes.find_all {|p|
  7129.           p.is_a?(Map_Projectile) &&
  7130.           p.type != REMOnReturn && p.type != REMInitSkill &&
  7131.           p.type != REMHomingSkill && p.type != REMInitItem &&
  7132.           p.type != REMHomingItem && p.group.include?(ai.group)}
  7133.       # filter projectiles depending on facing direction
  7134.       projectiles = case char.direction
  7135.       when 2 then projectiles.find_all {|p| p.real_y > char.real_y}
  7136.       when 4 then projectiles.find_all {|p| p.real_x < char.real_x}
  7137.       when 6 then projectiles.find_all {|p| p.real_x > char.real_x}
  7138.       when 8 then projectiles.find_all {|p| p.real_y < char.real_y}
  7139.       end
  7140.       # if enemy
  7141.       if char.is_a?(Map_Enemy)
  7142.         # filter projectiles
  7143.         projectiles = projectiles.find_all {|p| !wall?(char, p.x, p.y) &&
  7144.             can_perceive_char?(char, p.real_x, p.real_y)}
  7145.       end
  7146.       # check every projectile
  7147.       projectiles.each {|proj|
  7148.           # create affection area rectangle for projectile
  7149.           area = $BlizzABS.util.get_projectile_hit_area(proj)
  7150.           # if this projectile will hit character
  7151.           if $BlizzABS.util.intersection(area, char.hitbox)
  7152.             # depending on how to quicker evade it
  7153.             dir = case proj.direction
  7154.             when 2, 8 then (char.x >= proj.x ? 6 : 4)
  7155.             when 4, 6 then (char.y >= proj.y ? 2 : 8)
  7156.             end
  7157.             # if actually passable
  7158.             if char.passable?(char.x, char.y, dir)
  7159.               # move in that direction now
  7160.               char.force_move.unshift(Cache::FDirs[dir])
  7161.             # if passable in opposite direction
  7162.             elsif char.passable?(char.x, char.y, proj.direction)
  7163.               # move away now
  7164.               char.force_move.unshift(Cache::FDirs[proj.direction])
  7165.             end
  7166.           end}
  7167.     end
  7168.     #--------------------------------------------------------------------------
  7169.     # leader_update
  7170.     #  char - the leading map character
  7171.     #  The leader keeps updating every of his minions with the memory data of
  7172.     #  the other minions and shares their observation experience, so they can
  7173.     #  rate the actors and decide their actions better.
  7174.     #--------------------------------------------------------------------------
  7175.     def leader_update(char)
  7176.       # temporary variable
  7177.       ai = char.ai
  7178.       # if not leader
  7179.       if !ai.leader
  7180.         # minion releases self if leader has ceased to exist
  7181.         ai.lead = nil if ai.lead != nil && !ai.lead.valid?
  7182.         # stop
  7183.         return
  7184.       end
  7185.       # if confused
  7186.       if char.restriction == 3
  7187.         # release all minions
  7188.         ai.minions.each {|b| b.ai.lead = nil}
  7189.         ai.minions = []
  7190.         # stop updating
  7191.         return
  7192.       end
  7193.       # initialize
  7194.       in_range, delays, override = [], [], []
  7195.       # add all battlers in memory that have a matching group
  7196.       ai.memory.keys.each {|b| in_range.push(b) if b.ai.group == ai.group}
  7197.       # release all battlers that are out of range with expired counter
  7198.       (ai.minions - in_range).each {|b| b.ai.lead = nil}
  7199.       # minions are allies that are not leaders and don't have leaders
  7200.       ai.minions = in_range
  7201.       # remove other leaders
  7202.       ai.minions = in_range.find_all {|battler|
  7203.           !battler.ai.leader && battler.ai.lead == nil}
  7204.       # stop if no assigned minions
  7205.       return if ai.minions.size == 0
  7206.       # iterate through all minions
  7207.       ai.minions.each {|b|
  7208.           # if minion is not confused
  7209.           if b.restriction != 3
  7210.             # if action exists
  7211.             if b.ai.act.valid?
  7212.               # add delay time
  7213.               delays.push(b.ai.act.ready? ? 3 : b.ai.act.delay)
  7214.               # remember this minion
  7215.               override.push(b)
  7216.             end
  7217.             # set character as leader
  7218.             b.ai.lead = char
  7219.             # add battlers in sight
  7220.             ai.sight |= b.ai.sight
  7221.             # add minion's memorized battlers not memorized by leader yet
  7222.             ai.add_to_memory(b.ai.memory.keys - ai.memory.keys)
  7223.             # if battler observes
  7224.             if b.ai.observe
  7225.               # iterate through all observed battlers
  7226.               b.ai.observation.keys.each {|key|
  7227.                   # if no data exists for this battler
  7228.                   if ai.observation[key] == nil
  7229.                     # copy data
  7230.                     ai.observation[key] = b.ai.observation[key]
  7231.                   else
  7232.                     # unite time intervals
  7233.                     $BlizzABS.util.range_array_union(ai.observation[key],
  7234.                         b.ai.observation[key])
  7235.                   end}
  7236.             end
  7237.           end}
  7238.       # calculate average delay timer value
  7239.       average = delays.sum.to_f / delays.size
  7240.       # set each minion's delay timer to the average value
  7241.       override.each {|b| b.ai.act.delay = average}
  7242.     end
  7243.     #--------------------------------------------------------------------------
  7244.     # observe
  7245.     #  battler - the acting actor
  7246.     #  dmg     - damage done
  7247.     #  Stores actor damage. It Keeps track of all actor actions for enemy
  7248.     #  observations.
  7249.     #--------------------------------------------------------------------------
  7250.     def observe(battler, dmg)
  7251.       # create observer hash if none exists
  7252.       @observer = {} if @observer == nil
  7253.       # create battler hash if none exists
  7254.       @observer[battler] = [] if @observer[battler] == nil
  7255.       # if damage is numeric and there is damage
  7256.       if dmg.is_a?(Numeric) && dmg != 0
  7257.         # damage done at this moment if any damage done
  7258.         @observer[battler].push(ObserveData.new(dmg.abs, Graphics.frame_count))
  7259.       end
  7260.       # remove oldest if more than 1000 logs exist for this battler
  7261.       @observer[battler].shift if @observer[battler].size > 1000
  7262.     end
  7263.     #--------------------------------------------------------------------------
  7264.     # get_observation
  7265.     #  battler   - the requested actor
  7266.     #  intervals - time ranges where the actor was observed
  7267.     #  Returns the DPS (damage per second) rate for the given actor observed
  7268.     #  within the given intervals of time.
  7269.     #--------------------------------------------------------------------------
  7270.     def get_observation(battler, intervals = [])
  7271.       # create observer hash if none exists
  7272.       @observer = {} if @observer == nil
  7273.       # create battler hash if none exists
  7274.       @observer[battler] = [] if @observer[battler] == nil
  7275.       # initialize damage, time factors and temporary variable
  7276.       damage, time, tmp = 0, 1, intervals[intervals.size - 1]
  7277.       # if still observing
  7278.       if tmp.is_a?(Numeric)
  7279.         # convert starting observation time to interval until now
  7280.         intervals[intervals.size - 1] = tmp..Graphics.frame_count
  7281.       end
  7282.       # sum all damage within observation intervals
  7283.       @observer[battler].each {|data|
  7284.           damage += data.damage if intervals.any? {|int| data.time === int}}
  7285.       # sum up time of observation
  7286.       intervals.each {|int| time += int.last - int.first}
  7287.       # return damage per second rate
  7288.       return (damage * 40 / time)
  7289.     end
  7290.     #--------------------------------------------------------------------------
  7291.     # path_requesting_parameters
  7292.     #  x - x target coordinate or target character
  7293.     #  y - y target coordinate or nothing
  7294.     #  Prepares the parameters for path finding requests.
  7295.     #--------------------------------------------------------------------------
  7296.     def path_requesting_parameters(x, y)
  7297.       # if target is a character
  7298.       if x.is_a?(Map_Battler)
  7299.         # get pixel movement coordinates
  7300.         y = x.y
  7301.         x = x.x
  7302.       else
  7303.         # get pixel movement rate
  7304.         pix = $BlizzABS.pixel
  7305.         # if target is a normal character
  7306.         if x.is_a?(Game_Character)
  7307.           # create pixel movement coordinates from actual coordinates
  7308.           y = x.y * pix
  7309.           x = x.x * pix
  7310.         # if actual coordinates
  7311.         elsif x.is_a?(Numeric) && y.is_a?(Numeric)
  7312.           # create pixel movement coordinates from actual coordinates
  7313.           y *= pix
  7314.           x *= pix
  7315.         end
  7316.       end
  7317.       # return coordinates
  7318.       return [x, y]
  7319.     end
  7320.     #--------------------------------------------------------------------------
  7321.     # request_path
  7322.     #  a - character (point A) requesting a path
  7323.     #  x - x target coordinate or target character
  7324.     #  y - y target coordinate or nothing
  7325.     #  Logs requests for path finding.
  7326.     #--------------------------------------------------------------------------
  7327.     def request_path(a, x, y = nil)
  7328.       # get target coordinates from parameters
  7329.       x, y = path_requesting_parameters(x, y)
  7330.       # create requesting hash if none exists
  7331.       @request = {} if @request == nil
  7332.       # if request does not exist yet
  7333.       if a != nil && x != nil && y != nil && @request[a] == nil
  7334.         # add request
  7335.         @request[a] = PathRequest.new(a.x, a.y, x, y)
  7336.       end
  7337.     end
  7338.     #--------------------------------------------------------------------------
  7339.     # requesting
  7340.     #  char - character requesting a path
  7341.     #  Serves for quick determination if a character is waiting for a path to
  7342.     #  be calculated.
  7343.     #--------------------------------------------------------------------------
  7344.     def path_requesting?(char)
  7345.       return (@request != nil && @request[char] != nil)
  7346.     end
  7347.     #--------------------------------------------------------------------------
  7348.     # update
  7349.     #  Here is where the path calculation and observation is being done. The
  7350.     #  observer updates the data and the pathfinder calculation is being
  7351.     #  executed 5 times. It is called every frame while on the map.
  7352.     #--------------------------------------------------------------------------
  7353.     def update
  7354.       # create observer hash if none exists
  7355.       @observer = {} if @observer == nil
  7356.       # remove all observed actors that are not in the party (to save memory)
  7357.       @observer.clone.keys.each {|battler|
  7358.           @observer.delete(battler) unless $game_party.actors.include?(battler)}
  7359.       # create requesting hash if none exists
  7360.       @request = {} if @request == nil
  7361.       # get an array of all requesting characters
  7362.       characters = @request.keys
  7363.       # max of 4 calculations per frame to avoid lag
  7364.       count = 4
  7365.       # start calculation
  7366.       while characters.size > 0 && count > 0
  7367.         # get a hash key
  7368.         char = characters.shift
  7369.         # do path calculation for this character and his target
  7370.         result = find_path(char)
  7371.         # if result exists, add path to character, else add character to query
  7372.         result != nil ? char.force_move = result : characters.push(char)
  7373.         # decrease countdown
  7374.         count -= 1
  7375.       end
  7376.     end
  7377.     #--------------------------------------------------------------------------
  7378.     # find_path
  7379.     #  char - character requesting a path
  7380.     #  Implementation of the A* algorithm. It tests only one node and is called
  7381.     #  only 5 times per frame to prevent lag.
  7382.     #--------------------------------------------------------------------------
  7383.     def find_path(char)
  7384.       # get pixel movement rate
  7385.       pix = $BlizzABS.pixel
  7386.       # use request
  7387.       request = @request[char]
  7388.       # if no nodes to test
  7389.       if request.open.size == 0
  7390.         # abort testing for this character
  7391.         @request.delete(char)
  7392.         # resets state
  7393.         char.ai.state = (char.ai.state == Invalid ? Return : Ready)
  7394.         # stop execution
  7395.         return []
  7396.       end
  7397.       # found
  7398.       found = false
  7399.       # find minimal key
  7400.       key = request.open.keys.min {|a, b|
  7401.           Math.hypot(a[0] - request.tx, a[1] - request.ty) <=>
  7402.           Math.hypot(b[0] - request.tx, b[1] - request.ty)}
  7403.       # this node is now logged as checked
  7404.       request.closed[key[0], key[1]] = request.open[key]
  7405.       # remove this node from the pending array
  7406.       request.open.delete(key)
  7407.       # iterate through all possible directions with relative offsets
  7408.       Cache::PathDirs.each {|dir|
  7409.           # coordinates of new position
  7410.           kx, ky = key[0] + dir[0], key[1] + dir[1]
  7411.           # if new coordinates are destination
  7412.           if kx == request.tx && ky == request.ty
  7413.             # the new node was checked
  7414.             request.closed[kx, ky] = dir[2]
  7415.             # path was found
  7416.             found = true
  7417.             # stop checking
  7418.             break
  7419.           # if new node not checked yet and coordinates are passable
  7420.           elsif request.closed[kx, ky] == 0 &&
  7421.               char.passable?(key[0] * pix, key[1] * pix, dir[2])
  7422.             # add new node to be checked
  7423.             request.open[[kx, ky]] = dir[2]
  7424.           end}
  7425.       # stop execution except if found path
  7426.       return nil unless found
  7427.       # backtrack the path
  7428.       result = request.backtrack
  7429.       # finish testing for this character
  7430.       @request.delete(char)
  7431.       # resets state
  7432.       char.ai.state = (char.ai.state == Invalid ? Return : Ready)
  7433.       # return movement command array
  7434.       return result
  7435.     end
  7436.    
  7437.   end
  7438.  
  7439. end
  7440.  
  7441. # load Blizz-ABS Processor
  7442. $BlizzABS = BlizzABS::Processor.new
  7443.  
  7444. #==============================================================================
  7445. # module Input
  7446. #==============================================================================
  7447.  
  7448. module Input
  7449.  
  7450.   #----------------------------------------------------------------------------
  7451.   # Simple ASCII table
  7452.   #----------------------------------------------------------------------------
  7453.   Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
  7454.          'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
  7455.          'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
  7456.          'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
  7457.          'Y' => 89, 'Z' => 90,
  7458.          '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
  7459.          '6' => 54, '7' => 55, '8' => 56, '9' => 57,
  7460.          'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
  7461.          'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
  7462.          'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
  7463.          'NumberPad 9' => 33,
  7464.          'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
  7465.          'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
  7466.          'F11' => 122, 'F12' => 123,
  7467.          ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
  7468.          '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
  7469.          'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
  7470.          'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
  7471.          'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
  7472.          'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
  7473.          'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
  7474.          'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38,
  7475.          'Arrow Right' => 39, 'Arrow Down' => 40,
  7476.          'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
  7477.          'Mouse 4' => 5, 'Mouse 5' => 6}
  7478. #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7479. # START Configuration
  7480. #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7481.   UP = [Key['Arrow Up']]
  7482.   LEFT = [Key['Arrow Left']]
  7483.   DOWN = [Key['Arrow Down']]
  7484.   RIGHT = [Key['Arrow Right']]
  7485.   A = [Key['Shift']]
  7486.   B = [Key['Esc']]
  7487.   C = [Key['Enter']]
  7488.   X = []
  7489.   Y = []
  7490.   Z = []
  7491.   L = [Key['Page Down']]
  7492.   R = [Key['Page Up']]
  7493.   F5 = [Key['F5']]
  7494.   F6 = [Key['F6']]
  7495.   F7 = [Key['F7']]
  7496.   F8 = [Key['F8']]
  7497.   F9 = [Key['F9']]
  7498.   SHIFT = [Key['Shift']]
  7499.   CTRL = [Key['Ctrl']]
  7500.   ALT = [Key['Alt']]
  7501. #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7502. # END Configuration
  7503. #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7504.   # All keys
  7505.   KEY_COUNT = 256
  7506.   ALL_KEYS = (0...KEY_COUNT).to_a
  7507.   # Win32 API calls
  7508.   GetKeyboardState = Win32API.new('user32', 'GetKeyboardState', 'P', 'I')
  7509.   GetKeyboardLayout = Win32API.new('user32', 'GetKeyboardLayout', 'L', 'L')
  7510.   MapVirtualKeyEx = Win32API.new('user32', 'MapVirtualKeyEx', 'IIL', 'I')
  7511.   ToUnicodeEx = Win32API.new('user32', 'ToUnicodeEx', 'LLPPILL', 'L')
  7512.   # some other constants
  7513.   DOWN_STATE_MASK = 0x80
  7514.   DEAD_KEY_MASK = 0x80000000
  7515.   # data
  7516.   @state = "\0" * KEY_COUNT
  7517.   @triggered = Array.new(KEY_COUNT, false)
  7518.   @pressed = Array.new(KEY_COUNT, false)
  7519.   @released = Array.new(KEY_COUNT, false)
  7520.   @repeatedKey = -1
  7521.   @repeatedCount = 0
  7522.   #----------------------------------------------------------------------------
  7523.   # update
  7524.   #  Updates input.
  7525.   #----------------------------------------------------------------------------
  7526.   def self.update
  7527.     # get current language layout
  7528.     @language_layout = GetKeyboardLayout.call(0)
  7529.     # get new keyboard state
  7530.     GetKeyboardState.call(@state)
  7531.     # this special code is used because Ruby 1.9.x does not return a char
  7532.     # when using String#[] but another String
  7533.     key = 0
  7534.     @state.each_byte {|byte|
  7535.         # if pressed state
  7536.         if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK
  7537.           # not released anymore
  7538.           @released[key] = false
  7539.           # if not pressed yet
  7540.           if !@pressed[key]
  7541.             # pressed and triggered
  7542.             @pressed[key] = true
  7543.             @triggered[key] = true
  7544.             @repeatedKey = key
  7545.             @repeatedCount = 0
  7546.           else
  7547.             # not triggered anymore
  7548.             @triggered[key] = false
  7549.           end
  7550.           # update of repeat counter
  7551.           if key == @repeatedKey
  7552.             @repeatedCount < 17 ? @repeatedCount += 1 : @repeatedCount = 15
  7553.           end
  7554.         # not released yet
  7555.         elsif !@released[key]
  7556.           # if still pressed
  7557.           if @pressed[key]
  7558.             # not triggered, pressed or repeated, but released
  7559.             @triggered[key] = false
  7560.             @pressed[key] = false
  7561.             @released[key] = true
  7562.             if key == @repeatedKey
  7563.               @repeatedKey = -1
  7564.               @repeatedCount = 0
  7565.             end
  7566.           end
  7567.         else
  7568.           # not released anymore
  7569.           @released[key] = false
  7570.         end
  7571.         key += 1}
  7572.   end
  7573.   #----------------------------------------------------------------------------
  7574.   # dir4
  7575.   #  4 direction check.
  7576.   #----------------------------------------------------------------------------
  7577.   def self.dir4
  7578.     return 2 if self.press?(DOWN)
  7579.     return 4 if self.press?(LEFT)
  7580.     return 6 if self.press?(RIGHT)
  7581.     return 8 if self.press?(UP)
  7582.     return 0
  7583.   end
  7584.   #----------------------------------------------------------------------------
  7585.   # dir8
  7586.   #  8 direction check.
  7587.   #----------------------------------------------------------------------------
  7588.   def self.dir8
  7589.     down = self.press?(DOWN)
  7590.     left = self.press?(LEFT)
  7591.     return 1 if down && left
  7592.     right = self.press?(RIGHT)
  7593.     return 3 if down && right
  7594.     up = self.press?(UP)
  7595.     return 7 if up && left
  7596.     return 9 if up && right
  7597.     return 2 if down
  7598.     return 4 if left
  7599.     return 6 if right
  7600.     return 8 if up
  7601.     return 0
  7602.   end
  7603.   #----------------------------------------------------------------------------
  7604.   # trigger?
  7605.   #  Test if key was triggered once.
  7606.   #----------------------------------------------------------------------------
  7607.   def self.trigger?(keys)
  7608.     keys = [keys] if !keys.is_a?(Array)
  7609.     return keys.any? {|key| @triggered[key]}
  7610.   end
  7611.   #----------------------------------------------------------------------------
  7612.   # press?
  7613.   #  Test if key is being pressed.
  7614.   #----------------------------------------------------------------------------
  7615.   def self.press?(keys)
  7616.     keys = [keys] if !keys.is_a?(Array)
  7617.     return keys.any? {|key| @pressed[key]}
  7618.   end
  7619.   #----------------------------------------------------------------------------
  7620.   # repeat?
  7621.   #  Test if key is being pressed for repeating.
  7622.   #----------------------------------------------------------------------------
  7623.   def self.repeat?(keys)
  7624.     keys = [keys] if !keys.is_a?(Array)
  7625.     return (@repeatedKey >= 0 && keys.include?(@repeatedKey) &&
  7626.         (@repeatedCount == 1 || @repeatedCount == 16))
  7627.   end
  7628.   #----------------------------------------------------------------------------
  7629.   # release?
  7630.   #  Test if key was released.
  7631.   #----------------------------------------------------------------------------
  7632.   def self.release?(keys)
  7633.     keys = [keys] if !keys.is_a?(Array)
  7634.     return keys.any? {|key| @released[key]}
  7635.   end
  7636.   #----------------------------------------------------------------------------
  7637.   # get_character
  7638.   #  vk - virtual key
  7639.   #  Gets the character from keyboard input using the input locale identifier
  7640.   #  (formerly called keyboard layout handles).
  7641.   #----------------------------------------------------------------------------
  7642.   def self.get_character(vk)
  7643.     # get corresponding character from virtual key
  7644.     c = MapVirtualKeyEx.call(vk, 2, @language_layout)
  7645.     # stop if character is non-printable and not a dead key
  7646.     return '' if c < 32 && (c & DEAD_KEY_MASK) != DEAD_KEY_MASK
  7647.     # get scan code
  7648.     vsc = MapVirtualKeyEx.call(vk, 0, @language_layout)
  7649.     # result string is never longer than 4 bytes (Unicode)
  7650.     result = "\0" * 4
  7651.     # get input string from Win32 API
  7652.     length = ToUnicodeEx.call(vk, vsc, @state, result, 4, 0, @language_layout)
  7653.     return (length == 0 ? '' : result)
  7654.   end
  7655.   #----------------------------------------------------------------------------
  7656.   # get_input_string
  7657.   #  Gets the string that was entered using the keyboard over the input locale
  7658.   #  identifier (formerly called keyboard layout handles).
  7659.   #----------------------------------------------------------------------------
  7660.   def self.get_input_string
  7661.     result = ''
  7662.     # check every key
  7663.     ALL_KEYS.each {|key|
  7664.         # if repeated
  7665.         if self.repeat?(key)
  7666.           # get character from keyboard state
  7667.           c = self.get_character(key)
  7668.           # add character if there is a character
  7669.           result += c if c != ''
  7670.         end}
  7671.     # empty if result is empty
  7672.     return '' if result == ''
  7673.     # convert string from Unicode to UTF-8
  7674.     return self.unicode_to_utf8(result)
  7675.   end
  7676.   #----------------------------------------------------------------------------
  7677.   # unicode_to_utf8
  7678.   #  string - string in Unicode format
  7679.   #  Converts a string from Unicode format to UTF-8 format as RGSS does not
  7680.   #  support Unicode.
  7681.   #----------------------------------------------------------------------------
  7682.   def self.unicode_to_utf8(string)
  7683.     result = ''
  7684.     # L* format means a bunch of 4-byte wide-chars
  7685.     string.unpack('L*').each {|c|
  7686.         # characters under 0x80 are 1 byte characters
  7687.         if c < 0x0080
  7688.           result += c.chr
  7689.         # other characters under 0x800 are 2 byte characters
  7690.         elsif c < 0x0800
  7691.           result += (0xC0 | (c >> 6)).chr
  7692.           result += (0x80 | (c & 0x3F)).chr
  7693.         # other characters under 0x10000 are 3 byte characters
  7694.         elsif c < 0x10000
  7695.           result += (0xE0 | (c >> 12)).chr
  7696.           result += (0x80 | ((c >> 6) & 0x3F)).chr
  7697.           result += (0x80 | (c & 0x3F)).chr
  7698.         # other characters under 0x200000 are 4 byte characters
  7699.         elsif c < 0x200000
  7700.           result += (0xF0 | (c >> 18)).chr
  7701.           result += (0x80 | ((c >> 12) & 0x3F)).chr
  7702.           result += (0x80 | ((c >> 6) & 0x3F)).chr
  7703.           result += (0x80 | (c & 0x3F)).chr
  7704.         # other characters under 0x4000000 are 5 byte characters
  7705.         elsif c < 0x4000000
  7706.           result += (0xF8 | (c >> 24)).chr
  7707.           result += (0x80 | ((c >> 18) & 0x3F)).chr
  7708.           result += (0x80 | ((c >> 12) & 0x3F)).chr
  7709.           result += (0x80 | ((c >> 6) & 0x3F)).chr
  7710.           result += (0x80 | (c & 0x3F)).chr
  7711.         # other characters under 0x80000000 are 6 byte characters
  7712.         elsif c < 0x80000000
  7713.           result += (0xFC | (c >> 30)).chr
  7714.           result += (0x80 | ((c >> 24) & 0x3F)).chr
  7715.           result += (0x80 | ((c >> 18) & 0x3F)).chr
  7716.           result += (0x80 | ((c >> 12) & 0x3F)).chr
  7717.           result += (0x80 | ((c >> 6) & 0x3F)).chr
  7718.           result += (0x80 | (c & 0x3F)).chr
  7719.         end}
  7720.     return result
  7721.   end
  7722.  
  7723. end
  7724.  
  7725. #==============================================================================
  7726. # module Input
  7727. #------------------------------------------------------------------------------
  7728. # Added Blizz-ABS controls and control override.
  7729. #==============================================================================
  7730.  
  7731. module Input
  7732.  
  7733.   # Blizz-ABS control setup
  7734.   if BlizzABS::Control::CUSTOM_CONTROLS
  7735.     eval("Up       = [#{BlizzABS::Control::UP}]")
  7736.     eval("Left     = [#{BlizzABS::Control::LEFT}]")
  7737.     eval("Down     = [#{BlizzABS::Control::DOWN}]")
  7738.     eval("Right    = [#{BlizzABS::Control::RIGHT}]")
  7739.     eval("Prevpage = [#{BlizzABS::Control::PREVPAGE}]")
  7740.     eval("Nextpage = [#{BlizzABS::Control::NEXTPAGE}]")
  7741.     eval("Confirm  = [#{BlizzABS::Control::CONFIRM}]")
  7742.     eval("Cancel   = [#{BlizzABS::Control::CANCEL}]")
  7743.     eval("Attack   = [#{BlizzABS::Control::ATTACK}]")
  7744.     eval("Defend   = [#{BlizzABS::Control::DEFEND}]")
  7745.     eval("Skill    = [#{BlizzABS::Control::SKILL}]")
  7746.     eval("Item     = [#{BlizzABS::Control::ITEM}]")
  7747.     eval("Select   = [#{BlizzABS::Control::SELECT}]")
  7748.     eval("Hud      = [#{BlizzABS::Control::HUD}]")
  7749.     eval("Hotkey   = [#{BlizzABS::Control::HOTKEY}]")
  7750.     eval("Minimap  = [#{BlizzABS::Control::MINIMAP}]")
  7751.     eval("Run      = [#{BlizzABS::Control::RUN}]")
  7752.     eval("Sneak    = [#{BlizzABS::Control::SNEAK}]")
  7753.     eval("Jump     = [#{BlizzABS::Control::JUMP}]")
  7754.     eval("Turn     = [#{BlizzABS::Control::TURN}]")
  7755.   # default controls
  7756.   else
  7757.     Up       = [Key['W']]
  7758.     Left     = [Key['A']]
  7759.     Down     = [Key['S']]
  7760.     Right    = [Key['D']]
  7761.     Prevpage = [Key['Q']]
  7762.     Nextpage = [Key['E']]
  7763.     Confirm  = [Key['H']]
  7764.     Cancel   = [Key['F']]
  7765.     Attack   = [Key['K']]
  7766.     Defend   = [Key['L']]
  7767.     Skill    = [Key['J']]
  7768.     Item     = [Key['I']]
  7769.     Select   = [Key['O']]
  7770.     Hud      = [Key['Z']]
  7771.     Hotkey   = [Key['X']]
  7772.     Minimap  = [Key['C']]
  7773.     Run      = [Key['M']]
  7774.     Sneak    = [Key['.']]
  7775.     Jump     = [Key[',']]
  7776.     Turn     = [Key['U']]
  7777.   end
  7778.   if BlizzABS::Control::DISABLE_DEFAULT
  7779.     UP = Up
  7780.     LEFT = Left
  7781.     DOWN = Down
  7782.     RIGHT = Right
  7783.     B = Cancel
  7784.     C = Confirm
  7785.     L = Prevpage
  7786.     R = Nextpage
  7787.   else
  7788.     UP |= Up
  7789.     LEFT |= Left
  7790.     DOWN |= Down
  7791.     RIGHT |= Right
  7792.     B = (B - [Key['X']]) | Cancel
  7793.     C = (C - [Key['C']]) | Confirm
  7794.     L = (L - [Key['Page Down']]) | Prevpage
  7795.     R = (R - [Key['Page Up']]) | Nextpage
  7796.   end
  7797.  
  7798. end
  7799.  
  7800. #==============================================================================
  7801. # Numeric
  7802. #------------------------------------------------------------------------------
  7803. #  This class serves as superclass for all numbers. It was enhanced with a
  7804. #  utility method.
  7805. #==============================================================================
  7806.  
  7807. class Numeric
  7808.  
  7809.   #--------------------------------------------------------------------------
  7810.   # sgn
  7811.   #  Returns the sign of the number or 0 if the number is 0.
  7812.   #--------------------------------------------------------------------------
  7813.   def sgn
  7814.     return (self == 0 ? 0 : self / self.abs)
  7815.   end
  7816.  
  7817. end
  7818.  
  7819. #==============================================================================
  7820. # Array
  7821. #------------------------------------------------------------------------------
  7822. #  This class handles array data structures. It was modified to support the
  7823. #  utility operations sum and squares.
  7824. #==============================================================================
  7825.  
  7826. class Array
  7827.  
  7828.   #----------------------------------------------------------------------------
  7829.   # sum
  7830.   #  Sums up all the numeric values of the array.
  7831.   #----------------------------------------------------------------------------
  7832.   def sum
  7833.     # initialize
  7834.     sum = 0
  7835.     # add each element that's a number to sum
  7836.     self.each {|i| sum += i if i.is_a?(Numeric)}
  7837.     # return sum as float
  7838.     return sum
  7839.   end
  7840.  
  7841. end
  7842.  
  7843. #==============================================================================
  7844. # Hash
  7845. #------------------------------------------------------------------------------
  7846. #  This class handles hash data structures. It was modified to support the
  7847. #  utility operations sum and squares.
  7848. #==============================================================================
  7849.  
  7850. class Hash
  7851.  
  7852.   #----------------------------------------------------------------------------
  7853.   # sum
  7854.   #  Sums up all the numeric values of the array.
  7855.   #----------------------------------------------------------------------------
  7856.   def sum
  7857.     # initialize
  7858.     sum = 0
  7859.     # add each element that's a number to sum
  7860.     self.values.each {|i| sum += i if i.is_a?(Numeric)}
  7861.     # return sum as float
  7862.     return sum
  7863.   end
  7864.  
  7865. end
  7866.  
  7867. #============================================================================
  7868. # Circle
  7869. #----------------------------------------------------------------------------
  7870. #  This class represents a circle.
  7871. #============================================================================
  7872.  
  7873. class Circle
  7874.  
  7875.   # setting all accessible variables
  7876.   attr_accessor :x
  7877.   attr_accessor :y
  7878.   attr_accessor :radius
  7879.   attr_accessor :direction
  7880.   #--------------------------------------------------------------------------
  7881.   # Initialization
  7882.   #  x      - center x-coordinate
  7883.   #  y      - center y-coordinate
  7884.   #  radius - circle radius
  7885.   #--------------------------------------------------------------------------
  7886.   def initialize(x = 0, y = 0, radius = 1, direction = 0)
  7887.     @x, @y, @radius, @direction = x, y, radius, direction
  7888.   end
  7889.  
  7890. end
  7891.  
  7892. #==============================================================================
  7893. # Sprite
  7894. #------------------------------------------------------------------------------
  7895. #  This class was enhanced with quick color access, a critical animation flag
  7896. #  and special viewport coordinate calculation that is used by all HUD
  7897. #  elements.
  7898. #==============================================================================
  7899.  
  7900. class Sprite
  7901.  
  7902.   # setting all accessible variables
  7903.   attr_accessor :critical
  7904.   #----------------------------------------------------------------------------
  7905.   # system_color
  7906.   #  Returns the system color.
  7907.   #----------------------------------------------------------------------------
  7908.   def system_color
  7909.     return Color.new(192, 224, 255)
  7910.   end
  7911.   #----------------------------------------------------------------------------
  7912.   # normal_color
  7913.   #  Returns the normal color.
  7914.   #----------------------------------------------------------------------------
  7915.   def normal_color
  7916.     return Color.new(255, 255, 255)
  7917.   end
  7918.   #----------------------------------------------------------------------------
  7919.   # disabled_color
  7920.   #  Returns the disabled color.
  7921.   #----------------------------------------------------------------------------
  7922.   def disabled_color
  7923.     return Color.new(255, 255, 255, 128)
  7924.   end
  7925.   #----------------------------------------------------------------------------
  7926.   # crisis_color
  7927.   #  Returns the crisis color.
  7928.   #----------------------------------------------------------------------------
  7929.   def crisis_color
  7930.     return Color.new(255, 255, 64)
  7931.   end
  7932.   #----------------------------------------------------------------------------
  7933.   # knockout_color
  7934.   #  Returns the knockout color.
  7935.   #----------------------------------------------------------------------------
  7936.   def knockout_color
  7937.     return Color.new(255, 64, 0)
  7938.   end
  7939.   #----------------------------------------------------------------------------
  7940.   # vx
  7941.   #  Returns the x position on the screen.
  7942.   #----------------------------------------------------------------------------
  7943.   def vx
  7944.     return (self.x + (viewport == nil ? 0 : viewport.rect.x))
  7945.   end
  7946.   #----------------------------------------------------------------------------
  7947.   # vy
  7948.   #  Returns the y position on the screen.
  7949.   #----------------------------------------------------------------------------
  7950.   def vy
  7951.     return (self.y + (viewport == nil ? 0 : viewport.rect.y))
  7952.   end
  7953.   #----------------------------------------------------------------------------
  7954.   # vw
  7955.   #  Returns the width visible on the screen.
  7956.   #----------------------------------------------------------------------------
  7957.   def vw
  7958.     return (viewport == nil ? self.bitmap.width : viewport.rect.width)
  7959.   end
  7960.   #----------------------------------------------------------------------------
  7961.   # vh
  7962.   #  Returns the height visible on the screen.
  7963.   #----------------------------------------------------------------------------
  7964.   def vh
  7965.     return (viewport == nil ? self.bitmap.height : viewport.rect.height)
  7966.   end
  7967.   #----------------------------------------------------------------------------
  7968.   # in_screen?
  7969.   #  Checks if the sprite is visible on the screen.
  7970.   #----------------------------------------------------------------------------
  7971.   def in_screen?
  7972.     return (self.x.between?(0, 639) && (self.y-16).between?(0, 479))
  7973.   end
  7974.  
  7975. end
  7976.  
  7977. #==============================================================================
  7978. # RPG::Weapon
  7979. #------------------------------------------------------------------------------
  7980. #  This class was enhanced with optional data drawing either in name or in
  7981. #  description.
  7982. #==============================================================================
  7983.  
  7984. class RPG::Weapon
  7985.  
  7986.   #----------------------------------------------------------------------------
  7987.   # name
  7988.   #  Encapsulation of the name variable to provide the possibility of
  7989.   #  additional display.
  7990.   #----------------------------------------------------------------------------
  7991.   def name
  7992.     return $BlizzABS.util.add_weapon_text(@name, @id, 1)
  7993.   end
  7994.   #----------------------------------------------------------------------------
  7995.   # description
  7996.   #  Encapsulation of the description variable to provide the possibility of
  7997.   #  additional display.
  7998.   #----------------------------------------------------------------------------
  7999.   def description
  8000.     return $BlizzABS.util.add_weapon_text(@description, @id, 2)
  8001.   end
  8002.  
  8003. end
  8004.  
  8005. #==============================================================================
  8006. # RPG::Skill
  8007. #------------------------------------------------------------------------------
  8008. #  This class was enhanced with optional data drawing either in name or in
  8009. #  description.
  8010. #==============================================================================
  8011.  
  8012. class RPG::Skill
  8013.  
  8014.   #----------------------------------------------------------------------------
  8015.   # name
  8016.   #  Encapsulation of the name variable to provide the possibility of
  8017.   #  additional display.
  8018.   #----------------------------------------------------------------------------
  8019.   def name
  8020.     return $BlizzABS.util.add_skill_text(@name, @id, 1)
  8021.   end
  8022.   #----------------------------------------------------------------------------
  8023.   # description
  8024.   #  Encapsulation of the description variable to provide the possibility of
  8025.   #  additional display.
  8026.   #----------------------------------------------------------------------------
  8027.   def description
  8028.     return $BlizzABS.util.add_skill_text(@description, @id, 2)
  8029.   end
  8030.  
  8031. end
  8032.  
  8033. #==============================================================================
  8034. # RPG::Item
  8035. #------------------------------------------------------------------------------
  8036. #  This class was enhanced with optional data drawing either in name or in
  8037. #  description.
  8038. #==============================================================================
  8039.  
  8040. class RPG::Item
  8041.  
  8042.   #----------------------------------------------------------------------------
  8043.   # name
  8044.   #  Encapsulation of the name variable to provide the possibility of
  8045.   #  additional display.
  8046.   #----------------------------------------------------------------------------
  8047.   def name
  8048.     return $BlizzABS.util.add_item_text(@name, @id, 1)
  8049.   end
  8050.   #----------------------------------------------------------------------------
  8051.   # description
  8052.   #  Encapsulation of the description variable to provide the possibility of
  8053.   #  additional display.
  8054.   #----------------------------------------------------------------------------
  8055.   def description
  8056.     return $BlizzABS.util.add_item_text(@description, @id, 2)
  8057.   end
  8058.  
  8059. end
  8060.  
  8061. #==============================================================================
  8062. # Interpreter
  8063. #------------------------------------------------------------------------------
  8064. #  This class was enhanced with battleflow controlling commands. It was also
  8065. #  enhanced to support pixel movement for the force move command in case the
  8066. #  player is affected. It was also enhanced to support Blizz-ABS battle
  8067. #  handling and ABSEAL limitation.
  8068. #==============================================================================
  8069.  
  8070. class Interpreter
  8071.  
  8072.   # constants to help the user
  8073.   PARTY    = BlizzABS::PARTY
  8074.   TROOP    = BlizzABS::TROOP
  8075.   INCREASE = BlizzABS::INCREASE
  8076.   DECREASE = BlizzABS::DECREASE
  8077.   CONSTANT = BlizzABS::CONSTANT
  8078.   VARIABLE = BlizzABS::VARIABLE
  8079.   KILL     = BlizzABS::KILL
  8080.   NO_KILL  = BlizzABS::NO_KILL
  8081.   ADD      = BlizzABS::ADD
  8082.   REMOVE   = BlizzABS::REMOVE
  8083.   ATTACK   = BlizzABS::ATTACK
  8084.   DEFEND   = BlizzABS::DEFEND
  8085.   ESCAPE   = BlizzABS::ESCAPE
  8086.   SKILL    = BlizzABS::SKILL
  8087.   ITEM     = BlizzABS::ITEM
  8088.   ENEMIES  = BlizzABS::ENEMIES
  8089.   ACTORS   = BlizzABS::ACTORS
  8090.   NONE     = BlizzABS::NONE
  8091.  
  8092.   #----------------------------------------------------------------------------
  8093.   # override setup
  8094.   #----------------------------------------------------------------------------
  8095.   alias setup_blizzabs_later setup
  8096.   def setup(list, event_id)
  8097.     # clear trigger for special triggers
  8098.     if event_id != 0 && $game_map.events[event_id].trigger > 4
  8099.       $game_map.events[event_id].clear_starting
  8100.       $game_map.events[event_id].lock
  8101.     end
  8102.     # call original method
  8103.     setup_blizzabs_later(list, event_id)
  8104.     # for battleflow control commands
  8105.     @SELF = @event_id
  8106.   end
  8107.   #----------------------------------------------------------------------------
  8108.   # override command_end
  8109.   #----------------------------------------------------------------------------
  8110.   alias cmd_end_blizzabs_later command_end
  8111.   def command_end
  8112.     # delete event code
  8113.     @list = nil
  8114.     # call original method if event exists and return result or return true
  8115.     return ($game_map.events[@event_id] != nil ? cmd_end_blizzabs_later : true)
  8116.   end
  8117.   #----------------------------------------------------------------------------
  8118.   # override execute_command
  8119.   #----------------------------------------------------------------------------
  8120.   alias execute_command_blizzabs_later execute_command
  8121.   def execute_command
  8122.     # if on the map
  8123.     if $scene.is_a?(Scene_Map)
  8124.       # store old in_battle flag and set to false
  8125.       flag, $game_temp.in_battle = $game_temp.in_battle, false
  8126.     end
  8127.     # call original method
  8128.     result = execute_command_blizzabs_later
  8129.     # set in_battle flag back if on the map
  8130.     $game_temp.in_battle = flag if flag != nil
  8131.     # result of the command
  8132.     return result
  8133.   end
  8134.   #----------------------------------------------------------------------------
  8135.   # override command_209
  8136.   #----------------------------------------------------------------------------
  8137.   alias cmd_209_blizzabs_later command_209
  8138.   def command_209
  8139.     # call original method
  8140.     result = cmd_209_blizzabs_later
  8141.     # if REPAIR_MOVEMENT is turned on and character is player
  8142.     if $game_system.move_fix && @parameters.size == 2 &&
  8143.        get_character(@parameters[0]).is_a?(Map_Battler)
  8144.       # create command list duplicate
  8145.       old_list = @parameters[1].list.clone
  8146.       # remove original command list
  8147.       @parameters[1].list = []
  8148.       # iterate through all commands
  8149.       old_list.each {|command|
  8150.           # add command to command list
  8151.           @parameters[1].list.push(command)
  8152.           # if one of the movement commands
  8153.           if command.code.between?(1, 13)
  8154.             # add pixel movement rate - 1 times to correct movement
  8155.             ($BlizzABS.pixel - 1).times{@parameters[1].list.push(command)}
  8156.           end}
  8157.       @parameters.push(true)
  8158.     end
  8159.     # return result
  8160.     return result
  8161.   end
  8162.  
  8163. end
  8164.  
  8165. #==============================================================================
  8166. # Game_Temp
  8167. #------------------------------------------------------------------------------
  8168. #  This class was enhanced with a data pack that holds everything needed for
  8169. #  the character selection exception handling.
  8170. #==============================================================================
  8171.  
  8172. class Game_Temp
  8173.  
  8174.   attr_accessor :select_data
  8175.   attr_accessor :hud_refresh
  8176.  
  8177. end
  8178.  
  8179. #==============================================================================
  8180. # Game_System
  8181. #------------------------------------------------------------------------------
  8182. #  This class was enhanced with Blizz-ABS system settings, enemy creation and
  8183. #  destruction process handling.
  8184. #==============================================================================
  8185.  
  8186. class Game_System
  8187.  
  8188.   # setting all accessible variables
  8189.   attr_accessor :controls
  8190.   attr_accessor :auto_gameover
  8191.   attr_accessor :hud
  8192.   attr_accessor :hotkeys
  8193.   attr_accessor :minimap
  8194.   attr_accessor :move_fix
  8195.   attr_accessor :_8_way
  8196.   attr_accessor :bar_style
  8197.   attr_accessor :alignments
  8198.   attr_accessor :blizzabs
  8199.   attr_accessor :respawn_time
  8200.   attr_accessor :attack_button
  8201.   attr_accessor :defend_button
  8202.   attr_accessor :skill_button
  8203.   attr_accessor :item_button
  8204.   attr_accessor :select_button
  8205.   attr_accessor :hud_button
  8206.   attr_accessor :hotkey_button
  8207.   attr_accessor :minimap_button
  8208.   attr_accessor :turn_button
  8209.   attr_accessor :running_button
  8210.   attr_accessor :sneaking_button
  8211.   attr_accessor :jumping_button
  8212.   attr_reader   :killed
  8213.   attr_reader   :caterpillar
  8214.   attr_reader   :caterpillar_active
  8215.   attr_reader   :pixel_rate
  8216.   attr_reader   :bar_opacity
  8217.   # compatibility with ccoa's UMS
  8218.   attr_accessor :ums_mode
  8219.   #----------------------------------------------------------------------------
  8220.   # override initiliaze
  8221.   #----------------------------------------------------------------------------
  8222.   alias init_blizzabs_later initialize
  8223.   def initialize
  8224.     # call original method
  8225.     init_blizzabs_later
  8226.     # turn HUD on, Hotkey Assignment Display off and Minimap off
  8227.     @hud, @hotkeys, @minimap = true, false, 0
  8228.     # set auto gameover
  8229.     @auto_gameover = BlizzABS::Config::AUTO_GAMEOVER
  8230.     # set movement fix
  8231.     @move_fix = BlizzABS::Config::REPAIR_MOVEMENT
  8232.     # set 8-way movement
  8233.     @_8_way = BlizzABS::Config::EIGHT_WAY_MOVEMENT
  8234.     # set respawn time
  8235.     @respawn_time = BlizzABS::Config::RESPAWN_TIME
  8236.     # all action buttons available
  8237.     @attack_button = @defend_button = @skill_button = @item_button =
  8238.         @select_button = @hud_button = @hotkey_button = @minimap_button =
  8239.         @turn_button = true
  8240.     # movement buttons available depending on their configuration
  8241.     @running_button = (BlizzABS::Config::RUN_SPEED > 0)
  8242.     @sneaking_button = (BlizzABS::Config::SNEAK_SPEED > 0)
  8243.     @jumping_button = (BlizzABS::Config::JUMPING > 0)
  8244.     # set caterpillar
  8245.     @caterpillar = BlizzABS::Config::CATERPILLAR
  8246.     # set caterpillar active
  8247.     @caterpillar_active = true
  8248.     # set pixel movement rate
  8249.     self.pixel_rate = BlizzABS::Config::PIXEL_MOVEMENT_RATE
  8250.     # set up alignments
  8251.     @alignments = {}
  8252.     # create all initial alignment group setups
  8253.     BlizzABS::Alignments::GROUPS.each {|id|
  8254.         @alignments[id] = BlizzABS::AlignmentData.new(id)}
  8255.     # create AI now that alignments have been initialized
  8256.     $BlizzABS.AI = BlizzABS::AI.new
  8257.     # reset ABS data
  8258.     reset_abs_data
  8259.   end
  8260.   #----------------------------------------------------------------------------
  8261.   # override update
  8262.   #----------------------------------------------------------------------------
  8263.   alias upd_blizzabs_later update
  8264.   def update
  8265.     # call original method
  8266.     upd_blizzabs_later
  8267.     # delete removed alignment groups
  8268.     (@alignments.keys - BlizzABS::Alignments::GROUPS).each {|id|
  8269.         @alignments.delete(id)}
  8270.     # add all new alignment groups
  8271.     (BlizzABS::Alignments::GROUPS - @alignments.keys).each {|id|
  8272.         @alignments[id] = BlizzABS::AlignmentData.new(id)}
  8273.     # update Blizz-ABS Processor
  8274.     $BlizzABS.update
  8275.   end
  8276.   #----------------------------------------------------------------------------
  8277.   # caterpillar_active=
  8278.   #  Sets the caterpillar active mode.
  8279.   #----------------------------------------------------------------------------
  8280.   def caterpillar_active=(val)
  8281.     # dismantle caterpillar if deactivating
  8282.     $BlizzABS.actors.each {|actor| actor.remove_from_caterpillar} unless val
  8283.     # set new value
  8284.     @caterpillar_active = val
  8285.   end
  8286.   #----------------------------------------------------------------------------
  8287.   # caterpillar=
  8288.   #  Sets the caterpillar value and makes sure that the displayed characters
  8289.   #  are being refreshed.
  8290.   #----------------------------------------------------------------------------
  8291.   def caterpillar=(val)
  8292.     # if value has changed
  8293.     if @caterpillar != val
  8294.       # set new value
  8295.       @caterpillar = val
  8296.       # refresh player
  8297.       $game_player.refresh
  8298.     end
  8299.   end
  8300.   #----------------------------------------------------------------------------
  8301.   # pixel_rate=
  8302.   #  val - new pixel movement rate
  8303.   #  Changes the pixel movement rate is necessary.
  8304.   #----------------------------------------------------------------------------
  8305.   def pixel_rate=(val)
  8306.     if val > 5
  8307.       @pixel_rate = 5
  8308.     elsif val < 0
  8309.       @pixel_rate = 0
  8310.     else
  8311.       @pixel_rate = val
  8312.     end
  8313.   end
  8314.   #----------------------------------------------------------------------------
  8315.   # add_battlers_number
  8316.   #  group - group of the battler
  8317.   #  val   - the value to add
  8318.   #  Adds a count to the battler group count.
  8319.   #----------------------------------------------------------------------------
  8320.   def add_battler_number(group, val)
  8321.     @battlers_number[group] = battlers_number_group(group) + val
  8322.     @battlers_number[group] = 0 if @battlers_number[group] < 0
  8323.   end
  8324.   #----------------------------------------------------------------------------
  8325.   # battlers_number
  8326.   #  Returns the number of battlers on the current map.
  8327.   #----------------------------------------------------------------------------
  8328.   def battlers_number
  8329.     return @battlers_number.sum
  8330.   end
  8331.   #----------------------------------------------------------------------------
  8332.   # battlers_number_group
  8333.   #  group - group of the battler
  8334.   #  Returns the number of battlers on the current map from a specific type.
  8335.   #----------------------------------------------------------------------------
  8336.   def battlers_number_group(group)
  8337.     return (@battlers_number[group] != nil ? @battlers_number[group] : 0)
  8338.   end
  8339.   #----------------------------------------------------------------------------
  8340.   # reset_abs_data
  8341.   #  Resets ABS map data.
  8342.   #----------------------------------------------------------------------------
  8343.   def reset_abs_data
  8344.     # reset killed battlers arrays and the counters
  8345.     @killed, @battlers_number = {}, {}
  8346.   end
  8347.  
  8348. end
  8349.  
  8350. #==============================================================================
  8351. # Game_Screen
  8352. #------------------------------------------------------------------------------
  8353. #  This class was modified to correctly update pictures.
  8354. #==============================================================================
  8355.  
  8356. class Game_Screen
  8357.  
  8358.   #--------------------------------------------------------------------------
  8359.   # override update
  8360.   #--------------------------------------------------------------------------
  8361.   alias upd_blizzabs_later update
  8362.   def update
  8363.     # if on the map
  8364.     if $scene.is_a?(Scene_Map)
  8365.       # store old in_battle flag and set to false
  8366.       flag, $game_temp.in_battle = $game_temp.in_battle, false
  8367.     end
  8368.     # call original method
  8369.     upd_blizzabs_later
  8370.     # set in_battle flag back if on the map
  8371.     $game_temp.in_battle = flag if $scene.is_a?(Scene_Map)
  8372.   end
  8373.  
  8374. end
  8375.  
  8376. #==============================================================================
  8377. # Game_BattleAction
  8378. #------------------------------------------------------------------------------
  8379. #  This class was modified to prevent a bug where deciding a random target
  8380. #  for an enemy would cause the action to be cleared.
  8381. #==============================================================================
  8382.  
  8383. class Game_BattleAction
  8384.  
  8385.   #--------------------------------------------------------------------------
  8386.   # decide_random_target_for_enemy
  8387.   #  Dummy method.
  8388.   #--------------------------------------------------------------------------
  8389.   def decide_random_target_for_enemy
  8390.   end
  8391.  
  8392. end
  8393.  
  8394. #==============================================================================
  8395. # Game_Battler
  8396. #------------------------------------------------------------------------------
  8397. #  This class was enhanced with helping variables and methods.
  8398. #==============================================================================
  8399.  
  8400. class Game_Battler
  8401.  
  8402.   # setting all accessible variables
  8403.   attr_accessor :group
  8404.   attr_accessor :state_time
  8405.   attr_writer   :hpdamage
  8406.   attr_writer   :spdamage
  8407.   attr_accessor :last_attackers
  8408.   attr_accessor :last_slip_attackers
  8409.   attr_accessor :last_action
  8410.   attr_accessor :last_targets
  8411.   attr_accessor :last_hit_by
  8412.  
  8413.   #----------------------------------------------------------------------------
  8414.   # initialize
  8415.   #----------------------------------------------------------------------------
  8416.   alias initialize_blizzabs_earlier initialize
  8417.   def initialize
  8418.     initialize_blizzabs_earlier
  8419.     # reset last attackers
  8420.     @last_attackers = []
  8421.     # reset last slip attackers
  8422.     @last_slip_attackers = []
  8423.     # reset last action
  8424.     @last_action = ["none", false]
  8425.     # reset last targets
  8426.     @last_targets = []
  8427.     # reset lats hit by
  8428.     @last_hit_by = nil
  8429.   end
  8430.   #----------------------------------------------------------------------------
  8431.   # override hp=
  8432.   #----------------------------------------------------------------------------
  8433.   alias hp_is_blizzabs_later hp=
  8434.   def hp=(val)
  8435.     # store difference
  8436.     @hpdamage = @hp-val
  8437.     # call original method
  8438.     hp_is_blizzabs_later(val)
  8439.   end
  8440.   #----------------------------------------------------------------------------
  8441.   # override sp=
  8442.   #----------------------------------------------------------------------------
  8443.   alias sp_is_blizzabs_later sp=
  8444.   def sp=(val)
  8445.     # store difference
  8446.     @spdamage = @sp-val
  8447.     # call original method
  8448.     sp_is_blizzabs_later(val)
  8449.   end
  8450.   #----------------------------------------------------------------------------
  8451.   # hpdamage
  8452.   #  Returns hpdamage encapsulated.
  8453.   #----------------------------------------------------------------------------
  8454.   def hpdamage
  8455.     return (@hpdamage == nil ? 0 : @hpdamage)
  8456.   end
  8457.   #----------------------------------------------------------------------------
  8458.   # spdamage
  8459.   #  Returns spdamage encapsulated.
  8460.   #----------------------------------------------------------------------------
  8461.   def spdamage
  8462.     return (@spdamage == nil ? 0 : @spdamage)
  8463.   end
  8464.  
  8465. end
  8466.  
  8467. #==============================================================================
  8468. # Game_Actor
  8469. #------------------------------------------------------------------------------
  8470. #  This class was enhanced with helping variables and methods.
  8471. #==============================================================================
  8472.  
  8473. class Game_Actor
  8474.  
  8475.   # setting all accessible variables
  8476.   attr_accessor :skill
  8477.   attr_accessor :item
  8478.   attr_accessor :offensive
  8479.   attr_accessor :aggressive
  8480.   attr_reader   :skill_hotkeys
  8481.   attr_reader   :item_hotkeys
  8482.   attr_reader   :force_offensive
  8483.   attr_reader   :force_aggressive
  8484.   attr_reader   :triggers
  8485.   #----------------------------------------------------------------------------
  8486.   # override setup
  8487.   #----------------------------------------------------------------------------
  8488.   alias setup_blizzabs_later setup
  8489.   def setup(id)
  8490.     # call original method
  8491.     setup_blizzabs_later(id)
  8492.     # skill and item IDs on hotkeys
  8493.     @skill, @item = 0, 0
  8494.     # skills -> skill ID on key index
  8495.     @skill_hotkeys = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  8496.     # items -> item ID on key index
  8497.     @item_hotkeys = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  8498.     # last known level
  8499.     @old_level = @level
  8500.     # normal AI setup attributes
  8501.     @offensive, @aggressive, @force_offensive, @force_aggressive = 8, 8, 0, 0
  8502.     # hash for state time
  8503.     @state_time = {}
  8504.     # trigger AI conditions
  8505.     @triggers = []
  8506.   end
  8507.   #----------------------------------------------------------------------------
  8508.   # force_offensive=
  8509.   #  Encapsulation method that corrects the offensive attribute's value.
  8510.   #----------------------------------------------------------------------------
  8511.   def force_offensive=(val)
  8512.     if val > 15
  8513.       @force_offensive = 15
  8514.     elsif val < 0
  8515.       @force_offensive = 0
  8516.     else
  8517.       @force_offensive = val
  8518.     end
  8519.   end
  8520.   #----------------------------------------------------------------------------
  8521.   # force_aggressive=
  8522.   #  Encapsulation method that corrects the aggressive attribute's value.
  8523.   #----------------------------------------------------------------------------
  8524.   def force_aggressive=(val)
  8525.     if val > 15
  8526.       @force_aggressive = 15
  8527.     elsif val < 0
  8528.       @force_aggressive = 0
  8529.     else
  8530.       @force_aggressive = val
  8531.     end
  8532.   end
  8533.   #----------------------------------------------------------------------------
  8534.   # now_exp
  8535.   #  Returns the current EXP as number.
  8536.   #----------------------------------------------------------------------------
  8537.   def now_exp
  8538.     return (@exp - @exp_list[@level])
  8539.   end
  8540.   #----------------------------------------------------------------------------
  8541.   # next_exp
  8542.   #  Returns the EXP needed to level up or 0 is there are no more levels.
  8543.   #----------------------------------------------------------------------------
  8544.   def next_exp
  8545.     return (@exp_list[@level+1] > 0 ? @exp_list[@level+1]-@exp_list[@level] : 0)
  8546.   end
  8547.   #----------------------------------------------------------------------------
  8548.   # full_next_exp
  8549.   #  Returns the EXP needed to reach the next level.
  8550.   #----------------------------------------------------------------------------
  8551.   def full_next_exp
  8552.     return (@exp_list[@level+1] > 0 ? @exp_list[@level+1] : 0)
  8553.   end
  8554.   #----------------------------------------------------------------------------
  8555.   # level_up?
  8556.   #  Compares current level to lastly known level and returns a level up.
  8557.   #----------------------------------------------------------------------------
  8558.   def level_up?
  8559.     # result of level up and set current level is now last known level
  8560.     result, @old_level = (@old_level < @level), @level
  8561.     # return result
  8562.     return result
  8563.   end
  8564.  
  8565. end
  8566.  
  8567. #==============================================================================
  8568. # Game_Enemy
  8569. #------------------------------------------------------------------------------
  8570. #  This class was enhanced with helping variables.
  8571. #==============================================================================
  8572.  
  8573. class Game_Enemy
  8574.  
  8575.   # setting all accessible variables
  8576.   attr_writer :enemy_id
  8577.   #----------------------------------------------------------------------------
  8578.   # Override Initialization
  8579.   #  enemy - enemy in the database
  8580.   #----------------------------------------------------------------------------
  8581.   alias init_blizzabs_later initialize
  8582.   def initialize(enemy, other = nil)
  8583.     # if Blizz-ABS enemy initialization
  8584.     if other == nil
  8585.       # call superclass method
  8586.       super()
  8587.       # the enemy ID, no troop and not member in troop
  8588.       @enemy_id, @troop_id, @member_index = enemy.id, 0, 0
  8589.       # battler spriteset name and spriteset hue
  8590.       @battler_name, @battler_hue = enemy.battler_name, enemy.battler_hue
  8591.       # current HP and SP
  8592.       @hp, @sp = maxhp, maxsp
  8593.       # not hidden and not immortal
  8594.       @hidden = @immortal = false
  8595.     else
  8596.       # call normal enemy initialization
  8597.       init_blizzabs_later(enemy, other)
  8598.     end
  8599.     # hash for state time
  8600.     @state_time = {}
  8601.   end
  8602.  
  8603. end
  8604.  
  8605. #==============================================================================
  8606. # Game_Map
  8607. #------------------------------------------------------------------------------
  8608. #  This class was redefined by large parts for pixel movement handling and
  8609. #  quick minimap passability access.
  8610. #==============================================================================
  8611.  
  8612. class Game_Map
  8613.  
  8614.   # setting all accessible variables
  8615.   attr_reader :virtual_passability
  8616.   attr_reader :map
  8617.   attr_reader :respawns
  8618.   #----------------------------------------------------------------------------
  8619.   # override setup
  8620.   #----------------------------------------------------------------------------
  8621.   alias setup_blizzabs_later setup
  8622.   def setup(map_id)
  8623.     # array of Respawn Points
  8624.     @respawns = []
  8625.     # call original method
  8626.     setup_blizzabs_later(map_id)
  8627.     # setup enemies on the map
  8628.     $BlizzABS.battlers_refresh
  8629.     # if using the intelligent minimap system
  8630.     if BlizzABS::Config::INTELLIGENT_PASSABILITY
  8631.       # load virtual passability map from file
  8632.       @virtual_passability = load_data('Data/Map_Data.abs')[0][map_id]
  8633.     else
  8634.       # create virtual passability map
  8635.       @virtual_passability = $BlizzABS.util.setup_passability(@map)
  8636.     end
  8637.     # reset remotes, damage and beam sprites and clear observation data
  8638.     $BlizzABS.cache.clean
  8639.   end
  8640.   #----------------------------------------------------------------------------
  8641.   # events_only
  8642.   #  Returns an array of events that have no battler.
  8643.   #----------------------------------------------------------------------------
  8644.   def events_only
  8645.     return (@events.values - self.battlers)
  8646.   end
  8647.   #----------------------------------------------------------------------------
  8648.   # battlers
  8649.   #  Returns an array of all map battlers.
  8650.   #----------------------------------------------------------------------------
  8651.   def battlers
  8652.     return (@events.values.find_all {|e| e.is_a?(Map_Battler)})
  8653.   end
  8654.   #----------------------------------------------------------------------------
  8655.   # battlers_group
  8656.   #  group - alignment group of the battler
  8657.   #  Returns an array of map battlers from a specific alignment group.
  8658.   #----------------------------------------------------------------------------
  8659.   def battlers_group(group)
  8660.     return (battlers.find_all {|battler| battler.ai.group == group})
  8661.   end
  8662.   #----------------------------------------------------------------------------
  8663.   # battlers_in_range
  8664.   #  Checks how many battler instances are within ABSEAL range.
  8665.   #----------------------------------------------------------------------------
  8666.   def battlers_in_range
  8667.     return (battlers.find_all {|battler| battler.valid? && battler.update?})
  8668.   end
  8669.   #----------------------------------------------------------------------------
  8670.   # rename_event
  8671.   #  id   - event ID
  8672.   #  name - new name for the event
  8673.   #  Allows the renaming of specific events and applies Blizz-ABS update
  8674.   #  handling.
  8675.   #----------------------------------------------------------------------------
  8676.   def rename_event(id, name)
  8677.     # stop if event doesn't exist
  8678.     return if @events[id] == nil
  8679.     # set new name
  8680.     self.map.events[id].name = name
  8681.     # store old event
  8682.     character = @events[id]
  8683.     # update event by using name
  8684.     $BlizzABS.check_event_name(id)
  8685.     # clone position of the old character
  8686.     @events[id].clone_position(character)
  8687.     # stop if scene not Scene_Map or spriteset doesn't exist
  8688.     return if !$scene.is_a?(Scene_Map) || $scene.spriteset == nil
  8689.     # find this event's sprite
  8690.     $scene.spriteset.character_sprites.each {|sprite|
  8691.         # if sprite found
  8692.         if sprite.character == character
  8693.           # dispose old sprites
  8694.           sprite.dispose
  8695.           # set new character
  8696.           sprite.character = @events[id]
  8697.           # update sprite
  8698.           sprite.update
  8699.           # event found, stop here
  8700.           break
  8701.         end}
  8702.   end
  8703.   #----------------------------------------------------------------------------
  8704.   # self_valid?
  8705.   #  x - x-coordinate
  8706.   #  y - y-coordinate
  8707.   #  Checks if coordinates are valid. (pixel movement)
  8708.   #----------------------------------------------------------------------------
  8709.   def self_valid?(x, y)
  8710.     # get pixel movement rate
  8711.     pix = $BlizzABS.pixel
  8712.     # checks if coordinates are valid
  8713.     return (x >= 0 && x < width * pix - pix + 1 && y >= 0 && y < height * pix - pix + 1)
  8714.   end
  8715.   #----------------------------------------------------------------------------
  8716.   # direction_valid?
  8717.   #  x - x-coordinate
  8718.   #  y - y-coordinate
  8719.   #  Checks if coordinates are valid. (pixel movement)
  8720.   #----------------------------------------------------------------------------
  8721.   def direction_valid?(x, y)
  8722.     # get pixel movement rate
  8723.     pix = $BlizzABS.pixel
  8724.     # checks if coordinates are valid
  8725.     return (x >= 0 && x < width * pix && y >= 0 && y < height * pix)
  8726.   end
  8727.   #----------------------------------------------------------------------------
  8728.   # self_passable?
  8729.   #  x          - x-coordinate
  8730.   #  y          - y-coordinate
  8731.   #  d          - direction
  8732.   #  self_event - self event
  8733.   #  Checks if passable. (pixel movement)
  8734.   #----------------------------------------------------------------------------
  8735.   def self_passable?(x, y, d, self_event)
  8736.     # get pixel movement rate and set bit
  8737.     pix, bit = $BlizzABS.pixel, (1 << (d / 2 - 1)) & 0x0F
  8738.     # if not in horizontal center of 32x32 pixel tile
  8739.     if x != x / pix * pix
  8740.       # if current two tiles are impassable from one to another
  8741.       unless direction_passable?(x / pix * pix, y, 6) &&
  8742.           direction_passable?((x + pix) / pix * pix, y, 4)
  8743.         # impassable
  8744.         return false
  8745.       end
  8746.     end
  8747.     # if not in vertical center of 32x32 pixel tile
  8748.     if y != y / pix * pix
  8749.       # if current two tiles are impassable from one to another
  8750.       unless direction_passable?(x, y / pix * pix, 2) &&
  8751.           direction_passable?(x, (y + pix) / pix * pix, 8)
  8752.         # impassable
  8753.         return false
  8754.       end
  8755.     end
  8756.     # if jumping
  8757.     if d == 0
  8758.       # return passability on forced jump location or in any direction
  8759.       return (BlizzABS::Config::ALLOW_JUMP_TAGS.include?(
  8760.           $game_map.terrain_tag(x / pix, y / pix)) ||
  8761.           direction_passable?(x, y + pix - 1, 2) ||
  8762.           direction_passable?(x, y, 4) ||
  8763.           direction_passable?(x + pix - 1, y, 6) ||
  8764.           direction_passable?(x, y, 8))
  8765.     end
  8766.     # if changing tile and either no tile or no event exception
  8767.     if changing_tiles(x, y, d) && (!tile_exception(x, y, d) ||
  8768.         !event_exception(x, y, d, bit))
  8769.       # impassable
  8770.       return false
  8771.     end
  8772.     # iterate through all corners
  8773.     (0...4).each {|i|
  8774.         # gets coordinates to check
  8775.         xr, yr = x + (pix - 1) * (i % 2), y + (pix - 1) * (i / 2)
  8776.         # unless checking event and checking tile
  8777.         unless event_check(xr, yr, d, self_event) && tile_check(xr, yr, d)
  8778.           # impassable
  8779.           return false
  8780.         end}
  8781.     # passable
  8782.     return true
  8783.   end
  8784.   #----------------------------------------------------------------------------
  8785.   # direction_passable?
  8786.   #  x          - x-coordinate
  8787.   #  y          - y-coordinate
  8788.   #  d          - direction
  8789.   #  self_event - self event
  8790.   #  Checks if passable. (pixel movement)
  8791.   #----------------------------------------------------------------------------
  8792.   def direction_passable?(x, y, d)
  8793.     # impassable if coordinates not valid
  8794.     return false unless direction_valid?(x, y)
  8795.     # return event check and tile check result
  8796.     return (event_check(x, y, d) && tile_check(x, y, d))
  8797.   end
  8798.   #----------------------------------------------------------------------------
  8799.   # event_check
  8800.   #  x          - x-coordinate
  8801.   #  y          - y-coordinate
  8802.   #  d          - direction
  8803.   #  self_event - self event
  8804.   #  Checks if passable events. (pixel movement)
  8805.   #----------------------------------------------------------------------------
  8806.   def event_check(x, y, d, self_event = nil)
  8807.     # get pixel movement rate and set bit
  8808.     pix, bit = $BlizzABS.pixel, (1 << (d / 2 - 1)) & 0x0F
  8809.     # iterate trough all events except self
  8810.     (self.events_only - [self_event]).each {|event|
  8811.         # if there's an event that's not through and has a graphic
  8812.         if (event.character_name != "" || event.tile_id != 0) &&
  8813.            $BlizzABS.util.intersection(Rect.new(x, y,
  8814.            1, 1), event.phitbox) && !event.through &&
  8815.            (!self_event.is_a?(Map_Battler) || event.tile_id >= 384)
  8816.           # if obstacle bit is set
  8817.           if @passages[event.tile_id] & bit != 0
  8818.             # get x and y of next tile
  8819.             case d
  8820.             when 2 then nx, ny = x / pix, (y + 1) / pix
  8821.             when 4 then nx, ny = (x - 1) / pix, y / pix
  8822.             when 6 then nx, ny = (x + 1) / pix, y / pix
  8823.             when 8 then nx, ny = x / pix, (y - 1) / pix
  8824.             else
  8825.               nx = ny = nil
  8826.             end
  8827.             # impassable if not on the same tile anymore
  8828.             return false if x / pix != nx || y / pix != ny
  8829.           # if obstacle bit is set in all directions
  8830.           elsif @passages[event.tile_id] & 0x0F == 0x0F
  8831.             # impassable in the given direction
  8832.             return false
  8833.           # if priority is 0
  8834.           elsif @priorities[event.tile_id] == 0
  8835.             # passable in the given direction
  8836.             return true
  8837.           # if event is not a tile and not through
  8838.           elsif !event.through
  8839.             # impassable in any direction
  8840.             return false
  8841.           end
  8842.         end}
  8843.     # passable
  8844.     return true
  8845.   end
  8846.   #----------------------------------------------------------------------------
  8847.   # tile_check
  8848.   #  x - x-coordinate
  8849.   #  y - y-coordinate
  8850.   #  d - direction
  8851.   #  Checks if passable tile. (pixel movement)
  8852.   #----------------------------------------------------------------------------
  8853.   def tile_check(x, y, d)
  8854.     # get pixel movement rate and set bit
  8855.     pix, bit = $BlizzABS.pixel, (1 << (d / 2 - 1)) & 0x0F
  8856.     # passable if virtual passability works
  8857.     return true if ($game_map.virtual_passability[x / pix, y / pix] & bit != 0x00)
  8858.     # get x and y of next tile
  8859.     case d
  8860.     when 2 then nx, ny = x / pix, (y + 1) / pix
  8861.     when 4 then nx, ny = (x - 1) / pix, y / pix
  8862.     when 6 then nx, ny = (x + 1) / pix, y / pix
  8863.     when 8 then nx, ny = x / pix, (y - 1) / pix
  8864.     else
  8865.       nx = ny = nil
  8866.     end
  8867.     # passable if still on the same tile
  8868.     return (x / pix == nx && y / pix == ny)
  8869.   end
  8870.   #----------------------------------------------------------------------------
  8871.   # event_exception
  8872.   #  x          - x-coordinate
  8873.   #  y          - y-coordinate
  8874.   #  d          - direction
  8875.   #  bit        - passability attributes
  8876.   #  Checks if passable events. (pixel movement)
  8877.   #----------------------------------------------------------------------------
  8878.   def event_exception(x, y, d, bit)
  8879.     # get pixel movement rate
  8880.     pix = $BlizzABS.pixel
  8881.     # iterate trough all events
  8882.     self.events_only.each {|event|
  8883.         # if there's an event that's a tile and not through
  8884.         if !event.through && event.tile_id >= 384
  8885.           # get data depending on direction
  8886.           case d
  8887.           when 2
  8888.             x1, y1, bit1 = x / pix, (y + pix) / pix, 0x04
  8889.             x2, y2, bit2 = (x + pix) / pix, y1, 0x02
  8890.           when 4
  8891.             x1, y1, bit1 = (x - pix) / pix, y / pix, 0x01
  8892.             x2, y2, bit2 = x1, (y + pix) / pix, 0x08
  8893.           when 6
  8894.             x1, y1, bit1 = (x + pix) / pix, y / pix, 0x01
  8895.             x2, y2, bit2 = x1, (y + pix) / pix, 0x08
  8896.           when 8
  8897.             x1, y1, bit1 = x / pix, (y - pix) / pix, 0x04
  8898.             x2, y2, bit2 = (x + pix) / pix, y1, 0x02
  8899.           end
  8900.           # temporary variable
  8901.           passage = @passages[event.tile_id]
  8902.           # if tile is at right position and impassable
  8903.           if event.x == x1 && event.y == y1 && passage & bit1 == bit1 ||
  8904.               event.x == x2 && event.y == y2 && passage & bit2 == bit2
  8905.             # impassable
  8906.             return false
  8907.           end
  8908.         end}
  8909.     # passable
  8910.     return true
  8911.   end
  8912.   #----------------------------------------------------------------------------
  8913.   # tile_exception
  8914.   #  x       - x-coordinate
  8915.   #  y       - y-coordinate
  8916.   #  d       - direction
  8917.   #  Checks if passable when changing tiles. (pixel movement)
  8918.   #----------------------------------------------------------------------------
  8919.   def tile_exception(x, y, d)
  8920.     # get pixel movement rate
  8921.     pix = $BlizzABS.pixel
  8922.     # check direction and return map passability depending on direction
  8923.     return case d
  8924.     when 2
  8925.       (($game_map.virtual_passability[x / pix, (y + pix) / pix] & 0x04 == 0x04) &&
  8926.       ($game_map.virtual_passability[(x + pix) / pix, (y + pix) / pix] & 0x02 == 0x02))
  8927.     when 4
  8928.       (($game_map.virtual_passability[(x - pix) / pix, y / pix] & 0x01 == 0x01) &&
  8929.       ($game_map.virtual_passability[(x - pix) / pix, (y + pix) / pix] & 0x08 == 0x08))
  8930.     when 6
  8931.       (($game_map.virtual_passability[(x + pix) / pix, y / pix] & 0x01 == 0x01) &&
  8932.       ($game_map.virtual_passability[(x + pix) / pix, (y + pix) / pix] & 0x08 == 0x08))
  8933.     when 8
  8934.       (($game_map.virtual_passability[x / pix, (y - pix) / pix] & 0x04 == 0x04) &&
  8935.       ($game_map.virtual_passability[(x + pix) / pix, (y - pix) / pix] & 0x02 == 0x02))
  8936.     end
  8937.   end
  8938.   #----------------------------------------------------------------------------
  8939.   # changing_tiles
  8940.   #  x       - x-coordinate
  8941.   #  y       - y-coordinate
  8942.   #  d       - direction
  8943.   #  Checks if changing tiles. (pixel movement)
  8944.   #----------------------------------------------------------------------------
  8945.   def changing_tiles(x, y, d)
  8946.     # get pixel movement rate
  8947.     pix = $BlizzABS.pixel
  8948.     # if not changing the tile (up/down)
  8949.     if (y / pix != (y + pix - 1) / pix || x / pix == (x + pix - 1) / pix) &&
  8950.         (d == 2 || d == 8)
  8951.       # not changing
  8952.       return false
  8953.     end
  8954.     # if not changing the tile (left/right)
  8955.     if (x / pix != (x + pix - 1) / pix || y / pix == (y + pix - 1) / pix) &&
  8956.         (d == 4 || d == 6)
  8957.       # not changing
  8958.       return false
  8959.     end
  8960.     # changing
  8961.     return true
  8962.   end
  8963.   #----------------------------------------------------------------------------
  8964.   # pixel_counter?
  8965.   #  x - x-coordinate
  8966.   #  y - y-coordinate
  8967.   #  Checks if counter. (pixel movement)
  8968.   #----------------------------------------------------------------------------
  8969.   def pixel_counter?(x, y)
  8970.     # no counter if map ID is invalid
  8971.     return false if @map_id == 0
  8972.     # get pixel movement rate and initialize result
  8973.     pix, result = $BlizzABS.pixel, false
  8974.     # iterate through all layers and check each modified tile (pixel movement)
  8975.     BlizzABS::Cache::MapLayers.each {|i| (0...pix).each {|j| (0...pix).each {|k|
  8976.               # if tile is not valid ID
  8977.               if data[(x+j)/pix, (y+k)/pix, i] == nil
  8978.                 # no counter
  8979.                 return false
  8980.               # if counter bit is set
  8981.               elsif @passages[data[(x+j)/pix, (y+k)/pix, i]] & 0x80 == 0x80
  8982.                 # counter
  8983.                 result = true
  8984.               else
  8985.                 # no counter
  8986.                 return false
  8987.               end}}
  8988.           # return the result
  8989.           return result}
  8990.     # no counter
  8991.     return false
  8992.   end
  8993.   #----------------------------------------------------------------------------
  8994.   # pixel_bush?
  8995.   #  x - x-coordinate
  8996.   #  y - y-coordinate
  8997.   #  Checks if bush. (pixel movement)
  8998.   #----------------------------------------------------------------------------
  8999.   def pixel_bush?(x, y)
  9000.     # no bush if map ID is invalid
  9001.     return false if @map_id == 0
  9002.     # get pixel movement rate
  9003.     pix = $BlizzABS.pixel
  9004.     # iterate through all layers
  9005.     BlizzABS::Cache::MapLayers.each {|i|
  9006.         # if tile ID not valid
  9007.         if data[(x+pix/2)/pix, (y+pix/2)/pix, i] == nil
  9008.           # no bush
  9009.           return false
  9010.         # if bush bit is set
  9011.         elsif @passages[data[(x+pix/2)/pix, (y+pix/2)/pix, i]] & 0x40 == 0x40
  9012.           # bush
  9013.           return true
  9014.         end}
  9015.     # no bush
  9016.     return false
  9017.   end
  9018.   #----------------------------------------------------------------------------
  9019.   # jump_passable?
  9020.   #  x  - x-coordinate
  9021.   #  y  - y-coordinate
  9022.   #  nx - new x-coordinate
  9023.   #  ny - new y-coordinate
  9024.   #  Checks if there is a tile with NO_JUMP_TAGS or WALL_TAGS tag, so jumping
  9025.   #  isn't possible.
  9026.   #----------------------------------------------------------------------------
  9027.   def jump_passable?(x, y, nx, ny)
  9028.     # passable if tags are not being used at all (to save process time)
  9029.     return true if BlizzABS::Config::NO_JUMP_TAGS.size == 0
  9030.     # get pixel movement rate
  9031.     pix = $BlizzABS.pixel
  9032.     # get jump direction
  9033.     xdir, ydir = (nx - x).sgn, (ny - y).sgn
  9034.     # iterate
  9035.     loop do
  9036.       # if tile has one of the terrain tags or event that can't be jumped
  9037.       if !event_jump_passable?(x, y) ||
  9038.          BlizzABS::Config::NO_JUMP_TAGS.include?(terrain_tag(x / pix, y / pix))
  9039.         # impassable
  9040.         return false
  9041.       # if all tiles are passable
  9042.       elsif x == nx && y == ny
  9043.       # passable
  9044.         return true
  9045.       end
  9046.       # next tile
  9047.       x += xdir * pix
  9048.       y += ydir * pix
  9049.     end
  9050.   end
  9051.   #----------------------------------------------------------------------------
  9052.   # event_passable?
  9053.   #  x - x-coordinate
  9054.   #  y - y-coordinate
  9055.   #  Checks if the given tile is passable in any direction right now.
  9056.   #----------------------------------------------------------------------------
  9057.   def event_passable?(x, y)
  9058.     # get pixel movement rate
  9059.     pix = $BlizzABS.pixel
  9060.     # iterate trough all events
  9061.     self.events_only.each {|event|
  9062.         # if there's an event that's no enemy/actor/dropped item and not through
  9063.         if event.tile_id >= 0 && event.x == x / pix && event.y == y / pix &&
  9064.             !event.through
  9065.           # if obstacle bit is set
  9066.           if @passages[event.tile_id] & 0x0F == 0x0F
  9067.             # impassable tile in the given direction
  9068.             return false
  9069.           # if priority is 0
  9070.           elsif @priorities[event.tile_id] == 0
  9071.             # passable in the given direction
  9072.             return true
  9073.           end
  9074.         end}
  9075.     # passable
  9076.     return true
  9077.   end
  9078.   #----------------------------------------------------------------------------
  9079.   # event_jump_passable?
  9080.   #  x - x-coordinate
  9081.   #  y - y-coordinate
  9082.   #  Checks if the given tile is passable by jumping due to events.
  9083.   #----------------------------------------------------------------------------
  9084.   def event_jump_passable?(x, y)
  9085.     # get pixel movement rate
  9086.     pix = $BlizzABS.pixel
  9087.     # iterate trough all events
  9088.     self.events_only.each {|event|
  9089.         # if there's an event that is not enemy/actor/dropped and not jumpable
  9090.         if event.tile_id >= 0 && $BlizzABS.util.intersection(Rect.new(x, y,
  9091.           1, 1), event.phitbox) && event.no_jump
  9092.           return false
  9093.         end}
  9094.     # iterate through battlers
  9095.     self.battlers.each {|battler|
  9096.         # if there's a battler that is not jumpable
  9097.         if $BlizzABS.util.intersection(Rect.new(x, y, 1, 1),
  9098.           battler.phitbox) && battler.no_jump
  9099.           return false
  9100.         end}
  9101.     # passable
  9102.     return true
  9103.   end
  9104.  
  9105. end
  9106.  
  9107. #==============================================================================
  9108. # Game_Party
  9109. #------------------------------------------------------------------------------
  9110. #  This class was redefined to create characters used by the caterpillar and to
  9111. #  delete all remotes when a saved game was loaded.
  9112. #==============================================================================
  9113.  
  9114. class Game_Party
  9115.  
  9116.   #----------------------------------------------------------------------------
  9117.   # override setup_starting_members
  9118.   #----------------------------------------------------------------------------
  9119.   alias setup_starting_members_blizzabs_later setup_starting_members
  9120.   def setup_starting_members
  9121.     # call original method
  9122.     setup_starting_members_blizzabs_later
  9123.     # initialize caterpillar
  9124.     $BlizzABS.init_caterpillar
  9125.   end
  9126.   #----------------------------------------------------------------------------
  9127.   # override refresh
  9128.   #----------------------------------------------------------------------------
  9129.   alias refresh_blizzabs_later refresh
  9130.   def refresh
  9131.     # call original method
  9132.     refresh_blizzabs_later
  9133.     # reset remotes and damage sprites
  9134.     $BlizzABS.cache.clean
  9135.     # reinitialize caterpillar
  9136.     $BlizzABS.init_caterpillar
  9137.   end
  9138.  
  9139. end
  9140.  
  9141. #==============================================================================
  9142. # Game_Character
  9143. #------------------------------------------------------------------------------
  9144. #  This class was redefined to support name event command input, looping
  9145. #  animations, ABSEAL update limitation and relational movement commands.
  9146. #==============================================================================
  9147.  
  9148. class Game_Character
  9149.  
  9150.   # constants to help the user
  9151.   PARTY    = BlizzABS::PARTY
  9152.   TROOP    = BlizzABS::TROOP
  9153.   INCREASE = BlizzABS::INCREASE
  9154.   DECREASE = BlizzABS::DECREASE
  9155.   CONSTANT = BlizzABS::CONSTANT
  9156.   VARIABLE = BlizzABS::VARIABLE
  9157.   KILL     = BlizzABS::KILL
  9158.   NO_KILL  = BlizzABS::NO_KILL
  9159.   ADD      = BlizzABS::ADD
  9160.   REMOVE   = BlizzABS::REMOVE
  9161.   ATTACK   = BlizzABS::ATTACK
  9162.   DEFEND   = BlizzABS::DEFEND
  9163.   ESCAPE   = BlizzABS::ESCAPE
  9164.   SKILL    = BlizzABS::SKILL
  9165.   ITEM     = BlizzABS::ITEM
  9166.   ENEMIES  = BlizzABS::ENEMIES
  9167.   ACTORS   = BlizzABS::ACTORS
  9168.   NONE     = BlizzABS::NONE
  9169.   # setting all accessible variables
  9170.   attr_accessor :erased
  9171.   attr_accessor :loop_animation_id
  9172.   attr_accessor :terminate
  9173.   attr_accessor :teleport
  9174.   attr_accessor :icondrop
  9175.   attr_accessor :no_jump
  9176.   attr_accessor :center_sprite
  9177.   attr_accessor :hitbox_width
  9178.   attr_accessor :hitbox_height
  9179.   attr_accessor :no_dmg_sprites
  9180.   attr_reader   :move_route
  9181.   attr_reader   :move_type
  9182.   attr_reader   :pattern_size
  9183.   #----------------------------------------------------------------------------
  9184.   # override initialize
  9185.   #----------------------------------------------------------------------------
  9186.   alias init_blizzabs_later initialize
  9187.   def initialize
  9188.     # call original method
  9189.     init_blizzabs_later
  9190.     # set loop animation
  9191.     @loop_animation_id = 0
  9192.     # default number of frames on a spriteset
  9193.     @pattern_size = 4
  9194.     # last moving flag
  9195.     @last_moving = false
  9196.     # no jump flag
  9197.     @no_jump = false
  9198.     # center sprite flag
  9199.     @center_sprite = false
  9200.     # hitbox size
  9201.     @hitbox_width = @hitbox_height = 32
  9202.     # no damage sprites
  9203.     @no_dmg_sprites = false
  9204.   end
  9205.   #----------------------------------------------------------------------------
  9206.   # update?
  9207.   #  Checks whether the character should be updated or not.
  9208.   #----------------------------------------------------------------------------
  9209.   def update?
  9210.     # if this map has ABSEAL disabled or it's the player or an actor
  9211.     if BlizzABS::Config::DISABLE_ANTILAG_IDS.include?($game_map.map_id)
  9212.       # update
  9213.       return true
  9214.     end
  9215.     # if auto-start or parallel process or excluded from ABSEAL
  9216.     if @trigger == 3 || @trigger == 4 || self.name.clone.gsub!('\\eal') {''}
  9217.       # update
  9218.       return true
  9219.     end
  9220.     # if autokiller is on and no character sprite and no tile sprite
  9221.     if BlizzABS::Config::ABSEAL_AUTOKILL && @character_name == '' &&
  9222.         @tile_id < 384 && !@teleport && !@move_route_forcing
  9223.       # don't update
  9224.       return false
  9225.     end
  9226.     # check ABSEAL range
  9227.     return in_abseal_range?
  9228.   end
  9229.   #----------------------------------------------------------------------------
  9230.   # in_abseal_range?
  9231.   #  Checks if the character is within ABSEAL range.
  9232.   #----------------------------------------------------------------------------
  9233.   def in_abseal_range?
  9234.     # correct value out of range for ABSEAL factor
  9235.     factor = BlizzABS::Config::ABSEAL_FACTOR < 1 ? 1 :
  9236.         BlizzABS::Config::ABSEAL_FACTOR.to_i
  9237.     # don't update if outside of screen (left, up, right, down)
  9238.     return false if @real_x < $game_map.display_x - factor * 128
  9239.     return false if @real_y < $game_map.display_y - factor * 128
  9240.     return false if @real_x >= $game_map.display_x + 2560 + factor * 128
  9241.     return false if @real_y >= $game_map.display_y + 1920 + factor * 128
  9242.     # update
  9243.     return true
  9244.   end
  9245.   #----------------------------------------------------------------------------
  9246.   # clone_position
  9247.   #  character - the other character
  9248.   #  Sets own position to that of the other character with correction of pixel
  9249.   #  movement.
  9250.   #----------------------------------------------------------------------------
  9251.   def clone_position(character)
  9252.     # copy real_x and real_y
  9253.     @real_x, @real_y = character.real_x, character.real_y
  9254.     # get pixel movement rate
  9255.     pix = $BlizzABS.pixel
  9256.     # if battler and not battler before
  9257.     if self.is_a?(Map_Battler) && !character.is_a?(Map_Battler)
  9258.       # copy coordinates with correction
  9259.       @x, @y = character.x * pix, character.y * pix
  9260.     # if not battler and battler before
  9261.     elsif !self.is_a?(Map_Battler) && character.is_a?(Map_Battler)
  9262.       # copy coordinates with correction
  9263.       @x, @y = character.x / pix, character.y / pix
  9264.     else
  9265.       # just copy coordinates
  9266.       @x, @y = character.x, character.y
  9267.     end
  9268.   end
  9269.   #----------------------------------------------------------------------------
  9270.   # name
  9271.   #  Returns the event's name if the is one.
  9272.   #----------------------------------------------------------------------------
  9273.   def name
  9274.     return (@event != nil ? @event.name : '')
  9275.   end
  9276.   #----------------------------------------------------------------------------
  9277.   # move_toward_player
  9278.   #  Rerouting method.
  9279.   #----------------------------------------------------------------------------
  9280.   def move_toward_player
  9281.     move_toward($game_player)
  9282.   end
  9283.   #----------------------------------------------------------------------------
  9284.   # move_away_from_player
  9285.   #  Rerouting method.
  9286.   #----------------------------------------------------------------------------
  9287.   def move_away_from_player
  9288.     move_away_from($game_player)
  9289.   end
  9290.   #----------------------------------------------------------------------------
  9291.   # turn_toward_player
  9292.   #  Rerouting method.
  9293.   #----------------------------------------------------------------------------
  9294.   def turn_toward_player
  9295.     turn_toward($game_player)
  9296.   end
  9297.   #----------------------------------------------------------------------------
  9298.   # turn_away_from_player
  9299.   #  Rerouting method.
  9300.   #----------------------------------------------------------------------------
  9301.   def turn_away_from_player
  9302.     turn_away_from($game_player)
  9303.   end
  9304.   #----------------------------------------------------------------------------
  9305.   # move_toward
  9306.   #  character - the character
  9307.   #  Moves towards a character. (pixel movement)
  9308.   #----------------------------------------------------------------------------
  9309.   def move_toward(character)
  9310.     # calculate differences in x and y
  9311.     dx, dy = @real_x - character.real_x, @real_y - character.real_y
  9312.     # determines where to move according to the x and y differences
  9313.     if dx > 0 && dy > 0 # player is up left
  9314.       move_upper_left
  9315.     elsif dx > 0 && dy < 0 # player is down left
  9316.       move_lower_left
  9317.     elsif dx < 0 && dy > 0 # player is up right
  9318.       move_upper_right
  9319.     elsif dx < 0 && dy < 0 # player is down right
  9320.       move_lower_right
  9321.     elsif dx < 0 && dy == 0 # player is right
  9322.       move_right
  9323.     elsif dx > 0 && dy == 0 # player is left
  9324.       move_left
  9325.     elsif dx == 0 && dy < 0 # player is down
  9326.       move_down
  9327.     elsif dx == 0 && dy > 0 # player is up
  9328.       move_up
  9329.     end
  9330.   end
  9331.   #----------------------------------------------------------------------------
  9332.   # move_away_from
  9333.   #  character - the character
  9334.   #  Moves away from a character. (pixel movement)
  9335.   #----------------------------------------------------------------------------
  9336.   def move_away_from(character)
  9337.     # calculate differences in x and y
  9338.     dx, dy = @real_x - character.real_x, @real_y - character.real_y
  9339.     # determines where to move according to the x and y differences
  9340.     if dx > 0 && dy > 0 # character is up left
  9341.       move_lower_right
  9342.     elsif dx > 0 && dy < 0 # character is down left
  9343.       move_upper_right
  9344.     elsif dx < 0 && dy > 0 # character is up right
  9345.       move_lower_left
  9346.     elsif dx < 0 && dy < 0 # character is down right
  9347.       move_upper_left
  9348.     elsif dx < 0 && dy == 0 # character is right
  9349.       move_left
  9350.     elsif dx > 0 && dy == 0 # character is left
  9351.       move_right
  9352.     elsif dx == 0 && dy < 0 # character is down
  9353.       move_up
  9354.     elsif dx == 0 && dy > 0 # character is up
  9355.       move_down
  9356.     end
  9357.   end
  9358.   #----------------------------------------------------------------------------
  9359.   # move_away_random
  9360.   #  character    - the character
  9361.   #  turn_enabled - determines whether the character should turn as well
  9362.   #  distance     - distance
  9363.   #  Moves away from a character randomly. (pixel movement)
  9364.   #----------------------------------------------------------------------------
  9365.   def move_away_random(character, turn_enabled = true, distance = 1)
  9366.     # calculate differences in x and y
  9367.     dx, dy = @real_x - character.real_x, @real_y - character.real_y
  9368.     # array of directions
  9369.     dirs = ($game_system._8_way ? [1, 2, 3, 4, 6, 7, 8, 9] : [2, 4, 6, 8])
  9370.     # determines where can't move according to the x and y differences
  9371.     if dx > 0 && dy > 0 # character is up left
  9372.       dirs -= [4, 7, 8]
  9373.     elsif dx > 0 && dy < 0 # character is down left
  9374.       dirs -= [1, 2, 4]
  9375.     elsif dx < 0 && dy > 0 # character is up right
  9376.       dirs -= [6, 8, 9]
  9377.     elsif dx < 0 && dy < 0 # character is down right
  9378.       dirs -= [2, 3, 6]
  9379.     elsif dx < 0 && dy == 0 # character is right
  9380.       dirs -= [3, 6, 9]
  9381.     elsif dx > 0 && dy == 0 # character is left
  9382.       dirs -= [1, 4, 7]
  9383.     elsif dx == 0 && dy < 0 # character is down
  9384.       dirs -= [1, 2, 3]
  9385.     elsif dx == 0 && dy > 0 # character is up
  9386.       dirs -= [7, 8, 9]
  9387.     end
  9388.     # choose a random direction from available directions
  9389.     return case dirs[rand(dirs.size)]
  9390.     when 1 then distance.to_i.times {move_lower_left}
  9391.     when 2 then distance.to_i.times {move_down(turn_enabled)}
  9392.     when 3 then distance.to_i.times {move_lower_right}
  9393.     when 4 then distance.to_i.times {move_left(turn_enabled)}
  9394.     when 6 then distance.to_i.times {move_right(turn_enabled)}
  9395.     when 7 then distance.to_i.times {move_upper_left}
  9396.     when 8 then distance.to_i.times {move_up(turn_enabled)}
  9397.     when 9 then distance.to_i.times {move_upper_right}
  9398.     end
  9399.   end
  9400.   #----------------------------------------------------------------------------
  9401.   # turn_toward
  9402.   #  character - the character
  9403.   #  Turn towards a character. (pixel movement)
  9404.   #----------------------------------------------------------------------------
  9405.   def turn_toward(character)
  9406.     # calculate differences in x and y
  9407.     dx, dy = @real_x - character.real_x, @real_y - character.real_y
  9408.     # determines where to turn according to the x and y differences
  9409.     if dx < 0 && dx.abs >= dy.abs # character is right
  9410.       turn_right
  9411.     elsif dx > 0 && dx.abs >= dy.abs # character is left
  9412.       turn_left
  9413.     elsif dy < 0 # character is down
  9414.       turn_down
  9415.     elsif dy > 0 # character is up
  9416.       turn_up
  9417.     end
  9418.   end
  9419.   #----------------------------------------------------------------------------
  9420.   # turn_away_from
  9421.   #  character - the character
  9422.   #  Turn away from a character. (pixel movement)
  9423.   #----------------------------------------------------------------------------
  9424.   def turn_away_from(character)
  9425.     # calculate differences in x and y
  9426.     dx, dy = @real_x - character.real_x, @real_y - character.real_y
  9427.     # determines where to turn according to the x and y differences
  9428.     if dx < 0 && dx.abs >= dy.abs # character is right
  9429.       turn_left
  9430.     elsif dx > 0 && dx.abs >= dy.abs # character is left
  9431.       turn_right
  9432.     elsif dy < 0 # character is down
  9433.       turn_up
  9434.     elsif dy > 0 # character is up
  9435.       turn_down
  9436.     end
  9437.   end
  9438.   #----------------------------------------------------------------------------
  9439.   # dropped?
  9440.   #  Checks if the character is a dropped event.
  9441.   #----------------------------------------------------------------------------
  9442.   def dropped?
  9443.     return (@terminate_count != nil)
  9444.   end
  9445.   #----------------------------------------------------------------------------
  9446.   # hitbox
  9447.   #  returns a rectangle representing the hitbox in real coordinates.
  9448.   #----------------------------------------------------------------------------
  9449.   def hitbox
  9450.     x = @real_x / 4 + 16 - @hitbox_width / 2
  9451.     cy = (@center_sprite ? 16 - @hitbox_height / 2 : 32 - @hitbox_height)
  9452.     y = @real_y / 4 + cy
  9453.     return Rect.new(x, y, @hitbox_width, @hitbox_height)
  9454.   end
  9455.   #----------------------------------------------------------------------------
  9456.   # phitbox
  9457.   #  returns a rectangle representing the hitbox in pixel coordinates.
  9458.   #----------------------------------------------------------------------------
  9459.   def phitbox
  9460.     pscale = $BlizzABS.pixel / 32.0
  9461.     sx = (self.is_a?(Map_Battler) ? self.x : self.x * $BlizzABS.pixel)
  9462.     x = sx + (32 - @hitbox_width) * pscale / 2
  9463.     cy = (@center_sprite ? 16 - @hitbox_height / 2 : 32 - @hitbox_height)
  9464.     sy = (self.is_a?(Map_Battler) ? self.y : self.y * $BlizzABS.pixel)
  9465.     y = sy + cy * pscale
  9466.     return Rect.new(x, y, @hitbox_width * pscale, @hitbox_height * pscale)
  9467.   end
  9468.   #--------------------------------------------------------------------------
  9469.   # screen_z
  9470.   #  returns the z coordinate of the character.  Modified to force corpses to
  9471.   #  have a z coordinate of zero.
  9472.   #--------------------------------------------------------------------------
  9473.   alias screen_z_blizzabs_later screen_z
  9474.   def screen_z(height = 0)
  9475.     return 0 if @character_name.include?(BlizzABS::SPRCorpse)
  9476.     screen_z_blizzabs_later(height)
  9477.   end
  9478.  
  9479. end
  9480.  
  9481. #==============================================================================
  9482. # Game_Event
  9483. #------------------------------------------------------------------------------
  9484. #  This class was redefined as non-pixel movement character to support pixel
  9485. #  movement from other character types and ABSEAL update limitation in case
  9486. #  Tons of Add-ons is not available.
  9487. #==============================================================================
  9488.  
  9489. class Game_Event
  9490.  
  9491.   # setting all accessible variables
  9492.   attr_accessor :respawn_ids
  9493.   attr_accessor :respawn_time
  9494.   attr_accessor :icon
  9495.   attr_reader   :event
  9496.   attr_writer   :lock_time
  9497.   #----------------------------------------------------------------------------
  9498.   # override update
  9499.   #----------------------------------------------------------------------------
  9500.   alias upd_player_blizzabs_later update
  9501.   def update
  9502.     # if event lock exists, not expired and no other event is running
  9503.     if @event_lock != nil && @event_lock > 0 &&
  9504.         !$game_system.map_interpreter.running?
  9505.       # decrease event lock timer
  9506.       @event_lock -= 1
  9507.     end
  9508.     # if termination counter exists
  9509.     if @terminate_count != nil
  9510.       # decrease stay time if stay time is greater than 0
  9511.       @terminate_count -= 1 if @terminate_count > 0
  9512.       # set deletion flag if item taken or stay time expired
  9513.       erase if @terminate_count <= 0
  9514.     end
  9515.     # call original method if within ABSEAL range
  9516.     upd_player_blizzabs_later if update?
  9517.   end
  9518.   #----------------------------------------------------------------------------
  9519.   # override refresh
  9520.   #  A flag addition was added to this method.
  9521.   #----------------------------------------------------------------------------
  9522.   alias refresh_blizzabs_later refresh
  9523.   def refresh
  9524.     # call original method
  9525.     refresh_blizzabs_later
  9526.     # test command list on teleport command if command list exists
  9527.     @teleport = (@list != nil && @list.any? {|i| i.code == 201})
  9528.     # activate drop mode if dropped
  9529.     activate_drop_mode if dropped?
  9530.   end
  9531.   #----------------------------------------------------------------------------
  9532.   # override start
  9533.   #  Has been enhanced to support the event lock feature.
  9534.   #----------------------------------------------------------------------------
  9535.   alias start_blizzabs_later start
  9536.   def start
  9537.     # stop if event lock not expired yet
  9538.     return if @event_lock != nil && @event_lock > 0
  9539.     # call original method
  9540.     start_blizzabs_later
  9541.     # set event lock if activated by touch
  9542.     @event_lock = @lock_time if @trigger == 1 || @trigger == 2
  9543.   end
  9544.   #----------------------------------------------------------------------------
  9545.   # override erase
  9546.   #----------------------------------------------------------------------------
  9547.   alias erase_blizzabs_later erase
  9548.   def erase
  9549.     @terminate = true
  9550.     erase_blizzabs_later
  9551.   end
  9552.   #----------------------------------------------------------------------------
  9553.   # passable?
  9554.   #  x - x-coordinate
  9555.   #  y - y-coordinate
  9556.   #  d - facing direction
  9557.   #  Checks if the tile is passable.
  9558.   #----------------------------------------------------------------------------
  9559.   def passable?(x, y, d)
  9560.     # get new coordinates
  9561.     nx, ny = x+(d == 6 ? 1 : d == 4 ? -1 : 0), y+(d == 2 ? 1 : d == 8 ? -1 : 0)
  9562.     # not passable if coordinates are outside of map
  9563.     return false unless $game_map.valid?(nx, ny)
  9564.     # passable if through is ON
  9565.     return true if @through
  9566.     # not passable if unable to leave current tile in designated direction
  9567.     return false unless $game_map.passable?(x, y, d, self)
  9568.     # not passable if unable to enter move tile in designated direction
  9569.     return false unless $game_map.passable?(nx, ny, 10 - d)
  9570.     # if any event on new position and not through
  9571.     if $game_map.events_only.any? {|event|
  9572.         !event.through && event.x == nx && event.y == ny}
  9573.       # impassable
  9574.       return false
  9575.     end
  9576.     # passable if no spriteset
  9577.     return true if @character_name == ''
  9578.     # get pixel movement rate
  9579.     pix = $BlizzABS.pixel
  9580.     # rectangle
  9581.     rect = Rect.new(nx * pix, ny * pix, pix, pix)
  9582.     # if any battler in the way
  9583.     if ($BlizzABS.battlers + $game_map.battlers).any? {|battler|
  9584.         !battler.through && battler.character_name != '' &&
  9585.         $BlizzABS.util.rect_intersection(rect, battler.phitbox)}
  9586.         #Rect.new(battler.x, battler.y, pix, pix))}
  9587.       # impassable
  9588.       return false
  9589.     end
  9590.     # passable
  9591.     return true
  9592.   end
  9593.   #----------------------------------------------------------------------------
  9594.   # check_event_trigger_touch
  9595.   #  x - x-coordinate
  9596.   #  y - y-coordinate
  9597.   #  Check event if was triggered by touch. (pixel movement)
  9598.   #----------------------------------------------------------------------------
  9599.   def check_event_trigger_touch(x, y)
  9600.     # stop check if map interpreter is already running
  9601.     return false if $game_system.map_interpreter.running? || @trigger != 2
  9602.     # get pixel movement rate
  9603.     pix = $BlizzABS.pixel
  9604.     # if player touched this event and not jumping and not over_trigger
  9605.     if !jumping? && !over_trigger? &&
  9606.         $BlizzABS.util.rect_intersection(Rect.new(x * pix, y * pix, pix, pix),
  9607.         Rect.new($game_player.x, $game_player.y, pix, pix))
  9608.       # start
  9609.       start
  9610.       # started
  9611.       return true
  9612.     end
  9613.     # not started
  9614.     return false
  9615.   end
  9616.   #----------------------------------------------------------------------------
  9617.   # check_event_trigger_auto
  9618.   #  Check event if was triggered automatically. (pixel movement)
  9619.   #----------------------------------------------------------------------------
  9620.   def check_event_trigger_auto
  9621.     # if triggered by event touch
  9622.     if @trigger == 2
  9623.       # check player touch
  9624.       return check_event_trigger_at($game_player.x, $game_player.y)
  9625.     # if autorun
  9626.     elsif @trigger == 3
  9627.       # start
  9628.       start
  9629.       # started
  9630.       return true
  9631.     end
  9632.     # not started
  9633.     return false
  9634.   end
  9635.   #----------------------------------------------------------------------------
  9636.   # check_event_trigger_at
  9637.   #  x - x-coordinate
  9638.   #  y - y-coordinate
  9639.   #  Check event if it was triggered at a specific position. (pixel movement)
  9640.   #----------------------------------------------------------------------------
  9641.   def check_event_trigger_at(x, y)
  9642.     # get pixel movement rate
  9643.     pix = $BlizzABS.pixel
  9644.     # if player touched this event and not jumping and not over_trigger
  9645.     if !jumping? && !over_trigger? && $BlizzABS.util.rect_intersection(
  9646.         self.phitbox, Rect.new(x, y, pix, pix))
  9647.       # start
  9648.       start
  9649.       # started
  9650.       return true
  9651.     end
  9652.     # not started
  9653.     return false
  9654.   end
  9655.   #----------------------------------------------------------------------------
  9656.   # set_real_position
  9657.   #  real_x - new real x-coordinate
  9658.   #  real_y - new real y-coordinate
  9659.   #  Sets the real positions of the event.
  9660.   #----------------------------------------------------------------------------
  9661.   def set_real_position(real_x, real_y)
  9662.     @real_x, @real_y = real_x, real_y
  9663.   end
  9664.   #----------------------------------------------------------------------------
  9665.   # activate_drop_mode
  9666.   #  time - countdown timer
  9667.   #  Sets up everything for an event to act like a dropped event.
  9668.   #----------------------------------------------------------------------------
  9669.   def activate_drop_mode(time = @terminate_count)
  9670.     # set disappearance counter
  9671.     @terminate_count = time
  9672.     # set moving speed
  9673.     @move_speed = 6
  9674.     # set moving frequency
  9675.     @move_frequency = 6
  9676.     # set step anime
  9677.     @step_anime = true
  9678.     # set direction fix
  9679.     @direction_fix = true
  9680.   end
  9681.  
  9682. end
Add Comment
Please, Sign In to add comment