Pidey's User customizable AI Version: Alpha3
Introduction This script not only provides an AI for one character, it also provides a way of modifying the AI while in game. This is done by inserting items that represent snippets of code into the "AI window"
Features Very customizable by the user Ability to customize limited by items, thus the game designer can gradually unlock this complex feature Easy to add new potential lines Screenshots http://i12.photobucket.com/albums/a231/pidey/aidemopic.png Script Spoiler for "Main AI" :
class GratheAI def main $game_variables[74]=1 if $game_variables[74] == 100 throw_error end while $game_variables[71] >= 105 && $game_variables[74] <= 100 execute_line end if $game_variables[71] == 0 $game_variables[75]+=1 $game_variables[74]=1 end $game_variables[71]=500 #done so that the while statement isn't improperly tripped next time end def execute_line $game_variables[71] = $grathe_code[$game_variables[75]] #Stores the contents of the current line $game_variables[72] = $grathe_code2[$game_variables[75]] #Stores the location the line redirects to. if $game_variables[71] >= 105 # this means its redirect statement change_statement else chose_action $game_variables[75]+=1 end $game_variables[74]+=1 end def chose_action case $game_variables[71] #checks contents of current line #Note7 when 83 #attack random action_passer(0, 0, -1) when 84 #Attack last action_passer(0, 0, -1) when 85 #defend action_passer(0,1,-1) when 86 #bullet rain if $game_actors[6].sp>=50 $game_actors[6].sp -= 50 action_passer(1,100,-1) else throw_error end when 87 #recharge $game_actors[6].sp += 35 action_passer(1,101,-1) when 88 #Concentrate Fire if $game_actors[6].sp>=50 $game_actors[6].sp -= 50 action_passer(1,102,-1) else throw_error end when 89 #double burst if $game_actors[6].sp>=35 $game_actors[6].sp -= 35 action_passer(1,105,-1) else throw_error end when 90 #heal self if $game_actors[6].sp>=5 $game_actors[6].sp -= 5 action_passer(1,106,-1) else throw_error end end end def throw_error action_passer(1,83,-1) #Note8 end def change_statement goto = false case $game_variables[71] #checks contents of current line #Note 9 when 105 #a goto statement goto = true when 106 #SelfHP%>=25 # p (($game_actors[6].maxhp / 4) <= $game_actors[6].hp).to_s goto = ($game_actors[6].maxhp / 4) <= $game_actors[6].hp when 107 #selfMP>=50 goto = $game_actors[6].sp >= 50 when 108 #selfMP>=10 goto = $game_actors[6].sp >= 10 when 109 #random redirect $game_variables[72] = rand(7).round goto = true when 110 #50% chance of redirect goto = rand(2) == 1 when 111#10% chance of redirect goto = rand(10)>=9 #Add additional Redirect statements here end if goto $game_variables[75] = $game_variables[72] else $game_variables[75]+=1 end end #-------------------------------------------------------------------------- # * Force Action #-------------------------------------------------------------------------- def action_passer(action_type, action_id, target) # Ignore if not in battle unless $game_temp.in_battle return true end # Ignore if number of turns = 0 if $game_temp.battle_turn == 0 return true end # Process with iterator (For convenience, this process won't be repeated) iterate_battler(1, 0) do |battler| #Note6 # If battler exists if battler.exist? # Set action battler.current_action.kind = action_type if battler.current_action.kind == action_id battler.current_action.basic = action_id else battler.current_action.skill_id = action_id end # Set action target if target == -2 # -2 means last enemy battler.current_action.decide_last_target_for_actor elsif target == -1 # -1 means random enemy battler.current_action.decide_random_target_for_actor elsif target >= 0 battler.current_action.target_index = target end # Set force flag # If action is valid if battler.current_action.valid? battler.current_action.forcing = true # Set battler being forced into action $game_temp.forcing_battler = battler # End return false end end end # Continue return true end #-------------------------------------------------------------------------- # * Battler Iterator (consider entire troop and entire party) # parameter1 : If 0, enemy; if 1, actor # parameter2 : If 0 or above, index; if -1, all #-------------------------------------------------------------------------- def iterate_battler(parameter1, parameter2) # If enemy if parameter1 == 0 # Call enemy iterator iterate_enemy(parameter2) do |enemy| yield enemy end # If actor else # If entire party if parameter2 == -1 # Loop for entire party for actor in $game_party.actors # Evaluate block yield actor end # If single actor (N exposed) else # Get actor actor = $game_party.actors[parameter2] # Evaluate block yield actor if actor != nil end end end end
Spoiler for "Window1" :
class Window_Grathe_code_left < Window_Base #-------------------------------------------------------------------------- # * Object Initialization #-------------------------------------------------------------------------- def initialize(selectedline) super(0, 64, 320, 416) self.contents = Bitmap.new(width - 32, height - 32) self.contents.font.name = $fontface self.contents.font.size = $fontsize refresh(selectedline) end def refresh(selectedline) self.contents.clear if $choosing_line bitmap = RPG::Cache.picture('Highlighter') self.contents.blt(-19,-82, bitmap, Rect.new(0, 0, 640, 640)) end determine_line(selectedline-4,16) determine_line(selectedline-3,48) determine_line(selectedline-2,80) determine_line(selectedline-1,112) determine_line(selectedline,176) determine_line(selectedline+1,240) determine_line(selectedline+2,272) determine_line(selectedline+3,304) determine_line(selectedline+4,336) end def determine_line(linetodraw,y) if linetodraw<=0 or linetodraw > 150 return true else self.contents.draw_text (16, y, 48, 32, linetodraw.to_s) draw_item_name($data_items[$grathe_code[linetodraw]],58,y) self.contents.draw_text(250,y,64,32, $grathe_code2[linetodraw].to_s) end end end
Spoiler for "Window2" :
Note: This window doesn't do anything currently, but its a goodplace to put.... something.
class Window_Grathe_status < Window_Base def initialize super(320, 64, 320, 180) self.contents = Bitmap.new(width - 32, height - 32) self.contents.font.name = $fontface self.contents.font.size = $fontsize refresh end def refresh end end
Spoiler for "Window3" :
class Window_Grathe_unused < Window_Base def initialize(x,y) super(320, 244, 320, 236) self.contents = Bitmap.new(width - 32, height - 32) self.contents.font.name = $fontface self.contents.font.size = $fontsize @llega = 0 refresh(x,y) end def refresh(a,b) self.contents.clear if b == 0 #action c = 83 #Note 1 d = 103 #Note 2 else #a redirect c =105 #Note 3 d =125 #Note 4 end if !$choosing_line bitmap = RPG::Cache.picture('Highlighter') self.contents.blt(-19,-164, bitmap, Rect.new(0, 0, 640, 640)) end if b #drawing actions, items 83-103 draw_item_name($data_items[a], 64, 96) self.contents.draw_text(16,96,64,32, $game_party.item_number(a).to_s) if a-1>=c # Ensures it doesn't draw an item that isn't of the right type. draw_item_name($data_items[a-1], 64, 48) self.contents.draw_text(16,48,64,32, $game_party.item_number(a-1).to_s) if a-2>=c draw_item_name($data_items[a-2], 64, 16) self.contents.draw_text(16,16,64,32, $game_party.item_number(a-2).to_s) end end if a+1<=d draw_item_name($data_items[a+1], 64, 144) self.contents.draw_text(16,144,64,32, $game_party.item_number(a+1).to_s) if a+2<=d draw_item_name($data_items[a+2], 64, 176) self.contents.draw_text(16,176,64,32, $game_party.item_number(a+2).to_s) end end end end end
Instructions Place each of the above scripts in the game, I know that six is quite a few, but, they are all needed. Also download the attached file "highlighter" and put it in the pictures folder.
To bring up the AI editing screen, simply use the line $scene = Scene_grathe_code.new
Also, in scene_title, after command_new_game and in battle_test, insert these lines
$grathe_code =Grathe_Code_Bank.new $grathe_code2 =Grathe_Code_Bank2.new $grathe_AI = GratheAI.new
in Scene_load add these lines after all of the marshal.load
$grathe_code = Marshal.load(file) $grathe_code2 = Marshal.load(file) $grathe_AI = Marshal.load(file)
In Scene_save, add these after all of the Marshal.dump
Marshal.dump($grathe_code, file) Marshal.dump($grathe_code2, file) Marshal.dump($grathe_AI, file)
Also, I put various notes in the script in places that need to be customized for your specific game (my values are still in there)
Note1 This should be the number of the lowest action statement
Note2 This should be the number of the highest action statement
Note3 This should be the number of the lowest redirect statement
note4 This should be the number of the highest redirect statement
Note5 This should be the difference between the number of the lowest action statement and the number of the lowest redirect statement
Note6 Replace the 0 in this line with the location of the hero in the party (if he is 1st, keep it at 0, if he is 2nd, replace it with 1, if he is 3rd replace w/2, if he is 4th replace with 3.)
Note7 Here you have to impliment your own action lines, simply call action_passer(a,b,c)
A is 1 for a skill, and 0 for a regular action, B is the number of the skill, or for an action, 0 is attack, 1 is defend. Leave C to be -1, I can't fix it yet.
Note8 Replace the 83 with the skill you want performed upon failure of the AI.
Note9 Here is where the redirect lines are chosen, goto is a boolean, and simply make it true if you want it to redirect.
Note10 Here you can impliment the default AI. This section contains what item is in each line
Note11 Here you can impliment the default AI. This section contains where each line redirects to.
To add potential lines, dedicate a continuous chunk of 20 or so (more if you want) lines for actions, and THE SAME NUMBER for redirect statements. Name and description them appropriately, and then customize them where Note10 and Note11 are in the script.
-important- Due to the myriad of Custom battle systems, the installation requires a little bit of scripting knowledge, have it so that when the character's turn comes up, execute $grathe_AI.main instead of executing his turn.
Also, this script uses variables 70-75, so don't use them in the game.
FAQ Q.) do you plan on re-writing the script so it isn't such a PITA to impliment?
A.) I will consider it, just remember, it only needs to be implimented once.
Q.) Can I add my own lines?
A.) Yes, look above
Q.) Does it support more than one character?
A.) Not at this time, but you can have other characters that are not AI controlled.
Q.) OMG! CAN I HAVE YOUR BABIES?
A.) No, and if you take them anyway, you will be charged with kidnapping.
Compatibility Currently unknown.... but it does use variables 70-75, so its not compatible with anything else that uses em.
Author's Notes If you are having trouble figuring out how to modify a specific battle system to skip the guy's turn and instead use the AI, I can help with that.
Demo http://hosted.filefront.com/lordpidey/ (note that this is a demo of alpha2, and a few notable improvements have been made to the in game-editor.
*edit* whoops, as a later poster pointed out I formed the link to the screenshot incorrectly, my bad.