Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Imitating RMXP/VX's Product Key Prompt

I'm writting this for kicks, nothing more than to practice my Ruby/RGSSism, its supposed to be used in a Scene Activation script (where you enter your keycode and stuff), and all the values are set to 3 different values. This is everything I've wrote in the past 5 minutes, but I have questions overall about how to define everything, or if I'm doing it right.

1.) Identification Number
2.) Serial Number
3.) Product Key


So I defined each letter and number in the initialize method, like so...

Code:
A = ['A', 'F', 'M']
B = ['B', 'L', '0']
C = ['C', 'B', 'X']
# etc, etc, etc...

Lets say I wanted to pull the 'F' out of it, how would I do that?

Code:
def identification
  id_01 = A[0, <this value>, 0]
  id_02 = B[0, <this value>, 0]
  # etc, etc, etc...
end

And how would be the best way to set up the product key and registration and all of that? I was thinking something like this...

Code:
def product_key
  p_01 = digit.rand[<this value>, 0]
  p_02 = digit.rand[<this value, 0]
  # etc, etc, etc...
  s_01 = digit.rand[0, <this value>]
  # etc, etc, etc...
end

Of course, it would need to detect the Random of A..Z and 0..9, because all 36 digits are used (3 times) in the equations.

And for cross checking if the product key you've entered translates into the origional serial or registration or whatever, could I define it like this, or how should I go about it?

Code:
def check_identification
  for i in 0..valid_key01
    if key01.[0, <this value>] == id_02.[<this value>, 0] ? true : false
      return valid_key01 # tells it wether valid key is true or not
    end
  for i in 0..valid_key02
    if key02.[0, <this value>] == id_02.[<this value>, 0] ? true : false
      return valid_key02
 # tells it wether valid key is true or not (again)
    end
    # Blah blah
  end
end

These are just rough examples of what I am trying to do, but I need help on all of those.

In the end, the player needs to enter all the codes with his keyboard, and it cross checks if your activation code is valid, and returns true for each match, and each valid_key must equal true or the player can't unlock the product. I'm not sure how exactly I should write each method, take a good look at each example above and tell me what to do or what I'm doing wrong, or how I would pull each method off successfully.
 

khmp

Sponsor

I am really confused on how and what you are doing here. So forgive my ignorance if I ask something idiotic. Alright in your first code snippet you are defining 3 constants that each reference a different array of 3 elements which are strings. Pulling the string 'F' from the constant A is easily done by indexing A at position 1. A has 3 positions and all arrays start at index 0. So in this case valid positive input would be 0, 1, and 2.
Code:
A = ['A', 'F', 'M']
p A[1] # 'F'

I recommend a Ruby tutorial on Arrays and Hashes if you are confused about the subject.

As for generating a number unique to a PC is a little more difficult and I'd have to google it to find out more about it. I wouldn't  be so keen for using rand as it is, by all means, random. I think that based off of the unique PC ID you would run it through some sort of complex algorithm to generate a valid product key. But this is completely new to me and I'm writing it as I think about it :wink: I really want to know what PC games do with serial keys now...
 
People keep telling me I'll have to write it to a registry key or something, but I'm curious if I can write it into a file, such as Game_System.rxdata, within an encrypted project. Writting it to the actual Windows/Linux system registry shouldn't really be required to lock the project anyway... I mean, you could but I'm not trying to, I think it would be better handled internally.

Here's the actual script so far, it's a rough draft. The comments are in there to express what is eventually going to result into the full script, read them for any extra info. This is the only real way to understand what I'm talking about.

