1897 lines
73 KiB
Lua
1897 lines
73 KiB
Lua
-- Minislots game engine
|
|
-- by Vanessa "VanessaE" Dannenberg
|
|
|
|
local mtver = minetest.get_version()
|
|
|
|
math.randomseed(os.time())
|
|
|
|
local char_widths = {
|
|
[32] = { regular = 16, condensed = 12, bold = 24 },
|
|
[33] = { regular = 22, condensed = 18, bold = 28 },
|
|
[34] = { regular = 29, condensed = 23, bold = 40 },
|
|
[35] = { regular = 48, condensed = 39, bold = 47 },
|
|
[36] = { regular = 47, condensed = 39, bold = 47 },
|
|
[37] = { regular = 74, condensed = 60, bold = 75 },
|
|
[38] = { regular = 56, condensed = 46, bold = 61 },
|
|
[39] = { regular = 15, condensed = 12, bold = 20 },
|
|
[40] = { regular = 29, condensed = 24, bold = 29 },
|
|
[41] = { regular = 27, condensed = 22, bold = 28 },
|
|
[42] = { regular = 33, condensed = 27, bold = 34 },
|
|
[43] = { regular = 48, condensed = 39, bold = 49 },
|
|
[44] = { regular = 22, condensed = 18, bold = 23 },
|
|
[45] = { regular = 27, condensed = 22, bold = 28 },
|
|
[46] = { regular = 22, condensed = 18, bold = 23 },
|
|
[47] = { regular = 25, condensed = 21, bold = 24 },
|
|
[48] = { regular = 46, condensed = 37, bold = 47 },
|
|
[49] = { regular = 46, condensed = 37, bold = 47 },
|
|
[50] = { regular = 46, condensed = 37, bold = 47 },
|
|
[51] = { regular = 46, condensed = 37, bold = 47 },
|
|
[52] = { regular = 46, condensed = 38, bold = 48 },
|
|
[53] = { regular = 46, condensed = 37, bold = 47 },
|
|
[54] = { regular = 46, condensed = 37, bold = 47 },
|
|
[55] = { regular = 46, condensed = 37, bold = 47 },
|
|
[56] = { regular = 46, condensed = 37, bold = 47 },
|
|
[57] = { regular = 46, condensed = 37, bold = 47 },
|
|
[58] = { regular = 22, condensed = 18, bold = 28 },
|
|
[59] = { regular = 22, condensed = 18, bold = 28 },
|
|
[60] = { regular = 48, condensed = 39, bold = 49 },
|
|
[61] = { regular = 48, condensed = 39, bold = 49 },
|
|
[62] = { regular = 48, condensed = 39, bold = 49 },
|
|
[63] = { regular = 46, condensed = 37, bold = 51 },
|
|
[64] = { regular = 84, condensed = 69, bold = 82 },
|
|
[65] = { regular = 57, condensed = 47, bold = 61 },
|
|
[66] = { regular = 55, condensed = 45, bold = 61 },
|
|
[67] = { regular = 60, condensed = 49, bold = 61 },
|
|
[68] = { regular = 60, condensed = 49, bold = 61 },
|
|
[69] = { regular = 55, condensed = 45, bold = 56 },
|
|
[70] = { regular = 50, condensed = 41, bold = 51 },
|
|
[71] = { regular = 64, condensed = 53, bold = 65 },
|
|
[72] = { regular = 60, condensed = 49, bold = 61 },
|
|
[73] = { regular = 22, condensed = 18, bold = 23 },
|
|
[74] = { regular = 41, condensed = 33, bold = 47 },
|
|
[75] = { regular = 57, condensed = 47, bold = 61 },
|
|
[76] = { regular = 46, condensed = 38, bold = 51 },
|
|
[77] = { regular = 69, condensed = 56, bold = 70 },
|
|
[78] = { regular = 60, condensed = 49, bold = 61 },
|
|
[79] = { regular = 64, condensed = 53, bold = 65 },
|
|
[80] = { regular = 55, condensed = 45, bold = 56 },
|
|
[81] = { regular = 64, condensed = 53, bold = 65 },
|
|
[82] = { regular = 60, condensed = 49, bold = 61 },
|
|
[83] = { regular = 55, condensed = 45, bold = 56 },
|
|
[84] = { regular = 51, condensed = 42, bold = 52 },
|
|
[85] = { regular = 60, condensed = 49, bold = 61 },
|
|
[86] = { regular = 57, condensed = 47, bold = 57 },
|
|
[87] = { regular = 80, condensed = 66, bold = 81 },
|
|
[88] = { regular = 56, condensed = 46, bold = 57 },
|
|
[89] = { regular = 56, condensed = 46, bold = 56 },
|
|
[90] = { regular = 50, condensed = 41, bold = 51 },
|
|
[91] = { regular = 24, condensed = 20, bold = 28 },
|
|
[92] = { regular = 25, condensed = 21, bold = 24 },
|
|
[93] = { regular = 22, condensed = 18, bold = 28 },
|
|
[94] = { regular = 40, condensed = 33, bold = 49 },
|
|
[95] = { regular = 49, condensed = 41, bold = 49 },
|
|
[96] = { regular = 27, condensed = 22, bold = 28 },
|
|
[97] = { regular = 48, condensed = 40, bold = 49 },
|
|
[98] = { regular = 46, condensed = 37, bold = 51 },
|
|
[99] = { regular = 41, condensed = 34, bold = 47 },
|
|
[100] = { regular = 46, condensed = 37, bold = 51 },
|
|
[101] = { regular = 46, condensed = 37, bold = 47 },
|
|
[102] = { regular = 25, condensed = 21, bold = 30 },
|
|
[103] = { regular = 46, condensed = 37, bold = 51 },
|
|
[104] = { regular = 46, condensed = 37, bold = 51 },
|
|
[105] = { regular = 18, condensed = 14, bold = 23 },
|
|
[106] = { regular = 18, condensed = 14, bold = 23 },
|
|
[107] = { regular = 44, condensed = 36, bold = 48 },
|
|
[108] = { regular = 18, condensed = 14, bold = 23 },
|
|
[109] = { regular = 69, condensed = 56, bold = 75 },
|
|
[110] = { regular = 46, condensed = 37, bold = 51 },
|
|
[111] = { regular = 46, condensed = 37, bold = 51 },
|
|
[112] = { regular = 46, condensed = 37, bold = 51 },
|
|
[113] = { regular = 46, condensed = 37, bold = 51 },
|
|
[114] = { regular = 28, condensed = 23, bold = 33 },
|
|
[115] = { regular = 41, condensed = 33, bold = 47 },
|
|
[116] = { regular = 24, condensed = 20, bold = 28 },
|
|
[117] = { regular = 46, condensed = 37, bold = 51 },
|
|
[118] = { regular = 43, condensed = 36, bold = 48 },
|
|
[119] = { regular = 62, condensed = 51, bold = 67 },
|
|
[120] = { regular = 43, condensed = 35, bold = 48 },
|
|
[121] = { regular = 43, condensed = 36, bold = 48 },
|
|
[122] = { regular = 41, condensed = 33, bold = 42 },
|
|
[123] = { regular = 28, condensed = 23, bold = 33 },
|
|
[124] = { regular = 21, condensed = 17, bold = 24 },
|
|
[125] = { regular = 28, condensed = 23, bold = 33 },
|
|
[126] = { regular = 48, condensed = 39, bold = 49 },
|
|
[127] = { regular = 45, condensed = 37, bold = 48 },
|
|
}
|
|
|
|
local words_numbers = { -- image widths, in pixels
|
|
[0] = "ZERO",
|
|
"ONE",
|
|
"TWO",
|
|
"THREE",
|
|
"FOUR",
|
|
"FIVE",
|
|
"SIX",
|
|
"SEVEN",
|
|
"EIGHT",
|
|
"NINE",
|
|
"TEN",
|
|
"ELEVEN",
|
|
"TWELVE",
|
|
"THIRTEEN",
|
|
"FOURTEEN",
|
|
"FIFTEEN",
|
|
"SIXTEEN",
|
|
"SEVENTEEN",
|
|
"EIGHTEEN",
|
|
"NINETEEN",
|
|
}
|
|
|
|
local words_tens = {
|
|
"",
|
|
"TWENTY",
|
|
"THIRTY",
|
|
"FORTY",
|
|
"FIFTY",
|
|
"SIXTY",
|
|
"SEVENTY",
|
|
"EIGHTY",
|
|
"NINETY",
|
|
}
|
|
|
|
local words_magnitudes = {
|
|
"HUNDRED",
|
|
"THOUSAND",
|
|
"MILLION",
|
|
}
|
|
|
|
minislots.player_last_machine_def = {}
|
|
minislots.player_last_machine_pos = {}
|
|
|
|
function minislots.spin_reels(def)
|
|
local spin = { [1] = {}, [2] = {}, [3] = {} }
|
|
for reel = 1, def.constants.numreels do
|
|
local n = math.random(2, def.constants.numsymbols*2+1)/2
|
|
if math.random(1, 100) >= def.half_stops_weight then n = math.floor(n) end
|
|
|
|
-- force a mixed-7's win, 3-reel
|
|
-- local n = 3
|
|
-- if reel == 2 then n = 10 end
|
|
-- if reel == 3 then n = 14 end
|
|
|
|
-- force a mixed-7's win, 5-reel
|
|
-- local n = 3
|
|
-- if reel == 2 then n = 10 end
|
|
-- if reel == 3 then n = 3 end
|
|
-- if reel == 4 then n = 10 end
|
|
-- if reel == 5 then n = 14 end
|
|
|
|
-- force a mixed-7's win, 5-reel, but with one wild card on the mixed-7's payline
|
|
-- local n = 3
|
|
-- if reel == 2 then n = 10 end
|
|
-- if reel == 3 then n = 9 end
|
|
-- if reel == 4 then n = 10 end
|
|
-- if reel == 5 then n = 14 end
|
|
|
|
-- force the all-wilds win shown in the cabinet graphics, 3-reel
|
|
-- local n = 10
|
|
-- if reel == 2 then n = 9 end
|
|
-- if reel == 3 then n = 8 end
|
|
|
|
-- force the all-wilds win shown in the cabinet graphics, 5-reel
|
|
-- local n = 10
|
|
-- if reel == 3 then n = 9 end
|
|
-- if reel > 3 then n = 8 end
|
|
|
|
-- force a no-win spin
|
|
-- local n = 1
|
|
-- if reel == 2 then n = 4 end
|
|
-- if reel == 3 then n = 10 end
|
|
|
|
-- local n = 12 -- force a scatter win
|
|
|
|
-- local n = 16 -- force a bonus win + 3 line wins
|
|
|
|
spin[1][reel] = { n-1, def.symbols[n-1] }
|
|
spin[2][reel] = { n, def.symbols[n] }
|
|
spin[3][reel] = { n+1, def.symbols[n+1] }
|
|
end
|
|
return spin
|
|
end
|
|
|
|
function minislots.reset_reels(def)
|
|
local resetspin = { [1] = {}, [2] = {}, [3] = {} }
|
|
for reel = 1, def.constants.numreels do
|
|
resetspin[1][reel] = { 0, def.symbols[0] }
|
|
resetspin[2][reel] = { 1, def.symbols[1] }
|
|
resetspin[3][reel] = { 2, def.symbols[2] }
|
|
end
|
|
return resetspin
|
|
end
|
|
|
|
function minislots.check_win(spin, def, maxlines)
|
|
local allwins = { total = 0, line_wins_total = 0 }
|
|
local paylinecontent = {}
|
|
allwins.scatter = { count = 0, pos = {} }
|
|
allwins.bonus = { value = -1, count = 0, pos = {} }
|
|
|
|
for payline,paylineoffsets in ipairs(def.lines) do
|
|
local highestwin = nil
|
|
local wildcount = 0
|
|
if payline > maxlines then break end
|
|
paylinecontent[payline] = {}
|
|
for _,m in ipairs(def.matches) do
|
|
|
|
local matchwin = true
|
|
local wc = 0
|
|
for reel = 1, def.constants.numreels do
|
|
local row = paylineoffsets[reel]+2
|
|
if not m[reel+1] or type(m[reel+1]) == "string" then
|
|
paylinecontent[payline][reel] = spin[row][reel][2]
|
|
if m[reel+1]
|
|
and spin[row][reel][2] ~= m[reel+1]
|
|
and (spin[row][reel][2] ~= "wild"
|
|
or (spin[row][reel][2] == "wild"
|
|
and def.wild_doesnt_match
|
|
and def.wild_doesnt_match[m[reel+1]])) then
|
|
matchwin = false
|
|
break
|
|
end
|
|
if spin[row][reel][2] == "wild" then wc = wc + 1 end
|
|
else
|
|
local sublistmatch = false
|
|
for e in ipairs(m[reel+1]) do
|
|
paylinecontent[payline][reel] = spin[row][reel][2]
|
|
if spin[row][reel][2] == m[reel+1][e]
|
|
or (spin[row][reel][2] == "wild"
|
|
and not (def.wild_doesnt_match
|
|
and def.wild_doesnt_match[m[reel+1][e]])) then
|
|
sublistmatch = true
|
|
end
|
|
end
|
|
if not sublistmatch then
|
|
matchwin = false
|
|
break
|
|
end
|
|
if spin[row][reel][2] == "wild" then wc = wc + 1 end
|
|
end
|
|
end
|
|
|
|
if matchwin then
|
|
wildcount = wc
|
|
highestwin = m[1]
|
|
end
|
|
end
|
|
if highestwin then
|
|
if wildcount > 0 then highestwin = highestwin * wildcount * def.wild_multiplier end
|
|
table.insert(allwins, { payline = payline, value = highestwin, symbols = paylinecontent[payline]})
|
|
end
|
|
end
|
|
|
|
for row = 1, 3 do
|
|
for reel = 1, def.constants.numreels do
|
|
if spin[row][reel][2] == "scatter" then
|
|
allwins.scatter.count = allwins.scatter.count + 1
|
|
table.insert(allwins.scatter.pos, { reel, row } )
|
|
elseif spin[row][reel][2] == "bonus" then
|
|
allwins.bonus.count = allwins.bonus.count + 1
|
|
table.insert(allwins.bonus.pos, { reel, row } )
|
|
end
|
|
end
|
|
end
|
|
|
|
if #allwins > 0 then
|
|
for _, win in ipairs(allwins) do
|
|
allwins.line_wins_total = allwins.line_wins_total + win.value
|
|
end
|
|
end
|
|
|
|
return allwins
|
|
end
|
|
|
|
local horizscale = 0.805 -- scaling to apply to any position values that need it (will be most)
|
|
local vertscale = 0.867
|
|
local hanchor = 0.23 -- the position of (0,0) relative to the upper-left formspec corner
|
|
local vanchor = 0.24
|
|
local pix2iu = 0.0175
|
|
local spincouthelp_scalex = 0.8455
|
|
local spincouthelp_scaley = 1.0241
|
|
|
|
function minislots.register_machine(mdef)
|
|
local mdef_copy = table.copy(mdef)
|
|
mdef_copy.constants = {}
|
|
|
|
if string.sub(mtver.string, 1, 4) == "5.0." then
|
|
print("[Minislots] 5.0.x engine detected, Adjusting display to compensate.")
|
|
horizscale = 0.800
|
|
end
|
|
|
|
mdef_copy.constants.cashout_screen_ctrx = (mdef_copy.geometry.base_user_interface_width/2)*horizscale - hanchor
|
|
mdef_copy.constants.cashoutticketimg_posx = (mdef_copy.geometry.base_user_interface_width/2 - 4)*horizscale - hanchor
|
|
|
|
mdef_copy.constants.form_header = "size["..(mdef_copy.geometry.base_user_interface_width*0.785)..","..
|
|
((mdef_copy.geometry.upper_section_height+mdef_copy.geometry.lower_section_height)*0.823).."]"
|
|
mdef_copy.constants.mainpref = "image[-"..hanchor..",-"..vanchor..";"..
|
|
mdef_copy.geometry.base_user_interface_width..","..mdef_copy.geometry.upper_section_height..";"
|
|
mdef_copy.constants.screenposx = mdef_copy.geometry.screen_posx * horizscale - hanchor
|
|
mdef_copy.constants.screenposy = mdef_copy.geometry.screen_posy * vertscale - vanchor
|
|
mdef_copy.constants.lscrnpref = "image["..mdef_copy.constants.screenposx
|
|
|
|
mdef_copy.constants.lscrnypos1 = ","..(mdef_copy.constants.screenposy)..";"
|
|
mdef_copy.constants.lscrnypos2 = ","..(mdef_copy.constants.screenposy + mdef_copy.geometry.screen_line_height * vertscale)..";"
|
|
|
|
mdef_copy.constants.cslotposx = mdef_copy.geometry.cash_slot_posx * horizscale - hanchor
|
|
mdef_copy.constants.cslotposy = mdef_copy.geometry.cash_slot_posy * vertscale - vanchor
|
|
mdef_copy.constants.cslotbtnszx = mdef_copy.geometry.cash_slot_sizex * spincouthelp_scalex
|
|
mdef_copy.constants.cslotbtnszy = mdef_copy.geometry.cash_slot_sizey * spincouthelp_scaley
|
|
|
|
mdef_copy.constants.spincoutposx = mdef_copy.geometry.spin_cashout_posx * horizscale - hanchor
|
|
mdef_copy.constants.spinposy = mdef_copy.geometry.button_rows_posy * vertscale - vanchor
|
|
mdef_copy.constants.coutposy = (mdef_copy.geometry.button_rows_posy
|
|
+ mdef_copy.geometry.main_button_spacing) * vertscale - vanchor
|
|
mdef_copy.constants.spincoutsizex = mdef_copy.geometry.main_button_size*2
|
|
mdef_copy.constants.spincoutsizey = mdef_copy.geometry.main_button_size
|
|
mdef_copy.constants.spincoutbtnszx = mdef_copy.constants.spincoutsizex * 0.91
|
|
mdef_copy.constants.spincoutbtnszy = mdef_copy.constants.spincoutsizey * 1.05
|
|
|
|
mdef_copy.constants.helpposx = mdef_copy.geometry.button_help_posx * horizscale - hanchor
|
|
mdef_copy.constants.helpposy = mdef_copy.geometry.button_help_posy * vertscale - vanchor
|
|
mdef_copy.constants.helpbtnsizex = mdef_copy.geometry.button_help_sizex * spincouthelp_scalex
|
|
mdef_copy.constants.helpbtnposy = mdef_copy.geometry.button_help_sizey * spincouthelp_scaley
|
|
|
|
mdef_copy.constants.reelspc = mdef_copy.geometry.reel_sizex*1.3333
|
|
mdef_copy.constants.highlightboxszx = mdef_copy.geometry.reel_sizex*1.3333
|
|
mdef_copy.constants.highlightboxszy = mdef_copy.geometry.reel_sizey/3*1.3333
|
|
mdef_copy.constants.highlightboxoffsx = 1-(mdef_copy.geometry.reel_sizex/6)
|
|
mdef_copy.constants.highlightboxoffsy = 1-(mdef_copy.geometry.reel_sizey/18)
|
|
|
|
mdef_copy.constants.screenlnht2 = mdef_copy.geometry.screen_line_height * 0.6667
|
|
mdef_copy.constants.screenlnht3 = mdef_copy.geometry.screen_line_height * 0.3333
|
|
mdef_copy.constants.digitmed = mdef_copy.geometry.digit_glyph_sizex * 0.45
|
|
mdef_copy.constants.digitsm = mdef_copy.geometry.digit_glyph_sizex * 0.4
|
|
mdef_copy.constants.lscrnypos3 = ","..(mdef_copy.constants.screenposy + (mdef_copy.geometry.screen_line_height + mdef_copy.constants.screenlnht2) * vertscale)..";"
|
|
mdef_copy.constants.medlblsz1 = mdef_copy.geometry.label_medium_sizex..","..mdef_copy.geometry.screen_line_height..";"
|
|
mdef_copy.constants.medlblsz2 = mdef_copy.geometry.label_medium_sizex..","..mdef_copy.constants.screenlnht2..";"
|
|
mdef_copy.constants.posy3 = mdef_copy.constants.screenposy + (mdef_copy.geometry.screen_line_height + mdef_copy.constants.screenlnht2) * vertscale
|
|
mdef_copy.constants.lnwinlblsz = mdef_copy.geometry.line_win_label_sizex..","..mdef_copy.constants.screenlnht3..";"
|
|
mdef_copy.constants.parensize = mdef_copy.geometry.digit_glyph_sizex/4
|
|
mdef_copy.constants.parenlblsz = mdef_copy.constants.parensize..","..mdef_copy.constants.screenlnht3..";"
|
|
mdef_copy.constants.ln3dig = mdef_copy.geometry.digit_glyph_sizex/4
|
|
|
|
mdef_copy.constants.numreels = #mdef_copy.lines[1]
|
|
mdef_copy.constants.numsymbols = #mdef_copy.symbols
|
|
mdef_copy.symbols[#mdef_copy.symbols+1] = mdef_copy.symbols[1]
|
|
mdef_copy.symbols[0] = mdef_copy.symbols[mdef_copy.constants.numsymbols]
|
|
|
|
mdef_copy.constants.fast_med_cutover = mdef_copy.cutover_frames*2
|
|
mdef_copy.constants.med_slow_cutover = mdef_copy.constants.fast_med_cutover + mdef_copy.cutover_frames*2
|
|
mdef_copy.constants.slow_stop_cutover = mdef_copy.constants.med_slow_cutover + mdef_copy.cutover_frames*2
|
|
mdef_copy.constants.last_step = mdef_copy.inter_reel_steps * (mdef_copy.constants.numreels-1) + mdef_copy.constants.slow_stop_cutover
|
|
mdef_copy.constants.reel_wraparound_buf = mdef_copy.constants.numsymbols*10
|
|
|
|
mdef_copy.constants.basename = "minislots_"..mdef_copy.name.."_"
|
|
|
|
mdef_copy.constants.emptyimg = "minislots_empty_img.png"
|
|
|
|
mdef_copy.constants.reelimg = mdef_copy.constants.basename.."reel_background.png"
|
|
mdef_copy.constants.reelshadowimg = ":0,0="..mdef_copy.constants.basename.."reel_shadow.png]"
|
|
mdef_copy.constants.scatterhlimg = mdef_copy.constants.highlightboxszx..","..mdef_copy.constants.highlightboxszy..";"..
|
|
mdef_copy.constants.basename.."highlight_scatter.png]"
|
|
mdef_copy.constants.bonushlimg = mdef_copy.constants.highlightboxszx..","..mdef_copy.constants.highlightboxszy..";"..
|
|
mdef_copy.constants.basename.."highlight_bonus.png]"
|
|
mdef_copy.constants.cashslotscrnbg = mdef_copy.constants.basename.."cash_slot_screen_background.png"
|
|
mdef_copy.constants.paytablescrnbg = mdef_copy.constants.basename.."paytable_bg.png"
|
|
mdef_copy.constants.paylinescrnbg = mdef_copy.constants.basename.."payline_bg.png"
|
|
mdef_copy.constants.lines_bg = mdef_copy.constants.basename.."paytable_lines_bg.png"
|
|
|
|
mdef_copy.constants.symbolsfast = mdef_copy.constants.basename.."reel_symbols_fast.png"
|
|
mdef_copy.constants.symbolsmedium = mdef_copy.constants.basename.."reel_symbols_medium.png"
|
|
mdef_copy.constants.symbolsslow = mdef_copy.constants.basename.."reel_symbols_slow.png"
|
|
mdef_copy.constants.symbolsstopped = mdef_copy.constants.basename.."reel_symbols_stopped.png"
|
|
|
|
mdef_copy.constants.ballabelimg = mdef_copy.constants.basename.."label_balance.png]"
|
|
mdef_copy.constants.betlabelimg = mdef_copy.constants.basename.."label_bet.png]"
|
|
mdef_copy.constants.winlabelimg = mdef_copy.constants.basename.."label_win.png]"
|
|
mdef_copy.constants.linewinlabelimg = mdef_copy.constants.basename.."label_linewin.png]"
|
|
mdef_copy.constants.scatterwinlabelimg = mdef_copy.geometry.scatter_win_label_sizex..","..mdef_copy.constants.screenlnht3..";"..mdef_copy.constants.basename.."label_scatterwin.png]"
|
|
mdef_copy.constants.bonuswinlabelimg = mdef_copy.geometry.bonus_win_label_sizex..","..mdef_copy.constants.screenlnht3..";"..mdef_copy.constants.basename.."label_bonuswin.png]"
|
|
mdef_copy.constants.curlabelimg = ";"..mdef_copy.constants.basename.."label_currency.png"
|
|
|
|
mdef_copy.constants.lparenimg = mdef_copy.constants.basename.."glyph_lparen.png]"
|
|
mdef_copy.constants.rparenimg = mdef_copy.constants.basename.."glyph_rparen.png]"
|
|
mdef_copy.constants.colonimg = mdef_copy.constants.basename.."glyph_colon.png]"
|
|
|
|
mdef_copy.constants.lnbetpref = mdef_copy.geometry.main_button_size..","..mdef_copy.geometry.main_button_size..";"
|
|
|
|
mdef_copy.constants.behindreels = mdef_copy.constants.mainpref..mdef_copy.constants.basename.."behind_reels.png]"
|
|
mdef_copy.constants.overlay_upper = mdef_copy.constants.mainpref..mdef_copy.constants.basename.."overlay_upper.png]"
|
|
|
|
mdef_copy.constants.buttonspin = "image["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.spinposy..";"..
|
|
mdef_copy.constants.spincoutsizex..","..mdef_copy.constants.spincoutsizey..";"..
|
|
mdef_copy.constants.basename.."button_spin.png]"..
|
|
"image_button["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.spinposy..
|
|
";"..mdef_copy.constants.spincoutbtnszx..","..mdef_copy.constants.spincoutbtnszy..";"..
|
|
mdef_copy.constants.emptyimg..";spin;]"
|
|
mdef_copy.constants.buttonspin_dis = "image["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.spinposy..";"..
|
|
mdef_copy.constants.spincoutsizex..","..mdef_copy.constants.spincoutsizey..";"..
|
|
mdef_copy.constants.basename.."button_spin_dis.png]"
|
|
|
|
mdef_copy.constants.buttoncashout = "image["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.spincoutsizex..","..mdef_copy.constants.spincoutsizey..";"..
|
|
mdef_copy.constants.basename.."button_cash_out.png]"..
|
|
"image_button["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.spincoutbtnszx..","..mdef_copy.constants.spincoutbtnszy..";"..
|
|
mdef_copy.constants.emptyimg..";cout;]"
|
|
mdef_copy.constants.buttoncashout_dis = "image["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.spincoutsizex..","..mdef_copy.constants.spincoutsizey..";"..
|
|
mdef_copy.constants.basename.."button_cash_out_dis.png]"
|
|
|
|
mdef_copy.constants.buttonquit = "image["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.spincoutsizex..","..mdef_copy.constants.spincoutsizey..";"..
|
|
mdef_copy.constants.basename.."button_quit.png]"..
|
|
"image_button_exit["..mdef_copy.constants.spincoutposx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.spincoutbtnszx..","..mdef_copy.constants.spincoutbtnszy..";"..
|
|
mdef_copy.constants.emptyimg..";quit;]"
|
|
|
|
mdef_copy.constants.buttoncashslot = "image["..mdef_copy.constants.cslotposx..","..mdef_copy.constants.cslotposy..";"..
|
|
mdef_copy.geometry.cash_slot_sizex..","..mdef_copy.geometry.cash_slot_sizey..";"..
|
|
mdef_copy.constants.basename.."cash_slot.png]"..
|
|
"image_button["..mdef_copy.constants.cslotposx..","..mdef_copy.constants.cslotposy..";"..
|
|
mdef_copy.constants.cslotbtnszx..","..mdef_copy.constants.cslotbtnszy..";"..
|
|
mdef_copy.constants.emptyimg..";cslot;]"
|
|
|
|
mdef_copy.constants.buttoncashslot_dis = "image["..mdef_copy.constants.cslotposx..","..mdef_copy.constants.cslotposy..";"..
|
|
mdef_copy.geometry.cash_slot_sizex..","..mdef_copy.geometry.cash_slot_sizey..";"..
|
|
mdef_copy.constants.basename.."cash_slot.png]"
|
|
|
|
mdef_copy.constants.button_close = "minislots_close_button.png"
|
|
|
|
mdef_copy.constants.buttonhelp = "image["..mdef_copy.constants.helpposx..","..mdef_copy.constants.helpposy..";"..
|
|
mdef_copy.geometry.button_help_sizex..","..mdef_copy.geometry.button_help_sizey..";"..
|
|
mdef_copy.constants.basename.."button_help.png]"..
|
|
"image_button["..mdef_copy.constants.helpposx..","..mdef_copy.constants.helpposy..";"..
|
|
mdef_copy.constants.helpbtnsizex..","..mdef_copy.constants.helpbtnposy..";"..
|
|
mdef_copy.constants.emptyimg..";help;]"
|
|
|
|
mdef_copy.constants.buttonhelp_dis = "image["..mdef_copy.constants.helpposx..","..mdef_copy.constants.helpposy..";"..
|
|
mdef_copy.geometry.button_help_sizex..","..mdef_copy.geometry.button_help_sizey..";"..
|
|
mdef_copy.constants.basename.."button_help.png]"
|
|
|
|
mdef_copy.constants.reelsymsizex = mdef_copy.geometry.reel_sizex*64
|
|
mdef_copy.constants.reelsymsizey = mdef_copy.geometry.reel_sizey/3*64
|
|
|
|
mdef_copy.constants.reelcombinepref = ","..(mdef_copy.geometry.reel_posy*vertscale-vanchor)..";"..
|
|
(mdef_copy.geometry.reel_sizex)..","..(mdef_copy.geometry.reel_sizey)..";"..
|
|
mdef_copy.constants.reelimg..
|
|
"^[combine:"..mdef_copy.constants.reelsymsizex.."x"..
|
|
mdef_copy.constants.reelsymsizey
|
|
|
|
mdef_copy.constants.reelunderlightpref = mdef_copy.constants.basename.."reel_underlight_"
|
|
mdef_copy.constants.overlaylinepref = mdef_copy.constants.basename.."overlay_line_"
|
|
mdef_copy.constants.overlay_lower = "image[-"..hanchor..","..(11*vertscale-vanchor)..";"..
|
|
mdef_copy.geometry.base_user_interface_width..","..mdef_copy.geometry.lower_section_height..";"..
|
|
mdef_copy.constants.basename.."overlay_lower.png]"
|
|
|
|
mdef_copy.constants.upperbezel = mdef_copy.constants.mainpref.."minislots_golden7s_overlay_upper_bezel.png]"
|
|
mdef_copy.constants.cashoutbackground = mdef_copy.constants.mainpref.."minislots_blue_img.png]"
|
|
mdef_copy.constants.cashoutticketimg = "image["..mdef_copy.constants.cashoutticketimg_posx..","..(3.5-vanchor)..
|
|
";8,3;minislots_cashout_ticket.png]"
|
|
|
|
mdef_copy.constants.paylinestable_pref = "image_button[8.85,10.28;2,0.5;"
|
|
mdef_copy.constants.button_showpaytable = mdef_copy.constants.paylinestable_pref..mdef_copy.constants.basename..
|
|
"button_show_paytable.png;showpaytable;]"
|
|
mdef_copy.constants.button_showpaylines = mdef_copy.constants.paylinestable_pref..mdef_copy.constants.basename..
|
|
"button_show_paylines.png;showpaylines;]"
|
|
|
|
mdef_copy.constants.buttonadmin = "image["..
|
|
((mdef_copy.geometry.cash_slot_posx - mdef_copy.constants.cslotbtnszy - 0.02)* horizscale - hanchor)..","..
|
|
(mdef_copy.geometry.cash_slot_posy * vertscale - vanchor)..";"..
|
|
mdef_copy.constants.cslotbtnszy..","..mdef_copy.constants.cslotbtnszy..
|
|
";minislots_button_admin.png]"..
|
|
"image_button["..
|
|
((mdef_copy.geometry.cash_slot_posx - mdef_copy.constants.cslotbtnszy - 0.02)* horizscale - hanchor)..","..
|
|
(mdef_copy.geometry.cash_slot_posy * vertscale - vanchor)..";"..
|
|
mdef_copy.constants.cslotbtnszy..","..mdef_copy.constants.cslotbtnszy..
|
|
";"..mdef_copy.constants.emptyimg..";admin;]"
|
|
|
|
mdef_copy.constants.buttonadmin_dis = "image["..
|
|
((mdef_copy.geometry.cash_slot_posx - mdef_copy.constants.cslotbtnszy - 0.02)* horizscale - hanchor)..","..
|
|
(mdef_copy.geometry.cash_slot_posy * vertscale - vanchor)..";"..
|
|
mdef_copy.constants.cslotbtnszy..","..mdef_copy.constants.cslotbtnszy..
|
|
";minislots_button_admin.png]"
|
|
|
|
|
|
mdef_copy.constants.buttons_n_lines = {}
|
|
mdef_copy.constants.buttons_bet_n = {}
|
|
|
|
for i, value in ipairs(mdef_copy.linebuttons) do
|
|
mdef_copy.constants.buttons_n_lines[value] = {}
|
|
local posx = ((mdef_copy.geometry.button_rows_posx
|
|
+ (i-1)*mdef_copy.geometry.main_button_spacing) * horizscale - hanchor)
|
|
|
|
for _, state in ipairs( {"dis", "off", "on"} ) do
|
|
local btn = "image["..posx..","..mdef_copy.constants.spinposy..";"..
|
|
mdef_copy.constants.lnbetpref..mdef_copy.constants.basename.."button_lines_"..state.."_"..value..".png]"
|
|
if state ~= "dis" then
|
|
btn = btn.."image_button["..posx..","..mdef_copy.constants.spinposy..";"..
|
|
mdef_copy.constants.lnbetpref.."minislots_empty_img.png;lines_"..value..";]"
|
|
end
|
|
mdef_copy.constants.buttons_n_lines[value][state] = btn
|
|
end
|
|
end
|
|
|
|
for i, value in ipairs(mdef_copy.betbuttons) do
|
|
mdef_copy.constants.buttons_bet_n[value] = {}
|
|
|
|
local posx = ((mdef_copy.geometry.button_rows_posx
|
|
+ (i-1)*mdef_copy.geometry.main_button_spacing) * horizscale - hanchor)
|
|
|
|
for _, state in ipairs( {"dis", "off", "on"} ) do
|
|
local btn = "image["..posx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.lnbetpref..mdef_copy.constants.basename.."button_bet_"..state.."_"..value..".png]"
|
|
if state ~= "dis" then
|
|
btn = btn.."image_button["..posx..","..mdef_copy.constants.coutposy..";"..
|
|
mdef_copy.constants.lnbetpref.."minislots_empty_img.png;bet_"..value..";]"
|
|
end
|
|
mdef_copy.constants.buttons_bet_n[value][state] = btn
|
|
end
|
|
end
|
|
|
|
mdef_copy.constants.digits = {}
|
|
for i = 0, 9 do
|
|
mdef_copy.constants.digits[tostring(i)] = mdef_copy.constants.basename.."glyph_digit_"..i..".png"
|
|
end
|
|
|
|
mdef_copy.constants.symlookup = {}
|
|
for num,sym in ipairs(mdef_copy.symbols) do
|
|
mdef_copy.constants.symlookup["sym_"..sym] = num
|
|
end
|
|
|
|
local mesh = ""
|
|
local tiles = {}
|
|
local cbox = {}
|
|
|
|
if mdef_copy.machine_shape == "upright" then
|
|
mesh = "minislots_generic_machine_upright.obj"
|
|
cbox = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
|
|
{-0.5, 0.5, -0.1875, 0.5, 1.5, 0.5 },
|
|
}
|
|
}
|
|
elseif mdef_copy.machine_shape == "upright_big" then
|
|
mesh = "minislots_generic_machine_upright_big.obj"
|
|
cbox = {
|
|
type = "fixed",
|
|
fixed = { -1, -0.5, -0.5, 1.5, 3.5, 1.5 }
|
|
}
|
|
end
|
|
|
|
minetest.register_node(":minislots:"..mdef_copy.name, {
|
|
description = mdef_copy.description,
|
|
drawtype = "mesh",
|
|
mesh = mesh,
|
|
tiles = { "minislots_"..mdef_copy.name.."_cabinet_graphics.png" },
|
|
node_box = cbox, -- this is used to create proper collision info.
|
|
paramtype2 = "facedir",
|
|
selection_box = cbox,
|
|
is_ground_content = false,
|
|
groups = {cracky = 1, level = 2},
|
|
sounds = default.node_sound_metal_defaults(),
|
|
machine_def = table.copy(mdef_copy),
|
|
on_timer = minislots.cycle_states,
|
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos)
|
|
local player_name = clicker:get_player_name()
|
|
local oldform = meta:get_string("formspec")
|
|
local balance = meta:get_int("balance")
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
|
|
minislots.player_last_machine_def[player_name] = def
|
|
minislots.player_last_machine_pos[player_name] = pos
|
|
|
|
if not string.find(oldform, "locked-out") then
|
|
local state = meta:get_string("state")
|
|
if state ~= "stopped" then return end
|
|
local spin = minetest.deserialize(meta:get_string("spin"))
|
|
local linebet = meta:get_int("linebet")
|
|
local maxlines = meta:get_int("maxlines")
|
|
meta:set_string("last_right_clicker", clicker:get_player_name())
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = {},
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
pos = pos,
|
|
admin = default.can_interact_with_node(clicker, pos)
|
|
})
|
|
)
|
|
elseif meta:get_string("owner") == player_name then
|
|
minetest.get_node_timer(pos):stop()
|
|
minetest.show_formspec(player_name, "minislots:admin_form",
|
|
minislots.generate_admin_form(def, pos, balance))
|
|
return
|
|
end
|
|
end,
|
|
on_construct = function(pos)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local meta = minetest.get_meta(pos)
|
|
local resetspin = minislots.reset_reels(def)
|
|
local balance = 0
|
|
local linebet = 1
|
|
local maxlines = 1
|
|
local emptywins = {
|
|
scatter = { count = 0, pos = {} },
|
|
bonus = { value = -1, count = 0, pos = {} }
|
|
}
|
|
meta:set_int("balance", balance)
|
|
meta:set_int("last_cashout", 0)
|
|
meta:set_int("linebet", linebet)
|
|
meta:set_int("maxlines", maxlines)
|
|
meta:set_int("bonus_result", -1)
|
|
meta:set_string("state", "stopped")
|
|
meta:set_string("spin", minetest.serialize(resetspin))
|
|
meta:set_int("spin_timestamp", os.time())
|
|
|
|
meta:set_string("install_date", os.date())
|
|
meta:set_int("spin_count", 0)
|
|
meta:set_int("money_in", 0)
|
|
meta:set_int("money_out", 0)
|
|
meta:set_int("total_bets", 0)
|
|
meta:set_int("total_wins", 0)
|
|
meta:set_int("scatter_hits", 0)
|
|
meta:set_int("bonus_hits", 0)
|
|
|
|
meta:set_string("casino_name", "LocalGames Casino/Hotel")
|
|
|
|
meta:set_string("allwins", minetest.serialize(emptywins))
|
|
meta:mark_as_private({
|
|
"balance",
|
|
"last_cashout",
|
|
"linebet",
|
|
"maxlines",
|
|
"bonus_result",
|
|
"state",
|
|
"spin",
|
|
"spin_timestamp",
|
|
"allwins",
|
|
"casino_name",
|
|
"install_date",
|
|
"spin_count",
|
|
"money_in",
|
|
"money_out",
|
|
"total_bets",
|
|
"total_wins",
|
|
"scatter_hits",
|
|
"bonus_hits"
|
|
})
|
|
|
|
local inv = meta:get_inventory()
|
|
inv:set_size("main", 1)
|
|
end,
|
|
on_dig = function(pos, node, digger)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local player_name = digger:get_player_name()
|
|
if default.can_interact_with_node(digger, pos) then
|
|
local stack = ItemStack("minislots:"..def.name)
|
|
local nodemeta = minetest.get_meta(pos)
|
|
local stackmeta = stack:get_meta()
|
|
|
|
local balance = nodemeta:get_int("balance") or 0
|
|
local casino = nodemeta:get_string("casino_name")
|
|
stackmeta:set_int("balance", balance)
|
|
stackmeta:set_string("casino_name", casino)
|
|
stackmeta:set_int("last_cashout", nodemeta:get_int("last_cashout") )
|
|
stackmeta:set_string("install_date", nodemeta:get_string("install_date") )
|
|
stackmeta:set_int("spin_count", nodemeta:get_int("spin_count") )
|
|
stackmeta:set_int("money_in", nodemeta:get_int("money_in") )
|
|
stackmeta:set_int("money_out", nodemeta:get_int("money_out") )
|
|
stackmeta:set_int("total_bets", nodemeta:get_int("total_bets") )
|
|
stackmeta:set_int("total_wins", nodemeta:get_int("total_wins") )
|
|
stackmeta:set_int("scatter_hits", nodemeta:get_int("scatter_hits") )
|
|
stackmeta:set_int("bonus_hits", nodemeta:get_int("bonus_hits") )
|
|
stackmeta:set_string("description",
|
|
def.description.."\n(balance: "..balance.." Mg;\ncasino: "..casino..")")
|
|
local inv = digger:get_inventory()
|
|
if inv:room_for_item("main", stack) then
|
|
if (not creative or not creative.is_enabled_for(player_name))
|
|
or (creative and creative.is_enabled_for(player_name)
|
|
and not inv:contains_item("main", stack, true)) then
|
|
inv:add_item("main", stack)
|
|
end
|
|
minetest.remove_node(pos)
|
|
end
|
|
end
|
|
end,
|
|
after_place_node = function(pos, placer, itemstack)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local nodemeta = minetest.get_meta(pos)
|
|
local player_name = placer:get_player_name()
|
|
local stackmeta = itemstack:get_meta()
|
|
|
|
local balance = 0
|
|
local resetspin = minislots.reset_reels(def)
|
|
local linebet = 1
|
|
local maxlines = 1
|
|
local emptywins = {
|
|
scatter = { count = 0, pos = {} },
|
|
bonus = { value = -1, count = 0, pos = {} }
|
|
}
|
|
local casino = stackmeta:get_string("casino_name")
|
|
|
|
if stackmeta then
|
|
balance = stackmeta:get_int("balance")
|
|
nodemeta:set_int("balance", balance)
|
|
|
|
if casino ~= "" then
|
|
nodemeta:set_string("casino_name", casino)
|
|
end
|
|
nodemeta:set_int("last_cashout", stackmeta:get_int("last_cashout"))
|
|
nodemeta:set_int("spin_count", stackmeta:get_int("spin_count") )
|
|
nodemeta:set_int("money_in", stackmeta:get_int("money_in") )
|
|
nodemeta:set_int("money_out", stackmeta:get_int("money_out") )
|
|
nodemeta:set_int("total_bets", stackmeta:get_int("total_bets") )
|
|
nodemeta:set_int("total_wins", stackmeta:get_int("total_wins") )
|
|
nodemeta:set_int("scatter_hits", stackmeta:get_int("scatter_hits"))
|
|
nodemeta:set_int("bonus_hits", stackmeta:get_int("bonus_hits") )
|
|
end
|
|
nodemeta:set_string("owner", player_name)
|
|
nodemeta:set_string("infotext", def.description.."\nOwned by "..player_name)
|
|
nodemeta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = "stopped",
|
|
spin = resetspin,
|
|
allwins = emptywins,
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
admin = default.can_interact_with_node(placer, pos)
|
|
})
|
|
)
|
|
end,
|
|
can_dig = function(pos, player)
|
|
return default.can_interact_with_node(player, pos)
|
|
end,
|
|
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local player_name = player:get_player_name()
|
|
local meta = minetest.get_meta(pos)
|
|
local state = meta:get_string("state")
|
|
local spin = minetest.deserialize(meta:get_string("spin"))
|
|
local balance = meta:get_int("balance")
|
|
local linebet = meta:get_int("linebet")
|
|
local maxlines = meta:get_int("maxlines")
|
|
local timer = minetest.get_node_timer(pos)
|
|
local last_cashout = nil
|
|
timer:stop()
|
|
local inv = meta:get_inventory()
|
|
inv:remove_item("main", stack)
|
|
local state = "stopped"
|
|
meta:set_string("state", state)
|
|
meta:set_int("last_cashout", balance)
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = {},
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
last_cashout = last_cashout,
|
|
admin = default.can_interact_with_node(player, pos)
|
|
})
|
|
)
|
|
minetest.show_formspec(player_name, "minislots:cash_intake",
|
|
minislots.generate_cashslot_form(def, pos, balance))
|
|
end,
|
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local meta = minetest.get_meta(pos)
|
|
local inv = meta:get_inventory()
|
|
local sn = stack:get_name()
|
|
local mg
|
|
if string.find(sn, "currency:minegeld") and not string.find(sn, "bundle") then
|
|
if not string.find(sn, "cent") then
|
|
mg = tonumber(string.sub(sn, 19))
|
|
if not mg then mg = 1 end
|
|
else
|
|
mg = tonumber(string.sub(sn, 24)) / 100
|
|
end
|
|
if mg < def.currency_min or mg > def.currency_max then return 0 end
|
|
local balance = meta:get_int("balance")
|
|
if balance < (def.maxbalance - mg*stack:get_count()) then
|
|
local amount = mg*stack:get_count()
|
|
balance = balance + amount
|
|
meta:set_int("balance", balance)
|
|
meta:set_int("money_in", meta:get_int("money_in")+amount)
|
|
return -1
|
|
end
|
|
end
|
|
return 0
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local player_name = sender:get_player_name()
|
|
local meta = minetest.get_meta(pos)
|
|
local state = meta:get_string("state")
|
|
local spin = minetest.deserialize(meta:get_string("spin"))
|
|
local balance = meta:get_int("balance")
|
|
local linebet = meta:get_int("linebet")
|
|
local maxlines = meta:get_int("maxlines")
|
|
local timer = minetest.get_node_timer(pos)
|
|
timer:stop()
|
|
|
|
local allfields = minetest.serialize(fields)
|
|
if fields.admin then
|
|
if player_name == meta:get_string("owner") then
|
|
minetest.get_node_timer(pos):stop()
|
|
meta:set_string("formspec", "size[4,1]"..
|
|
"image_button_exit[3.65,-0.2;0.55,0.5;"..def.constants.button_close..";close;]"..
|
|
"label[0.3,0.2;This machine has been locked-out by]"..
|
|
"label[0.1,0.5;the Administrator. Please come back later.]")
|
|
minetest.show_formspec(player_name, "minislots:admin_form",
|
|
minislots.generate_admin_form(def, pos, balance))
|
|
return
|
|
end
|
|
elseif fields.cslot then
|
|
local meta = minetest.get_meta(pos)
|
|
local balance = meta:get_int("balance")
|
|
local player_name = sender:get_player_name()
|
|
minetest.show_formspec(player_name, "minislots:cash_intake",
|
|
minislots.generate_cashslot_form(def, pos, balance))
|
|
return
|
|
elseif fields.help then
|
|
local meta = minetest.get_meta(pos)
|
|
local balance = meta:get_int("balance")
|
|
local player_name = sender:get_player_name()
|
|
minetest.show_formspec(player_name, "minislots:help_screen",
|
|
minislots.generate_paytable_form(def))
|
|
return
|
|
elseif fields.cout then
|
|
if balance > 0 and balance <= def.maxbalance then
|
|
local state = "stopped"
|
|
local last_cashout = balance
|
|
local casino_name = meta:get_string("casino_name")
|
|
balance = 0
|
|
meta:set_string("state", state)
|
|
meta:set_int("last_cashout", balance)
|
|
meta:set_int("balance", balance)
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = {},
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
last_cashout = last_cashout,
|
|
pos = pos,
|
|
casino_name = casino_name,
|
|
admin = default.can_interact_with_node(sender, pos)
|
|
})
|
|
)
|
|
local fifties = math.floor(last_cashout/50)
|
|
local tens = math.floor((last_cashout - fifties*50)/10)
|
|
local fives = math.floor((last_cashout - fifties*50 - tens*10)/5)
|
|
local ones = math.floor(last_cashout - fifties*50 - tens*10 - fives*5)
|
|
local inv = sender:get_inventory()
|
|
if (fifties == 0 or inv:room_for_item("main", "currency:minegeld_50 "..fifties))
|
|
and (tens == 0 or inv:room_for_item("main", "currency:minegeld_10 "..tens))
|
|
and (fives == 0 or inv:room_for_item("main", "currency:minegeld_5 "..fives))
|
|
and (ones == 0 or inv:room_for_item("main", "currency:minegeld "..ones)) then
|
|
|
|
if fifties > 0 then inv:add_item("main", "currency:minegeld_50 "..fifties) end
|
|
if tens > 0 then inv:add_item("main", "currency:minegeld_10 "..tens) end
|
|
if fives > 0 then inv:add_item("main", "currency:minegeld_5 "..fives) end
|
|
if ones > 0 then inv:add_item("main", "currency:minegeld "..ones) end
|
|
meta:set_int("money_out", meta:get_int("money_out")+last_cashout)
|
|
end
|
|
return
|
|
end
|
|
elseif fields.quit then
|
|
local allwins = minislots.check_win(spin, def, maxlines)
|
|
meta:set_string("allwins", minetest.serialize(allwins))
|
|
local state = "stopped"
|
|
meta:set_string("state", state)
|
|
local oldform = meta:get_string("formspec")
|
|
if not string.find(oldform, "locked-out") then
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = {},
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
admin = default.can_interact_with_node(sender, pos)
|
|
})
|
|
)
|
|
end
|
|
return
|
|
elseif fields.spin then
|
|
if state == "stopped" or string.find(state, "win") then
|
|
if (linebet*maxlines) > balance or balance > def.maxbalance then return end
|
|
meta:set_int("spin_timestamp", os.time())
|
|
local node = minetest.get_node(pos)
|
|
local spin = minislots.spin_reels(def)
|
|
local allwins = minislots.check_win(spin, def, maxlines)
|
|
meta:set_string("spin", minetest.serialize(spin))
|
|
meta:set_string("allwins", minetest.serialize(allwins))
|
|
meta:set_string("state", "start")
|
|
minislots.cycle_states(pos)
|
|
return
|
|
end
|
|
elseif string.find(allfields, "bet_") then
|
|
local s1 = string.sub(allfields, 15)
|
|
local s2 = string.find(s1, '"')
|
|
local linebet = tonumber(string.sub(s1, 1, s2-1)) or 1
|
|
if def.bet_initiates_spin then
|
|
if maxlines*linebet > balance or balance > def.maxbalance then return end
|
|
meta:set_int("linebet", linebet)
|
|
local node = minetest.get_node(pos)
|
|
local spin = minislots.spin_reels(def)
|
|
local allwins = minislots.check_win(spin, def, maxlines)
|
|
meta:set_string("spin", minetest.serialize(spin))
|
|
meta:set_string("allwins", minetest.serialize(allwins))
|
|
meta:set_string("state", "start")
|
|
minislots.cycle_states(pos)
|
|
return
|
|
else
|
|
if maxlines*linebet <= balance then
|
|
local state = "stopped"
|
|
meta:set_string("state", state)
|
|
meta:set_int("linebet", linebet)
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = {},
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
showlines = true,
|
|
admin = default.can_interact_with_node(sender, pos)
|
|
})
|
|
)
|
|
end
|
|
end
|
|
elseif string.find(allfields, "lines_") then
|
|
local s1 = string.sub(allfields, 17)
|
|
local s2 = string.find(s1, '"')
|
|
local maxlines = tonumber(string.sub(s1, 1, s2-1)) or 1
|
|
if maxlines*linebet <= balance then
|
|
local state = "stopped"
|
|
meta:set_string("state", state)
|
|
meta:set_int("maxlines", maxlines)
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = {},
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
showlines = true,
|
|
admin = default.can_interact_with_node(sender, pos)
|
|
})
|
|
)
|
|
end
|
|
end
|
|
end
|
|
})
|
|
end
|
|
|
|
|
|
--###################
|
|
-- the state machine
|
|
--###################
|
|
|
|
function minislots.cycle_states(pos)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name].machine_def
|
|
local meta = minetest.get_meta(pos)
|
|
local state = meta:get_string("state")
|
|
local spin = minetest.deserialize(meta:get_string("spin"))
|
|
local linebet = meta:get_int("linebet")
|
|
local maxlines = meta:get_int("maxlines")
|
|
local balance = meta:get_int("balance")
|
|
local allwins = minetest.deserialize(meta:get_string("allwins"))
|
|
local numscatter = (allwins and allwins.scatter and allwins.scatter.count) or 0
|
|
local numbonus = (allwins and allwins.bonus and allwins.bonus.count) or 0
|
|
local last_right_clicker = meta:get_string("last_right_clicker")
|
|
local player = minetest.get_player_by_name(last_right_clicker)
|
|
local admin = player and default.can_interact_with_node(player, pos)
|
|
|
|
local timeout = 0
|
|
|
|
if state == "start" then
|
|
balance = meta:get_int("balance") - linebet*maxlines
|
|
meta:set_int("balance", balance)
|
|
meta:set_int("spin_count", meta:get_int("spin_count")+1)
|
|
meta:set_int("total_bets", meta:get_int("total_bets")+linebet*maxlines)
|
|
state = "spinning_fast_0"
|
|
timeout = def.reel_fast_timeout
|
|
elseif string.find(state, "spinning_fast_") then
|
|
local c = tonumber(string.sub(state, 15))
|
|
c = c + 2
|
|
if c >= def.constants.fast_med_cutover then
|
|
state = "spinning_medm_"..def.constants.fast_med_cutover
|
|
timeout = def.reel_medium_timeout
|
|
else
|
|
state = "spinning_fast_"..c
|
|
timeout = def.reel_fast_timeout
|
|
end
|
|
elseif string.find(state, "spinning_medm_") then
|
|
local c = tonumber(string.sub(state, 15))
|
|
c = c + 2
|
|
if c >= def.constants.med_slow_cutover then
|
|
state = "spinning_slow_"..def.constants.med_slow_cutover
|
|
timeout = def.reel_slow_timeout
|
|
else
|
|
state = "spinning_medm_"..c
|
|
timeout = def.reel_medium_timeout
|
|
end
|
|
elseif string.find(state, "spinning_slow_") then
|
|
local c = tonumber(string.sub(state, 15))
|
|
c = c + 2
|
|
if c >= def.constants.slow_stop_cutover then
|
|
state = "reels_stopping_"..def.constants.slow_stop_cutover
|
|
timeout = def.reel_slow_timeout
|
|
else
|
|
state = "spinning_slow_"..c
|
|
timeout = def.reel_slow_timeout
|
|
end
|
|
elseif string.find(state, "reels_stopping_") then
|
|
local sr = tonumber(string.sub(state, 16))
|
|
sr = sr + 1
|
|
if sr <= def.constants.last_step then
|
|
state = "reels_stopping_"..sr
|
|
timeout = def.reel_slow_timeout
|
|
else
|
|
if numscatter >= def.min_scatter or numbonus >= def.min_bonus then
|
|
state = "stopped"
|
|
timeout = 0.1
|
|
else
|
|
state = "stopped"
|
|
timeout = def.win_delay
|
|
end
|
|
end
|
|
elseif state == "stopped" then
|
|
if #allwins > 0 then
|
|
local amount = allwins.line_wins_total*linebet
|
|
balance = balance + amount
|
|
allwins.total = allwins.total + amount
|
|
meta:set_int("total_wins", meta:get_int("total_wins")+amount)
|
|
end
|
|
if numscatter >= def.min_scatter then
|
|
local amount = allwins.scatter.count*def.scatter_value*linebet
|
|
balance = balance + amount
|
|
allwins.total = allwins.total + amount
|
|
meta:set_int("scatter_hits", meta:get_int("scatter_hits")+1)
|
|
meta:set_int("total_wins", meta:get_int("total_wins")+amount)
|
|
end
|
|
if numbonus >= def.min_bonus and allwins.bonus.value < 0 then
|
|
allwins.bonus.value = def.initiate_bonus(spin, def)
|
|
balance = balance + allwins.bonus.value
|
|
allwins.total = allwins.total + allwins.bonus.value
|
|
meta:set_int("bonus_hits", meta:get_int("bonus_hits")+1)
|
|
meta:set_int("total_wins", meta:get_int("total_wins")+allwins.bonus.value)
|
|
end
|
|
meta:set_string("allwins", minetest.serialize(allwins))
|
|
meta:set_int("balance", balance)
|
|
if numbonus >= def.min_bonus then
|
|
state = "bonus_win"
|
|
timeout = def.line_timeout
|
|
elseif numscatter >= def.min_scatter then
|
|
state = "scatter_win"
|
|
timeout = def.line_timeout
|
|
elseif #allwins > 0 then
|
|
state = "win_1"
|
|
timeout = def.line_timeout
|
|
end
|
|
elseif state == "bonus_win" then
|
|
if numscatter >= def.min_scatter then
|
|
state = "scatter_win"
|
|
timeout = def.line_timeout
|
|
elseif #allwins > 0 then
|
|
state = "win_1"
|
|
timeout = def.line_timeout
|
|
end
|
|
elseif state == "scatter_win" then
|
|
if #allwins > 0 then
|
|
state = "win_1"
|
|
timeout = def.line_timeout
|
|
end
|
|
elseif string.find(state, "win_") then
|
|
local w = tonumber(string.sub(state, 5)) + 1
|
|
if w > #allwins then
|
|
if numbonus >= def.min_bonus then
|
|
state = "bonus_win"
|
|
timeout = def.line_timeout
|
|
elseif numscatter >= def.min_scatter then
|
|
state = "scatter_win"
|
|
timeout = def.line_timeout
|
|
else
|
|
state = "win_1"
|
|
if #allwins > 1 then
|
|
timeout = def.line_timeout
|
|
end
|
|
end
|
|
else
|
|
state = "win_"..w
|
|
timeout = def.line_timeout
|
|
end
|
|
end
|
|
|
|
if meta:get_int("spin_timestamp") < (os.time() - 60) then
|
|
minetest.get_node_timer(pos):stop()
|
|
state = "stopped"
|
|
meta:set_string("state", state)
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = allwins,
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
admin = admin
|
|
})
|
|
)
|
|
return
|
|
end
|
|
|
|
meta:set_string("state", state)
|
|
meta:set_string("formspec",
|
|
minislots.generate_display(def, {
|
|
state = state,
|
|
spin = spin,
|
|
allwins = allwins,
|
|
balance = balance,
|
|
linebet = linebet,
|
|
maxlines = maxlines,
|
|
admin = admin
|
|
})
|
|
)
|
|
if timeout > 0 then
|
|
local timer = minetest.get_node_timer(pos)
|
|
timer:start(timeout)
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
--####################
|
|
-- the display engine
|
|
--####################
|
|
|
|
local function calcrp(def, spin, i, statenum)
|
|
local rp = (
|
|
spin[2][i+1][1]*2-2
|
|
+ statenum
|
|
+ def.constants.reel_wraparound_buf
|
|
- def.constants.last_step
|
|
+ (def.constants.numreels-i-1)*def.inter_reel_steps
|
|
) % (def.constants.numsymbols * 2)
|
|
return rp/2
|
|
end
|
|
|
|
function minislots.generate_display(def, options)
|
|
local state = options.state
|
|
local spin = options.spin
|
|
local allwins = options.allwins
|
|
local balance = options.balance
|
|
local linebet = options.linebet
|
|
local maxlines = options.maxlines
|
|
local showlines = options.showlines
|
|
local last_cashout = options.last_cashout
|
|
local pos = options.pos
|
|
local casino_name = options.casino_name
|
|
local admin = options.admin
|
|
|
|
local reels = ""
|
|
local lines = ""
|
|
local scatters = ""
|
|
local bonuses = ""
|
|
local underlights = {}
|
|
local spinbutton = ""
|
|
local cashoutbutton = ""
|
|
|
|
for i = 1, def.constants.numreels do underlights[i] = "" end
|
|
|
|
if state == "scatter_win" and allwins.scatter.count > 0 then
|
|
for reel = 1, def.constants.numreels do
|
|
local t = {}
|
|
for row = 0, 2 do
|
|
if spin[row+1][reel][2] == "scatter" then
|
|
t[#t+1] = ":0,"..(row*def.constants.reelsymsizey).."="
|
|
..def.constants.reelunderlightpref..(row+1)..".png"
|
|
end
|
|
end
|
|
if #t > 0 then
|
|
underlights[reel] = table.concat(t, ":")
|
|
end
|
|
end
|
|
elseif state == "bonus_win" and allwins.bonus.count > 0 then
|
|
for reel = 1, def.constants.numreels do
|
|
local t = {}
|
|
for row = 0, 2 do
|
|
if spin[row+1][reel][2] == "bonus" then
|
|
t[#t+1] = ":0,"..(row*def.constants.reelsymsizey).."="
|
|
..def.constants.reelunderlightpref..(row+1)..".png"
|
|
end
|
|
end
|
|
if #t > 0 then
|
|
underlights[reel] = table.concat(t, ":")
|
|
end
|
|
end
|
|
end
|
|
|
|
local statenum = tonumber(string.sub(state, (string.find(state, "stopping") and 16 or 15)))
|
|
if string.find(state, "spinning_fast_") then
|
|
local t = {}
|
|
for i = 0, def.constants.numreels-1 do
|
|
local rs = calcrp(def, spin, i, statenum) * -def.constants.reelsymsizey
|
|
t[i+1] = "image["..((i*def.constants.reelspc+def.geometry.reel_posx)*horizscale-hanchor)..
|
|
def.constants.reelcombinepref..
|
|
":0,"..rs.."="..def.constants.symbolsfast..
|
|
def.constants.reelshadowimg
|
|
end
|
|
reels = table.concat(t)
|
|
elseif string.find(state, "spinning_medm_") then
|
|
local t = {}
|
|
for i = 0, def.constants.numreels-1 do
|
|
local rs = calcrp(def, spin, i, statenum) * -def.constants.reelsymsizey
|
|
t[i+1] = "image["..((i*def.constants.reelspc+def.geometry.reel_posx)*horizscale-hanchor)..
|
|
def.constants.reelcombinepref..
|
|
":0,"..rs.."="..def.constants.symbolsmedium..
|
|
def.constants.reelshadowimg
|
|
end
|
|
reels = table.concat(t)
|
|
elseif string.find(state, "spinning_slow_") then
|
|
local t = {}
|
|
for i = 0, def.constants.numreels-1 do
|
|
local rs = calcrp(def, spin, i, statenum) * -def.constants.reelsymsizey
|
|
t[i+1] = "image["..((i*def.constants.reelspc+def.geometry.reel_posx)*horizscale-hanchor)..
|
|
def.constants.reelcombinepref..
|
|
":0,"..rs.."="..def.constants.symbolsslow..
|
|
def.constants.reelshadowimg
|
|
end
|
|
reels = table.concat(t)
|
|
elseif string.find(state, "reels_stopping_") then
|
|
local t = {}
|
|
for i = 0, def.constants.numreels-1 do
|
|
if i > ((statenum-def.constants.slow_stop_cutover-1)/def.inter_reel_steps) then
|
|
local rs = calcrp(def, spin, i, statenum) * -def.constants.reelsymsizey
|
|
t[i+1] = "image["..((i*def.constants.reelspc+def.geometry.reel_posx)*horizscale-hanchor)..
|
|
def.constants.reelcombinepref..
|
|
":0,"..rs.."="..def.constants.symbolsslow..
|
|
def.constants.reelshadowimg
|
|
else
|
|
local rs = (spin[2][i+1][1]-1) * -def.constants.reelsymsizey
|
|
t[i+1] = "image["..((i*def.constants.reelspc+def.geometry.reel_posx)*horizscale-hanchor)..
|
|
def.constants.reelcombinepref..
|
|
underlights[i+1]..":0,"..rs.."="..def.constants.symbolsstopped..
|
|
def.constants.reelshadowimg
|
|
end
|
|
end
|
|
reels = table.concat(t)
|
|
elseif state == "stopped" or state == "start" or string.find(state, "win") then
|
|
local t = {}
|
|
for i = 0, def.constants.numreels-1 do
|
|
local rs = (spin[2][i+1][1]-1) * -def.constants.reelsymsizey
|
|
t[i+1] = "image["..((i*def.constants.reelspc+def.geometry.reel_posx)*horizscale-hanchor)..
|
|
def.constants.reelcombinepref..
|
|
underlights[i+1]..":0,"..rs.."="..def.constants.symbolsstopped..
|
|
def.constants.reelshadowimg
|
|
end
|
|
reels = table.concat(t)
|
|
end
|
|
|
|
if not showlines then
|
|
if string.find(state, "win_") then
|
|
local w = string.sub(state, 5)
|
|
local linewin = allwins[tonumber(w)].payline
|
|
lines = def.constants.mainpref..def.constants.overlaylinepref..linewin..".png]"
|
|
end
|
|
else
|
|
local t = {}
|
|
for i = 1, maxlines do
|
|
t[i] = def.constants.mainpref..def.constants.overlaylinepref..i..".png]"
|
|
end
|
|
lines = table.concat(t)
|
|
end
|
|
|
|
local t = {}
|
|
if state == "scatter_win" and allwins.scatter.count > 0 then
|
|
for i,pos in ipairs(allwins.scatter.pos) do
|
|
t[i] = "image["..(((pos[1]-1)*def.constants.reelspc+def.constants.highlightboxoffsx)*horizscale-hanchor)..","..
|
|
(((pos[2]-1)*(def.geometry.reel_sizey/3)+def.constants.highlightboxoffsy)*vertscale-vanchor)..";"..
|
|
def.constants.scatterhlimg
|
|
end
|
|
scatters = table.concat(t)
|
|
end
|
|
|
|
local t = {}
|
|
if state == "bonus_win" and allwins.bonus.count > 0 then
|
|
for i,pos in ipairs(allwins.bonus.pos) do
|
|
t[i] = "image["..(((pos[1]-1)*def.constants.reelspc+def.constants.highlightboxoffsx)*horizscale-hanchor)..","..
|
|
(((pos[2]-1)*(def.geometry.reel_sizey/3)+def.constants.highlightboxoffsy)*vertscale-vanchor)..";"..
|
|
def.constants.bonushlimg
|
|
end
|
|
bonuses = table.concat(t)
|
|
end
|
|
|
|
-- all the stuff that is shown in the lower section's "screen"
|
|
|
|
local posx = def.constants.screenposx + def.geometry.label_medium_sizex * horizscale
|
|
local posy2 = def.constants.screenposy + def.geometry.screen_line_height * vertscale
|
|
local tb = maxlines*linebet
|
|
local dgszx = def.geometry.digit_glyph_sizex*0.75
|
|
|
|
local bal = def.constants.lscrnpref..def.constants.lscrnypos1..def.constants.medlblsz1..def.constants.ballabelimg..
|
|
minislots.print_number(def,
|
|
balance,
|
|
posx,
|
|
def.constants.screenposy,
|
|
dgszx,
|
|
def.geometry.screen_line_height,
|
|
true)
|
|
|
|
local betwin = def.constants.lscrnpref..def.constants.lscrnypos2..def.constants.medlblsz1..def.constants.betlabelimg..
|
|
minislots.print_number(def,
|
|
tb,
|
|
posx,
|
|
posy2,
|
|
dgszx,
|
|
def.geometry.screen_line_height,
|
|
true)
|
|
|
|
if string.find(state, "win") and allwins.total > 0 then
|
|
-- switch to 3-line mode
|
|
|
|
local tblen = string.len(tostring(tb))
|
|
|
|
betwin = def.constants.lscrnpref..def.constants.lscrnypos2..def.constants.medlblsz2..def.constants.betlabelimg..
|
|
minislots.print_number(def,
|
|
tb,
|
|
posx,
|
|
posy2,
|
|
def.constants.digitmed,
|
|
def.constants.screenlnht2,
|
|
true)..
|
|
|
|
"image["..(def.constants.screenposx + (def.geometry.label_medium_sizex
|
|
+ def.constants.digitmed * (tblen+2.3333)) * horizscale)..
|
|
def.constants.lscrnypos2..def.constants.medlblsz2..def.constants.winlabelimg..
|
|
|
|
minislots.print_number(def,
|
|
allwins.total,
|
|
def.constants.screenposx + (def.geometry.label_medium_sizex*2
|
|
+ def.constants.digitmed * (tblen+2.3333)) * horizscale,
|
|
posy2,
|
|
def.constants.digitmed,
|
|
def.constants.screenlnht2,
|
|
true)
|
|
|
|
if state == "scatter_win" then
|
|
|
|
betwin = betwin..def.constants.lscrnpref..def.constants.lscrnypos3..def.constants.scatterwinlabelimg..
|
|
minislots.print_number(def,
|
|
allwins.scatter.count * def.scatter_value * linebet,
|
|
def.constants.screenposx + def.geometry.scatter_win_label_sizex * horizscale,
|
|
def.constants.posy3,
|
|
def.constants.digitsm,
|
|
def.constants.screenlnht3,
|
|
true)
|
|
elseif state == "bonus_win" then
|
|
if allwins.bonus.value > -1 then
|
|
|
|
betwin = betwin..def.constants.lscrnpref..def.constants.lscrnypos3..def.constants.bonuswinlabelimg..
|
|
minislots.print_number(def,
|
|
allwins.bonus.value,
|
|
def.constants.screenposx + def.geometry.bonus_win_label_sizex * horizscale,
|
|
def.constants.posy3,
|
|
def.constants.digitsm,
|
|
def.constants.screenlnht3,
|
|
true)
|
|
end
|
|
else
|
|
local w = string.sub(state, 5)
|
|
local lwlen = string.len(w)
|
|
local s = tonumber(w)
|
|
local lwn = allwins[s].payline
|
|
|
|
betwin = betwin..def.constants.lscrnpref..def.constants.lscrnypos3..def.constants.lnwinlblsz..
|
|
def.constants.linewinlabelimg..
|
|
"image["..(
|
|
def.constants.screenposx
|
|
+ (def.geometry.line_win_label_sizex
|
|
+ def.constants.ln3dig) * horizscale)..
|
|
def.constants.lscrnypos3..def.constants.parenlblsz..def.constants.lparenimg..
|
|
|
|
minislots.print_number(def,
|
|
lwn,
|
|
def.constants.screenposx
|
|
+ (def.geometry.line_win_label_sizex
|
|
+ def.constants.ln3dig
|
|
+ def.constants.parensize) * horizscale,
|
|
def.constants.posy3,
|
|
def.constants.digitsm,
|
|
def.constants.screenlnht3,
|
|
false)..
|
|
|
|
"image["..(
|
|
def.constants.screenposx
|
|
+ (def.geometry.line_win_label_sizex
|
|
+ def.constants.ln3dig
|
|
+ def.constants.parensize
|
|
+ def.constants.digitsm * lwlen) * horizscale)..
|
|
def.constants.lscrnypos3..def.constants.parenlblsz..def.constants.rparenimg..
|
|
|
|
"image["..(
|
|
def.constants.screenposx
|
|
+ (def.geometry.line_win_label_sizex
|
|
+ def.constants.ln3dig
|
|
+ def.constants.parensize*2 -- i.e. two colon/paren spaces' worth
|
|
+ def.constants.digitsm * lwlen) * horizscale)..
|
|
def.constants.lscrnypos3..def.constants.parenlblsz..def.constants.colonimg..
|
|
|
|
minislots.print_number(def,
|
|
allwins[s].value*linebet,
|
|
def.constants.screenposx
|
|
+ (def.geometry.line_win_label_sizex
|
|
+ def.constants.digitsm -- that is, two separate 1/2 spaces' worth
|
|
+ def.constants.parensize*3 -- i.e. three colon/paren spaces' worth
|
|
+ def.constants.digitsm * lwlen) * horizscale,
|
|
def.constants.posy3,
|
|
def.constants.digitsm,
|
|
def.constants.screenlnht3,
|
|
true)
|
|
end
|
|
end
|
|
|
|
local onoff
|
|
local linesbetbuttons = {}
|
|
for i,b in ipairs(def.linebuttons) do
|
|
onoff = "off"
|
|
if b*linebet > balance or string.find(state, "spinning") or string.find(state, "reels_stopping_") then onoff = "dis"
|
|
elseif maxlines == tonumber(b) then onoff = "on"
|
|
end
|
|
linesbetbuttons[#linesbetbuttons+1] = def.constants.buttons_n_lines[b][onoff]
|
|
end
|
|
|
|
onoff = "off"
|
|
for i,b in ipairs(def.betbuttons) do
|
|
onoff = "off"
|
|
if b*maxlines > balance or string.find(state, "spinning") or string.find(state, "reels_stopping_") then onoff = "dis"
|
|
elseif linebet == tonumber(b) then onoff = "on"
|
|
end
|
|
linesbetbuttons[#linesbetbuttons+1] = def.constants.buttons_bet_n[b][onoff]
|
|
end
|
|
|
|
local spincashoutbuttons = ""
|
|
local upper_screen = ""
|
|
local cash_slot = ""
|
|
local button_admin = ""
|
|
local button_help = ""
|
|
|
|
if not (string.find(state, "spinning") or string.find(state, "reels_stopping_")) then
|
|
button_help = def.constants.buttonhelp
|
|
cash_slot = def.constants.buttoncashslot
|
|
if balance > 0 then
|
|
spincashoutbuttons = def.constants.buttonspin..def.constants.buttoncashout
|
|
else
|
|
spincashoutbuttons = def.constants.buttonspin_dis..def.constants.buttonquit
|
|
end
|
|
if admin then button_admin = def.constants.buttonadmin end
|
|
else
|
|
button_help = def.constants.buttonhelp_dis
|
|
cash_slot = def.constants.buttoncashslot_dis
|
|
spincashoutbuttons = def.constants.buttonspin_dis..def.constants.buttoncashout_dis
|
|
if admin then button_admin = def.constants.buttonadmin_dis end
|
|
end
|
|
|
|
if not last_cashout then
|
|
upper_screen =
|
|
def.constants.behindreels..
|
|
reels..
|
|
def.constants.overlay_upper..
|
|
scatters..
|
|
bonuses..
|
|
cash_slot..
|
|
button_admin..
|
|
button_help
|
|
else
|
|
local maxw = 6
|
|
local maxmw = 2.25
|
|
|
|
local posy = 3.6 - vanchor
|
|
|
|
local txtszy = 0.25
|
|
local numszy = 0.85
|
|
local nameszy = 0.35
|
|
local mstr_sizey = 0.15
|
|
|
|
local w = minislots.str_width_pix(casino_name, "regular")*pix2iu*nameszy
|
|
local name_sizex = w < maxw and w or maxw
|
|
|
|
local numberwords = minislots.number_to_words(last_cashout).." Minegeld"
|
|
local w = minislots.str_width_pix(numberwords, "condensed")*pix2iu*txtszy
|
|
local numwords_maxszx = w < maxw and w or maxw
|
|
|
|
local lastcoutstr = tostring(last_cashout).." Mg"
|
|
local w = minislots.str_width_pix(lastcoutstr, "bold")*pix2iu*numszy
|
|
local numstr_maxszx = w < maxw and w or maxw
|
|
|
|
local machinestr = "MACHINE #"..string.format("%.0f", minetest.hash_node_position(pos))
|
|
local w = minislots.str_width_pix(machinestr, "bold")*pix2iu*mstr_sizey
|
|
local mstr_sizex = w < maxmw and w or maxmw
|
|
|
|
local nameposx = def.constants.cashout_screen_ctrx - name_sizex*horizscale/2
|
|
local numwordsposx = def.constants.cashout_screen_ctrx - numwords_maxszx*horizscale/2
|
|
local numstrposx = def.constants.cashout_screen_ctrx - numstr_maxszx*horizscale/2
|
|
local mstr_posx = 6.25
|
|
|
|
upper_screen =
|
|
def.constants.cashoutbackground..
|
|
def.constants.upperbezel..
|
|
def.constants.cashoutticketimg..
|
|
minislots.print_string(def, casino_name, nameposx, posy, name_sizex, nameszy, "regular", false, "black")..
|
|
minislots.print_string(def, numberwords, numwordsposx, posy+1.4, numwords_maxszx, txtszy, "condensed", false, "black")..
|
|
minislots.print_string(def, lastcoutstr, numstrposx, posy+1.6, numstr_maxszx, numszy, "bold", false, "black")..
|
|
minislots.print_string(def, machinestr, mstr_posx, posy+2.36, mstr_sizex, mstr_sizey, "bold", false, "black")
|
|
end
|
|
|
|
return def.constants.form_header..
|
|
def.constants.overlay_lower..
|
|
upper_screen..
|
|
table.concat(linesbetbuttons)..
|
|
spincashoutbuttons..
|
|
lines..
|
|
bal..
|
|
betwin
|
|
end
|
|
|
|
function minislots.str_width_pix(str, weight)
|
|
local w = 0
|
|
local len = string.len(str)
|
|
for i = 1, len do
|
|
w = w + char_widths[string.byte(str, i)][weight]
|
|
end
|
|
return w
|
|
end
|
|
|
|
function minislots.print_string(def, str, posx, posy, sizex, sizey, weight, shadow, color)
|
|
local t = {}
|
|
if not str then return "" end
|
|
local len = string.len(str)
|
|
if len < 1 then return "" end
|
|
local colorize = color and "\\^[colorize\\:"..color.."\\:255" or ""
|
|
local shadowcolor = "\\^[colorize\\:black\\:255"
|
|
|
|
local px = 0
|
|
for i = 1, len do
|
|
local asc = string.byte(str, i)
|
|
|
|
t[#t+1] = px..",0=minislots_font_"..weight.."_char_"..asc..".png"
|
|
px = px + char_widths[asc][weight]
|
|
end
|
|
|
|
local text = "image["..posx..","..posy..";"..sizex..","..sizey..";"..
|
|
minetest.formspec_escape("[combine:"..px.."x80:")..
|
|
table.concat(t, ":")..colorize.."]"
|
|
if shadow then
|
|
text = "image["..(posx+0.03)..","..(posy+0.03)..";"..sizex..","..sizey..";"..
|
|
minetest.formspec_escape("[combine:"..px.."x80:")..
|
|
table.concat(t, ":")..shadowcolor.."]"..text
|
|
end
|
|
return text
|
|
end
|
|
|
|
function minislots.print_number(def, num, posx, posy, sizex, sizey, cur, color)
|
|
local t = {}
|
|
local sn = tostring(num)
|
|
local len = string.len(sn)
|
|
local colorize = color and minetest.formspec_escape("^[colorize:"..color..":255").."]" or "]"
|
|
|
|
for i = 1, len do
|
|
t[#t+1] = "image["..(posx + (i-1)*sizex * horizscale)..","..posy..";"..
|
|
sizex..","..sizey..";"..def.constants.digits[string.sub(sn, i, i)]..colorize
|
|
end
|
|
|
|
if cur then
|
|
t[#t+1] = "image["..(posx + (len*sizex+sizex/4) * horizscale)..","..posy..";"..
|
|
(sizex*1.3333)..","..(sizey)..def.constants.curlabelimg..colorize
|
|
end
|
|
|
|
return table.concat(t)
|
|
end
|
|
|
|
function minislots.number_to_words(number)
|
|
|
|
local numstr = tostring(number)
|
|
local numlen = string.len(numstr)
|
|
local words = {}
|
|
|
|
if number == 0 then return words_numbers[0] end
|
|
|
|
local i = 1
|
|
while i <= numlen do
|
|
if (i+2)/3 == math.floor((i+2)/3) then -- it's a one's digit
|
|
local n = tonumber(string.sub(numstr, -i-1, -i))
|
|
local num = words_numbers[n]
|
|
if not num then -- it's > 19
|
|
n = tonumber(string.sub(numstr, -i, -i))
|
|
if n > 0 then
|
|
words[#words+1] = words_numbers[n]
|
|
end
|
|
words[#words+1] = words_tens[tonumber(string.sub(numstr, -i-1, -i-1))]
|
|
elseif n > 0 then
|
|
words[#words+1] = num
|
|
end
|
|
i = i + 2 -- skip over the ten's place, since we already handled it.
|
|
elseif i/3 == math.floor(i/3) then -- it's a hundred's digit
|
|
local h = string.sub(numstr, -i, -i)
|
|
if h ~= "0" then -- we should only print "hundred" if the hundreds place is non-zero
|
|
words[#words+1] = words_magnitudes[1]
|
|
words[#words+1] = words_numbers[tonumber(h)]
|
|
end
|
|
i = i + 1
|
|
end
|
|
if i > numlen then break end
|
|
if tonumber(string.sub(numstr, -i-2, -i)) ~= 0 then -- the magnitude is non-zero
|
|
if i == 4 then
|
|
words[#words+1] = words_magnitudes[2] -- thousand
|
|
elseif i == 7 then
|
|
words[#words+1] = words_magnitudes[3] -- million
|
|
end
|
|
end
|
|
end
|
|
|
|
local w = {}
|
|
for i = #words, 1, -1 do
|
|
w[#w+1] = words[i]
|
|
end
|
|
|
|
return table.concat(w, " ")
|
|
end
|
|
|
|
function minislots.generate_paytable_form(def)
|
|
local t = {}
|
|
t[1] = "size[10.7,10.4]background[-0.14,-0.17;11,11;"..def.constants.paytablescrnbg.."]"..
|
|
"image_button_exit[10.25,-0.1;0.55,0.5;"..def.constants.button_close..";close;]"
|
|
|
|
local y = def.geometry.paytable_posy
|
|
local sympadding = 0.05
|
|
local column = def.geometry.paytable_column1
|
|
|
|
if def.paytable_desc then
|
|
for _, line in ipairs(def.paytable_desc) do
|
|
if line == "@wrap" then
|
|
column = def.geometry.paytable_column2
|
|
y = def.geometry.paytable_posy
|
|
else
|
|
local x = column
|
|
for _, item in ipairs(line) do
|
|
if string.sub(item, 1, 1) == "@" then
|
|
if item == "@X" then
|
|
t[#t+1] = "image["..(x*horizscale)..","..(y*vertscale)..";"..
|
|
def.geometry.paytable_lineheight..","..def.geometry.paytable_lineheight..
|
|
";"..def.constants.emptyimg.."]"
|
|
else
|
|
local sym = string.sub(item, 2)
|
|
local sympos = def.constants.symlookup["sym_"..sym] * -def.constants.reelsymsizey - (def.constants.reelsymsizey - def.constants.reelsymsizex)/2
|
|
t[#t+1] = "image["..(x*horizscale)..","..(y*vertscale)..";"..
|
|
(def.geometry.paytable_lineheight-sympadding)..","..
|
|
(def.geometry.paytable_lineheight-sympadding)..";"..
|
|
"[combine:"..def.constants.reelsymsizex.."x"..def.constants.reelsymsizex..
|
|
":0\\,"..sympos.."="..def.constants.symbolsstopped.."]"
|
|
end
|
|
x = x + def.geometry.paytable_lineheight
|
|
else
|
|
local szx = minislots.str_width_pix(item, "regular")*pix2iu*def.geometry.paytable_textheight
|
|
t[#t+1] = minislots.print_string(def, item, x*horizscale, (y+def.geometry.paytable_textshift)*vertscale, szx, def.geometry.paytable_textheight, "regular", true)
|
|
x = x + szx
|
|
end
|
|
end
|
|
end
|
|
y = y + def.geometry.paytable_lineheight
|
|
end
|
|
end
|
|
t[#t+1] = def.constants.button_showpaylines
|
|
return table.concat(t)
|
|
end
|
|
|
|
function minislots.generate_paylines_form(def)
|
|
local t = {}
|
|
local height = 10.4
|
|
t[1] = "size[10.7,"..height.."]background[-0.14,-0.17;11,11;"..def.constants.paylinescrnbg.."]"..
|
|
"image_button_exit[10.25,-0.1;0.55,0.5;"..def.constants.button_close..";close;]"
|
|
if def.paylines_desc then
|
|
|
|
local x = def.geometry.paylines_column1
|
|
local y = def.geometry.paylines_posy
|
|
local maxy = def.geometry.paylines_posy
|
|
|
|
for _, item in ipairs(def.paylines_desc) do
|
|
if item == "@wrap" then
|
|
y = def.geometry.paylines_posy
|
|
x = def.geometry.paylines_column2
|
|
elseif string.sub(item, 1, 1) == "@" then
|
|
local split = string.find(item, " ")
|
|
local s = tonumber(string.sub(item, 2, split))
|
|
local e = tonumber(string.sub(item, split))
|
|
t[#t+1] = "image["..x*horizscale..","..y*vertscale..";"..
|
|
def.geometry.paylines_sizex..","..def.geometry.paylines_sizey..";"..
|
|
def.constants.lines_bg.."]"
|
|
|
|
for l = s, e do
|
|
t[#t+1] = "image["..x*horizscale..","..y*vertscale..";"..
|
|
def.geometry.paylines_sizex..","..def.geometry.paylines_sizey..";"..
|
|
def.constants.overlaylinepref..l..".png]"
|
|
end
|
|
y = y + def.geometry.paylines_sizey + def.geometry.paylines_img_padding
|
|
else
|
|
local szx = minislots.str_width_pix(item, "regular")*pix2iu*def.geometry.paylines_textheight
|
|
t[#t+1] = minislots.print_string(def, item, x*horizscale, y*vertscale, szx, def.geometry.paylines_textheight, "regular", true)
|
|
y = y + def.geometry.paylines_lineheight
|
|
end
|
|
|
|
if y > height then
|
|
y = def.geometry.paylines_posy
|
|
x = def.geometry.paylines_column2
|
|
end
|
|
end
|
|
end
|
|
t[#t+1] = def.constants.button_showpaytable
|
|
return table.concat(t)
|
|
end
|
|
|
|
function minislots.generate_admin_form(def, pos, balance)
|
|
local meta = minetest.get_meta(pos)
|
|
local casino = meta:get_string("casino_name")
|
|
|
|
local money_in = meta:get_int("money_in")
|
|
local money_out = meta:get_int("money_out")
|
|
local total_bets = meta:get_int("total_bets")
|
|
local total_wins = meta:get_int("total_wins")
|
|
local spin_count = meta:get_int("spin_count")
|
|
local scatter_hits = meta:get_int("scatter_hits")
|
|
local bonus_hits = meta:get_int("bonus_hits")
|
|
local install_date = meta:get_string("install_date")
|
|
|
|
local pay_percent = 0
|
|
if total_bets > 0 then pay_percent = math.floor((total_wins/total_bets+0.0005)*1000)/10 end
|
|
|
|
local balancestr = "Current Balance: "..balance.." Mg"
|
|
local money_instr = "Money in: "..money_in.." Mg"
|
|
local money_outstr = "Money out: "..money_out.." Mg"
|
|
local total_betsstr = "Total bets: "..total_bets.." Mg"
|
|
local total_winsstr = "Total wins: "..total_wins.." Mg"
|
|
local percent_str = "Payout percentage: "..pay_percent.."%"
|
|
local spin_countstr = "Spin count: "..spin_count
|
|
local scatter_hitsstr = "Scatter wins (count): "..scatter_hits
|
|
local bonus_hitsstr = "Bonus wins (count): "..bonus_hits
|
|
local install_datestr = "Install Date: "..install_date
|
|
local cstr = "Casino name:"
|
|
|
|
local sizey = 0.23
|
|
|
|
local balw = minislots.str_width_pix(balancestr, "regular")*pix2iu*sizey
|
|
local miw = minislots.str_width_pix(money_instr, "regular")*pix2iu*sizey
|
|
local mow = minislots.str_width_pix(money_outstr, "regular")*pix2iu*sizey
|
|
local tbw = minislots.str_width_pix(total_betsstr, "regular")*pix2iu*sizey
|
|
local tww = minislots.str_width_pix(total_winsstr, "regular")*pix2iu*sizey
|
|
local pctw = minislots.str_width_pix(percent_str, "regular")*pix2iu*sizey
|
|
local spcw = minislots.str_width_pix(spin_countstr, "regular")*pix2iu*sizey
|
|
local sccw = minislots.str_width_pix(scatter_hitsstr, "regular")*pix2iu*sizey
|
|
local bcw = minislots.str_width_pix(bonus_hitsstr, "regular")*pix2iu*sizey
|
|
local idw = minislots.str_width_pix(install_datestr, "regular")*pix2iu*sizey
|
|
local cnw = minislots.str_width_pix(cstr, "regular")*pix2iu*sizey
|
|
|
|
local formspec =
|
|
"size[6,4.5]"..
|
|
"image_button_exit[5.65,-0.2;0.55,0.5;"..def.constants.button_close..";close;]"..
|
|
minislots.print_string(def, "Admin/configuration", 0.85, -0.15, 5, 0.4, "bold", true)..
|
|
minislots.print_string(def, balancestr, 0, 0.5, balw, sizey, "regular", true)..
|
|
minislots.print_string(def, money_instr, 0, 0.8, miw, sizey, "regular", true)..
|
|
minislots.print_string(def, money_outstr, 0, 1.1, mow, sizey, "regular", true)..
|
|
minislots.print_string(def, total_betsstr, 0, 1.4, tbw, sizey, "regular", true)..
|
|
minislots.print_string(def, total_winsstr, 0, 1.7, tww, sizey, "regular", true)..
|
|
minislots.print_string(def, percent_str, 0, 2, pctw, sizey, "regular", true)..
|
|
minislots.print_string(def, spin_countstr, 0, 2.3, spcw, sizey, "regular", true)..
|
|
minislots.print_string(def, scatter_hitsstr, 0, 2.6, sccw, sizey, "regular", true)..
|
|
minislots.print_string(def, bonus_hitsstr, 0, 2.9, bcw, sizey, "regular", true)..
|
|
minislots.print_string(def, install_datestr, 0, 3.2, idw, sizey, "regular", true)..
|
|
minislots.print_string(def, cstr, 1, 3.7, cnw, sizey, "regular", true)..
|
|
|
|
"field[1.3,3.4;4,3;casino_input;;"..casino.."]"..
|
|
"field_close_on_enter[casino_input;true]"
|
|
return formspec
|
|
end
|
|
|
|
function minislots.generate_cashslot_form(def, pos, balance)
|
|
local spos = pos.x .. "," .. pos.y .. "," ..pos.z
|
|
local formspec =
|
|
"size[8,7]"..
|
|
"background[-0.2,-0.25;8.4,7.74;"..def.constants.cashslotscrnbg.."]"..
|
|
"image_button_exit[7.55,-0.1;0.55,0.5;"..def.constants.button_close..";close;]"..
|
|
"list[nodemeta:".. spos .. ";main;3.5,1;1,1;]"..
|
|
"label[2.5,-0.25;Insert money into the space below.]"..
|
|
"label[2.2,0;When you're done, close this screen, then]"..
|
|
"label[2.2,0.25;go back to the machine to continue playing.]"..
|
|
"label[2.5,0.5;The machine's balance is: "..balance.." Mg]"..
|
|
"image["..def.geometry.cash_slot_cin_posx..","..def.geometry.cash_slot_cin_posy..";"..
|
|
def.geometry.cash_slot_sizex..","..def.geometry.cash_slot_sizey..";"..
|
|
def.constants.basename.."cash_slot.png]"..
|
|
"list[current_player;main;0,3.28;8,4;]"..
|
|
"listring[]"
|
|
return formspec
|
|
end
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if string.find(formname, "minislots:") then
|
|
|
|
local player_name = player:get_player_name()
|
|
local def = minislots.player_last_machine_def[player_name]
|
|
local pos = minislots.player_last_machine_pos[player_name]
|
|
local meta
|
|
if pos then meta = minetest.get_meta(pos) end
|
|
|
|
if fields.close and (formname == "minislots:cash_intake"
|
|
or formname == "minislots:help_screen") then
|
|
minetest.close_formspec(player_name, formname)
|
|
elseif fields.showpaylines and formname == "minislots:help_screen" then
|
|
if not def then
|
|
minetest.show_formspec(player_name, "minislots:update_form", minislots.generate_too_old_screen())
|
|
return
|
|
end
|
|
minetest.show_formspec(player_name, "minislots:help_screen",
|
|
minislots.generate_paylines_form(minislots.player_last_machine_def[player_name]))
|
|
elseif fields.showpaytable and formname == "minislots:help_screen" then
|
|
if not def then
|
|
minetest.show_formspec(player_name, "minislots:update_form", minislots.generate_too_old_screen())
|
|
return
|
|
end
|
|
minetest.show_formspec(player_name, "minislots:help_screen",
|
|
minislots.generate_paytable_form(minislots.player_last_machine_def[player_name]))
|
|
elseif fields.key_enter_field and fields.key_enter_field == fields.key_enter_field then
|
|
if not def then
|
|
minetest.show_formspec(player_name, "minislots:update_form", minislots.generate_too_old_screen())
|
|
return
|
|
end
|
|
if def and pos and meta and meta:get_string("owner") == player_name then
|
|
meta:set_string("formspec", "")
|
|
meta:set_string("casino_name", minetest.formspec_escape(fields.casino_input))
|
|
end
|
|
elseif (fields.close or fields.quit) and formname == "minislots:admin_form" then
|
|
if not def then
|
|
minetest.show_formspec(player_name, "minislots:update_form", minislots.generate_too_old_screen())
|
|
return
|
|
end
|
|
if def and pos and meta and meta:get_string("owner") == player_name then
|
|
meta:set_string("formspec", "")
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
function minislots.generate_too_old_screen()
|
|
local form = "size[4,1]"..
|
|
"image_button_exit[3.65,-0.2;0.55,0.5;minislots_close_button.png;close;]"..
|
|
"label[0.32,0.2;Sorry, your client is too old to]"..
|
|
"label[0.15,0.5;show this screen. Please update.]"
|
|
return form
|
|
end
|
|
|
|
print("[Minislots] Loaded!")
|