[XP] Blizz-ABS Controller for RMX-OS

Started by Blizzard, January 17, 2010, 05:02:36 pm

Previous topic - Next topic

Blizzard

January 17, 2010, 05:02:36 pm Last Edit: March 23, 2019, 11:34:51 am by Blizzard
Blizz-ABS Controller for RMX-OS
Authors: Blizzard
Version: 3.02
Type: RMX-OS Plugin
Key Term: RMX-OS Plugin



Introduction

This script allows the proper usage of Blizz-ABS in combination with RMX-OS. It will allow the RMX-OS Server to assign a client the role of the processor (Global Master) and allow global processing Blizz-ABS AI behavior.

This script is to be distributed under the same terms and conditions like the scripts it was created for: RMX-OS.


Features


  • sets up all save data related to Blizz-ABS
  • allows proper display of other players when using Blizz-ABS
  • implementation of global master controller for Blizz-ABS processing
  • party system with shared EXP / gold
  • PvP



Screenshots

N/A for this sort of script


Demo

N/A


Script

Just make a new script above main and paste this code into it.
Spoiler: ShowHide

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Blizz-ABS Controller for RMX-OS by Blizzard
# Version: 3.02
# Type: RMX-OS Add-on
# Date: 15.2.2010
# Date v1.01: 16.2.2010
# Date v1.02: 23.4.2010
# Date v1.1: 5.12.2010
# Date v1.19: 22.1.2011
# Date v1.2: 25.1.2011
# Date v1.3: 3.2.2011
# Date v1.31: 11.2.2011
# Date v1.32: 11.2.2011
# Date v1.33: 4.3.2011
# Date v1.34: 6.3.2011
# Date v1.4: 9.3.2011
# Date v1.5: 22.6.2012
# Date v1.51: 29.3.2013
# Date v1.52: 6.4.2013
# Date v2.0: 12.6.2013
# Date v2.01: 25.8.2013
# Date v2.1: 23.2.2014
# Date v2.2: 24.2.2014
# Date v3.0: 27.2.2014
# Date v3.01: 3.3.2014
# Date v3.02: 22.5.2014
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
#  This script is to be distributed under the same terms and conditions like
#  the scripts it was created for: RMX-OS and Blizz-ABS.
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# - Special Thanks to Ryex for providing the basecode for the fix for the
#   controls conflict between Blizz-ABS and RMX-OS.
#
# Information:
#
#   This script must be placed below RMX-OS and Blizz-ABS. It requires RMX-OS
#   and Blizz-ABS to work properly. This script will allow the RMX-OS Server to
#   assign a client the role of the processor (Global Master) and allow global
#   processing Blizz-ABS AI behavior.
#   
#   
# What is different:
#   
#   - Map actor data will not be stored completely. Special states and effects
#     that are related to Blizz-ABS (i.e. the data regarding the charging
#     state) are not being saved.
#   - RMX-OS was not intended to have Blizz-ABS allies! Players will not see
#     other players' allies on the map if you add them and you are risking data
#     corruption during saving! The same goes for summons!
#   - Alignment groups are available, but dynamic change of alignment groups
#     is mostly disabled for convenience.
#   - Target selection is disabled. Every skill that has target selection will
#     be executed immediately. If a selection skill targets only one target, a
#     random target from all available targets will be chosen. Generally you
#     should avoid single-target selection skills and items.
#   - ABSEAL is disabled.
#   - Processing takes place only on the Global Master client that is assigned
#     dynamically by the server.
#   - Killed enemy events that are set on Death trigger are run only on the
#     Global Master client. It is recommended that killed enemies trigger
#     global switches that run common events. For that you need a plugin for
#     RMX-OS that allows you to have global switches.
#   - Item / Gold Drops are disabled. The actor who killed the enemy will get
#     the item reward. EXP and gold rewards are shared among party members
#     where each party member adds a specific amount to the gained EXP.
#     Remember that items can be traded so a shared item reward is unnecessary.
#   - Some more extensive eventing features are disabled, might not work right
#     or have not been tested. (e.g. check of last attacker, check of last
#     action, multi-event-body enemies, various knockback modes, etc.)
#   
#   
# Notes:
#   
#   - Keep in mind that adding and/or removing this script will corrupt the
#     save data in the RMX-OS SQL database.
#   - You shouldn't have any non-map scenes during the battle. This can disrupt
#     the normal game flow. You should get a custom menu system on the map for
#     the menu system specifically.
#   - You should set the PING_TIMEOUT option in RMX-OS to 1.
#   - There is a problem in PvP in Blizz-ABS versions lower than 2.86.
#     Sometimes online players will attack themselves including other players.
#     To fix this problem, get Blizz-ABS v2.86.
#   
#   
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

if !$BlizzABS || BlizzABS::VERSION < 2.87
  raise 'ERROR: The "Blizz-ABS Controller" requires Blizz-ABS 2.87 or higher.'
elsif !defined?(RMXOS) || RMXOS::VERSION < 2.04
  raise 'ERROR: The "Blizz-ABS Controller" requires RMX-OS 2.04 or higher.'
end

$blizzabs_rmxos = 3.02

#==============================================================================
# module RMXOS
#==============================================================================
 
