Files
infinitefusion-e18/Data/Scripts/052_InfiniteFusion/dynamic_waterfall.rb
2025-06-07 08:16:50 -04:00

226 lines
6.4 KiB
Ruby

class Game_Temp
attr_accessor :temp_waterfall
attr_accessor :waterfall_sprites
attr_accessor :splash_sprites
attr_accessor :splash_coords
end
def generate_dynamic_waterfall(starting_x_position, waterfall_top_y, thickness=1)
map_height = $game_map.height - 8
echoln map_height
boulder_positions = []
CIANWOOD_BOULDER_IDS.each do |event_id|
event = $game_map.events[event_id]
boulder_positions << [event.x, event.y]
end
# Add columns from starting_x_position to the right
active_columns = []
(starting_x_position...(starting_x_position + thickness)).each do |x|
break if x >= $game_map.width # Don't go past map edge
active_columns << { x: x, y: waterfall_top_y }
end
visited = []
final_coords = []
splash_coords = []
while !active_columns.empty?
new_columns = []
active_columns.each do |segment|
x = segment[:x]
y = segment[:y]
next if visited.include?([x, y])
visited << [x, y]
while y < map_height
pos = [x, y]
final_coords << pos
if boulder_positions.include?(pos)
splash_coords << [x - 1, y] if x > 0
splash_coords << [x + 1, y] if x < $game_map.width - 1
splash_coords << [x, y]
new_y = y
new_columns << { x: x - 1, y: new_y } if x > 0 && !visited.include?([x - 1, new_y])
new_columns << { x: x + 1, y: new_y } if x < $game_map.width - 1 && !visited.include?([x + 1, new_y])
break
end
#currents section
if y > CIANWOOD_WATERFALL_EDGE+10
if !$game_map.passable?(x, y + 1, DIRECTION_DOWN)
splash_coords << [x, y + 1] if y + 1 < $game_map.height
break
end
end
if y == CIANWOOD_WATERFALL_EDGE
splash_coords << [x, y]
end
if y == map_height
splash_coords << [x, y]
end
y += 1
end
end
active_columns = new_columns
end
$game_temp.temp_waterfall = final_coords.uniq
$game_temp.splash_coords = splash_coords.uniq
echoln $game_temp.temp_waterfall
draw_waterfall_layer
end
def draw_waterfall_layer
return if !$game_temp.temp_waterfall || $game_temp.temp_waterfall.empty?
# Clear previous sprites
if $game_temp.waterfall_sprites
$game_temp.waterfall_sprites.each(&:dispose)
end
if $game_temp.splash_sprites
$game_temp.splash_sprites.each(&:dispose)
end
$game_temp.waterfall_sprites = []
$game_temp.splash_sprites = []
tile_size = 32
waterfall_tile_id = 0 # Waterfall
splash_tile_id = 4 # Splash impact tile, assuming we have this in the tileset
tileset = RPG::Cache.tileset($game_map.tileset_name)
# Draw waterfall tiles
$game_temp.temp_waterfall.each do |x, y|
sprite = Sprite.new(Spriteset_Map.viewport)
sprite.z = 10
sprite.x = x * tile_size
sprite.y = y * tile_size
sprite.bitmap = Bitmap.new(tile_size, tile_size)
source_rect = Rect.new(waterfall_tile_id * tile_size,0, tile_size, tile_size) # Frame 0
sprite.bitmap.blt(0, 0, tileset, source_rect)
# Store metadata for animation
sprite.instance_variable_set(:@frame_offset, rand(3)) # Optional: make them start at different frames
sprite.instance_variable_set(:@tile_x, x)
sprite.instance_variable_set(:@tile_y, y)
$game_temp.waterfall_sprites << sprite
end
# Draw splash impact tiles
$game_temp.splash_coords.each do |x, y|
sprite = Sprite.new(Spriteset_Map.viewport)
sprite.z = 300 # Draw splash above the waterfall
sprite.x = x * tile_size
sprite.y = y * tile_size
sprite.bitmap = Bitmap.new(tile_size, tile_size)
source_rect = Rect.new(splash_tile_id * tile_size,1, tile_size, tile_size) # Splash frame 0
sprite.bitmap.blt(0, 0, tileset, source_rect)
# Store metadata for splash animation
sprite.instance_variable_set(:@frame_offset, rand(3)) # Optional: make them start at different frames
sprite.instance_variable_set(:@tile_x, x)
sprite.instance_variable_set(:@tile_y, y)
$game_temp.splash_sprites << sprite
end
end
CIANWOOD_BOULDER_IDS = [2,3,5,6,
4 ]#chuck head
CIANWOOD_WATERFALL_EDGE =19
def player_on_temp_waterfall?
return false if !$game_temp.temp_waterfall
boulder_positions = []
CIANWOOD_BOULDER_IDS.each do |event_id|
event = $game_map.events[event_id]
boulder_positions << [event.x, event.y]
end
# Return false if a boulder is directly below the player
return false if boulder_positions.include?([$game_player.x, $game_player.y + 1])
return $game_temp.temp_waterfall.any? { |x, y, _| x == $game_player.x && y == $game_player.y }
end
class Spriteset_Map
alias_method :cianwood_waterfall_update, :update
def update
cianwood_waterfall_update
waterfall_edge = CIANWOOD_WATERFALL_EDGE
if $game_temp.waterfall_sprites
frame_count = Graphics.frame_count
tile_size = 32
autotile_id = 0
tileset = RPG::Cache.tileset($game_map.tileset_name)
# Animate waterfall sprites
$game_temp.waterfall_sprites.each do |sprite|
tile_y = sprite.instance_variable_get(:@tile_y)
frame_offset = sprite.instance_variable_get(:@frame_offset)
# Animate every 15 frames (change for speed control)
animation_frame = (frame_count / 15 + tile_y - frame_offset) % 4
tileset_x = (autotile_id * 4 + animation_frame) * tile_size
tileset_y = tile_y >= waterfall_edge ? tile_size : 0
source_rect = Rect.new(tileset_x,tileset_y, tile_size, tile_size)
sprite.bitmap.clear
sprite.bitmap.blt(0, 0, tileset, source_rect)
# Scroll with map
sprite.ox = $game_map.display_x / 4
sprite.oy = $game_map.display_y / 4
end
# Animate splash sprites
$game_temp.splash_sprites.each do |sprite|
tile_y = sprite.instance_variable_get(:@tile_y)
frame_offset = sprite.instance_variable_get(:@frame_offset)
# Animate every 10 frames for splash (you can adjust this speed)
offset = (autotile_id * 4 + 4) * tile_size
animation_frame = (frame_count / 10 + tile_y + frame_offset) % 4
source_rect = Rect.new((autotile_id * 4 + animation_frame) * tile_size + offset, 0, tile_size, tile_size)
sprite.bitmap.clear
sprite.bitmap.blt(0, 0, tileset, source_rect)
# Scroll with map
sprite.ox = $game_map.display_x / 4
sprite.oy = $game_map.display_y / 4
end
end
end
end