The help would be very much appreciated.
Thanks,
Andy
Code:
=begin
================================================================================
Extended Troops
Author: Night Runner, Tsukihime
Version: 0.2
Date: May 1, 2012
--------------------------------------------------------------------------------
** Change log
0.2 May 7, 2012
-introduced bias and deviation
-added "final" option
-added "include" option
0.1 May 1, 2012
-initial release
================================================================================
** Instructions
This system extends the enemy troop management system by allowing you to
specify more options for a particular troop. It uses probabilistic methods
to generate enemies depending on the given inputs.
The system provides a set of options that you can set in a game troop's
event list using comments. You start by specifying the number of enemies
<numenemies=1>
You can also specify min/max ranges instead of a fixed number
<minenemies=1, maxenemies=3>
Additionally, you may bias the number generator towards a specific
range of numbers using a specified bias and optionally a deviance
<minenemies=2, maxenemies=7, bias=3, deviance=1>
Then you specify which enemies should be randomly selected. The engine
will pick an arbitrary number of enemies until it has satisfies the number
of enemies that was generated from above.
The simplest way to specify an enemy is to provide its name
<name=slime>
You may specify different enemies to be chosen by adding a new line for each
<name=slime>
<name=wisp>
<name=werewolf>
Additional options can be added to provide more interesting results.
For example, if you want one enemy to statistically occur more often, you
can specify the weight
<name=slime, weight=100>
<name=wisp, weight=10>
This would mean wisps will occur less frequently than slimes
There are a variety of options that you can choose as well. They are
described below.
If you run out of comment space, simply create a new comment and continue
from there. All entries must appear together though (no other events in
in between)
--------------------------------------------------------------------------------
** Options
All options will be comma-separated within an entry.
<option1=val, option2, option3=val, option4, ... >
== Troop size options ==
* NumEnemies=integer
Number of enemies that can appear
* MinEnemies=integer
Minimum number of enemies that can appear.
* MaxEnemies=integer
Maximum number of enemies that can appear.
* Bias=integer
* Deviation=integer
== Enemy entry options ==
* Name=name
The name of the enemy that should appear. Same as the name in the
database
* Weight=integer
Adjusts how frequent the enemy will appear compared to other enemies
* Spots=integer
How many "spots" an enemy takes up. This represents the size of an enemy.
An enemy with "spots=2" means that they count as 2 enemies and so if your
numenemies is 5, you can only have 3 more.
* PackOnly
This forces the troop to contain only that enemy.
* PackSize=integer
Enemies will be added in groups of the specified integer. So if PackSize=2,
then the enemy will always appear in pairs, assuming there is enough room
in the
* Avoid="name1;name2;..."
The enemies that are listed in this option will not appear with the troop.
The specified enemies must have entries specified.
* Include="name1;name2;..."
The enemies that are listed in this option will automatically appear with
the enemy. The specified enemies must have entries specified.
* Final
If this enemy is selected, the engine will proceed to create the troop even
if the maximum size has not been met
================================================================================
=end
module NR_EncounterSystem_Config
#name of the options. You can change all of these if you want.
MaxEnemiesText = 'maxenemies'
MinEnemiesText = 'minenemies'
NumEnemiesText = 'numenemies'
BiasText = 'bias'
DeviationText = 'deviation'
NameText = 'name'
WeightText = 'weight'
MaxText = 'max'
SpotsText = 'spots'
PackSizeText = 'packsize'
AvoidText = 'avoid'
PackOnlyText = 'packonly'
FinalText = 'final'
IncludeText = 'include'
Delimiter = ';'
end
#================================================================================
# Rest of the script
#================================================================================
module NR_EncounterSystem_Config
DefaultWeight = 100
DefaultMin = 1
DefaultMax = 8
DefaultDeviation = 2
DefaultSpots = 1
DefaultPackOnly = false
DefaultPackSize = 1
DefaultAvoid = []
DefaultFinalEnemy = false
DefaultInclude = []
MaxEnemiesRegex = /#{MinEnemiesText}\s*\=\s*((\d)+)/
MinEnemiesRegex = /#{MaxEnemiesText}\s*=\s*((\d)+)/
NumEnemiesRegex = /#{NumEnemiesText}\s*=\s*((\d)+)/
BiasRegex = /#{BiasText}\s*=\s*((\d)+)/
DeviationRegex = /#{DeviationText}\s*=\s*((\d)+)/
NameRegex = /#{NameText}\s*=\s*([^,]*),/
WeightRegex = /#{WeightText}\s*=\s*([^,]*),/
MaxRegex = /#{MaxText}\s*=\s*([^,]*),/
SpotsRegex = /#{SpotsText}\s*=\s*([^,]*),/
PackSizeRegex = /#{PackSizeText}\s*=\s*([^,]*),/
AvoidRegex = /#{AvoidText}\s*=\s*([^,]*),/
PackOnlyRegex = /#{PackOnlyText}\s*(=\s*([^,]*)),/
FinalRegex = /#{FinalText}\s*,/
IncludeRegex = /#{IncludeText}\s*=\s*([^,]*),/
end
#==============================================================================
# ** Game_Troop
#------------------------------------------------------------------------------
# Modified to have random battlers.
#==============================================================================
class Game_Troop
#--------------------------------------------------------------------------
# * Include Modules
#--------------------------------------------------------------------------
include NR_EncounterSystem_Config
#--------------------------------------------------------------------------
# * Get Troop Objects
#--------------------------------------------------------------------------
def troop
@troops
end
#--------------------------------------------------------------------------
# * Setup
#--------------------------------------------------------------------------
alias nr_encounter_system_setup setup unless $@
def setup(troop_id)
setup_enemies(troop_id)
nr_encounter_system_setup(troop_id)
end
#--------------------------------------------------------------------------
# * Setup
#--------------------------------------------------------------------------
def setup_enemies(troop_id)
# Get the enemy troop
@troops = $data_troops[troop_id]
# Check if the first command on the first page is a comment
get_num_enemies
return if @num_enemies <= 0
p "Maximum number of enemies: #{@num_enemies}"
# Parse possible enemies
@enemies = []
@total_weighting = 0
parse_possible_enemies
@members = []
@members_size = 0
generate_enemies
create_enemy_troop
end
#--------------------------------------------------------------------------
# * Just a biased sample
#--------------------------------------------------------------------------
def biased_sample(range, bias, dev)
integers = range.to_a
(bias-dev..bias+dev).each {|n| integers << n}
integers.sample
end
#--------------------------------------------------------------------------
# * Generate random number of enemies
#--------------------------------------------------------------------------
def generate_number(high, low, bias, deviation)
# introduce a bias towards a certain range of numbers
if bias
num = biased_sample(low..high, bias, deviation)
else
num = Random.rand(high + 1 - low) + low
end
return num
end
#--------------------------------------------------------------------------
# * Get Number of Enemies
#--------------------------------------------------------------------------
def get_num_enemies
if @troops.pages[0].list[0].code == 108
# Get the text in the comment
@text = ""
index = 0
begin
@text += @troops.pages[0].list[index].parameters[0].downcase
index += 1
end while [108, 408].include? @troops.pages[0].list[index].code
# Get the number of enemies (do nothing if not stated)
if @text.include?(MaxEnemiesText)
min_enemies = @text.scan(MaxEnemiesRegex)[0]
max_enemies = @text.scan(MinEnemiesRegex)[0][0].to_i
bias = @text.scan(BiasRegex)[0][0].to_i
deviation = @text.scan(DeviationRegex)[0]
min_enemies = min_enemies == nil ? DefaultMin : min_enemies[0].to_i
deviation = deviation == nil ? DefaultDeviation : deviation[0].to_i
@num_enemies = generate_number(max_enemies, min_enemies, bias, deviation)
elsif @text.include?(NumEnemiesText)
@num_enemies = @text.scan(NumEnemiesRegex)[0][0].to_i
else
@num_enemies = -1
end
end
end
#--------------------------------------------------------------------------
# * Parse Possible Enemies
#--------------------------------------------------------------------------
def parse_possible_enemies
# Parse the enemies
for line in @text.split(/<([^<>]*)>/).map { |s| s + ',' }
next if not line.include?(NameText)
name = line.scan(NameRegex)[0][0]
weight = line.scan(WeightRegex)[0]
weight = weight == nil ? DefaultWeight : weight[0].to_i
@total_weighting += weight
max = line.scan(MaxRegex)[0]
max = max == nil ? DefaultMax : max[0].to_i
spots = line.scan(SpotsRegex)[0]
spots = spots == nil ? DefaultSpots : spots[0].to_i
packsize = line.scan(PackSizeRegex)[0]
packsize = packsize == nil ? DefaultPackSize : packsize[0].to_i
avoid = line.scan(AvoidRegex)[0]
avoid = avoid == nil ? DefaultAvoid : avoid[0].split(Delimiter)
packonly = line.scan(PackOnlyRegex)[0]
packonly = packonly == nil ? DefaultPackOnly : true
final = line.scan(FinalRegex)[0]
finalenemy = final == nil ? DefaultFinalEnemy : true
include = line.scan(IncludeRegex)[0]
include = include == nil ? DefaultInclude : include[0].split(Delimiter)
enemy = {
:name => name,
:weight => weight,
:max => max,
:spots => spots,
:packsize => packsize,
:avoid => avoid,
:packonly => packonly,
:finalenemy => finalenemy,
:include => include,
}
@enemies << enemy
end
end
#--------------------------------------------------------------------------
# * Generate Enemies Array
#--------------------------------------------------------------------------
def generate_enemies
# Generate the enemies
@max_wait_loops = 10
loops_since_member_added = 0
begin
loops_since_member_added += 1
enemy_weight = Random.rand(@total_weighting + 1) + 1
for enemy in @enemies
enemy_weight -= enemy[:weight]
if (enemy_weight <= 0) and (can_add_enemy?(enemy))
# If this is a pack enemy, remove the rest from the enemy group
if enemy[:packonly]
for e in @enemies
if e != enemy
@total_weighting -= e[:weight]
e[:weight] = -1
end
end
end
# Add the enemy to the party
loops_since_member_added = 0
add_enemy(enemy)
# Add the enemy's allies
for ally in enemy[:include]
enemy = @enemies.find { |en| en[:name] == ally }
add_enemy(enemy)
end
if enemy[:finalenemy] == true
loops_since_member_added = @max_wait_loops
end
end
end
end while (@members_size < @num_enemies) and
(loops_since_member_added < @max_wait_loops)
#shuffle them up
@members.shuffle
end
#--------------------------------------------------------------------------
# * Can Add Enemy?
#--------------------------------------------------------------------------
def can_add_enemy?(enemy)
# Skip is appropriate
return false if enemy[:weight] < 0
# Get the number of enemy spots for this enemy
en_spots = enemy[:spots] * enemy[:packsize]
# Skip if this will make too many enemies in the party
return false if @members_size + en_spots > @num_enemies
# Check if this will make too many of this enemy
num_this_enemy = @members.count(enemy)
return false if num_this_enemy > enemy[:max]
# Skip this enemy if it's avoid is in the members list
return false if not (@members & enemy[:avoid]).empty?
# Skip if packonly and other enemies are in the array
has_other_members = @members.select { |en| enemy[:name] != en }
return false if (enemy[:packonly]) and not (has_other_members.empty?)
# Otherwise, it can be part of the party.
return true
end
#--------------------------------------------------------------------------
# * Add Enemy
#--------------------------------------------------------------------------
def add_enemy(enemy)
@members += [enemy[:name]] * enemy[:packsize]
@members_size += enemy[:spots] * enemy[:packsize]
if @members.count(enemy[:name]) >= enemy[:max]
@total_weighting -= enemy[:weight]
enemy[:weight] = -1
end
end
#--------------------------------------------------------------------------
# * Create Enemy Troop
#--------------------------------------------------------------------------
def create_enemy_troop
# Create the troops array
@troops.members = []
for index in 0...@members.size
enemy = @members[index]
enemy_ID = $data_enemies.select { |en|
next if en.nil?; enemy == en.name.downcase }[0].id
troop_member = RPG::Troop::Member.new
troop_member.enemy_id = enemy_ID
@troops.members << troop_member
end
reorganise_troops_positions
end
#--------------------------------------------------------------------------
# * Reorganise Troops Positions
#--------------------------------------------------------------------------
def reorganise_troops_positions
num_members = @troops.members.size
for index in 0...num_members
troop_member = @troops.members[index]
enemy_width = 128
enemy_height = 96
max_across = Graphics.width / enemy_width
left = (Graphics.width - [num_members, max_across].min * enemy_width) / 2
troop_member.x = left + (index % max_across) * enemy_width
troop_member.y = 280 - (index / max_across) * enemy_height
end
end
end
#==============================================================================
# ** End of Script.
#==============================================================================