module RMXOS
 
  #============================================================================
  # module RMXOS::Options
  #============================================================================
 
  module Options
 
    #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    # START Configuration
    #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
   
    # PvP active or not
    PVP = false
    # how much percent to the total EXP gain does each party member add
    PARTY_EXP_BONUS = 20
    # how much percent to the total gold gain does each party member add
    PARTY_GOLD_BONUS = 20
    # this should be only changed if necessary!
    BATTLER_VARIABLES = ['@battler|@hp', '@battler|@sp',
        '@battler|@states', '@battler|@states_turn', '@battler|@state_time']
    ACTOR_VARIABLES = ['@battler|@actor_id', '@battler|@class_id',
        '@battler|@level', '@battler|@maxhp_plus', '@battler|@maxsp_plus',
        '@battler|@str_plus', '@battler|@dex_plus', '@battler|@agi_plus',
        '@battler|@int_plus', '@battler|@skills', '@battler|@weapon_id',
        '@battler|@armor1_id', '@battler|@armor2_id', '@battler|@armor4_id',
        '@battler|@armor3_id', '@battler|@character_name',
        '@battler|@character_hue']
    ENEMY_VARIABLES = ['@battler|@enemy_id', '@battler|@immortal',
        '@ai|@altered_alignment', '@ai|@aggressive', '@ai|@view_range',
        '@ai|@hearing_range_ratio', '@ai|@positive', '@ai|@negative',
        '@ai|@neutral']
    DAMAGE_VARIABLES = ['@battler|@damage', '@battler|@hpdamage',
        '@battler|@spdamage', '@battler|@critical', '@battler|@states',
        '@battler|@states', '@battler|@states_turn', '@animation_id',
        '@attacked']
   
    #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    # END Configuration
    #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
    # because Game_Player was redefined
    old_Game_Player = SAVE_DATA.keys.find_all {|key|
        key.is_a?(Class) && key.name == 'Game_Player'}[0]
    SAVE_DATA[Game_Player] = SAVE_DATA[old_Game_Player]
    SAVE_DATA.delete(old_Game_Player)
    # other additional save data
    SAVE_DATA[Map_Actor] = SAVE_DATA[Game_Player].clone
    SAVE_DATA[Game_System].concat(['@hud', '@hotkeys', '@minimap',
        '@attack_button', '@defend_button', '@skill_button', '@item_button',
        '@select_button', '@hud_button', '@hotkey_button', '@minimap_button',
        '@turn_button', '@running_button', '@sneaking_button', '@jumping_button',
        '@caterpillar', '@caterpillar_active'])
    SAVE_DATA[Game_Actor].concat(['@skill', '@item', '@skill_hotkeys',
        '@item_hotkeys', '@old_level', '@offensive', '@aggressive',
        '@force_offensive', '@force_aggressive', '@state_time', '@triggers'])
    SAVE_DATA[BlizzABS::Trigger] = ['@activator', '@condition', '@comparator',
        '@value', '@action_type', '@action_data', '@target']
    # new creation data
    CREATION_DATA[Map_Actor] = '0'
 
  end
 
  #============================================================================
  # module RMXOS::Data
  #============================================================================
 
  module Data
   
    PartyAlreadyMember = 'Player is already a member of your party.'
    PartyNone          = 'You are not in a party.'
    PartyNotLeader     = 'You are not the leader of the party.'
    PartyNotMember     = 'Player is not a member of your party.'
    PartyInfo          = 'Party Leader: LEADER; Members: MEMBERS'
   
    ColorParty = Color.new(0xFF, 0x7F, 0x1F)
   
  end

  #============================================================================
  # module RMXOS::Documentation
  #============================================================================
 
  module Documentation
   
    # Party commands
    PARAMETERS['party']   = 'USERNAME'
    PARAMETERS['premove'] = 'USERNAME'
    PARAMETERS['pleave']  = 'none'
    PARAMETERS['pmsg']    = 'MESSAGE'
    PARAMETERS['pinfo']   = 'none'
   
    DESCRIPTIONS['party']   = 'Invites a player into your party.'
    DESCRIPTIONS['premove'] = 'Removes a player from your party.'
    DESCRIPTIONS['pleave']  = 'Leaves the current party. Disbands the party if you are the party leader.'
    DESCRIPTIONS['pmsg']    = 'Sends a message to all party members.'
    DESCRIPTIONS['pinfo']   = 'Displays information about your party.'
   
  end
 
  def self.change_keys
    controls = [Input::LEFT, Input::RIGHT, Input::UP, Input::DOWN, Input::B,
        Input::C]
    keys = []
    replacements = ['Arrow Left', 'Arrow Right', 'Arrow Up', 'Arrow Down',
        'Esc', 'Enter']
    controls.each_index {|i|
        keys[i] = controls[i].clone
        controls[i].clear
        controls[i].push(Input::Key[replacements[i]])
    }
    return keys
  end
 
  def self.restore_keys(keys)
    controls = [Input::LEFT, Input::RIGHT, Input::UP, Input::DOWN, Input::B,
        Input::C]
    controls.each_index {|i|
        controls[i].clear
        keys[i].each {|key| controls[i].push(key)}
    }
  end
 
end

#==============================================================================
# module BlizzABS
#==============================================================================
 
module BlizzABS
 
  #============================================================================
  # module BlizzABS::Config
  #============================================================================
 
  module Config
   
    ABSEAL_FACTOR = 485
    GOLD_DROP = ''
    ITEM_DROP = false
    CORPSES = false
   
  end
 
  #============================================================================
  # module BlizzABS::Alignments
  #============================================================================
 
  module Alignments
   
    ONLINE_GROUP = 0
    GROUPS.push(ONLINE_GROUP)
    GROUPS.sort!
   
    class << Alignments
      alias enemies_blizzabsrmxos_alias enemies
      alias allies_blizzabsrmxos_alias allies
      alias neutral_blizzabsrmxos_alias neutral
    end
   
    def self.allies(id)
      result = allies_blizzabsrmxos_alias(id)
      case id
      when ONLINE_GROUP
        result = allies_blizzabsrmxos_alias(ACTOR_GROUP).clone
        result |= [ACTOR_GROUP, ONLINE_GROUP]
      when ACTOR_GROUP
        result |= [ONLINE_GROUP]
      end
      return result
    end
   
    def self.enemies(id)
      result = enemies_blizzabsrmxos_alias(id)
      case id
      when ONLINE_GROUP
        result = enemies_blizzabsrmxos_alias(ACTOR_GROUP).clone
        if RMXOS::Options::PVP
          result |= [ACTOR_GROUP, ONLINE_GROUP]
        end
      when ACTOR_GROUP
        result |= [ONLINE_GROUP] if RMXOS::Options::PVP
      when ENEMY_GROUP
        result |= [ONLINE_GROUP]
      end
      return result
    end
   
    def self.neutral(id)
      return (neutral_blizzabsrmxos_alias(id) | [ONLINE_GROUP])
    end
   
  end
 
  #============================================================================
  # BlizzABS::AI::Data_Enemy
  #============================================================================
 
  class AI::Data_Enemy
   
    alias lifeless_blizzabsrmxos_alias? lifeless?
    def lifeless?
      return (!$network.gmaster || lifeless_blizzabsrmxos_alias?)
    end
   
  end

  #============================================================================
  # BlizzABS::Processor
  #============================================================================
 
  class Processor
   
    attr_reader :killed
   
    def update_killed
      deleted_killed = []
      $game_system.killed.each_key {|key|
          $game_system.killed[key] -= 1
          if key.execute
            key.update
          elsif $game_system.killed[key] <= 0
            if !key.ai.lifeless_blizzabsrmxos_alias? &&
                ($game_system.respawn_time > 0 || key.respawn_point != nil)
              if $network.gmaster && !key.respawning
                $network.send_enemy_respawn(key)
                key.respawning = true
              end
            else
              deleted_killed.push(key)
            end
          end}
      deleted_killed.each {|key| $game_system.killed.delete(key)}
    end
   
    alias exp_result_blizzabsrmxos_alias exp_result
    def exp_result(enemy)
      if enemy.last_targeter == $network.user_id ||
          $network.party.include?(enemy.last_targeter)
        return exp_result_blizzabsrmxos_alias(enemy)
      end
      return 0
    end
   
    alias gold_result_blizzabsrmxos_alias gold_result
    def gold_result(enemy)
      if enemy.last_targeter == $network.user_id ||
          $network.party.include?(enemy.last_targeter)
        return gold_result_blizzabsrmxos_alias(enemy)
      end
      return 0
    end
   
    alias additional_result_blizzabsrmxos_alias additional_result
    def additional_result(enemy)
      if enemy.last_targeter == $network.user_id
        return additional_result_blizzabsrmxos_alias(enemy)
      end
    end
   
    alias drop_items_blizzabsrmxos_alias drop_items
    def drop_items(enemy)
      if enemy.last_targeter == $network.user_id
        return drop_items_blizzabsrmxos_alias(enemy)
      end
      return []
    end
   
    alias remove_enemy_blizzabsrmxos_alias remove_enemy
    def remove_enemy(enemy)
      if $network.gmaster
        $network.send_enemy_death(enemy)
        if $game_map.events.has_value?(enemy)
          $game_map.events.delete(enemy.id)
          @killed = {} if @killed == nil
          @killed[enemy.id] = enemy
        end
      end
    end
   
    def delete_enemy(enemy)
      return if enemy.execute || enemy.erased || enemy.body != nil
      enemy.start if enemy.trigger == BlizzABS::CETDeath
      $game_map.events.delete(enemy.id) unless enemy.execute
      if BlizzABS::Config::CORPSES
        if BlizzABS::Config::EMPTY_CORPSES
          drop_event([], enemy.real_x, enemy.real_y, enemy)
        end
      end
      self.add_respawn(enemy)
    end
   
    def add_respawn(enemy)
      tmp = $game_map.respawns.find_all {|event|
          !event.erased && event.respawn_ids != nil &&
          event.respawn_ids.include?(enemy.battler_id)}
      if tmp.size == 0
        time = $game_system.respawn_time
      else
        enemy.respawn_point = tmp[rand(tmp.size)]
        time = enemy.respawn_point.respawn_time
      end
      $game_system.killed[enemy] = time * 40
    end
   
  end
 
  #============================================================================
  # BlizzABS::Controller
  #============================================================================
 
  class Controller
   
    alias update_control_blizzabsrmxos_alias update_control
    def update_control
      update_control_blizzabsrmxos_alias if !$game_temp.chat_active
    end
   
  end
 
  #============================================================================
  # BlizzABS::Controls
  #============================================================================
 
  class Controls
   
    alias update_blizzabsrmxos_alias update
    def update
      update_blizzabsrmxos_alias if !$game_temp.chat_active
    end
   
  end
 
  #============================================================================
  # BlizzABS::Utility
  #============================================================================
 
  class Utility
   
    alias request_damage_sprite_blizzabsrmxos_alias request_damage_sprite
    def request_damage_sprite(char, damage = nil)
      if $network.gmaster
        $network.send_damage_variables(char)
      end
      request_damage_sprite_blizzabsrmxos_alias(char, damage)
    end
   
  end
 
