Files
infinitefusion-e18/Data/Scripts/018_Minigames/003_Minigame_SlotMachine.rb

405 lines
13 KiB
Ruby

################################################################################
# "Slot Machine" mini-game
# By Maruno
#-------------------------------------------------------------------------------
# Run with: pbSlotMachine(1)
# - The number is either 0 (easy), 1 (default) or 2 (hard).
################################################################################
class SlotMachineReel < BitmapSprite
attr_accessor :reel
attr_accessor :toppos
attr_accessor :spinning
attr_accessor :stopping
attr_accessor :slipping
SCROLLSPEED = 16 # Must be a divisor of 48
ICONSPOOL = [[0,0,0,0,1,1,2,2,3,3,3,4,4,4,5,5,6,6,7], # 0 - Easy
[0,0,0,0,1,1,1,2,2,2,3,3,4,4,5,6,7], # 1 - Medium (default)
[0,0,1,1,1,2,2,2,3,3,4,4,5,6,7] # 2 - Hard
]
SLIPPING = [0,0,0,0,0,0,1,1,1,2,2,3]
def initialize(x,y,difficulty=1)
@viewport=Viewport.new(x,y,64,144)
@viewport.z=99999
super(64,144,@viewport)
@reel=[]
for i in 0...ICONSPOOL[difficulty].length
@reel.push(ICONSPOOL[difficulty][i])
end
@reel.shuffle!
@toppos=0
@spinning=false
@stopping=false
@slipping=0
@index=rand(@reel.length)
@images=AnimatedBitmap.new(_INTL("Graphics/Pictures/Slot Machine/images"))
@shading=AnimatedBitmap.new(_INTL("Graphics/Pictures/Slot Machine/ReelOverlay"))
update
end
def startSpinning
@spinning=true
end
def stopSpinning(noslipping=false)
@stopping=true
@slipping=SLIPPING[rand(SLIPPING.length)]
@slipping=0 if noslipping
end
def showing
array=[]
for i in 0...3
num=@index-i
num+=@reel.length if num<0
array.push(@reel[num])
end
return array # [0] = top, [1] = middle, [2] = bottom
end
def update
self.bitmap.clear
if @toppos==0 && @stopping && @slipping==0
@spinning=@stopping=false
end
if @spinning
@toppos+=SCROLLSPEED
if @toppos>0
@toppos-=48
@index=(@index+1)%@reel.length
@slipping-=1 if @slipping>0
end
end
for i in 0...4
num=@index-i
num+=@reel.length if num<0
self.bitmap.blt(0,@toppos+i*48,@images.bitmap,Rect.new(@reel[num]*64,0,64,48))
end
self.bitmap.blt(0,0,@shading.bitmap,Rect.new(0,0,64,144))
end
end
class SlotMachineScore < BitmapSprite
attr_reader :score
def initialize(x,y,score=0)
@viewport=Viewport.new(x,y,70,22)
@viewport.z=99999
super(70,22,@viewport)
@numbers=AnimatedBitmap.new(_INTL("Graphics/Pictures/Slot Machine/numbers"))
self.score=score
end
def score=(value)
@score = value
@score = Settings::MAX_COINS if @score > Settings::MAX_COINS
refresh
end
def refresh
self.bitmap.clear
for i in 0...5
digit=(@score/(10**i))%10 # Least significant digit first
self.bitmap.blt(14*(4-i),0,@numbers.bitmap,Rect.new(digit*14,0,14,22))
end
end
end
class SlotMachineScene
attr_accessor :gameRunning
attr_accessor :gameEnd
attr_accessor :wager
attr_accessor :replay
def update
pbUpdateSpriteHash(@sprites)
end
def pbPayout
@replay=false
payout=0
bonus=0
wonRow=[]
# Get reel pictures
reel1=@sprites["reel1"].showing
reel2=@sprites["reel2"].showing
reel3=@sprites["reel3"].showing
combinations=[[reel1[1],reel2[1],reel3[1]], # Centre row
[reel1[0],reel2[0],reel3[0]], # Top row
[reel1[2],reel2[2],reel3[2]], # Bottom row
[reel1[0],reel2[1],reel3[2]], # Diagonal top left -> bottom right
[reel1[2],reel2[1],reel3[0]], # Diagonal bottom left -> top right
]
for i in 0...combinations.length
break if i>=1 && @wager<=1 # One coin = centre row only
break if i>=3 && @wager<=2 # Two coins = three rows only
wonRow[i]=true
case combinations[i]
when [1,1,1] # Three Magnemites
payout += 8
when [2,2,2] # Three Shellders
payout += 8
when [3,3,3] # Three Pikachus
payout += 15
when [4,4,4] # Three Psyducks
payout += 15
when [5,5,6], [5,6,5], [6,5,5], [6,6,5], [6,5,6], [5,6,6] # 777 multi-colored
payout += 90
bonus = 1 if bonus<1
when [5,5,5], [6,6,6] # Red 777, blue 777
payout += 300
bonus = 2 if bonus<2
when [7,7,7] # Three replays
@replay = true
else
if combinations[i][0]==0 # Left cherry
if combinations[i][1]==0 # Centre cherry as well
payout+=4
else
payout+=2
end
else
wonRow[i]=false
end
end
end
@sprites["payout"].score=payout
frame=0
if payout>0 || @replay
if bonus>0
pbMEPlay("Slots big win")
else
pbMEPlay("Slots win")
end
# Show winning animation
timePerFrame = Graphics.frame_rate/8
until frame==Graphics.frame_rate*3
Graphics.update
Input.update
update
@sprites["window2"].bitmap.clear if @sprites["window2"].bitmap
@sprites["window1"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/win"))
@sprites["window1"].src_rect.set(152*((frame/timePerFrame)%4),0,152,208)
if bonus>0
@sprites["window2"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/bonus"))
@sprites["window2"].src_rect.set(152*(bonus-1),0,152,208)
end
@sprites["light1"].visible=true
@sprites["light1"].src_rect.set(0,26*((frame/timePerFrame)%4),96,26)
@sprites["light2"].visible=true
@sprites["light2"].src_rect.set(0,26*((frame/timePerFrame)%4),96,26)
for i in 1..5
if wonRow[i-1]
@sprites["row#{i}"].visible = ((frame/timePerFrame)%2)==0
else
@sprites["row#{i}"].visible = false
end
end
frame += 1
end
@sprites["light1"].visible=false
@sprites["light2"].visible=false
@sprites["window1"].src_rect.set(0,0,152,208)
# Pay out
loop do
break if @sprites["payout"].score<=0
Graphics.update
Input.update
update
@sprites["payout"].score -= 1
@sprites["credit"].score += 1
if Input.trigger?(Input::USE) || @sprites["credit"].score == Settings::MAX_COINS
@sprites["credit"].score += @sprites["payout"].score
@sprites["payout"].score = 0
end
end
(Graphics.frame_rate/2).times do
Graphics.update
Input.update
update
end
else
# Show losing animation
timePerFrame = Graphics.frame_rate/4
until frame==Graphics.frame_rate*2
Graphics.update
Input.update
update
@sprites["window2"].bitmap.clear if @sprites["window2"].bitmap
@sprites["window1"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/lose"))
@sprites["window1"].src_rect.set(152*((frame/timePerFrame)%2),0,152,208)
frame += 1
end
end
@wager = 0
end
def pbStartScene(difficulty)
@sprites={}
@viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
@viewport.z=99999
addBackgroundPlane(@sprites,"bg","Slot Machine/bg",@viewport)
@sprites["reel1"]=SlotMachineReel.new(64,112,difficulty)
@sprites["reel2"]=SlotMachineReel.new(144,112,difficulty)
@sprites["reel3"]=SlotMachineReel.new(224,112,difficulty)
for i in 1..3
@sprites["button#{i}"]=IconSprite.new(68+80*(i-1),260,@viewport)
@sprites["button#{i}"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/button"))
@sprites["button#{i}"].visible=false
end
for i in 1..5
y=[170,122,218,82,82][i-1]
@sprites["row#{i}"]=IconSprite.new(2,y,@viewport)
@sprites["row#{i}"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/line%1d%s",
1+i/2,(i>=4) ? ((i==4) ? "a" : "b") : ""))
@sprites["row#{i}"].visible=false
end
@sprites["light1"]=IconSprite.new(16,32,@viewport)
@sprites["light1"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/lights"))
@sprites["light1"].visible=false
@sprites["light2"]=IconSprite.new(240,32,@viewport)
@sprites["light2"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/lights"))
@sprites["light2"].mirror=true
@sprites["light2"].visible=false
@sprites["window1"]=IconSprite.new(358,96,@viewport)
@sprites["window1"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/insert"))
@sprites["window1"].src_rect.set(0,0,152,208)
@sprites["window2"]=IconSprite.new(358,96,@viewport)
@sprites["credit"]=SlotMachineScore.new(360,66,$Trainer.coins)
@sprites["payout"]=SlotMachineScore.new(438,66,0)
@wager=0
update
pbFadeInAndShow(@sprites)
end
def pbMain
frame=0
spinFrameTime = Graphics.frame_rate/4
insertFrameTime = Graphics.frame_rate*4/10
loop do
Graphics.update
Input.update
update
@sprites["window1"].bitmap.clear if @sprites["window1"].bitmap
@sprites["window2"].bitmap.clear if @sprites["window2"].bitmap
if @sprites["credit"].score == Settings::MAX_COINS
pbMessage(_INTL("You've got {1} Coins.", Settings::MAX_COINS.to_s_formatted))
break
elsif $Trainer.coins==0
pbMessage(_INTL("You've run out of Coins.\nGame over!"))
break
elsif @gameRunning # Reels are spinning
@sprites["window1"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/stop"))
@sprites["window1"].src_rect.set(152*((frame/spinFrameTime)%4),0,152,208)
if Input.trigger?(Input::USE)
pbSEPlay("Slots stop")
if @sprites["reel1"].spinning
@sprites["reel1"].stopSpinning(@replay)
@sprites["button1"].visible=true
elsif @sprites["reel2"].spinning
@sprites["reel2"].stopSpinning(@replay)
@sprites["button2"].visible=true
elsif @sprites["reel3"].spinning
@sprites["reel3"].stopSpinning(@replay)
@sprites["button3"].visible=true
end
end
if !@sprites["reel3"].spinning
@gameEnd=true
@gameRunning=false
end
elsif @gameEnd # Reels have been stopped
pbPayout
# Reset graphics
@sprites["button1"].visible=false
@sprites["button2"].visible=false
@sprites["button3"].visible=false
for i in 1..5
@sprites["row#{i}"].visible=false
end
@gameEnd=false
else # Awaiting coins for the next spin
@sprites["window1"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/insert"))
@sprites["window1"].src_rect.set(152*((frame/insertFrameTime)%2),0,152,208)
if @wager>0
@sprites["window2"].setBitmap(sprintf("Graphics/Pictures/Slot Machine/press"))
@sprites["window2"].src_rect.set(152*((frame/insertFrameTime)%2),0,152,208)
end
if Input.trigger?(Input::DOWN) && @wager<3 && @sprites["credit"].score>0
pbSEPlay("Slots coin")
@wager+=1
@sprites["credit"].score-=1
if @wager>=3
@sprites["row5"].visible=true
@sprites["row4"].visible=true
elsif @wager>=2
@sprites["row3"].visible=true
@sprites["row2"].visible=true
elsif @wager>=1
@sprites["row1"].visible=true
end
elsif @wager>=3 || (@wager>0 && @sprites["credit"].score==0) ||
(Input.trigger?(Input::USE) && @wager>0) || @replay
if @replay
@wager=3
for i in 1..5
@sprites["row#{i}"].visible=true
end
end
@sprites["reel1"].startSpinning
@sprites["reel2"].startSpinning
@sprites["reel3"].startSpinning
frame=0
@gameRunning=true
elsif Input.trigger?(Input::BACK) && @wager==0
break
end
end
frame = (frame+1)%(Graphics.frame_rate*4)
end
$Trainer.coins = @sprites["credit"].score
end
def pbEndScene
pbFadeOutAndHide(@sprites)
pbDisposeSpriteHash(@sprites)
@viewport.dispose
end
end
class SlotMachine
def initialize(scene)
@scene=scene
end
def pbStartScreen(difficulty)
@scene.pbStartScene(difficulty)
@scene.pbMain
@scene.pbEndScene
end
end
def pbSlotMachine(difficulty=1)
if GameData::Item.exists?(:COINCASE) && !$PokemonBag.pbHasItem?(:COINCASE)
pbMessage(_INTL("It's a Slot Machine."))
elsif $Trainer.coins == 0
pbMessage(_INTL("You don't have any Coins to play!"))
elsif $Trainer.coins == Settings::MAX_COINS
pbMessage(_INTL("Your Coin Case is full!"))
else
pbFadeOutIn {
scene = SlotMachineScene.new
screen = SlotMachine.new(scene)
screen.pbStartScreen(difficulty)
}
end
end