-
Notifications
You must be signed in to change notification settings - Fork 0
/
MA_SaveThumbnail.rb
446 lines (437 loc) · 18 KB
/
MA_SaveThumbnail.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
#==============================================================================
# ■ save & load screen customization
# Ver 0.02 2012/01/21 Fixed scene for event command “Save screen”
# Fixed a bug that was not compatible with "Open"
# Ver 0.01 2011/12/25
# http://fweb.midi.co.jp/~mikagami/atelier/
#------------------------------------------------------------------------------
#
# Change the appearance of the save screen and load screen with thumbnail.
# Save location (map display name) in the save file and the game screen.
#
# ※Note!
# ・Save files that are used before installing this script can no longer be used.
# ・Because the thumbnail of the game screen is converted and saved,
# Save file size is relatively large. Also, the preview display speed is slow.
# ・Although we have confirmed functionality, we do not guarantee zero defects.
# ・The author holds the copyrights to this script. 水鏡幻姿 (Mikagami Atelier)
# However, you do not need the author's permission to use, revise, or redistribute this script.
# The author does not have an obligation to fulfill requests to revise the script or complete its unfinished parts.
# Instead of asking another person to revise the script, everybody will be happy if you revise it yourself.
#
#==============================================================================
module DataManager
#--------------------------------------------------------------------------
# ◎ Maximum number of save files (overwrite definition)
#--------------------------------------------------------------------------
def self.savefile_max
return 20 # Set a reasonable amount
end
#--------------------------------------------------------------------------
# ● Get save folder name
#--------------------------------------------------------------------------
def self.save_folder_name
return "Save"
end
#--------------------------------------------------------------------------
# ◎ Save file existence judgment (overwrite definition)
#--------------------------------------------------------------------------
def self.save_file_exists?
if save_folder_name == ""
path = 'Save*.rvdata2'
else
path = save_folder_name + '/Save*.rvdata2'
end
!Dir.glob(path).empty?
end
#--------------------------------------------------------------------------
# ◎ Create file name (overwrite definition)
# index : File index
#--------------------------------------------------------------------------
def self.make_filename(index)
file_name = sprintf("Save%03d.rvdata2", index + 1)
if save_folder_name == ""
return file_name
else
return save_folder_name + '/' + file_name
end
end
#--------------------------------------------------------------------------
# ● Execution of save / preview
#--------------------------------------------------------------------------
def self.save_game_with_preview(index)
begin
save_game_without_rescue2(index)
rescue
delete_save_file(index)
false
end
end
#--------------------------------------------------------------------------
# ● Load execution and preview available
#--------------------------------------------------------------------------
def self.load_game2(index)
load_game_without_rescue2(index) rescue false
end
#--------------------------------------------------------------------------
# ● Load preview
#--------------------------------------------------------------------------
def self.load_preview(index)
load_preview_without_rescue(index) rescue nil
end
#--------------------------------------------------------------------------
# ● Execution of save and preview (no exception handling)
#--------------------------------------------------------------------------
def self.save_game_without_rescue2(index)
unless FileTest.directory?(save_folder_name)
if FileTest.exist?(save_folder_name)
msgbox "An error occurred during the save process. Please restart."
return false
end
Dir::mkdir(save_folder_name)
unless FileTest.directory?(save_folder_name)
msgbox "Save failed. Check your HDD/SSD free space, etc."
return false
end
end
File.open(make_filename(index), "wb") do |file|
$game_system.on_before_save
Marshal.dump(make_save_header2, file)
Marshal.dump(make_save_preview, file)
Marshal.dump(make_save_contents, file)
@last_savefile_index = index
end
return true
end
#--------------------------------------------------------------------------
# ● Load execution with preview (no exception handling)
#--------------------------------------------------------------------------
def self.load_game_without_rescue2(index)
File.open(make_filename(index), "rb") do |file|
Marshal.load(file)
Marshal.load(file)
extract_save_contents(Marshal.load(file))
reload_map_if_updated
@last_savefile_index = index
end
return true
end
#--------------------------------------------------------------------------
# ● Create / extend save header
#--------------------------------------------------------------------------
def self.make_save_header2
header = {}
header[:characters] = $game_party.characters_for_savefile
header[:playtime_s] = $game_system.playtime_s
header[:savetitle] = $game_map.display_name
header
end
#--------------------------------------------------------------------------
# ● Load preview (no exception handling)
#--------------------------------------------------------------------------
def self.load_preview_without_rescue(index)
File.open(make_filename(index), "rb") do |file|
Marshal.load(file)
return array_to_bitmap(Marshal.load(file))
end
return nil
end
#--------------------------------------------------------------------------
# ● Create preview
#--------------------------------------------------------------------------
def self.make_save_preview
preview = bitmap_to_array($game_temp.save_preview_bmp)
preview
end
#--------------------------------------------------------------------------
# ● Convert preview bitmap to saveable array format
# bitmap
#--------------------------------------------------------------------------
def self.bitmap_to_array(bitmap)
return unless bitmap
data = []
for i in 0...bitmap.width
data[i] = []
for j in 0...bitmap.height
color = bitmap.get_pixel(i, j)
value = (color.red.floor << 16) + (color.green.floor << 8) + color.blue.floor
data[i][j] = value
end
end
return data
end
#--------------------------------------------------------------------------
# ● Restore preview bitmap from array format to bitmap
#--------------------------------------------------------------------------
def self.array_to_bitmap(data)
return unless data
bitmap = Bitmap.new(data.size, data[0].size)
for i in 0...data.size
for j in 0...data[0].size
red = (data[i][j] >> 16) & 0xff
green = (data[i][j] >> 8) & 0xff
blue = data[i][j] & 0xff
color = Color.new(red, green, blue)
bitmap.set_pixel(i, j, color)
end
end
return bitmap
end
end
class Game_Temp
#--------------------------------------------------------------------------
# ● Public instance variables
#--------------------------------------------------------------------------
attr_accessor :save_preview_bmp # BMP for save preview
#--------------------------------------------------------------------------
# ● Object initialization
#--------------------------------------------------------------------------
alias _old001_initialize initialize
def initialize
_old001_initialize
@save_preview_bmp = Bitmap.new(1, 1)
end
#--------------------------------------------------------------------------
# ● BMP for save preview
#--------------------------------------------------------------------------
def create_save_preview
@save_preview_bmp.dispose if @save_preview_bmp
@save_preview_bmp = Bitmap.new(224, 160)
rect = Rect.new(0, 0, 224, 160)
rect.x = $game_player.screen_x - 112
rect.y = $game_player.screen_y - 80 - 16
bitmap = Graphics.snap_to_bitmap
@save_preview_bmp.blt(0, 0, bitmap, rect)
bitmap.dispose
end
end
class Game_Party < Game_Unit
#--------------------------------------------------------------------------
# ◎ Character image information for save file display (overwrite definition)
#--------------------------------------------------------------------------
def characters_for_savefile
battle_members.collect do |actor|
[actor.character_name, actor.character_index, actor.level, actor.name]
end
end
end
#==============================================================================
# ■ Window_SaveFileList
#------------------------------------------------------------------------------
# Save file list window displayed on the save & load screen.
#==============================================================================
class Window_SaveFileList < Window_Selectable
#--------------------------------------------------------------------------
# ● Object initialization
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, (Graphics.width - x) / 2, Graphics.height - y)
load_savefileheader
refresh
activate
end
#--------------------------------------------------------------------------
# ● Get number of items
#--------------------------------------------------------------------------
def item_max
DataManager.savefile_max
end
#--------------------------------------------------------------------------
# ● Get item height
#--------------------------------------------------------------------------
def item_height
(height - standard_padding * 2) / 5
end
#--------------------------------------------------------------------------
# ● Drawing items
#--------------------------------------------------------------------------
def draw_item(index)
rect = item_rect_for_text(index)
text_h = rect.y + (rect.height - line_height * 2) / 2
name = Vocab::File + " #{index + 1}"
change_color(system_color)
draw_text(rect.x, text_h, rect.width, line_height, name)
return unless @data[index]
change_color(normal_color)
draw_playtime(rect.x, text_h, rect.width, line_height, index)
draw_savetitle(rect.x, text_h + line_height, rect.width, line_height, index)
end
#--------------------------------------------------------------------------
# ● Processing when the enter button is pressed
#--------------------------------------------------------------------------
def process_ok
call_ok_handler # Process with scene class
end
#--------------------------------------------------------------------------
# ● Read all save file headers
#--------------------------------------------------------------------------
def load_savefileheader
@data = []
for i in 0...item_max do @data[i] = DataManager.load_header(i) end
end
#--------------------------------------------------------------------------
# ● Drawing play time
#--------------------------------------------------------------------------
def draw_playtime(x, y, width, height, i)
draw_text(x, y, width, height, @data[i][:playtime_s], 2)
end
#--------------------------------------------------------------------------
# ● Drawing save titles
#--------------------------------------------------------------------------
def draw_savetitle(x, y, width, height, i)
title = @data[i][:savetitle]
title = "<NO TITLE>" if title == ""
draw_text(x, y, width, height, title)
end
end
#==============================================================================
# ■ Window_SaveFilePreview
#------------------------------------------------------------------------------
# This is the save file window displayed during save & load screen.
#==============================================================================
class Window_SaveFilePreview < Window_Base
#--------------------------------------------------------------------------
# ● Object initialization
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, Graphics.width - x, Graphics.height - y)
@file_no = -1
@bmps = []
@data = []
end
#--------------------------------------------------------------------------
# ● Dispose
#--------------------------------------------------------------------------
def dispose
for bmp in @bmps
next if bmp == nil or bmp.disposed?
bmp.dispose
end
super
end
#--------------------------------------------------------------------------
# ● Load save file and display preview
# file_no : Save file number
#--------------------------------------------------------------------------
def set_preview(file_no)
return if @file_no == file_no
@file_no = file_no
refresh
end
#--------------------------------------------------------------------------
# ● Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
load_preview(@file_no)
return unless @data[@file_no]
bitmap = @bmps[@file_no]
start_x = (contents.width - bitmap.width) / 2
contents.fill_rect(start_x - 1, 7, bitmap.width + 2, bitmap.height + 2, Color.new(0, 0, 0))
contents.blt(start_x, 8, bitmap, bitmap.rect)
header = @data[@file_no]
header[:characters].each_with_index do |data, i|
break if i >= 4
character_y = bitmap.height + 22 + i * 40
draw_character(data[0], data[1], start_x + 16, character_y + 28)
draw_level_for_preview(data[2], start_x + 40, character_y)
draw_name_for_preview(data[3], start_x + 100, character_y, bitmap.width - start_x - 100)
end
end
#--------------------------------------------------------------------------
# ● Load preview data
#--------------------------------------------------------------------------
def load_preview(file_no)
return if @data[file_no]
@bmps[file_no] = DataManager.load_preview(file_no)
return unless @bmps[file_no]
@data[file_no] = DataManager.load_header(file_no)
end
#--------------------------------------------------------------------------
# ● Level drawing
#--------------------------------------------------------------------------
def draw_level_for_preview(level, x, y)
change_color(system_color)
draw_text(x, y, 24, line_height, Vocab::level_a)
change_color(normal_color)
draw_text(x + 24, y, 24, line_height, level, 2)
end
#--------------------------------------------------------------------------
# ● Actor name drawing
#--------------------------------------------------------------------------
def draw_name_for_preview(name, x, y, width)
change_color(normal_color)
draw_text(x, y, width, line_height, name)
end
end
class Scene_File < Scene_MenuBase
#--------------------------------------------------------------------------
# ◎ Start processing (overwrite definition)
#--------------------------------------------------------------------------
def start
super
create_help_window
@filelist_window = Window_SaveFileList.new(0, @help_window.height)
@filelist_window.set_handler(:ok, method(:on_savefile_ok))
@filelist_window.set_handler(:cancel, method(:on_savefile_cancel))
@preview_window = Window_SaveFilePreview.new(@filelist_window.width, @help_window.height)
init_selection
end
#--------------------------------------------------------------------------
# ◎ End processing (overwrite definition)
#--------------------------------------------------------------------------
def terminate
super
end
#--------------------------------------------------------------------------
# ◎ Initialize selected state (overwrite definition)
#--------------------------------------------------------------------------
def init_selection
index = first_savefile_index
@filelist_window.select(index)
@preview_window.set_preview(index)
end
#--------------------------------------------------------------------------
# ◎ Frame update (overwrite definition)
#--------------------------------------------------------------------------
def update
super
@preview_window.set_preview(@filelist_window.index)
end
end
class Scene_Save < Scene_File
#--------------------------------------------------------------------------
# ◎ Save file (overwrite definition)
#--------------------------------------------------------------------------
def on_savefile_ok
super
if DataManager.save_game_with_preview(@filelist_window.index)
on_save_success
else
Sound.play_buzzer
end
end
end
class Scene_Load < Scene_File
#--------------------------------------------------------------------------
# ◎ Save file (overwrite definition)
#--------------------------------------------------------------------------
def on_savefile_ok
super
if DataManager.load_game2(@filelist_window.index)
on_load_success
else
Sound.play_buzzer
end
end
end
class Scene_Map < Scene_Base
#--------------------------------------------------------------------------
# ◎ End processing
#--------------------------------------------------------------------------
alias _old001_terminate terminate
def terminate
$game_temp.create_save_preview
_old001_terminate
end
end