じ☆ve冰风 发表于 2026-7-12 11:49:56

Gem Roulette XP

Gem Roulette XP
Version 1.0.8


by Kyonides​


Introduction

This is my own version of a roulette mini game. The gems you can see on the screenshot below will rotate as expected after you hit the OK button. Later on it will show you your prize. After you collect it, it will show up on the window on the right hand side of the screen as an icon. You may collect more prizes the more attempts you get.

Just remember I didn't provide the gems you see below. Use your own icons if possible, you just need 10 of them.

You may also find ports to VX and VX Ace.

Screenshots





Instructions

There is a TXT file you need to edit so you can configure the prizes the player might earn after spinning the wheel. Later on you may check the instructions included in my script. You also need to place all required (gem) graphics in Graphics/Icons directory, you may need to create it first.

All 3 Scripts

DOWNLOAD DEMOS HERE


XP Version 1.0.8

                Code:        
# * Gem Roulette XP - Stand Alone Version
#   Scripter : Kyonides-Arkanthos
#   v 1.0.8 - 2021-10-09

#   Script Calls

#   To open Gem Roulette :         $scene = Gem_Roulette.new

#   To increase Spinning Attempts :$game_party.roulette_attempts += Number

#   This script will let you spin some gems as if they were part of a Wheel of
#   Fortune. Later on you will collect your prize. Previous prizes will be
#   displayed on the window on the right hand side.

#   Prizes are picked up randomly but you can configure what prizes they might
#   get if you edit the file named as shown on the PRIZE_FILENAME Constant below

#   There is the possibility of not letting the player get a prize depending on
#   then gem or slot selected by the script.

#   Don't forget to include the sprites needed for the 10 Gem-Slots.

module GemRouletteSetup
# Gem Icon Sprite Name Prefix - will be used as Slots
ICON_NAME_PREFIX = 'gem'
# SE for Startup and Prize is ready to be collected
SE_STARTUP = "056-Right02"
# Prizes TXT Filename
PRIZE_FILENAME = 'prizes.txt'
# Label for Position or Slot
POSITION_LABEL = 'Slot'
# Label for No Prize for you
NO_PRIZE = 'Nothing'
# Label for Item as Prize
ITEM_PRIZE   = 'Item'
# Label for Weapon as Prize
WEAPON_PRIZE = 'Weapon'
# Label for Armor as Prize
ARMOR_PRIZE= 'Armor'
# Label for Skill as Prize
SKILL_PRIZE= 'Skill'
# Label for HP as Prize or Punishment
HP_LOSS = 'HP'
# Label for SP as Prize or Punishment
SP_LOSS = 'SP'
# Icon filename for Losing HP or SP
STATS_LOSS_ICON = ''
# Points Earned Label
STATS_LOSS_LABEL = ' Earned: '
# Attempts Left Label
ATTEMPTS_LEFT = 'Attempts Left: '
# Spin the Wheel String
SPIN_WHEEL = 'Spin Wheel'
# Collect Prize String
COLLECT = 'Collect'
# No More Spins Left String
RUNOUT = 'No More Spins'
# Better Luck Next Time String
NEXT_TIME = 'Better Luck Next Time!'
# Points Label
POINTS = 'Points'
# DO NOT EDIT ANYTHING BELOW THIS LINE
PRIZE_RXDATA = 'Data/GemRoulette.rxdata'
PRIZES = {}
@prizes = []
@prize_points = []
extend self
attr_reader :prizes, :prize_points
def get_prize_data
    if $DEBUG and File.exist?(PRIZE_FILENAME)
      lines = File.readlines(PRIZE_FILENAME)
      10.times do |n|
      pts = lines.scan(/\d+ #{POINTS}/).sub!(/ #{POINTS}/,'')
      @prize_points << pts.to_i
      lines.shift
      PRIZES = []
      regex = /+/
      kinds = lines.scan(regex).map {|ln| self.prize_kind(ln) }
      indexes = lines.scan(/+/).map {|ln| self.prize_kind(ln) }
      kinds.size.times {|m| PRIZES << , indexes] }
      lines.shift
      end
      File.open(PRIZE_RXDATA, 'wb') do |file|
      Marshal.dump(@prize_points, file)
      Marshal.dump(PRIZES, file)
      end
      return
    end
    File.open(PRIZE_RXDATA, 'rb') do |file|
      @prize_points = Marshal.load(file)
      PRIZES.merge!(Marshal.load(file))
    end
