Files
infinitefusion-e18/Data/Scripts/005_Sprites/009_Sprite_DynamicShadows.rb
2025-06-07 08:16:50 -04:00

254 lines
7.9 KiB
Ruby

#===============================================================================
# Sprite_Shadow (Sprite_Ombre )
# Based on Genzai Kawakami's shadows, dynamisme & features by Rataime, extra
# features Boushy
# Modified by Peter O. to be compatible with Pokémon Essentials
#===============================================================================
class Sprite_Shadow < RPG::Sprite
attr_accessor :character
def initialize(viewport, character = nil, params = [])
super(viewport)
@source = params[0]
@anglemin = (params.size > 1) ? params[1] : 0
@anglemax = (params.size > 2) ? params[2] : 0
@self_opacity = (params.size > 4) ? params[4] : 100
@distancemax = (params.size > 3) ? params[3] : 350
@character = character
update
end
def dispose
@chbitmap&.dispose
super
end
def update
if !in_range?(@character, @source, @distancemax)
self.opacity = 0
return
end
super
if @tile_id != @character.tile_id ||
@character_name != @character.character_name ||
@character_hue != @character.character_hue
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_hue = @character.character_hue
@chbitmap&.dispose
if @tile_id >= 384
@chbitmap = pbGetTileBitmap(@character.map.tileset_name,
@tile_id, @character.character_hue)
self.src_rect.set(0, 0, 32, 32)
@ch = 32
@cw = 32
self.ox = 16
self.oy = 32
else
@chbitmap = AnimatedBitmap.new('Graphics/Characters/' + @character.character_name,
@character.character_hue)
@cw = @chbitmap.width / 4
@ch = @chbitmap.height / 4
self.ox = @cw / 2
self.oy = @ch
end
end
if @chbitmap.is_a?(AnimatedBitmap)
@chbitmap.update
self.bitmap = @chbitmap.bitmap
else
self.bitmap = @chbitmap
end
self.visible = !@character.transparent
if @tile_id == 0
sx = @character.pattern * @cw
sy = (@character.direction - 2) / 2 * @ch
if self.angle > 90 || angle < -90
case @character.direction
when 2 then sy = @ch * 3
when 4 then sy = @ch * 2
when 6 then sy = @ch
when 8 then sy = 0
end
end
self.src_rect.set(sx, sy, @cw, @ch)
end
self.x = ScreenPosHelper.pbScreenX(@character)
self.y = ScreenPosHelper.pbScreenY(@character) - 5
self.z = ScreenPosHelper.pbScreenZ(@character, @ch) - 1
self.zoom_x = ScreenPosHelper.pbScreenZoomX(@character)
self.zoom_y = ScreenPosHelper.pbScreenZoomY(@character)
self.blend_type = @character.blend_type
self.bush_depth = @character.bush_depth
if @character.animation_id != 0
animation = $data_animations[@character.animation_id]
animation(animation, true)
@character.animation_id = 0
end
@deltax = ScreenPosHelper.pbScreenX(@source) - self.x
@deltay = ScreenPosHelper.pbScreenY(@source) - self.y
self.color = Color.new(0, 0, 0)
@distance = ((@deltax**2) + (@deltay**2))
self.opacity = @self_opacity * 13_000 / ((@distance * 370 / @distancemax) + 6000)
self.angle = 57.3 * Math.atan2(@deltax, @deltay)
@angle_trigo = self.angle + 90
@angle_trigo += 360 if @angle_trigo < 0
if @anglemin != 0 || @anglemax != 0
if (@angle_trigo < @anglemin || @angle_trigo > @anglemax) && @anglemin < @anglemax
self.opacity = 0
return
end
if @angle_trigo < @anglemin && @angle_trigo > @anglemax && @anglemin > @anglemax
self.opacity = 0
return
end
end
end
def in_range?(element, object, range) # From Near's Anti Lag Script, edited
elemScreenX = ScreenPosHelper.pbScreenX(element)
elemScreenY = ScreenPosHelper.pbScreenY(element)
objScreenX = ScreenPosHelper.pbScreenX(object)
objScreenY = ScreenPosHelper.pbScreenY(object)
x = (elemScreenX - objScreenX) * (elemScreenX - objScreenX)
y = (elemScreenY - objScreenY) * (elemScreenY - objScreenY)
r = x + y
return r <= range * range
end
end
#===================================================
# ? CLASS Sprite_Character edit
#===================================================
class Sprite_Character < RPG::Sprite
alias shadow_initialize initialize unless method_defined?(:shadow_initialize)
def initialize(viewport, character = nil)
@ombrelist = []
@character = character
shadow_initialize(viewport, @character)
end
def setShadows(map, shadows)
if character.is_a?(Game_Event) && shadows.length > 0
params = XPML_read(map, "Shadow", @character, 4)
if params != nil
shadows.each do |shadow|
@ombrelist.push(Sprite_Shadow.new(viewport, @character, shadows))
end
end
end
if character.is_a?(Game_Player) && shadows.length > 0
shadows.each do |shadow|
@ombrelist.push(Sprite_Shadow.new(viewport, $game_player, shadow))
end
end
update
end
def clearShadows
@ombrelist.each { |s| s&.dispose }
@ombrelist.clear
end
alias shadow_update update unless method_defined?(:shadow_update)
def update
shadow_update
@ombrelist.each { |ombre| ombre.update }
end
end
#===================================================
# ? CLASS Game_Event edit
#===================================================
class Game_Event
attr_accessor :id
end
#===================================================
# ? CLASS Spriteset_Map edit
#===================================================
class Spriteset_Map
attr_accessor :shadows
alias shadow_initialize initialize unless method_defined?(:shadow_initialize)
def initialize(map = nil)
@shadows = []
warn = false
map = $game_map if !map
map.events.keys.sort.each do |k|
ev = map.events[k]
warn = true if ev.list != nil && ev.list.length > 0 && ev.list[0].code == 108 &&
(ev.list[0].parameters == ["s"] || ev.list[0].parameters == ["o"])
params = XPML_read(map, "Shadow Source", ev, 4)
@shadows.push([ev] + params) if params != nil
end
if warn == true
p "Warning : At least one event on this map uses the obsolete way to add shadows"
end
shadow_initialize(map)
@character_sprites.each do |sprite|
sprite.setShadows(map, @shadows)
end
$scene.spritesetGlobal.playersprite.setShadows(map, @shadows)
end
end
#===================================================
# ? XPML Definition, by Rataime, using ideas from Near Fantastica
#
# Returns nil if the markup wasn't present at all,
# returns [] if there wasn't any parameters, else
# returns a parameters list with "int" converted as int
# eg :
# begin first
# begin second
# param1 1
# param2 two
# begin third
# anything 3
#
# p XPML_read("first", event_id) -> []
# p XPML_read("second", event_id) -> [1, "two"]
# p XPML_read("third", event_id) -> [3]
# p XPML_read("forth", event_id) -> nil
#===================================================
def XPML_read(map, markup, event, max_param_number = 0)
parameter_list = nil
return nil if !event || event.list.nil?
event.list.size.times do |i|
if event.list[i].code == 108 &&
event.list[i].parameters[0].downcase == "begin " + markup.downcase
parameter_list = [] if parameter_list.nil?
((i + 1)...event.list.size).each do |j|
if event.list[j].code == 108
parts = event.list[j].parameters[0].split
if parts.size != 1 && parts[0].downcase != "begin"
if parts[1].to_i != 0 || parts[1] == "0"
parameter_list.push(parts[1].to_i)
else
parameter_list.push(parts[1])
end
else
return parameter_list
end
else
return parameter_list
end
return parameter_list if max_param_number != 0 && j == i + max_param_number
end
end
end
return parameter_list
end