Code:
#===============================================================================
# ~** Activate Product Code **~
#===============================================================================
# Written by  : Kain Nobel
# Version     : 0.06 (Beta)
# Last Update : 5/14/2008
# Date Created: 4/28/2008
#===============================================================================
# Activation_Debug
#   true : Enabled for Playtest
#   false: Disabled for Playtest
#------------------------------------------
# Activation_Required
#   true : Enabled for Game.exe
#   false: Disabled for Game.exe
#------------------------------------------
# Activation_TL_Hour
#   nil : Doesn't calculate hours
#   0..? : Calculates to set max hours
#------------------------------------------
# Activation_TL_Min
#   nil : Doesn't calculate minutes
#   0..59 : Calculates to set max minutes
#------------------------------------------
# Activation_TL_Sec
#   nil : Doesn't calculate seconds
#   0..59 : Calculates to set max seconds
#------------------------------------------
# Serial_Digits_Max
#   How many keys long is the Serial #?
#------------------------------------------
# Product_Digits_Max
#   How many keys long is the Product #?
#------------------------------------------
# Activation_Digits_Max (Don't touch)
#   Adds Product and Serial digits together
#------------------------------------------
# Activation_Menu_Disable
#   true  : disable menu in trial version
#   false : menu isn't disabled by script
#------------------------------------------
# Activation_Save_Disabled
#   true  : disable save in trial version
#   false : save isn't disabled by script
#------------------------------------------
# Activation_Load_Disabled
#   true  : disable load in trial version
#   false : load isn't disabled by script
#===============================================================================
# Script and Debug
Activation_Debug = false
Activation_Required = false
# Time Limit
Activation_TL_Hour = nil
Activation_TL_Min = nil
Activation_TL_Sec = nil
# Digits Max
Serial_Digits_Max = 25
Product_Digits_Max = 25
# Function Restrictions
Activation_Menu_Disabled = false
Activation_Save_Disabled = false
Activation_Load_Disabled = false
# Do Not Touch Last Constant, script will malfunction
Activation_Digits_Max = Serial_Digits_Max + Product_Digits_Max
################################################################################
# What does it do?
#===============================================================================
#   When you open the game and are brought to the Title screen, you are only
# allowed to access New Game, you are not allowed to continue. Also, you are
# not allowed to save a game in progress and have a specified time frame in
# which you're allowed to play the game, until you've activated the game.
#   Upon accessing a New Game, or trying to Save in a game in progress, you
# will be re-directed to the "Enter Product Key" window, where you must
# enter your "Proof of Purchase" code. Once you've entered a "Proof of Purchase"
# code, it is to be permanently saved to the Game_System so you will be able
# to play the game with no limitations.
#   NOTE: By default, the system allows for New Game, which will let players
# play for a limited time (hence the option to set the time limit.) This will
# automatically exit the game after its been on for a certain ammount of time.
################################################################################
# Who would Want this?!
#===============================================================================
#   Somebody who plans on selling their game to the general public for a small
# profit, or somebody who would require money for a person to play their game,
# such as an MMORPG, to keep their server running, etc.
#   I personally didn't write this for my own use, but hopefully somebody would
# find good use of it. For god's sake, I wouldn't use it for a project demo or
# anything without disabling/removing the script, but if you've got a FULL game
# you want to sell (that doesn't suck) go ahead and use the script, and be sure
# to not expose your personal code keys to the public (thats why they're blank.)
################################################################################
# How are the codes determined?
#===============================================================================
#   They are randomized upon first startup, and saved into the system. Each code
# translates as being the same, but are 'cloaked' to be different. The actual
# 'values' MUST be set by you, every letter A to Z and number 0 to 9, so that it
# they're unique from somebody else's game. That is why, when you open the
# script, you notice it is defined like...
#
# key_a = ['A', '', '']
#
# Those blank '' you must write a letter/number in and make sure you don't use
# the same value twice in the same column, like so...
#
# key_a = ['', 'C', '']
# key_b = ['', 'C', '']
#
# Notice how the middle digits are both 'C' ? Refrain from using the same letter
# or number twice, because that'll defeat the purpose of the codes translating
# like they should, and you'll possibly lose customers. Nobody wants to purchase
# a game, just to rip their hair out when trying to enter their purchased
# product key.
################################################################################
# Whats the chances of the same codes working on another game?
#===============================================================================
#   Highly unlikely, they're randomized. Letters A-Z is 26 + 0-9 is 10, so thats
# 36 x 36 = 1296 different codes possible to be generated, so it's not exactly
# easy to get duplicate codes on different games.
################################################################################
# How are the codes set up?
#===============================================================================
# serial = [@serial_a, @serial_b, @serial_c, @serial_d, @serial_e]
# product = [@product_a, @product_b, @product_c, @product_d, @product_e]
#
# These all translate into each other, so secretly @serial_a and @product_a are
# really the same code translated like XD3F9 <--> MF89C
#
# Then when we get to activation code, it secretly translates like
#
# activation[@serial_a, @product_a, @serial_b, @product_b, ...]
#
# Again, each 'key' translates like A = ['A', '0', 'C'], depending on what
# type of code we're talking about.
################################################################################
# How do I give a customer their activation code? 
#===============================================================================
#   Sorry, thats the only thing that's completely up to you to handle. Best bet
# would be to have them send their codes to some kinda website server that'll
# translate their activation code for them, which I know nothing about. As long
# as you know how my script works, you'll have to develop a keygen tool for your
# project yourself, with the same 3 values for each Key as you've defined in the
# script. 
#   If worse comes to worse, they'll have to E-mail their serial/product
# code to you, and you'll have to translate it for them by hand. You better be
# on it if you're selling your game, because I do not support ripping people
# off!
#
#   Good luck and have fun with it!
#===============================================================================
################################################################################
#===============================================================================
# ** Module : RPG
#===============================================================================
module RPG
  #=============================================================================
  # * RPG::Registration
  #-----------------------------------------------------------------------------
  # On scene title, these values are automatically overwritten if the activation
  # code does not translate back to the digits in "serial" and "product".
  #=============================================================================
  class Registration
    #--------------------
    # * Initialize Method
    #--------------------
    def initialize
      # Registered Serial Number
      serial = [@serial_a, @serial_b, @serial_c, @serial_d, @serial_e]
      # Serial Digits
      @serial_a = 0
      @serial_b = 0
      @serial_c = 0
      @serial_d = 0
      @serial_e = 0
      # Registered Product Number
      product = [@product_a, @product_b, @product_c, @product_d, @product_e]
      # Product Digits
      @product_a = 0
      @product_b = 0
      @product_c = 0
      @product_d = 0
      @product_e = 0
      # Registered Activation Code
      activation = [@activ_a,@activ_b,@activ_c,@activ_d,@activ_e,
                    @activ_f, @activ_g,@activ_h, @activ_i, @activ_j]
      # Activation Digits
      @activ_a = 0
      @avtiv_b = 0
      @activ_c = 0
      @activ_d = 0
      @activ_e = 0
      @activ_f = 0
      @activ_g = 0
      @activ_h = 0
      @activ_i = 0
      @activ_j = 0
    end
    # Registered Serial Number
    attr_accessor :serial
    # Serial Digits
    attr_accessor :serial_a
    attr_accessor :serial_b
    attr_accessor :serial_c
    attr_accessor :serial_d
    # Registered Product Number
    attr_accessor :product
    # Product Digits
    attr_accessor :product_a
    attr_accessor :product_b
    attr_accessor :product_c
    attr_accessor :product_d
    # Activation Code
    attr_accessor :activation
    # Activation Digits
    attr_accessor :activ_a
    attr_accessor :activ_b
    attr_accessor :activ_c
    attr_accessor :activ_d
    attr_accessor :activ_e
    attr_accessor :activ_f
    attr_accessor :activ_g
    attr_accessor :activ_h
  end