end

$BlizzABS = BlizzABS::Processor.new

#==============================================================================
# RMXOS::Network
#==============================================================================

class RMXOS::Network
 
  attr_reader :gmaster
  attr_reader :party
  attr_reader :partyleader
 
  alias init_blizzabsrmxos_alias initialize
  def initialize
    init_blizzabsrmxos_alias
    @gmaster = false
    self.party_reset
  end
 
  alias reset_blizzabsrmxos_alias reset
  def reset
    self.party_reset
    reset_blizzabsrmxos_alias
  end
 
  def party_reset
    @partyleader = ''
    @party = []
  end
 
  alias clear_map_players_blizzabsrmxos_alias clear_map_players
  def clear_map_players
    clear_map_players_blizzabsrmxos_alias
    $game_system.killed.clear
  end
 
  alias check_game_blizzabsrmxos_alias check_game
  def check_game(message)
    case message
    when /\AABSGMA\Z/ # global master activate
      @gmaster = true
      return true
    when /\AABSGMD\Z/ # global master deactivate
      @gmaster = false
      return true
    when /\AABSMDR\Z/ # map data request
      $game_map.battlers.each {|battler| battler.send_exchange_variables}
      return true
    when /\AABSMEE\t(.+)\t(.+)/ # exchange variables for enemies
      id = $1.to_i
      variables = eval($2)
      if $game_map != nil && $game_map.events != nil &&
          $game_map.events.has_key?(id)
        $game_map.events[id].evaluate(variables)
      end
      return true
    when /\AABSMED\t(.+)/ # enemy is dead
      id = $1.to_i
      if $game_map.events.has_key?(id)
        enemy = $game_map.events[id]
        enemy.last_targeter = nil
        $BlizzABS.delete_enemy(enemy)
      end
    when /\AABSBED\t(.+)\t(.+)/ # broadcast enemy death
      id = $1.to_i
      targeter_id = $2.to_i
      if $BlizzABS.killed != nil && $BlizzABS.killed.has_key?(id)
        enemy = $BlizzABS.killed[id]
        $BlizzABS.killed.delete(id)
        $game_map.events[id] = enemy
      end
      if $game_map.events.has_key?(id)
        enemy = $game_map.events[id]
        enemy.last_targeter = (targeter_id != 0 ? targeter_id : nil)
        $BlizzABS.remove_enemy_blizzabsrmxos_alias(enemy)
        $BlizzABS.add_respawn(enemy)
      end
    when /\AABSBER\t(.+)/ # broadcast enemy respawn
      id = $1.to_i
      $game_system.killed.keys.each {|enemy|
        if enemy.id == id
          $game_map.events[id] = $BlizzABS.respawn_enemy(enemy)
          $game_system.killed.delete(enemy)
          break
        end
      }
      return true
    when /\AABSADM\t(.+)\t(.+)/ # actor damage variables
      id = $1.to_i
      variables = eval($2)
      if @user_id == id
        $game_player.evaluate(variables)
        $game_player.damage_effect
        $game_player.send_exchange_variables
      elsif @players.has_key?(id)
        @players[id].evaluate(variables)
        @players[id].damage_effect
      end
      return true
    when /\AABSEDM\t(.+)\t(.+)/ # enemy damage variables
      id = $1.to_i
      if $game_map != nil && $game_map.events != nil &&
          $game_map.events.has_key?(id)
        variables = eval($2)
        $game_map.events[id].evaluate(variables)
        $game_map.events[id].damage_effect
      end
      return true
    when /\AABSACM/ # attack consume
      $game_player.attack_consumption
      return true
    when /\AABSSCM\t(.+)/ # skill consume
      $game_player.skill_consumption($data_skills[$1.to_i])
      return true
    when /\AABSICM\t(.+)/ # item consume
      $game_player.item_consumption($data_items[$1.to_i])
      return true
    when /\AABSPIN\t(.+)\t(.+)/ # party invite
      @partyleader = $1
      @party = eval($2).compact.sort
      @party.delete(@username)
      return true
    when /\AABSPRM\t(.+)/ # party remove
      @party.delete($1)
      return true
    when /\AABSPRE\Z/ # party reset
      self.party_reset
      return true
    end
    return check_game_blizzabsrmxos_alias(message)
  end
 
  alias check_normal_commands_blizzabsrmxos_alias check_normal_commands
  def check_normal_commands(message)
    case message
    when /\A\/party (\S+)\Z/
      command_party_invite($1)
      return true
    when /\A\/premove (\S+)\Z/
      command_party_remove($1)
      return true
    when /\A\/pleave\Z/
      command_party_leave
      return true
    when /\A\/pmsg (\S{1}.*)/
      command_party_chat($1)
      return true
    when /\A\/pinfo\Z/
      command_party_info
      return true
    end
    return check_normal_commands_blizzabsrmxos_alias(message)
  end
 
  def partyleader?
    return (self.in_party? && @partyleader == @username)
  end
 
  def in_party?
    return (@partyleader != '')
  end
   
  def check_partyleader_action
    if !self.partyleader?
      self.add_error(RMXOS::Data::PartyNotLeader)
      return false
    end
    return true
  end
   
  def check_party_action
    if !self.in_party?
      self.add_error(RMXOS::Data::PartyNone)
      return false
    end
    return true
  end
   
  def command_party_invite(username)
    if !self.in_party? || self.check_partyleader_action
      if @party.include?(username)
        self.add_error(RMXOS::Data::PartyAlreadyMember)
      else
        self.send('ABSPIN', username)
      end
    end
  end
 
  def command_party_remove(username)
    if self.check_partyleader_action
      if !@party.include?(username)
        self.add_error(RMXOS::Data::PartyNotMember)
      else
        self.send('ABSPRM', username)
      end
    end
  end
 
  def command_party_leave
    if self.check_party_action
      self.send('ABSPLE')
    end
  end
 
  def command_party_info
    if self.check_party_action
      text = RMXOS::Data::PartyInfo.sub('LEADER') {@partyleader}
      text = text.sub('MEMBERS') {(@party - [@partyleader]).join(', ')}
      self.add_info(text)
    end
  end
   
  def command_party_chat(message)
    if self.check_party_action
      send_chat_message(message, RMXOS::Data::ColorParty, 'ABSPME')
    end
  end
 
  def try_deactivate_gmaster
    self.send('ABSGMD')
    @gmaster = false
  end
 
  def send_enemy_exchange_variables(id, variables)
    self.send('ABSMEE', id, variables.inspect)
  end
 
  def send_attack(char)
    type = nil
    if char.is_a?(Map_Actor)
      id = (char == $game_player ? @user_id : char.user_id)
      type = 'ABSAAT'
    elsif char.is_a?(Map_Enemy)
      id = char.id
      type = 'ABSEAT'
    end
    $network.send(type, id) if type != nil
  end
 
  def send_attack_consume(user_id)
    self.send('ABSACM', user_id)
  end
   
  def send_skill_consume(user_id, skill_id)
    self.send('ABSSCM', user_id, skill_id)
  end
 
  def send_item_consume(user_id, item_id)
    self.send('ABSICM', user_id, item_id)
  end
 
  def send_damage_variables(char)
    type = nil
    variables = char.get_exchange_variables(RMXOS::Options::DAMAGE_VARIABLES)
    if char.is_a?(Map_Actor)
      id = (char == $game_player ? @user_id : char.user_id)
      type = 'ABSADM'
    elsif char.is_a?(Map_Enemy)
      id = char.id
      type = 'ABSEDM'
    end
    $network.send(type, id, variables.inspect) if type != nil
  end
 
  def send_enemy_death(enemy)
    return if enemy.last_targeter == nil
    if enemy.last_targeter == $game_player
      id = $network.user_id
    elsif enemy.last_targeter.is_a?(Map_OnlineBattler)
      id = enemy.last_targeter.user_id
    end
    self.send('ABSBED', enemy.id, id)
  end
 
  def send_enemy_respawn(enemy)
    self.send('ABSBER', enemy.id)
  end
 
