Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - orochii

Update. New 2018 version is out. Here some links.


It includes both English and Spanish. As you might imagine, English translation was made by me (my native is Spanish), so please excuse the greatness in quality.

Here is the roadmap for the script.
- Stop/pause effect support.
- Loop points. Both for entry and exit.
- Audio playback.
- Particle system editor.

There is some other tweaks to do that I've just considered, specifically for bitmap loading (in order to make it compatible with the editor idea, and for simplicity). But yeah.

RMXP Script Database / [XP][VX][VXA] Particle Emissor
August 14, 2018, 05:28:10 pm
Particle Emissor
Authors: Orochii Zouveleki
Version: 0.5a
Type: Visual Object Class
Key Term: Misc Add-on


Sometimes referred to as particle system, this is more like an utility for now but it's a class to be used in order to add particle effects to your game. It includes a lot of properties for your particles and I think it's pretty capable of doing some stuff. Might be kind of hard to use though, especially since I haven't made a proper easy integration with, say, maps and battles. But a capable scripter should be able to gie this thing a good use.


  • Make a particle emitter

  • Customize particle emitter shape and emission properties (interval, particles per second, etc).

  • Support for both constant emission and particle bursts (bursts can also use additional images).

  • Properties for particles, such as size, speed, acceleration, rotation, color... Each of these can vary through the particle lifespan.



Particles.7z (~200Kb)


Spoiler: ShowHide

OZ Particle Emitter - Versión 0.5a
Testeado en RGSS1
Autor: Orochii Zouveleki

module OZMath
  Este módulo incluye algunas operaciones comunes.

  def self.deg2rad(degrees) - Convierte grados a radianes.
Retorno: Numeric.
  def self.lerp(v,a,b) - Interpolación lineal entre números a y b
de acuerdo a v (0..1).
Retorno: Numeric.
  def self.clamp(v,min,max) - Restringe un valor v a un intérvalo [min,max]
Retorno: Numeric.
  def self.rand_range(a,b) - Número aleatorio entre a y b.
Retorno: Numeric.
  def self.rand_range_i(a,b) - Número aleatorio entero entre a y b.
Retorno: Numeric.
  def self.lerp_col(v, c1, c2) - Interpolación lineal entre Color c1 y c2
de acuerdo a v.
  Retorno: Color.

class FreeRange
Esta clase es una versión inútil de Range, con el objeto de soportar
valores de punto flotante.
Simplemente necesitaba algo que lo guardara, y no fuera Array. ¯\_(ツ)_/¯

  def initialize(first,last) -Inicializa objeto
  attr_reader :first -Valor inicial
  attr_reader :last -Valor final

class Particle < Sprite
  attr_reader :dead
  def initialize(bitmap,emissor,x,y,viewport=nil)
-Inicialización partícula
  def update -Lógica de partícula
  def get_property(p,modifier=nil,k=:number)
-Obtiene valor real de propiedad
  Retorno: Numeric, Array de Numeric o Color
  def get_max(p, k=:number) -
  Retorno: Numeric o Array de Numeric
  def get_modifier(mod)
    Retorno: Numeric 0..1
  # Métodos de utilidad internos
  def iter_modifiers(m, lm, sm)
  def get_property_color(p,modifier)
  def get_property_array(p,modifier)
  def get_property_number(p,modifier)
  def get_max_array(p)
  def get_max_number(p)

class ParticleEmissorProperties
  # Global attributes
  attr_accessor :viewport -Viewport usado por todos los sprites
  attr_accessor :simulation_space -:local para mover partícula con emisor
  attr_accessor :max_particles -Numeric, límite de sprites
  attr_accessor :duration -frames antes de reinicio de emisión
  attr_accessor :looping -si se repite el efecto
  attr_accessor :autoplay -emitir al iniciar
  attr_accessor :bitmaps -imágenes usadas por partículas (al azar)
  # Emission attributes
  attr_accessor :pps -Partículas por segundo
  attr_accessor :bursts -Array de ráfagas. Usa un tiempo t de
