masterdragonson

Error Fix For Map Screenshot By Hime

Nov 10th, 2015
471
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.67 KB | None | 0 0
  1. =begin
  2. #===============================================================================
  3. Title: Map Screenshot
  4. Author: Hime
  5. Date: Sep 25, 2015
  6. --------------------------------------------------------------------------------
  7. ** Change log
  8. Sep 25, 2015
  9. - fixed placement issue with large sprites
  10. Dec 7, 2014
  11. - added option to draw certain events
  12. Apr 15, 2013
  13. - updated script to use GDI+ interface
  14. - added support for region map overlay and passage map overlay
  15. Apr 6, 2013
  16. - fixed bug where drawing events crashed the game
  17. Apr 2, 2013
  18. - map data is now setup by an instance of Game_Map, to account for custom
  19. map scripts adding to the map
  20. Jul 27
  21. - Export dirNames are now optional
  22. May 28
  23. - updated overlay mapping compatibility to draw the overlays
  24. based on the player's current position
  25. - fixed issue where import hash was commented out
  26. - Added support for Yami's overlay mapping
  27. May 24, 2012
  28. - fixed large characters
  29. - some optimizations for calculating bounds and dimensions
  30. May 5, 2012
  31. - fixed waterfall autotile
  32. - added screenshot feature
  33. May 4, 2012
  34. - fixed tiles with alpha channel
  35. - fixed shadows
  36. - fixed wall autotiles
  37. May 1, 2012
  38. - fixed wall autotile, although there is still an issue with some tiles
  39. Apr 29, 2012
  40. - fixed shadow map drawing
  41. - added region highlighting
  42. - added damage tile highlighting
  43. Apr 28, 2012
  44. - Initial Release
  45. ------------------------------------------------------------------------------
  46. ** Description
  47.  
  48. This script allows you to take a full image of any of your game's maps
  49. and export. An image of the map is referred to as a "mapshot" (as opposed to
  50. screenshot).
  51.  
  52. The script provides various configuration options to control what kinds of
  53. things you want to see on your map, such as events, vehicles, region ID's, or
  54. specific tile properties.
  55.  
  56. ------------------------------------------------------------------------------
  57. ** Usage
  58.  
  59. The default key for taking a mapshot is F7. This can be changed in the
  60. configuration section.
  61.  
  62. To take a mapshot, first start the game, and then hit F7.
  63. A message will appear informing you that a mapshot was successfully taken.
  64.  
  65. Alternatively, you can use script calls to take mapshots.
  66.  
  67. Map_Saver.new(map_id).export
  68.  
  69. Aside from exporting images, you are able to use the image that the
  70. map saver captures.
  71.  
  72. ms = Map_Saver.new(map_id)
  73. bmp = ms.map_image
  74.  
  75. This gives you a reference to a Bitmap object that contains an image of
  76. your map.
  77.  
  78. Drawing Events
  79.  
  80. One of the configuration options available is to determine whether events can be drawn or not: if it’s true, then events will be drawn. If it’s false, then they will not be drawn.
  81.  
  82. However, if an event is meant to act as a tile, then you want to be able to specify that only these should be drawn. You can do this by creating a comment on the first page of any events that should
  83.  
  84. <screenshot: tile>
  85. These events will then be drawn even if you have chosen not to draw events.
  86. --------------------------------------------------------------------------------
  87. ** Credits
  88.  
  89. Cremno
  90. -GDI+ interface code
  91. Cidiomar
  92. -for drawing autotiles and shadows,
  93. -providing efficient bmp and png exporters
  94. Moon
  95. -auto-tile related info
  96. Mephistox
  97. -testing and suggestions
  98. ================================================================================
  99. =end
  100. $imported = {} if $imported.nil?
  101. $imported["TH_MapSaver"] = true
  102. #===============================================================================
  103. # ** Configuration
  104. #===============================================================================
  105. module TH
  106. module Map_Saver
  107.  
  108. #Mapshot options. This takes an image of the entire map
  109. Mapshot_Button = Input::F7
  110. Mapshot_Scale = 1
  111.  
  112. #Screenshot options. This takes an image of the visible map
  113. Screenshot_Button = Input::F6
  114. Screenshot_Scale = 1
  115.  
  116. #Folder that the map will be exported to
  117. Mapshot_Directory = "Mapshots"
  118. Screenshot_Directory = "Screenshots"
  119.  
  120. # format you want to export to. You should stick with png.
  121. # Options: [bmp, png]
  122. Export_Format = "png"
  123.  
  124. # Sprite draw options
  125. Draw_Events = true
  126. Draw_Player = true
  127. Draw_Followers = true
  128. Draw_Vehicles = true
  129.  
  130. # Message Options
  131. Display_Message = true
  132.  
  133. #Should shadows be drawn? What color?
  134. Draw_Shadow = true
  135. Shadow_Color = Color.new(0, 0, 0, 128)
  136.  
  137. # Should parallax settings be drawn?
  138. Draw_Parallax = true
  139.  
  140. # Should regions be drawn? Requires "Region Overlay Map" script
  141. Draw_Regions = false
  142.  
  143. # Should passage settings be drawn? Requires "Passage Overlay Map" script
  144. Draw_Passages = false
  145.  
  146. #Should damage tiles be highlighted? What color?
  147. Highlight_Damage = true
  148. Damage_Color = Color.new(128, 0, 0, 128)
  149. end
  150. end
  151.  
  152. #==============================================================================
  153. # ** Module: Map_Tiles
  154. # Contains data and methods useful for working with maps and tiles
  155. #==============================================================================
  156.  
  157. module Map_Tiles
  158. AUTOTILE_PARTS = [[18,17,14,13], [ 2,14,17,18], [13, 3,17,18], [ 2, 3,17,18],
  159. [13,14,17, 7], [ 2,14,17, 7], [13, 3,17, 7], [ 2, 3,17, 7],
  160. [13,14, 6,18], [ 2,14, 6,18], [13, 3, 6,18], [ 2, 3, 6,18],
  161. [13,14, 6, 7], [ 2,14, 6, 7], [13, 3, 6, 7], [ 2, 3, 6, 7],
  162. [16,17,12,13], [16, 3,12,13], [16,17,12, 7], [12, 3,16, 7],
  163. [10, 9,14,13], [10, 9,14, 7], [10, 9, 6,13], [10, 9, 6, 7],
  164. [18,19,14,15], [18,19, 6,15], [ 2,19,14,15], [ 2,19, 6,15],
  165. [18,17,22,21], [ 2,17,22,21], [18, 3,22,21], [ 2, 3,21,22],
  166. [16,19,12,15], [10, 9,22,21], [ 8, 9,12,13], [ 8, 9,12, 7],
  167. [10,11,14,15], [10,11, 6,15], [18,19,22,23], [ 2,19,22,23],
  168. [16,17,20,21], [16, 3,20,21], [ 8,11,12,15], [ 8, 9,20,21],
  169. [16,19,20,23], [10,11,22,23], [ 8,11,20,23], [ 0, 1, 4, 5]]
  170. WATERFALL_PIECES = [[ 2, 1, 6, 5], [ 0, 1, 4, 5], [ 2, 3, 6, 7], [0, 3, 4, 7]]
  171. WALL_PIECES = [[10, 9, 6, 5], [ 8, 9, 4, 5], [ 2, 1, 6, 5], [ 0, 1, 4, 5],
  172. [10,11, 6, 7], [ 8,11, 4, 7], [ 2, 3, 6, 7], [ 0, 3, 4, 7],
  173. [10, 9,14,13], [ 8, 9,12,13], [ 2, 1,14,13], [ 0, 1,12,13],
  174. [10,11,14,15], [8, 11,12,15], [ 2, 3,14,15], [ 0, 3,12,15]]
  175.  
  176. A1_TILES = [[0, 0], [0, 96], [192, 0], [192, 96],
  177. [256, 0], [448, 0], [256, 96], [448, 96],
  178. [0, 192], [192, 192], [0, 288], [192, 288],
  179. [256, 192], [448, 192], [256, 288], [448, 288]]
  180.  
  181.  
  182. #--------------------------------------------------------------------------
  183. # * Checks if a tile is a wall
  184. #--------------------------------------------------------------------------
  185. def is_wall?(data)
  186. return true if data.between?(2288, 2335)
  187. return true if data.between?(2384, 2431)
  188. return true if data.between?(2480, 2527)
  189. return true if data.between?(2576, 2623)
  190. return true if data.between?(2672, 2719)
  191. return true if data.between?(2768, 2815)
  192. return true if data.between?(4736, 5119)
  193. return true if data.between?(5504, 5887)
  194. return true if data.between?(6272, 6655)
  195. return true if data.between?(7040, 7423)
  196. return true if data > 7807
  197. false
  198. end
  199. #--------------------------------------------------------------------------
  200. # * Checks if a tile is roof
  201. #--------------------------------------------------------------------------
  202. def is_roof?(data)
  203. return true if data.between?(4352, 4735)
  204. return true if data.between?(5120, 5503)
  205. return true if data.between?(5888, 6271)
  206. return true if data.between?(6656, 7039)
  207. return true if data.between?(7424, 7807)
  208. false
  209. end
  210. #--------------------------------------------------------------------------
  211. # * Checks if a tile is soil
  212. #--------------------------------------------------------------------------
  213. def is_soil?(data)
  214. return true if data.between?(2816, 4351) && !is_table?(data)
  215. return true if data > 1663 && !is_stair?(data)
  216. false
  217. end
  218. #--------------------------------------------------------------------------
  219. # * Checks if a tile is a stair
  220. #--------------------------------------------------------------------------
  221. def is_stair?(data)
  222. return true if data.between?(1541, 1542)
  223. return true if data.between?(1549, 1550)
  224. return true if data.between?(1600, 1615)
  225. false
  226. end
  227. #--------------------------------------------------------------------------
  228. # * Checks if a tile is a table
  229. #--------------------------------------------------------------------------
  230. def is_table?(data)
  231. return true if data.between?(3152, 3199)
  232. return true if data.between?(3536, 3583)
  233. return true if data.between?(3920, 3967)
  234. return true if data.between?(4304, 4351)
  235. false
  236. end
  237.  
  238. #--------------------------------------------------------------------------
  239. # * The tileset to be used
  240. #--------------------------------------------------------------------------
  241. def tileset
  242. $data_tilesets[@tileset_id]
  243. end
  244.  
  245. #--------------------------------------------------------------------------
  246. # * Region ID
  247. #--------------------------------------------------------------------------
  248. def region_id(x, y)
  249. valid?(x, y) ? @map.data[x, y, 3] >> 8 : 0
  250. end
  251.  
  252. #--------------------------------------------------------------------------
  253. # * Gets all of the tiles for each layer at position x,y
  254. #--------------------------------------------------------------------------
  255. def layered_tiles(x, y)
  256. [2, 1, 0].collect {|z| @map.data[x, y, z] }
  257. end
  258.  
  259. def layered_tiles_flag?(x, y, bit)
  260. layered_tiles(x, y).any? {|tile_id| tileset.flags[tile_id] & bit != 0 }
  261. end
  262.  
  263. def valid?(x, y)
  264. x >= 0 && x < width && y >= 0 && y < height
  265. end
  266.  
  267. def damage_floor?(x, y)
  268. valid?(x, y) && layered_tiles_flag?(x, y, 0x100)
  269. end
  270.  
  271. #--------------------------------------------------------------------------
  272. # * Specifies which type of autotile is used
  273. #--------------------------------------------------------------------------
  274. def auto_tile(id)
  275. id / 48
  276. end
  277.  
  278. #--------------------------------------------------------------------------
  279. # * Specifies the specific arrangement of autotiles used
  280. #--------------------------------------------------------------------------
  281. def auto_index(id)
  282. id % 48
  283. end
  284.  
  285. #--------------------------------------------------------------------------
  286. # * Put the auto-tile pieces together
  287. #--------------------------------------------------------------------------
  288. def make_autotile(rects, sx, sy)
  289. @tile.clear
  290. for i in 0...4
  291. @auto_rect.x = (rects[i] % 4) * 16 + sx
  292. @auto_rect.y = (rects[i] / 4) * 16 + sy
  293. @tile.blt((i % 2) * 16,(i / 2) * 16, @tilemap, @auto_rect)
  294. end
  295. end
  296.  
  297. #--------------------------------------------------------------------------
  298. # * Get auto-tile A1 tiles
  299. #--------------------------------------------------------------------------
  300. def autotile_A1(tile_id)
  301. @tilemap = @bitmaps[0]
  302. autotile = tile_id / 48
  303. auto_id = tile_id % 48
  304. sx, sy = A1_TILES[autotile]
  305. if is_wall?(tile_id + 2048)
  306. rects = WATERFALL_PIECES[auto_id]
  307. else
  308. rects = AUTOTILE_PARTS[auto_id]
  309. end
  310. make_autotile(rects, sx, sy)
  311. end
  312.  
  313. #--------------------------------------------------------------------------
  314. # * Get auto-tile A2 tiles.
  315. # 64x96 tiles, 8 per row, 4 rows
  316. #--------------------------------------------------------------------------
  317. def autotile_A2(tile_id)
  318. autotile = tile_id / 48
  319. auto_id = tile_id % 48
  320. @tilemap = @bitmaps[1]
  321. sx = (autotile % 8) * 64
  322. sy = (autotile / 8 % 4) * 96
  323. rects = AUTOTILE_PARTS[auto_id]
  324. make_autotile(rects, sx, sy)
  325. end
  326.  
  327. #--------------------------------------------------------------------------
  328. # * Get auto-tile A3 tiles.
  329. # 64x64 tiles, 8 per row, 4 rows
  330. #--------------------------------------------------------------------------
  331. def autotile_A3(tid)
  332. @tilemap = @bitmaps[2]
  333. sx = (auto_tile(tid) % 8) * 64
  334. sy = (auto_tile(tid) / 8 % 4) * 64
  335. rects = WALL_PIECES[auto_index(tid)]
  336. make_autotile(rects, sx, sy)
  337. end
  338.  
  339. #--------------------------------------------------------------------------
  340. # * Get auto-tile A4 tiles (walls)
  341. #--------------------------------------------------------------------------
  342. def autotile_A4(tile_id)
  343. @tilemap = @bitmaps[3]
  344. autotile = tile_id / 48
  345. auto_id = tile_id % 48
  346. sx = (autotile % 8) * 64
  347. sy = (autotile / 16 * 160) + (autotile / 8 % 2) * 96
  348. if is_wall?(tile_id + 5888)
  349. rects = WALL_PIECES[auto_id]
  350. else
  351. rects = AUTOTILE_PARTS[auto_id]
  352. end
  353. make_autotile(rects, sx, sy)
  354. end
  355.  
  356. #--------------------------------------------------------------------------
  357. # * Get auto-tile A5 tiles (normal)
  358. #--------------------------------------------------------------------------
  359. def autotile_A5(tile_id)
  360. @tilemap = @bitmaps[4]
  361. sx = (tile_id) % 8 * tilesize
  362. sy = (tile_id) / 8 * tilesize
  363. @src_rect.set(sx, sy, tilesize, tilesize)
  364. @tile.clear
  365. @tile.blt(0, 0, @tilemap, @src_rect)
  366. end
  367.  
  368. #--------------------------------------------------------------------------
  369. # * Get normal tiles B, C, D, E
  370. #--------------------------------------------------------------------------
  371. def normal_tile(tile_id)
  372. @tilemap = @bitmaps[5 + tile_id / 256]
  373. sx = (tile_id / 128 % 2 * 8 + tile_id % 8) * tilesize;
  374. sy = (tile_id % 256 / 8 % 16) * tilesize;
  375. @src_rect.set(sx, sy, tilesize, tilesize)
  376. @tile.clear
  377. @tile.blt(0, 0, @tilemap, @src_rect)
  378. end
  379.  
  380. #--------------------------------------------------------------------------
  381. # * Get bitmap for the specified tile id
  382. #--------------------------------------------------------------------------
  383. def get_bitmap(id)
  384. if id < 1024
  385. normal_tile(id)
  386. elsif id < 1664
  387. autotile_A5(id - 1536)
  388. elsif id < 2816
  389. autotile_A1(id - 2048)
  390. elsif id < 4352
  391. autotile_A2(id - 2816)
  392. elsif id < 5888
  393. autotile_A3(id - 4352)
  394. else
  395. autotile_A4(id - 5888)
  396. end
  397. end
  398. end
  399.  
  400. #==============================================================================
  401. # **
  402. #==============================================================================
  403.  
  404. class Game_Player < Game_Character
  405.  
  406. alias :th_mapsaver_update :update
  407. def update
  408. th_mapsaver_update
  409. if Input.trigger?(TH::Map_Saver::Mapshot_Button)
  410. if $game_map.width > 400 && $game_map.height > 400 # Script Can't Generate Large Maps
  411. #msgbox "Script Can't Generate Large Maps...\n" +
  412. # "Map Width: #{$game_map.width}\n" +
  413. # "Map Height: #{$game_map.height}\n" +
  414. # "Currently Supported: 400 x 400"
  415. return
  416. end
  417. s = Map_Saver.new($game_map.map_id)
  418. s.set_scale(TH::Map_Saver::Mapshot_Scale)
  419. s.mapshot
  420. end
  421. if Input.trigger?(TH::Map_Saver::Screenshot_Button)
  422. s = Map_Saver.new($game_map.map_id)
  423. s.set_scale(TH::Map_Saver::Screenshot_Scale)
  424. s.screenshot
  425. end
  426. end
  427. end
  428.  
  429. class Game_Vehicle < Game_Character
  430. attr_reader :map_id
  431. end
  432.  
  433. class Game_Map
  434. attr_reader :map
  435. end
  436.  
  437. #==============================================================================
  438. # **
  439. #==============================================================================
  440.  
  441. class Map_Saver
  442. include TH::Map_Saver
  443. include Map_Tiles
  444. #--------------------------------------------------------------------------
  445. # * Constants
  446. #--------------------------------------------------------------------------
  447.  
  448. SHADOW_COLOR = TH::Map_Saver::Shadow_Color
  449. DAMAGE_COLOR = TH::Map_Saver::Damage_Color
  450.  
  451. #--------------------------------------------------------------------------
  452. # * Public instance variables
  453. #--------------------------------------------------------------------------
  454. attr_reader :map_image
  455.  
  456. def initialize(map_id=$game_map.map_id, x=$game_player.x, y=$game_player.y)
  457. @scale = 1
  458. @map_id = map_id
  459. @local_x = x
  460. @local_y = y
  461. @screen_local = false
  462. @shadow_bitmap = Bitmap.new(128, 128)
  463. @draw_layer0 = true
  464. @draw_layer1 = true
  465. @draw_layer2 = true
  466. @draw_events = Draw_Events
  467. @draw_vehicles = Draw_Vehicles
  468. @draw_player = Draw_Player
  469. @display_msg = Display_Message
  470. @draw_followers = Draw_Followers
  471. @draw_shadow = Draw_Shadow
  472. @draw_damage = Highlight_Damage
  473. @draw_regions = Draw_Regions
  474. @draw_passages = Draw_Passages
  475. @draw_parallax = Draw_Parallax
  476. @tile = Bitmap.new(32, 32) #stores the current tile to be drawn
  477. @tilemap = nil
  478. @src_rect = Rect.new
  479. @auto_rect = Rect.new(0, 0, tilesize / 2, tilesize/ 2) #constant
  480. @tile_rect = Rect.new(0, 0, tilesize, tilesize) #constant
  481. end
  482.  
  483. def load_tilesets
  484. bitmaps = []
  485. tileset.tileset_names.each_with_index do |name, i|
  486. bitmaps[i] = Cache.tileset(name)
  487. end
  488. return bitmaps
  489. end
  490.  
  491. #--------------------------------------------------------------------------
  492. # * Refresh, possibly with a new map
  493. #--------------------------------------------------------------------------
  494. def redraw(map_id=$game_map.map_id, x=$game_player.x, y=$game_player.y)
  495. @map_image.dispose if @map_image
  496. @map_id = map_id
  497. @local_x = x
  498. @local_y = y
  499. @game_map = Game_Map.new
  500. @game_map.setup(map_id)
  501. @map = @game_map.map
  502. @map_info = $data_mapinfos[map_id]
  503. @screen = $game_map.screen
  504. @tileset_id = @game_map.tileset.id
  505. @bitmaps = load_tilesets
  506.  
  507. get_bounds
  508. @map_image = Bitmap.new(@width * tilesize, @height * tilesize)
  509. draw_map
  510. scale_map if @scale != 1
  511. end
  512.  
  513. #--------------------------------------------------------------------------
  514. # * Pre-process. These will never change when drawing the map.
  515. #--------------------------------------------------------------------------
  516. def get_bounds
  517. @start_x = start_x
  518. @start_y = start_y
  519. @end_x = end_x
  520. @end_y = end_y
  521. @width = width
  522. @height = height
  523. @tilesize = tilesize
  524. end
  525.  
  526. def screen_tile_x
  527. Graphics.width / 32
  528. end
  529.  
  530. def screen_tile_y
  531. Graphics.height / 32
  532. end
  533.  
  534. #--------------------------------------------------------------------------
  535. # * Sets the scale for the map
  536. #--------------------------------------------------------------------------
  537. def set_scale(scale)
  538. @scale = scale
  539. end
  540.  
  541. #--------------------------------------------------------------------------
  542. # * Sets the display message for the map
  543. #--------------------------------------------------------------------------
  544. def set_display_msg(display_msg)
  545. @display_msg = display_msg
  546. end
  547.  
  548. #--------------------------------------------------------------------------
  549. # * Size of a tile
  550. #--------------------------------------------------------------------------
  551. def tilesize
  552. 32
  553. end
  554.  
  555. #--------------------------------------------------------------------------
  556. # * Width and height of the map, both locally and globally
  557. #--------------------------------------------------------------------------
  558. def width
  559. end_x - @start_x
  560. end
  561.  
  562. def height
  563. end_y - @start_y
  564. end
  565.  
  566. #--------------------------------------------------------------------------
  567. # * Starting and end positions, relative to the screen or map
  568. #--------------------------------------------------------------------------
  569. def start_x
  570. @screen_local ? [[$game_player.x - screen_tile_x / 2, @map.width - screen_tile_x].min, 0].max : 0
  571. end
  572.  
  573. def start_y
  574. @screen_local ? [[$game_player.y - screen_tile_y / 2, @map.height - screen_tile_y].min, 0].max : 0
  575. end
  576.  
  577. def end_x
  578. @screen_local ? [[screen_tile_x, @local_x + screen_tile_x / 2 + 1].max, @map.width].min : @map.width
  579. end
  580.  
  581. def end_y
  582. @screen_local ? [[screen_tile_y, @local_y + screen_tile_y / 2 + 1].max, @map.height].min : @map.height
  583. end
  584.  
  585. #--------------------------------------------------------------------------
  586. # * Draw tile onto image. x and y values are absolute coords. They should
  587. # be re-mapped based on the start_x and start_y values
  588. #--------------------------------------------------------------------------
  589. def draw_tile(x, y, tile, rect)
  590. ox = (x - @start_x) * tilesize
  591. oy = (y - @start_y) * tilesize
  592. @map_image.blt(ox, oy, tile, rect)
  593. end
  594.  
  595. def draw_character(x, y, width, height, bmp, rect)
  596. ox = (x - @start_x) * tilesize
  597. oy = (y - @start_y) * tilesize
  598.  
  599. ox = ox - width / 4 if width > 32
  600. oy = oy - height / 2 if height > 32
  601. @map_image.blt(ox, oy, bmp, rect)
  602. end
  603.  
  604. #--------------------------------------------------------------------------
  605. # * Get bitmap for the specified character
  606. #--------------------------------------------------------------------------
  607. def get_character_bitmap(name)
  608. charmap = Cache.character(name)
  609. sign = name[/^[\!\$]./]
  610. if sign && sign.include?('$')
  611. cw = charmap.width / 3
  612. ch = charmap.height / 4
  613. else
  614. cw = charmap.width / 12
  615. ch = charmap.height / 8
  616. end
  617. return charmap, cw, ch
  618. end
  619.  
  620. #--------------------------------------------------------------------------
  621. # * Draw the character onto the tile
  622. #--------------------------------------------------------------------------
  623. def set_character_bitmap(character, x, y)
  624. charmap, cw, ch = get_character_bitmap(character.character_name)
  625. index = character.character_index
  626. pattern = character.pattern < 3 ? character.pattern : 1
  627. sx = (index % 4 * 3 + pattern) * cw
  628. sy = (index / 4 * 4 + (character.direction - 2) / 2) * ch
  629. @src_rect.set(sx, sy, cw, ch)
  630. draw_character(x, y, cw, ch, charmap, @src_rect)
  631. end
  632.  
  633. #--------------------------------------------------------------------------
  634. # * create the shadow map
  635. #--------------------------------------------------------------------------
  636. def make_shadow_map
  637. for s in 0 ... 16
  638. x = s % 4
  639. y = s / 4
  640. if s & 0b1000 == 0b1000
  641. @shadow_bitmap.fill_rect(x*tilesize+16, y*@tilesize+16, 16, 16, SHADOW_COLOR)
  642. end
  643. if s & 0b0100 == 0b0100
  644. @shadow_bitmap.fill_rect(x*tilesize, y*@tilesize+16, 16, 16, SHADOW_COLOR)
  645. end
  646. if s & 0b0010 == 0b0010
  647. @shadow_bitmap.fill_rect(x*tilesize+16, y*@tilesize, 16, 16, SHADOW_COLOR)
  648. end
  649. if s & 0b0001 == 0b0001
  650. @shadow_bitmap.fill_rect(x*tilesize, y*@tilesize, 16, 16, SHADOW_COLOR)
  651. end
  652. end
  653. end
  654.  
  655. # New Draw Parallax
  656. def draw_parallax
  657. image = Cache.parallax(@map.parallax_name)
  658. original = Rect.new(0, 0, image.width, image.height)
  659. @src_rect.set(0, 0, @map.width * 32, image.height)
  660.  
  661. tmp_height = 0
  662. tmp_map_height = @map.height * 32
  663.  
  664. tmp_width = 0
  665. tmp_map_width = @map.width * 32
  666.  
  667. until (tmp_map_height < 0)
  668. until (tmp_map_width < 0)
  669. @src_rect.set(0, 0, image.width, image.height)
  670. @map_image.blt(tmp_width, tmp_height, image, @src_rect)
  671. tmp_width += image.width
  672. tmp_map_width -= image.width
  673. end
  674. tmp_width = 0
  675. tmp_map_width = @map.width * 32
  676. tmp_height += image.height
  677. tmp_map_height -= image.height
  678. end
  679. end
  680.  
  681. # def draw_parallax
  682. # image = Cache.parallax(@map.parallax_name)
  683. # @src_rect.set(0, 0, image.width, image.height)
  684. # @map_image.blt(0, 0, image, @src_rect)
  685. # end
  686.  
  687. #--------------------------------------------------------------------------
  688. # * Draw the shadow map
  689. #--------------------------------------------------------------------------
  690. def draw_shadow_map
  691. for x in @start_x ... @end_x
  692. for y in @start_y ... @end_y
  693. _x, _y = x*@tilesize, y*@tilesize
  694. s = @map.data[x, y, 3] & 0b1111
  695. if s != 0
  696. x_ = (s % 4) * @tilesize
  697. y_ = (s / 4) * @tilesize
  698. @src_rect.set(x_, y_, @tilesize, @tilesize)
  699. draw_tile(x, y, @shadow_bitmap, @src_rect)
  700. end
  701. end
  702. end
  703. end
  704.  
  705. #--------------------------------------------------------------------------
  706. # * Draw the specified layer
  707. #--------------------------------------------------------------------------
  708. def draw_layer(layer)
  709. for x in @start_x ... @end_x
  710. for y in @start_y ... @end_y
  711. _x, _y = x*@tilesize, y*@tilesize
  712. tile_id = @map.data[x, y, layer]
  713. next if tile_id == 0
  714. get_bitmap(tile_id)
  715. draw_tile(x, y, @tile, @tile_rect)
  716. end
  717. end
  718. end
  719.  
  720. #-----------------------------------------------------------------------------
  721. # Draw game regions
  722. #-----------------------------------------------------------------------------
  723. def draw_regions
  724. if $imported["TH_RegionOverlay"]
  725. image = SceneManager.scene.instance_variable_get(:@spriteset).instance_variable_get(:@region_map).bitmap
  726. @src_rect.set(@start_x * tilesize, @start_y * tilesize, image.width, image.height)
  727. @map_image.blt(0, 0, image, @src_rect, 255)
  728. end
  729. end
  730.  
  731. def draw_passages
  732. if $imported["TH_OverlayPassageMap"]
  733. image = SceneManager.scene.instance_variable_get(:@spriteset).instance_variable_get(:@passage_map).bitmap
  734. @src_rect.set(@start_x * tilesize, @start_y * tilesize, image.width, image.height)
  735. @map_image.blt(0, 0, image, @src_rect, 255)
  736. end
  737. end
  738.  
  739. #--------------------------------------------------------------------------
  740. # * Draw the game player
  741. #--------------------------------------------------------------------------
  742. def draw_player
  743. set_character_bitmap($game_player, $game_player.x, $game_player.y) if @map_id == $game_map.map_id
  744. end
  745.  
  746. def draw_followers
  747. end
  748.  
  749. #--------------------------------------------------------------------------
  750. # * Draw map events
  751. #--------------------------------------------------------------------------
  752. def draw_events
  753. @map.events.values.each do |event|
  754. canDraw = event.pages[0].list.any? do |cmd|
  755. cmd.code == 108 && cmd.parameters[0] =~ /<screenshot:\s*tile\s*>/i
  756. end
  757. next unless @draw_events || canDraw
  758. id = event.pages[0].graphic.tile_id
  759. char_name = event.pages[0].graphic.character_name
  760. if id > 0
  761. normal_tile(id)
  762. draw_tile(event.x, event.y, @tilemap, @src_rect)
  763. elsif char_name != ""
  764. set_character_bitmap(event.pages[0].graphic, event.x, event.y)
  765. end
  766. end
  767. end
  768.  
  769. #--------------------------------------------------------------------------
  770. # * Draw map vehicles
  771. #--------------------------------------------------------------------------
  772. def draw_vehicles
  773. $game_map.vehicles.each do |vehicle|
  774. set_character_bitmap(vehicle, vehicle.x, vehicle.y) if @map_id == vehicle.map_id
  775. end
  776. end
  777.  
  778. #--------------------------------------------------------------------------
  779. # * Draw map sprites
  780. #--------------------------------------------------------------------------
  781. def draw_sprites
  782. draw_events
  783. draw_vehicles if @draw_vehicles
  784. draw_player if @draw_player
  785. draw_followers if @draw_followers
  786. end
  787.  
  788. #--------------------------------------------------------------------------
  789. # * Highlight damage tiles
  790. #--------------------------------------------------------------------------
  791. def draw_damage
  792. @tile.clear
  793. @tile.fill_rect(0, 0, @tilesize, @tilesize, DAMAGE_COLOR)
  794. @src_rect.set(0, 0, @tilesize, @tilesize)
  795. for x in @start_x ... @end_x
  796. for y in @start_y ... @end_y
  797. _x, _y = x*@tilesize, y*@tilesize
  798. if damage_floor?(x, y)
  799. draw_tile(x, y, @tile, @src_rect)
  800. end
  801. end
  802. end
  803. end
  804.  
  805. def draw_screen_effects
  806. end
  807. #--------------------------------------------------------------------------
  808. # * Draw the map
  809. #--------------------------------------------------------------------------
  810. def draw_map
  811. make_shadow_map if @draw_shadow
  812. draw_parallax if @draw_parallax
  813. draw_layer(0)
  814. draw_layer(1)
  815. draw_shadow_map
  816. draw_layer(2)
  817. draw_damage if @draw_damage
  818. draw_regions if @draw_regions
  819. draw_passages if @draw_passages
  820. draw_sprites
  821. draw_screen_effects
  822. end
  823.  
  824. #--------------------------------------------------------------------------
  825. # * Scale the map
  826. #--------------------------------------------------------------------------
  827. def scale_map
  828. nw = @width * @scale
  829. nh = @height * @scale
  830. @src_rect.set(0, 0, @width, @height)
  831. scaled_map = Bitmap.new(nw, nh)
  832. scaled_rect = Rect.new(0, 0, nw, nh)
  833. scaled_map.stretch_blt(scaled_rect, @map_image, @src_rect)
  834. @map_image = scaled_map
  835. end
  836.  
  837. #--------------------------------------------------------------------------
  838. # * Take a mapshot of the map
  839. #--------------------------------------------------------------------------
  840. def mapshot
  841. @screen_local = false
  842. redraw
  843. export(TH::Map_Saver::Mapshot_Directory)
  844. $game_message.add("Mapshot taken") if @display_msg
  845. end
  846.  
  847. #--------------------------------------------------------------------------
  848. # * Take a screenshot of the map
  849. #--------------------------------------------------------------------------
  850. def screenshot
  851. @screen_local = true
  852. redraw
  853. export(TH::Map_Saver::Screenshot_Directory)
  854. $game_message.add("Screenshot taken")
  855. end
  856.  
  857. #--------------------------------------------------------------------------
  858. # * Get the format to export to
  859. #--------------------------------------------------------------------------
  860. def get_format
  861. TH::Map_Saver::Export_Format
  862. end
  863.  
  864. #--------------------------------------------------------------------------
  865. # * Export the map to a file
  866. #--------------------------------------------------------------------------
  867. def export(dirName="")
  868. format = get_format
  869. dirName = TH::Map_Saver::Mapshot_Directory if dirName == ""
  870. #name = @map.display_name != "" ? @map.display_name : @map_info.name
  871.  
  872. place_name = $data_mapinfos[@map_id.to_i].name
  873.  
  874. #name = sprintf("Map%03d" %[@map_id])
  875. name = sprintf("%03d - %s" %[@map_id, place_name])
  876.  
  877. Dir.mkdir(dirName) unless File.directory?(dirName)
  878. name =
  879. filename = "%s\\%s.%s" %[dirName, name, format]
  880. t1 = Time.now
  881. redraw(@map_id) unless @map_image
  882. @map_image.save(filename)
  883. t2 = Time.now
  884. $game_message.add("Exported in %f seconds" %[t2 - t1]) if @display_msg
  885. end
  886. end
  887.  
  888. class Bitmap
  889.  
  890. def save(filename, options = {})
  891. options.merge!(format: File.extname(filename)[1..-1].to_sym)
  892. retval = false
  893. #bitmap = Gdiplus::Bitmap.new(:hbitmap, hbitmap)
  894. #bitmap = Gdiplus::Bitmap.new(:gdidib, *gdidib)
  895. # this seems to be the fastest one (RGSS 3.0.1, Windows 8 64-bit)
  896. bitmap = Gdiplus::Bitmap.new(:scan0, width, height, scan0)
  897. if bitmap
  898. retval = bitmap.save(:file, filename, options[:format])
  899. bitmap.dispose
  900. end
  901. retval
  902. end
  903.  
  904. private
  905.  
  906. def _data_struct(offset = 0)
  907. @_data_struct ||= (DL::CPtr.new((object_id << 1) + 16).ptr + 8).ptr
  908. (@_data_struct + offset).ptr.to_i
  909. end
  910.  
  911. def gdidib
  912. [_data_struct(8), _data_struct(16)]
  913. end
  914.  
  915. def hbitmap
  916. _data_struct(44)
  917. end
  918.  
  919. def scan0
  920. _data_struct(12)
  921. end
  922.  
  923. end
  924.  
  925. # ★ GDI+ interface
  926. # ★★★★★★★★★★★★
  927. #
  928. # Author : Cremno
  929. #
  930.  
  931. module Gdiplus
  932. DLL = 'gdiplus.dll'
  933.  
  934. def self.get_function name, import, export = 'L'
  935. Win32API.new DLL, name, import, export
  936. end
  937.  
  938. FUNCTIONS = {
  939. GdiplusStartup: get_function('GdiplusStartup', 'PPP'),
  940. GdiplusShutdown: get_function('GdiplusShutdown', 'P', 'V'),
  941. GdipDisposeImage: get_function('GdipDisposeImage', 'P'),
  942. GdipSaveImageToFile: get_function('GdipSaveImageToFile', 'PPPP'),
  943. GdipCreateBitmapFromGdiDib: get_function('GdipCreateBitmapFromGdiDib', 'LLP'),
  944. GdipCreateBitmapFromHBITMAP: get_function('GdipCreateBitmapFromHBITMAP', 'LLP'),
  945. GdipCreateBitmapFromScan0: get_function('GdipCreateBitmapFromScan0', 'LLLLPP')
  946. }
  947.  
  948. @@token = [0].pack('I')
  949. def self.token
  950. @@token
  951. end
  952.  
  953. @@clsids = {}
  954. def self.clsids
  955. @@clsids
  956. end
  957.  
  958. def self.gen_clsids
  959. return unless @@clsids.empty?
  960. func = Win32API.new('rpcrt4.dll', 'UuidFromString', 'PP', 'L')
  961. {
  962. bmp: '557cf400-1a04-11d3-9a73-0000f81ef32e',
  963. jpeg: '557cf401-1a04-11d3-9a73-0000f81ef32e',
  964. gif: '557cf402-1a04-11d3-9a73-0000f81ef32e',
  965. tiff: '557cf405-1a04-11d3-9a73-0000f81ef32e',
  966. png: '557cf406-1a04-11d3-9a73-0000f81ef32e'
  967. }.each_pair do |k, v|
  968. clsid = [0].pack('I')
  969. func.call(v, clsid)
  970. @@clsids[k] = clsid
  971. end
  972. @@clsids[:jpg] = @@clsids[:jpeg]
  973. @@clsids[:tif] = @@clsids[:tiff]
  974. end
  975.  
  976. # TODO: prepend prefix (Gdip or Gdiplus) automatically
  977. def self.call(*args)
  978. name = args.shift
  979. func = FUNCTIONS[name]
  980. v = func.call(*args)
  981. if v && v != 0
  982. msgbox "GDI+ error: #{v}\n\nFunction: #{name}\nArguments: #{args.inspect}"
  983. false
  984. else
  985. true
  986. end
  987. end
  988.  
  989. def self.startup
  990. call :GdiplusStartup, @@token, [1, 0, 0, 0].pack('L4'), 0
  991. end
  992.  
  993. def self.shutdown
  994. call :GdiplusShutdown, @@token
  995. end
  996.  
  997. class Image
  998.  
  999. attr_reader :instance
  1000. def initialize
  1001. @instance = 0
  1002. true
  1003. end
  1004.  
  1005. def save(destination, *args)
  1006. case destination
  1007. when :file
  1008. filename = args.shift << "\0"
  1009. filename.encode!('UTF-16LE')
  1010. argv = [:GdipSaveImageToFile, filename, Gdiplus.clsids[args.shift], 0]
  1011. else
  1012. raise ArgumentError, "unknown GDI+ image destination: #{source}"
  1013. end
  1014. argv.insert(1, @instance)
  1015. Gdiplus.call *argv
  1016. end
  1017.  
  1018. def dispose
  1019. Gdiplus.call :GdipDisposeImage, @instance
  1020. end
  1021. end
  1022.  
  1023. class Bitmap < Image
  1024.  
  1025. def initialize source, *args
  1026. case source
  1027. when :gdidib
  1028. argv = [:GdipCreateBitmapFromGdiDib, args.shift, args.shift]
  1029. when :hbitmap
  1030. argv = [:GdipCreateBitmapFromHBITMAP, args.shift, 0]
  1031. when :scan0
  1032. w = args.shift
  1033. h = args.shift
  1034. argv = [:GdipCreateBitmapFromScan0, w, h, w * -4, 0x26200a, args.shift]
  1035. else
  1036. raise ArgumentError, "unknown GDI+ bitmap source: #{source}"
  1037. end
  1038. argv.push([0].pack('I'))
  1039. retval = Gdiplus.call *argv
  1040. @instance = retval ? argv.last.unpack('I').first : 0
  1041. retval
  1042. end
  1043. end
  1044. end
  1045.  
  1046. if Gdiplus.startup
  1047. Gdiplus.gen_clsids
  1048. class << SceneManager
  1049. alias_method :run_wo_gdip_shutdown, :run
  1050. def run
  1051. run_wo_gdip_shutdown
  1052. Gdiplus.shutdown
  1053. end
  1054. end
  1055. end
  1056.  
  1057. #==============================================================================
  1058. # * Compatibility add-ons
  1059. #==============================================================================
  1060. #Yami overlays
  1061. if $imported["YSE-OverlayMapping"]
  1062. class Map_Saver
  1063. def draw_overlay_map_ground
  1064. filename = YSA::OVERLAY::GROUND
  1065. filename += $game_map.map_id.to_s
  1066. filename += "-" + $game_variables[YSA::OVERLAY::GROUND_VARIABLE].to_s
  1067. p filename
  1068. image = Cache.overlay(filename)
  1069. @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height)
  1070. @map_image.blt(0, 0, image, @src_rect)
  1071. end
  1072.  
  1073. def draw_overlay_map_parallax
  1074. filename = YSA::OVERLAY::PARALLAX
  1075. filename += $game_map.map_id.to_s
  1076. filename += "-" + $game_variables[YSA::OVERLAY::PARALLAX_VARIABLE].to_s
  1077. image = Cache.overlay(filename)
  1078. @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height)
  1079. @map_image.blt(0, 0, image, @src_rect)
  1080. end
  1081.  
  1082. def draw_overlay_map_light
  1083. filename = YSA::OVERLAY::LIGHT
  1084. filename += $game_map.map_id.to_s
  1085. filename += "-" + $game_variables[YSA::OVERLAY::LIGHT_VARIABLE].to_s
  1086. image = Cache.overlay(filename)
  1087. @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height)
  1088. @map_image.blt(0, 0, image, @src_rect, 10)
  1089. end
  1090.  
  1091. def draw_overlay_map_shadow
  1092. filename = YSA::OVERLAY::SHADOW
  1093. filename += $game_map.map_id.to_s
  1094. filename += "-" + $game_variables[YSA::OVERLAY::SHADOW_VARIABLE].to_s
  1095. image = Cache.overlay(filename)
  1096. @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height)
  1097. @map_image.blt(0, 0, image, @src_rect, 10)
  1098. end
  1099.  
  1100. alias :th_map_overlay_draw_map :draw_map
  1101. def draw_map
  1102. th_map_overlay_draw_map
  1103. draw_overlay_map_ground if $game_switches[YSA::OVERLAY::GROUND_SWITCH]
  1104. draw_overlay_map_parallax if $game_switches[YSA::OVERLAY::PARALLAX_SWITCH]
  1105. draw_overlay_map_shadow if $game_switches[YSA::OVERLAY::SHADOW_SWITCH]
  1106. draw_overlay_map_light if $game_switches[YSA::OVERLAY::LIGHT_SWITCH]
  1107. end
  1108. end
  1109. end
  1110.  
  1111. if $imported["TH_AreaOverlay"]
  1112. class Map_Saver
  1113. def draw_overlay_area_map
  1114. image = SceneManager.scene.instance_variable_get(:@spriteset).instance_variable_get(:@area_map).bitmap
  1115. @src_rect.set(@start_x * tilesize, @start_y * tilesize, image.width, image.height)
  1116. @map_image.blt(0, 0, image, @src_rect, 255)
  1117. end
  1118.  
  1119. alias :th_area_overlay_draw_map :draw_map
  1120. def draw_map
  1121. th_area_overlay_draw_map
  1122. draw_overlay_area_map
  1123. end
  1124. end
  1125. end
Add Comment
Please, Sign In to add comment