end

#==============================================================================
# Game_Enemy
#==============================================================================

class Game_Enemy
 
  alias exp_blizzabs_rmxos_alias exp
  def exp
    result = exp_blizzabs_rmxos_alias
    bonus = $network.party.size * RMXOS::Options::PARTY_EXP_BONUS
    return (result * (100 + bonus) / 100 / ($network.party.size + 1))
  end
 
  alias gold_blizzabs_rmxos_alias gold
  def gold
    result = gold_blizzabs_rmxos_alias
    bonus = $network.party.size * RMXOS::Options::PARTY_GOLD_BONUS
    return (result * (100 + bonus) / 100 / ($network.party.size + 1))
  end
 
end

#==============================================================================
# Map_Battler
#==============================================================================

class Map_Battler
 
  attr_accessor :last_targeter
 
  alias update_blizzabsrmxos2_alias update
  def update
    @blinking = 0
    update_blizzabsrmxos2_alias
  end
 
  def get_exchange_variable_names
    return (RMXOS::Options::EXCHANGE_VARIABLES |
        RMXOS::Options::BATTLER_VARIABLES)
  end
 
  def in_screen?
    return true
  end
         
  def damage_effect
    if self.damage_display?
      @battler.hp -= @battler.hpdamage
      @battler.sp -= @battler.spdamage
      user_damage_display
      @battler.hpdamage, @battler.spdamage, @battler.damage = 0, 0, nil
      return true
    end
    return false
  end
 
end

#==============================================================================
# Map_Actor
#==============================================================================

class Map_Actor

  alias update_blizzabsrmxos_alias update
  def update
    @blinking = 0 # disables blinking
    update_blizzabsrmxos_alias
  end
 
  def get_exchange_variable_names
    return (super | RMXOS::Options::ACTOR_VARIABLES)
  end
 
  def update_exchange_variables
    if self == $game_player
      changed = self.get_exchange_variables_changes
      if changed.size > 0
        self.send_exchange_variables(changed)
        self.store_exchange_variables(changed)
      end
    end
  end
 
  def send_exchange_variables(variables = nil)
    variables = super(variables)
    $network.send_exchange_variables(variables) if self == $game_player
    return variables
  end
 
  alias attack_effect_blizzabsrmxos_alias attack_effect
  def attack_effect(character, _battler)
    return false if !$network.gmaster
    return attack_effect_blizzabsrmxos_alias(character, _battler)
  end
 
  alias skill_effect_blizzabsrmxos_alias skill_effect
  def skill_effect(character, _battler, skill)
    return false if !$network.gmaster
    return skill_effect_blizzabsrmxos_alias(character, _battler, skill)
  end
 
  alias item_effect_blizzabsrmxos_alias item_effect
  def item_effect(character, _battler, item)
    return false if !$network.gmaster
    return item_effect_blizzabsrmxos_alias(character, _battler, item)
  end
 
  alias use_attack_blizzabsrmxos_alias use_attack
  def use_attack
    result = use_attack_blizzabsrmxos_alias
    if self == $game_player
      variables = {}
      variables['@ai|@act|@kind'] = BlizzABS::ACTAttack
      variables['@ai|@act|@type'] = BlizzABS::ATTACK
      self.send_exchange_variables(variables)
    end
    return result
  end
 
  alias use_skill_blizzabsrmxos_alias use_skill
  def use_skill(skill, forced = false)
    result = use_skill_blizzabsrmxos_alias(skill, forced)
    if self == $game_player
      variables = {}
      variables['@ai|@act|@kind'] = BlizzABS::ACTSkill
      variables['@ai|@act|@type'] = BlizzABS::SKILL
      variables['@ai|@act|@id'] = skill.id
      self.send_exchange_variables(variables)
    end
    return result
  end
 
  alias use_item_blizzabsrmxos_alias use_item
  def use_item(item, forced = false)
    result = use_item_blizzabsrmxos_alias(item, forced)
    if self == $game_player
      variables = {}
      variables['@ai|@act|@kind'] = BlizzABS::ACTItem
      variables['@ai|@act|@type'] = BlizzABS::ITEM
      variables['@ai|@act|@id'] = item.id
      self.send_exchange_variables(variables)
    end
    return result
  end
 
end

#==============================================================================
# Map_Enemy
#==============================================================================

