neonblack

Relationship System

Feb 26th, 2013
210
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ##----------------------------------------------------------------------------##
  2. ## The Legend of NeonBlack's Maus Romancing Sa-Ga Script v1.0
  3. ## Created by Neon Black
  4. ##
  5. ## For both commercial and non-commercial use as long as credit is given to
  6. ## Neon Black and any additional authors.  Licensed under Creative Commons
  7. ## CC BY 3.0 - http://creativecommons.org/licenses/by/3.0/.
  8. ##----------------------------------------------------------------------------##
  9.                                                                               ##
  10. ##----------------------------------------------------------------------------##
  11. ##    Revision Info:
  12. ## v1.0 - 3.3.2013
  13. ##  Wrote and debugged main script
  14. ##----------------------------------------------------------------------------##
  15.                                                                               ##
  16. $imported ||= {}                                                              ##
  17. $imported["CP_RELATIONSHIP"] = 1.0                                            ##
  18.                                                                               ##
  19. ##----------------------------------------------------------------------------##
  20. ##    Instructions:
  21. ## Place this script in the script editor below "Materials" and above "Main".
  22. ## This script requires Neon Black's Features and Effects name module.  You can
  23. ## obtain it from http://cphouseset.wordpress.com/modules/.  If you do not
  24. ## import it, you will get errors.
  25. ##
  26. ## This script allows additional features to be gained via relationships between
  27. ## two characters.  The names, descriptions, and power of the features can be
  28. ## modified by the script as well as numerous other conditions.  This script
  29. ## has both note tags and script calls that allow it to work.  These are as
  30. ## follows.
  31. ##
  32. ##------
  33. ##    Notebox Tags:
  34. ##
  35. ## relationship[+5 atk]  -or-  friends[-1% def]  -or-  lovers[+5.5% mmp]  -etc-
  36. ##  - The main tag used by this script and by far the most useful.  The tag can
  37. ##    be used to define if the bonus should apply to friends, lovers, or all
  38. ##    relationship types.  You can set any value, positive or negative, whole or
  39. ##    decimal, percentage or integer.  The last section of the code is the 3
  40. ##    letter name of the stat to modify.  Any stat from page 2 of a features
  41. ##    box may be used.  By default, all bonuses are added only when BOTH party
  42. ##    members are in the battle party.  At this time, extra parameter scripts
  43. ##    will not work with this script.
  44. ## relationship[skill 5]  -etc-
  45. ##  - Allows a skill to be learned when a relation ship is formed.  The skill
  46. ##    will be learned as long as relationship type and party conditions are met
  47. ##    so it is advised to use additional parameters for this tag (see below).
  48. ##    The "relationship" value of this tag can be replaced with "lovers" or
  49. ##    "friends" like the tag above.
  50. ## friends[weapon 2]  -or-  lovers[armor 3]  -etc-
  51. ##  - Allows weapons or armours of certain types to be equipped even if the
  52. ##    actor would not normally be able to equip them.  All the same rules as
  53. ##    skills above apply.
  54. ## for actor[3]  -or-  for actor[1, 2, 3]
  55. ##  - Allows additional parameters to be added to a bonus that allow only
  56. ##    certain actors to recieve the bonus.  This tag goes immediately after the
  57. ##    bonus you want to tag, for example:  relationship[+1% mmp] for actor[2]
  58. ## for level[4]  -or-  for level[3+]  -or-  for level[1-5]
  59. ##  - Allows additional parameters to be added to a bonus that prevent the bonus
  60. ##    from being added unless the relationship level is in the specified range.
  61. ##    This works similar to the tag above.
  62. ## <relationship party>  -and-  </relationship party>
  63. ##  - Allows all bonuses between the tags to be used as long as both party
  64. ##    members are in the party, even if they are not in the battle party
  65. ##    together.
  66. ## <relationship constant>  -and-  </relationship constant>
  67. ##  - Similar to the tags above, however all bonuses between these tags are
  68. ##    ALWAYS active, even if the actors are not in the party together.
  69. ## gender[male]  -and-  gender[female]
  70. ##  - Used to determine the base gender of a character.  By default, same sex
  71. ##    couples are friends and opposite sex couples are lovers.  If the
  72. ##    HOMOSEXUAL option is disabled, same sex couples can only reach the defined
  73. ##    cap in the lovers catagory.
  74. ##
  75. ##------
  76. ##    Script Calls:
  77. ##
  78. ## Relationship.open
  79. ##  - Quite simply, opens the status screen.
  80. ## Relationship.exp(actor1, actor2, exp)
  81. ##  - Used to alter the exp of a relationship.  The exp can be positive or
  82. ##    negative.  All other normal things that would happen occur automatically.
  83. ## Relationship.type(actor1, actor2, :switch)
  84. ##  - Used to change the type of relationship two actors are in.  This
  85. ##    automatically breaks a max level relationship if one has been established.
  86. ##    Note that :switch will switch the type of relationship from/to both
  87. ##    friends/lovers, while you can use :lovers or :friends to define the type
  88. ##    to switch to manually.
  89. ## Relationship.level(actor1, actor2)  -or-  Check.relationship_level(a1, a2)
  90. ##  - Gets the relationship level of two actors.  Can be used for conditional
  91. ##    script calls and such.
  92. ## Relationship.between(actor1, actor2)  -or-  Check.relationship_between(a, b)
  93. ##  - Gets the type of relationship two actors are in.  Returns a value of
  94. ##    either :lovers or :friends.
  95. ##----------------------------------------------------------------------------##
  96.                                                                               ##
  97. module CP           # Do not touch                                            ##
  98. module RELATIONSHIP #  these lines.                                           ##
  99.                                                                               ##
  100. ##----------------------------------------------------------------------------##
  101. ##    Config:
  102. ## The config options are below.  You can set these depending on the flavour of
  103. ## your game.  Each option is explained in a bit more detail above it.
  104. ##
  105. ##------
  106. # This hash contains the info for each level of friendship.  The key is the
  107. # level.  The first value is the exp required to reach that level, the second
  108. # value is the name of that level, the third value is the description for the
  109. # level, and the last value is the bonus multiplier for the level.
  110. FRIEND_LEVELS ={
  111.   1 => [1,  "Stranger",      "Only just met each other",          0.0],
  112.   2 => [5,  "Aquaintance",   "Know about each other at best",     0.0],
  113.   3 => [10, "Party Member",  "Just work together",                1.0],
  114.   4 => [15, "Friends",       "Are friendly with each other",      2.0],
  115.   5 => [20, "Good Friends",  "Trust each other",                  3.0],
  116.   6 => [25, "Teammate",      "Would go to the other's aid",       4.0],
  117.   7 => [35, "Best Friends",  "Rush to each other's aid",          6.0],
  118.   8 => [45, "Partners",      "Trust each other with their lives", 8.0],
  119. }
  120.  
  121. # Same as above, but for lover levels.
  122. LOVER_LEVELS ={
  123.   1  => [1,  "Stranger",      "Only just met each other",       0.0],
  124.   2  => [5,  "Aquaintance",   "Know about each other at best",  0.0],
  125.   3  => [10, "Party Member",  "Just work together",             1.0],
  126.   4  => [15, "Friends",       "Are friendly with each other",   2.0],
  127.   5  => [20, "Good Friends",  "Trust each other",               3.0],
  128.   6  => [25, "Crush",         "Share a mutual attraction",      4.0],
  129.   7  => [30, "Close",         "Getting to know each other",     5.0],
  130.   8  => [35, "Dating",        "Getting to know each other",     6.0],
  131.   9  => [40, "Lovers",        "Certain of each other's love",   8.0],
  132.   10 => [45, "Soul Mate",     "Bound by fate",                 10.0],
  133. }
  134.  
  135. # And finally rival levels for negative amounds of EXP.  This array starts at 0
  136. # and goes DOWN into the negatives.
  137. ENEMY_LEVELS ={
  138.    0 => [0,   "Annoyance", "Barely tolerate each other",  0.0],
  139.   -1 => [-10, "Rival",     "Fed up with each other",      0.0],
  140.   -2 => [-25, "Enemy",     "Do not get along at all",    -1.0],
  141. }
  142.  
  143. # The caps for all other relationships of the same type when a relationship has
  144. # reached max in that catagory.
  145. FRIEND_CAP = 6
  146. LOVER_CAP = 5
  147.  
  148. # The minimum levels required for a name and rank to appear in the menu.
  149. FRIEND_MIN = 4
  150. LOVER_MIN = 6
  151.  
  152. # If this is set to true, if a lover has not reached the minimum lover level to
  153. # appear in the menu, but has enough EXP that they are the highest relationship
  154. # AND they have reached the minimum level required for friends, they will appear
  155. # as a friend.  If you are confused by this option, please just turn it off.
  156. LOVER_AS_FRIEND = true
  157.  
  158. # The symbol that separates the name and relationship ranking when a lover or
  159. # friend is drawn in a window.  Ignore the misspelling.
  160. SEPERATOR = '-'
  161.  
  162. # The text to display when no characters can be classified as a closest relation
  163. # of some sort.
  164. NO_FRIEND = "Lone Wolf"
  165. NO_LOVER = "Single"
  166. NO_ENEMY = "No Enemies"
  167.  
  168. # While this value is false, same sex couples cannot go above LOVER_CAP in the
  169. # lovers catagory.  If it is set to true, they function the same as opposite
  170. # sex couples.  This is only to prevent bugs and not meant to portray any way
  171. # of thinking.
  172. HOMOSEXUAL = false
  173.  
  174. # This option determines if the character's lover is displayed in the status
  175. # screen.  This will display right below the equips if it is enabled.
  176. STATUS_SCREEN = true
  177.  
  178. # Define if a menu option can be used to access a page displaying all
  179. # relationship bonuses.  Also allows you to name this option.
  180. USE_MENU = true
  181. MENU_NAME = "Relationships"
  182.  
  183. # Used in the scene mentioned above to display the closest friend and lover.
  184. FRIEND_NAME = "Closest Friend"
  185. LOVER_NAME = "Closest Relationship"
  186. ##----------------------------------------------------------------------------##
  187.                                                                               ##
  188.                                                                               ##
  189. ##----------------------------------------------------------------------------##
  190. ## The following lines are the actual core code of the script.  While you are
  191. ## certainly invited to look, modifying it may result in undesirable results.
  192. ## Modify at your own risk!
  193. ###----------------------------------------------------------------------------
  194.  
  195.  
  196. end
  197. end
  198.  
  199. module DataManager
  200.   class << self
  201.     alias :cp_rshp_setup_new_game :setup_new_game
  202.     alias :cp_rshp_setup_battle :setup_battle_test
  203.   end
  204.  
  205.   def self.setup_new_game(*args)
  206.     cp_rshp_setup_new_game(*args)
  207.     $game_party.all_members.each { |m| m.recover_all }
  208.   end
  209.  
  210.   def self.setup_battle_test(*args)
  211.     cp_rshp_setup_battle(*args)
  212.     $game_party.all_members.each { |m| m.recover_all }
  213.   end
  214. end
  215.  
  216. module SceneManager
  217.   class << self
  218.     alias :cp_rshp_run :run unless method_defined?(:cp_rshp_run)
  219.   end
  220.  
  221.   def self.run
  222.     cp_module_check_features
  223.     cp_rshp_run
  224.   end
  225.  
  226.   def self.cp_module_check_features
  227.     return if $imported["CP_FEATURES_EFFECTS"]
  228.     a1 = "One or more scripts require Neon Black's Features and Effects module."
  229.     a2 = "This can be obtained at http://cphouseset.wordpress.com/modules/"
  230.     a3 = "Please add this module and try again."
  231.     a4 = "Please contact the creator of the game to resolve this issue."
  232.     if $TEST || $BTEST
  233.       msgbox "#{a1}/n#{a2}/n#{a3}"
  234.       Thread.new{system("start http://cphouseset.wordpress.com/modules/#features")}
  235.     else
  236.       msgbox "#{a1}/n#{a4}"
  237.     end
  238.   end
  239. end
  240.  
  241. module Relationship
  242.   def self.exp(act1, act2, exp)
  243.     old_lvl = $game_party.relationship_level(act1, act2)
  244.     mlvl = $game_party.change_rlevel_exp(act1, act2, exp)
  245.     if $game_party.relationship_level(act1, act2) < mlvl
  246.       $game_party.break_relationship(act1, act2)
  247.     elsif exp >= 0
  248.       $game_party.make_relationship(act1, act2)
  249.     end
  250.     if old_lvl != $game_party.relationship_level(act1, act2)
  251.       $game_party.reset_relationship
  252.     end
  253.   end
  254.  
  255.   def self.type(act1, act2, val = :switch)
  256.     $game_party.break_relationship(act1, act2)
  257.     mlvl = $game_party.relationship_type_switch(act1, act2, val)
  258.     if $game_party.relationship_level(act1, act2) >= mlvl
  259.       $game_party.make_relationship(act1, act2)
  260.     end
  261.     $game_party.reset_relationship
  262.   end
  263.  
  264.   def self.level(act1, act2)
  265.     $game_party.relationship_level(act1, act2)
  266.   end
  267.  
  268.   def self.between(act1, act2)
  269.     $game_party.relationship_type(act1, act2)
  270.   end
  271.  
  272.   def self.open
  273.     SceneManager.call(Scene_RelationshipStatus)
  274.   end
  275. end
  276.  
  277. module Check
  278.   def self.relationship(act1, act2)
  279.     [relationship_between(act1, act2), relationship_level(act1, act2)]
  280.   end
  281.  
  282.   def self.relationship_level(act1, act2)
  283.     $game_party.relationship_level(act1, act2)
  284.   end
  285.  
  286.   def self.relationship_between(act1, act2)
  287.     $game_party.relationship_type(act1, act2)
  288.   end
  289. end
  290.  
  291. class Game_Actors
  292.   def each
  293.     make_all_actors
  294.     @data.each do |actor|
  295.       next unless actor
  296.       yield actor
  297.     end
  298.   end
  299.  
  300.   def size
  301.     make_all_actors
  302.     @data.size
  303.   end
  304.  
  305.   def make_all_actors
  306.     return if @all_setup; @all_setup = true
  307.     $data_actors.each_with_index do |act, id|
  308.       next unless act
  309.       @data[id] ||= Game_Actor.new(id)
  310.     end
  311.   end
  312. end
  313.  
  314. class Game_Actor < Game_Battler
  315.   alias :cp_rshp_init :initialize
  316.   def initialize(*args)
  317.     cp_rshp_init(*args)
  318.     @relationship_bonuses = {}
  319.   end
  320.  
  321.   def reset_relationship
  322.     @relationship_bonuses = {}
  323.     relationship_features
  324.     refresh
  325.   end
  326.  
  327.   alias :cp_rshp_features :all_features
  328.   def all_features
  329.     cp_rshp_features + relationship_features
  330.   end
  331.  
  332.   def relationship_features
  333.     return [] unless @relationship_bonuses
  334.     battle_party_rsfeatures + current_party_rsfeatures + all_party_rsfeatures
  335.   end
  336.  
  337.   def battle_party_rsfeatures
  338.     result = []
  339.     return result unless $game_party.battle_members.include?(self)
  340.     $game_party.battle_members.each do |mem|
  341.       next if mem.nil? || mem.id == self.id
  342.       result += mem.relationship_bonuses(@actor_id, :battle)
  343.     end
  344.     result
  345.   end
  346.  
  347.   def current_party_rsfeatures
  348.     result = []
  349.     return result unless $game_party.all_members.include?(self)
  350.     $game_party.all_members.each do |mem|
  351.       next if mem.nil? || mem.id == self.id
  352.       result += mem.relationship_bonuses(@actor_id, :party)
  353.     end
  354.     result
  355.   end
  356.  
  357.   def all_party_rsfeatures
  358.     result = []
  359.     $game_actors.each do |mem|
  360.       next if mem.nil? || mem.id == self.id
  361.       result += mem.relationship_bonuses(@actor_id, :game)
  362.     end
  363.     result
  364.   end
  365.  
  366.   def rsfeatures_total_others
  367.     results = {}
  368.     $game_actors.each do |mem|
  369.       next if mem.nil? || mem.id == self.id
  370.       results[mem.id] = []
  371.       mem.relationship_bonuses(@actor_id, :battle).each do |ft|
  372.         results[mem.id].push([:battle, ft])
  373.       end
  374.       mem.relationship_bonuses(@actor_id, :party).each do |ft|
  375.         results[mem.id].push([:party, ft])
  376.       end
  377.       mem.relationship_bonuses(@actor_id, :game).each do |ft|
  378.         results[mem.id].push([:game, ft])
  379.       end
  380.     end
  381.     return results
  382.   end
  383.  
  384.   def relationship_bonuses(id, scope)
  385.     @relationship_bonuses = {} if @relationship_bonuses.nil?
  386.     return @relationship_bonuses[id][scope] if @relationship_bonuses.include?(id)
  387.     make_relationship_features(@actor_id, id)
  388.     return @relationship_bonuses[id][scope]
  389.   end
  390.  
  391.   def make_relationship_features(host, id)
  392.     @relationship_bonuses[id] = {:battle=>[], :party=>[], :game=>[]}
  393.     rlevel = $game_party.relationship_level(host, id)
  394.     multi = $game_party.relationship_multiplier(host, id)
  395.     rtype = $game_party.relationship_type(host, id, false)
  396.     actor.relationship_features.each do |scope, array|
  397.       array.each do |item|
  398.         next unless item[4] == rtype || item[4] == :relationship
  399.         next if !item[5][:actor].empty? && !item[5][:actor].include?(id)
  400.         next unless level_from_array(rlevel, item[5][:level])
  401.         @relationship_bonuses[id][scope].push(get_feature_from_array(item, multi))
  402.       end
  403.       @relationship_bonuses[id][scope].compact!
  404.     end
  405.   end
  406.  
  407.   def level_from_array(rlevel, lvl)
  408.     case lvl
  409.     when /(\d+)[-](\d+)/i
  410.       return rlevel >= $1.to_i && rlevel <= $2.to_i
  411.     when /(\d+)[\+]/i
  412.       return rlevel >= $1.to_i
  413.     when /(\d+)/i
  414.       return rlevel == $1.to_i
  415.     else
  416.       return true
  417.     end
  418.   end
  419.  
  420.   def get_feature_from_array(array, multi)
  421.     case array[0]
  422.     when :stat
  423.       return nil unless multi != 0
  424.       codes = CP::Features.get_feature(array[3], array[2])
  425.       return nil unless codes
  426.       ft = RPG::BaseItem::Feature.new(codes[0], codes[1], array[1] * multi)
  427.     when :skill
  428.       ft = RPG::BaseItem::Feature.new(43, array[1], 0)
  429.     when :weapon
  430.       ft = RPG::BaseItem::Feature.new(51, array[1], 0)
  431.     when :armor, :armour
  432.       ft = RPG::BaseItem::Feature.new(52, array[1], 0)
  433.     end
  434.     return ft
  435.   end
  436.  
  437.   def gender
  438.     unless @composite_male.nil?
  439.       return @composite_male ? :male : :female
  440.     else
  441.       return actor.gender
  442.     end
  443.   end
  444. end
  445.  
  446. class Game_Party < Game_Unit
  447.   def reset_relationship
  448.     $game_actors.each { |m| m.reset_relationship }
  449.   end
  450.  
  451.   def relationship_type(act1, act2, rrival = true)
  452.     a1, a2 = [act1, act2].sort
  453.     init_relationship_table unless @relationship_table
  454.     table_type, exp_level = @relationship_table[[a1, a2]]
  455.     return table_type unless rrival
  456.     return exp_level > 0 ? table_type : :rivals
  457.   end
  458.  
  459.   def relationship_level(act1, act2)
  460.     a1, a2 = [act1, act2].sort
  461.     init_relationship_table unless @relationship_table
  462.     table_type, exp_level = @relationship_table[[a1, a2]]
  463.     return 0 if table_type.nil? || exp_level.nil?
  464.     if table_type == :friends
  465.       top = @friends_hash[a1] ? @friends_hash[a1] == a2 : true
  466.     elsif table_type == :lovers
  467.       top = false if !CP::RELATIONSHIP::HOMOSEXUAL &&
  468.                      $game_actors[a1].gender == $game_actors[a2].gender
  469.       top = @lovers_hash[a1] ? @lovers_hash[a1] == a2 : true
  470.     end
  471.     return [make_rlevel(table_type, exp_level),
  472.             make_rcap(table_type, top || true)].min
  473.   end
  474.  
  475.   def make_rlevel(type, exp)
  476.     if exp > 0
  477.       lvl = 1
  478.       cp_relate_hashes(type).each do |key, array|
  479.         lvl = key if key > lvl && exp >= array[0]
  480.       end
  481.     else
  482.       lvl = 0
  483.       cp_relate_hashes(:rivals).each do |key, array|
  484.         lvl = key if key < lvl && exp <= array[0]
  485.       end
  486.     end
  487.     return lvl
  488.   end
  489.  
  490.   def change_rlevel_exp(act1, act2, exp)
  491.     a1, a2 = [act1, act2].sort
  492.     init_relationship_table unless @relationship_table
  493.     type = @relationship_table[[a1, a2]][0]
  494.     @relationship_table[[a1, a2]][1] += exp
  495.     check_relationship_cap(a1, a2, type)
  496.     return cp_relate_hashes(type).keys.max
  497.   end
  498.  
  499.   def check_relationship_cap(act1, act2, type = nil)
  500.     a1, a2 = [act1, act2].sort
  501.     table_type, exp = @relationship_table[[a1, a2]]
  502.     if type == :friends
  503.       return if table_type != type ||
  504.                 (@friends_hash[a1].nil? && @friends_hash[a2].nil?) ||
  505.                 (@friends_hash[a1] == a2 && @friends_hash[a2] == a1)
  506.       cap = CP::RELATIONSHIP::FRIEND_CAP
  507.     elsif type == :lovers
  508.       return if table_type != type ||
  509.                 (@lovers_hash[a1].nil? && @lovers_hash[a2].nil?) ||
  510.                 (@lovers_hash[a1] == a2 && @lovers_hash[a2] == a1)
  511.       cap = CP::RELATIONSHIP::LOVER_CAP
  512.     else
  513.       return
  514.     end
  515.     mexp = cp_relate_hashes(type)[cap][0]
  516.     @relationship_table[[a1, a2]][1] = mexp if exp > mexp
  517.   end
  518.  
  519.   def relationship_type_switch(act1, act2, val)
  520.     a1, a2 = [act1, act2].sort
  521.     init_relationship_table unless @relationship_table
  522.     type = @relationship_table[[a1, a2]][0]
  523.     case val
  524.     when :switch
  525.       if type == :lovers
  526.         @relationship_table[[a1, a2]][0] = :friends
  527.       elsif type == :friends
  528.         @relationship_table[[a1, a2]][0] = :lovers
  529.       end
  530.     when :lovers
  531.       @relationship_table[[a1, a2]][0] = :lovers
  532.     when :friends
  533.       @relationship_table[[a1, a2]][0] = :friends
  534.     end
  535.     return cp_relate_hashes(@relationship_table[[a1, a2]][0]).keys.max
  536.   end
  537.  
  538.   def make_rcap(type, top)
  539.     lvl = 999
  540.     if type == :lovers
  541.       lvl = CP::RELATIONSHIP::LOVER_CAP unless top
  542.     elsif type == :friends
  543.       lvl = CP::RELATIONSHIP::FRIEND_CAP unless top
  544.     end
  545.     return lvl
  546.   end
  547.  
  548.   def relationship_multiplier(act1, act2)
  549.     init_relationship_table unless @relationship_table
  550.     rlevel = relationship_level(act1, act2)
  551.     a1, a2 = [act1, act2].sort
  552.     table_type = relationship_type(a1, a2)
  553.     multi = cp_relate_hashes(table_type)[rlevel][3] rescue multi = 0
  554.     return multi
  555.   end
  556.  
  557.   def break_relationship(act1, act2)
  558.     a1, a2 = [act1, act2].sort
  559.     table_type, exp_level = @relationship_table[[a1, a2]]
  560.     case table_type
  561.     when :friends
  562.       return unless @friends_hash[a1] == a2 && @friends_hash[a2] == a1
  563.       @friends_hash[a1] = nil
  564.       @friends_hash[a2] = nil
  565.     when :lovers
  566.       return unless @lovers_hash[a1] == a2 && @lovers_hash[a2] == a1
  567.       @lovers_hash[a1] = nil
  568.       @lovers_hash[a2] = nil
  569.     end
  570.   end
  571.  
  572.   def make_relationship(act1, act2)
  573.     a1, a2 = [act1, act2].sort
  574.     table_type, exp_level = @relationship_table[[a1, a2]]
  575.     case table_type
  576.     when :friends
  577.       return unless @friends_hash[a1].nil? && @friends_hash[a2].nil?
  578.       @friends_hash[a1] = a2
  579.       @friends_hash[a2] = a1
  580.     when :lovers
  581.       return unless @lovers_hash[a1].nil? && @lovers_hash[a2].nil?
  582.       @lovers_hash[a1] = a2
  583.       @lovers_hash[a2] = a1
  584.     end
  585.     $game_actors.each do |a3|
  586.       next if a3.nil? || a3.id == a1 || a3.id == a2
  587.       check_relationship_cap(a1, a3.id, table_type)
  588.       check_relationship_cap(a2, a3.id, table_type)
  589.     end
  590.   end
  591.  
  592.   def cp_relate_hashes(table)
  593.     case table
  594.     when :lovers
  595.       return CP::RELATIONSHIP::LOVER_LEVELS
  596.     when :friends
  597.       return CP::RELATIONSHIP::FRIEND_LEVELS
  598.     when :rivals
  599.       return CP::RELATIONSHIP::ENEMY_LEVELS
  600.     else
  601.       return {}
  602.     end
  603.   end
  604.  
  605.   def init_relationship_table
  606.     @relationship_table = {}
  607.     @lovers_hash = {}
  608.     @friends_hash = {}
  609.     $game_actors.each do |a1|
  610.       next unless a1
  611.       @lovers_hash[a1] = nil
  612.       @friends_hash[a1] = nil
  613.       $game_actors.each do |a2|
  614.         next if !a2 || a1.id >= a2.id
  615.         status = a1.gender == a2.gender ? :friends : :lovers
  616.         exp = 1
  617.         @relationship_table[[a1.id, a2.id]] = [status, exp]
  618.       end
  619.     end
  620.   end
  621.  
  622.   def greatest_relationship(act, type)
  623.     if type == :friends
  624.       return @friends_hash[act] if @friends_hash[act]
  625.     elsif type == :lovers
  626.       return @lovers_hash[act] if @lovers_hash[act]
  627.     end
  628.     result = 0
  629.     exp = nil
  630.     $game_actors.each do |a|
  631.       next if a.nil? || a.id == act
  632.       rt = relationship_type(a.id, act)
  633.       rl = relationship_level(a.id, act)
  634.       next if !CP::RELATIONSHIP::LOVER_AS_FRIEND && type != rt
  635.       next if (type == :lovers && !@lovers_hash[a.id].nil? &&
  636.                @lovers_hash[a.id] != act) || (type == :friends &&
  637.                !@friends_hash[a.id].nil? && @friends_hash[a.id] != act)
  638.       a1, a2 = [a.id, act].sort
  639.       next if type == :lovers && (rt != :lovers ||
  640.               rl < CP::RELATIONSHIP::LOVER_MIN)
  641.       next if type == :friends && (rl < CP::RELATIONSHIP::FRIEND_MIN ||
  642.               (rt == :lovers && rl >= CP::RELATIONSHIP::LOVER_MIN))
  643.       _, aex = @relationship_table[[a1, a2]]
  644.       next unless exp.nil? || aex.abs > exp.abs
  645.       result, exp = a.id, aex
  646.     end
  647.     return result
  648.   end
  649. end
  650.  
  651. class Scene_Menu < Scene_MenuBase
  652.   alias :cp_rshp_form_ok :on_formation_ok
  653.   def on_formation_ok(*args)
  654.     cp_rshp_form_ok(*args)
  655.     $game_party.all_members.each { |m| m.refresh }
  656.     @status_window.refresh
  657.   end
  658. end
  659.  
  660. ##------
  661. ## Scenes and windows below.
  662. ##------
  663.  
  664. class Scene_RelationshipStatus < Scene_MenuBase
  665.   def start
  666.     super
  667.     draw_all_windows
  668.   end
  669.  
  670.   def draw_all_windows
  671.     @top_window = Window_RelationshipTop.new(@actor)
  672.     @bonus_window = Window_RelationshipBonus.new(@top_window)
  673.     @bonus_window.set_handler(:ok,       method(:select_actor))
  674.     @bonus_window.set_handler(:cancel,   method(:return_scene))
  675.     @bonus_window.set_handler(:pagedown, method(:next_actor))
  676.     @bonus_window.set_handler(:pageup,   method(:prev_actor))
  677.   end
  678.  
  679.   def select_actor
  680.     @actor = $game_actors[@bonus_window.valid_partners.keys[@bonus_window.index]]
  681.     on_actor_change
  682.   end
  683.  
  684.   def on_actor_change
  685.     @top_window.actor = @actor
  686.     @top_window.refresh
  687.     @bonus_window.refresh
  688.     @bonus_window.activate
  689.   end
  690. end
  691.  
  692. class Scene_Menu < Scene_MenuBase
  693.   alias :cp_rshp_cc_window :create_command_window
  694.   def create_command_window
  695.     cp_rshp_cc_window
  696.     @command_window.set_handler(:cp_rshp, method(:command_personal))
  697.   end
  698.  
  699.   alias :cp_rshp_personal_ok :on_personal_ok
  700.   def on_personal_ok
  701.     cp_rshp_personal_ok
  702.     case @command_window.current_symbol
  703.     when :cp_rshp
  704.       Relationship.open
  705.     end
  706.   end
  707. end
  708.  
  709. class Window_Base < Window
  710.   def draw_actor_friend(actor, x, y, width = 180)
  711.     act2 = $game_party.greatest_relationship(actor.id, :friends)
  712.     unless act2 == 0
  713.       rt = $game_party.relationship_type(actor.id, act2)
  714.       lvl = $game_party.relationship_level(actor.id, act2)
  715.       level = $game_party.cp_relate_hashes(rt)[lvl][1]
  716.       draw_relationship(act2, level, x, y, width)
  717.     else
  718.       draw_text(x + 24, y, width, line_height, CP::RELATIONSHIP::NO_FRIEND)
  719.     end
  720.   end
  721.  
  722.   def draw_actor_lover(actor, x, y, width = 180)
  723.     act2 = $game_party.greatest_relationship(actor.id, :lovers)
  724.     unless act2 == 0
  725.       rt = $game_party.relationship_type(actor.id, act2)
  726.       lvl = $game_party.relationship_level(actor.id, act2)
  727.       level = $game_party.cp_relate_hashes(rt)[lvl][1]
  728.       draw_relationship(act2, level, x, y, width)
  729.     else
  730.       draw_text(x + 24, y, width, line_height, CP::RELATIONSHIP::NO_LOVER)
  731.     end
  732.   end
  733.  
  734.   def draw_actor_rival(actor, x, y, width = 180)
  735.     act2 = $game_party.greatest_relationship(actor.id, :rivals)
  736.     unless act2 == 0
  737.       rt = $game_party.relationship_type(actor.id, act2)
  738.       lvl = $game_party.relationship_level(actor.id, act2)
  739.       level = $game_party.cp_relate_hashes(rt)[lvl][1]
  740.       draw_relationship(act2, level, x, y, width)
  741.     else
  742.       draw_text(x + 24, y, width, line_height, CP::RELATIONSHIP::NO_ENEMY)
  743.     end
  744.   end
  745.  
  746.   def draw_relationship_between(act1, act2, x, y, width = 180)
  747.     lvl = $game_party.relationship_level(act1, act2)
  748.     case $game_party.relationship_type(act1, act2)
  749.     when :lovers
  750.       level = $game_party.cp_relate_hashes(:lovers)[lvl][1]
  751.       txt = $game_party.cp_relate_hashes(:lovers)[lvl][2]
  752.     when :friends
  753.       level = $game_party.cp_relate_hashes(:friends)[lvl][1]
  754.       txt = $game_party.cp_relate_hashes(:friends)[lvl][2]
  755.     when :rivals
  756.       level = $game_party.cp_relate_hashes(:rivals)[lvl][1]
  757.       txt = $game_party.cp_relate_hashes(:rivals)[lvl][2]
  758.     end
  759.     draw_relationship(act2, level, x, y, width)
  760.     lfs = contents.font.size
  761.     contents.font.size = contents.font.size / 6 * 5
  762.     draw_text(x, y + line_height, width, line_height, txt, 1)
  763.     contents.font.size = lfs
  764.   end
  765.  
  766.   def draw_relationship(actor, level, x, y, width)
  767.     other = $game_actors[actor]
  768.     return unless other
  769.     draw_actor_icon(other, x, y)
  770.     lfs = contents.font.size
  771.     draw_text((x + width / 2) - 12, y, 24, line_height,
  772.               CP::RELATIONSHIP::SEPERATOR, 1)
  773.     contents.font.size = contents.font.size / 6 * 5
  774.     draw_actor_name(other, x + 24, y, (width / 2) - 36)
  775.     change_color(normal_color)
  776.     draw_text((x + width / 2) + 12, y, width / 2 - 16, line_height, level)
  777.     contents.font.size = lfs
  778.   end
  779.  
  780.   def draw_actor_icon(actor, x, y)
  781.     character_name = actor.character_name
  782.     character_index = actor.character_index
  783.     return unless character_name
  784.     bitmap = Cache.character(character_name)
  785.     sign = character_name[/^[\!\$]./]
  786.     if sign && sign.include?('$')
  787.       cw = bitmap.width / 3
  788.       ch = bitmap.height / 4
  789.     else
  790.       cw = bitmap.width / 12
  791.       ch = bitmap.height / 8
  792.     end
  793.     n = character_index
  794.     src_rect = Rect.new(((n%4*3+1)*cw) + [(cw-24)/2, 0].max, (n/4*4)*ch,
  795.                         [24, cw].min, 24)
  796.     contents.blt(x, y, bitmap, src_rect)
  797.   end
  798. end
  799.  
  800. class Window_MenuCommand < Window_Command
  801.   alias :cp_rshp_ocomm :add_original_commands
  802.   def add_original_commands
  803.     cp_rshp_ocomm
  804.     if CP::RELATIONSHIP::USE_MENU
  805.       add_command(CP::RELATIONSHIP::MENU_NAME, :cp_rshp, main_commands_enabled)
  806.     end
  807.   end
  808. end
  809.  
  810. class Window_Status < Window_Selectable
  811.   alias :cp_rshp_block3 :draw_block3
  812.   def draw_block3(y)
  813.     cp_rshp_block3(y)
  814.     return unless CP::RELATIONSHIP::STATUS_SCREEN
  815.     draw_actor_lover(@actor, 288, y + line_height * 5, 196)
  816.   end
  817. end
  818.  
  819. class Window_RelationshipTop < Window_Base
  820.   attr_accessor :actor
  821.  
  822.   def initialize(actor)
  823.     super(0, 0, Graphics.width, fitting_height(4))
  824.     @actor = actor
  825.     refresh
  826.   end
  827.  
  828.   def refresh
  829.     contents.clear
  830.     draw_actor_face(@actor, 2, 0)
  831.     draw_actor_name(@actor, 106, line_height, 180)
  832.     draw_actor_nickname(@actor, 106, line_height * 2)
  833.     draw_favorites_block(290, contents.width - 290)
  834.   end
  835.  
  836.   def draw_favorites_block(x, width)
  837.     change_color(system_color)
  838.     draw_text(x, 0, width, line_height, CP::RELATIONSHIP::FRIEND_NAME)
  839.     draw_text(x, line_height * 2, width, line_height,
  840.               CP::RELATIONSHIP::LOVER_NAME)
  841.     change_color(normal_color)
  842.     draw_actor_friend(@actor, x, line_height, width)
  843.     draw_actor_lover(@actor, x, line_height * 3, width)
  844.   end
  845. end
  846.  
  847. class Window_RelationshipBonus < Window_Selectable
  848.   def initialize(parent)
  849.     @parent = parent
  850.     h = Graphics.height - @parent.height
  851.     super(@parent.x, @parent.y + @parent.height, Graphics.width, h)
  852.     refresh
  853.     activate
  854.   end
  855.  
  856.   def col_max
  857.     return 2
  858.   end
  859.  
  860.   def item_max
  861.     return valid_partners.size
  862.   end
  863.  
  864.   def item_height
  865.     return line_height * 2 if item_max <= 0
  866.     return (valid_partners.values.collect{|s| s.size}.max + 2) * line_height + 8
  867.   end
  868.  
  869.   def valid_partners
  870.     return @parent.actor.rsfeatures_total_others.select do |k,v|
  871.       $game_party.all_members.include?($game_actors[k]) || !v.empty?
  872.     end
  873.   end
  874.  
  875.   def refresh
  876.     select(0)
  877.     create_contents
  878.     draw_all_items
  879.   end
  880.  
  881.   def current_item_enabled?
  882.     return false if item_max <= 0
  883.     $game_party.all_members.include?($game_actors[valid_partners.keys[@index]])
  884.   end
  885.  
  886.   def draw_item(index)
  887.     rect = item_rect(index)
  888.     rect.x += 2; rect.y += 4; rect.width -= 4
  889.     act = valid_partners.keys[index]
  890.     draw_relationship_between(@parent.actor.id, act, rect.x, rect.y,
  891.                               rect.width)
  892.     valid_partners.values[index].each_with_index do |array, i|
  893.       text = array[1].vocab
  894.       case array[0]
  895.       when :battle
  896.         tf = $game_party.battle_members.include?($game_actors[act]) &&
  897.              $game_party.battle_members.include?(@parent.actor)
  898.       when :party
  899.         tf = $game_party.all_members.include?($game_actors[act]) &&
  900.              $game_party.all_members.include?(@parent.actor)
  901.       else
  902.         tf = true
  903.       end
  904.       change_color(normal_color, tf)
  905.       draw_text(rect.x + 2, rect.y + line_height * (i + 2), rect.width - 4,
  906.                 line_height, text)
  907.     end
  908.     change_color(normal_color)
  909.   end
  910.  
  911.   def update_padding_bottom
  912.   end
  913. end
  914.  
  915. ##------
  916. ## REGEXP and game objects below.
  917. ##------
  918.  
  919. module CP
  920. module REGEXP
  921. module RELATIONSHIP
  922.   ##             $1 Type                         $2 Op. $3 1. $4 .1  $5 %  $6 stat
  923.   STAT_MODIF_2  = /(relationship|friends|lovers)\[(\+|-)(\d+)(\.\d+)?(%?) (.{3})\]/i
  924.   EXTRA_MODIF_2 = /(relationship|friends|lovers)\[(skill|weapon|armor|armour) (\d+)\]/i
  925.   FOR_ACTOR_2   = /for (actor|level)\[([\d, ]+)\]/i
  926.   FOR_LEVEL_2   = /for (level)\[(\d+)(\+|-)?(\d*)\]/i
  927.   CONSTANT1_2   = /<relationship constant>/i
  928.   CONSTANT2_2   = /<\/relationship constant>/i
  929.   PARTY1_2      = /<relationship party>/i
  930.   PARTY2_2      = /<\/relationship party>/i
  931.   GENDER_2      = /gender\[(male|female)]/i
  932. end
  933. end
  934. end
  935.  
  936. class RPG::Actor < RPG::BaseItem
  937.   include CP::REGEXP::RELATIONSHIP
  938.  
  939.   def relationship_features
  940.     create_reship_features if @relationship_features.nil?
  941.     return @relationship_features
  942.   end
  943.  
  944.   def gender
  945.     create_reship_features if @gender_base.nil?
  946.     return @gender_base
  947.   end
  948.  
  949.   def create_reship_features
  950.     @relationship_features = {:battle=>[], :party=>[], :game=>[]}
  951.     @gender_base = :male
  952.     type = :battle
  953.     self.note.split(/[\r\n]+/i).each do |line|
  954.       @reyash = nil
  955.       case line
  956.       when STAT_MODIF_2
  957.         n = $3.to_f + $4.to_f
  958.         fti = CP::Features.get_feature($6.to_s, $5.to_s)
  959.         if [21, 23].include?(fti[0])
  960.           n = $2.to_s == '-' ? (100.0 - n) / 100.0 :
  961.               $2.to_s == '+' ? (n + 100.0) / 100.0 : n
  962.         elsif fti[0] == 22
  963.           n = $2.to_s == '-' ? -n / 100.0 :
  964.               $2.to_s == '+' ? n / 100.0 : n
  965.         else
  966.           n *= -1 if $2.to_s == '-'
  967.         end
  968.         @reyash = [:stat,     n,       $5.to_s, $6.to_s, $1.to_sym]
  969.         ext = {:actor => [], :level => "all"}
  970.       when EXTRA_MODIF_2
  971.         @reyash = [$2.to_sym, $3.to_i, nil,     nil,     $1.to_sym]
  972.         ext = {:actor => [], :level => "0+"}
  973.       when CONSTANT1_2
  974.         type = :game if type == :battle
  975.       when CONSTANT2_2
  976.         type = :battle if type == :game
  977.       when PARTY1_2
  978.         type = :party if type == :battle
  979.       when PARTY2_2
  980.         type = :battle if type == :party
  981.       when GENDER_2
  982.         @gender_base = $1.to_sym
  983.         next
  984.       end
  985.       next unless @reyash
  986.       if line =~ FOR_ACTOR_2
  987.         ext[$1.to_sym] = $2.to_s.delete(' ').split(/,/).collect {|i| i.to_i}
  988.       end
  989.       if line =~ FOR_LEVEL_2
  990.         ext[$1.to_sym] = "#{$2.to_s}#{$3.to_s}#{$4.to_s}"
  991.       end
  992.       @reyash.push(ext)
  993.       @relationship_features[type].push(@reyash)
  994.     end
  995.   end
  996. end
  997.  
  998.  
  999. ###--------------------------------------------------------------------------###
  1000. #  End of script.                                                              #
  1001. ###--------------------------------------------------------------------------###
RAW Paste Data