acuerdo al temporizador interno del emisor
y un número n de partículas a emitir en
el momento. bmp es usado para determinar
un bitmap personalizado (nil para usar
los otros al azar).
[[t1,n1,bmp],[t2,n2,bmp], (...)]
  attr_accessor :shape -Forma del emisor. :circle o :square
  attr_accessor :shape_a -Radio mínimo para :circle. Ancho para :square
  attr_accessor :shape_b -Radio máximo para :circle. Alto para :square
  attr_accessor :shape_angle -En círculos, delimita el arco de efecto.
  # Particle attributes
Los atributos de partícula suelen poseer un atributo modificador que modifica su
comportamiento de acuerdo a otro valor.
Ej. Si speed_modifier==:lifetime, la velocidad cambiará a lo largo de
la vida de la partícula.
Los atributos además pueden recibir valores en arrays o sueltos, así como rangos.
Los rangos pueden ser clase Range o FreeRange (clase hecha como parte de este script).
color =,0,0,0)
color = [,0,0,255),,128,196,160)]
speed = [1,0]
speed = [[-1,5,7],,3)]
Algunos atributos requieren ser encapsulados en un array siempre de un tamaño específico,
pero sus miembros internos pueden encapsularse en otro array o ser Range/FreeRange.

  attr_accessor :lifetime -Tiempo de vida de partículas (en frames)
  attr_accessor :speed -Velocidad [X,Y].
  attr_accessor :speed_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :acceleration -
  attr_accessor :acceleration_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :size -
  attr_accessor :size_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :rotation -
  attr_accessor :rotation_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :opacity -
  attr_accessor :opacity_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :color -
  attr_accessor :color_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  def initialize(bitmaps=[]) -Inicializador, recibe bitmaps a usar.
  def get_random_bitmap -Devuelve un bitmap al azar de bitmaps.