class Map_Enemy
 
  attr_accessor :respawning
 
  def get_exchange_variable_names
    return (super | RMXOS::Options::ENEMY_VARIABLES)
  end
 
  def update_exchange_variables
    return if !$network.gmaster
    changed = self.get_exchange_variables_changes
    if changed.size > 0
      self.send_exchange_variables(changed)
      self.store_exchange_variables(changed)
    end
  end
 
  def send_exchange_variables(variables = nil)
    variables = super(variables)
    $network.send_enemy_exchange_variables(self.id, variables)
    return variables
  end
 
  alias attack_effect_blizzabsrmxos_alias attack_effect
  def attack_effect(character, _battler)
    return false if !$network.gmaster
    @last_targeter = character
    return attack_effect_blizzabsrmxos_alias(character, _battler)
  end
 
  alias skill_effect_blizzabsrmxos_alias skill_effect
  def skill_effect(character, _battler, skill)
    return false if !$network.gmaster
    @last_targeter = character
    return skill_effect_blizzabsrmxos_alias(character, _battler, skill)
  end
 
  alias item_effect_blizzabsrmxos_alias item_effect
  def item_effect(character, _battler, item)
    return false if !$network.gmaster
    @last_targeter = character
    return item_effect_blizzabsrmxos_alias(character, _battler, item)
  end
 
  alias use_attack_blizzabsrmxos_alias use_attack
  def use_attack
    result = use_attack_blizzabsrmxos_alias
    if result && $network.gmaster
      variables = {}
      variables['@ai|@act|@kind'] = BlizzABS::ACTAttack
      variables['@ai|@act|@type'] = BlizzABS::ATTACK
      self.send_exchange_variables(variables)
    end
    return result
  end
 
  alias use_skill_blizzabsrmxos_alias use_skill
  def use_skill(skill, forced = false)
    result = use_skill_blizzabsrmxos_alias(skill, forced)
    if result && $network.gmaster
      variables = {}
      variables['@ai|@act|@kind'] = BlizzABS::ACTSkill
      variables['@ai|@act|@type'] = BlizzABS::SKILL
      variables['@ai|@act|@id'] = skill.id
      self.send_exchange_variables(variables)
    end
    return result
  end
 
end

#==============================================================================
# Map_OnlineBattler
#==============================================================================

class Map_OnlineBattler < Map_Actor
 
  attr_reader   :user_id
  attr_reader   :username
  attr_reader   :usergroup
  attr_reader   :guildname
  attr_accessor :map_id
 
  def initialize
    super(0)
    @battler = Game_Actor.new(1)
    @cindex = nil
    @locked = true
    @ai.setup_group(BlizzABS::Alignments::ONLINE_GROUP)
    @normal_speed = BlizzABS::Config::NORMAL_SPEED
    refresh
  end
 
  def update
    super
    self.moving? ? @stop_count = 0 : @stop_count += 1
  end
 
  def check_action
    return if !self.valid? || !@ai.act.valid?
    battlers = ($game_map.battlers + $BlizzABS.battlers).find_all {|b|
        b.valid?}
    battlers.compact!
    allies = []
    enemies = []
    confused = (self.restriction == 3)
    negative, positive = @ai.negative, @ai.positive
    negative, positive = positive, negative if confused
    unless @ai.act.basic?
      allies = battlers.find_all {|b| positive.include?(b.ai.group)}
    end
    enemies = battlers.find_all {|b| negative.include?(b.ai.group)}
    enemies -= [self] if !confused
    $BlizzABS.AI.normal_action(self, allies, enemies, @ai.act.basic?,
        @ai.act.type, 0xFFFF, 0xFFFF, @ai.act.id, @ai.act.skill?,
        confused, true)
    @ai.act.delay = 0 if !@ai.act.defend?
    self.reset_action
  end
 
  def can_act?
    return false
  end

  def process_ai?
    return false
  end
 
  def set_user_data(user_id, username, usergroup, guildname)
    @user_id = user_id
    @username = username
    @usergroup = usergroup
    @guildname = guildname
    refresh
  end
 
  def evaluate(variables)
    super(variables)
    refresh
  end
 
  def battler(override = false)
    return @battler
  end
 
  def send_exchange_variables(variables = nil)
  end
 
  # needed because of problematic polymorphism in Ruby when alias is involved
  def attack_effect(character, _battler)
    return super
  end
 
  # needed because of problematic polymorphism in Ruby when alias is involved
  def use_attack
    return super
  end
 
  # needed because of problematic polymorphism in Ruby when alias is involved
  def skill_effect(character, _battler, skill)
    return super
  end
 
  # needed because of problematic polymorphism in Ruby when alias is involved
  def use_skill(skill, forced = false)
    return super
  end
 
  # needed because of problematic polymorphism in Ruby when alias is involved
  def item_effect(character, _battler, item)
    return super
  end
 
  # needed because of problematic polymorphism in Ruby when alias is involved
  def use_item(item, forced = false)
    return super
  end
 
  def attack_consumption
    $network.send_attack_consume(@user_id)
  end
 
  def skill_consumption(skill)
    $network.send_skill_consume(@user_id, skill.id)
  end
 
  def item_consumption(item)
    $network.send_item_consume(@user_id, item.id)
  end
 
  def update_ci(ind = nil)
  end
 
  def update_buffer(move)
  end
 
  def turn_toward(character)
  end
 
  def moveto(x, y)
    pix = $BlizzABS.pixel
    super(x / pix, y / pix)
  end
 
end

Game_OnlineCharacter = Map_OnlineBattler

#==============================================================================
# Game_Map
#==============================================================================

class Game_Map
 
  alias battlers_blizzabsrmxos_alias battlers
  def battlers
    return (battlers_blizzabsrmxos_alias | $network.map_players.values)
  end
 
end

#==============================================================================
# Frame_Text
#==============================================================================

class Frame_Text
 
  alias update_input_blizzabsrmxos2_alias update_input
  def update_input
    keys = RMXOS.change_keys
    update_input_blizzabsrmxos2_alias
    RMXOS.restore_keys(keys)
  end
 
end

#==============================================================================
# Frame_Chat
#==============================================================================

class Frame_Chat
 
  alias update_blizzabsrmxos_alias update
  def update
    keys = RMXOS.change_keys
    update_blizzabsrmxos_alias
    RMXOS.restore_keys(keys)
  end
 
end

#==============================================================================
# Frame_ChatInput
#==============================================================================

class Frame_ChatInput
 
  alias update_input_blizzabsrmxos_alias update_input
  def update_input
    keys = RMXOS.change_keys
    update_input_blizzabsrmxos_alias
    RMXOS.restore_keys(keys)
  end
 
end

#==============================================================================
# Scene_Login
#==============================================================================

class Scene_Login
 
  alias update_blizzabsrmxos_alias update
  def update
    keys = RMXOS.change_keys
    update_blizzabsrmxos_alias
    RMXOS.restore_keys(keys)
  end
 
end

#==============================================================================
# Scene_Register
#==============================================================================

class Scene_Register
 
  alias update_blizzabsrmxos_alias update
  def update
    keys = RMXOS.change_keys
    update_blizzabsrmxos_alias
    RMXOS.restore_keys(keys)
  end
 
end

#==============================================================================
# Scene_Map
#==============================================================================

