11-05-2024, 05:06 PM (This post was last modified: 11-05-2024, 06:15 PM by DerVVulfman.)
I don't know. I've used it in the past...
And wow! Revisiting it, I was a bit ... Its demo is so old, it still had the original Japanese scripts within. A 2005 script, it isn't up to what was later considered 'standard' coding.
NOT to say it is sloppy, but it is hard to read, doesn't have the game classes arranged within properly defined orders, doesn't have the configuration variables within a module...
I'm looking at it... kinda... to see about (at least) proper formatting.
I will say that the use of ALIAS is correct, the coder using his name, the name of the script, and the name of the method within. Its possible that he set the standard for alias renaming within the RMXP SDK project since he was a member of that team.
As to your request, I would assume that it would be that you want certain events (heroic NPCs) to reveal the map area as if they were the player. I am unsure if it can be done. BUT... I need to examine this... thing!!!!
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)
11-05-2024, 06:15 PM (This post was last modified: 11-05-2024, 06:16 PM by DerVVulfman.)
EDIT 1:
Well, I said I was considering 'proper formatting'... It sure helped. Consider THIS:
#-------------------------------------------------------------------------- # * Get map name #-------------------------------------------------------------------------- def map_name return load_data('Data/MapInfos.rxdata')[@map_id].name end #-------------------------------------------------------------------------- # * Frame Update: What tiles have been discovered or not currently covered #-------------------------------------------------------------------------- def update_fow_grid px = $game_player.x py = $game_player.y x = px - @fow_range start_y = py y = start_y count = 1 mod = 1
I think I kinda found WHERE to perform a simple bit of 'surgery' to the original script. The below change works:
#-------------------------------------------------------------------------- # * Frame Update: What tiles have been discovered or not currently covered # px : (Optional) x coordinate for target event revealing map # py : (Optional) y coordinate for target event revealing map #-------------------------------------------------------------------------- def update_fow_grid(px=$game_player.x, py=$game_player.y) # Define x/y update coordinates based on passed x/y values x = px - @fow_range start_y = py y = start_y count = 1 mod = 1
AND... it actually works.
By doing so, I can insert x/y coordinates into the command to reveal 'areas' outside of the player's coordinates, assuming I also pass a couple other commands too:
This was the result, the events around me vanished while the events in the 'circled' dynamic area were visible. Fixed by re-executing the commands with the focus on the player.
Yesterday, 04:11 AM (This post was last modified: Yesterday, 05:16 AM by Tepe.)
I've updated this script a bit and moved all the configuration options to the module, I'll make it available as soon as I'm on the computer. What you've shown is some progress. Although we still need to think about how to define events in the module table that can explore the map with the player but independently of him and assign them their own visibility radius. I haven't tested your demo yet so I don't know if this is exactly what I was thinking.
-------------------------------------------
Ou I see Your code is very very clearly than what i have done with original. But...i have one more option.
In my code You can set options of the map in script not in map name. This is helpful when You use location script and he download map name.
Code:
#==============================================================================
# ** Fog of War
#------------------------------------------------------------------------------
# Version 2.0, 2005-11-21
# by Wachunga
#==============================================================================
=begin
0.8 - original release
0.85
- added colour parameter to map names
- fixed bug where map grids overlapped
0.9
- switched over to a tilemap (from a sprite)
- now more compatible with minimap scripts (but they'll have to take
extra tilemap into account)
1.0
- switched over to an autotile instead of using a custom tileset
* edges looks nicer, but gradual fading had to be removed
* colour parameter no longer possible (set by autotile)
- move event (including jumping and speed changes) bug fixed
- teleportation bug fixed
- some optimization
- made compatible with Cogwheel's Pixel Movement script
(see http://www.rmxp.net/forums/index.php?showtopic=24716 for details)
1.01
- fixed bug when teleporting from map without fow to a map with fow
2.0
- now two independent types of fog of war:
* static, which never returns (i.e. typical RTS "terrain" fog)
* dynamic, which returns once out of visual range and can optionally
hide map events (i.e. typical RTS "unit" fog)
- now using a compact version of Near's Dynamic Maps script
- fog of war is now above weather and normal fog
- added support for much larger visual ranges (0 - 9)
- added support for option to set up fog of war from a call script event
command
- optimization
A map specified as having "fog of war" (fow) has tiles that are (fully or
partially) obscured until the player gets within visual range. The amount of
fow to disappear as the player moves depends on the visual range specified.
Gamers with experience playing Real Time Strategy games like Warcraft, Age of
Empires, etc. should be quite familiar with the concept.
This script supports two kinds of fog of war: static and dynamic.
Static fow is the kind that typically hides terrain in RTS games. It covers
the entire map until the player explores the area, discovering the underlying
terrain. Once static fow disappears from an area of the map, it stays gone
indefinitely (even if loading a saved game, leaving the map and returning
later, going to the menu, etc).
Dynamic fow is identical to the static kind except that it doesn't stay gone
forever: as soon as the player leaves visual range of an explored tile,
dynamic fow covers it again. This kind of fow is typically used to hide enemy
units in RTS games.
SETUP:
There's no need to add the autotile via the database. Just place the
file in the autotile folder, import it, and change the FOW_AT_NAME constant
to the appropriate filename. To change the colour of the fog of war you must
create a new autotile. (However, opacity is customizable by constants below.)
To indicate a map is to have either (or both) of these kinds of fog of war,
include <fow> in its name (via "Map properties"). To enable both static and
dynamic fow, you can either add nothing more (since it's the default), or
add <s><d> (or <d><s>). To enable one or the other, just add the appropriate
one (e.g. <s> for static, <d> for dynamic). You may also optionally specify a
visual range between 0 and 9 in the map name (e.g. <5>), noting that 3 is
the default. Here are some example map names:
"your-map-name <fow><2>" (defaults to static&dynamic on; range specified as 2)
"your-map-name <fow><s>" (only static fow is on; range defaults to 3)
"your-map-name <fow><d><8>" (only dynamic fow is on; range specified as 8)
Alternatively, fog of war can be setup via a call script event command using
the fog_of_war global method. Detailed instructions are just before
the method itself.
Finally, an edited version of Near Fantastica's Dynamic Maps script needs
to be below this one. You may find it at the following URL:
http://www.rmxp.net/forums/index.php?showtopic=24716
The ranges work as follows:
range = 0 reveals just the square on which the player stands
range = 1 is the same as range 0 plus four adjacent tiles
i.e. @
@P@
@
range = 2 is the same as range 1 plus eight additional tiles
i.e. @
@@@
@@P@@
@@@
@
range = 3 (default) is the same as range 2 plus twelve additional tiles
i.e. @
@@@
@@@@@
@@@P@@@
@@@@@
@@@
@
etc.
Note: I've taken great pains to optimize this script as much as possible
(which unfortunately reduces the readability of the code). There shouldn't be
much visible effect on frame rate.
=end
module FogOfWarSettings
#------------------------------------------------------------------------------
# filename of the fog of war autotile (used for both):
FOW_AT_NAME = 'fow_default' # Użyj odpowiedniego indeksu autotile zamiast nazwy
# the opacity of static (non-returning) and dynamic (returning) fog of war
# (value between 0 and 255)
FOW_STATIC_OPACITY = 255
FOW_DYNAMIC_OPACITY = 0
# whether or not dynamic fow hides map events
FOW_DYNAMIC_HIDES_EVENTS = false
# default range of fog of war (if not specified in map name)
FOW_RANGE_DEFAULT = 3
#------------------------------------------------------------------------------
# internal constants - no need to edit
FOW = 0b00
REVEALED = 0b01
# tiles with no surrounding fog are flagged "SKIP" for efficiency
SKIP = 0b10
#------------------------------------------------------------------------------
# Method to retrieve settings for a given map
def self.settings_for_map(map_id)
option = MAP_OPTIONS.find { |map| map[:id] == map_id }
option || { :enabled => false }
end
end
def fog_of_war(static, dynamic, range = FOW_RANGE_DEFAULT, reset = false)
if static == nil or dynamic == nil
print 'Two true/false parameters are required in call to fog_of_war.'
exit
elsif range < 0 or range > 9
print 'Invalid range in call to fog_of_war (only 0-9 is valid).'
exit
end
$game_map.fow_static = static
$game_map.fow_dynamic = dynamic
$game_map.fow_range = range
if reset
$game_map.fow_grid = nil
end
if not $game_map.fow_static and not $game_map.fow_dynamic
$game_map.fow = false
$scene.spriteset.fow_tilemap.dispose
# set all events back to visible
for i in $game_map.events.keys
$game_map.events[i].transparent = false
end
else
# static or dynamic fow (or both) are on
$game_map.fow = true
if $game_map.fow_grid == nil # only if not already defined
$game_map.fow_grid = Table.new($game_map.width, $game_map.height, 2)
for i in 0...$game_map.fow_grid.xsize
for j in 0...$game_map.fow_grid.ysize
$game_map.fow_grid[i,j,1] = $game_map.fow_grid[i,j,0] = FogOfWarSettings::FOW
end
end
end
if $game_map.fow_dynamic
$game_map.fow_revealed = $game_map.fow_last_revealed = []
end
$scene.spriteset.initialize_fow
end
end
alias wachunga_fow_gm_setup setup
def setup(map_id)
wachunga_fow_gm_setup(map_id)
@fow = false
@fow_dynamic = false
@fow_static = false
@fow_grid = nil
@fow_range = nil
# Use settings from FogOfWarSettings module
settings = FogOfWarSettings.settings_for_map(map_id)
@fow = settings[:enabled]
@fow_static = true if @fow # default to true if fog of war is enabled
@fow_dynamic = true if @fow
@fow_range = settings[:visibility_radius] if settings[:visibility_radius]
if @fow
if @fow_grid == nil # only if not already defined
@fow_grid = Table.new(@map.width, @map.height, 2)
for i in 0...@fow_grid.xsize
for j in 0...@fow_grid.ysize
@fow_grid[i,j,1] = @fow_grid[i,j,0] = FogOfWarSettings::FOW
end
end
end
@fow_revealed = @fow_last_revealed = [] if @fow_dynamic
end
end
def map_name
return load_data('Data/MapInfos.rxdata')[@map_id].name
end
def update_fow_grid
px = $game_player.x
py = $game_player.y
x = px - @fow_range
start_y = py
y = start_y
count = 1
mod = 1
# loop through all tiles in visible range
until x == (px + @fow_range + 1)
i = count
while i > 0
if valid?(x,y)
if @fow_static
@fow_grid[x,y,1] |= FogOfWarSettings::REVEALED
end
if @fow_dynamic
@fow_grid[x,y,0] = FogOfWarSettings::REVEALED if @fow_grid[x,y,0] == FogOfWarSettings::FOW
@fow_revealed.push([x,y])
end
end
y -= 1
i -= 1
end
if x == px
mod = -1
end
x += 1
start_y += 1 * mod
y = start_y
count += 2 * mod
end
if @fow_dynamic
if @fow_last_revealed != []
# make dynamic fog return once out of visual range
for t in @fow_last_revealed - @fow_revealed
@fow_grid[t[0],t[1],0] = FogOfWarSettings::FOW
end
end
@fow_last_revealed = @fow_revealed
@fow_revealed = []
end
end
end
alias wachunga_fow_ssm_initialize initialize
def initialize
initialize_fow if $game_map.fow
wachunga_fow_ssm_initialize
end
=begin
Initializes fog of war.
=end
def initialize_fow
@fow_tilemap = Tilemap.new
@fow_tilemap.map_data = Table.new($game_map.width, $game_map.height, 3)
@fow_tilemap.priorities = Table.new(144)
@fow_autotiles = Hash.new(0)
j = 48 # starting autotile index
for i in Autotile_Keys
@fow_autotiles[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@fow_autotiles[i] = @fow_autotiles[Duplicate_Keys[i]]
end
if $game_map.fow_static
for m in 0...$game_map.fow_grid.xsize
for n in 0...$game_map.fow_grid.ysize
# reset SKIP flag
$game_map.fow_grid[m,n,1] &= ~FogOfWarSettings::SKIP
end
end
at = Bitmap.new(96,128)
at.blt(0,0,RPG::Cache.autotile(FogOfWarSettings::FOW_AT_NAME),\
Rect.new(0,0,96,128),FogOfWarSettings::FOW_STATIC_OPACITY)
@fow_tilemap.autotiles[0] = at
# set everything to fog
for x in 0...$game_map.width
for y in 0...$game_map.height
@fow_tilemap.map_data[x,y,2] = 48 # fog
end
end
# set to highest priority
for i in 48...96
@fow_tilemap.priorities[i] = 5
end
end
if $game_map.fow_dynamic
bm = Bitmap.new(96,128)
bm.blt(0,0,RPG::Cache.autotile(FogOfWarSettings::FOW_AT_NAME),\
Rect.new(0,0,96,128),FogOfWarSettings::FOW_DYNAMIC_OPACITY)
@fow_tilemap.autotiles[1] = bm
# unlike tilemap for static, set everything to clear
for x in 0...$game_map.width
for y in 0...$game_map.height
@fow_tilemap.map_data[x,y,1] = 0
end
end
# set to highest priority
for i in 96...144
@fow_tilemap.priorities[i] = 5
end
end
$game_map.update_fow_grid
update_fow_tilemap
update_event_transparency if $game_map.fow_dynamic
end
=begin
Updates the (static and/or dynamic) fog of war tilemap based on the map's
underlying grid.
=end
def update_fow_tilemap
if $game_map.fow_static
checked = Table.new($game_map.width,$game_map.height)
for j in 0...$game_map.width
for k in 0...$game_map.height
checked[j,k] = 0
end
end
end
dx = ($game_map.display_x/128).round
dy = ($game_map.display_y/128).round
# to increase performance, only process fow currently on the screen
for x in dx-1 .. dx+21
for y in dy-1 .. dy+16
# check boundaries
if not $game_map.valid?(x,y) then next end
if $game_map.fow_dynamic
if $game_map.fow_grid[x,y,0] == FogOfWarSettings::REVEALED
@fow_tilemap.map_data[x,y,1] = 0 if @fow_tilemap.map_data[x,y,1]!=0
else
@fow_tilemap.map_data[x,y,1]=96 if @fow_tilemap.map_data[x,y,1]!=96
end
end
if $game_map.fow_static
if $game_map.fow_grid[x,y,1] == FogOfWarSettings::REVEALED # (but not SKIP)
others = false;
@fow_tilemap.map_data[x,y,2] = 0 if @fow_tilemap.map_data[x,y,2]!=0
for i in x-1 .. x+1
for j in y-1 .. y+1
# check new boundaries
if not $game_map.valid?(i,j) then next end
if $game_map.fow_grid[i,j,1] == FogOfWarSettings::FOW
others = true # can't flag as SKIP because there's nearby fog
if checked[i,j] == 0
checked[i,j] = 1
# only fill if not already revealed
if @fow_tilemap.map_data[i,j,2] != 0
adj = check_adjacent(i,j,1,$game_map.fow_grid,FogOfWarSettings::REVEALED)
if adj != nil
@fow_tilemap.map_data[i,j,2] =
eval '@fow_autotiles[adj.to_i]'
end
end
end
end
end
end
if not others
# no adjacent static fog found, so flag tile to avoid reprocessing
$game_map.fow_grid[x,y,1] |= FogOfWarSettings::SKIP
end
end
end # fow_static
end # for
end # for
if $game_map.fow_dynamic
if $game_map.fow_static
for x in dx-1 .. dx+21
for y in dy-1 .. dy+16
# erase dynamic fow if static fow is above it anyway
if @fow_tilemap.map_data[x,y,2] == 48
@fow_tilemap.map_data[x,y,1]=0 if @fow_tilemap.map_data[x,y,1]!=0
end
end
end
end
# calculate autotiles for dynamic fow (around player)
px = $game_player.x
py = $game_player.y
tiles = []
x = px - ($game_map.fow_range+1)
y_top = py
mod_top = -1
y_bot = py
mod_bot = 1
until x == px + ($game_map.fow_range+2)
tiles.push([x,y_top]) if $game_map.valid?(x,y_top)
tiles.push([x,y_bot]) if $game_map.valid?(x,y_bot)
if x == px
mod_top = 1
mod_bot = -1
x+=1
next
end
y_top+=1*mod_top
y_bot+=1*mod_bot
tiles.push([x,y_top]) if $game_map.valid?(x,y_top)
tiles.push([x,y_bot]) if $game_map.valid?(x,y_bot)
x+=1
end
tiles.uniq.each do |t|
adj = check_adjacent(t[0],t[1],0,$game_map.fow_grid,FogOfWarSettings::REVEALED)
if adj != nil
@fow_tilemap.map_data[t[0],t[1],1] =
(eval '@fow_autotiles[adj.to_i]') + 48
end
end
end
end
=begin
Update event transparency based on dynamic fog.
Note that if a specific character is passed as a parameter then only
its transparency is updated; otherwise, all events are processed.
=end
def update_event_transparency(pChar = nil)
return if not FogOfWarSettings::FOW_DYNAMIC_HIDES_EVENTS
if pChar == nil
# check them all
for i in $game_map.events.keys
event = $game_map.events[i]
if $game_map.fow_grid[event.x,event.y,0] == FogOfWarSettings::FOW
event.transparent = true
else
event.transparent = false
end
end
else
# just check the one
pChar.transparent=($game_map.fow_grid[pChar.x,pChar.y,0]==FogOfWarSettings::FOW) ?true:false
end
end
# create a list of tiles adjacent to a specific tile that don't match a flag
# (used for calculating tiles within an autotile)
def check_adjacent(i,j,k,grid,flag)
return if not $game_map.valid?(i,j) or grid == nil or flag == nil
adj = ''
if (i == 0)
adj << '147'
else
if (j == 0) then adj << '1'
else
if (grid[i-1,j-1,k] != flag) then adj << '1' end
end
if (grid[i-1,j,k] != flag) then adj << '4' end
if (j == $game_map.height-1) then adj << '7'
else
if (grid[i-1,j+1,k] != flag) then adj << '7' end
end
end
if (i == $game_map.width-1)
adj << '369'
else
if (j == 0) then adj << '3'
else
if (grid[i+1,j-1,k] != flag) then adj << '3' end
end
if (grid[i+1,j,k] != flag) then adj << '6' end
if (j == $game_map.height-1) then adj << '9'
else
if (grid[i+1,j+1,k] != flag) then adj << '9' end
end
end
if (j == 0)
adj << '2'
else
if (grid[i,j-1,k] != flag) then adj << '2' end
end
if (j == $game_map.height-1)
adj << '8'
else
if (grid[i,j+1,k] != flag) then adj << '8' end
end
# if no adjacent fog, set it as 0
if (adj == '') then adj = '0' end
# convert to an array, sort, and then back to a string
return adj.split(//).sort.join
end
alias wachunga_fow_ssm_dispose dispose
def dispose
@fow_tilemap.dispose if @fow_tilemap != nil
wachunga_fow_ssm_dispose
end
alias wachunga_fow_ssm_update update
def update
if $game_map.fow
@fow_tilemap.ox = $game_map.display_x / 4
@fow_tilemap.oy = $game_map.display_y / 4
@fow_tilemap.update
end
wachunga_fow_ssm_update
end
end
class Game_Character
alias wachunga_fow_gch_initialize initialize
def initialize
wachunga_fow_gch_initialize
@last_x = @x
@last_y = @y
end
alias wachunga_fow_gch_update_move update_move
def update_move
wachunga_fow_gch_update_move
if $game_map.fow
if $game_map.fow_dynamic and (@x != @last_x or @y != @last_y)\
and self != $game_player
end
end
@last_x = @x
@last_y = @y
end
end
def update_jump
super
# only update when about to land, not revealing anything jumped over
if $game_map.fow and @jump_count == 0
$game_map.update_fow_grid
$scene.spriteset.update_event_transparency if $game_map.fow_dynamic
$scene.spriteset.update_fow_tilemap
end
end
def update_move
if $game_map.fow and (@x != @last_x or @y != @last_y)
unless jumping?
$game_map.update_fow_grid
$scene.spriteset.update_event_transparency if $game_map.fow_dynamic
$scene.spriteset.update_fow_tilemap
end
end
super
end
The function to return the index of a single tile within an autotile
(given by at_index) is (at_index-1)*48 + col-1 + (row-1)*8
(where row, col, and at_index are again NOT zero-indexed)
=end
=begin
The following array lists systematic keys which are based on adjacent
walls (where 'W' is the wall itself):
1 2 3
4 W 6
7 8 9
e.g. 268 is the key that will be used to refer to the autotile
which has adjacent walls north, east, and south. For the Castle Prison
tileset (autotile #1), this is 67.
11 hours ago(This post was last modified: 11 hours ago by Tepe.)
Okay, this is my extended version of this script.
Now you can add fog of war to the map based on its ID and assign it any configuration!
Unfortunately it doesn't have the option to reveal the map through events yet, but with @DerVVulfman help there is a chance we can achieve that. :)
Code:
#===============================================================================
# ** FOG OF WAR V 2.5
#-------------------------------------------------------------------------------
# Author : Wachunga
#-------------------------------------------------------------------------------
# Website : None
#-------------------------------------------------------------------------------
# Contact : None
#-------------------------------------------------------------------------------
# Modifier : Tepe
#-------------------------------------------------------------------------------
# Website : http://www.rpgmaker.pl
#-------------------------------------------------------------------------------
# Contact : simple.pixel.pictures@gmail.com
#-------------------------------------------------------------------------------
# Support : DerWulfman (code clarity)
#-------------------------------------------------------------------------------
# Website : http://www.save-point.org
#-------------------------------------------------------------------------------
# Contact : None
#-------------------------------------------------------------------------------
# Related modules : None
#-------------------------------------------------------------------------------
# Description:
=begin
0.8 - original release
0.85
- added colour parameter to map names
- fixed bug where map grids overlapped
0.9
- switched over to a tilemap (from a sprite)
- now more compatible with minimap scripts (but they'll have to take
extra tilemap into account)
1.0
- switched over to an autotile instead of using a custom tileset
* edges looks nicer, but gradual fading had to be removed
* colour parameter no longer possible (set by autotile)
- move event (including jumping and speed changes) bug fixed
- teleportation bug fixed
- some optimization
- made compatible with Cogwheel's Pixel Movement script
(see http://www.rmxp.net/forums/index.php?showtopic=24716 for details)
1.01
- fixed bug when teleporting from map without fow to a map with fow
2.0
- now two independent types of fog of war:
* static, which never returns (i.e. typical RTS "terrain" fog)
* dynamic, which returns once out of visual range and can optionally
hide map events (i.e. typical RTS "unit" fog)
- now using a compact version of Near's Dynamic Maps script
- fog of war is now above weather and normal fog
- added support for much larger visual ranges (0 - 9)
- added support for option to set up fog of war from a call script event
command
- optimization
2.5
- The ability to assign any fog of war configuration to a map based
on its ID.
A map specified as having "fog of war" (fow) has tiles that are (fully or
partially) obscured until the player gets within visual range. The amount of
fow to disappear as the player moves depends on the visual range specified.
Gamers with experience playing Real Time Strategy games like Warcraft, Age of
Empires, etc. should be quite familiar with the concept.
This script supports two kinds of fog of war: static and dynamic.
Static fow is the kind that typically hides terrain in RTS games. It covers
the entire map until the player explores the area, discovering the underlying
terrain. Once static fow disappears from an area of the map, it stays gone
indefinitely (even if loading a saved game, leaving the map and returning
later, going to the menu, etc).
Dynamic fow is identical to the static kind except that it doesn't stay gone
forever: as soon as the player leaves visual range of an explored tile,
dynamic fow covers it again. This kind of fow is typically used to hide enemy
units in RTS games.
SETUP:
Fog can be assigned to any map based on its ID number.
For each map, any fog configuration can be used.
To add another map, simply add the following code in the appropriate
section of the module:
{ :map_id => 1,
:fow_at_name => 'fow_default', # Name of the autotile file on map 1
:fow_static => true, # Use static fog on the map
:fow_static_opacity => 255, # Opacity of the static fog
:fow_dynamic => false, # Use dynamic fog on the map
:fow_dynamic_opacity => 100, # Opacity of the dynamic fog
:fow_hides_events => false, # Whether dynamic fog hides events
:visibility_radius => 3, # Visibility radius around the player
},
Alternatively, fog of war can be setup via a call script event command using
the fog_of_war global method. Detailed instructions are just before
the method itself.
Finally, an edited version of Near Fantastica's Dynamic Maps script needs
to be below this one. You may find it at the following URL:
http://www.rmxp.net/forums/index.php?showtopic=24716
The ranges work as follows:
range = 0 reveals just the square on which the player stands
range = 1 is the same as range 0 plus four adjacent tiles
i.e. @
@P@
@
range = 2 is the same as range 1 plus eight additional tiles
i.e. @
@@@
@@P@@
@@@
@
range = 3 (default) is the same as range 2 plus twelve additional tiles
i.e. @
@@@
@@@@@
@@@P@@@
@@@@@
@@@
@
etc.
Note: I've taken great pains to optimize this script as much as possible
(which unfortunately reduces the readability of the code). There shouldn't be
much visible effect on frame rate.
=end
#===============================================================================
#==============================================================================
# ** Fog_of_War
#------------------------------------------------------------------------------
# This module handles the flags, tile placement and key values for the fog
# of war tileset which covers defined maps.
#==============================================================================
module Fog_of_War
#------------------------------------------------------------------------------
# filename of the fog of war autotile (used for both):
FOW_AT_NAME_DEFAULT = 'fow_default'
# the opacity of static (non-returning) and dynamic (returning) fog of war
# (value between 0 and 255)
# note that static fow appears on top of its dynamic counterpart (if both on)
FOW_STATIC_OPACITY_DEFAULT = 255
FOW_DYNAMIC_OPACITY_DEFAULT = 100
# whether or not dynamic fow hides map events
FOW_HIDES_EVENTS_DEFAULT = true
# default range of fog of war (if not specified in map name)
FOW_RANGE_DEFAULT = 3
MAP_OPTIONS = [
{ :map_id => 3,
:fow_at_name => 'fow_default', # Name of the autotile file on map 1
:fow_static => true, # Use static fog on the map
:fow_static_opacity => 255, # Opacity of the static fog
:fow_dynamic => false, # Use dynamic fog on the map
:fow_dynamic_opacity => 100, # Opacity of the dynamic fog
:fow_hides_events => false, # Whether dynamic fog hides events
:visibility_radius => 3, # Visibility radius around the player
},
{ :map_id => 2,
:fow_at_name => 'fow_default', # Name of the autotile file on map 1
:fow_static => false, # Use static fog on the map
:fow_static_opacity => 255, # Opacity of the static fog
:fow_dynamic => true, # Use dynamic fog on the map
:fow_dynamic_opacity => 100, # Opacity of the dynamic fog
:fow_hides_events => false, # Whether dynamic fog hides events
:visibility_radius => 3, # Visibility radius around the player
}
]
# Method to retrieve settings for a given map
def self.settings_for_map(map_id)
option = MAP_OPTIONS.find { |map| map[:map_id] == map_id }
option || { :fow_static => false }
end
end
#==============================================================================
# ** Fog_of_War
#------------------------------------------------------------------------------
# This module handles the flags, tile placement and key values for the fog
# of war tileset which covers defined maps.
#==============================================================================
module Fog_of_War
#--------------------------------------------------------------------------
# * Invariables
#--------------------------------------------------------------------------
FOW = 0b00
REVEALED = 0b01
SKIP = 0b10 # Flag for tiles with no surrounding fog
if @fow
if @fow_grid == nil # only if not already defined
@fow_grid = Table.new(@map.width, @map.height, 2)
for i in 0...@fow_grid.xsize
for j in 0...@fow_grid.ysize
@fow_grid[i,j,1] = @fow_grid[i,j,0] = Fog_of_War::FOW
end
end
end
@fow_revealed = @fow_last_revealed = [] if @fow_dynamic
end
end
#--------------------------------------------------------------------------
# * Get map name
#--------------------------------------------------------------------------
def map_name
return load_data('Data/MapInfos.rxdata')[@map_id].name
end
#--------------------------------------------------------------------------
# * Frame Update: What tiles have been discovered or not currently covered
# px : (Optional) x coordinate for target event revealing map
# py : (Optional) y coordinate for target event revealing map
#--------------------------------------------------------------------------
def update_fow_grid(px=$game_player.x, py=$game_player.y)
x = px - @fow_range
start_y = py
y = start_y
count = 1
mod = 1
# loop through all tiles in visible range
until x == (px + @fow_range+1)
#
i = count
#
while i > 0
if valid?(x,y)
if @fow_static
@fow_grid[x,y,1] |= Fog_of_War::REVEALED
end
if @fow_dynamic
if @fow_grid[x,y,0] == Fog_of_War::FOW
@fow_grid[x,y,0] = Fog_of_War::REVEALED
end
@fow_revealed.push([x,y])
end
end
y -= 1
i -= 1
end
#
if x == px
mod = -1
end
#
x += 1
start_y += 1*mod
y = start_y
count += 2*mod
#
end
if @fow_dynamic
if @fow_last_revealed != []
# make dynamic fog return once out of visual range
for t in @fow_last_revealed - @fow_revealed
@fow_grid[t[0],t[1],0] = Fog_of_War::FOW
end
end
@fow_last_revealed = @fow_revealed
@fow_revealed = []
end
end
end
#==============================================================================
# ** Game_Character
#------------------------------------------------------------------------------
# This class deals with characters. It's used as a superclass for the
# Game_Player and Game_Event classes.
#==============================================================================
class Game_Character
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
alias wachunga_fow_gch_initialize initialize
alias wachunga_fow_gch_update_move update_move
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
# Perform the original method
wachunga_fow_gch_initialize
@last_x = @x
@last_y = @y
end
#--------------------------------------------------------------------------
# * Update frame (move)
#--------------------------------------------------------------------------
def update_move
# Perform the original method
wachunga_fow_gch_update_move
if $game_map.fow
if $game_map.fow_dynamic and (@x != @last_x or @y != @last_y)\
and self != $game_player
# check if character entered/left player's visual range
$scene.spriteset.update_event_transparency(self)
end
end
@last_x = @x
@last_y = @y
end
end
#==============================================================================
# ** Game_Player
#------------------------------------------------------------------------------
# This class handles the player. Its functions include event starting
# determinants and map scrolling. Refer to "$game_player" for the one
# instance of this class.
#==============================================================================
class Game_Player < Game_Character
#--------------------------------------------------------------------------
# * Frame Update (jump)
#--------------------------------------------------------------------------
def update_jump
# Inherit original method statements from the Game_Character superclass
super
# only update when about to land, not revealing anything jumped over
if $game_map.fow and @jump_count == 0
$game_map.update_fow_grid
$scene.spriteset.update_event_transparency if $game_map.fow_dynamic
$scene.spriteset.update_fow_tilemap
end
end
#--------------------------------------------------------------------------
# * Update frame (move)
#--------------------------------------------------------------------------
def update_move
if $game_map.fow and (@x != @last_x or @y != @last_y)
unless jumping?
$game_map.update_fow_grid
$scene.spriteset.update_event_transparency if $game_map.fow_dynamic
$scene.spriteset.update_fow_tilemap
end
end
# Inherit original method statements from the Game_Character superclass
super
end
end
#==============================================================================
# ** Spriteset_Map
#------------------------------------------------------------------------------
# This class brings together map screen sprites, tilemaps, etc.
# It's used within the Scene_Map class.
#==============================================================================
class Spriteset_Map
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :fow_tilemap # Fog of of war tilemap
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias wachunga_fow_ssm_initialize initialize
alias wachunga_fow_ssm_dispose dispose
alias wachunga_fow_ssm_update update
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
# Initialize the fog of war if flagged
initialize_fow if $game_map.fow
# Perform the original method
wachunga_fow_ssm_initialize
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
def dispose
# Dispose of fog of war if it exists
@fow_tilemap.dispose if @fow_tilemap != nil
# Perform the original method
wachunga_fow_ssm_dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Adjust origin position and update the fog of war if it exists
if $game_map.fow
@fow_tilemap.ox = $game_map.display_x / 4
@fow_tilemap.oy = $game_map.display_y / 4
@fow_tilemap.update
end
update_event_transparency
# Perform the original method
wachunga_fow_ssm_update
end
#--------------------------------------------------------------------------
# * Object Initialization : fog of war
#--------------------------------------------------------------------------
def initialize_fow
# Get settings from MAP_OPTIONS for the current map
settings = Fog_of_War.settings_for_map($game_map.map_id)
# If autotile file name is not defined, use the default
fow_at_name = settings[:fow_at_name] || Fog_of_War::FOW_AT_NAME_DEFAULT
# Define tilemap for the fog
@fow_tilemap = Tilemap.new
@fow_tilemap.map_data = Table.new($game_map.width, $game_map.height, 3)
@fow_tilemap.priorities = Table.new(144)
@fow_autotiles = Hash.new(0)
# Set initial autotile index
j = 48
# Define autotiles for the fog
for i in Fog_of_War::Autotile_Keys
@fow_autotiles[i] = j
j += 1
end
# Add duplicates
for i in Fog_of_War::Duplicate_Keys.keys
@fow_autotiles[i] = @fow_autotiles[Fog_of_War::Duplicate_Keys[i]]
end
# If static fog
if $game_map.fow_static
# Traverse the fog grid
for m in 0...$game_map.fow_grid.xsize
for n in 0...$game_map.fow_grid.ysize
# Reset SKIP flags
$game_map.fow_grid[m, n, 1] &= ~Fog_of_War::SKIP
end
end
# Blit autotile and apply to tilemap with opacity for static fog
at = Bitmap.new(96, 128)
at.blt(0, 0, RPG::Cache.autotile(fow_at_name), Rect.new(0, 0, 96, 128), settings[:fow_static_opacity] || Fog_of_War::FOW_STATIC_OPACITY_DEFAULT)
@fow_tilemap.autotiles[0] = at
# Set all fields to fog
for x in 0...$game_map.width
for y in 0...$game_map.height
@fow_tilemap.map_data[x, y, 2] = 48 # fog
end
end
# Set to highest priority
for i in 48...96
@fow_tilemap.priorities[i] = 5
end
end
# If dynamic fog
if $game_map.fow_dynamic
# Blit autotile for dynamic fog with opacity
bm = Bitmap.new(96, 128)
bm.blt(0, 0, RPG::Cache.autotile(fow_at_name), Rect.new(0, 0, 96, 128), settings[:fow_dynamic_opacity] || Fog_of_War::FOW_DYNAMIC_OPACITY_DEFAULT)
@fow_tilemap.autotiles[1] = bm
# Traverse the game map
for x in 0...$game_map.width
for y in 0...$game_map.height
# Set field as clear (unlike tilemap for static maps)
@fow_tilemap.map_data[x, y, 1] = 0
end
end
# Set to highest priority
for i in 96...144
@fow_tilemap.priorities[i] = 5
end
end
# Update the game map, fog of war tiles, and events for dynamic maps
$game_map.update_fow_grid
update_fow_tilemap
end
#--------------------------------------------------------------------------
# * Object Initialization : fog of war - handling static or dynamic tilemap
#--------------------------------------------------------------------------
def update_fow_tilemap
if $game_map.fow_static
checked = Table.new($game_map.width,$game_map.height)
for j in 0...$game_map.width
for k in 0...$game_map.height
checked[j,k] = 0
end
end
end
dx = ($game_map.display_x/128).round
dy = ($game_map.display_y/128).round
# to increase performance, only process fow currently on the screen
for x in dx-1 .. dx+21
for y in dy-1 .. dy+16
# check boundaries
if not $game_map.valid?(x,y) then next end
if $game_map.fow_dynamic
if $game_map.fow_grid[x,y,0] == Fog_of_War::REVEALED
@fow_tilemap.map_data[x,y,1] = 0 if @fow_tilemap.map_data[x,y,1]!=0
else
@fow_tilemap.map_data[x,y,1]=96 if @fow_tilemap.map_data[x,y,1]!=96
end
end
if $game_map.fow_static
if $game_map.fow_grid[x,y,1] == Fog_of_War::REVEALED # (but not SKIP)
others = false;
@fow_tilemap.map_data[x,y,2] = 0 if @fow_tilemap.map_data[x,y,2]!=0
for i in x-1 .. x+1
for j in y-1 .. y+1
# check new boundaries
if not $game_map.valid?(i,j) then next end
if $game_map.fow_grid[i,j,1] == Fog_of_War::FOW
others = true # can't flag as SKIP because there's nearby fog
if checked[i,j] == 0
checked[i,j] = 1
# only fill if not already revealed
if @fow_tilemap.map_data[i,j,2] != 0
adj = check_adjacent(i,j,1,$game_map.fow_grid,Fog_of_War::REVEALED)
if adj != nil
@fow_tilemap.map_data[i,j,2] =
eval '@fow_autotiles[adj.to_i]'
end
end
end
end
end
end
if not others
# no adjacent static fog found, so flag tile to avoid reprocessing
$game_map.fow_grid[x,y,1] |= Fog_of_War::SKIP
end
end
end # fow_static
end # for
end # for
if $game_map.fow_dynamic
if $game_map.fow_static
for x in dx-1 .. dx+21
for y in dy-1 .. dy+16
# erase dynamic fow if static fow is above it anyway
if @fow_tilemap.map_data[x,y,2] == 48
@fow_tilemap.map_data[x,y,1]=0 if @fow_tilemap.map_data[x,y,1]!=0
end
end
end
end
# calculate autotiles for dynamic fow (around player)
px = $game_player.x
py = $game_player.y
tiles = []
x = px - ($game_map.fow_range+1)
y_top = py
mod_top = -1
y_bot = py
mod_bot = 1
until x == px + ($game_map.fow_range+2)
tiles.push([x,y_top]) if $game_map.valid?(x,y_top)
tiles.push([x,y_bot]) if $game_map.valid?(x,y_bot)
if x == px
mod_top = 1
mod_bot = -1
x+=1
next
end
y_top+=1*mod_top
y_bot+=1*mod_bot
tiles.push([x,y_top]) if $game_map.valid?(x,y_top)
tiles.push([x,y_bot]) if $game_map.valid?(x,y_bot)
x+=1
end
tiles.uniq.each do |t|
adj = check_adjacent(t[0],t[1],0,$game_map.fow_grid,Fog_of_War::REVEALED)
if adj != nil
@fow_tilemap.map_data[t[0],t[1],1] =
(eval '@fow_autotiles[adj.to_i]') + 48
end
end
end
end
#--------------------------------------------------------------------------
# * Object Initialization: fog of war - handling fog of war events
# pChar : character
#--------------------------------------------------------------------------
def update_event_transparency(pChar = nil)
# Get settings from MAP_OPTIONS
settings = Fog_of_War.settings_for_map($game_map.map_id)
# Check if event hiding is enabled (defaults to true if nil)
hide_events = settings[:fow_hides_events].nil? ? Fog_of_War::FOW_HIDES_EVENTS_DEFAULT : settings[:fow_hides_events]
# If event hiding is enabled, handle event transparency
if hide_events
if pChar.nil?
# Check all events
$game_map.events.each_value do |event|
# Set event transparency based on fog grid
# If dynamic fog is off, hide events as well based on static fog
event.transparent = (
($game_map.fow_dynamic && $game_map.fow_grid[event.x, event.y, 0] == Fog_of_War::FOW) ||
($game_map.fow_static && $game_map.fow_grid[event.x, event.y, 1] == Fog_of_War::FOW)
)
end
else
# Check only one event
pChar.transparent = (
($game_map.fow_dynamic && $game_map.fow_grid[pChar.x, pChar.y, 0] == Fog_of_War::FOW) ||
($game_map.fow_static && $game_map.fow_grid[pChar.x, pChar.y, 1] == Fog_of_War::FOW)
)
end
end
end
#--------------------------------------------------------------------------
# * Get list of adjacent tiles based upon flag for autotile placement
# i :
# j :
# k :
# grid :
# flag :
#--------------------------------------------------------------------------
def check_adjacent(i,j,k,grid,flag)
return if not $game_map.valid?(i,j) or grid == nil or flag == nil
adj = ''
if (i == 0)
adj << '147'
else
if (j == 0) then adj << '1'
else
if (grid[i-1,j-1,k] != flag) then adj << '1' end
end
if (grid[i-1,j,k] != flag) then adj << '4' end
if (j == $game_map.height-1) then adj << '7'
else
if (grid[i-1,j+1,k] != flag) then adj << '7' end
end
end
if (i == $game_map.width-1)
adj << '369'
else
if (j == 0) then adj << '3'
else
if (grid[i+1,j-1,k] != flag) then adj << '3' end
end
if (grid[i+1,j,k] != flag) then adj << '6' end
if (j == $game_map.height-1) then adj << '9'
else
if (grid[i+1,j+1,k] != flag) then adj << '9' end
end
end
if (j == 0)
adj << '2'
else
if (grid[i,j-1,k] != flag) then adj << '2' end
end
if (j == $game_map.height-1)
adj << '8'
else
if (grid[i,j+1,k] != flag) then adj << '8' end
end
# if no adjacent fog, set it as 0
if (adj == '') then adj = '0' end
# convert to an array, sort, and then back to a string
return adj.split(//).sort.join
end
end
#==============================================================================
# ** Interpreter
#------------------------------------------------------------------------------
# This interpreter runs event commands. This class is used within the
# Game_System class and the Game_Event class.
#==============================================================================
class Interpreter
#--------------------------------------------------------------------------
# * Fog of War
# static : Full map uncovered
# dynamic : Immediate area uncovered
# range : (Optional) Range in tiles (0-9)
# reset : (Optional) Reset map
#--------------------------------------------------------------------------
def fog_of_war(static, dynamic, range = Fog_of_War::FOW_RANGE_DEFAULT, reset = false)
# Alert messages
if static.nil? or dynamic.nil?
print 'Two true/false parameters are required in call to fog_of_war.'
exit
end
if range < 0 or range > 9
print 'Invalid range in call to fog_of_war (only 0-9 is valid).'
exit
end
# Set values into Game_Map class
$game_map.fow_static = static
$game_map.fow_dynamic = dynamic
$game_map.fow_range = range
if reset
$game_map.fow_grid = nil
end
if not $game_map.fow_static and not $game_map.fow_dynamic
$game_map.fow = false
$scene.spriteset.fow_tilemap.dispose
# set all events back to visible
for i in $game_map.events.keys
$game_map.events[i].transparent = false
end
return
end
# static or dynamic fow (or both) are on
$game_map.fow = true
# If the fog of war has not yet been created
if $game_map.fow_grid.nil?
# Define/Redefine the fog of war grid based on map dimensions
$game_map.fow_grid = Table.new($game_map.width, $game_map.height, 2)
#
# Cycle through fog of war grid dimensions
for i in 0...$game_map.fow_grid.xsize
for j in 0...$game_map.fow_grid.ysize
#
# Apply the FOW flag to the map/grid coordinates
$game_map.fow_grid[i,j,1] = Fog_of_War::FOW
$game_map.fow_grid[i,j,0] = Fog_of_War::FOW
#
end
end
end
# Set currently revealed if dynamic map is true
if $game_map.fow_dynamic
$game_map.fow_revealed = $game_map.fow_last_revealed = []
end
# Initialize/redraw the spriteset fog of war
$scene.spriteset.initialize_fow
end
end
#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
# This class performs map screen processing.
#==============================================================================
class Scene_Map
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :spriteset # Spriteset
end
#================================
# ■ Dynamic Maps
#================================
# By: Near Fantastica
# Date: 05.09.05
# Version: 1
#================================
# updated 2005-11-07 by Wachunga
# generalized to work for modified versions of Game_Map,
# e.g. even if more instance variables are added
module Map
#--------------------------------------------------------------
@map_data = {}
#--------------------------------------------------------------------------
def Map.set_map(map, map_id)
@map_data[map_id] = map
end
#--------------------------------------------------------------------------
def Map.data(map_id)
return @map_data[map_id]
end
end
class Game_Map
#--------------------------------------------------------------
alias dm_orig_setup setup
def setup(map_id)
save_map(@map_id)
if Map.data(map_id) == nil
dm_orig_setup(map_id)
else
load_map(map_id)
end
end
#-----------------------------------------------------------
def load_map(map_id)
$game_map = Map.data(map_id)
end
#--------------------------------------------------------------
def save_map(map_id)
return if map_id == 0
Map.set_map(self.dup, map_id)
end
end