[XP][VX] ATB Engine [Meant for Scripters]

Started by fugibo, October 16, 2008, 11:10:39 pm

Previous topic - Next topic

fugibo

October 16, 2008, 11:10:39 pm Last Edit: October 14, 2009, 10:14:45 pm by Longfellow
ATB Engine Script
Authors: Longfellow
Version: 1.00
Type: Battle System Component
Key Term: Scripting Tool



Introduction

This is a script utility to simplify the construction of ATB battle systems. Use it if you want.


Features


  • Simple API, very easy to use

  • Powerful, makes full use of the Object-Oriented paradigm

  • Completely stand-alone, other than the fact that it does nothing on its own




Screenshots
n/a


Script

This script is for scripters only, and thus I needn't tell you where it should go:
Spoiler: ShowHide

#============================================================================================
# ** ATB
#============================================================================================
module ATB

#========================================================================================
# * Group
#----------------------------------------------------------------------------------------
# Group is a simple subclass of Array, meant to be used to hold clients and
# update them easily. Can also be overwritten to alter methods such as modifier,
# which allows for much more flexible control.
#========================================================================================
class Group < Array
#------------------------------------------------------------------------------------
# modifier
#------------------------------------------------------------------------------------
def modifier
return 1.0
end

#------------------------------------------------------------------------------------
# update
#------------------------------------------------------------------------------------
def update(mod = 1.0)
self.each do |c|
c.update self.modifier * mod
end
end
end

#========================================================================================
# * Client
#----------------------------------------------------------------------------------------
# This is a custom-written class that can be used both on its own and as a
# a superclass for more specialized client classes. It holds data on ATB state
# and the callback that should be called when the client's ATB bar has filled.
#========================================================================================
class Client
attr_accessor :rate, :progress, :callback
#------------------------------------------------------------------------------------
# initialize(rate)
#------------------------------------------------------------------------------------
def initialize rate
@rate = rate
@progress = 0
@callback = Proc.new
end

#------------------------------------------------------------------------------------
# modifier
# - This method is called by Client#update to dynamically generate
# the rate modifier for the client.
# - This can be overwritten by subclasses to allow for interesting effects,
# i.e. lowering the speed of a character when their HP/MP is low, etc
# - Defaults to simply returning 1.0.
#------------------------------------------------------------------------------------
def modifier
return 1.0
end

#------------------------------------------------------------------------------------
# variance
# - This method is called by Client#upate to dynamically generate the
# amount of variance for the ATB update.
# - This can be overwritten by subclasses to allow for interesting effects,
# i.e. significantly boosting the maximum variance for actors with high luck
# - Defaults to adding or subtracting up to 1 TP from the client.
#------------------------------------------------------------------------------------
def variance
return (rand(21) - 10) / 10
end

#------------------------------------------------------------------------------------
# update
#------------------------------------------------------------------------------------
def update mod = 1.0
@progress += @rate * self.modifier * mod
@progress += self.variance

if @progress >= 100
@callback.call self
@progress = 0
end
end
end

end



Instructions

How to use this script: ShowHide

This scriptlet has a single function: Simplify the "Active Time" part of "Active Time Battle." To achieve this, it uses two classes: ATB::Group, and ATB::Client.