class Scene_Map
 
  alias main_blizzabsrmxos_alias main
  def main
    main_blizzabsrmxos_alias
    $network.try_deactivate_gmaster
  end
 
  alias transfer_player_blizzabsrmxos_alias transfer_player
  def transfer_player
    if $game_temp.player_new_map_id != $game_map.map_id
      $network.try_deactivate_gmaster
    end
    transfer_player_blizzabsrmxos_alias
  end
 
  def initialize_selection
  end
 
  def process_selection
    object, r, type, sprites = $game_temp.select_data
    if $tons_version != nil && object.is_a?(RPG::Skill) &&
        ($tons_version >= 6.02 && $game_system.TARGET_EM_ALL &&
        FULL_TARGET_IDS.include?(object.id))
      targets = []
      sprites.each {|sprite| targets.push(sprite.character)}
    else
      targets = [sprites[rand(sprites.size)].character]
    end
    return targets
  end
 
  def execute_selection(targets)
    if targets.size > 0
      $game_player.ai.target = targets[0]
      case $game_temp.select_data[0]
      when RPG::Skill then $game_player.use_skill($game_temp.select_data[0])
      when RPG::Item then $game_player.use_item($game_temp.select_data[0])
      end
    end
    $game_temp.select_data = nil
  end
 
  alias call_menu_blizzardrmxos_alias call_menu
  def call_menu
    if $game_temp.chat_active
      $game_temp.menu_calling = false
      $game_temp.menu_beep = false
      return
    end
    call_menu_blizzardrmxos_alias
  end
 
  alias check_huds_blizzardrmxos_alias check_huds
  def check_huds
    minimap_button = $game_system.minimap_button
    hotkey_button = $game_system.hotkey_button
    hud_button = $game_system.hud_button
    if $game_temp.chat_active
      $game_system.minimap_button = false
      $game_system.hotkey_button = false
      $game_system.hud_button = false
    end
    check_huds_blizzardrmxos_alias
    $game_system.minimap_button = minimap_button
    $game_system.hotkey_button = hotkey_button
    $game_system.hud_button = hud_button
  end
 
  alias update_hotkeys_blizzardrmxos_alias update_hotkeys
  def update_hotkeys
    update_hotkeys_blizzardrmxos_alias if !$game_temp.chat_active
  end
 
end


Make a new file with an .rb extension in the Extensions folder of RMX-OS and copy-paste this script into it.
Spoiler: ShowHide

module RMXOS
 
  def self.load_current_extension
    return BlizzABS
  end
 
  module Data
    GlobalMasterActivate_CLIENT_MAPID = 'Client \'CLIENT\' activate G-Master for map \'MAPID\'.'
    GlobalMasterDeactivate_CLIENT_MAPID = 'Client \'CLIENT\' deactivate G-Master for map \'MAPID\'.'
    GlobalMasterRelease_MAPID = 'Map \'MAPID\' has been released.'
    PartyDisbanded = 'The party has been disbanded.'
    PartyInvitation_PLAYER = '\'PLAYER\' has invited you to join a party.'
    PartyInvited_PLAYER = 'You have invited \'PLAYER\' to join your party.'
    PartyJoin_PLAYER = 'You have joined the party of \'PLAYER\'.'
    PartyJoined_PLAYER = '\'PLAYER\' has joined the party.'
    PartyNoJoin = 'You have not joined the party.'
    PartyNoJoinPlayer_PLAYER = '\'PLAYER\' has not accepted the party invitation.'
    PartyRemoved = 'You have left the party.'
    PartyRemoved_PLAYER = '\'PLAYER\' has left the party.'
  end
 
  module Error
    PartyFull = 'Your party is already full.'
    PartyAlready_PLAYER = '\'PLAYER\' is already in a party.'
  end
 
end

#==========================================================================
# module BlizzABS
#==========================================================================

module BlizzABS
 
  VERSION = 3.02
  RMXOS_VERSION = 2.04
  SERVER_THREAD = true
  IDENTIFIER = 'Blizz-ABS'
 
  # START Configuration
  MAX_ONLINE_PARTY = 4
  GMASTER_TIMEOUT = 5 # after how much time an inactive time global master client should be released (you should set the PING_TIMEOUT value in RMX-OS to 1!)
  SERVER_DISPLAY = false # show log in command prompt screen
  LOG_FILENAME = 'logs/blizzabs.log' # leave empty if no log file should be created
  DELETE_LOG_ON_START = true
  # END Configuration
 
  def self.initialize
    @mutex = Mutex.new
    @client_times = {}
    @gmasters = {}
    @capable_clients = {}
    @battlers = {}
    @dead = {}
    if LOG_FILENAME != ''
      File.delete(LOG_FILENAME) if DELETE_LOG_ON_START && FileTest.exist?(LOG_FILENAME)
      RMXOS::Logs[IDENTIFIER] = LOG_FILENAME
    end
  end
 
  def self.mutex
    return @mutex
  end
 
  def self.main
    while RMXOS.server.running
      @mutex.synchronize {
        self.server_update
      }
      sleep(0.01)
    end
  end
 
  def self.server_update
    time = Time.now
    logged_in_clients = RMXOS.clients.get
    old_clients = @client_times.keys - logged_in_clients
    old_clients.each {|client|
      @client_times.delete(client)
      @capable_clients.delete(@capable_clients.key(client))
      self.try_deactivate_gmaster(client)
      if client.player.partyleader != ''
        client.action.execute_party_remove(client.player.username, client.player.partyleader)
      end
    }
    new_clients = logged_in_clients - @client_times.keys
    new_clients.each {|client| @client_times[client] = time}
    @capable_clients.keys.each {|key|
      if time - @client_times[@capable_clients[key]] > GMASTER_TIMEOUT
        client = @capable_clients[key]
        @capable_clients.delete(key)
        self.try_deactivate_gmaster(client)
      end
    }
    (@capable_clients.values - logged_in_clients).each {|client| @capable_clients.delete(@capable_clients.key(client))}
    map_ids = []
    logged_in_clients.each {|client| map_ids.push(client.player.map_id)}
    map_ids |= map_ids # removes duplicates
    (@battlers.keys - map_ids).each {|map_id| @battlers.delete(map_id)}
    (@dead.keys - map_ids).each {|map_id| @dead.delete(map_id)}
    (@gmasters.keys - map_ids).each {|map_id| self.release_map(map_id)}
    (map_ids - @gmasters.keys).each {|map_id| self.try_activate_gmaster(map_id)}
  end
 
  def self.client_update(client)
    case client.message
    when /\AABSGMD\Z/ # deactivate capable global master client
      @capable_clients.delete(client.player.user_id) if @capable_clients.has_key?(client.player.user_id)
      self.try_deactivate_gmaster(client, client.player.map_id) if client == @gmasters[client.player.map_id]
      return true
    when /\APNG\Z/ # client ping
      if client.player.user_id != 0
        @client_times[client] = Time.now
        @capable_clients[client.player.user_id] = client
      end
      return false
    when /\AMEN\t(.+)/ # enter map
      map_id = $1.to_i
      if @battlers.has_key?(map_id)
        @battlers[map_id].each_key {|id|
          client.send('ABSMEE', id, @battlers[map_id][id].get_exchange_variables)
        }
      end
      if @dead.has_key?(map_id)
        @dead[map_id].each {|id| client.send('ABSMED', id)}
      end
      return false
    when /\AABSMEE\t(.+)\t(.+)/ # exchange variables for enemies
      if @gmasters[client.player.map_id] == client
        id = $1.to_i
        variables = eval($2)
        @battlers[client.player.map_id] = {} if !@battlers.has_key?(client.player.map_id)
        @battlers[client.player.map_id][id] = Player.new(nil) if !@battlers[client.player.map_id].has_key?(id)
        @battlers[client.player.map_id][id].evaluate(variables)
        client.sender.send_to_map(client.message)
      end
      return true
    when /\AABSBED\t(.+)\t(.+)/ # broadcast enemy death
      if @gmasters[client.player.map_id] == client
        id = $1.to_i
        client.sender.send_to_map(client.message, true)
        @dead[client.player.map_id] = [] if !@dead.has_key?(client.player.map_id)
        @dead[client.player.map_id].push(id) if !@dead[client.player.map_id].include?(id)
      end
      return true
    when /\AABSBER\t(.+)/ # broadcast enemy respawn
      if @gmasters[client.player.map_id] == client
        id = $1.to_i
        client.sender.send_to_map(client.message, true)
        @dead[client.player.map_id] = [] if !@dead.has_key?(client.player.map_id)
        @dead[client.player.map_id].delete(id) if @dead[client.player.map_id].include?(id)
      end
      return true
    when /\AABSADM\t(.+)\t(.+)/ # actor damage variables
      if @gmasters[client.player.map_id] == client
        client.sender.send_to_map(client.message)
      end
      return true
    when /\AABSEDM\t(.+)\t(.+)/ # enemy damage variables
      if @gmasters[client.player.map_id] == client
        client.sender.send_to_map(client.message)
      end
      return true
    when /\AABSACM\t(.+)/ # attack consume
      if @gmasters[client.player.map_id] == client
        user_id = $1.to_i
        client.sender.send_to_id(user_id, 'ABSACM')
      end
      return true
    when /\AABSSCM\t(.+)\t(.+)/ # skill consume
      if @gmasters[client.player.map_id] == client
        user_id = $1.to_i
        skill_id = $2.to_i
        client.sender.send_to_id(user_id, RMXOS.make_message('ABSSCM', skill_id))
      end
      return true
    when /\AABSICM\t(.+)\t(.+)/ # item consume
      if @gmasters[client.player.map_id] == client
        user_id = $1.to_i
        item_id = $2.to_i
        client.sender.send_to_id(user_id, RMXOS.make_message('ABSICM', item_id))
      end
      return true
    when /\AABSPIN\t(.+)/ # party invitation
      username = $1
      client._process_result(client.action.prepare_party_invite(username))
      return true
    when /\AABSPLE\Z/ # party leave
      client.action.execute_party_leave
      return true
    when /\AABSPRM\t(.+)/ # party remove
      username = $1
      client.action.execute_party_remove(username)
      return true
    when /\AABSPME\t(.+)/ # party message
      client.sender.send_to_party(RMXOS.make_message('CHT', $1), true)
      return true
    end
    return false
  end
 
  def self.try_activate_gmaster(map_id)
    return if @gmasters.has_key?(map_id)
    clients = @capable_clients.values.find_all {|client| client.player.map_id == map_id}
    return if clients.size == 0
    client = clients[0]
    client.send('ABSGMA')
    @gmasters[map_id] = client
    @dead[map_id] = [] if !@dead.has_key?(map_id)
    if !@battlers.has_key?(map_id)
      @battlers[map_id] = {}
      client.send('ABSMDR')
    end
    message = RMXOS::Data.args(RMXOS::Data::GlobalMasterActivate_CLIENT_MAPID, {'CLIENT' => client.player.username, 'MAPID' => map_id.to_s})
    self.log(message)
  end
 
  def self.try_deactivate_gmaster(client, map_id = nil)
    if map_id == nil
      @gmasters.each_key {|key|
        if client == @gmasters[key]
          map_id = key
          break
        end
      }
    end
    return if map_id == nil
    @gmasters.delete(map_id)
    client.send('ABSGMD')
    message = RMXOS::Data.args(RMXOS::Data::GlobalMasterDeactivate_CLIENT_MAPID, {'CLIENT' => client.player.username, 'MAPID' => map_id.to_s})
    self.log(message)
    self.try_activate_gmaster(map_id)
    self.release_map(map_id) if !@gmasters.has_key?(map_id)
  end
 
  def self.release_map(map_id)
    @gmasters.delete(map_id) if @gmasters.has_key?(map_id)
    message = RMXOS::Data.args(RMXOS::Data::GlobalMasterRelease_MAPID, {'MAPID' => map_id.to_s})
    self.log(message)
  end
 
  def self.log(message)
    puts message if SERVER_DISPLAY
    RMXOS.log('Log', IDENTIFIER, message)
  end
 