end
################################################################################
#===============================================================================
# ** Game_System
#-------------------------------------------------------------------------------
#  This class is aliased to save serial and product number information.
#===============================================================================
class Game_System #<< RPG::Registration
  #[Attributes]-----------------------------------------------------------------
  attr_accessor :serial_number
  attr_accessor :product_number
  attr_accessor :activation_code
  #-----------------------------------------------------------------------------
  # * Alias Methods
  #-----------------------------------------------------------------------------
  alias_method :activation_game_scene_initialize, :initialize
  #--------------------
  # * Initialize Method
  #--------------------
  def initialize
    @serial_number = serial_number
    @product_number = product_number
    @activation_code = activation_code
    activation_game_scene_initialize
  end
  #----------------
  # * Serial Number
  #----------------
  def serial_number
    @s_valid = false
    if @serial_number != nil && @serial_number == $game_activate.serial
      @s_valid = true
      return @serial_number
    else
      @s_valid = false
      register_new_serial
    end
  end
  #-----------------
  # * Product Number
  #-----------------
  def product_number
    @p_valid = false
    if @product_number == $game_activate.product
      @p_valid = true
      return @product_number
    else
      @p_valid = false
      register_new_product
    end
  end
  #-----------------------------
  # * Register New Serial Number
  #-----------------------------
  def register_new_serial
    # Serial Number is sent to an instance variable
    @reg_serial = serial_number
    # Maximum digits in the serial number
    @digits_max = Activation_Digits_Max
    # If Serial Number doesn't exist...
    if @reg_serial == nil
      # Serial Number size is sent to an instance variable
      @digit = @reg_serial.size
      # For the information in Serial Number size...
      for i in @digit
        # A random key is sent to the serial digit
        @digit = random_key[i]
        # Add 1 to the serial number size determinate.
        @size += 1
        # Push the digit into the serial number
        serial_number.push(@digit)
        # Ends once the digits max
      end until size == @digits_max
    end
  end
  #----------------------------
  # * Register New Product Code
  #----------------------------
  def register_new_product
    @reg_product = $game_system.product_number
    if @reg_product == nil
      # The method...?
    end
  end
  #-----------------
  # * Activation Key
  #-----------------
  def activation_code
    @code = $game_activate.activation_code
    @serial = $game_activate.serial
    if @code == @serial
      @unlock_new_product = true
    else
      @unlock_new_product = false
    end
    return @unlock_new_product
  end
