Skip to content

Commit d5c0d72

Browse files
committed
Add Item Popup System script
Window-based popup notifications for obtained items that slide in from the right edge of the screen and stack vertically for multiple simultaneous pickups.
1 parent 857947c commit d5c0d72

File tree

1 file changed

+330
-0
lines changed

1 file changed

+330
-0
lines changed
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
#==============================================================================
2+
# ** Item Popup System
3+
#------------------------------------------------------------------------------
4+
# Standard RPG Maker XP window-based popup for obtained items.
5+
# Windows slide in from the right edge of the screen and stack vertically.
6+
#
7+
# Usage in Event Script:
8+
# $game_party.item_popup(item_id, amount) # For items
9+
# $game_party.weapon_popup(weapon_id, amount) # For weapons
10+
# $game_party.armor_popup(armor_id, amount) # For armor
11+
# $game_party.gold_popup(amount) # For gold
12+
#
13+
# Example:
14+
# $game_party.item_popup(1, 2) # Shows "[Icon] Potion x 2"
15+
# $game_party.weapon_popup(1, 1) # Shows "[Icon] Bronze Sword x 1"
16+
# $game_party.gold_popup(500) # Shows "[Icon] Gold x 500"
17+
#==============================================================================
18+
19+
#==============================================================================
20+
# ** Window_ItemPopup
21+
#------------------------------------------------------------------------------
22+
# A standard RPG Maker XP window for item popups
23+
#==============================================================================
24+
class Window_ItemPopup < Window_Base
25+
#--------------------------------------------------------------------------
26+
# * Configuration
27+
#--------------------------------------------------------------------------
28+
DISPLAY_TIME = 120 # Frames to display (2 seconds at 60fps)
29+
SLIDE_IN_TIME = 12 # Frames for slide-in animation
30+
SLIDE_OUT_TIME = 12 # Frames for slide-out animation
31+
SOUND_EFFECT = "002-System02" # Sound when popup appears
32+
WINDOW_WIDTH = 260 # Width of popup window
33+
WINDOW_HEIGHT = 52 # Height of popup window (compact but fits content)
34+
OVERHANG = 32 # How much window hangs off right edge
35+
MARGIN_BOTTOM = 8 # Margin from bottom edge
36+
STACK_SPACING = 4 # Space between stacked popups
37+
GOLD_ICON = "032-Item01" # Icon for gold popup
38+
39+
#--------------------------------------------------------------------------
40+
# * Object Initialization
41+
#--------------------------------------------------------------------------
42+
def initialize(stack_index = 0)
43+
@stack_index = stack_index
44+
super(640, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
45+
self.contents = Bitmap.new(width - 32, height - 32)
46+
self.z = 9999
47+
@timer = 0
48+
@phase = :hidden
49+
update_target_position
50+
end
51+
52+
#--------------------------------------------------------------------------
53+
# * Update Target Position Based on Stack Index
54+
#--------------------------------------------------------------------------
55+
def update_target_position
56+
@target_x = 640 - WINDOW_WIDTH + OVERHANG
57+
@target_y = 480 - WINDOW_HEIGHT - MARGIN_BOTTOM - (@stack_index * (WINDOW_HEIGHT + STACK_SPACING))
58+
end
59+
60+
#--------------------------------------------------------------------------
61+
# * Set Stack Index
62+
#--------------------------------------------------------------------------
63+
def stack_index=(value)
64+
@stack_index = value
65+
update_target_position
66+
if @phase == :displayed || @phase == :sliding_in
67+
self.y = @target_y
68+
end
69+
end
70+
71+
#--------------------------------------------------------------------------
72+
# * Get Stack Index
73+
#--------------------------------------------------------------------------
74+
def stack_index
75+
@stack_index
76+
end
77+
78+
#--------------------------------------------------------------------------
79+
# * Display Popup
80+
#--------------------------------------------------------------------------
81+
def display_popup(name, icon_name, amount, play_sound = true)
82+
if play_sound
83+
se = RPG::AudioFile.new(SOUND_EFFECT, 80, 100)
84+
$game_system.se_play(se)
85+
end
86+
self.contents.clear
87+
icon_bitmap = nil
88+
if icon_name != "" && icon_name != "gold"
89+
begin
90+
icon_bitmap = RPG::Cache.icon(icon_name)
91+
rescue
92+
icon_bitmap = nil
93+
end
94+
elsif icon_name == "gold"
95+
begin
96+
icon_bitmap = RPG::Cache.icon(GOLD_ICON)
97+
rescue
98+
icon_bitmap = nil
99+
end
100+
end
101+
content_height = WINDOW_HEIGHT - 32
102+
icon_x = 0
103+
icon_y = (content_height - 24) / 2
104+
105+
if icon_bitmap
106+
self.contents.blt(icon_x, icon_y, icon_bitmap, Rect.new(0, 0, 24, 24))
107+
end
108+
text_x = icon_x + 32
109+
text_y = (content_height - 16) / 2 - 1
110+
self.contents.font.size = 18
111+
self.contents.font.bold = true
112+
self.contents.font.color = normal_color
113+
self.contents.draw_text(text_x, text_y, 110, 18, name)
114+
if amount > 0
115+
self.contents.font.color = system_color
116+
amount_text = "x #{amount}"
117+
self.contents.draw_text(WINDOW_WIDTH - 32 - OVERHANG - 60, text_y, 60, 18, amount_text, 2)
118+
end
119+
self.contents.font.bold = false
120+
@timer = 0
121+
@phase = :sliding_in
122+
update_target_position
123+
self.x = 640
124+
self.y = @target_y
125+
self.visible = true
126+
end
127+
128+
#--------------------------------------------------------------------------
129+
# * Frame Update
130+
#--------------------------------------------------------------------------
131+
def update
132+
super
133+
134+
case @phase
135+
when :sliding_in
136+
@timer += 1
137+
progress = [@timer.to_f / SLIDE_IN_TIME.to_f, 1.0].min
138+
ease_progress = 1.0 - (1.0 - progress) ** 2
139+
self.x = 640 - ((640 - @target_x) * ease_progress).to_i
140+
141+
if @timer >= SLIDE_IN_TIME
142+
@phase = :displayed
143+
@timer = 0
144+
self.x = @target_x
145+
end
146+
147+
when :displayed
148+
self.y = @target_y
149+
@timer += 1
150+
if @timer >= DISPLAY_TIME
151+
@phase = :sliding_out
152+
@timer = 0
153+
end
154+
155+
when :sliding_out
156+
@timer += 1
157+
progress = [@timer.to_f / SLIDE_OUT_TIME.to_f, 1.0].min
158+
ease_progress = progress ** 2
159+
self.x = @target_x + ((640 - @target_x) * ease_progress).to_i
160+
161+
if @timer >= SLIDE_OUT_TIME
162+
@phase = :hidden
163+
@timer = 0
164+
self.visible = false
165+
self.x = 640
166+
end
167+
168+
when :hidden
169+
self.visible = false
170+
end
171+
end
172+
173+
#--------------------------------------------------------------------------
174+
# * Check if Active
175+
#--------------------------------------------------------------------------
176+
def active?
177+
@phase != :hidden
178+
end
179+
180+
#--------------------------------------------------------------------------
181+
# * Check if Ready for Reuse
182+
#--------------------------------------------------------------------------
183+
def available?
184+
@phase == :hidden
185+
end
186+
end
187+
188+
#==============================================================================
189+
# ** ItemPopupManager
190+
#------------------------------------------------------------------------------
191+
# Manages multiple stacked item popup windows
192+
#==============================================================================
193+
class ItemPopupManager
194+
MAX_POPUPS = 5 # Maximum simultaneous popups
195+
196+
def initialize
197+
@popups = []
198+
MAX_POPUPS.times do |i|
199+
@popups << Window_ItemPopup.new(i)
200+
end
201+
end
202+
203+
def show_item(item_id, amount = 1)
204+
item = $data_items[item_id]
205+
return unless item
206+
$game_party.gain_item(item_id, amount)
207+
add_popup(item.name, item.icon_name, amount)
208+
end
209+
210+
def show_weapon(weapon_id, amount = 1)
211+
weapon = $data_weapons[weapon_id]
212+
return unless weapon
213+
$game_party.gain_weapon(weapon_id, amount)
214+
add_popup(weapon.name, weapon.icon_name, amount)
215+
end
216+
217+
def show_armor(armor_id, amount = 1)
218+
armor = $data_armors[armor_id]
219+
return unless armor
220+
$game_party.gain_armor(armor_id, amount)
221+
add_popup(armor.name, armor.icon_name, amount)
222+
end
223+
224+
def show_gold(amount)
225+
return if amount <= 0
226+
$game_party.gain_gold(amount)
227+
add_popup("Gold", "gold", amount)
228+
end
229+
230+
def add_popup(name, icon_name, amount)
231+
@popups.each do |popup|
232+
if popup.active?
233+
popup.stack_index += 1
234+
end
235+
end
236+
available_popup = @popups.find { |p| p.available? }
237+
238+
if available_popup
239+
available_popup.stack_index = 0
240+
available_popup.display_popup(name, icon_name, amount)
241+
end
242+
end
243+
244+
def update
245+
@popups.each { |popup| popup.update }
246+
reindex_popups
247+
end
248+
249+
def reindex_popups
250+
active = @popups.select { |p| p.active? }.sort_by { |p| p.stack_index }
251+
active.each_with_index do |popup, index|
252+
popup.stack_index = index
253+
end
254+
end
255+
256+
def dispose
257+
@popups.each { |popup| popup.dispose }
258+
@popups.clear
259+
end
260+
end
261+
262+
#==============================================================================
263+
# ** Scene_Map
264+
#------------------------------------------------------------------------------
265+
# Add item popup manager to map scene
266+
#==============================================================================
267+
class Scene_Map
268+
#--------------------------------------------------------------------------
269+
# * Alias: Main Processing
270+
#--------------------------------------------------------------------------
271+
alias item_popup_main main unless method_defined?(:item_popup_main)
272+
def main
273+
$item_popup_manager = ItemPopupManager.new
274+
item_popup_main
275+
$item_popup_manager.dispose
276+
$item_popup_manager = nil
277+
end
278+
279+
#--------------------------------------------------------------------------
280+
# * Alias: Frame Update
281+
#--------------------------------------------------------------------------
282+
alias item_popup_update update unless method_defined?(:item_popup_update)
283+
def update
284+
$item_popup_manager.update if $item_popup_manager
285+
item_popup_update
286+
end
287+
end
288+
289+
#==============================================================================
290+
# ** Game_Party
291+
#------------------------------------------------------------------------------
292+
# Add convenience methods to trigger popups from events
293+
#==============================================================================
294+
class Game_Party
295+
#--------------------------------------------------------------------------
296+
# * Show Item Popup (call from event)
297+
#--------------------------------------------------------------------------
298+
def item_popup(item_id, amount = 1)
299+
if $item_popup_manager
300+
$item_popup_manager.show_item(item_id, amount)
301+
end
302+
end
303+
304+
#--------------------------------------------------------------------------
305+
# * Show Weapon Popup (call from event)
306+
#--------------------------------------------------------------------------
307+
def weapon_popup(weapon_id, amount = 1)
308+
if $item_popup_manager
309+
$item_popup_manager.show_weapon(weapon_id, amount)
310+
end
311+
end
312+
313+
#--------------------------------------------------------------------------
314+
# * Show Armor Popup (call from event)
315+
#--------------------------------------------------------------------------
316+
def armor_popup(armor_id, amount = 1)
317+
if $item_popup_manager
318+
$item_popup_manager.show_armor(armor_id, amount)
319+
end
320+
end
321+
322+
#--------------------------------------------------------------------------
323+
# * Show Gold Popup (call from event)
324+
#--------------------------------------------------------------------------
325+
def gold_popup(amount)
326+
if $item_popup_manager
327+
$item_popup_manager.show_gold(amount)
328+
end
329+
end
330+
end

0 commit comments

Comments
 (0)