- 累计送礼:
- 0 个
- 累计收礼:
- 1 个
TA的每日心情 | 开心 3 小时前 |
|---|
签到天数: 220 天 连续签到: 8 天 [LV.7]常住居民III

管理员
  
- VIP
- 7
- 卡币
- 64785
- OK点
- 16
- 推广点
- 0
- 同能卷
- 50
- 积分
- 74796


|
[Ruby] 纯文本查看 复制代码 #==============================================================================
# ▼ 射击系统脚本 (Shooting System)
# 作者:Ruigi
# -- 放在 Main 之前
#==============================================================================
# 标签(写在技能/物品的「备注」栏):
# <gun> 标记为射击类
# <guntime:数字> 射击模式持续时间(帧),默认 300
# <bullet:物品编号> 每次射击消耗的物品ID
# <kind:动画编号> 持枪状态动画(持续循环播放)
# <shoot:动画编号> 射击命中敌人时对目标播放的动画
# <Impact:动画编号> 准星位置播放的弹孔/火花(无论命中与否都播放)
# <Precision:数字> 准星平滑度(1 = 不滑,越大越滑越难瞄)
# <Automatic:秒数> 自动挡模式(支持小数)
# <Xrecoil:幅度> 水平后坐力(像素)
# <Yrecoil:幅度> 垂直后坐力(像素)
#
# ★ 射击技能的「使用效果」要设置伤害公式(如 a.atk * 4 - b.def * 2)
#==============================================================================
module Shooting_Config
# ---- 基础 ----
CROSSHAIR_IMAGE = "crosshair"
CROSSHAIR_SIZE = [48, 48]
DEFAULT_GUNTIME = 300
SHOOT_KEY = :C
HIT_SOUND = "gun1"
EXIT_KEYS = [:B]
USE_MOUSE_LEFT = true
SHOT_COOLDOWN = 8
KEYBOARD_SPEED = 6
CHECK_BULLET_ON_ENTER = true
HIT_RECT_PADDING = 0
# ---- 爆头机制 ----
HEADSHOT_ENABLED = true
HEADSHOT_RATIO = 0.35
HEADSHOT_MULTIPLIER = 2.0
HEADSHOT_SOUND = "Critical"
HEADSHOT_TEXT = "爆头!"
# ---- 准星平滑 ----
DEFAULT_PRECISION = 3
# ---- 后坐力 ----
RECOIL_DECAY = 0.82
# ---- 弹孔 / 空枪反馈 ----
IMPACT_OFFSET_X = 0
IMPACT_OFFSET_Y = 0
IMPACT_Z = 8000
# ★ 每次射击(命中或未命中)都重播一次 <kind:> 动画
# true = 每次开火都重播(更有"枪口抖动"感)
# false = 只在未命中时重播(默认,避免命中时视觉过乱)
REPLAY_KIND_ON_HIT = false
# ---- 子弹 HUD ----
HUD_X = 0
HUD_Y = 0
HUD_WIDTH = 200
HUD_Z = 9000
HUD_SHOW_NAME = true
HUD_LOW_COLOR = true
HUD_LOW_THRESHOLD = 3
# ---- 自动挡 ----
AUTO_HUD_LABEL = "[自动]"
# ---- 调试 ----
DEBUG_AUTO = false
end
#==============================================================================
# ■ Spriteset_Battle - 开放精灵数组读取
#==============================================================================
class Spriteset_Battle
attr_reader :actor_sprites, :enemy_sprites
end
#==============================================================================
# ■ NoteNum - 宽容的标签数字解析
#==============================================================================
module NoteNum
FULLWIDTH_DIGITS = {
"0"=>"0","1"=>"1","2"=>"2","3"=>"3","4"=>"4",
"5"=>"5","6"=>"6","7"=>"7","8"=>"8","9"=>"9"
}
def self.extract(note, tag)
m = note.match(/<#{tag}\s*:\s*([^>\r\n]*)/i)
return nil unless m
raw = m[1].strip
num = raw[/[0-90-9..,,]+/]
return nil unless num
s = num.each_char.map { |c| FULLWIDTH_DIGITS[c] || c }.join
s = s.tr(".,,", ".")
s.to_f
end
end
#==============================================================================
# ■ RPG::UsableItem - 标签解析
#==============================================================================
class RPG::UsableItem < RPG::BaseItem
def shooting?
return @shooting unless @shooting.nil?
@shooting = !note[/<gun>/i].nil?
end
def gun_time
return @gun_time unless @gun_time.nil?
v = NoteNum.extract(note, "guntime")
@gun_time = v ? v.to_i : Shooting_Config::DEFAULT_GUNTIME
end
def bullet_id
return @bullet_id unless @bullet_id.nil?
v = NoteNum.extract(note, "bullet")
@bullet_id = v ? v.to_i : 0
end
def kind_animation_id
return @kind_anim unless @kind_anim.nil?
v = NoteNum.extract(note, "kind")
@kind_anim = v ? v.to_i : 0
end
def shoot_animation_id
return @shoot_anim unless @shoot_anim.nil?
v = NoteNum.extract(note, "shoot")
@shoot_anim = v ? v.to_i : 0
end
def impact_animation_id
return @impact_anim unless @impact_anim.nil?
v = NoteNum.extract(note, "Impact")
@impact_anim = v ? v.to_i : 0
end
def precision
return @precision unless @precision.nil?
v = NoteNum.extract(note, "Precision")
@precision = v ? v.to_i : Shooting_Config::DEFAULT_PRECISION
end
def automatic_interval
return @auto_interval unless @auto_interval.nil?
v = NoteNum.extract(note, "Automatic")
@auto_interval = v && v > 0 ? v : 0.0
end
def automatic_interval_frames
return 0 if automatic_interval <= 0
[(automatic_interval * 60).round, 1].max
end
def automatic?
automatic_interval > 0
end
def x_recoil
return @x_recoil unless @x_recoil.nil?
v = NoteNum.extract(note, "Xrecoil")
@x_recoil = v && v > 0 ? v : 0.0
end
def y_recoil
return @y_recoil unless @y_recoil.nil?
v = NoteNum.extract(note, "Yrecoil")
@y_recoil = v && v > 0 ? v : 0.0
end
end
#==============================================================================
# ■ Mouse - 鼠标辅助
#==============================================================================
module Mouse
WIN32_AVAILABLE = defined?(::Win32API) ? true : false
if WIN32_AVAILABLE
@get_cursor_pos = ::Win32API.new("user32", "GetCursorPos", "P", "I")
@screen_to_client = ::Win32API.new("user32", "ScreenToClient", "LP", "I")
@find_window = ::Win32API.new("user32", "FindWindow", "PP", "L")
@get_async_key = ::Win32API.new("user32", "GetAsyncKeyState", "i", "i")
end
@cached_pos = [320, 240]
@prev_left = false
def self.available?
WIN32_AVAILABLE
end
def self.find_hwnd
return 0 unless WIN32_AVAILABLE
["RGSS Player", "RGSS3 Player", "RPG Maker VX Ace", "Game"].each do |t|
hwnd = @find_window.call(nil, t)
return hwnd if hwnd != 0
end
0
end
def self.position
return @cached_pos unless WIN32_AVAILABLE
hwnd = find_hwnd
return @cached_pos if hwnd == 0
pos = [0, 0].pack("ll")
@get_cursor_pos.call(pos)
@screen_to_client.call(hwnd, pos)
@cached_pos = pos.unpack("ll")
end
def self.left_held?
return false unless WIN32_AVAILABLE
(@get_async_key.call(0x01) & 0x8000) != 0
end
def self.left_click?
now = left_held?
result = now && !@prev_left
@prev_left = now
result
end
end
#==============================================================================
# ■ Sprite_Crosshair - 准星精灵
#==============================================================================
class Sprite_Crosshair < Sprite
attr_accessor :precision
def initialize(viewport = nil)
super(viewport)
@active = false
@precision = Shooting_Config::DEFAULT_PRECISION
@target_x = 320
@target_y = 240
@current_x = 320
@current_y = 240
@recoil_x = 0.0
@recoil_y = 0.0
begin
self.bitmap = Cache.picture(Shooting_Config::CROSSHAIR_IMAGE)
rescue
self.bitmap = nil
end
if self.bitmap
self.zoom_x = Shooting_Config::CROSSHAIR_SIZE[0].to_f / self.bitmap.width
self.zoom_y = Shooting_Config::CROSSHAIR_SIZE[1].to_f / self.bitmap.height
else
self.bitmap = Bitmap.new(32, 32)
c = Color.new(255, 0, 0)
self.bitmap.draw_line(16, 0, 16, 12, c)
self.bitmap.draw_line(16, 20, 16, 32, c)
self.bitmap.draw_line(0, 16, 12, 16, c)
self.bitmap.draw_line(20, 16, 32, 16, c)
self.bitmap.draw_line(6, 6, 12, 12, c)
self.bitmap.draw_line(26, 6, 20, 12, c)
self.bitmap.draw_line(6, 26, 12, 20, c)
self.bitmap.draw_line(26, 26, 20, 20, c)
end
self.visible = false
self.z = 9999
end
def activate
@active = true
self.visible = true
if Mouse.available?
@target_x, @target_y = Mouse.position
else
@target_x = 320
@target_y = 240
end
@current_x = @target_x
@current_y = @target_y
@recoil_x = 0.0
@recoil_y = 0.0
update_position
end
def deactivate
@active = false
self.visible = false
end
def active?
@active
end
def screen_pos
[@current_x + @recoil_x, @current_y + @recoil_y]
end
def add_recoil(x_amp, y_amp)
@recoil_x += (rand * 2.0 - 1.0) * x_amp if x_amp && x_amp > 0
@recoil_y += (rand * 2.0 - 1.0) * y_amp if y_amp && y_amp > 0
end
def update_position
return unless @active
if Mouse.available?
@target_x, @target_y = Mouse.position
else
@target_x -= Shooting_Config::KEYBOARD_SPEED if Input.press?(:LEFT)
@target_x += Shooting_Config::KEYBOARD_SPEED if Input.press?(:RIGHT)
@target_y -= Shooting_Config::KEYBOARD_SPEED if Input.press?(:UP)
@target_y += Shooting_Config::KEYBOARD_SPEED if Input.press?(:DOWN)
@target_x = [[@target_x, 0].max, 640].min
@target_y = [[@target_y, 0].max, 480].min
end
factor = 1.0 / [@precision, 1].max
@current_x += (@target_x - @current_x) * factor
@current_y += (@target_y - @current_y) * factor
@current_x = @target_x if (@target_x - @current_x).abs < 0.5
@current_y = @target_y if (@target_y - @current_y).abs < 0.5
@recoil_x *= Shooting_Config::RECOIL_DECAY
@recoil_y *= Shooting_Config::RECOIL_DECAY
@recoil_x = 0.0 if @recoil_x.abs < 0.1
@recoil_y = 0.0 if @recoil_y.abs < 0.1
draw_x = @current_x + @recoil_x
draw_y = @current_y + @recoil_y
w = self.bitmap ? self.bitmap.width * zoom_x : 0
h = self.bitmap ? self.bitmap.height * zoom_y : 0
self.x = draw_x - w / 2
self.y = draw_y - h / 2
end
end
#==============================================================================
# ■ Sprite_Impact - 弹孔动画精灵
#==============================================================================
class Sprite_Impact < Sprite_Base
def initialize(viewport = nil)
super(viewport)
self.visible = false
self.z = Shooting_Config::IMPACT_Z
@playing = false
end
def play(x, y, animation_id)
return if animation_id.nil? || animation_id <= 0
animation = $data_animations[animation_id]
return unless animation
self.x = x + Shooting_Config::IMPACT_OFFSET_X
self.y = y + Shooting_Config::IMPACT_OFFSET_Y
@playing = true
self.visible = true
start_animation(animation)
end
def update
super
if @playing && !animation?
@playing = false
self.visible = false
end
end
end
#==============================================================================
# ■ Window_BulletCounter - 左上角子弹数量 HUD
#==============================================================================
class Window_BulletCounter < Window_Base
def initialize
super(Shooting_Config::HUD_X, Shooting_Config::HUD_Y,
Shooting_Config::HUD_WIDTH, fitting_height(1))
self.z = Shooting_Config::HUD_Z
self.visible = false
self.openness = 255
[url=home.php?mod=space&uid=363652]@Bullet[/url] = nil
@count = 0
@automatic = false
end
def show_bullet(item, automatic = false)
return unless item
@bullet = item
@automatic = automatic
refresh
self.visible = true
end
def hide_bullet
self.visible = false
@bullet = nil
end
def update_count
return unless @bullet
new_count = $game_party.item_number(@bullet)
return if new_count == @count
@count = new_count
refresh
end
def refresh
contents.clear
return unless @bullet
@count = $game_party.item_number(@bullet)
draw_icon(@bullet.icon_index, 0, 0)
offset = 28
if @automatic && Shooting_Config::AUTO_HUD_LABEL && !Shooting_Config::AUTO_HUD_LABEL.empty?
change_color(Color.new(120, 200, 255))
draw_text(offset, 0, 48, line_height, Shooting_Config::AUTO_HUD_LABEL)
change_color(normal_color)
offset += 48
end
if Shooting_Config::HUD_SHOW_NAME
change_color(normal_color)
draw_text(offset, 0, 120 - (offset - 28), line_height, @bullet.name)
count_x = 148
count_w = contents.width - count_x
else
count_x = offset
count_w = contents.width - count_x
end
if Shooting_Config::HUD_LOW_COLOR && @count <= Shooting_Config::HUD_LOW_THRESHOLD
change_color(Color.new(255, 80, 80))
else
change_color(system_color)
end
draw_text(count_x, 0, count_w, line_height, "x#{@count}", 2)
change_color(normal_color)
end
end
#==============================================================================
# ■ Game_Battler - 射击状态管理 + 爆头伤害加成
#==============================================================================
class Game_Battler < Game_BattlerBase
attr_accessor :gun_active
attr_accessor :gun_time_remaining
attr_accessor :gun_item
attr_accessor :shooting_headshot
alias shooting_init_game_battler initialize
def initialize
shooting_init_game_battler
@gun_active = false
@gun_time_remaining = 0
@gun_item = nil
@shooting_headshot = false
end
def start_gun(item)
@gun_active = true
@gun_time_remaining = item.gun_time
@gun_item = item
end
def stop_gun
@gun_active = false
@gun_time_remaining = 0
@gun_item = nil
end
def update_gun
return unless @gun_active
@gun_time_remaining -= 1
stop_gun if @gun_time_remaining <= 0
end
def gun_active?
@gun_active
end
alias shooting_make_damage_value make_damage_value
def make_damage_value(user, item)
shooting_make_damage_value(user, item)
if @shooting_headshot && Shooting_Config::HEADSHOT_ENABLED && @result.hp_damage > 0
multiplier = Shooting_Config::HEADSHOT_MULTIPLIER
@result.hp_damage = (@result.hp_damage * multiplier).to_i
end
end
end
#==============================================================================
# ■ Game_Enemy - 命中判定后备矩形
#==============================================================================
# 注意:不覆盖 screen_x / screen_y / screen_z —— 保留引擎原版定义,
# 让 $data_troops 里手动摆放的敌人坐标继续生效。
# 这里只新增一个 screen_rect 后备方法,仅在找不到精灵时使用。
class Game_Enemy < Game_Battler
def screen_rect
# 引擎原版的 screen_x / screen_y 是精灵的绘制坐标(左上角)
# 真实尺寸由精灵决定,找不到精灵时给一个宽松的默认矩形
Rect.new(screen_x, screen_y, 64, 64)
end
end
#==============================================================================
# ■ Scene_Battle - 射击模式集成
#==============================================================================
class Scene_Battle < Scene_Base
alias shooting_start start
def start
shooting_start
@shooting_mode = false
@shooting_item = nil
@crosshair = Sprite_Crosshair.new
@impact = Sprite_Impact.new
@shot_cooldown = 0
@bullet_window = Window_BulletCounter.new
@dbg_counter = 0
end
alias shooting_terminate terminate
def terminate
shooting_terminate
@bullet_window.dispose if @bullet_window
@impact.dispose if @impact
end
alias shooting_update update
def update
if @shooting_mode
update_basic
@spriteset.update if @spriteset
@impact.update if @impact
update_shooting
else
shooting_update
@impact.update if @impact
update_shooting
end
end
#--------------------------------------------------------------------------
# ● 每帧射击相关更新
#--------------------------------------------------------------------------
def update_shooting
@crosshair.update_position if @crosshair.active?
@shot_cooldown -= 1 if @shot_cooldown > 0
$game_party.members.each { |m| m.update_gun }
$game_troop.members.each { |m| m.update_gun }
@bullet_window.update_count if @shooting_mode
return unless @shooting_mode
update_gun_animation
if Shooting_Config::DEBUG_AUTO
@dbg_counter += 1
if @dbg_counter % 30 == 0
p "[AUTO DBG] automatic?=#{auto_mode?} interval=#{@shooting_item.automatic_interval rescue 'nil'} " +
"frames=#{@shooting_item.automatic_interval_frames rescue 'nil'} " +
"cooldown=#{@shot_cooldown} " +
"kbd_press=#{Input.press?(Shooting_Config::SHOOT_KEY)} " +
"mouse_held=#{Shooting_Config::USE_MOUSE_LEFT && Mouse.available? ? Mouse.left_held? : false}"
end
end
if @shooting_item && $game_party.members.none? { |m| m.gun_active? }
exit_shooting_mode
return
end
if @shot_cooldown <= 0
if auto_mode?
perform_shot if shoot_key_held?
else
perform_shot if shoot_key_triggered?
end
end
Shooting_Config::EXIT_KEYS.each do |key|
if Input.trigger?(key)
exit_shooting_mode
return
end
end
end
def auto_mode?
@shooting_item && @shooting_item.automatic?
end
def shoot_key_held?
return true if Input.press?(Shooting_Config::SHOOT_KEY)
if Shooting_Config::USE_MOUSE_LEFT && Mouse.available?
return true if Mouse.left_held?
end
false
end
def shoot_key_triggered?
return true if Input.trigger?(Shooting_Config::SHOOT_KEY)
if Shooting_Config::USE_MOUSE_LEFT && Mouse.available?
return true if Mouse.left_click?
end
false
end
def shot_interval
return Shooting_Config::SHOT_COOLDOWN unless @shooting_item
frames = @shooting_item.automatic_interval_frames
frames > 0 ? frames : Shooting_Config::SHOT_COOLDOWN
end
#--------------------------------------------------------------------------
# ● 拦截 process_action
#--------------------------------------------------------------------------
alias shooting_process_action process_action
def process_action
return if scene_changing?
if !@subject || !@subject.current_action
@subject = BattleManager.next_subject
end
return turn_end unless @subject
if @subject.current_action
@subject.current_action.prepare
if @subject.current_action.valid?
@status_window.open
item = @subject.current_action.item
if item && item.shooting? && @subject.is_a?(Game_Actor)
if Shooting_Config::CHECK_BULLET_ON_ENTER && !has_bullet?(item)
Sound.play_buzzer
@log_window.add_text(sprintf("%s 的弹药不足!", @subject.name)) if @log_window
@subject.remove_current_action
@status_window.close rescue nil
return
end
@subject.use_item(item)
refresh_status
@subject.remove_current_action
enter_shooting_mode(item)
return
end
execute_action
end
@subject.remove_current_action
end
process_action_end unless @subject.current_action
end
def has_bullet?(item)
return true if item.bullet_id <= 0
bullet = $data_items[item.bullet_id]
return false if bullet.nil?
$game_party.item_number(bullet) > 0
end
#--------------------------------------------------------------------------
# ● 进入 / 退出射击模式
#--------------------------------------------------------------------------
def enter_shooting_mode(item)
@shooting_mode = true
@shooting_item = item
@shot_cooldown = 0
@crosshair.precision = item.precision
@crosshair.activate
$game_party.members.each { |m| m.start_gun(item) }
play_actor_animation(item.kind_animation_id)
if item.bullet_id > 0
bullet = $data_items[item.bullet_id]
@bullet_window.show_bullet(bullet, item.automatic?) if bullet
end
if Shooting_Config::DEBUG_AUTO
p "=== 进入射击模式:#{item.name} ==="
p " shooting? = #{item.shooting?}"
p " bullet_id = #{item.bullet_id}"
p " precision = #{item.precision}"
p " automatic? = #{item.automatic?}"
p " auto_interval = #{item.automatic_interval}"
p " auto_frames = #{item.automatic_interval_frames}"
p " impact_anim = #{item.impact_animation_id}"
p " kind_anim = #{item.kind_animation_id}"
p " x_recoil = #{item.x_recoil}"
p " y_recoil = #{item.y_recoil}"
p " note = #{item.note.inspect}"
end
end
def exit_shooting_mode
@shooting_mode = false
@shooting_item = nil
@crosshair.deactivate
$game_party.members.each { |m| m.stop_gun }
@bullet_window.hide_bullet
end
#--------------------------------------------------------------------------
# ● 执行射击
#--------------------------------------------------------------------------
def perform_shot
return unless @shooting_item
bullet_id = @shooting_item.bullet_id
if bullet_id > 0
bullet_item = $data_items[bullet_id]
if bullet_item.nil? || $game_party.item_number(bullet_item) <= 0
Sound.play_buzzer
@log_window.add_text("弹药耗尽!") if @log_window
exit_shooting_mode
return
end
end
# 拍快照:本次射击用当前准星位置判定(含已有后坐力)
shot_x, shot_y = @crosshair.screen_pos
# 扣弹药
if bullet_id > 0
$game_party.lose_item($data_items[bullet_id], 1)
end
# 准星位置播放弹孔/火花动画(无论命中与否)
impact_id = @shooting_item.impact_animation_id
if impact_id > 0 && @impact
@impact.play(shot_x, shot_y, impact_id)
end
# 施加后坐力(视觉立即偏移,影响下一发)
@crosshair.add_recoil(@shooting_item.x_recoil, @shooting_item.y_recoil)
# 用快照位置判定目标
target = find_enemy_at(shot_x, shot_y)
# =========================================================
# 空枪:播放开火音效 + 重播 kind 动画(开火动作反馈)
# =========================================================
unless target
Sound.play_use_skill rescue nil
# ★ 未命中时重新播放角色身上的持枪动画
play_actor_animation(@shooting_item.kind_animation_id)
@log_window.add_text("未命中...") if @log_window
@shot_cooldown = shot_interval
if bullet_id > 0 && $game_party.item_number($data_items[bullet_id]) <= 0
exit_shooting_mode
end
return
end
# =========================================================
# 命中:敌人播 <shoot:>,可选重播 kind
# =========================================================
headshot = headshot_hit_at?(target, shot_x, shot_y)
Sound.play_use_skill rescue nil
# 可选:命中时也重播 kind 动画(由配置控制)
if Shooting_Config::REPLAY_KIND_ON_HIT
play_actor_animation(@shooting_item.kind_animation_id)
end
play_enemy_animation(target, @shooting_item.shoot_animation_id)
if Shooting_Config::HIT_SOUND && !Shooting_Config::HIT_SOUND.empty?
Audio.se_play("Audio/SE/" + Shooting_Config::HIT_SOUND, 80, 100) rescue nil
end
if headshot
if Shooting_Config::HEADSHOT_SOUND && !Shooting_Config::HEADSHOT_SOUND.empty?
Audio.se_play("Audio/SE/" + Shooting_Config::HEADSHOT_SOUND, 90, 100) rescue nil
end
if @log_window && Shooting_Config::HEADSHOT_TEXT && !Shooting_Config::HEADSHOT_TEXT.empty?
@log_window.add_text(Shooting_Config::HEADSHOT_TEXT) rescue nil
end
end
target.shooting_headshot = headshot
apply_shot_effect(target, @shooting_item)
target.shooting_headshot = false
@shot_cooldown = shot_interval
if bullet_id > 0 && $game_party.item_number($data_items[bullet_id]) <= 0
exit_shooting_mode
end
end
#--------------------------------------------------------------------------
# ● 命中检测 / 爆头判定
#--------------------------------------------------------------------------
def find_enemy_at(mx, my)
$game_troop.alive_members.each do |enemy|
sprite = find_enemy_sprite(enemy)
rect = enemy_hit_rect(enemy, sprite)
return enemy if mx >= rect.x && mx <= rect.x + rect.width &&
my >= rect.y && my <= rect.y + rect.height
end
nil
end
def enemy_hit_rect(enemy, sprite)
pad = Shooting_Config::HIT_RECT_PADDING
if sprite && sprite.bitmap
w = sprite.bitmap.width * sprite.zoom_x
h = sprite.bitmap.height * sprite.zoom_y
x = sprite.x - sprite.ox * sprite.zoom_x - pad
y = sprite.y - sprite.oy * sprite.zoom_y - pad
Rect.new(x, y, w + pad * 2, h + pad * 2)
else
r = enemy.screen_rect
Rect.new(r.x - pad, r.y - pad, r.width + pad * 2, r.height + pad * 2)
end
end
def headshot_hit_at?(enemy, mx, my)
return false unless Shooting_Config::HEADSHOT_ENABLED
sprite = find_enemy_sprite(enemy)
rect = enemy_hit_rect(enemy, sprite)
return false unless mx >= rect.x && mx <= rect.x + rect.width
return false unless my >= rect.y && my <= rect.y + rect.height
head_bottom = rect.y + rect.height * Shooting_Config::HEADSHOT_RATIO
my <= head_bottom
end
def apply_shot_effect(target, item)
user = $game_party.members[0]
return unless user
target.item_apply(user, item)
if @log_window
@log_window.display_action_results(target, item) rescue nil
end
end
def play_actor_animation(anim_id)
return if anim_id <= 0 || !@spriteset
animation = $data_animations[anim_id]
return unless animation
$game_party.members.each do |actor|
sprite = find_actor_sprite(actor)
sprite.start_animation(animation) if sprite
end
end
def play_enemy_animation(target, anim_id)
return if anim_id <= 0 || !@spriteset
animation = $data_animations[anim_id]
return unless animation
sprite = find_enemy_sprite(target)
sprite.start_animation(animation) if sprite
end
def update_gun_animation
return unless @shooting_item
anim_id = @shooting_item.kind_animation_id
return if anim_id <= 0 || !@spriteset
animation = $data_animations[anim_id]
return unless animation
$game_party.members.each do |actor|
sprite = find_actor_sprite(actor)
next unless sprite
next if sprite.animation?
sprite.start_animation(animation)
end
end
def find_actor_sprite(actor)
return nil unless @spriteset
return nil unless @spriteset.respond_to?(:actor_sprites)
@spriteset.actor_sprites.find { |s| s.battler == actor }
end
def find_enemy_sprite(target)
return nil unless @spriteset
return nil unless @spriteset.respond_to?(:enemy_sprites)
@spriteset.enemy_sprites.find { |s| s.battler == target }
end
end
#==============================================================================
# ■ 战斗窗口中射击技能/物品的图标标记
#==============================================================================
class Window_BattleSkill < Window_SkillList
alias shooting_draw_item draw_item
def draw_item(index)
shooting_draw_item(index)
skill = @data[index]
return unless skill
if skill.shooting?
rect = item_rect(index)
draw_icon(132, rect.x + rect.width - 24, rect.y, true) rescue nil
end
end
end
class Window_BattleItem < Window_ItemList
alias shooting_draw_item draw_item
def draw_item(index)
shooting_draw_item(index)
item = @data[index]
return unless item
if item.shooting?
rect = item_rect(index)
draw_icon(132, rect.x + rect.width - 24, rect.y, true) rescue nil
end
end
end
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|