end
################################################################################
#===============================================================================
# ** Window_Activation
#-------------------------------------------------------------------------------
# This Window is called at the title screen if the user's activation validation
# code hasn't been entered.
#===============================================================================
class Window_Activation < Window_Base
  #--------------------
  # * Initialize Method
  #--------------------
  def initialize
    super(0, 0, 0, 0)
    @serial = $game_system.serial_number
    @product = $game_system.product_number
    @activation = []
    refresh
  end
  #-----------------
  # * Refresh Method
  #-----------------
  def refresh
    self.contents.clear
    # Draw Code Names
    self.contents.font = Default.font_type
    self.contents.font.color = system_color
    self.contents.draw_text(0, 0, 0, 0, "Serial :", 1)
    self.contents.draw_text(0, 64, 0, 0, "Product :", 1)
    self.contents.draw_text(0, 128, 0, 0, "Activation :", 1)
    # Draw Code Values
    self.contents.font = "Georgia"
    self.contents.font.color = Color.new(0, 0, 0, 255)
    self.contents.draw_text(0, 32, 0, 0, @reg_serial.to_s, 1)
    self.contents.draw_text(0, 96, 0, 0, @reg_product.to_s, 1)
    self.contents.draw_text(0, 160, 0, 0, @reg_activ.to_s, 1)
  end
  #----------------
  # * Update Method
  #----------------
  def dispose
    super
  end
end
################################################################################
#===============================================================================
# ** Scene_Title (Aliased)
#-------------------------------------------------------------------------------
#   This scene is aliased to include the Activation scene when entering either
# command_new_game, or command_continue (provided a save file is present.)
#===============================================================================
class Scene_Title
  #-----------------------------------------------------------------------------
  # * Aliased Methods
  #-----------------------------------------------------------------------------
  alias_method :activation_scene_title_main, :main
  alias_method :activation_scene_title_new_game, :command_new_game
  alias_method :activation_scene_title_continue, :command_continue
  #------------------------
  # * Main Method (Aliased)
  #------------------------
  def main
    # Create Activation Window, make it invisible and inactive.
    @activ_window = Window_Activation.new
    @activ_window.visible = false
    @activ_window.active = false
    # Alias method
    activation_scene_title_main
  end
  #---------------------
  # * New Game (Aliased)
  #---------------------
  def command_new_game
    # Open Activation window if purchase registration not completed
    if $activation = true
      # Alias method
      activation_scene_title_new_game
    else
      # Goto: Enter Registration Method
      enter_registration
    end
  end
  #---------------------
  # * Continue (Aliased)
  #---------------------
  def command_continue
    if $activation = true
      # Alias method
      activation_scene_title_continue
    else
      # Goto: Enter Registration method
      enter_registration
    end
  end
  #---------------------
  # * Enter Registration
  #---------------------
  def enter_registration
    # Coming soon...
    print("Coming Soon...")
  end
end
################################################################################
#===============================================================================
# ** Scene Save
#===============================================================================
class Scene_Save
  #--------------------------------
  # * Initialize Method (Overwrite)
  #--------------------------------
  def initialize
    # If you haven't entered product key...?
    if $activation = false
      # Prints message, save disabled flag is true
      super("You cannot save without activation key.")
      @flag_save_disable = true
    else
      # Prints message, save disabled flag is false
      super("Which file would you like to save to?")
      @flag_save_disable = false
    end
    # Goto: Save Enabled? Method
    save_enabled?
  end
  #---------------
  # * Disable Save
  #---------------
  def save_enabled?
    if @flag_save_disabled == true
      $game_system.save_disabled = true
    else
      $game_system.save_disabled = false
    end
  end
end
################################################################################

Thanks that linked explanation helped out (kinda) but I'm still a little confused, I'll brush up on it a little bit. Code is updated, I'm not sure if I'm starting the method right though... here's the start of the method that will determine each random digit in the array.

Code:
class Game_System
  # Start Example
  #-----------------------------
  # * Register New Serial Number
  #-----------------------------
  def register_new_serial
    # Serial Number is sent to an instance variable
    @reg_serial = serial_number
    # Maximum digits in the serial number
    @digits_max = Activation_Digits_Max #See constants defined in top of script.
    # If Serial Number doesn't exist...
    if @reg_serial == nil
      # Serial Number size is sent to an instance variable
      @digit = @reg_serial.size
      # For the information in Serial Number size...
      for i in @digit
        # A random key is sent to the serial digit
        @digit = random_key[i]
        # Add 1 to the serial number size determinate.
        @size += 1
        # Push the digit into the serial number
        serial_number.push(@digit)
        # Ends once the digits max
      end until size == @digits_max
    end
  end
  # End Example
end

Finally, this is an example of how each code would translate between each other to the activation code...

Serial #    : XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
Product # : XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

The activation code would be an instance of both those translated into different numbers and letters, and hence is double in size, kinda like the tumblers of a rollodex lock.

Activate #:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
               serial    prod    serial    prod     serial    prod    serial    prod     serial   prod

Meaning that while serial and product has a pre-set 5 groups of 5 digits, that'd mean activation would have 5 groups of 10 digits. I'm sure you'll be able to make it smaller or bigger, but this is how it was invisioned in my head.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top