end

#==========================================================================
# Player
#==========================================================================

class Player

  IGNORE_VARIABLES.push('@battler|@damage')
  IGNORE_VARIABLES.push('@battler|@hpdamage')
  IGNORE_VARIABLES.push('@battler|@spdamage')
  IGNORE_VARIABLES.push('@ai|@act|@kind')
  IGNORE_VARIABLES.push('@ai|@act|@id')
 
  attr_accessor :party
  attr_accessor :partyleader
 
  alias initialize_blizzabsrmxos_later initialize
  def initialize(client)
    initialize_blizzabsrmxos_later(client)
    self.reset_party
  end
 
  def reset_party
    @partyleader = ''
    @party = []
  end
 
end

#==========================================================================
# Action
#==========================================================================

class Action
 
  TYPE_ABS_PARTY_JOIN = 1001
 
end
 
#==========================================================================
# Result
#==========================================================================

module RMXOS

  class Result
 
    ABS_PARTY_FULL = 1001
    ABS_PLAYER_ALREADY_IN_PARTY = 1002
   
    class << self
      alias error_blizzabsrmxos_later error
    end

    def self.error(code, message)
      result = Result.new(RMXOS::Data::ColorError)
      case code
      when RMXOS::Result::ABS_PARTY_FULL        then result.message = RMXOS::Error::PartyFull
      when RMXOS::Result::ABS_PLAYER_ALREADY_IN_PARTY  then result.message = RMXOS::Error::PartyAlready_PLAYER
      else
        return error_blizzabsrmxos_later(code, message)
      end
      return result
    end
 
  end
 
end
 
#==========================================================================
# ActionHandler
#==========================================================================

