A Battle Extension - Creating Complex Actions

Maximus32

Absolute Genius
Veteran
Joined
Feb 20, 2014
Messages
81
Reaction score
27
First Language
English
Primarily Uses
N/A
Hello!

So, this isn't necessarily a concise "script", but it is related to scripting, so I thought it would be appropriate to place here. Basically, it's a method I devised for creating battler actions that reference many variables or perform complex actions. I came up with this because it was becoming difficult to cram a bunch of code into the notes box in the skills editor. In addition, it can be built from scratch, although there are some scripts out there that perform similar functions.

The Battle Extension Class -

You first need to create a new class. I called mine Game_BattleExtension and assigned it to a global variable $battle_extension, because it works like an extension of the Scene_Battle class and I plan to interact with it across many classes. Although making it global isn't necessary in all cases. Also, because it might be used to display text often, you might want to give it full access to the Scene_Battle's log_window object. You'll want to create an instance of your Battle Extension class around here:

class Scene_Battle def start super create_spriteset create_all_windows create_battle_extension BattleManager.method_wait_for_message = method:)wait_for_message) end def create_battle_extension $battle_extension = Game_BattleExtension.new(@log_window) # over here! end ...endSo, let's say you want an Action to do some damage, but you want it to alter the game in some way before it executes, maybe display a certain line of text before damage is dealt. You'll want to create a method in your Battle Extension class that is called before an Action is executed, as such:

class Game_BattleExtension def initialize(log_window) @log_window = log_window end def pre_invocation_processing(action, subject, target) # right here! endendThe Pre-* Method -

You'll see that I call this method right before the invoke_item method is called, thus it is named pre_invocation_processing. However, you can call such a method any time during the processing/execution of the action and thus give it any name (i.e. pre_processing, pre_execution, etc.). I also pass the action, the action subject, and the action target as parameters. In reality, all you truly need is the action object itself.

class Scene_Battle ... def use_item ... targets.each { |target| item.repeats.times { $battle_extension.pre_invocation_processing(action, @subject, target) # right here! invoke_item(target, item) } } end ...endNow for the cool part! This is why the Ruby programming language is awesome.

You'll want to add some code like this:

def pre_invocation_processing(action, subject, target) method_name = action.item.name.downcase.gsub(/[ ,\.]/, "_") return unless methods.include?(method_name.to_sym) method(method_name).call(action, subject, target)endHere's what this does:

  • The second line translates the action's "name" (what you called it in the editor) into a method name, like so:Super Attack              --> super_attack
  • Valence Electron_3    --> valence_electron_3
  • Magic Homerun 2.0    --> magic_homerun_2_0
[*]The third line checks the rest of the Battle Extension class for any methods that match this method name. If there are none, the method returns handling to the Scene_Battle, and nothing special happens
[*]The fourth line references a method object--the Action Method--from the method name (which should correspond to a particular method later in the class) and calls it
The Action Method -

So, lets say I wanted, before invoking an action, to make some text appear. I name my action "Dipper Pines" in the editor. I do everything as mentioned before, and then I create an Action Method dipper_pines in the Battle Extension class. Like so:

def dipper_pines @log_window.add_text("Mabel! Stop bedazzling all of my stuff!!")endSo when this action is processed, the Scene_Battle class will call on the pre_invocation_method, which will notice that there is a method that corresponds to this particular action and execute it, thus displaying the text.

An Example -

There's a LOT of stuff you can do when you aren't hindered by the strictness of the editor. Here's an example of one thing I did:

I created an action named "Swing" that chooses a random object to swing at an opponent. In the Battle Extension class, I initialized a hash called @swing_objects containing strings like "flimsy stick", "iron pipe", "fists" matched to numbers like 0.5, 3, 1, respectively that correspond to relative damage. the "swing" Action Method, when called, displays a message describing what object is being swung. It then proceeds to change the action's damage formula depending on the number that was chosen. When handling returns to the Scene_Battle, the new damage formula is used to do damage (This in itself is a complex topic as well, so don't worry about how it can be done for now, just know that the damage changes considerably for the object that's chosen).

def swing(action, subject, target)  pair = @swing_objects.to_a.sample  object = pair[0]  coefficient = pair[1]  @log_window.add_text(sprintf(Vocab::Skill_Swing, subject.name, object))  clear_item_formula(action.item)  action.item.damage.formula = sprintf(action.item.damage.formula, coefficient.to_s)end

Conclusion -

What's awesome is that, using Ruby, you can VERY easily check if there's a method to be called and then actually transform a string that is a method name into an actual method call! And, if there is no special processing to be done, the code takes care of it, returning early.

Hope this was interesting! If you didn't understand any bit (even with my fancy color-coded text), feel free to ask a question. Also, I encourage people to find more efficient ways of doing this and sharing it on this thread.
 
Last edited by a moderator:

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,897
Reaction score
2,884
First Language
French
Primarily Uses
RMMV
first ...we don't start a .new in a initialization you should do a a external call like htis

Code:
class Scene_Battle < Scene_Basealias nio_start startdef startbattle_extention_checknio_startenddef battle_extention_check$battle_extention = Battle_extention.newendend
 
Last edited by a moderator:

Engr. Adiktuzmiko

Chemical Engineer, Game Developer, Using BlinkBoy'
Veteran
Joined
May 15, 2012
Messages
14,696
Reaction score
3,008
First Language
Tagalog
Primarily Uses
RMVXA
In addition, this does not require any external scripts
Nope, you still added a new script/class...

You also modified the existing scripts via overwrites which sometimes isn't a good idea...

You also need a new method per item, which is kind of overkill in case you only want simple things.

I guess we can pass it as an alternative to existing scripts that allow you to do such stuff (like my Skill Apply Extension for example)
 
Last edited by a moderator:

Maximus32

Absolute Genius
Veteran
Joined
Feb 20, 2014
Messages
81
Reaction score
27
First Language
English
Primarily Uses
N/A
Nio Kasgami: Haha! Yeah, actually, that's exactly how I do it on my computer, but for simplicity of posting here, I did break some syntactical norms.

TheoAllen: That is true. However, I might use the Battle Extension class elsewhere, like on the game map, to affect future battles.

Engr. Adiktuzmiko: Oh I see... Yeah, by not requiring external scripts, I meant it's built from scratch. Guess I mislabeled that. As for directly editing existing code, I think it's okay because each time you create a new game in RPG Maker, it starts you off fresh with the original script. In my opinion, it's kind of like a canvas.

Thanks for the suggestions, everybody :)
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,479
Reaction score
6,311
First Language
Indonesian
Primarily Uses
RMVXA
If you want to make it global, you should initialize the Battle Extension inside the create_game_objects in DataManager. And when the battle starts, you can call reset function from the Battle Extension itself without reinitializing the Battle Extension object. In case if you want to keep some values that should not reseted.
 

Engr. Adiktuzmiko

Chemical Engineer, Game Developer, Using BlinkBoy'
Veteran
Joined
May 15, 2012
Messages
14,696
Reaction score
3,008
First Language
Tagalog
Primarily Uses
RMVXA
As for directly editing existing code, I think it's okay because each time you create a new game in RPG Maker, it starts you off fresh with the original script. In my opinion, it's kind of like a canvas
Yeah, but I'm not talking about problems with the next game. Modifying the existing ones via overwrites need to be done carefully since it could cause problems with different scripts that you make/add that would overwrite those things too, in that very same game that you're making...
 
Last edited by a moderator:

Maximus32

Absolute Genius
Veteran
Joined
Feb 20, 2014
Messages
81
Reaction score
27
First Language
English
Primarily Uses
N/A
Yeah, but I'm not talking about problems with the next game. Modifying the existing ones via overwrites need to be done carefully since it could cause problems with different scripts that you make/add that would overwrite those things too, in that very same game that you're making...
Ah, I see... Yes, this did happen to me in a previous project I was working on, where modifying original code caused problems down the road with other game features    :/
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,434
Reaction score
3,450
First Language
English
It's a good idea. I use similar ideas for the command manager, feature manager, and effect manager.


Being able to quickly define your own behaviors using a framework is much more efficient than having to write it all yourself.


It also improves compatibility since you're just plugging stuff in, rather than aliasing or overwriting things.


But yes, there are several issues that you need to be aware of when you're modifying shared objects.
 
Last edited by a moderator:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

So yesterday I got a follower (follow my NSFW art account) who dmed me and said to me :
if you continue to be friends with [name of the artists] which make me uncomfortable I will have to unfollow and I am like :
... do it?
Did I add too many?? Is there such a thing?

Rabbit's Shop I've been reworking. Still some dated graphics but 99% satisfied I think.:kaophew:
Traps, detecting traps, and disarming traps including treasure traps have now been implemented into my Might and Magic-inspired project. If you don't want to get hurt, you better have a character who focuses on the perception skill, and you better have a character who focuses on the disarm skill!

Done tinkering a project idea for MZ, time to make a little document and wait for the release... :kaoswt:

Forum statistics

Threads
100,834
Messages
980,071
Members
132,481
Latest member
loehz
Top