Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
| #=============================================================================== | |
| # )----------------------------------------------------------------------------( | |
| # )-- AUTHOR: Mr Trivel --( | |
| # )-- NAME: Enemy AI - Checks & Tables --( | |
| # )-- CREATED: 2014-11-09 --( | |
| # )-- VERSION: 1.1 --( | |
| #=============================================================================== | |
| # )-- VERSION HISTORY --( | |
| # )-- 1.0 - Initial script. --( | |
| # )-- 1.1 - Small compatibility addon. --( | |
| # )-- Enemies will use default patterns in database if tables and --( | |
| # )-- checks aren't created. --( | |
| #=============================================================================== | |
| # )-- DESCRIPTION --( | |
| # )-- Instead of using Attack Patterns in database which don't allow for --( | |
| # )-- much customization. All enemy patterns will be written in module --( | |
| # )-- allowing more complex and varying interactions in the battle. --( | |
| # )-- --( | |
| # )-- How the AI works: --( | |
| # )-- AI goes through every Check in order, checking conditions for it. --( | |
| # )-- Depending on condition results, it checks which Table to use. --( | |
| # )-- If Table is a nil, it goes to the next check. Else it uses the Table --( | |
| # )-- that was set. --( | |
| # )-- Repeat for all checks until Table is found. --( | |
| # )-- After Table is found, it uses weighted randomness to determine which --( | |
| # )-- attack to use from that Table. --( | |
| # )-- --( | |
| # )-- Warning: This may be a tiny little bitty bitsy complex to set up. --( | |
| #=============================================================================== | |
| # )-- LICENSE INFO --( | |
| # )-- Free for non-commercial & commercial games if credit was given to --( | |
| # )-- Mr Trivel. --( | |
| # )----------------------------------------------------------------------------( | |
| #=============================================================================== | |
| module ATDATA | |
| # )--------------------------------------------------------------------------( | |
| # )-- DATA Hash creation. Leave it alone. --( | |
| # )--------------------------------------------------------------------------( | |
| DATA = {} | |
| # )==========================================================================( | |
| # )--- Setup your enemy AI here. ---( | |
| # )==========================================================================( | |
| # )--------------------------------------------------------------------------( | |
| # )-- DATA[ID] - which enemy AI will it be. --( | |
| # )--------------------------------------------------------------------------( | |
| # )-- DATA[1] - AI for Enemy with ID 1. --( | |
| # )--------------------------------------------------------------------------( | |
| DATA[1] = { | |
| # )------------------------------------------------------------------------( | |
| # )-- Checks part. --( | |
| # )-- Runs through every Check in a row until non-nil Table is found. --( | |
| # )-- Once it finds a non-nil Table, it will ignore other checks. --( | |
| # )-- In this case, it will go to Check #2 unless both conditions are --( | |
| # )-- fulfilled. --( | |
| # )------------------------------------------------------------------------( | |
| :checks => { | |
| # Check #1 | |
| 1 => { | |
| # )--------------------------------------------------------------------( | |
| # )-- Check Conditions --( | |
| # )-- In this case, there are 2 conditions, and conditions always --( | |
| # )-- return TRUE or FALSE. TRUE being 1 and FALSE being 0. --( | |
| # )-- Meaning you can have combinations of 00, 01, 10 and 11. --( | |
| # )--------------------------------------------------------------------( | |
| :conditions => [ | |
| "$game_troop.turn_count % 2 == 0", | |
| "hp_rate <= 0.75" | |
| ], | |
| # )--------------------------------------------------------------------( | |
| # )-- Remember the 00, 01, 10 and 11 from last box? They pick which --( | |
| # )-- Attack Table to use! --( | |
| # )-- Looking at the conditions up there, if the turn is even and --( | |
| # )-- it has less or equal to 75% of his HP, it will use Attack --( | |
| # )-- Table with ID 0. But in any other case, it will return nil, --( | |
| # )-- meaning it will go to the next Check. --( | |
| # )--------------------------------------------------------------------( | |
| :tables => { | |
| # Condition Result => Attack Table ID | |
| "00" => nil, #false && false | |
| "01" => nil, #false && true | |
| "10" => nil, #true && false | |
| "11" => 0 #true && true | |
| } | |
| }, # end of Check #1 | |
| # Check #2 | |
| 2 => { | |
| # )--------------------------------------------------------------------( | |
| # )-- This case is 3 conditions, meaning the results can be: --( | |
| # )-- 000, 001, 010, 011, 100, 101, 111 --( | |
| # )--------------------------------------------------------------------( | |
| :conditions => [ | |
| "states.include?(5)", | |
| "hp_rate > 0.75", | |
| "$game_troop.turn_count % 2 != 0" | |
| ], | |
| # )--------------------------------------------------------------------( | |
| # )-- Just tables, with 3 digits this time, since 3 conditions. --( | |
| # )--------------------------------------------------------------------( | |
| :tables => { | |
| "000" => 1, | |
| "001" => 2, | |
| "010" => 3, | |
| "011" => 3, | |
| "100" => 2, | |
| "101" => 4, | |
| "111" => 3 | |
| } | |
| } # end of Check #2 | |
| }, # checks end | |
| # )------------------------------------------------------------------------( | |
| # )-- This is where your enemy's Attack Tables are. --( | |
| # )------------------------------------------------------------------------( | |
| :attack_tables => { | |
| # )----------------------------------------------------------------------( | |
| # )-- The Attack Table ID refers to this. 0 => {, 1 => {, etc.. --( | |
| # )-- That's which table the enemy will use to get a weighted random --( | |
| # )-- from. --( | |
| # )----------------------------------------------------------------------( | |
| # Attack Table ID 0 | |
| 0 => { | |
| # )--------------------------------------------------------------------( | |
| # )-- Structure for this is simple. --( | |
| # )-- Attack ID => Attack Chance in % --( | |
| # )--------------------------------------------------------------------( | |
| 1 => 20, | |
| 2 => 80 | |
| }, | |
| # Attack Table ID 1 | |
| 1 => { | |
| 1 => 50, | |
| 3 => 25, | |
| 4 => 25 | |
| }, | |
| # Attack Table ID 2 | |
| 2 => { | |
| 1 => 80, | |
| 2 => 10, | |
| 3 => 10 | |
| }, | |
| # Attack Table ID 3 | |
| 3 => { | |
| 1 => 100 | |
| }, | |
| # Attack Table ID 4 | |
| 4 => { | |
| 1 => 50, | |
| 2 => 50 | |
| } | |
| } # attack_tables end | |
| } | |
| # )==========================================================================( | |
| # )--- Stop setting up your enemy AI here. ---( | |
| # )==========================================================================( | |
| end | |
| # )=======---------------------------------------------------------------------( | |
| # )-- Class: Game_Enemy --( | |
| # )---------------------------------------------------------------------=======( | |
| class Game_Enemy < Game_Battler | |
| alias :mrts_enemy_ai_CAT_make_actions :make_actions | |
| # )--------------------------------------------------------------------------( | |
| # )-- Alias Method: make_actions --( | |
| # )--------------------------------------------------------------------------( | |
| def make_actions | |
| if ATDATA::DATA[@enemy_id] | |
| super | |
| return if @actions.empty? | |
| attack_table = nil | |
| # Check loop | |
| ATDATA::DATA[@enemy_id][:checks].each { |check_id, check_val| | |
| evaluation = "" | |
| # condition loop | |
| check_val[:conditions].each { |condition| | |
| eval(condition) ? evaluation += "1" : evaluation += "0" | |
| } | |
| table = check_val[:tables][evaluation] | |
| if table != nil | |
| attack_table = table | |
| break | |
| end | |
| } | |
| return if attack_table == nil | |
| # select an action from attack table | |
| roll = rand(100)+1 | |
| skill = nil | |
| ATDATA::DATA[@enemy_id][:attack_tables][attack_table].each { |skill_id, chance| | |
| if roll > chance | |
| roll -= chance | |
| else | |
| skill = skill_id | |
| break | |
| end | |
| } | |
| @actions.each do |action| | |
| action.set_enemy_action_from_table(skill) | |
| end | |
| else | |
| mrts_enemy_ai_CAT_make_actions | |
| end | |
| end | |
| end | |
| # )=======---------------------------------------------------------------------( | |
| # )-- Class: Game_Action --( | |
| # )---------------------------------------------------------------------=======( | |
| class Game_Action | |
| # )--------------------------------------------------------------------------( | |
| # )-- New Method: set_enemy_action_from_table --( | |
| # )--------------------------------------------------------------------------( | |
| def set_enemy_action_from_table(action) | |
| if action | |
| set_skill(action) | |
| else | |
| clear | |
| end | |
| end | |
| end |