Devuelve un bitmap blanco de 8x8 si no hay bitmaps.
class ParticleEmissor
  attr_accessor :properties
  attr_accessor :x
  attr_accessor :y
  def initialize(x, y, z,
  def update
  def create_new_particle(bmp)
  def get_shape_coordinate
  def dispose

module OZMath
  def self.deg2rad(degrees)
    return degrees * Math::PI / 180
  def self.lerp(v,a,b)
    return (b-a)*v + a
  def self.clamp(v,min,max)
    return [ [ min, v ].max, max ].min
  def self.rand_range(a,b)
    return rand * (b-a) + a
  def self.rand_range_i(a,b)
    return rand(b-a)+a
  def self.lerp_col(v, c1, c2)
    r = lerp(v,,
    g = lerp(v,,
    b = lerp(v,,
    a = lerp(v, c1.alpha, c2.alpha)

class FreeRange
  def initialize(first,last)
    @first = first
    @last = last
  attr_reader :first
  attr_reader :last

class Particle < Sprite
  attr_reader :dead
  def initialize(bitmap, emissor, x, y, viewport=nil)
    self.bitmap = bitmap
    self.blend_type = 1
    @ref = emissor if
    @x = x
    @y = y
    if @ref==nil
      @x += emissor.x
      @y += emissor.y
    # Lifetime is constant
    @lifetime = get_property(
    @starting_lifetime = @lifetime
    @dead = false
    # Modifiers are also constant
    @speed_modifier =
    @acceleration_modifier =
    @size_modifier =
    @rotation_modifier =
    @opacity_modifier =
    @color_modifier =
    # Others are processed
    @speed =
    @top_speed = get_max(,:array)
    @acceleration =
    @size =
    @rotation =
    @opacity_ =
    @color =
    # Initialize speed
    if @speed_modifier==:lifetime
      @current_speed = get_property(@speed,0,:array)
      @current_speed = get_property(@speed,nil,:array)
    # Update
  def iter_modifiers(m, lm, sm)
    return (m==:lifetime) ? lm : (m==:speed) ? sm : nil
  def update
    # Lifetime update
    return if @dead==true
    @lifetime -= 1
    # Buffer modifiers
    lm = get_modifier(:lifetime)
    sm = get_modifier(:speed)
    # Set modifier buffers to each
    speed_mod = iter_modifiers(@speed_modifier,lm,sm)
    accel_mod = iter_modifiers(@acceleration_modifier,lm,sm)
    size_mod = iter_modifiers(@size_modifier,lm,sm)
    rot_mod = iter_modifiers(@rotation_modifier,lm,sm)
    opacity_mod = iter_modifiers(@opacity_modifier,lm,sm)
    color_mod = iter_modifiers(@color_modifier, lm, sm)
    # Update speed
    accel = get_property(@acceleration,accel_mod,:array)
    @current_speed[0] += accel[0]
    @current_speed[1] += accel[1]
    # Update size
    self.zoom_x = get_property(@size[0],size_mod) if size_mod != nil
    self.zoom_y = get_property(@size[1],size_mod) if size_mod != nil
    # Update angle
    self.angle += get_property(@rotation,rot_mod)
    self.opacity = get_property(@opacity_,opacity_mod)
    # Update color
    self.color = get_property(@color, color_mod, :color)
    # Update position
    sm = speed_mod==nil ? 1 : speed_mod
    @x += @current_speed[0]*sm
    @y += @current_speed[1]*sm
    if @ref==nil
      self.x = @x
      self.y = @y
      self.x = @x + @ref.x
      self.y = @y + @ref.y
    if (@lifetime <= 0)
      @dead = true
      self.visible = false
  # Returns: Any number / array of number
  def get_property(p,modifier=nil,k=:number)
    return get_property_color(p, modifier) if k==:color
    return get_property_array(p, modifier) if k==:array
    return get_property_number(p,modifier)
  # Returns: Any number / array of number
  def get_max(p, k=:number)
    return get_max_array(p) if k==:array
    return get_max_number(p)
  # Returns: 0..1
  def get_modifier(mod)
    if mod==:lifetime
      return (@starting_lifetime-@lifetime)*1.0/@starting_lifetime
    if mod==:speed
      s = @current_speed[0].abs + @current_speed[1].abs
      ts= @top_speed[0].abs + @top_speed[1].abs
      return (s*1.0/ts)
    return 0
  # "HELPERS" (or internal methods)
  def get_property_color(p,modifier)
    if p.is_a?(Array)
      m = modifier==nil ? rand() : modifier
      a = (p.size * m).floor
      a = p.size-1 if a>=p.size
      b = a+1
      b = a if b>=p.size
      c1 = p[a]
      c2 = p[b]
      l = (m * p.size) - a
      return OZMath.lerp_col(l, c1, c2)
    elsif p.is_a?(Color)
      return p
  def get_property_array(p,modifier)
    val = []
    for i in 0...p.size
      val[i] = get_property_number(p[i], modifier)
    return val
  def get_property_number(p,modifier)
    # If modifier set to none
    if (modifier == nil)
      if p.is_a?(Numeric)||p.is_a?(Color)
        return p
      elsif p.is_a?(Array)
        return 0 if p.size==0
        a = rand(p.size)
        return p[a]
      elsif p.is_a?(Range) || p.is_a?(FreeRange)
        return OZMath.rand_range(p.first, p.last)
    # Modifier must be 0..1
    if p.is_a?(Numeric)
      return p * modifier
    elsif p.is_a?(Array)
      return 0 if p.size==0
      a = (p.size * modifier).floor
      a = OZMath.clamp(a, 0, p.size-1)
      return p[a]
    elsif p.is_a?(Range) || p.is_a?(FreeRange)
      return OZMath.lerp(modifier, p.first, p.last)
  def get_max_array(p)
    val = []
    for i in 0...p.size
      val[i] = get_max_number(p[i])
    return val
  def get_max_number(p)
    if p.is_a?(Numeric)
      return p
    elsif p.is_a?(Array)
      a = 0
      p.each {|v| a = v if a<v}
      return a
    elsif p.is_a?(Range) || p.is_a?(FreeRange)
      return p.last

class ParticleEmissorProperties
  # Global attributes
  attr_accessor :viewport
  attr_accessor :simulation_space
  attr_accessor :max_particles
  attr_accessor :duration
  attr_accessor :looping
  attr_accessor :autoplay
  attr_accessor :bitmaps
  # Emission attributes
  attr_accessor :pps #Particles Per Second
  attr_accessor :bursts #Array [[t1,n1],[t2,n2]]
  attr_accessor :shape # :circle :square
  attr_accessor :shape_a
  attr_accessor :shape_b
  attr_accessor :shape_angle #circle only, [a,b,c]
  # Particle attributes (can receive array, range, etc)
  attr_accessor :lifetime
  attr_accessor :speed
  attr_accessor :speed_modifier # :none :speed :lifetime
  attr_accessor :acceleration
  attr_accessor :acceleration_modifier # :none :speed :lifetime
  attr_accessor :size
  attr_accessor :size_modifier # :none :speed :lifetime
  attr_accessor :rotation
  attr_accessor :rotation_modifier # :none :speed :lifetime
  attr_accessor :opacity
  attr_accessor :opacity_modifier # :none :speed :lifetime
  attr_accessor :color
  attr_accessor :color_modifier # :none :speed :lifetime
  def initialize(bitmaps=[])
    @viewport = nil
    @simulation_space = :global
    @max_particles = 1000
    @duration = 200
    @looping = true
    @autoplay = true
    @pps = 24
    @bursts = []
    @shape = :circle
    @shape_a = 8
    @shape_b = 0
    @shape_angle = [0,360,0]
    @lifetime = 60
    @speed = [,1),,1)]# ??
    @speed_modifier = :none
    @acceleration = [0,0]
    @acceleration_modifier = :none
    @size = [,1.0),,1.0)]
    @size_modifier = :none
    @rotation = 2
    @rotation_modifier = :none
    @opacity =,32)
    @opacity_modifier = :lifetime
    @color = [,255,255,255),
    @color_modifier = :lifetime
    @bitmaps = bitmaps
  def get_random_bitmap
    if @bitmaps.size==0
      b =,8)
      @bitmaps[0] = b
      return b
    return @bitmaps[rand(bitmaps.size)]

class ParticleEmissor
  attr_accessor :properties
  attr_accessor :x
  attr_accessor :y
  def initialize(x, y, z,
    @particles = []
    @properties = _properties
    @playing = @properties.autoplay
    @timer = @properties.duration
    @x = x
    @y = y
    @z = z
    @fps = @pps = 0 # Particle creation control variables
  def update
    # Create control variables
    to_delete = []
    count = 0
    # Update existing particles.
    @particles.each {|p|
      if p.dead==true
        count += 1
    # Remove old particles from array
    @particles = (@particles-to_delete)
    # Playing particle effect (creates new particles if it's playing)
    return if (!@playing)
    @timer -= 1
    if @timer <= 0
      if @properties.looping
        @timer = @properties.duration
        @playing = false
    return if count > @properties.max_particles
    # Current second particles
    @fps += 1
    if @fps > Graphics.frame_rate
      @pps = @fps = 0
    expected_pps = @properties.pps * @fps / Graphics.frame_rate
    particles_to_create = expected_pps - @pps
    # TODO - Bursts
    curr_time = @properties.duration - @timer
    @properties.bursts.each { |burst|
      if burst[0]==curr_time
        burst[1].times {|n| create_new_particle(burst[2])}
    if particles_to_create > 0
      # Create particle x times
      particles_to_create.times {|n| create_new_particle(nil)}
    @pps = expected_pps
  def create_new_particle(bmp)
    return if @particles.size >= @properties.max_particles
    # Create new particles
    if bmp==nil
      b = properties.get_random_bitmap
      b = bmp
    coord = get_shape_coordinate
    p =, self, coord[0], coord[1], @viewport)
    p.z = @z
  def get_shape_coordinate
    coord = [0,0]
    case @properties.shape
    when :circle
      _ap = @properties.shape_angle
      angle = OZMath.rand_range(_ap[0], _ap[1])
      angle = (angle / _ap[2]).floor * _ap[2] if _ap[2] > 0
      radius = OZMath.rand_range(@properties.shape_a, @properties.shape_b)
      rad = OZMath.deg2rad(angle)
      coord[0] = Math.cos(rad)*radius
      coord[0] = Math.sin(rad)*radius
    when :square
      ah = @properties.shape_a/2
      bh = @properties.shape_b/2
      coord[0] = OZMath.rand_range(-ah,ah)
      coord[1] = OZMath.rand_range(-bh,bh)
    return coord
  def dispose
    @particles.each {|p| p.dispose }


You can refer to the usage in the demo inside Scene_Title, as it showcases some of the features. But basically it works as an sprite, by changing parameters and other stuff. I did however sepparate the particle emissor properties from the emitter object, as preparation for an editor.

Most basic usage:

@yourvariable =, y, z)
#At update
#At dispose

Some extra stuff I did at the demo

p =
# By default, all particles use a white autogenerated 8x8 square.
# This is how you assign custom bitmaps. Pass an array, and it will select one at random.
p.bitmaps = [RPG::Cache.picture("particle1")]
# Defining bursts.
p.bursts = [
      [100,32,RPG::Cache.picture("particle2")] #At the hundredth frame, spawns 32 particles using "particle2" as bitmap.
@particles =, 160, 600, p) #This is how you pass custom properties to an emitter object.


Afaik, none. It's an independent class.

Credits and Thanks

  • Unity, I tried ripping off as much as possible.

Author's Notes

License is Creative Commons 0. Free for use, commercial or non-commercial. You can use, share, modify it. Whatever. :^)
A lot of comments are in Spanish. Sorry! Had no time to change it. But other comments are in English just because. So there is some balance! (?)
RMXP Script Database / Re: [XP] XP Ace Tilemap
December 18, 2017, 11:19:31 pm
I just did update to the most recent version (was using the 0.32 or something like that). I'll be using this one, doing more of these "extensive tests" and keep an eye on it.

I'm still confused though, since the map actually works, it's just maybe after several teleports. I remember an issue with RGSS3's way of handling disposed bitmaps that gave errors before, but I remember that being resolved. As for files, since the map actually loads fine, just sometimes don't, I am not even sure if there is an actual problem with the map itself.

But yeah, I'll keep an eye on it. Hopefully I'll find the same bug again this week xD. Dunno how elusive it is.
RMXP Script Database / Re: [XP] XP Ace Tilemap
December 18, 2017, 11:37:34 am
Hi! Here I am, trying to report a bug.

I was just trying my game, everything worked nicely, but after some time (15mins maybe) of doing random stuff like walking teleporting, battling, the game crashed after attempting to load the next map. The error said "Failed to create bitmap". Weird thing is, it happened when I was at a town, then entered a house, did some basic stuff, then tried to get back to town and it crashed. That's just to say the map just worked before.

Here is the lines it points to.
# ** Bitmap
class Bitmap
  attr_accessor :filename
  alias set_filename_of_bitmap initialize
  def initialize(*args)
    # Associate the bitmap with the filename of the graphic; empty string otherwise
    @filename = args.size == 1 ? File.basename(args[0], '.*') : ''

Basically, it fails when loading a bitmap, still not sure which one since I haven't been able to reproduce the bug (will do if I encounter it some more times :^D).

Still, haven't tried but I'm pretty sure it's one of these weird bugs that just happen at seemingly random moments. I'll try and replicate it if I can.
Yeah, this is something EB should had made from the start. I think most of the people that start scripting do something about this issue in one way or another heh. I.e. make it based on your strength, dexterity or whatever.

So thanks for sharing. :^)
Hello there! It's me again. Uh, I just wanted to share some stuff with you guys, progress and all that :^). AND the soundtrack on Soundcloud so if someone wants to listen that there you go ma'boys.

Some unnecesary fluff
And more unnecesary fluff but it's a thing I wanted to do for some time, weapons being visible and all that just like RM2k3/FF.

See ya soon!
RMXP Script Database / Re: [XP] XP Ace Tilemap
March 09, 2017, 03:47:19 pm
Just updated my game to this, and it works like a charm (I even think it goes 1-2 frames better). Anyway anything I find I'll be sure to pester notify you.

