Well this is what I was able to come up with. It could be better, but at least the functionality is there.
# Rewrites the attack method to allow reflecting of projectiles
# Not aliased due to the amount of setup required and possible performance loss
module BlizzABS
class Processor
#--------------------------------------------------------------------------
# attack_process
# ch - the character in action
# Processes ABS attack setup and handling for actors and enemies.
#--------------------------------------------------------------------------
def attack_process(ch)
# temporary variable
ai = ch.ai
# determine whether actor or enemy for easier reference
if ch.is_a?(Map_Actor)
# decide target group
group = ((ch != $game_player && ch.restriction == 3)) ?
ai.positive : ai.negative
# determine range
d = Weapons.range(ch.battler.weapon_id)
d = 1 if d < 1
# determine type
type = Weapons.type(ch.battler.weapon_id)
# determine charge
charge = Weapons.charge(ch.battler.weapon_id)
# determine projectile speed
projectile_speed = Weapons.projectile_speed(ch.battler.weapon_id)
else
# determine target group depending on confusion
group = (ch.restriction == 3 ? ai.positive : ai.negative)
# determine range
d = Enemies.range(ch.battler_id)
d = 1 if d < 1
# determine type
type = Enemies.type(ch.battler_id)
# determine charge
charge = Enemies.charge(ch.battler_id)
# determine charge
charge[0] = BlizzABS::CHARGEMove if charge[0] == BlizzABS::CHARGETrigger
# determine projectile speed
projectile_speed = Weapons.projectile_speed(ch.battler_id)
end
# if item shooting type
if type == BOW_ARROW
# temporary variable
ids = Weapons.consume(ch.battler.weapon_id)
# if no more items
if !ids.include?(ch.battler.item) ||
$game_party.item_number(ch.battler.item) == 0
# can't use
return false
end
end
# if not charging already
if charge[0] != CHARGENone && !ch.charging?
# setup charging
ch.setup_charge(ch, charge)
# not used yet
return false
end
# create affection area depending on attack type
case type
when SWORD, SPEAR, FLAIL # sword attack
# get attack affection area
area = $BlizzABS.util.get_attack_area(ch, d, type)
when BOOMERANG # returning projectile attack
# decide spriteset
spriteset = ch.is_a?(Map_Actor) ?
BlizzABS::SPRProjWeapon + ch.battler.weapon_id.to_s :
BlizzABS::SPRProjEnemy + ch.battler_id.to_s
# create returning projectile
proj = Map_Projectile.new(spriteset, ch, 0, d, projectile_speed,
REMReturning, group)
when BOW # projectile attack
# decide spriteset
spriteset = ch.is_a?(Map_Actor) ?
BlizzABS::SPRProjWeapon + ch.battler.weapon_id.to_s :
BlizzABS::SPRProjEnemy + ch.battler_id.to_s
# create returning projectile
proj = Map_Projectile.new(spriteset, ch, 0, d, projectile_speed,
REMNormal, group)
when BOW_ARROW # item consuming projectile
# remove one item from inventory
$game_party.lose_item(ch.battler.item, 1)
# temporary variable
item = $data_items[ch.battler.item]
# get item explosion data
explode = Items.type(item.id)
# if explosion exists
if explode[1] != EXPLNone
# fix the missing explosion animation error
explode[2] = 0 if explode[2] == nil
# create projectile from exploding item with weapon attack effect
proj = Map_Projectile.new(BlizzABS::SPRProjItem + item.id.to_s, ch,
item.id, d, projectile_speed, REMShotItem, group, false,
explode[1, 3])
else
# create projectile from item with weapon attack effect
proj = Map_Projectile.new(BlizzABS::SPRProjItem + item.id.to_s, ch,
item.id, d, projectile_speed, REMShotItem, group)
end
when SHURIKEN # self consuming weapon
# temporary variable
weapon = $data_weapons[ch.battler.weapon_id]
# unequip last weapon if no more weapons in inventory
ch.battler.equip(0, 0) if $game_party.weapon_number(weapon.id) == 0
# remove one weapon from inventory
$game_party.lose_weapon(weapon.id, 1)
# self shooting weapon, create projectile from weapon
proj = Map_Projectile.new(BlizzABS::SPRProjWeapon + weapon.id.to_s, ch,
weapon.id, d, projectile_speed, REMShotWeapon, group)
end
# if projectile fired
if proj != nil
# add projectile to buffer
$BlizzABS.cache.remotes.push(proj)
# used
return true
end
# iterate through all battlers
($game_map.battlers + $BlizzABS.battlers).each {|battler|
# if target can be hit considering all conditions
if battler.battler != nil && group.include?(battler.ai.group) &&
(battler != ch || group == ai.positive) &&
!battler.battler.dead? && @util.intersection(area,
battler.hitbox)
# execute attack
battler.attack_effect(ch, ch.battler)
# clear damage displays
battler.battler.damage, battler.battler.damage_pop = nil, false
end
}
#*************************************************************************
# EDIT BEGINS HERE
#*************************************************************************
# If attacked with SWORD weapon
if type == SWORD
$BlizzABS.cache.remotes.each{|projectile|
# Ignore if not a SHOOT projectile
next unless projectile.is_a?(Map_Projectile) &&
[REMNormalSkill, REMBreakSkill].include?(projectile.type)
# Ignore if the creator of the projectile and this character are of
# the same type
next if projectile.battler.class == ch.battler.class
# If projectile in attack area
if @util.intersection(area, projectile.hitbox)
# Reflect the projectile
projectile.reflect_projectile(ch)
end
}
end
#*************************************************************************
# EDIT ENDS HERE
#*************************************************************************
# enemies were attacked
return true
end
end
end
# Added reflection method
class Map_Projectile < Map_Remote
def reflect_projectile(ch)
pix = 128 / $BlizzABS.pixel
# Reset variables so that the reflector is now the owner of the projectile
@creator = ch
@battler_copy = ch.battler.clone
@group = ch.ai.negative
# Get the remaining distance the projectile had left to move
distance = case @direction
when 2 then @y * pix - @real_y
when 4 then @real_x - @x * pix
when 6 then @x * pix - @real_x
when 8 then @real_y - @y * pix
end
# Change projectile's direction
@direction = ch.direction
# Set new target location for the projectile
case @direction
when 2
@y = (@real_y + distance) / pix
@x = ch.x
when 4
@x = (@real_x - distance) / pix
@y = ch.y
when 6
@x = (@real_x + distance) / pix
@y = ch.y
when 8
@y = (@real_y - distance) / pix
@x = ch.x
end
end
end
Your player must be using a SWORD weapon type and it can only reflect projectiles of the SHOOT type. Edit it according to your needs. The reflected projectile's damage will be the same as if the player were to shoot the exact same projectile himself.