Jump to content
Sign in to follow this  
Kayzee

Event Battlers: Attach battlers to events and gave them gang up on you.

Recommended Posts

Here is a little script I have been working on, semi-inspired by the earthbound/mother games how enemies will find you on the map and attack you, other nearby ones joining in, or the newer SaGa game's 'chain battles' when you run in to enemies with others near by.

 

Here is the script:

 

#========================================================================

# ** Event battlers, by: KilloZapit

#------------------------------------------------------------------------

# Changelog of changeness:

#

# Version the fourth: Okay the joke is getting old.

#

# -- Featuring blah blah blah --

#

# Bug fix and improvement for apply_item (and apply_skill by extention) that

# allows a array of targets and some other things.

#

# Version the third: Magical Pocketrat's Jamboree!

#

# -- Featuring a small but notable addition to be detailed below! --

#

# New functions "apply_item" and "apply_skill" that can be used to

# apply items and skills to a target as if they have been hit in battle!

#

# Descriptions also added for the new scripts of course.

#

# <strike>Rainbow Dash</strike> (What? How the hell did you get back in

# here? And now you are backing... My little pony references? You never

# even saw that show! GET OUT!) (... Tee-hee, don't worry I know a secret

# way back in. :3 )

#

#------------------------------------------------------------------------

# Version the Second: Now we are cooking with pinneedles.

#

# -- Featuring all the following exciting changes! --

#

# Comment tags can be on any page!

#

# New comment tags and related features to support having battlers only

# being active on some pages!

#

# The old comment tags (well... okay, tag) are now redone Yanfly-style!

#

# Help text consequently changed to use [] instead of <> to mark stuff

# that should be replaced (as a side note, I play this online text game,\

# where if you enter a wrong command, it says to type "newbie <text>",

# and it rather amazes me that people type exactly that so often.)

#

# Tons of more options for get_event_battlers!

#

# Some bug fixes for some bugs I noticed!

#

# Doesn't have the word engine in the name! (Okay that's not new but...

# serious, why are so many scripts "such and such engine", they aren't

# engines people they are patches at best. System is much better, even

# if it is a little cliche...)

#

# <strike>A pony!</strike> (We apologize, the person responsible for

# this changelog has been sacked.)

#

#========================================================================

# ** Help and description

#------------------------------------------------------------------------

#

# These are simple scripts to setup and use battlers attached to events.

# To use put "<enemy_id [number]>" in a comment on the active page of an

# event, replacing "[number]" with the database id of the enemy to use

# and use the included scripts. You will need to call a script before and

# after a battle event to use, while one that runs during battle events

# to handle things if there are more event battlers then troop slots in

# the fight.

#

# Other comment tags:

#

# <enemy_id nil>

# Setting enemy_id to nil instead of a number will delete the battler

# form this event when the page you put the comment on becomes the

# current page. If you then switch back to a page with a normal

# enemy_id tag, the battler will be recreated. This way you can set up

# events with enemies that you can make reappear later.

#

# <alert [yes/no]>

# Set this replacing [yes/no] with yes or no to change if this event

# is alerted by other events entering a battle. If you plan on using

# event battlers that are in a passive or hidden in different pages,

# you will need to mark each page you use with an alert tag.

#

# <post_battle_page [page number]>

# Set this replacing [page number] with the page number you want to

# use for this event's post-battle actions. This way you can override

# the default for whatever event you choose. Note: This will call the

# events on the page, but not switch to it.

#

# Included scripts:

#

# - Before battle - (run these scripts before the battle event)

#

# get_event_battlers([character], [radius], [repeats], [emotion], [pause])

# Find all event battlers nearby, angering them and including them in

# the list of battlers for the net battle, then recursively finds any

# event battlers near those events. In battle they will fill the slots

# for the battles troop up to the troop's max members.

# [character] part is optional and defaults to the current event,

# and can be either an event id number, or a direct character object

# like $game_player.

# [radius] is also optional, and sets how close events have to be in

# order to be added. Add 0.5 and it will base it on a square pattern

# instead of a circle.

# [repeats] is also also optional, and if it is not nil, each time it

# checks it will count one step down, ending when zero. By default the

# number of steps is unlimited, so you could theoretically end up with

# every event in the map on the list.

# [emotion] is once again optional and can be replaced by the emotion

# bubble number to display, or "nil" to disable the bubble display. The

# Default is 5 (angry).

# [pause] is even more optional and can be replaced with the number

# of frames to wait for each step, defaulting to 10.

# All defaults can be changed below.

#

# push_event_battler([event id])

# Manually put the selected event by id into the list. Once again the

# [event id] is optional and defaults to the triggering event id.

#

# - During battle - (run these scripts in battle events)

#

# replace_enemies([number to replace])

# If there are more events in the list then the troop slots, this will

# replace up to [number to replace] dead or hidden enemies with new

# ones form the remainder of event enemies. The [number to replace] is

# again optional and defaults to one.

#

# - After battle - (run these scripts after the battle event)

#

# post_battle_common_event([common event number])

# runs the common event [common event number] for every enemy who got

# to fight in battle, alive or dead. Any who were in the list but

# didn't actually appear in battle are left out.

#

# post_battle_run_page([common event number])

# runs the common event [common event number] for every enemy who got

# to fight in battle, alive or dead. Any who were in the list but

# didn't actually appear in battle are left out.

#

# post_battle_eval([ruby code string])

# evaluates the code in [ruby code string] for all events who got to

# fight.

#

# - Misc scripts - (utility scripts, run whenever)

#

# battler_alive?([event id])

# Check if the event battler is alive. Intended for use in conditional

# blocks in post battle events. If the player runs form a battle the

# event battlers keep all damage retained and can enter battle again.

# The [event id] is optional and defaults to the triggering event id.

#

# battler_AI_Step

# Simple move route script to run to or away from players depending on

# the battlers remaining HP.

#

# apply_item([item id], [target], [user], [animate flag])

# Applies the effect of an item as if it was used in battle.

# The [item id] is the database number of the item to use.

# The [target] can be $game_player or an event object or a event id.

# The [user] is optional, and defaults to the player, but can be any

# of the same things as the target.

# The [animate flag] is also optional and defaults to false. If true,

# the item's animation will be shown on the target.

#

# apply_skill([skill id], [target], [user], [animate flag])

# Works the same way as apply_item except with skills.

# The [skill id] is the database number of the skill to use.

# Everything else works exactly the same as above.

#

#========================================================================

 

$imported = {} if $imported.nil?

$imported["KZ!-EventBattlers"] = true

 

module KZIsAwesome

 

# why do people always make modules based on their names?

# I guess it's just to have a unique namespace is all...

 

module EventBattlers

 

# How far events can be form the event checking for enemies to join

# in on a battle. Add 0.5 and it will base it on a square pattern

# instead of a circle.

# Default: 1

RADIUS = 1

 

# Default for the recursive depth of the surrounding enemy search.

# Note this is not how many times the search can be done despite

# the name, it's how many "generations" the search can have.

# But it's a but simpler to name it this I think?

# Default: nil (It will keep searching till it can't find anything)

REPEATS = nil

 

# The emotion bubble number to display. Might let it use animations

# too in the future, maybe by making it a string and parsing it? But

# maybe better to just have values over 9000 or something be an

# animation. And yes I went there

# Default: 5

EMOTION = 5

 

# How many frames to pause each step.

# Default: 10

PAUSE = 10

 

# If animations for items and skills used on the map should be

# used or not by default

# Default: False

ANIMATE_APPLY = false

 

end

end

#========================================================================

# * Class: Game_Event

#========================================================================

 

class Game_Event < Game_Character

 

# * Added Public Instance Variable: The battler attached to this event.

attr_reader :battler

# * Added Public Instance Variable: Flag to disable joining battles.

attr_reader :battler_no_alert

# * Added Public Instance Variable: Runs a event page instead of the

# normal post-battle effect

attr_reader :battler_special_page

 

# * Alias: Object Initialization

alias_method :initialize_battler_event_base, :initialize

def initialize(*args)

@battler = nil

@battler_no_alert = false

@battler_special_page = nil

initialize_battler_event_base(*args)

end

 

# * Alias: Read settings on page change

alias_method :setup_page_battler_base, :setup_page

def setup_page(new_page)

setup_page_battler_base(new_page)

unless @page.nil?

for item in @page.list

if item.code == 108 or item.code == 408

next if item.parameters[0].nil?

if item.parameters[0].downcase =~ /^<\s*enemy_id\s*([0-9]+)\s*>/

@battler = Game_Enemy.new(nil, $1.to_i) if @battler.nil?

elsif item.parameters[0].downcase =~ /^<\s*enemy_id\s*nil\s*>/

@battler = nil

elsif item.parameters[0].downcase =~ /^<\s*alert\s*(no|false|hide)\s*>/

@battler_no_alert = true

elsif item.parameters[0].downcase =~ /^<\s*alert\s*(yes|true|show)\s*>/

@battler_no_alert = false

elsif item.parameters[0].downcase =~ /^<\s*post_battle_page\s*([0-9]+)\s*>/

@battler_special_page = $1.to_i

end

end

end

end

end

 

# * New method: Move differently depending on hp and player distance

def battler_AI_Step

if near_the_player?

unless @battler.nil?

if @battler.hp / @battler.mhp > 0.33

move_toward_player

else

move_away_from_player

end

else

move_random

end

else

move_random

end

end

 

# * New method: Do post battle eval for this event

def post_battle_eval(str)

eval(str)

end

 

end

 

#========================================================================

# * Class: Game_Map

#========================================================================

 

class Game_Map

 

# * Added Public Instance Variable: Battler event list for next battle.

attr_accessor :event_battlers

 

# * Alias: Object Initialization, clear event battler list.

alias_method :initialize_battler_map_base, :initialize

def initialize

initialize_battler_map_base

@event_battlers = nil

end

 

# * New method: Recursively alert and list nearby battler events

def get_event_battlers(character, radius, repeats, emotion, pause)

unless character.is_a?(Game_Character)

character = @events[character.to_i]

end

e = []

@events.each_value do |ent|

next if ent.battler.nil? || ent.battler_no_alert || !ent.battler.alive?

next if @event_battlers.include?(ent) || e.include?(ent)

sx = character.distance_x_from(ent.x)

sy = character.distance_y_from(ent.y)

if (radius*2)%1 == 1

next unless (sx.abs <= radius.floor) && (sy.abs <= radius.floor)

else

next unless sx.abs + sy.abs <= radius

end

e.push(ent)

end

return if e.empty?

@event_battlers.concat(e)

unless emotion.nil?

e.each do |ent|

ent.balloon_id = 5

end

end

pause.times { Fiber.yield } unless pause.nil? || pause < 1

if repeats.nil? || repeats > 0

e.each do |ent|

get_event_battlers(ent, radius, repeats.nil? ? nil : repeats-1, emotion, pause)

end

end

end

 

# * New method: Push a event onto the list for next battle

def event_battler_push(id)

@event_battlers = [] if @event_battlers.nil?

@event_battlers.push(@events[id])

end

 

# * New method: Run a common event for all event battlers

def post_battle_common_event(common_event_id)

common_event = $data_common_events[common_event_id]

if common_event

@event_battlers.each do |ent|

next if post_battle_special_action(ent)

Call_Interpreter(common_event, ent)

end

end

@event_battlers = nil

end

 

# * New method: Run a page of the event for all event battlers

def post_battle_run_page(page_id)

map = load_data(sprintf("Data/Map%03d.rvdata2", $game_map.map_id))

@event_battlers.each do |ent|

next if post_battle_special_action(ent)

page = map.events[ent.id].pages[page_id-1]

Call_Interpreter(page, ent)

end

@event_battlers = nil

end

 

# * New method: Pass a string to be evaluated for all event battlers

def post_battle_eval(str)

@event_battlers.each do |e|

next if post_battle_special_action(ent)

e.post_battle_eval(str)

end

@event_battlers = nil

end

 

# * New method: Handle special post-battle actions for events

def post_battle_special_action(ent)

return false if ent.battler_special_page.nil?

map = load_data(sprintf("Data/Map%03d.rvdata2", $game_map.map_id))

page = map.events[ent.id].pages[ent.battler_special_page-1]

return false if page.nil?

Call_Interpreter(page, ent)

return true

end

 

def Call_Interpreter(page, ent)

child = Game_Interpreter.new

# The following is for compatibility with Saba Kan's Random Dungeon

# Generator, and maybe other scripts that duplicate events and put

# the real event id in event_id... if any others do.

id = (defined? ent.event_id).nil? ? ent.id : ent.event_id

child.setup(page.list, id)

child.run

end

 

 

end

 

#========================================================================

# * Class: Game_Enemy

#========================================================================

 

class Game_Enemy < Game_Battler

# * Allow writing to the troop index from another class.

attr_accessor :index

end

 

#========================================================================

# * Class: Game_Troop

#========================================================================

 

class Game_Troop

 

# * Alias: If the event battler list is not nil, populate troop

# with battlers from the list in reverse, pushing the

# troops used back into a fresh list for post battle,

# keeping the rest in an array for later.

alias_method :setup_battler_map_base, :setup

def setup(troop_id)

if $game_map.event_battlers.nil? || $game_map.event_battlers.empty?

@enemies_left = nil

setup_battler_map_base(troop_id)

return

end

clear

@troop_id = troop_id

@enemies = []

@enemies_left = $game_map.event_battlers.reverse

$game_map.event_battlers = []

troop.members.each do |member|

next if @enemies_left.empty?

event = @enemies_left.pop

enemy = event.battler

$game_map.event_battlers.push(event)

enemy.index = @enemies.size

enemy.appear

enemy.screen_x = member.x

enemy.screen_y = member.y

@enemies.push(enemy)

end

init_screen_tone

make_unique_names

end

 

# * New method: Replace dead or hidden enemies with new ones from

# the remaining enemy list.

def replace_enemies(num = 1)

return if @enemies_left.nil? || @enemies_left.empty?

i = 0

l = []

troop.members.each_index do |index|

next if @enemies_left.empty?

next if i >= num

unless @enemies.size < index

next unless @enemies[index].hidden? || !@enemies[index].alive?

end

i += 1

event = @enemies_left.pop

enemy = event.battler

$game_map.event_battlers.push(event)

enemy.index = index

enemy.appear

enemy.screen_x = troop.members[index].x

enemy.screen_y = troop.members[index].y

if @enemies.size < index

@enemies.push(enemy)

else

@enemies[index].index = nil

@enemies[index] = enemy

end

enemy.make_actions

enemy.on_battle_start

$game_message.add(sprintf(Vocab::Emerge, enemy.name))

end

make_unique_names

SceneManager.scene.replace_enemy_sprites

BattleManager.wait_for_message

end

 

end

 

#========================================================================

# * Class: Scene_Battle

#========================================================================

 

class Scene_Battle

 

# * New method: tell the sprite set to refresh the enemy sprites.

def replace_enemy_sprites

@spriteset.replace_enemy_sprites

end

 

end

 

#========================================================================

# * Class: Spriteset_Battle

#========================================================================

 

class Spriteset_Battle

 

# * New method: Create new sprites for newly appeared enemies,

# disposing of ones for replaced enemies.

def replace_enemy_sprites

e = $game_troop.members.reverse.collect.with_index do |enemy, i|

if @enemy_sprites.nil?

Sprite_Battler.new(@viewport1, enemy)

elsif @enemy_sprites.battler == enemy

@enemy_sprites

else

@enemy_sprites.dispose

Sprite_Battler.new(@viewport1, enemy)

end

end

@enemy_sprites = e

end

 

end

 

#========================================================================

# * Class: Game_Interpreter

#========================================================================

 

class Game_Interpreter

 

# * New method: Do this event's battler_AI_Step

def battler_AI_Step

@event_id.battler_AI_Step

end

 

# * New method: Clear event battler list and start recursive look up.

def get_event_battlers( id = @event_id,

radius = KZIsAwesome::EventBattlers::RADIUS,

repeats = KZIsAwesome::EventBattlers::REPEATS,

emotion = KZIsAwesome::EventBattlers::EMOTION,

pause = KZIsAwesome::EventBattlers::PAUSE)

$game_map.event_battlers = []

$game_map.get_event_battlers(id, radius, repeats, emotion, pause)

end

 

# * New method: Interface for Game_Map's event_battler_push

def event_battler_push(id = @event_id)

$game_map.event_battler_push(id)

end

 

# * New method: Interface for Game_Map's post_battle_common_event

def post_battle_common_event(common_event_id)

$game_map.post_battle_common_event(common_event_id)

end

 

# * New method: Interface for Game_Map's post_battle_run_page

def post_battle_run_page(page_id)

$game_map.post_battle_run_page(page_id)

end

 

# * New method: Interface for Game_Map's post_battle_eval

def post_battle_eval(str)

$game_map.post_battle_eval(str)

end

 

# * New method: Interface for Game_Troop's replace_enemies(

def replace_enemies(num = 1)

$game_troop.replace_enemies(num)

end

 

# * New method: Returns if the battler attached to an event is alive.

def battler_alive?(id = @event_id)

$game_map.events[id].battler.alive?

end

 

def apply_item(item, targets, user = $game_player, animate = KZIsAwesome::EventBattlers::ANIMATE_APPLY)

unless user.is_a?(Game_Battler)

if user == $game_player

user = $game_party.leader

elsif user.is_a?(Game_Event)

user = user.battler

elsif user.is_a?(Integer)

user = $game_map.events[user].battler

else

puts("apply_item failed: invalid user")

return

end

end

unless item.is_a?(RPG::UsableItem)

unless item.is_a?(Integer)

puts("apply_item failed: invalid item")

end

item = $data_items[item]

end

unless targets.is_a?(Enumerable)

targets = [targets]

end

targets.each do |target|

animtarget=nil

unless target.is_a?(Game_Battler)

if target == $game_player

animtarget = $game_player

target = $game_party.leader

elsif target.is_a?(Game_Follower)

animtarget = target

target = animtarget.actor

elsif target.is_a?(Game_Event)

animtarget = target

target = target.battler

elsif target.is_a?(Integer)

animtarget = $game_map.events[target]

target = animtarget.battler

else

puts("apply_item failed: invalid target")

next

end

end

#puts("apply_item succeded: ("+item.name+", "+target.name+", "+user.name+").")

if animate && animtarget != nil

animtarget.animation_id = item.animation_id

Fiber.yield while animtarget.animation_id > 0

# Only do screen animations once.

if $data_animations[item.animation_id].to_screen?

animate = false

end

end

target.item_apply(user, item)

end

end

 

# * New method: Applies a skill's effects to a target battler.

# Really just passes a skill object to apply_item.

def apply_skill(skill, *args)

unless skill.is_a?(RPG::UsableItem)

unless skill.is_a?(Integer)

puts("apply_skill failed: invalid skill")

return

end

skill = $data_skills[skill]

end

apply_item(skill, *args)

end

 

end

 

 

Here is some more description and screenshots:

 

 

Oh look a bunch of enemies

test1.png

 

Aww crap you pissed them off! (using get_event_battlers)

test2.png

 

huh? only 5? I could have sworn there were more...

test3.png

 

Okay let's do this... die slime!

test4.png

 

Awww crap... looks like the others were waiting on the sidelines... (using replace_enemies in a battle event)

test5.png

 

Time to run! Looks like I got away but... only the one I killed vanished... (using post_battle_common_event and battler_alive?)

test6.png

 

Event setup (Probably a good idea to dump this in a common event and call it):

test7.png

 

Post battle common event example:

test8.png

 

 

Try it out! Looking to see if anyone has feedback.

Edited by KilloZapit

Share this post


Link to post
Share on other sites
To use simply put "enemy <number>" in a comment on the first page of an event

 

I've been thinking about whether the first page is an ideal place to put these things.

Maybe the script should be checking whether the "active" page has the comment, because someone might want to make the 2nd page the enemy, like maybe some stone gargoyles turn into actual monsters when you trigger something.

Share this post


Link to post
Share on other sites
To use simply put "enemy <number>" in a comment on the first page of an event

 

I've been thinking about whether the first page is an ideal place to put these things.

Maybe the script should be checking whether the "active" page has the comment, because someone might want to make the 2nd page the enemy, like maybe some stone gargoyles turn into actual monsters when you trigger something.

 

The way it works now, the battler is set when the map loads. Is there a method that events call when they change pages? I have to look into that I guess. Personally, I almost rather not use comments at all, and just do everything with script calls. Only reason I use a comment is to avoid needing a auto start event. Come to think of it, a script to allow comment tags to be used to do something like "onload: <insert code here>" and "ondefeat: <insert code more code here>" would work better. Might just do that.

Share this post


Link to post
Share on other sites

Whenever an event is refreshed, the event runs a check in reverse order to figure out which page should be run, which is basically checking whether page conditions have been met (the 5 conditions on the left). It will just choose whichever page that can be run when it sees it.

 

The page is then stored in @page until the event is refreshed again.

Event refreshing actually occurs frequently, and is done whenever $game_map.need_refresh is true.

Edited by Tsukihime

Share this post


Link to post
Share on other sites

I'm having a problem figuring out how to use this script. What exactly should I do to use it in-game?

Also, I'm having trouble with the following:

By enemy <number>, does number refer to the enemy database ID?

Do I just use the script calls, or do I have to include 'Battle Processing' through the event command to actually enter a battle?

 

Really appreciate all the hard work here! Excuse me for misunderstanding, but I am very grateful for this. All the best! :)

Share this post


Link to post
Share on other sites

I'm having a problem figuring out how to use this script. What exactly should I do to use it in-game?

Also, I'm having trouble with the following:

By enemy <number>, does number refer to the enemy database ID?

Do I just use the script calls, or do I have to include 'Battle Processing' through the event command to actually enter a battle?

 

Really appreciate all the hard work here! Excuse me for misunderstanding, but I am very grateful for this. All the best! :)

 

Yeah it's the enemy database ID and you include 'Battle Processing' through the event command.

 

Here are a few more screenshots of the setup:

 

 

 

Event setup (Probably a good idea to dump this in a common event and call it):

test7.png

Post battle common event example:

test8.png

 

 

 

Edit: For completeness's sake, here is a screenshot of the troop I am using. The enemies in a troop get replaced by the event battler enemies.

 

test9.png

 

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Pew, just updated this script in the original post with lots more features. It changes the name of the comment tag to "<enemy_id [number]>" instead of just "enemy [number]". Other then that, I took Tsukihime's advice and comment tags now refresh themselves on page load, as well as some new tags for changing if an enemy will respond to nearby battles. Hopefully it's more useful now. I really should make a demo... I am a bit reluctant to, for reasons I... rather not disclose.

Share this post


Link to post
Share on other sites

Hehe thanks. I just made a vary minor change to get rid of my attempt at sorting, because I noticed it wasn't really working like I expected.

Share this post


Link to post
Share on other sites

Honestly, this is really amazing! Thanks so much for your reply, and it works perfectly for me now!

I'm also loving the new updates

Thanks (references btw are My Little Pony? Just guessing lol..)

Share this post


Link to post
Share on other sites

Hehe, thanks! Wow, someone actually read all my silly changelog text? :P I had way to much fun typing those. I blame my avatar, it makes me want to be childish, giggly, and playful. *Sprinkles some fairy dust on you.*

 

(I actually chose this avatar because the game I have been slowly fiddling with making that I made this script for stars a fairy! Wheee!)

Edited by KilloZapit

Share this post


Link to post
Share on other sites

I'm having trouble understanding how to set this up... could someone please provide me with a screenshot of the event page?

Share this post


Link to post
Share on other sites

I already posted one in this post in one of the spoiler tags. I added them to the screenshots in the original post too so people can find them easier. Should have done that before.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Made a small improvement with apply_item (and apply_skill) that allows an array of targets to be passed to it instead of a single target. It's fully backwards compatible though. It also fixes a bug I noticed and I think I added the ability for it to apply items and skills to followers too. Really apply_item and apply_skill are only that useful if you want to make an alternate battle system on the map it's self, but they should be really useful if say, someone wants to make a tactical or rogue-like battle system. Which I may do some time, if I get around to it.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
Top ArrowTop Arrow Highlighted