end

def prize_kind(kind)
    regexp = /\d+/
    case kind
    when ITEM_PRIZE then :item
    when WEAPON_PRIZE then :weapon
    when ARMOR_PRIZE then :armor
    when SKILL_PRIZE then :skill
    when HP_LOSS then :hp
    when SP_LOSS then :sp
    when regexp then kind.to_i
    end
end
get_prize_data
end

class StatsItem
attr_reader :name, :points, :icon_name
def initialize(new_name, new_points)
    @name = new_name.to_s.upcase + ' ' + GemRouletteSetup::STATS_LOSS_LABEL
    @name += new_points.to_s
    @points = new_points
    @icon_name = GemRouletteSetup::STATS_LOSS_ICON
end
end

class Game_Party
attr_accessor :roulette_attempts, :roulette_points
alias kyon_gem_roulette_gm_party_init initialize
def initialize
    @roulette_attempts = 0
    @roulette_points = 0
    @skills = {}
    kyon_gem_roulette_gm_party_init
end

def gain_skill(sid, n)
    return unless sid > 0
    @skills = [.max, 99].min
end
def lose_skill(sid, n) gain_skill(sid, -n) end
def skill_number(sid) @skills.include?(sid)? @skills : 0 end
end

class Sprite_Blink < Sprite
def update
    super
    if @_blink
      @_blink_count = (@_blink_count + 1) % 32
      alpha = 6 * (@_blink_count < 16 ? 16 - @_blink_count : @_blink_count - 16)
      self.color.set(255, 255, 255, alpha)
    end
    @@_animations.clear rescue nil
end

def blink_on
    return if @_blink
    @_blink = true
    @_blink_count = 0
end

def blink_off
    return unless @_blink
    @_blink = false
    self.color.set(0, 0, 0, 0)
end
end

class Window_Roulette_Prizes < Window_Base
def initialize
    super(552, 80, 88, 340)
    @column_max = 2
    refresh
end

def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = GemRouletteSetup.prizes
    @item_max = @data.size
    return if @item_max == 0
    self.contents = Bitmap.new(width - 32, @item_max * 32)
    @item_max.times {|n| draw_item(n) }
end

def draw_item(index)
    x = index % 2 * 32
    y = index / 2 * 32
    bitmap = RPG::Cache.icon(@data)
    contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
end
end

class Window_Command
def replace_command(index, command)
    @commands = command
    refresh
end
end

class Window_GRPLabel < Window_Base
def initialize(w)
    super(0, 0, w, 64)
    self.contents = Bitmap.new(width - 32, height - 32)
    refresh
end

def refresh
    c = self.contents
    c.clear
    c.font.color = system_color
    points = GemRouletteSetup::POINTS
    c.draw_text(0, 0, self.width - 32, 32, points)
    c.font.color = normal_color
    points = $game_party.roulette_points.to_s
    c.draw_text(0, 0, self.width - 32, 32, points, 2)
end
end

class Gem_Roulette
include GemRouletteSetup
def initialize
    path = 'Graphics/Icons/'
    items = Dir.sort
    @items = items.map{|item| item.sub!(path, '') }
    @moving_frames = 15
    @steps = 60
    Audio.se_play("Audio/SE/" + SE_STARTUP, 80, 100)
    @item_sprites = []
    @cx = 320
    @cy = 240
    if @items.size < 10
      @items += items.dup
    elsif @items.size > 10
      @items = @items
    end
    @item_max = @items.size
    @radius = 120
    @d = 2.0 * Math::PI / @item_max
    @item_max.times do |n|
      @item_sprites << Sprite_Blink.new
      @item_sprites.x = @cx - 20 - (@radius * Math.sin(@d * n)).round
      @item_sprites.y = @cy - 60 + (@radius * Math.cos(@d * n)).round
      @item_sprites.bitmap = RPG::Cache.icon(items)
    end
    @blink_index = 0
    @item_sprites[@blink_index].blink_on
    @xy = [@item_sprites.x, @item_sprites.y]
    @prize_sprites = []
    3.times do
      @prize_sprites << Sprite.new
      @prize_sprites[-1].z = 5000
    end
    @prize_sprites.x = @cx - 12
    @prize_sprites.y = @cy - 36
    @prize_sprites.x = @prize_sprites.x - 78
    @prize_sprites.y = @prize_sprites.y + 36
    @prize_sprites.x = 210
    @prize_sprites.y = 344
    make_attempts_left_label
    @option_window = Window_Command.new(160, )
    @option_window.x = 240
    @option_window.y = @prize_sprites.y + 36
end

def make_attempts_left_label
    @prize_sprites.bitmap.clear rescue nil
    @prize_sprites.bitmap = bitmap = Bitmap.new(220, 32)
    color = Color.new(25, 25, 25, 180)
    @prize_sprites.bitmap.fill_rect(0, 0, 220, 32, color)
    attempts = ATTEMPTS_LEFT + $game_party.roulette_attempts.to_s
    bitmap.draw_text(0, 0, 220, 32, attempts, 1)
end

def main
    @spriteset = Spriteset_Map.new
    @points_window = Window_GRPLabel.new(172)
    @points_window.x = 640 - @points_window.width
    3.times {|n| @prize_sprites.z = 5000 }
    @item_max.times {|n| @item_sprites.z = 5000 }
    @prizes_window = Window_Roulette_Prizes.new
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      break if $scene != self
    end
    Graphics.freeze
    @prizes_window.dispose
    @option_window.dispose
    @xy.clear
    @prize_sprites.each {|sprite| sprite.dispose }
    @prize_sprites.clear
    @item_sprites.each {|sprite| sprite.dispose }
    @item_sprites.clear
    @prize_sprites = @item_sprites = @xy = nil
    @points_window.dispose
    @spriteset.dispose
end

def update
    @option_window.update
    @prizes_window.update
    @item_sprites.each{|sprite| sprite.update }
    if @move
      refresh_sprites
      return
    end
    if Input.trigger?(Input::B)
      exit_scene
      return
    elsif Input.trigger?(Input::C)
      if $game_party.roulette_attempts == 0
      if @result
          retrieve_new_prize
          exit_scene
      else
          $game_system.se_play($data_system.buzzer_se)
      end
      return
      end
      $game_system.se_play($data_system.decision_se)
      retrieve_new_prize
    end
end

def exit_scene
    $game_system.se_play($data_system.buzzer_se)
    GemRouletteSetup.prizes.clear
    $scene = Scene_Map.new
end

def retrieve_new_prize
    if !@move and !@result
      @item_sprites[@blink_index].blink_off
      @option_window.index = -1
      $game_party.roulette_attempts -= 1
      make_attempts_left_label
      @index = rand(@item_max)
      @move = true
      return
    end
    return unless @result
    GemRouletteSetup.prizes << @new_prize.icon_name if @new_prize
    @prizes_window.refresh
    @option_window.index = 0
    case @kind
    when :item then $game_party.gain_item(@new_prize.id, 1)
    when :weapon then $game_party.gain_weapon(@new_prize.id, 1)
    when :armor then $game_party.gain_armor(@new_prize.id, 1)
    when :skill then $game_party.gain_skill(@new_prize.id, 1)
    when :hp then $game_party.actors.hp += @new_prize.points
    when :sp then $game_party.actors.sp += @new_prize.points
    end
    @prize_sprites.bitmap.clear rescue nil
    @prize_sprites.bitmap.clear rescue nil
    @result = nil
    comm = $game_party.roulette_attempts > 0 ? SPIN_WHEEL : RUNOUT
    @option_window.replace_command(0, comm)