class ActionHandler
 
  def prepare_party_invite(username)
    @args = {'PLAYER' => username}
    return RMXOS::Result::ABS_PARTY_FULL if @client.player.party.size >= BlizzABS::MAX_ONLINE_PARTY - 1
    check = RMXOS.server.sql.query("SELECT COUNT(*) AS count FROM users WHERE username = '#{RMXOS.sql_string(username)}'")
    hash = check.fetch_hash
    return RMXOS::Result::PLAYER_NOT_EXIST if hash['count'].to_i == 0
    client = RMXOS.clients.get_by_name(username)
    return RMXOS::Result::PLAYER_NOT_ONLINE if client == nil
    return RMXOS::Result::PLAYER_NOT_ON_MAP if client.player.map_id != @client.player.map_id
    return RMXOS::Result::ABS_PLAYER_ALREADY_IN_PARTY if client.player.party.size > 0
    # prepare invitation
    sender_messages = Action::MessagePack.new(RMXOS::Data::PartyInvited_PLAYER,
      '', RMXOS::Data::GuildNoJoin_PLAYER, @args)
    receiver_messages = Action::MessagePack.new(self.make_accept_message(RMXOS::Data::PartyInvitation_PLAYER),
      RMXOS::Data::PartyJoined_PLAYER, RMXOS::Data::PartyNoJoin, {'PLAYER' => @client.player.username})
    self.create_interaction(Action::TYPE_ABS_PARTY_JOIN, sender_messages, [client], @client.player.user_id, receiver_messages)
    return RMXOS::Result::SUCCESS
  end
 
  def execute_party_join(action)
    user_id = action.data
    leader = RMXOS.clients.get_by_id(user_id)
    return RMXOS::Result::NO_ACTION if leader == nil
    leader.player.party |= [@client.player.username]
    @client.player.party = leader.player.party.clone
    @client.player.partyleader = leader.player.partyleader = leader.player.username
    @client.send('ABSPIN', leader.player.username, leader.player.party.inspect)
    message = RMXOS::Data.args(RMXOS::Data::PartyJoined_PLAYER, {'PLAYER' => @client.player.username})
    joinMessage = RMXOS.make_message('ABSPIN', leader.player.username, leader.player.party.inspect)
    message = RMXOS.make_message('CHT', RMXOS::Data::ColorOk, 0, message)
    RMXOS.clients.get_in_party(@client).each {|client|
      client.send(joinMessage)
      client.send(message)
      client.player.party = leader.player.party.clone
    }
    return RMXOS::Result::SUCCESS
  end
 
  def execute_party_leave
    if @client.player.partyleader == @client.player.username # leader left, disband party
      clients = RMXOS.clients.get_in_party(@client, true)
      clients.each {|client|
        client.send('ABSPRE')
        client.send_chat(RMXOS::Data::ColorInfo, RMXOS::Data::PartyDisbanded)
        client.player.reset_party
      }
      return
    end
    clients = RMXOS.clients.get_in_party(@client)
    @client.send('ABSPRE')
    @client.send_chat(RMXOS::Data::ColorInfo, RMXOS::Data::PartyRemoved)
    @client.player.reset_party
    leaveMessage = RMXOS.make_message('ABSPRM', @client.player.username)
    message = RMXOS::Data.args(RMXOS::Data::PartyRemoved_PLAYER, {'PLAYER' => @client.player.username})
    message = RMXOS.make_message('CHT', RMXOS::Data::ColorOk, 0, message)
    clients.each {|client|
      client.send(leaveMessage)
      client.send(message)
      client.player.party -= [@client]
    }
  end
 
  def execute_party_remove(username)
    client = RMXOS.clients.get_by_name(username)
    client.action.execute_party_leave if client != nil
  end
 
  alias execute_custom_yes_blizzabsrmxos_later execute_custom_yes
  def execute_custom_yes(action)
    return case action.type
    when Action::TYPE_ABS_PARTY_JOIN then self.execute_party_join(action)
    else
      execute_custom_yes_blizzabsrmxos_later(action)
    end
  end
 
  alias execute_custom_no_blizzabsrmxos_later execute_custom_no
  def execute_custom_no(action)
    return case action.type
    when Action::TYPE_ABS_PARTY_JOIN then RMXOS::Result::SUCCESS
    else
      execute_custom_no_blizzabsrmxos_later(action)
    end
  end
 
end

#==========================================================================
# ClientHandler
#==========================================================================

class ClientHandler
 
  def get_in_party(current, including = false)
    clients = RMXOS.clients.get.find_all {|client| client.player.partyleader == current.player.partyleader}
    clients.delete(current) if !including
    return clients
  end
 
end

#==========================================================================
# Sender
#==========================================================================

class Sender
 
  def send_to_party(message, including = false)
    self.send_to_clients(RMXOS.clients.get_in_party(@client, including), message)
  end
 
end




Instructions

In the script in the first comment.


Compatibility

Requires Blizz-ABS to work.
Requires RMX-OS to work.


Credits and Thanks


  • Boris "Blizzard" Mikić
  • Special Thanks to Ryex for providing the basecode for the fix for the controls conflict between Blizz-ABS and RMX-OS



Author's Notes

Remember to activate the server extension by adding the server extension filename to the list in the configuration.

If you find any bugs, please report them here:
http://forum.chaos-project.com

That's it! N-Joy! =D
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

C.C. rOyAl

Spoiler: ShowHide

Aqua


Ryex

Quote from: Blizzard on January 17, 2010, 05:02:36 pm
This script allows the proper usage of Blizz-ABS in combination with RMX-OS.
The current version of the script is not fully functional. Enemies on the map are not controlled globally and it's not possible to see other players attacking enemies. This version also does not require the server extension.


And here i was getting all excited! :P
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

fugibo

Quote from: Ryexander on January 17, 2010, 07:25:39 pm
Quote from: Blizzard on January 17, 2010, 05:02:36 pm
This script allows the proper usage of Blizz-ABS in combination with RMX-OS.
The current version of the script is not fully functional. Enemies on the map are not controlled globally and it's not possible to see other players attacking enemies. This version also does not require the server extension.


And here i was getting all excited! :P


At least people will shutup about it now.

C.C. rOyAl

@fugibo: why did u change ur name?

@Ryex: its because its only version 0.8
Spoiler: ShowHide

Aqua

Numbers have nothing to do with anything...
GG's Modded Menu    .98    game_guy
Advanced Time and Environment System (ATES)    0.4    Blizzard
Key Simulator    0.1    Fantasist
Animated BlizzABS HUD (MOG)    0.9    Moghunter, Subsonic Noise, Blizzard
Those are all under 1.0 and work well XD

Besides... it's 0.7

G_G

Pretty much what the version 0.x is that all planned features are not yet implemented.

Blizzard

Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

C.C. rOyAl

Yeah i hadnt been on recently but i was goin to say the exact thing
Spoiler: ShowHide

edwardthefma

good work blizzard it is a awesome peace of work
this working in conjuntion with the  globel switches 
is a must tho you will need 1 swich per monster for the enter game
XD i got alot of work aheah of me
i am the lead dev for the shellium mmorpg project
http://wiki.shellium.org/w/Mmorpg
shellium.org :) free linux shells pm me and i will gladly
help you get 1

whitespirits

how do i setup with extension in the config file, i added the .rb files with script in just when i enter extenstion server wont stay open EXTENSIONS = [enter here?]

Blizzard

February 03, 2010, 04:17:44 pm #12 Last Edit: February 03, 2010, 04:33:02 pm by Blizzard
i.e.

filename:
Blizz-ABS.rb

config:
EXTENSIONS = ['Blizz-ABS']

or:
EXTENSIONS = ["Blizz-ABS"]


I put the second in the second row so you can edit it easier like this:

EXTENSIONS = [
'Blizz-ABS', 'blabla', 'some other extension'
]


At least that's how I prefer it. Even if you accidentally add a comma after the last extension, RMX-OS actually ignores the non-existing entries.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

crzyone9584

Not sure if it has something to do with The addon or not but its this script :'(

This happens when i move the character.

QuoteScript 'Blizz-ABS RMX-OS' line 161: NoMethodError occurred.

undefinedmethod 'creat_character_data' for
#<RMXOS::Network:0x81bf668


Any ideas?

Line 161 is
data = create_character_data(actor)

Aqua


crzyone9584

Yes i have RMX-OS then the ABS 1,2,3 then ABS RMX-OS script. I got fed up. I took it off. I have to sit down when i have time and dedicate a few hours to actually customizing the script so it wont interfere with typing in the chat window. decided to just get small things working like a new menu and things like that.

G_G

That happens because you didnt add the extension. Place the extension script in a file called abs.rb.
Go into the config for rmx-os and in the extensions option add 'abs' with quotes

crzyone9584

i have the extension. its called Blitz-ABS. maybe i didn't copy off it though. Ill have to double check that now. When i get home see if my mysql fixes an issues ill move back to the abs.

whitespirits

Ive added all scripts for abs i can get ingame i walk a little and get an error in controller script on this line
  def send_actor_data(actor)
    data = create_character_data(actor)
    #self.send("MAA#{data}")
  end
 
end

G_G

when I log in I end up in the top left corner of the map and thats not where I was when I entered that map D: