Script Body
#=====================================================
# Bitmap + Script Coder: Shadowtext
#=====================================================
# This is a simple script to extend the functionality of the "Bitmap" class.
# It adds two functions to the basic class, which are documented below.
#=====================================================
class Bitmap
#-----------------------------------------------------------------------------------------
# draw_bar(x,y,width,height,fill_percent[,fill_color][,back_color])
#-----------------------------------------------------------------------------------------
# Draws a simple progress bar / meter on the bitmap.
# x = The x coordinate where the bar should be drawn. (Within the Bitmap)
# y = The y coordinate where the bar should be drawn. (Within the Bitmap)
# width = The width of the bar.
# height = The height of the bar.
# fill_percent = The percentage that the bar should be filled.
# fill_color = The color of the "filled" portion of the bar.
# back_color = The color of the "empty" portion of the bar.
#-----------------------------------------------------------------------------------------
def draw_bar(x,y,width,height,fill_percent,fill_color = COLOR_BAR_FILL,back_color = COLOR_BAR_BACK)
fill_width = fill_percent * (width - 7) / 100
# Borders
self.fill_rect (x + 1, y, width - 2, height, COLOR_BAR_OUTLINE)
self.fill_rect (x, y + 1, width, height - 2, COLOR_BAR_OUTLINE)
self.fill_rect (x + 2, y + 1, width - 4, height - 2, COLOR_WHITE)
self.fill_rect (x + 1, y + 2, width - 2, height - 4, COLOR_WHITE)
# Basin
self.fill_rect (x + 3, y + 3, width - 7, height - 6, back_color)
self.fill_rect (x + 3, y + 3, fill_width, height - 6, fill_color)
# Inside Corners
self.fill_rect (x + 4, y + 3, 1, 1, COLOR_BLACK)
self.fill_rect (x + 4, y + height - 4, 1, 1, COLOR_BLACK)
self.fill_rect (x + width - 5, y + 3, 1, 1, COLOR_BLACK)
self.fill_rect (x + width - 5, y + height - 4, 1, 1, COLOR_BLACK)
# Inside Borders
self.fill_rect (x + 4, y + 2, width - 8, 1, COLOR_BLACK)
self.fill_rect (x + 4, y + height - 3, width - 8, 1, COLOR_BLACK)
self.fill_rect (x + 3, y + 4, 1, height - 8, COLOR_BLACK)
self.fill_rect (x + width - 4, y + 4, 1, height - 8, COLOR_BLACK)
end
#-----------------------------------------------------------------------------------------
# draw_text_outlined(x,y,w,h,text[,align])
#-----------------------------------------------------------------------------------------
# Draws outlined text to the bitmap.
# x = The x coordinate where the text should be drawn. (Within the Bitmap)
# y = The y coordinate where the text should be drawn. (Within the Bitmap)
# w = The width of the container block for the text.
# h = The height of the container block for the text.
# text = The text to draw.
# align = Alignment within the container block. 0 = Left, 1 = Center, 2 = Right.
#-----------------------------------------------------------------------------------------
def draw_text_outlined(x,y,w,h,text,align = 0)
color1 = self.font.color.clone
color2 = Color.new(255 - color1.red,255 - color1.green,255 - color1.blue,(color1.alpha / 2))
color3 = COLOR_CLEAR
self.font.color = color2
draw_text(x - FONT_OUTLINE_SIZE,y,w,h,text,align)
draw_text(x,y - FONT_OUTLINE_SIZE,w,h,text,align)
draw_text(x + FONT_OUTLINE_SIZE,y,w,h,text,align)
draw_text(x,y + FONT_OUTLINE_SIZE,w,h,text,align)
#self.font.color = color3
#draw_text(x,y,w,h,text,align)
self.font.color = color1
draw_text(x,y,w,h,text,align)
end
end#==============================================================================
# Console
#==============================================================================
# This module works much like the Logging module, only instead of saving to a
# file, output goes to a debugging window. The window only shows up in Debug
# mode, so launching it from RMXP it will show up, but it won't when run from
# Game.exe.
# To use the console, simply call Console::setup() from your Main script, then
# use echo(string) from any other script you want, like you would print().
#
# The Console allows for quick access to information without having to open a log
# and without bringing up a message window that halts progress, so it's perfect
# for having to track changes in a loop with many iterations. My own tests show
# no lag, so it should be all good.
#==============================================================================
module Console
attr_reader :bufferHandle
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
CONSOLE_TEXTMODE_BUFFER = 0x00000001
def Console::AllocConsole
return @apiAllocConsole.call
end
def Console::CreateConsoleScreenBuffer(dwDesiredAccess,dwShareMode,dwFlags)
return @apiCreateConsoleScreenBuffer.call(dwDesiredAccess,dwShareMode,nil,dwFlags,nil)
end
def Console::WriteConsole(lpBuffer)
hFile = @bufferHandle
return @apiWriteConsole.call(hFile,lpBuffer,lpBuffer.size,0,0)
end
def Console::SetConsoleActiveScreenBuffer(hScreenBuffer)
return @apiSetConsoleActiveScreenBuffer.call(hScreenBuffer)
end
def Console::SetConsoleTitle(title)
return @apiSetConsoleTitle.call(title)
end
def self.setup
unless $DEBUG
return
end
@apiAllocConsole = Win32API.new("kernel32","AllocConsole","","l")
@apiCreateConsoleScreenBuffer = Win32API.new("kernel32","CreateConsoleScreenBuffer",['l','l','p','l','p'],"l")
@apiSetConsoleActiveScreenBuffer = Win32API.new("kernel32","SetConsoleActiveScreenBuffer","l","s")
@apiWriteConsole = Win32API.new("kernel32","WriteConsole","lpnnn","S")
@apiSetConsoleTitle = Win32API.new("kernel32","SetConsoleTitle","p","s")
access = (GENERIC_READ | GENERIC_WRITE)
sharemode = (FILE_SHARE_READ | FILE_SHARE_WRITE)
returnCode = AllocConsole()
@bufferHandle = CreateConsoleScreenBuffer(access,sharemode,CONSOLE_TEXTMODE_BUFFER)
f = File.open("Game.ini")
lines = f.readlines()
s = lines[3]
len = s.size
title = (s[6,len - 7])
SetConsoleTitle("Debug Console -- #{title}")
echo "#{title} Output Window\n"
echo "-------------------------------\n"
echo "If you are seeing this window, you are running\n"
echo "#{title} in Debug Mode. This means\n"
echo "that you're either playing a Debug Version, or\n"
echo "you are playing from within RPG Maker XP.\n"
echo "\n"
echo "Closing this window will close the game. If \n"
echo "you want to get rid of this window, run the\n"
echo "program from the Shell, or download a Release\n"
echo "version.\n"
echo "\n"
echo "Gameplay will be paused while the console has\n"
echo "focus. To resume playing, switch to the Game\n"
echo "Window.\n"
echo "-------------------------------\n"
echo "Debug Ouput:\n"
echo "-------------------------------\n\n"
SetConsoleActiveScreenBuffer(@bufferHandle)
end
def self.get_input
loop do
poo = $stdin
if poo[poo.size - 1] == "\n"
break
end
end
echo poo
end
end
module Kernel
def echo(string)
unless $DEBUG
return
end
Console::WriteConsole(string)
end
end#======================================================
# Geometry module ver 1.0 |
#======================================================
# By: Shadowtext (shadowtext@gmail.com) |
# This module is designed to do some geometric |
# functions, including drawing lines and shapes for |
# whatever crazy purpose you need to draw lines and |
# shapes for. It also draws text balloons. Yay. |
#======================================================
module Geometry
#sqr: Squares the provided value. I'm surprised they didn't have
#a squaring or exponent raising function to begin with. I tried
#just redoing Numeric to include "^," but I couldn't figure out
#how to get the value of numeric. Probably something to do with
#recievers or something else that I'm too tired to figure out
#at the moment.
def self.sqr(i)
return i * i
end
#quad: provide it with a, b, and c, and it'll do the quadratic
#equation for you. Y'know, I don't think I actually ended up
#using this function, even though the early versions of a lot
#of my classes had to use 'em. Anyway, a is what you multiply
#x^2 by, b is what you multiply x by, and c is everything else.
#If you don't know the quadratic equation, you probably shouldn't
#be using this function anyway, though.
def self.quad(a,b,c)
x = [2]
x[0] = (-b) + Math.sqrt(Geometry.sqr(b) - 4 * a * c)
x[0] /= (2 * a)
x[1] = (-b) - Math.sqrt(Geometry.sqr(b) - 4 * a * c)
x[1] /= (2 * a)
return x
end
#====================================================
# Point class |
#====================================================
# It's like a Rect object, only with only x,y |
# values. Anyway, you declare it as Point.new(x,y) |
# You can find the distance between two points just |
# by subtracting them, like d = p1 - p2. To change |
# the point's location, use the move! function. |
# Finally, to_s turns the thing into a string in the|
# format of "(x,y)". Like good old Cartesian Coor- |
# dinates. |
#====================================================
class Point
def initialize(x,y)
@ax = x
@ay = y
end
def -(i)
return Math.sqrt(Geometry.sqr(i.x - x) + Geometry.sqr(i.y - y))
end
def x
return @ax
end
def y
return @ay
end
def move(mx,my)
return Point.new(@ax += mx, @ay += my)
end
def move!(mx,my)
@ax += mx
@ay += my
end
def to_s
return "(" + @ax.to_s + "," + @ay.to_s + ")"
end
def is_on?(line)
unless line.is_a? Line
print "Type Mismatch in module Geometry.\nPoint.is_on? was passed a variable of type #{line.class}."
return false
end
if self.x < line.smallx
return false
end
if self.x > line.bigx
return false
end
if self.y < line.smally
return false
end
if self.y > line.bigy
return false
end
if line.slope != false
targ_y = line.get_y(self.x)
bool = (self.y >= (targ_y - 1)) and (self.y <= (targ_y + 1))
else
targ_x = line.get_x(self.y)
bool = (self.x >= (targ_x - 1)) and (self.x <= (targ_x + 1))
end
return bool
end
end
#====================================================
# Line class |
#====================================================
# Declare it with Line.new(x1,x2,y1,y2). I know, it |
# should probably declare with points, or at least |
# as x1,y1,x2,y2. But I did it this way, and I'd |
# have to go and change all my declarations if I |
# changed it now. |
# width is the linewidth when drawing, and color is |
# the color that it's drawn in. smallx, smally, bigx|
# and bigy are the smallest x, smallest y, biggest x|
# and biggest y values for the line respectively. |
# Length is the actual distance between point 1 and |
# point 2, and find_point will find a point on the |
# the line that is the given percent (* 100) of the |
# total length away from the starting point, point |
# 1. |
# crosses and intersects will compare it to |
# another line and find if it intersects. |
# slope is the change in y divided by the change in |
# x, which you should know from geography class. |
# yint is where the thing touches when x is zero. |
# Finally, if you provide the function draw(bmp) |
# with a bitmap, it'll draw the line to the bitmap. |
#====================================================
class Line
attr_reader :x1
attr_reader :x2
attr_reader :y1
attr_reader :y2
attr_accessor :width
attr_accessor :color
def initialize(x1, x2, y1, y2)
@x1 = x1
@x2 = x2
@y1 = y1
@y2 = y2
@color = Color.new(0,0,0,255)
@width = 2
end
def to_s
return "(" + @x1.to_s + "," + @y1.to_s + "); (" + @x2.to_s + "," + @y2.to_s + ")\n\tSlope=" + slope.to_s + "\n\tY-Int=" + yint.to_s
end
def get_x(y)
if slope != false
x = (y - yint) / slope
return x
else
return smallx
end
end
def get_y(x)
if slope == false
return false
end
y = slope * x + yint
if y < smally or y > smally
return false
end
return y
end
def smallx
if @x1 < @x2
return @x1
else
return @x2
end
end
def smally
if @y1 < @y2
return @y1
else
return @y2
end
end
def bigx
if @x1 > @x2
return @x1
else
return @x2
end
end
def bigy
if @y1 > @y2
return @y1
else
return @y2
end
end
def length
changey = @y1 - @y2
changex = @x1 - @x2
rad = (changey * changey) + (changex * changex)
val = Math.sqrt(rad)
return val
end
def find_point(distance)
# Distance should be the percentage from the starting point
# that the found point should be.
draw_distance = distance * length / 100.0
if slope == false
x = @x1
if @y1 - draw_distance < smally
return Point.new(x,(@y1 + draw_distance).to_i)
else
return Point.new(x,(@y1 - draw_distance).to_i)
end
end
if slope == 0
x = @x1 + draw_distance
y = @y1
return Point.new(x,y)
end
a = Point.new(x1,y2)
b = Point.new(x2,y2)
c = Point.new(x1,x1)
ab = a - b
bc = b - c
ca = a - c
cp = draw_distance
dp = ab * cp / bc
dc = ca * cp / bc
if c.x == smallx
x = c.x + dp
else
x = c.x - dp
end
if c.y == smally
y = c.y + dc
else
y = c.y - dc
end
p = Point.new(x,y)
return p
end
def slope
dify = (@y1 - @y2) * 1.0
difx = (@x1 - @x2) * 1.0
if difx == 0
return false
end
return dify / difx
end
def yint
if slope == false
return false
else
return @y1 - slope * @x1
end
end
def crosses(line,tolerance = 1,check_parallels = false)
return intersects(line,tolerance)
end
def check_parallels(line2)
line1 = self
x1 = line1.smallx
x2 = line2.smallx
x3 = line1.bigx
x4 = line2.bigx
bool = false
print "Point Validity" +
"\nx1=#{line1.get_y(x1) != false}" +
"\nx2=#{line2.get_y(x2) != false}" +
"\nx3=#{line1.get_y(x3) != false}" +
"\nx4=#{line2.get_y(x4) != false}" +
bool |= line1.get_y(x1) != false
bool |= line2.get_y(x2) != false
bool |= line1.get_y(x3) != false
bool |= line2.get_y(x4) != false
return bool
end
def intersects(line2,tolerance = 1,check_parallels = false)
line1 = self
unless line1.is_a? Line and line2.is_a? Line
return nil
end
if line1.slope == line2.slope
if check_parallels == true
return check_parallels(line2)
end
else
return nil
end
if line1.slope == false
x = line1.x1
y = line2.get_y(x)
elsif line2.slope == false
x = line2.x1
y = line1.get_y(x)
else
x = (line2.yint - line1.yint) / (line1.slope - line2.slope)
y = line1.get_y(x)
end
if x < (line1.smallx - tolerance) or x < (line2.smallx - tolerance)
return nil
end
if x > (line1.bigx + tolerance) or x > (line2.bigx + tolerance)
return nil
end
#print Point.new(x,y).to_s +
# "\n\nLine1" +
# "\n\tSmall\tBig" +
# "\nX=\t#{line1.smallx}\t#{line1.bigx}" +
# "\nY=\t#{line1.smally}\t#{line1.bigy}" +
# "\n\nLine 2" +
# "\n\tSmall\tBig" +
# "\nX=\t#{line2.smallx}\t#{line2.bigx}" +
# "\nY=\t#{line2.smally}\t#{line2.bigy}"
#if y < (line1.smally - tolerance) or y < (line2.smallx - tolerance)
# return nil
#end
#if y > (line1.bigy + tolerance) or y > (line2.bigy + tolerance)
# return nil
#end
return Point.new(x,y)
end
def draw(bitmap)
if slope == false
bitmap.fill_rect smallx.round, smally.round, @width, bigy.round - smally.round, @color
return
end
for x in smallx..bigx
y = (((slope * x) + yint) + 0.5).to_i
height = ([slope,1].max) * @width
while y + height > (bigy + @width)
height -= 1
end
bitmap.fill_rect x - (@width / 2), y - (@width / 2), @width, height, @color
end
end
end
#====================================================
# Polygon class |
#====================================================
# The Polygon class is built from an array of points|
# that you provide during initialization. 3 points |
# is the minumum that can make up a polygon. Anyway,|
# It'll build the polygon for you, and even draw it |
# and fill it in. The bounding box is a Rect |
# produced during initialization that holds every |
# point the polygon will have in it. linewidth sets |
# how big the lines will be drawn, and linecolor and|
# fillcolor set what color your lines and fills |
# should be. The boolean fill, off by default, tells|
# the draw function to fill in the Polygon. Oh, and |
# the draw function draws to a provided bitmap. |
# Whee.
#====================================================
class Polygon
attr_reader :points
attr_reader :lines
attr_reader :linecolor
attr_accessor :fill
attr_accessor :fillcolor
attr_reader :linewidth
def initialize(points)
unless points.size > 2
return nil
end
@fill = false
@linecolor = Color.new(0,0,0,255)
@fillcolor = Color.new(0,0,0,255)
@linewidth = 2
@points = points
lines = []
for i in 0...points.size
point = points[i]
unless point == points.last
nextpoint = points[i + 1]
else
nextpoint = points.first
end
unless point.is_a? Point and point.x and point.y
return nil
end
unless nextpoint.is_a? Point and nextpoint.x and nextpoint.y
return nil
end
lines.push Line.new(point.x, nextpoint.x,point.y, nextpoint.y)
end
@lines = lines
define_box
end
def linecolor=(color)
@linecolor = color
for i in @lines
i.color = color
end
end
def linewidth=(width)
@linewidth = width
for i in @lines
i.width = width
end
end
def define_box
smallx = 1024
smally = 1024
bigx = 0
bigy = 0
for i in @points
if i.x > bigx
bigx = i.x
end
if i.x < smallx
smallx = i.x
end
if i.y > bigy
bigy = i.y
end
if i.y < smally
smally = i.y
end
end
smallx -= linewidth
smally -= linewidth
bigx += linewidth
bigy += linewidth
width = bigx - smallx
height = bigy - smally
@bounding_box = Rect.new(smallx, smally, width, height)
end
def scanline(y, bmp)
test = Line.new(@bounding_box.x,@bounding_box.x + @bounding_box.width,y,y)
x_points = []
x_points.push Point.new(@bounding_box.x,y)
x_points.push Point.new(@bounding_box.x + @bounding_box.width,y)
for i in @lines
poo = i.crosses test
#unless x_points.include? poo
x_points.push poo if poo
#end
end
x_points.uniq!
x_points.sort! {|a,b| a.x <=> b.x}
poo = x_points.clone
if x_points.size > 4
for i in 0...x_points.size
thispoint = x_points[i]
if thispoint == x_points.last or i == 0
next
end
nextpoint = x_points[i + 1]
if nextpoint == x_points.last
next
end
if (thispoint - nextpoint) < 4
poo.slice! i
end
end
end
x_points = poo
if x_points.size <= 3
return
end
for i in 0...x_points.size
if i % 2 == 1
thispoint = x_points[i]
unless x_points[i] == x_points.last
nextpoint = x_points[i + 1]
else
next
end
bmp.fill_rect thispoint.x,
y,
nextpoint.x - thispoint.x,
1,
@fillcolor
end
end
end
def draw bmp
if @fill == true
for y in @bounding_box.y...(@bounding_box.y + @bounding_box.height)
scanline(y,bmp)
end
end
for i in @lines
i.draw bmp
end
@bitmap = bmp
end
def to_s
return @points.join("\n")
end
end
#====================================================
# Ellipse class |
#====================================================
# One of those round sideways oval thingies. Anyway,|
# give it a center point, and two axes (the width |
# and height, really), and it'll draw you up an |
# ellipse nice and proper. Just tell it to draw and |
# give it a bitmap to draw to, and it'll do it. |
#====================================================
class Ellipse
attr_reader :semimajor
attr_reader :semiminor
attr_accessor :linewidth
attr_accessor :linecolor
attr_accessor :fill
attr_accessor :fillcolor
def initialize(center, axis1, axis2)
if axis1 > axis2
@majoraxis = axis1
@minoraxis = axis2
else
@majoraxis = axis2
@minoraxis = axis1
end
@semimajor = @majoraxis / 2
@semiminor = @minoraxis / 2
@center = center
c = Math.sqrt(Geometry.sqr(@semimajor) - Geometry.sqr(@semiminor))
x1 = center.x - c.round
x2 = center.x + c.round
y = center.y
@focus1 = Point.new(x1,y)
@focus2 = Point.new(x2,y)
@linewidth = 2
@linecolor = Color.new(0,0,0,255)
@fillcolor = Color.new(255,255,255,255)
@fill = false
@semimajor = semimajor
@semiminor = semiminor
end
def get_ys(x)
i = @center.x
j = @center.y
maj = @semimajor
min = @semiminor
ys = []
a2 = Geometry.sqr(maj)
b2 = Geometry.sqr(min)
x2 = Geometry.sqr(x - i)
foo = ((a2 * b2) - (b2 * x2)) / a2
val = Math.sqrt(foo)
return [nil,nil] if val.nan?
ys[0] = (j - val).round
ys[1] = (j + val).round
return ys
end
def get_xs(y)
i = @center.x
j = @center.y
maj = @semimajor
min = @semiminor
a2 = Geometry.sqr(maj)
b2 = Geometry.sqr(min)
y2 = Geometry.sqr(y - j)
foo = ((a2 * b2) - (a2 * y2)) / b2
val = Math.sqrt(foo)
return [nil,nil] if val.nan?
xs = []
xs[0] = (i - val).round
xs[1] = (i + val).round
return xs
end
def smallx
return get_xs(@center.y).min.round
end
def bigx
return get_xs(@center.y).max.round
end
def smally
return get_ys(@center.x).min.round
end
def bigy
return get_ys(@center.x).max.round
end
def draw(bmp)
if @fill == true
for i in smallx..bigx
ys = get_ys(i)
if ys[0] and ys[1]
h = ys.max - ys.min
bmp.fill_rect i,ys.min,1,h,@fillcolor
end
end
end
for i in smallx..bigx
ys = get_ys(i)
if ys[0]
bmp.fill_rect i - (@linewidth / 2),
ys.min - (@linewidth / 2),
@linewidth,
@linewidth,
@linecolor
end
if ys[1]
bmp.fill_rect i - (@linewidth / 2),
ys.max - (@linewidth / 2),
@linewidth,
@linewidth,
@linecolor
end
end
for i in smally..bigy
xs = get_xs(i)
if xs[0]
bmp.fill_rect xs[0] - (@linewidth / 2),
i - (@linewidth / 2),
@linewidth,
@linewidth,
@linecolor
end
if xs[1]
bmp.fill_rect xs[1] - (@linewidth / 2),
i - (@linewidth / 2),
@linewidth,
@linewidth,
@linecolor
end
end
end
end
end#==============================================================================
# Logging
#==============================================================================
# This module allows for quick logging of any data the designer wants. It is worked into
# the Kernel, and therefore after this script has been loaded, the designer has very little
# work for himself.
#
# Simply use the line "log(string)" anywhere in your code, and the string you give it will be logged
# to the logfile. You can also use "log_s(title,string)" to automatically draw a "section" in a log, which is one
# that is set off by its title an ascii box before drawing the actual text.string you give it.
#
# The file will bear the name of your project as defined in "Game.ini." with the spaces removed, and the
# extension ".log." So if you were working on "Taret Blade," your logfile would be "taretblade.log"
#
# Use this feature when "print" would not be feasible, such as when you have to log a lot of data at once,
# or check something from within a loop or iterator.
#==============================================================================
module Logging
attr_reader :separator
attr_reader :line
def self.setup
if $DEBUG
@separator = "=============================================================================="
@line = "------------------------------------------------------------------------------"
f = File.open("Game.ini")
lines = f.readlines()
s = (lines[3].gsub(/( )/,"")).downcase
len = s.size
title = (s[6,len - 7]) + ".log"
@logstream = File.new(title,"w+")
chronos = Time.new
@logstream.puts @separator,
"*** BEGIN LOG ***",
@line,
chronos.to_s,
@separator
end
end
def self.write(txt, leading_line = true)
if $DEBUG
@logstream.puts "" if leading_line
if txt.is_a?(Array)
for i in txt
if i.is_a? String
if i == "="
@logstream.puts @separator
elsif i == "-"
@logstream.puts @line
else
@logstream.puts i
end
else
print "Error: Logging module can only write strings or arrays of strings."
end
end
return
elsif txt.is_a? String
if txt == "="
@logstream.puts @separator
elsif txt == "-"
@logstream.puts @line
else
@logstream.puts txt
end
return
else
print "Error: Logging module can only write strings or arrays of strings."
return
end
end
end
def self.write_section(title,txt)
@logstream.puts ""
@logstream.puts @separator
@logstream.puts title
@logstream.puts @line
if txt.is_a?(Array)
for i in txt
if i.is_a? String
if i == "="
@logstream.puts @separator
elsif i == "-"
@logstream.puts @line
else
@logstream.puts i
end
else
print "Error: Logging module can only write strings or arrays of strings."
end
return
end
elsif txt.is_a?(String)
if txt == "="
@logstream.puts @separator
elsif txt == "-"
@logstream.puts @line
else
@logstream.puts txt
end
return
else
print "Error: Logging module can only write strings or arrays of strings."
return
end
end
def self.close
if $DEBUG
chronos = Time.new
if @logstream
@logstream.puts @separator,
"*** END LOG ***",
@line,
chronos.to_s,
@separator
end
end
end
end
module Kernel
def log(txt, lead = true)
Logging.write(txt, lead)
end
def log_s(title, txt)
Logging.write_section(title, txt)
end
def log_table(table)
s = "Table Contents:"
for y in 0...table.ysize
s += "\n\t"
for x in 0...table.xsize
s += "#{table[x,y]}, "
end
end
log s
end
end#==============================================================================
# ** Main+ Script by: Shadowtext
#------------------------------------------------------------------------------
# This is a modified "Main" script that allows you to use ".rb" files as external RGSS
# scripts. You can download some from my site, as well as a few other sites around
# the net. (Most of the others I've seen doing this are Japanese, though).
#
# You can distribute your own scripts easier this way. But keep in mind THIS script
# can't really be "required," so instead of downloading it, you should copy and paste
# it into your "Main" script.
#==============================================================================
begin
# Prepare for transition
Graphics.freeze
# The next three lines will allow you to use the "require" statement
# to access any ".rb" file stored in your project's root directory, or the
# "scripts" subdirectory of the project's root directory. Note that you
# must create the "scripts" directory manually.
$:.clear
$:.push "."
$:.push ".//scripts"
# The following require statements are here as examples, and should be commented
# out if you have not downloaded or do not plan to use the scripts available on this site.
require "bitmap+.rb"
require "geometry.rb"
require "string_table.rb"
require "textbubble.rb"
$scene = Scene_Title.new
# Call main method as long as $scene is effective
while $scene != nil
$scene.main
end
# Fade out
Graphics.transition(20)
rescue Errno::ENOENT
# Supplement Errno::ENOENT exception
# If unable to open file, display message and end
filename = $!.message.sub("No such file or directory - ", "")
print("Unable to find file #{filename}.")
end#=====================================================
# String Table Script Coder: Shadowtext
#=====================================================
# This is a script to use string tables rather than putting in text directly
# within RMXP. The main purpose for using String Tables instead of
# just hard-coding the text is that String Tables make translation or
# dialogue editting much easier.
#
# Admittedly, as few projects get finished as do, translation into other
# languages might seem silly, but here it is anyway.
#
# Also, as mentioned earlier, it can make dialogue editting easier, in that
# you will not have to find the proper events in which to change the
# dialogue, instead just editting it within the string table.
#
#=====================================================
# USING THE STRING TABLE CLASS
#=====================================================
# In the "main" script, add a declaration of "$data_strings = Data_Strings.new"
#
# Now, any time you want to get a string from the table, just do "$data_strings[index]",
# where index is the line (starting from zero) where the string can be found in
# the table.
#
# You can change the language with $data_strings.lang_id. This should be the
# line number of the language as it appears in Languages.dat.
#
#=====================================================
# MAKING THE STRING TABLE AND LANGUAGES.DAT FILE:
#=====================================================
# The string table class uses two or more files. The first is a file in the
# "/data/" directory of the project named "Languages.dat." This
# language file is a text file, with each line representing one of the
# languages that the string tables are available in.
# Each line should have the name of the language, followed by a tab,
# and then the font that the language should be displayed in within
# RMXP.
# The other type of file is the string table itself. This will be a text file
# named "(*).txtdata", where (*) is the name of the language named in
# Languages.dat
#
# The format of a string table is very simple. Each line (the first line is
# considered #0) is a string entry.It starts with the name of the speaker,
# which is followed by a tab, and then has the text for the entry.
#
#=====================================================
# USEFUL FUNCTIONS AND PROPERTIES
#=====================================================
# $data_strings.language - the name of the active language.
# $data_strings.font - the name of the font for the currently active language.
#
# $data_strings[index].to_s - returns the entry as a string. Change the constants below to
# alter how .to_s behaves.
# $data_strings[index].speaker - returns a string containing the speaker's name for this entry.
# $data_strings[index].text - returns a string containing the text for this entry.
#
#=====================================================
SPEAKER_MOD = "\C[1]" # The string to preface the speaker's name with
# in the function "to_s()"
SPEAKER_UNMOD = "\C[0] -" # The string to end the speaker's name with
# in the function "to_s()"
SHOW_SPEAKER_NAME = true # Sets whether or not the speaker's name is displayed
# in the function "to_s()"
class Data_Strings
attr_reader :data
attr_reader :lang_id
def initialize()
@data = []
langfil = File.new("data/Languages.dat","r")
@fonts = []
@languages = []
for i in langfil.readlines
str = i.slice!(/\t[\w\W]*/)
len = str.size - 1
@fonts.push str[1,len]
@languages.push i
end
@lang_id = 0
langfil.close
end
def language
return @languages[@lang_id]
end
def font
return @fonts[@lang_id]
end
def lang_id=(value)
@lang_id = value
$fontface = self.font
end
def [](index)
unless @data[index].is_a? StringEntry
@data[index] = StringEntry.new(index,self.language)
end
if @data[index].language != self.language
@data[index] = StringEntry.new(index,self.language)
end
return @data[index]
end
end
class StringEntry
attr_reader :speaker
attr_reader :text
attr_reader :index
attr_reader :language
def initialize(index,language)
@index = index
@language = language
get_data()
end
def get_data()
strfile = File.new("data/#{@language}.txtdata","r")
str = strfile.readlines[@index]
@text = str.slice!(/\t[\w\W]*/)
len = @text.size - 1
@text = @text[1,len][0,len - 1]
@speaker = str
strfile.close
end
def to_s()
if @speaker != ""
if SHOW_SPEAKER_NAME == true
return "#{SPEAKER_MOD}#{@speaker}#{SPEAKER_UNMOD} -\n\"#{@text}\""
else
return "#{@text}\""
else
return "#{@text}\""
end
end#======================================================
# Message Bubble Sript ver 0.8 |
#======================================================
# By: Shadowtext (journeyman.shadowtext@gmail.com) |
# |
# This script is designed to draw message bubbles in |
# RPG Maker XP. It requires the Geometry Module. |
#======================================================
# NOTE: Uncomment the "require" statement below if you have set up RMXP to
# work with "require" statements. If not, simply make sure you've copies the geometry
# script into your project.
# require "geometry.rb"
class Spriteset_Map
def bubble_viewport
$bubble_viewport = @viewport1
return @viewport1
end
end
class BubbleHandler
attr_accessor :sprite
attr_accessor :bubble
attr_accessor :text_queue
attr_accessor :speaker_queue
def initialize(viewport = $bubble_viewport)
@sprite = Sprite.new(viewport)
@sprite.bitmap = Bitmap.new(640,480)
@sprite.z = 99999
@text_queue = []
@speaker_queue = []
end
def say(name,text)
if $game_temp.message_window_showing
return
end
unless get_character_by_name(name)
p 'Character "' + name + '" does not exist on this map.'
return
end
$game_temp.message_window_showing = true
@text_queue.push text
@speaker_queue.push get_character_by_name(name)
process_messages
update
end
def process_messages
if @text_queue.first
unless @bubble
@sprite.bitmap.clear
speaker = @speaker_queue.shift
text = @text_queue.shift
@bubble = Geometry::Balloon.new(speaker.x * 32,speaker.y * 32,text)
@bubble.draw @sprite.bitmap
end
end
end
def get_character_by_name(name)
for i in $game_map.events.keys.sort
if $game_map.events[i].name == name
return $game_map.events[i]
end
end
return nil
end
def dispose
@sprite.bitmap.dispose
@sprite = nil
$game_temp.message_window_showing = false
end
def update
process_messages
if @bubble
@sprite.visible = true
@sprite.update
$game_temp.message_window_showing = true
else
@sprite.visible = false
$game_temp.message_window_showing = false
return
end
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
$game_map.need_refresh = true
@bubble = nil
end
end
end
module Geometry
#====================================================
# Balloon class |
#====================================================
# It's a special kind of Ellipse. It draws a comic- |
# style speech balloon. You tell it where the |
# speaker is, and tell it what ti say, and it'll do |
# the rest. It's in format Ellipse.new(x,y,text). |
# If text is provided as an array, it'll do a multi-|
# line message, too. |
# Now, it assumes your speaker is the normal size |
# of RTP sprites, so the actual spacing might be a |
# little off if you're having something else speak. |
# Shouldn't be too bad, and you can just change the |
# x a little if that becomes the case, yeah? |
# Treat it the same way you would an ellipse once it|
# has been defined, and draw it the same way and |
# all.
#====================================================
class Balloon < Ellipse
def initialize(speaker_x,speaker_y,text)
@text = text
test = Bitmap.new(640,480)
test.font.name = MESSAGE_FONT
test.font.size = MESSAGE_SIZE
test.font.color = MESSAGE_COLOR
lines = 0
maxwidth = 0
if text.is_a? Array
for i in text
lines += 1
curwid = test.text_size(i).width
hi = test.text_size(i).height
if curwid > maxwidth
maxwidth = curwid
end
end
end
r = Rect.new(0,0,maxwidth,lines * hi)
test.dispose
test = nil
@width = r.width + 32
@height = r.height + 24
@maj = Math.sqrt(Geometry.sqr(@width) + Geometry.sqr(@height)).abs
if speaker_x < (@maj / 2).round
@x = 0
elsif speaker_x > (640 - @maj.round)
@x = 640 - @maj.round
else
@x = speaker_x - (@maj / 2).round
end
if speaker_y < (20 + @height)
@y = speaker_y + 52
tail_y = @y + 36
ty = @y + 8
else
@y = speaker_y - 20 - @height
tail_y = @y + (@height - 16)
ty = @y + 8
end
tail_x = @x + (@maj / 4)
cx = @x + (@width / 2)
cy = @y + (@height / 2)
center = Point.new(cx,cy)
super(center,@maj,@height)
if cx < speaker_x
speaker_x -= 16
else
speaker_x += 16
end
@speaker_p = Point.new(speaker_x,speaker_y)
@tail_p = Point.new(tail_x,tail_y)
tx = @x + ((@maj - @width) / 2)
@text_rect = Rect.new(tx,ty,@width - 8,@height - 8)
@linewidth = 2
@linecolor = Color.new(0,0,0,255)
@fillcolor = Color.new(255,255,255,255)
@fill = true
end
def draw_text bmp
bmp.font.name = MESSAGE_FONT
bmp.font.size = MESSAGE_SIZE
bmp.font.color = MESSAGE_COLOR
if @text.is_a? Array
for i in 0...@text.size
str = @text[i]
hi = bmp.text_size(str).height
bmp.draw_text @text_rect.x,@text_rect.y + (hi * i),@text_rect.width,hi,str,1
end
else
bmp.draw_text @text_rect.x,@text_rect.y,@text_rect.width,@text_rect.height,@text,1
end
end
def draw_tail(bmp)
more = @tail_p.x.round + 20
less = @tail_p.x.round - 10
if @tail_p.y == 36
p1 = Point.new(@speaker_p.x + 16,@speaker_p.y + 4)
p2y = @y + 40
p3y = @y + 40
else
p1 = Point.new(@speaker_p.x + 16,@speaker_p.y - 4)
p2y = @y + @height - 4
p3y = @y + @height - 4
end
p2 = Point.new((more),p2y)
p3 = Point.new((less),p3y)
l1 = Line.new(p2.x,p1.x,p2.y,p1.y)
l2 = Line.new(p3.x,p1.x,p3.y,p1.y)
l1.color = @linecolor
l2.color = @linecolor
l1.width = @linewidth
l2.width = @linewidth
sml = [l1.x1,l1.x2,l2.x1,l2.x2].min
big = [l1.x1,l1.x2,l2.x1,l2.x2].max
for i in sml..big
line = [l1.get_y(i),l2.get_y(i)]
h = line.max - line.min
bmp.fill_rect i,line.min,1,h,@fillcolor
end
l1.draw bmp
l2.draw bmp
end
def draw bmp
super
draw_tail bmp
draw_text bmp
end
end
endThe scripts on this page are Ruby-based RGSS code for use in RPG Maker XP.
To view a script, click on its name on the list of scripts at the right. To download, click its name above the code window.