end

def refresh_sprites
    d1 = -@d / @moving_frames * 2
    @item_max.times do |n|
      m = n - @index
      d = @d * m + d1 * @steps
      @item_sprites.x = @cx - 20 - (@radius * Math.sin(d)).round
      @item_sprites.y = @cy - 60 + (@radius * Math.cos(d)).round
    end
    @steps -= 1
    if @steps == -1
      if rand(5) == 0
      @steps += 5
      return
      end
      Audio.se_play("Audio/SE/" + GemRouletteSetup::SE_STARTUP, 80, 100)
      @move = nil
      @steps = 1 + @moving_frames * (3 + rand(5))
      results = @item_sprites.map{|sprite| @xy == }
      @blink_index = @result = results.index(true)
      @item_sprites[@blink_index].blink_on
      check_prize
    end
end

def get_prize_kind(kind, index)
    @kind = kind
    case kind
    when :item then $data_items
    when :weapon then $data_weapons
    when :armor then $data_armors
    when :skill then $data_skills
    when :hp, :sp then StatsItem.new(kind, index)
    end
end

def find_prize
    case @prizes.size
    when 1
      @prizes ? get_prize_kind(@prizes, @prizes) : nil
    else
      index = @prizes.size > 2 ? rand(@prizes.size) : rand(4) % 2
      get_prize_kind(@prizes, @prizes)
    end
end

def no_prize
    @kind = nil
    @prize_sprites.bitmap = bitmap = Bitmap.new(200, 24)
    bitmap.font.bold = true
    bitmap.font.size = 19
    bitmap.draw_text(0, 0, 200, 24, NEXT_TIME, 1)
end

def check_prize
    $game_party.roulette_points += GemRouletteSetup.prize_points[@blink_index]
    @points_window.refresh
    @prizes = PRIZES[@result]
    return no_prize if @prizes.nil? or @prizes.nil?
    @new_prize = find_prize
    return no_prize unless @new_prize
    @prizes.clear
    @prize_sprites.bitmap = RPG::Cache.icon(@new_prize.icon_name).dup
    @prize_sprites.bitmap = bitmap = Bitmap.new(180, 24)
    bitmap.font.bold = true
    bitmap.font.size = 19
    bitmap.draw_text(0, 0, 180, 24, @new_prize.name, 1)
    @option_window.replace_command(0, COLLECT)
end
end



TXT Config File
Valid for All Versions
                Code:        
Slot 1
Weapon 1, Item 1, Armor 1, Skill 1
Slot 2
Weapon 2, Item 2, Skill 2
Slot 3
Weapon 5, Item 3, Armor 4, Skill 3
Slot 4
Weapon 1, Item 1, Armor 1, Skill 1
Slot 5
Weapon 1, Item 5, Item 8, Skill 1
Slot 6
Weapon 1, Item 1, Armor 8, Skill 1
Slot 7
Weapon 1, Item 1, Armor 1, Skill 1
Slot 8
Nothing
Slot 9
Weapon 1, Item 1, Armor 1, Skill 5
Slot 10
Weapon 4, Item 1, Armor 4, Skill 20


FAQ

Nothing to say, yet.


Compatibility

Designed for RPG Maker XP & VX & VX ACE. You may need to check out the other subfora to find them.


Terms and Conditions

Free for use in non commercial projects, but you may contact me in case you want to go commercial. Due credit is a must.

By the way, I will only support the latest version available because it usually includes bug fixes and improvements.

You are not allowed to repost my scripts on any other boards.

Give me a free copy of your completed game if you include at least 2 of my scripts!
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7


本贴来自国际rpgmaker官方论坛作者:kyonides处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/gem-roulette-xp.115333/
页: [1]
查看完整版本: Gem Roulette XP