12-01-2018, 09:01 PM
(This post was last modified: 12-01-2018, 10:06 PM by Kain Nobel.)
I now have some animated battlers developed! Doing major work on the battle system at the moment, there are so many problems! Reducing and streamlining code, restructuring everything, it'll probably leave my project unplayable for the next month or two. Sometimes I worry if I've coded myself into oblivion and have to roll back to an earlier version. Oh well, it will get fixed/improved/mastered eventually.
^Screenshot already out of date BTW. I've fixed the animation Z problem which stands out in this picture.
Prototype builds are in the spirit of Cloud and the gang, but they're only temporary placeholders until I get my original characters more fleshed out. Now I've got whole sheets of an original battle templates (child, woman, man, man (muscle), man (fat)) and pieces of hair, clothing, shoes, accessories, etc I've made. Still making more battle poses, assumed end goal would be sheets tailored to each weapon type.
Also working on battler "AI" (if you want to call it that.)
Some scripted enemies...
BattleAI::Ghost
BattleAI::Vagrant
BattleAI::Basilisk
The oldschool "Action List" style enemies are still functional for when I want to use it, but I'll be doing these for tricky enemies and most of the more difficult boss fights. I'm amazed at how much there is to define just for a simple fly-by random encounter, but bosses will be a lot more fun to design and fight from now on!
I like to write enemy routine scripts, it gives for a lot of cunning and calculating on part of the acting enemy. As such, a Ghost will iterate through the actor with the most skills to the actor with the least skills and determine if they need to inflict "Silence" or not, prioritizing the one with the most potential skills whom doesn't already have "Silence". The physical attackers have to deal with Ghosts vanishing all the time so either way it makes for an annoying to potentially difficult fight depending on your level and patience.
ANIMATED/AI BATTLER PROGRESS
Heroes
Logan - Character (100%) Battler (112% (Most Poses/Actions))
Mac - Character (100%) Battler (60%)
Sasha - Character (100%) Battler (30%)
Enemies
Ghost - Animated/AI
Soldier 1 - Animated (80%)
Soldier 2 - Animated (100%)
Cain (Knight Blade) - Animated
Basilisk - Animated/AI
Hellhound - Animated/AI
Hellraiser - AI (No animation yet :( )
Tesla Wyrm - Animated/AI
Triterrortops - Animated/AI
Doberman - Animated/AI
Cobra - Animated
Razor Palm - Animated
Oily Body - Animated
Flame Soul - Animated/AI
Other Characters
Locke (FF6) - Character/Battler
Sabin (FF6) - Character/Battler
Celes (FF6) - Character/Battler
Terra (FF6) - Character/Battler
Cloud (FF7) - Character
Tifa (FF7) - Character/Battler (155% (Most Poses/Actions))
Aeris (FF7) - Character/Battler
Ward (FF8) - Character
Red Baron (Shining Force II) - Character/Battler
Ghestal (Shining Force II) - Battler (20%)
I'll probably be doing more non-original characters during the expansion process of the animated battler template I've been creating. It's easier to beta animations when you're designing familiar heroes/villians than if you were to worry about creating a new character from scratch too. Thanks to Tifa, my females have so much more actions than the males so the boys will have to eventually catch up. Heck, Cloud doesn't even have a battler designed for him yet - not that it's on my high priorities list - but I might get to him soon just because it bugs me.
My internet connection sucks and I can't get IRC to work, plus I work a lot, so I don't know how much I'll be around after the holidays. Still, I'll try to drop in once in awhile just so people know I'm alive lol.
^Screenshot already out of date BTW. I've fixed the animation Z problem which stands out in this picture.
Prototype builds are in the spirit of Cloud and the gang, but they're only temporary placeholders until I get my original characters more fleshed out. Now I've got whole sheets of an original battle templates (child, woman, man, man (muscle), man (fat)) and pieces of hair, clothing, shoes, accessories, etc I've made. Still making more battle poses, assumed end goal would be sheets tailored to each weapon type.
Also working on battler "AI" (if you want to call it that.)
Some scripted enemies...
BattleAI::Ghost
Code:
#===============================================================================
# ** BattleAI::Ghost
#-------------------------------------------------------------------------------
# A wicked wandering spirit which vanishes at will, curses your party
# and uses Arcane magic. Once physically attacked, it will try to stay in
# an "Invisible" state to avoid your hits. Once magically attacked, it will
# begin adding "Silence" to its routine.
#
# Attacks
# -------
# Attack - Physical Attack
# Dreadful Sin - Magical Attack. Contains "Dark" element.
# Screaming Pain - Physical Attack. 20% chance of resetting ATB bar.
# Silence - Non-Damage. Inflicts "Silence".
#===============================================================================
class BattleAI::Ghost < BattleAI
#-----------------------------------------------------------------------------
# * Setup
#-----------------------------------------------------------------------------
def setup
# Default physically attacked false
@physically_attacked = false
# Default magically attacked false
@magically_attacked = false
# Set vanish and angry to 0
@vanish = 0
@angry = 0
# Start with a random step between 1 and 3
@step = rand(1..3)
# 1/8 chance of first attack
first_attack if rand(1..8) == 8
end
#-----------------------------------------------------------------------------
# * First Attack
#-----------------------------------------------------------------------------
def first_attack
# End method unless battler is leader
return unless @battler.index == 0
# Set first attack flag
@first_attack = true
# Select all foes
@battler.set_target(:foes_all)
# Use Skill ("Curse")
@battler.use_skill(111)
end
#-----------------------------------------------------------------------------
# * Process
#-----------------------------------------------------------------------------
def process
# Add 1 to vanish if state
@vanish += 1 if @battler.state?(38)
# End method and die if SP 0
return if process_sp0
# End method if process vanish
return if process_vanish
# End method if process reappear
return if process_reappear
# End method if process low HP
return if process_lowhp
# Perform regular process
process_phase1
end
#-----------------------------------------------------------------------------
# * Process : SP 0
#-----------------------------------------------------------------------------
def process_sp0
# If battler has no SP
if @battler.sp == 0
# Battler automatically dies
@battler.die
# Return true
return true
end
# Return false
false
end
#-----------------------------------------------------------------------------
# * Process : Vanish
#-----------------------------------------------------------------------------
def process_vanish
# False unless been physically attacked before
return false unless @physical_attack
# False unless 2/3 (66%) chance
return false unless rand(1..3) > 1
# Set target self
@battler.set_target(:user)
# Use Skill ("Vanish")
@battler.use_skill(80)
# Return true
true
end
#-----------------------------------------------------------------------------
# * Process : Reappear
#-----------------------------------------------------------------------------
def process_reappear
# Return false unless vanished for 2 or more turns
return false unless @vanish >= 2 && @battler.state?(38)
# Set target self
@battler.set_target(:user)
# Use Skill ("Appear")
@battler.use_skill(81)
# Return true
true
end
#-----------------------------------------------------------------------------
# * Process : Low HP
#-----------------------------------------------------------------------------
def process_lowhp
# Return false unless 1/4 chance
return false unless rand(1..4) == 4
# Return false unless HP less than 35%
return false unless @battler.hp < (@battler.maxhp * 0.35)
# Return false unless able to use skill "Drain Energy"
return false unless @battler.skill_can_use?(83)
# Set target with highest HP
@battler.set_target(:foe_highest_hp)
# Use Skill ("Drain Energy")
@battler.use_skill(83)
# Return true
true
end
#-----------------------------------------------------------------------------
# * Regular Attack
#-----------------------------------------------------------------------------
def regular_attack
# Select nearest target
@battler.set_target(:foe_nearest)
# Do Attack
@battler.do_attack
end
#-----------------------------------------------------------------------------
# * Use "Dreadful Sin"
#-----------------------------------------------------------------------------
def use_dreadful_sin
# If 3/8 (38%) chance
if (rand(1..8) < 4)
# Select target with highest HP
@battler.set_target(:foe_highest_hp)
# Use Skill ("Dreadful Sin")
@battler.use_skill(109)
# If 5/8 (62%) chance
else
# Do a regular attack
regular_attack
end
end
#-----------------------------------------------------------------------------
# * Use "Screaming Pain"
#-----------------------------------------------------------------------------
def use_screaming_pain
# If 3/8 (38%) chance
if (rand(1..8) < 4)
# Select random target
@battler.set_target(:foe_random)
# Use Skill ("Screaming Pain")
@battler.use_skill(110)
# If 5/8 (62%) chance
else
# Do a regular attack
regular_attack
end
end
#-----------------------------------------------------------------------------
# * Use "Silence"
#-----------------------------------------------------------------------------
def use_silence
# Order target from least to most skills obtained
arr = $game_party.actors.sort {|a, b| a.skills.size <=> b.skills.size}
# Set nil target
target = nil
# Go through each actor from most skills to least skills
arr.reverse.each do |actor|
# Skip if actor already has "Silence" state
next if actor.state?(17)
# Set target
target = actor
end
# If no target
if target.nil?
# Do a regular attack
regular_attack
# If target
else
# Set target
@battler.set_target(target)
# Use Skill ("Silence")
@battler.use_skill(37)
end
end
#-----------------------------------------------------------------------------
# * Process : Phase 1
#-----------------------------------------------------------------------------
def process_phase1
# Branch out by step
case @step
when 1
# Do a regular attack
regular_attack
# Increase step
@step += 1
when 2
# Use "Dreadful Sin"
use_dreadful_sin
# Increase step
@step += 1
when 3
# Use "Screaming Pain"
use_screaming_pain
# Increase step if magically attacked or reset to 1
@step = (@magically_attacked ? @step + 1 : 1)
when 4
# Use "Silence"
use_silence
# Reset step to 1
@step = 1
end
# Set step back to 1 if too high
@step = 1 if (@step > (@magically_attacked ? 4 : 3))
end
#-----------------------------------------------------------------------------
# * Counter
#-----------------------------------------------------------------------------
def counter(attacker)
# If attacker using attack
if attacker.do_attack?
# Set physically attacked flag
@physically_attacked = true
# Set target self
@battler.set_target(:user)
# Use Skill ("Vanish")
@battler.use_skill(82)
# If attacker is using a skill
elsif attacker.do_skill?
# Get attacker skill
skill = $data_skills[attacker.current_action.skill_id]
# Retaliate against heal damage
retaliate_heal(attacker, skill)
# If attacker is using an item
elsif attacker.do_item?
# Get attacker item
item = $data_items[attacker.current_action.item_id]
# Retaliate against heal damage
retaliate_heal(attacker, item)
end
end
#-----------------------------------------------------------------------------
# * Retaliate Heal
#-----------------------------------------------------------------------------
def retaliate_heal(attacker, object)
# End method unless object has "Heal" element
return unless object.element_set.include?(1)
# Send an angry message
send_angry_message
# Target attacker
@battler.set_target(@angry == 2 ? :foes_all : attacker)
# Use Skill ("Curse")
@battler.use_skill(111)
end
#-----------------------------------------------------------------------------
# * Send Angry Message
#-----------------------------------------------------------------------------
def send_angry_message
# End method if angry message already said
return if @angry == 2
# If message variable 0
if @angry == 0
# Send 1st angry message
$scene.set_msg(@battler, "How dare you..")
$scene.set_msg(@battler, "You'll pay dearly...")
elsif @angry == 1
# Send 2nd angry message
$scene.set_msg(@battler, "Curse you!")
$scene.set_msg(@battler, "You'll all pay now!")
end
# Increase message value
@angry += 1
end
#-----------------------------------------------------------------------------
# * Death
#-----------------------------------------------------------------------------
def death(attacker)
# Do nothing
end
end
BattleAI::Vagrant
Code:
#===============================================================================
# ** BattleAI::Vagrant
#-------------------------------------------------------------------------------
# Vagrants are packs of wandering thieves. They've got nothing better
# to do but rob and harass travelers going about their day. While they
# typically escape after stealing an item, they can steal another and another
# if given the chance. Whatever the very last item each enemy has stolen
# is the only item(s) you'll be getting back from said enemy.
# Their only strength is in numbers, and the fact that they could take
# something rare and awesome. They become cowards when their friends run low
# and are more likely to escape then. Their evasion is slightly higher than
# normal, 30%, so you may want to use magic skills so you don't miss.
#===============================================================================
class BattleAI::Vagrant < BattleAI
#-----------------------------------------------------------------------------
# * Setup
#-----------------------------------------------------------------------------
def setup
# Set random step between 1 and 3
@step = rand(1..3)
end
#-----------------------------------------------------------------------------
# * Process
#-----------------------------------------------------------------------------
def process
# If stolen item and 1/3 (33%) chance
if @battler.stolen_item > 0 && (rand(1..3) == 3)
# Set successful steal message
$scene.set_msg(@battler, msg_success)
# Do Escape
@battler.do_escape
# End method
return
end
# If he is alone in battle and 4/5 (80%) chance
if $game_troop.enemies.size == 1 && (rand(1..5) > 1)
# Set coward message
$scene.set_msg(@battler, msg_coward)
# Do escape
@battler.do_escape
# End method
return
end
# Skip from step 1 to step 2 or 3 if already stolen
@step = rand(2..3) if (@step == 1 && @battler.stolen_item > 0)
# Branch out by step
case @step
when 1
# Set mugger's message
$scene.set_msg(@battler, msg_shakedown)
when 2
# Select nearest foe
@battler.set_target(:foe_nearest)
# Do Attack
@battler.do_attack
when 3
# Select random foe
@battler.set_target(:foe_nearest)
# Use Skill ("Mug")
@battler.use_skill(142)
end
# Add 1 step
@step += 1
# Set step 0 if too high
@step = 1 if @step > 3
end
#-----------------------------------------------------------------------------
# * Message : Shakedown
#-----------------------------------------------------------------------------
def msg_shakedown
# Default blank text
text = ''
# Get text based on battler index
text = case @battler.index
when 0 ; 'Hand it over and nobody has to get hurt, ya hear?'
when 1 ; 'Give us everything you\'ve got!'
end
# Return text
text
end
#-----------------------------------------------------------------------------
# * Message : Success
#-----------------------------------------------------------------------------
def msg_success
# Default blank text
text = ''
# Get text based on battler index
text = case @battler.index
when 0 ; 'Haha, see ya suckers!'
when 1 ; 'Come to the hood and get jacked!'
when 2 ; 'Looks like we\'re making out like bandits!'
end
# Return text
text
end
#-----------------------------------------------------------------------------
# * Message : Coward
#-----------------------------------------------------------------------------
def msg_coward
'I... I\'m outta here!'
end
#-----------------------------------------------------------------------------
# * Message : Angry
#-----------------------------------------------------------------------------
def msg_angry
# Text if enemy hasn't stolen from party yet
@angry_msg1 ||= 'Oh so you think you can steal from me?!'
# Text if enemy has already stolen from party
@angry_msg2 ||= 'Finders, keepers! I stole it fair and square!'
# Return message
(@battler.stolen_item > 0 ? @angry_msg2 : @angry_msg1)
end
#-----------------------------------------------------------------------------
# * Counter
#-----------------------------------------------------------------------------
def counter(attacker)
# If attacker is using a skill
if attacker.do_skill?
# Get skill
skill = $data_skills[attacker.current_action.skill_id]
# Retaliate steal
retaliate_steal(attacker, skill)
# If attacker is using an item
elsif attacker.do_item?
# Get item
item = $data_items[attacker.current_action.item_id]
# Retaliate steal
retaliate_steal(attacker, item)
end
end
#-----------------------------------------------------------------------------
# * Retaliate Steal
#-----------------------------------------------------------------------------
def retaliate_steal(attacker, object)
# End method unless object performs steal/mug type effect
return unless object.do_steal?
# Set angry message
$scene.set_msg(@battler, msg_angry)
# Select attacker
@battler.set_target(attacker)
# Do Attack
@battler.do_attack
end
#-----------------------------------------------------------------------------
# * Death
#-----------------------------------------------------------------------------
def death(attacker)
# If battler had stolen before dying
if @battler.stolen_item > 0
# Re-appropriate very last item stolen
$game_party.gain_item(@battler.stolen_item, 1)
# If nothing was ever stolen
else
# Give a +5% EXP bonus to killer
$game_troop.bonus_exp[attacker] += 0.05
# Give a +5% Gold bonus to killer's party
$game_troop.bonus_gold += 0.05
end
end
end
BattleAI::Basilisk
Code:
#===============================================================================
# ** BattleAI::Basilisk
#-------------------------------------------------------------------------------
# A lazy lizard monster with a savage bite and nails of steel. If you
# discover it sleeping think twice about waking it up.
#===============================================================================
class BattleAI::Basilisk
#-----------------------------------------------------------------------------
# * Setup
#-----------------------------------------------------------------------------
def setup
# Default provoked false
@provoked = false
# Default sleeping flag
@sleeping = false
# If 1/3 (33%) chance
if rand(1..3) == 3
# Start out with "Sleep"
@battler.add_state(18)
# Set flag
@sleeping = true
end
end
#-----------------------------------------------------------------------------
# * Process
#-----------------------------------------------------------------------------
def process
# Do nothing if unprovoked
return unless @provoked
# Set step to random number
@step = rand(1..16)
# If 3/8 (38%)
if @step.between?(1..6)
# Select nearest foe
@battler.set_target(:foe_nearest)
# Use Skill ("Bite")
@battler.do_skill(150)
# If 3/8 (37%)
elsif @step.between?(7..12)
# Select random foe
@battler.set_target(:foe_random)
# Use Skill ("Claw")
@battler.do_skill(151)
# If 1/4 (25%)
elsif @step.between?(13..16)
# If 3/4 (75%) and can use "Slow" skill
if (rand(1..4) < 4) && @battler.skill_can_use?(49)
# Default nil target
target = nil
# Get list of actors sorted from slowest to fastest
actors = $game_party.actors.sort {|a, b| a.agi <=> b.agi}
# Go through each actor from fastest to slowest
actors.reverse.each do |actor|
# Next if already has "Slow" state or immobile
next if (actor.state?(26) || !actor.movable?)
# Select target
target = actor
end
# Unless no target
unless target.nil?
# Select target
@battler.set_target(target)
# Do Skill ("Slow")
@battler.use_skill(49)
# End method
return
end
end
# Select nearest foe
@battler.set_target(:foe_nearest)
# Do Attack
@battler.do_attack
end
end
#-----------------------------------------------------------------------------
# * Counter
#-----------------------------------------------------------------------------
def counter(attacker)
# Set provoked flag if damage taken
@provoked = (@battler.hp < @battler.maxhp)
# If attacker is using a skill
if attacker.do_skill?
# Get skill
skill = $data_skills[attacker.current_action.skill_id]
# Provoked if stolen from
steal_provoke(attacker, skill)
# If attacker is using an item
elsif attacker.do_item?
# Get item
item = $data_items[attacker.current_action.item_id]
# Provoked if stolen from
steal_provoke(attacker, item)
end
end
#-----------------------------------------------------------------------------
# * Steal Provoke
#-----------------------------------------------------------------------------
def steal_provoke(attacker, object)
# Set provoked flag if stealing and not "Sleep"
@provoked = true if object.do_steal? && !@battler.state?(18)
end
#-----------------------------------------------------------------------------
# * Death
#-----------------------------------------------------------------------------
def death(attacker)
# Do nothing
end
end
The oldschool "Action List" style enemies are still functional for when I want to use it, but I'll be doing these for tricky enemies and most of the more difficult boss fights. I'm amazed at how much there is to define just for a simple fly-by random encounter, but bosses will be a lot more fun to design and fight from now on!
I like to write enemy routine scripts, it gives for a lot of cunning and calculating on part of the acting enemy. As such, a Ghost will iterate through the actor with the most skills to the actor with the least skills and determine if they need to inflict "Silence" or not, prioritizing the one with the most potential skills whom doesn't already have "Silence". The physical attackers have to deal with Ghosts vanishing all the time so either way it makes for an annoying to potentially difficult fight depending on your level and patience.
ANIMATED/AI BATTLER PROGRESS
Heroes
Logan - Character (100%) Battler (112% (Most Poses/Actions))
Mac - Character (100%) Battler (60%)
Sasha - Character (100%) Battler (30%)
Enemies
Ghost - Animated/AI
Soldier 1 - Animated (80%)
Soldier 2 - Animated (100%)
Cain (Knight Blade) - Animated
Basilisk - Animated/AI
Hellhound - Animated/AI
Hellraiser - AI (No animation yet :( )
Tesla Wyrm - Animated/AI
Triterrortops - Animated/AI
Doberman - Animated/AI
Cobra - Animated
Razor Palm - Animated
Oily Body - Animated
Flame Soul - Animated/AI
Other Characters
Locke (FF6) - Character/Battler
Sabin (FF6) - Character/Battler
Celes (FF6) - Character/Battler
Terra (FF6) - Character/Battler
Cloud (FF7) - Character
Tifa (FF7) - Character/Battler (155% (Most Poses/Actions))
Aeris (FF7) - Character/Battler
Ward (FF8) - Character
Red Baron (Shining Force II) - Character/Battler
Ghestal (Shining Force II) - Battler (20%)
I'll probably be doing more non-original characters during the expansion process of the animated battler template I've been creating. It's easier to beta animations when you're designing familiar heroes/villians than if you were to worry about creating a new character from scratch too. Thanks to Tifa, my females have so much more actions than the males so the boys will have to eventually catch up. Heck, Cloud doesn't even have a battler designed for him yet - not that it's on my high priorities list - but I might get to him soon just because it bugs me.
My internet connection sucks and I can't get IRC to work, plus I work a lot, so I don't know how much I'll be around after the holidays. Still, I'll try to drop in once in awhile just so people know I'm alive lol.