ATB::Group is a subclass of Array that allows for updating of held clients and has support for advanced subclassing tricks (namely, overwriting ATB::Group#modifier to dynamically change the rate at which clients update), and you use it exactly the same as Array except for the presence of Group#update, which you call every time you want to update the clients in the group.

ATB::Client is a custom class I wrote that holds data on an ATB "client," which is one of the battlers or actions involved in the ATB that has something to do and a rate at which it prepares to do it. To create one, you call ATB::Client.new with one argument, which is the rate that it should prepare at in percentage. In addition, you pass a block that takes the client as an argument. This block is called when the client finishes preparing.

client = ATB::Client.new(1.0) do |client|
 client.rate = 0 # Client stops doing things when it does the first thing
end


When creating your ATB, you will simply use these two classes to handle the ATB interactions - create groups and clients for your enemies and actors, and update them accordingly.



Compatibility

Unless you declared an ATB constant somewhere, it'll be fine.


Credits and Thanks


  • Blizzard, for being Blizzard

  • Willy Wonka, for his amazing taffy




Author's Notes

n/a

Blizzard

Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

fugibo

...you know it's only for the ATB engine, no actual Battle System code, right?

but I do like this part:
(@count = 0 ; @progress += 1) if @count >= @rate.round

Blizzard

... -_- I just noticed. I thought this would be enough to add into the editor plus a few lines of code and voila, there goes a new ATB.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

fugibo

This can still reduce the code for one quite a bit.

Sorry I'm a dissappointment, Blizz :(

Blizzard

No, not at all. You created an engine, this isn't "nothing". That means you had to consider and plan in advance. You had to analyze the system and how it works in order to create a versatile piece of code that is supposed to work with "anything". Show me another scripter who has done the same and you'll know that you found an equal. You will find out that only the "better" scripters have done or are able to do something like this.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

fugibo

That's what happens to you after two years of constantly modding Ubuntutu.

Sally


Juan

Dropbox Who need luck when you can make your own.
3ds Friend code: ShowHide
 4468 1422  6617

KRoP

Neat.  I'm certain someone will find good use for it.

Aqua

I wish I understood this more to make my own ATB... ;_____;

fugibo

October 14, 2009, 08:53:22 pm #11 Last Edit: October 14, 2009, 09:04:14 pm by Longfellow
Quote from: Aqua on October 14, 2009, 06:46:24 pm
I wish I understood this more to make my own ATB... ;_____;


To be honest, I'm not even sure this works... Lemme write up something new to replace this, 'kay? :P

And here it is...
Spoiler: ShowHide


class ATB

class Group

attr_accessor :modifier

def initialize
@clients = []
@modifier = 1.0
end

def add_client client
@clients.push client
end

def empty
@clients = []
end

def update(mod = 1.0)
@clients.each do |c|
c.update(@modifier * mod)
end
end

end

class Client

attr_accessor :modifier, :callback, :rate

def initialize(rate, mod = 1.0)
@rate = rate
@modifier = mod
@callback = Proc.new
@count = 0
end

def update(mod = 1.0)
@count += rate * @modifier * mod
if @count >= 100
@callback.call(self)
@count = 0
end
end

end

def initialize
@groups = []
end

def add_group g
@groups.push g
end

def empty
@groups = 0
end

def update
@groups.each do |g|
g.upate
end
end

end



To use it, you create an ATB handler with ATB.new, then populate it with however many groups you need (at least one). Each group is just a way to handle clients conveniently; you can start or stop all members of a group by setting that group's modifier to 0.0. Then, you populate each group with whatever clients by creating them like so:

# You give .new an argument of the client's "rate," or what percentage of their bar should fill each update.
# You can also preset the "modifier" setting here; it is a multiplier used on the rate each frame.
c = ATB::Client.new(3) do |atb_client|
 print "Hello, world!\n"
end
# You also give it a callback, which is called, obviously enough, back by the ATB engine when the bar is filled.
# The block is passed with the client as an argument, allowing
# you to reconfigure the client is need at the end of an action (say,
# setting their modified to 0 so they won't move until you want them to)


Simple enough, don't you think?

EDIT: Blah, ATB::Group should be a subclass of Array. Here you go:

class ATB < Array
class Group < Array
attr_accessor :modifier

def initialize(mod = 1.0)
super()
@modifier = mod
end

def update(mod = 1.0)
self.each do |c|
c.update @modifier * mod
end
end
end

class Client
attr_accessor :modifier, :callback, :rate

def initialize(rate, mod = 1.0)
@rate = rate
@modifier = mod
@callback = Proc.new
@count = 0
end

def update(mod = 1.0)
@count += rate * mod
if @count >= 100
@callback.call(self)
@count = 0
end
end
end

def initialize
@groups = []
end

def add_group g
@groups.push g
end

def remove_group g
@groups.delete g
end

def empty
@groups = 0
end

def update
@groups.each do |g|
g.upate
end
end
end


Aqua

I appreciate you doing this :)

Just to be sure...
This only handles the actual time counting of the ATB, right?

fugibo

Quote from: Aqua on October 14, 2009, 09:41:41 pm
I appreciate you doing this :)

Just to be sure...
This only handles the actual time counting of the ATB, right?


Yep, but it standardizes it and gives you a clean API for it. This makes it much easier to create ATB-centric effects; the version I'm about to release emphasizes that.

Blizzard

ATB doesn't have to be a subclass of Array. Also, I think you're kinda overcomplicating this.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

fugibo

Quote from: Blizzard on October 15, 2009, 04:39:47 am
ATB doesn't have to be a subclass of Array. Also, I think you're kinda overcomplicating this.


That version is outdated :/