So yeah thanks for your great work KK20 and all people involved in this.
I may think about trying this, I've played other patched games anyway such as Shin Megami Tensei and Ragnarok Online 2 when it was just being released/tested in Korea xD (ooooh I miss going through walls </3).

Now question! How similar is this one to the offline Monster Hunter? Is is similar to any of the main series or something?
I love when you people talk about these things, it's the reason why I'm in this community <3.

This feels me with determination.

Oh, just don't mind me, please continue with your conversation.
Oh, ok. I remember the Simple Mouse System from Ace had that functionality and more done. Maybe someone will make those things for MV too (it included the cursor changing depending on the kind of event and other stuff).

But anyway, KK20's link proved to help you with your problem so yay! :^D.
But what do you mean by activating events via mouse click? Doesn't MV have something like that already? Because it is intended to work in mobile, where all you have is touch-screen, and touch inputs most of the time are treated as clicks.

Do you mean click but without moving the character?

Just asking...
Projects / Games / Re: (XP) BlueSkies 2
May 29, 2016, 12:20:06 pm
Your game looks pretty, I like how things look like so clear and tidy. I don't know, there is something special going in there :^D. Also from what I can see in the screens, you give a lot of emphasis to panorama backgrounds with skies. Pretty adequate for a game with sky on its name xD.

Cheers and good luck with it. :^3
RMXP Script Database / Re: [XP] XP Ace Tilemap
May 23, 2016, 10:24:16 pm
Quite sweeeeeeeet ma' boy! <3. I love planes *gets run over by an airplane*.
Me wants this new plane thing. <3<3<3

And tilemap update. Oh my. Such delicacies. Life is such a sweet potato sometimes.
Chat / Re: What are you listening to right now?
May 20, 2016, 09:37:59 am
I've been a month already just listening to my personal hell. And Undertale music, because it saves me from hell.
Welcome! / Re: Hi all!! Starmage here!
May 20, 2016, 09:36:42 am
Welcome, and I hope you can fantasize with us-- I mean, make fantastic games. Yeah I'll stick to that.

Have a wonderful day and sprite a lot, that's the only way possible for the mastery of the pixel (?).
Welcome! / Re: Olá! :)
May 12, 2016, 10:39:07 pm
Well the staff in RMWeb is not that bad :/. Some are kind of jumpy at some specific topics but they are nice people.

Blizz on the other hand is our lord and saviour so start making some sacrifices to please his beard. His beard likes to screw with the word (when it's available).

Welcome to this place Denver. :^D
RMXP Script Database / Re: [XP] RMX-OS
May 07, 2016, 08:51:18 pm
I think you're right. RMX-OS is actually a good easy solution to put online to almost anything in RPG Maker, though that comes up with the price that the thing you made "instantly online" wasn't built to be online.

I have another idea, since RMX-OS has this thing of "first one becomes server for the map", how about making a special client that makes sure to be a map's gmaster? Basically my idea is this: a client that doesn't renders anything neither does anything, just like a dummy character (maybe even not log as a character at all). It just picks the work as gmaster and that's it. As for picking the gmaster as soon as possible, since the client always ping to see when the server is online, make it automatically log in, or even prohibit logging in until one of these special clients is on (someone could develop a script that beats "us" just to mock everyone, I guess xD).

Maybe make these clients able to be gmasters in more than one map. Assume we have 100 maps and 4 PCs. You then make each PC the gmaster of 25 maps each (or make it 20-15-30-40, maybe some maps are designed to accommodate more players than others).

It's pretty much distributing the load into several computers. And it doesn't need that much of a change as far as I know since these client-servers (?) will be just like a regular client.
General Discussion / Re: Screenshot Thread
May 05, 2016, 08:06:39 am
My favourite RPG Maker games tended to do that, including the author in some sort of way. It was so dumb but was made for jokes.
Is there a battler of you to take as a reference? I think I could think about adding a Blizzard somewhere x'D.

Some screens of my game, Drekirökr.

Need to make more maps and stuff... xD. I've been doing so much that isn't visual. Salut!
Welcome! / Re: I'm back
May 04, 2016, 09:51:54 am
Welcome back Juan! Have some cookies and cream :^D.