RPG NPC ActorsAuthor: Jens of Zanicuud
Version: 1.0
Released on: 9 Dec 2011
Terms of use: Free use, just credit; for commercial use, you have to ask for permission.
Customization: Free, just link the mod version in this topic...
FAQ or help:Feel free to ask for everything.
Hello everyone again.
This time I'll post the Game_NPC script system...
It handles with heroes controlled by computer. You can set their actions ratings in the Skill panel...
I think it could be useful for host characters or Summons.
To use it, just create a new script and paste the code below.
N.B. You'll need to download these files and put it in the Icons folder to let this script work.
Icons.zip ( 1.46K )
Number of downloads: 44CODE
#==============================================================================
# ** Game_NPC Version 1.0 - Jens of Zanicuud
# Free use, but credit is needed. You can find me on www.rpgrevolution.com
# Just advise me if you want to employ it anywhere
#------------------------------------------------------------------------------
# This class handles with actors controlled by CPU...
# In Skill Window you can set the rating of their actions.
#
#==============================================================================
NPC = [5,6] #Set here the IDs of all NPC actors
#==============================================================================
# ** Game_Party
#------------------------------------------------------------------------------
# This class handles the party. It includes information on amount of gold
# and items. Refer to "$game_party" for the instance of this class.
#==============================================================================
class Game_Party
#--------------------------------------------------------------------------
# * good_health? (i.e. all party with heal greater than 70%)
#--------------------------------------------------------------------------
def good_health?
flag = true
for actor in self.actors
if actor.hp*100/actor.maxhp < 70.0
flag = false
end
end
return flag
end
#--------------------------------------------------------------------------
# * weakest actor (i.e. actors with lesser heal)
#--------------------------------------------------------------------------
def weakest_actors_roulette
weakest = [self.actors[0]]
for actor in self.actors
if actor.hp*100/actor.maxhp < weakest[0].hp*100/actor.maxhp
weakest = [actor]
elsif actor.hp*100/actor.maxhp == weakest[0].hp*100/actor.maxhp
weakest.push(actor)
end
end
return weakest[rand(weakest.size)]
end
end
#==============================================================================
# ** Game_Game_BattleAction
#------------------------------------------------------------------------------
# Added ratings in actions
#==============================================================================
class Game_BattleAction
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :speed # speed
attr_accessor :kind # kind (basic / skill / item)
attr_accessor :basic # basic (attack / guard / escape)
attr_accessor :skill_id # skill ID
attr_accessor :item_id # item ID
attr_accessor :target_index # target index
attr_accessor :forcing # forced flag
attr_accessor :rating # rating
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
clear
end
#--------------------------------------------------------------------------
# * Clear
#--------------------------------------------------------------------------
def clear
@speed = 0
@kind = 0
@basic = 3
@skill_id = 0
@item_id = 0
@target_index = -1
@forcing = false
@rating = 0
end
#--------------------------------------------------------------------------
# * Skill
#--------------------------------------------------------------------------
def skill
return $data_skills[self.skill_id]
end
#--------------------------------------------------------------------------
# * Random Target (for NPC)
#--------------------------------------------------------------------------
def decide_random_target_for_NPC
# Diverge with effect scope
#NEW HP check
if self.kind == 1 and self.skill.power < 0
if for_one_friend?
battler = $game_party.weakest_actors_roulette
end
end
if battler == nil
if for_one_friend_hp0?
battler = $game_party.random_target_actor_hp0
elsif for_one_friend?
battler = $game_party.random_target_actor
else
battler = $game_troop.random_target_enemy
end
end
# If a target exists, get an index, and if a target doesn't exist,
# clear the action
if battler != nil
@target_index = battler.index
else
clear
end
end
end
#==============================================================================
# ** Game_NPC
#------------------------------------------------------------------------------
# This class handles the actor. It's used within the Game_Actors class
# ($game_actors) and refers to the Game_Party class ($game_party).
#==============================================================================
class Game_NPC < Game_Actor
#--------------------------------------------------------------------------
# * Setup
# actor_id : actor ID
#--------------------------------------------------------------------------
def setup(actor_id)
super
@rates = {}
for i in -3...$data_skills.size
@rates[i] = 4
end
end
#--------------------------------------------------------------------------
# * Actions
#--------------------------------------------------------------------------
def actions
act = []
for id in self.skills
skill = $data_skills[id]
ab = Game_BattleAction.new
ab.kind = 1
ab.skill_id = skill.id
ab.rating = @rates[skill.id]
act.push(ab)
end
ab = Game_BattleAction.new
ab.kind = 0
ab.basic = 0
ab.rating = @rates[0]
act.push(ab)
ab = Game_BattleAction.new
ab.kind = 0
ab.basic = 1
ab.rating = @rates[-1]
act.push(ab)
return act
end
#--------------------------------------------------------------------------
# * Rates
#--------------------------------------------------------------------------
def rates(index)
return @rates[index]
end
#--------------------------------------------------------------------------
# * Change Rates
#--------------------------------------------------------------------------
def change_rate(skill_id,rate)
@rates[skill_id] = rate
end
#--------------------------------------------------------------------------
# * Make Action
#--------------------------------------------------------------------------
def make_action
# Clear current action
self.current_action.clear
# If unable to move
unless self.movable?
# End Method
return
end
# Extract current effective actions
available_actions = []
rating_max = 0
for action in self.actions
# Confirm sp conditions
if action.kind == 1 and $data_skills[action.skill_id].sp_cost>self.sp
next
end
# Confirm rating conditions
if action.rating == 0
next
end
#NEW# Stop healing skills to be used if there's no target
test_skill = $data_skills[action.skill_id]
if action.kind == 1 and test_skill.power < 0 and
(test_skill.scope == 3 or test_skill.scope == 4)
if $game_party.good_health?
next
end
end
# Add this action to applicable conditions
available_actions.push(action)
if action.rating > rating_max
rating_max = action.rating
end
end
# Calculate total with max rating value at 3 (exclude 0 or less)
ratings_total = 0
for action in available_actions
if action.rating > rating_max - 3
ratings_total += action.rating - (rating_max - 3)
end
end
# If ratings total isn't 0
if ratings_total > 0
# Create random numbers
value = rand(ratings_total)
# Set things that correspond to created random numbers as current action
for action in available_actions
if action.rating > rating_max - 3
if value < action.rating - (rating_max - 3)
self.current_action.kind = action.kind
self.current_action.basic = action.basic
self.current_action.skill_id = action.skill_id
self.current_action.decide_random_target_for_NPC
return
else
value -= action.rating - (rating_max - 3)
end
end
end
end
end
#--------------------------------------------------------------------------
# * Inputable?
#--------------------------------------------------------------------------
def inputable?
return false
end
end
#==============================================================================
# ** Game_Actors
#------------------------------------------------------------------------------
# This class handles the actor array. Refer to "$game_actors" for each
# instance of this class.
#==============================================================================
class Game_Actors
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@data = []
end
#--------------------------------------------------------------------------
# * Get Actor
# actor_id : actor ID
#--------------------------------------------------------------------------
def [](actor_id)
if actor_id > 999 or $data_actors[actor_id] == nil
return nil
end
if @data[actor_id] == nil
if NPC.include?(actor_id)
@data[actor_id] = Game_NPC.new(actor_id)
else
@data[actor_id] = Game_Actor.new(actor_id)
end
end
return @data[actor_id]
end
#--------------------------------------------------------------------------
# * Change to NPC
# actor_id : actor ID
#--------------------------------------------------------------------------
def change_to_NPC(id)
@data[id] = Game_NPC.new(id)
end
end
#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
# This class performs battle screen processing.
#==============================================================================
class Scene_Battle
#--------------------------------------------------------------------------
# * Start Main Phase
#--------------------------------------------------------------------------
def start_phase4
# Shift to phase 4
@phase = 4
# Turn count
$game_temp.battle_turn += 1
# Search all battle event pages
for index in 0...$data_troops[@troop_id].pages.size
# Get event page
page = $data_troops[@troop_id].pages[index]
# If this page span is [turn]
if page.span == 1
# Clear action completed flags
$game_temp.battle_event_flags[index] = false
end
end
# Set actor as unselectable
@actor_index = -1
@active_battler = nil
# Enable party command window
@party_command_window.active = false
@party_command_window.visible = false
# Disable actor command window
@actor_command_window.active = false
@actor_command_window.visible = false
# Set main phase flag
$game_temp.battle_main_phase = true
# Make enemy action
for enemy in $game_troop.enemies
enemy.make_action
end
for actor in $game_party.actors
if actor.is_a?(Game_NPC)
actor.make_action
end
end
# Make action orders
make_action_orders
# Shift to step 1
@phase4_step = 1
end
end
#==============================================================================
# ** Window_Skill
#------------------------------------------------------------------------------
# This window displays usable skills on the skill and battle screens.
#==============================================================================
class Window_Skill < Window_Selectable
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
@data.push("Attacco") if @actor.is_a?(Game_NPC)
@data.push("Guardia") if @actor.is_a?(Game_NPC)
for i in 0...@actor.skills.size
skill = $data_skills[@actor.skills[i]]
if skill != nil
@data.push(skill)
end
end
# If item count is not 0, make a bit map and draw all items
@item_max = @data.size
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_item(i)
end
end
end
#--------------------------------------------------------------------------
# * Draw Item
# index : item number
#--------------------------------------------------------------------------
def draw_item(index)
skill = @data[index]
if skill.is_a?(String)
case skill
when "Attacco"
id = 0
when "Guardia"
id = -1
end
self.contents.font.color = normal_color
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
case @actor.rates(id)
when 5
bitmap = RPG::Cache.icon("High")
when 4
bitmap = RPG::Cache.icon("Medium")
when 3
bitmap = RPG::Cache.icon("Low")
when 0
bitmap = RPG::Cache.icon("Never")
end
opacity = 255
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 204, 32, skill, 0)
else
if @actor.skill_can_use?(skill.id) or @actor.is_a?(Game_NPC)
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
if @actor.is_a?(Game_NPC)
case @actor.rates(skill.id)
when 5
bitmap = RPG::Cache.icon("High")
when 4
bitmap = RPG::Cache.icon("Medium")
when 3
bitmap = RPG::Cache.icon("Low")
when 0
bitmap = RPG::Cache.icon("Never")
end
else
bitmap = RPG::Cache.icon(skill.icon_name)
end
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
end
end
#--------------------------------------------------------------------------
# * Help Text Update
#--------------------------------------------------------------------------
def update_help
if self.skill == "Attack"
description = "Regular attack with equipped weapon."
elsif self.skill == "Guard"
description = "Halves damage received."
else
description = self.skill.description if self.skill != nil
end
@help_window.set_text(description == nil ? "" : description )
end
end
#==============================================================================
# ** Scene_Skill
#------------------------------------------------------------------------------
# This class performs skill screen processing.
#==============================================================================
class Scene_Skill
#--------------------------------------------------------------------------
# * Object Initialization
# actor_index : actor index
#--------------------------------------------------------------------------
def initialize(actor_index = 0, equip_index = 0)
@actor_index = actor_index
end
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
# Get actor
@actor = $game_party.actors[@actor_index]
# Make help window, status window, and skill window
@help_window = Window_Help.new
@status_window = Window_SkillStatus.new(@actor)
@skill_window = Window_Skill.new(@actor)
# Associate help window
@skill_window.help_window = @help_window
# Make target window (set to invisible / inactive)
@target_window = Window_Target.new
@target_window.visible = false
@target_window.active = false
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
if $scene != self
break
end
end
# Prepare for transition
Graphics.freeze
# Dispose of windows
@help_window.dispose
@status_window.dispose
@skill_window.dispose
@target_window.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Update windows
@help_window.update
@status_window.update
@skill_window.update
@target_window.update
# If skill window is active: call update_skill
if @skill_window.active
update_skill
return
end
# If skill target is active: call update_target
if @target_window.active
update_target
return
end
end
#--------------------------------------------------------------------------
# * Frame Update (if skill window is active)
#--------------------------------------------------------------------------
def update_skill
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Switch to menu screen
$scene = Scene_Menu.new(1)
return
end
# If C button was pressed
if @actor.is_a?(Game_NPC)
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
@skill = @skill_window.skill if @skill_window.index > 0
update_command
return
end
else
if Input.trigger?(Input::C)
# Get currently selected data on the skill window
@skill = @skill_window.skill
# If unable to use
if @skill == nil or not @actor.skill_can_use?(@skill.id)
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# Play decision SE
$game_system.se_play($data_system.decision_se)
# If effect scope is ally
if @skill.scope >= 3
# Activate target window
@skill_window.active = false
@target_window.x = (@skill_window.index + 1) % 2 * 304
@target_window.visible = true
@target_window.active = true
# Set cursor position to effect scope (single / all)
if @skill.scope == 4 || @skill.scope == 6
@target_window.index = -1
elsif @skill.scope == 7
@target_window.index = @actor_index - 10
else
@target_window.index = 0
end
# If effect scope is other than ally
else
# If common event ID is valid
if @skill.common_event_id > 0
# Common event call reservation
$game_temp.common_event_id = @skill.common_event_id
# Play use skill SE
$game_system.se_play(@skill.menu_se)
# Use up SP
@actor.sp -= @skill.sp_cost
# Remake each window content
@status_window.refresh
@skill_window.refresh
@target_window.refresh
# Switch to map screen
$scene = Scene_Map.new
return
end
end
return
end
end
# If R button was pressed
if Input.trigger?(Input::R)
# Play cursor SE
$game_system.se_play($data_system.cursor_se)
# To next actor
@actor_index += 1
@actor_index %= $game_party.actors.size
# Switch to different skill screen
$scene = Scene_Skill.new(@actor_index)
return
end
# If L button was pressed
if Input.trigger?(Input::L)
# Play cursor SE
$game_system.se_play($data_system.cursor_se)
# To previous actor
@actor_index += $game_party.actors.size - 1
@actor_index %= $game_party.actors.size
# Switch to different skill screen
$scene = Scene_Skill.new(@actor_index)
return
end
end
#--------------------------------------------------------------------------
# * Frame Update (when target window is active)
#--------------------------------------------------------------------------
def update_target
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Erase target window
@skill_window.active = true
@target_window.visible = false
@target_window.active = false
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# If unable to use because SP ran out
unless @actor.skill_can_use?(@skill.id)
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# If target is all
if @target_window.index == -1
# Apply skill use effects to entire party
used = false
for i in $game_party.actors
used |= i.skill_effect(@actor, @skill)
end
end
# If target is user
if @target_window.index <= -2
# Apply skill use effects to target actor
target = $game_party.actors[@target_window.index + 10]
used = target.skill_effect(@actor, @skill)
end
# If single target
if @target_window.index >= 0
# Apply skill use effects to target actor
target = $game_party.actors[@target_window.index]
used = target.skill_effect(@actor, @skill)
end
# If skill was used
if used
# Play skill use SE
$game_system.se_play(@skill.menu_se)
# Use up SP
@actor.sp -= @skill.sp_cost
# Remake each window content
@status_window.refresh
@skill_window.refresh
@target_window.refresh
# If entire party is dead
if $game_party.all_dead?
# Switch to game over screen
$scene = Scene_Gameover.new
return
end
# If command event ID is valid
if @skill.common_event_id > 0
# Command event call reservation
$game_temp.common_event_id = @skill.common_event_id
# Switch to map screen
$scene = Scene_Map.new
return
end
end
# If skill wasn't used
unless used
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
end
return
end
end
#--------------------------------------------------------------------------
# * Frame Update (when arrow window is active)
#--------------------------------------------------------------------------
def update_command
if @skill_window.index == 0
rate = 0
elsif @skill_window.index == 1
rate = -1
else
rate = @skill.id
end
case @actor.rates(rate)
when 0
rate = 3
when 3
rate = 4
when 4
rate = 5
when 5
rate = 0
end
if @skill_window.index == 0
@actor.change_rate(0,rate)
elsif @skill_window.index == 1
@actor.change_rate(-1,rate)
else
@actor.change_rate(@skill.id,rate)
end
@skill_window.refresh
return
end
end
That's all folks! I hope it can be useful.
See you next script...
Jens
This post has been edited by Jens of Zanicuud: Dec 10 2011, 04:51 AM