Game Development Community

RPG Resource 5 AKA Classic Battle/ AI / package system

by Kevin Mitchell · 10/05/2009 (1:23 am) · 16 comments

File Front:
Click Here


This is my last post for to night funny how this may take the longest to explain. This is what's taken me the longest to create. It's still not 100% complete but gives a good structure for a classic RPG battle system with AI for monsters and players. Even thought the Players AI isn't installed it still has the prototypes to build from.

I'm fairly sure all the files needed are there. The only ones you may have to provide are dummy objects for Tori, Mika, and Tiny Bat.

I used my Tori Object, Gedion, and Soldier from the beta's for testing, just renamed their dta blocks.

The first thing to explain is the packaging system that I saw used in a blog years ago that no one really seemed to use or atleast what Ive observed. But in my opinion this is the best way of handeling multiple screen modes while using the same keypad controls.

activatePackage(KeyMapRPGMode);


//CUSTOM
moveMap.bind( keyboard, w, buttonup );
moveMap.bind( keyboard, a, buttonleft );
moveMap.bind( keyboard, s, buttondown );
moveMap.bind( keyboard, d, buttonright );

moveMap.bind( keyboard, i, buttonA );
moveMap.bind( keyboard, j, buttonB );
moveMap.bind( keyboard, k, buttonC );
moveMap.bind( keyboard, l, buttonD );


moveMap.bind( keyboard, q, buttonL );
moveMap.bind( keyboard, e, buttonR );

This is a mapping for the basic game pad / keyboard for now till i figure out why my game pad fails to reconize.

Basically I make these to functions that are over loaded inside packages. In seperate package files.

EX:

package KeyMapRPGMode
{
   
function startMenu()
{
quit();
}

function buttonleft(%val)
{
   $mvLeftAction = %val * $movementSpeed;
}

function buttonright(%val)
{
   $mvRightAction = %val * $movementSpeed;
}

function buttonup(%val)
{
   $mvForwardAction = %val * $movementSpeed;
}

function buttondown(%val)
{
   $mvBackwardAction = %val * $movementSpeed;
}




//alt shoot function
function buttonL(%val)
{

   $mvYawRightSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
  
}

function buttonR(%val)
{
   $mvYawLeftSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}


//shoot function
function buttonA(%val)
{
   if(%val){
      Canvas.setContent(PauseMenu);
   }
}

function buttonB(%val)
{
   $mvTriggerCount2++;
}

function buttonC(%val)
{
   if(%val){
      if($Interaction::ItemStore){
         Canvas.setContent(ItemStore);
      }
   }
}

//jump function
function buttonD(%val)
{
   if(%val){
      Canvas.setContent(BattleGui); 
   }
}


//options screen
function buttonStart(%val)
{
   
}



};//package


This is what I use when in normal Roaming. If i'm in a sub menu or a item store I can switch to the different control levels of the interface. Just by loading a different Package. In the files above I use this to change to different stages of selecting the Battle Action -> Monsters to attack -> item usage -> target for item usage.

The player and monster object class work simular. The players are loaded from the database, their stats are loaded, then equiped armor. A calculation of base attack based on the class grades selected for the class that is attached to the player is calculated.

There are level up functions to recalculate the players new stats once they level.

Before i had a bunch of setters and getters as a habit from programming cpp but i just took it out since everything is public in the first place.

The player has several variables thats used by the battle system and the AI battle to operate. Also if you notice that This object has a Avatar variable. This will be used when the characters datablock is dropped into the scene. This way the player class can control everyting with minimum out side assistance.

Hopefully most of this is straight forward. I tried to make everything as simple and as readable as possible. With me that maybe a miracle.


function Players::StartThinking(%this, %obj){

This is the start of the AI/Manual Player Think Tick

The player/monster waits in a cool down state till their wait time is over. If in AI mode then they will go into one of their AI states and automatically find a target based on certain requirements.

Note: Only random attack is programmed in this example: :P

Other wise if not on AI it will add its self to the battle que where the Attack selection menur will appear for the player to select from differnt options:

Attack
Arcana
Kouyou (Special abilities)
Item
Defend
Escape

The only thing I know that works 100% is attack. Also the monster stats for Tiny Bat is pretty strong at level 2 I had to edit it down to level one to actually win a battle, and then it was still close.

I have to really re figure the damage calculations.

Any way. From choosing the target the object class gets the pointer of the enemy's object. So it has direct access to the targets Avatar and Life information. The player will run up and "hit" the enemy and return to the location of origin.

There is a spot where I want to find out if i can add a trigger to set isAnimationDone to true using the T3D object editor but I've yet to have time to check if it's possible. For now I auto set it to true. IE why no animation plays for the Hit animation.

The character return to position and "should" do a 180 turn but my calculations are off for the axis shift.

Upon finishing the move the AI returns to coll down Mode. Also when it's dead it dies and enters IDLE state incase the character is revived and is sent into battle state again.

Globals:

$PlayerObject::Player="";
$PlayerObject::PlayerCount=0;

$STATS::MAXSTATS=8;

$STATS::ATK=0;
$STATS::DEF=1;
$STATS::MATK=2;
$STATS::MDEF=3;
$STATS::MAG=4;
$STATS::VIT=5;
$STATS::EVA=6;
$STATS::ACC=7;

$UPS::MAXUPS=6;

$UPS::PROTECTED=0;
$UPS::COATED=1;
$UPS::REVED=2;
$UPS::GENERATED=3;
$UPS::BUFFED=4;
$UPS::SPIKED=5;

$ARMOR::ARMORPEICES=6;

$ARMOR::SUIT=0;
$ARMOR::KOUYOU=1;
$ARMOR::SUB=2;
$ARMOR::ASS1=3;
$ARMOR::ASS2=4;
$ARMOR::ASS3=5;

$AISTATES::COOLDOWN=0;
$AISTATES::WAITING_ACTION=1;
$AISTATES::ATTACK=2;
$AISTATES::ARCANA=3;
$AISTATES::KOUYOU=4;
$AISTATES::ITEM=5;
$AISTATES::DEFEND=6;
$AISTATES::ESCAPE=7;
$AISTATES::RETURN_TO_ORGIN=8;
$AISTATES::DIE=9;
$AISTATES::REVIVE=10;
$AISTATES::IDLE=11;
$AISTATES::TAKE_DAMMAGE=12;
$AISTATES::SHUTDOWN=13;
$AISTATES::VICTORY=14;
$AISTATES::LEVEL=15; 
  
$AITRAIT::ATTACK_RANDOM=0;
$AITRAIT::ATTACK_WEAK=1;
$AITRAIT::DEFEND_RECOVER=2;
$AITRAIT::ATTACK_RECOVER=3;
$AITRAIT::PROTECT_MAGES=4;
$AITRAIT::POWER_SPELLS_RANDOM=5;
$AITRAIT::POWER_SPELLS_WEAK=6;
$AITRAIT::CONSERITIVE_SPELLS_RANDOM=7;
$AITRAIT::CONSERITIVE_SPELLS_WEAK=8;
$AITRAIT::BALANCED=9;
$AITRAIT::DEFENSIVE=10;

$ANIMATIONS::BATTLE_STANCE=0;
$ANIMATIONS::BATTLE_STANCE_HURT=1;
$ANIMATIONS::ATTACK=2;
$ANIMATIONS::DEFEND=3;
$ANIMATIONS::ITEM_USE=4;
$ANIMATIONS::TAKE_DAMMAGE=5;
$ANIMATIONS::DIE=6;
$ANIMATIONS::REVIVE=7;
$ANIMATIONS::LEVEL_UP=8;
$ANIMATIONS::VICTORY_STANCE=9;
$ANIMATIONS::ESCAPE=10;
$ANIMATIONS::RUN=11;

$ANI_NAME=0;
$ANI_TIME=1;
$ANI_POWER=2;

$PLAYER_REQUEST=0;

new ScriptObject(Players){
   
            PlayerID=0;
            Name="";
            Race="";
            Level="";
            ClassID="";
            ClassName="";
            CriticalRate="";
            Biography="";
            DataBlock="";
            
            Attack="";
            Defense="";
            MagicAttack="";
            MagicDefense="";
            Vitality="";
            Magic="";
            Evasion="";
            Accuracy="";

            AttackLetterGrade="";
            AttackGradeMod="";
            DefenseLetterGrade="";
            DefenseGradeMod="";
            MagicAttackLetterGrade="";
            MagicAttackGradeMod="";
            MagicDefenseLetterGrade="";
            MagicDefenseGradeMod="";
            VitalityLetterGrade="";
            VitalityGradeMod="";
            MagicLetterGrade="";
            MagicGradeMod="";
            EvasionLetterGrade="";
            EvasionGradeMod="";
            AccuracyLetterGrade="";
            AccuracyGradeMod="";
            
            CurrentHP="";
            CurrentMP="";
            CurrentKP="";
            
            MaxHP="";
            MaxMP="";
            MaxKP="";
                        
            ExpTNL="";
            ExpTotal="";
            
            InParty=true;
            InBattle=true;
            
            //STATUS AILMENTS
            IsPoisoned=false;
            IsBlind=false;
            IsParalysed=false;
            IsConfused=false;
            IsSleep=false;
            IsSilenced=false;
            IsBlind=false;
            IsDead=false;
            
            //EQUIPED ID
            SuitID="";
            KouyouID="";
            Ass1ID="";
            Ass2ID="";
            Ass3ID="";
            
            //EQUIPED NAMES
            SuitName="";
            KouyouName="";
            Ass1Name="";
            Ass2Name="";
            Ass3Name="";
            
            ARMORS_ATK="";//5 colum array
            ARMORS_DEF="";//5 colum array
            ARMORS_MATK="";//5 colum array
            ARMORS_MDEF="";//5 colum array
            ARMORS_VIT="";//5 colum array
            ARMORS_MAG="";//5 colum array
            ARMORS_EVA="";//5 colum array
            ARMORS_ACC="";//5 colum array
            
            Avatar="";
            WaitTimmer=0;
            innerState=0; 
            isDefending=0;
            WaitMod="";//used for status ailments
            AIEnabled=0;
            AIState=$AISTATES::COOLDOWN;
            isBeingTargeted=0;
            AITrait=0;//used for AI Battle
            target="";
            scheduleHandel="";
            ThinkSpeed=500;//can not be 0, in milliseconds
            AttackAnimationTime=0;
            DestinationX=0;//Do not modify
            DestinationY=0;//Do not modify
            Origin=0;//Do not modify
            OriginX=0;//Do not modify
            OriginY=0;//Do not modify
            RunSpeed=1;//Do what you want cant go higher than 1
            AIManualAction=0;
            AIStatePrev=0;
            isAnimationDone=0;
            HaultAction=0;
            LastDis=0;
            
            CastTimmer=0;
            Animations_Standard_Time="";
            Animations_Standard_Name="";
            selectedSpecial=0;
            Animations_Speacials_Time="";
            Animations_Speacials_Name="";
            selectedMagic=0;
            Animations_Magics_Time="";
            Animations_Magics_Name="";
};

Loading Info:
function InitializePlayers(){
   %sqlite = new SQLiteObject(sqlite);
   if (%sqlite == 0)
   {
      echo("ERROR: Failed to create SQLiteObject. sqliteTest aborted.");
      return;
   }
   // open database
   if (sqlite.openDatabase("Database.db") == 0)
   {
      echo("ERROR: Failed to open database: " @ %dbname);
      echo("       Ensure that the disk is not full or write protected.  sqliteTest aborted.");
      sqlite.delete();
      return;
   }
   %query = "Select PlayerID FROM PlayersInit;";
   %result = sqlite.query(%query, 0);
   if (%result == 0)
   {
      echo("ERROR: Failed to SELECT from users table.");
   }else{
      // attempt to retrieve result data
      %i=0;
      while (!sqlite.endOfResult(%result))
      {
         %PlayerID = sqlite.getColumn(%result, "PlayerID");
        $PlayerObject::Player[%i] = new ScriptObject(){
            class=Players;
            PlayerID=%PlayerID;
         };
         $PlayerObject::PlayerCount=%i;
         %i++;
         sqlite.nextRow(%result);
      }
   }
   sqlite.clearResult(%result);
   sqlite.closeDatabase();
   sqlite.delete();
   
   PopulatePlayers();
}

function PopulatePlayers(){
   for(%i=0;%i<$PlayerObject::PlayerCount;%i++){
      $PlayerObject::Player[%i].LoadPlayerInfo($PlayerObject::Player[%i]);
      $PlayerObject::Player[%i].LoadParams($PlayerObject::Player[%i]);
      $PlayerObject::Player[%i].LoadGrades($PlayerObject::Player[%i]);
      $PlayerObject::Player[%i].LoadPartyProperties($PlayerObject::Player[%i]);
      $PlayerObject::Player[%i].LoadPlayerArmors($PlayerObject::Player[%i]);
      $PlayerObject::Player[%i].SetupStats($PlayerObject::Player[%i]);
   }
}

function Players::LoadGrades(%this, %obj){
   %sqlite = new SQLiteObject(sqlite);
   if (%sqlite == 0)
   {
      echo("ERROR: Failed to create SQLiteObject. sqliteTest aborted.");
      return;
   }
   // open database
   if (sqlite.openDatabase("Database.db") == 0)
   {
      echo("ERROR: Failed to open database: " @ %dbname);
      echo("       Ensure that the disk is not full or write protected.  sqliteTest aborted.");
      sqlite.delete();
      return;
   }
   %query = "select Grades.GradeLetter, Grades.GradeMod from ClassGrades join Grades on ClassGrades.GradeID=Grades.GradeID join GradeTypes on GradeTypes.GradeTypeID=ClassGrades.GradeTypeID where ClassGrades.ClassID="@%obj.ClassID@";";
   %result = sqlite.query(%query, 0);
   if (%result == 0)
   {
      echo("ERROR: Failed to SELECT from users table.");
   }else{
      %obj.AttackLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.AttackGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.DefenseLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.DefenseGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.MagicAttackLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.MagicAttackGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.MagicDefenseLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.MagicDefenseGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.VitalityLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.VitalityGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.MagicLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.MagicGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.EvasionLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.EvasionGradeMod = sqlite.getColumn(%result, "GradeMod");
      sqlite.nextRow(%result);
      %obj.AccuracyLetterGrade = sqlite.getColumn(%result, "GradeLetter");
      %obj.AccuracyGradeMod= sqlite.getColumn(%result, "GradeMod");
   }
   sqlite.clearResult(%result);
   sqlite.closeDatabase();
   sqlite.delete();
}

function Players::LoadPlayerInfo(%this, %obj){
   %sqlite = new SQLiteObject(sqlite);
   if (%sqlite == 0)
   {
      echo("ERROR: Failed to create SQLiteObject. sqliteTest aborted.");
      return;
   }
   // open database
   if (sqlite.openDatabase("Database.db") == 0)
   {
      echo("ERROR: Failed to open database: " @ %dbname);
      echo("       Ensure that the disk is not full or write protected.  sqliteTest aborted.");
      sqlite.delete();
      return;
   }
   %query = "select PlayersInit.Name, Races.Name, PlayersInit.Level, Classes.ClassID, Classes.Name, Classes.CriticalRate, PlayersInit.Biography , PlayersInit.DataBlock from PlayersInit join Races on PlayersInit.RaceID=Races.RaceID join Classes on Classes.ClassID=PlayersInit.ClassID where PlayerID="@%obj.PlayerID@";";
   %result = sqlite.query(%query, 0);
   if (%result == 0)
   {
      echo("ERROR: Failed to SELECT from users table.");
   }else{
      %obj.Name = sqlite.getColumn(%result, 1);
      %obj.Race = sqlite.getColumn(%result, 2);
      %obj.Level = sqlite.getColumn(%result, 3);
      %obj.ClassID = sqlite.getColumn(%result, 4);
      %obj.ClassName = sqlite.getColumn(%result, 5);
      %obj.CriticalRate = sqlite.getColumn(%result, 6);
      %obj.Biography = sqlite.getColumn(%result, 7);
      %obj.DataBlock = sqlite.getColumn(%result, 8);
   }
   sqlite.clearResult(%result);
   sqlite.closeDatabase();
   sqlite.delete();
}

function  Players::LoadParams(%this, %obj){
   %sqlite = new SQLiteObject(sqlite);
   if (%sqlite == 0)
   {
      echo("ERROR: Failed to create SQLiteObject. sqliteTest aborted.");
      return;
   }
   // open database
   if (sqlite.openDatabase("Database.db") == 0)
   {
      echo("ERROR: Failed to open database: " @ %dbname);
      echo("       Ensure that the disk is not full or write protected.  sqliteTest aborted.");
      sqlite.delete();
      return;
   }
   %query = "select PlayerParams.Value from PlayerParams join Parameters on Parameters.ParamID=PlayerParams.ParamID where PlayerParams.PlayerID="@%obj.PlayerID@";";
   %result = sqlite.query(%query, 0);
   if (%result == 0)
   {
      echo("ERROR: Failed to SELECT from users table.");
   }else{
      %obj.Attack = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.Defense = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.MagicAttack = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.MagicDefense = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.Vitality = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.Magic = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.Evasion = sqlite.getColumn(%result, "Value");
      sqlite.nextRow(%result);
      %obj.Accuracy = sqlite.getColumn(%result, "Value");
   }
   sqlite.clearResult(%result);
   sqlite.closeDatabase();
   sqlite.delete();
}

function Players::LoadPartyProperties(%this, %obj){
   %sqlite = new SQLiteObject(sqlite);
   if (%sqlite == 0)
   {
      echo("ERROR: Failed to create SQLiteObject. sqliteTest aborted.");
      return;
   }
   // open database
   if (sqlite.openDatabase("Database.db") == 0)
   {
      echo("ERROR: Failed to open database: " @ %dbname);
      echo("       Ensure that the disk is not full or write protected.  sqliteTest aborted.");
      sqlite.delete();
      return;
   }
   %query = "select Position, Inbattle, StatusID from PartyInit where PlayerID="@%obj.PlayerID@";";
   %result = sqlite.query(%query, 0);
   if (%result == 0||sqlite.endOfResult(%result))
   {
         %obj.InParty=false;
         %obj.InBattle=false;
         %obj.PartyPosition=-1;
         %obj.IsPoisoned=false;
         %obj.IsBlind=false;
         %obj.IsParalysed=false;
         %obj.IsConfused=false;
         %obj.IsSleep=false;
         %obj.IsSilenced=false;
   }else{
      %obj.InParty=true;
      if(sqlite.getColumn(%result, "Inbattle")==1){
         %obj.InBattle=true;
      }else{
         %obj.InBattle=false;
      }
      %obj.PartyPosition=sqlite.getColumn(%result, "Position");
      
      if((sqlite.getColumn(%result, "StatusID")&1)==1){
         %obj.IsPoisoned=true;
      }else{
         %obj.IsPoisoned=false;
      }
      
      if((sqlite.getColumn(%result, "StatusID")&2)==2){
         %obj.IsBlind=true;
      }else{
         %obj.IsBlind=false;
      }
      
      if((sqlite.getColumn(%result, "StatusID")&4)==4){
         %obj.IsParalysed=true;
      }else{
         %obj.IsParalysed=false;
      }
      
      if((sqlite.getColumn(%result, "StatusID")&8)==8){
         %obj.IsConfused=true;
      }else{
         %obj.IsConfused=false;
      }
      
      if((sqlite.getColumn(%result, "StatusID")&16)==16){
         %obj.IsSleep=true;
      }else{
         %obj.IsSleep=false;
      }
      
      if((sqlite.getColumn(%result, "StatusID")&32)==32){
         %obj.IsSilenced=true;
      }else{
         %obj.IsSilenced=false;
      }
      
   }
   sqlite.clearResult(%result);
   sqlite.closeDatabase();
   sqlite.delete();
}
   

function Players::LoadPlayerArmors(%this, %obj){
   %sqlite = new SQLiteObject(sqlite);
   if (%sqlite == 0)
   {
      echo("ERROR: Failed to create SQLiteObject. sqliteTest aborted.");
      return;
   }
   // open database
   if (sqlite.openDatabase("Database.db") == 0)
   {
      echo("ERROR: Failed to open database: " @ %dbname);
      echo("       Ensure that the disk is not full or write protected.  sqliteTest aborted.");
      sqlite.delete();
      return;
   }
   %query = "select EquippedArmors.ArmorID, Armors.Name from EquippedArmors inner join Armors on Armors.ArmorID=EquippedArmors.ArmorID where EquippedArmors.PlayerID="@%obj.PlayerID@" and Armors.ArmorTypeID=1";
   %result = sqlite.query(%query, 0);
   if (%result == 0||sqlite.endOfResult(%result))
   {
      %obj.KouyouID=0;
      %obj.KouyouName="";
   }else{
      %obj.KouyouID=sqlite.getColumn(%result, "ArmorID");
      %obj.KouyouName=sqlite.getColumn(%result, "Name");
         
         sqlite.clearResult(%result);
         %query = "select Value from ArmorParams where ArmorID="@%obj.KouyouID@";";
         %result = sqlite.query(%query, 0);
         if (%result == 0||sqlite.endOfResult(%result))
         {
            %obj.ARMORS_ATK[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_DEF[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_MATK[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_MDEF[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_VIT[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_MAG[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_EVA[$ARMOR::KOUYOU]=0;
            %obj.ARMORS_ACC[$ARMOR::KOUYOU]=0;
         }else{
            %obj.ARMORS_ATK[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_DEF[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MATK[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MDEF[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_VIT[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MAG[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_EVA[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_ACC[$ARMOR::KOUYOU] = sqlite.getColumn(%result, "Value");
         }   
   }
   sqlite.clearResult(%result);
   %query = "select EquippedArmors.ArmorID, Armors.Name from EquippedArmors inner join Armors on Armors.ArmorID=EquippedArmors.ArmorID where EquippedArmors.PlayerID="@%obj.PlayerID@" and Armors.ArmorTypeID=2";
   %result = sqlite.query(%query, 0);
   if (%result == 0||sqlite.endOfResult(%result))
   {
      %obj.SuitID=0;
      %obj.SuitName="";
   }else{
      %obj.SuitID=sqlite.getColumn(%result, "ArmorID");
      %obj.SuitName=sqlite.getColumn(%result, "Name");
         
         sqlite.clearResult(%result);
         %query = "select Value from ArmorParams where ArmorID="@%obj.SuitID@";";
         %result = sqlite.query(%query, 0);
         if (%result == 0||sqlite.endOfResult(%result))
         {
            %obj.ARMORS_ATK[$ARMOR::SUIT]=0;
            %obj.ARMORS_DEF[$ARMOR::SUIT]=0;
            %obj.ARMORS_MATK[$ARMOR::SUIT]=0;
            %obj.ARMORS_MDEF[$ARMOR::SUIT]=0;
            %obj.ARMORS_VIT[$ARMOR::SUIT]=0;
            %obj.ARMORS_MAG[$ARMOR::SUIT]=0;
            %obj.ARMORS_EVA[$ARMOR::SUIT]=0;
            %obj.ARMORS_ACC[$ARMOR::SUIT]=0;
         }else{
            %obj.ARMORS_ATK[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_DEF[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MATK[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MDEF[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_VIT[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MAG[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_EVA[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_ACC[$ARMOR::SUIT] = sqlite.getColumn(%result, "Value");
         }   
   }
   sqlite.clearResult(%result);
   %query = "select EquippedArmors.ArmorID, Armors.Name from EquippedArmors inner join Armors on Armors.ArmorID=EquippedArmors.ArmorID where EquippedArmors.PlayerID="@%obj.PlayerID@" and Armors.ArmorTypeID=3";
   %result = sqlite.query(%query, 0);
   if (%result == 0||sqlite.endOfResult(%result))
   {
      %obj.Ass1ID=0;
      %obj.Ass1Name="";
   }else{
      %obj.Ass1ID=sqlite.getColumn(%result, "ArmorID");
      %obj.Ass1Name=sqlite.getColumn(%result, "Name");
         
         sqlite.clearResult(%result);
         %query = "select Value from ArmorParams where ArmorID="@%obj.Ass1ID@";";
         %result = sqlite.query(%query, 0);
         if (%result == 0||sqlite.endOfResult(%result))
         {
            %obj.ARMORS_ATK[$ARMOR::ASS1]=0;
            %obj.ARMORS_DEF[$ARMOR::ASS1]=0;
            %obj.ARMORS_MATK[$ARMOR::ASS1]=0;
            %obj.ARMORS_MDEF[$ARMOR::ASS1]=0;
            %obj.ARMORS_VIT[$ARMOR::ASS1]=0;
            %obj.ARMORS_MAG[$ARMOR::ASS1]=0;
            %obj.ARMORS_EVA[$ARMOR::ASS1]=0;
            %obj.ARMORS_ACC[$ARMOR::ASS1]=0;
         }else{
            %obj.ARMORS_ATK[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_DEF[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MATK[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MDEF[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_VIT[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MAG[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_EVA[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_ACC[$ARMOR::ASS1] = sqlite.getColumn(%result, "Value");
         }   
   }
   sqlite.clearResult(%result);
   %query = "select EquippedArmors.ArmorID, Armors.Name from EquippedArmors inner join Armors on Armors.ArmorID=EquippedArmors.ArmorID where EquippedArmors.PlayerID="@%obj.PlayerID@" and Armors.ArmorTypeID=3";
   %result = sqlite.query(%query, 0);
   if (%result == 0||sqlite.endOfResult(%result))
   {
      %obj.Ass2ID=0;
      %obj.Ass2Name="";
   }else{
      %obj.Ass2ID=sqlite.getColumn(%result, "ArmorID");
      %obj.Ass2Name=sqlite.getColumn(%result, "Name");
         
         sqlite.clearResult(%result);
         %query = "select Value from ArmorParams where ArmorID="@%obj.Ass2ID@";";
         %result = sqlite.query(%query, 0);
         if (%result == 0||sqlite.endOfResult(%result))
         {
            %obj.ARMORS_ATK[$ARMOR::ASS2]=0;
            %obj.ARMORS_DEF[$ARMOR::ASS2]=0;
            %obj.ARMORS_MATK[$ARMOR::ASS2]=0;
            %obj.ARMORS_MDEF[$ARMOR::ASS2]=0;
            %obj.ARMORS_VIT[$ARMOR::ASS2]=0;
            %obj.ARMORS_MAG[$ARMOR::ASS2]=0;
            %obj.ARMORS_EVA[$ARMOR::ASS2]=0;
            %obj.ARMORS_ACC[$ARMOR::ASS2]=0;
         }else{
            %obj.ARMORS_ATK[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_DEF[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MATK[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MDEF[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_VIT[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MAG[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_EVA[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_ACC[$ARMOR::ASS2] = sqlite.getColumn(%result, "Value");
         }   
   }
   sqlite.clearResult(%result);
   %query = "select EquippedArmors.ArmorID, Armors.Name from EquippedArmors inner join Armors on Armors.ArmorID=EquippedArmors.ArmorID where EquippedArmors.PlayerID="@%obj.PlayerID@" and Armors.ArmorTypeID=3";
   %result = sqlite.query(%query, 0);
   if (%result == 0||sqlite.endOfResult(%result))
   {
      %obj.Ass3ID=0;
   }else{
      %obj.Ass3ID=sqlite.getColumn(%result, "ArmorID");
      %obj.Ass3Name=sqlite.getColumn(%result, "Name");
         
         sqlite.clearResult(%result);
         %query = "select Value from ArmorParams where ArmorID="@%obj.Ass3ID@";";
         %result = sqlite.query(%query, 0);
         if (%result == 0||sqlite.endOfResult(%result))
         {
            %obj.ARMORS_ATK[$ARMOR::ASS3]=0;
            %obj.ARMORS_DEF[$ARMOR::ASS3]=0;
            %obj.ARMORS_MATK[$ARMOR::ASS3]=0;
            %obj.ARMORS_MDEF[$ARMOR::ASS3]=0;
            %obj.ARMORS_VIT[$ARMOR::ASS3]=0;
            %obj.ARMORS_MAG[$ARMOR::ASS3]=0;
            %obj.ARMORS_EVA[$ARMOR::ASS3]=0;
            %obj.ARMORS_ACC[$ARMOR::ASS3]=0;
         }else{
            %obj.ARMORS_ATK[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_DEF[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MATK[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MDEF[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_VIT[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_MAG[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_EVA[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
            sqlite.nextRow(%result);
            %obj.ARMORS_ACC[$ARMOR::ASS3] = sqlite.getColumn(%result, "Value");
         }   
   }
   sqlite.clearResult(%result);
   sqlite.closeDatabase();
   sqlite.delete();
}
   
function Players::SetupStats(%this, %obj){
   
            %obj.Attack=mFloor((((%obj.AttackGradeMod)*(%obj.Level))/1000)*999);
            %obj.Defense=mFloor((((%obj.DefenseGradeMod)*(%obj.Level))/1000)*999);
            %obj.MagicAttack=mFloor((((%obj.MagicAttackGradeMod)*(%obj.Level))/1000)*999);
            %obj.MagicDefense=mFloor((((%obj.MagicDefenseGradeMod)*(%obj.Level))/1000)*999);
            %obj.Vitality=mFloor((((%obj.VitalityGradeMod)*(%obj.Level))/1000)*999);
            %obj.Magic=mFloor((((%obj.MagicGradeMod)*(%obj.Level))/1000)*999);
            %obj.Evasion=mFloor((((%obj.EvasionGradeMod)*(%obj.Level))/1000)*999);
            %obj.Accuracy=mFloor((((%obj.AccuracyGradeMod)*(%obj.Level))/1000)*999);
                            
            %obj.CurrentHP=%obj.Vitality*12;
            %obj.CurrentMP=%obj.Magic*12;
            %obj.CurrentKP=%obj.Level*12;
            
            %obj.MaxHP=%obj.Vitality*12;
            %obj.MaxMP=%obj.Magic*12;
            %obj.MaxKP=%obj.Level*12;
            
            %obj.ExpTNL=(%obj.Level+1)*1000;
            
}

function Players::LevelUp(%this, %obj)
{
      %obj.Level++;
      %obj.SetupStats();
}

AI:
function Players::StartThinking(%this, %obj){
   %obj.AIState=$AISTATES::COOLDOWN;
   %obj.ThinkSpeed=500;
   %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
}

function Players::AIStateMachine(%this, %obj){

 switch(%obj.AIState){
    case $AISTATES::COOLDOWN : 
      //WAIT FOR WAIT TIME AND REACT TO BATTLE AKA DEFEND ACTION TIME
         switch(%obj.innerState){
            case 0 : 
               %obj.WaitTimmer = (1-(%obj.Evasion/(%obj.Level*20)))*10000;
               %obj.innerState=1;
               
            case 1 : 
               %obj.WaitTimmer-=%obj.ThinkSpeed;
               if(%obj.WaitTimmer<=0){
                  %obj.isDefending=false;
                  %obj.AIState=$AISTATES::WAITING_ACTION;
                  %obj.innerState=0;
               }
               if(%obj.isBeingTargeted){
                  %obj.AIStatePrev=$AISTATES::COOLDOWN;
                  %obj.AIState=$AISTATES::DEFEND;
               }
               
         }
       
    case $AISTATES::WAITING_ACTION : 
      //ENROLL INTO MANUAL MODE IF SET TO MANUAL OR DECIDE NEXT ACTION BASED ON AI TRAIT
      switch(%obj.innerState){
         case 0 :       
         
         if(%obj.AIEnabled){
            switch(%obj.AITrait){
               case $AITRAIT::ATTACK_RANDOM :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::ATTACK_WEAK :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::DEFEND_RECOVER :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::ATTACK_RECOVER :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::PROTECT_MAGES :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::POWER_SPELLS_RANDOM :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::POWER_SPELLS_WEAK :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::CONSERITIVE_SPELLS_RANDOM :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::CONSERITIVE_SPELLS_WEAK :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::BALANCED :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
               case $AITRAIT::DEFENSIVE :
                  %obj.target=getTargetEnemy(getRandom(1,getNumberOfLivingEnemies())-1);
                  %obj.innerState=0;
                  %obj.AIState=$AISTATES::ATTACK;
                  
            }
            %obj.HaultAction=1;
            AttackQueAdd(%obj);
         }else{
            %obj.AIManualAction=0;
            AddToQue(%obj);
         }
         %obj.innerState=1;
         
         case 1 :
               if(%obj.isBeingTargeted){
                  %obj.AIStatePrev=$AISTATES::WAITING_ACTION;
                  %obj.AIState=$AISTATES::DEFEND;
               }
               if(%obj.AIManualAction){
                  %obj.isDefending=false;
                  %obj.innerState=0;
                  %obj.AIState=%obj.AIManualAction;
               }
            
      }
       
    case $AISTATES::ATTACK : 
      if(%obj.HaultAction){
         %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
         return;
      }
      switch(%obj.innerState){
         case 0 :
            %obj.Avatar.setMoveDestination(%obj.target.Avatar.getPosition(),true);
            %obj.innerState=1;
              
         case 1:
         
            %distance = VectorDist( %obj.target.Avatar.getTransform(),%obj.Avatar.getTransform() );
            
            if(%distance<4){
               cancel(%obj.scheduleHandel);
               
               %obj.Avatar.setActionThread(%obj.AttackAnimation, 
               false,//hold = false,  
               false//fsp = false,   
               );
               %obj.innerState=2;
               %obj.isAnimationDone=0;
            }
            
         case 2 :
            if(true/*%obj.isAnimationDone*/){
               %obj.Target.CurrentHP-=attackDammage(%obj,%obj.Target);
               %obj.innerState=0;
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;      
            }
            
      }
    
      //ADVANCE TOWARD TARGET WHEN TARGER IN RANGE ATTACK THEN SWITCH TO RETURN TO ORGIN
      
       
    case $AISTATES::ARCANA : 
      //START SPELL CASTING ANIMATION WAIT TILL TIME FINISHED THEN PLAY CAST SPELL ANIMATION AND INVOKE THE PARTICAL CREATION WAIT TILL FINISHED REMOVE PARTICAL THEN RETURN TO ORGIN

      if(%obj.HaultAction){
         %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
         return;
      }
      switch(%obj.innerState){      
         case 0 :
               %obj.CastTimmer = ((1-(%obj.Magic/(%obj.Level*20)))*(%obj.Animations_Magics_Time[%obj.selectedMagic]));
               %obj.innerState=1;
              
         case 1 :
            %obj.CastTimmer-=%obj.ThinkSpeed/1000;
             if(%obj.CastTimmer<=0){
               %obj.innerState=2;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Magics_Name[%obj.selectedMagic], 
               false,//hold = false,  
               false//fsp = false,   
               );
            }
            
         case 2 :
            if(%obj.isAnimationDone){
               %obj.innerState=0;
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;      
            }
            
      }      
       
    case $AISTATES::KOUYOU : 
      //START SPEICAL PREP ANIMATION WAIT TILL TIME FINISHED THEN PLAY SPECIAL ANIMATION AND INVOKE THE PARTICAL CREATION WAIT TILL FINISHED REMOVE PARTICAL THEN RETURN TO ORGIN IF NEEDED
      if(%obj.HaultAction){
         %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
         return;
      }
      switch(%obj.innerState){
         case 0 :
               %obj.CastTimmer = %obj.Animations_Speacials_Time[%obj.selectedSpecial];
               %obj.innerState=1;
              
         case 1:
            %obj.CastTimmer-=%obj.ThinkSpeed/1000;
             if(%obj.CastTimmer<=0){
               %obj.innerState=2;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Speacials_Name[%obj.selectedSpecial], 
               false,//hold = false,  
               false//fsp = false,   
               );
            }
            
         case 2 :
            if(%obj.isAnimationDone){
               %obj.innerState=0;
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;      
            }
      }      
       
    case $AISTATES::ITEM : 
      //TURN TO THE USER IF NOT YOUR SELF PLAY ITEM USE ANIMATION AND INVOKE THE PARTICAL ANIMATION THEN RETURN TO FORWARD POSITION
      if(%obj.HaultAction){
         %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
         return;
      }
      switch(%obj.innerState){
         case 0 :
               %obj.CastTimmer = %obj.Animations_Standard_Time[$ANIMATIONS::ITEM_USE];
               %obj.innerState=1;
               
         case 1:
            %obj.CastTimmer-=%obj.ThinkSpeed/1000;
             if(%obj.CastTimmer<=0){
               %obj.innerState=2;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::ITEM_USE], 
               false,//hold = false,  
               false//fsp = false,   
               );
            }
            
         case 2 :
            if(%obj.isAnimationDone){
               %obj.innerState=0;
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;      
            }
            
      }      
       
    case $AISTATES::DEFEND : 
      //DEFEND FOR A TURN OR DEFEND DURING REACTION TIME BLOCKING
         if(%obj.HaultAction){
            %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
            return;
         }
         %obj.isDefending=true;
         %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::DEFEND], 
               false,//hold = false,  
               false//fsp = false,   
         );
         if(%obj.AIStatePrev==-1){
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;
         }else{
               %obj.AIState=%obj.AIStatePrev;
               %obj.AIStatePrev=-1;
         }
       
    case $AISTATES::ESCAPE : 
      //PLAY RUNNING ANIMATION START TIMMER THEN CHECK ESCAPE FREQUENCY
         if(%obj.HaultAction){
            %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
            return;
         }
      switch(%obj.innerState){
         case 0 :
               %obj.CastTimmer = %obj.Animations_Standard_Time[$ANIMATIONS::ESCAPE];
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::ESCAPE], 
               false,//hold = false,  
               false//fsp = false,   
               );
               %obj.innerState=1;
              
         case 1:
            %obj.CastTimmer-=%obj.ThinkSpeed/1000;
             if(%obj.CastTimmer<=0){
               %obj.innerState=2;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::RUN], 
               false,//hold = false,  
               false//fsp = false,   
               );
            }
            
         case 2 :
            if(%obj.isAnimationDone){
               %obj.innerState=0;
               %obj.AIState=$AISTATES::SHUTDOWN;      
               END_BATTLE();
            }
            
      }     
       
    case $AISTATES::RETURN_TO_ORGIN : 
      //RETURN TO ORGIN THEN FACE FORWARD AND ENTER COOL DOWN BASED ON LAST ACTION
      
      switch(%obj.innerState){
         case 0 :
               %obj.Avatar.setMoveDestination(%obj.Avatar.orgin,true);
               %obj.innerState=1;
              
         case 1:
         
            %distance = VectorDist( %obj.Avatar.orgin,%obj.Avatar.getTransform() );
            
            if(%distance<4){
               %obj.Avatar.stop();
               %xfrm = %obj.Avatar.getTransform();
               %lx = getword(%xfrm,0);
               %ly = getword(%xfrm,1);
               %lz = getword(%xfrm,2);
               %rz = 3.14159265359;
               %obj.Avatar.setTransform(%lx SPC %ly SPC %lz SPC 0 SPC 0 SPC 1 SPC %rz);
               %obj.innerState=2;
               %obj.isAnimationDone=0;
            }
            
         case 2 :
               %obj.innerState=0;
               %obj.AIState=$AISTATES::COOLDOWN;      
            
      }
       
       
    case $AISTATES::DIE : 
      //EAT IT! THEN ENTER IDLE
      switch(%obj.innerState){
         case 0:
               %obj.innerState=1;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread("death1"/*%obj.Animations_Standard_Name[$ANIMATIONS::DIE]*/, 
               true,//hold = false,  
               false//fsp = false,   
               );
            
         case 1 :
            if(true/*%obj.isAnimationDone*/){
               %obj.isDead=1;
               %obj.innerState=0;
               %obj.AIState=$AISTATES::IDLE;      
            }
      }      
       
    case $AISTATES::REVIVE : 
      //PLAY REVIVE ANIMATION
      switch(%obj.innerState){
         case 0:
               %obj.innerState=1;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::DIE], 
               false,//hold = false,  
               false//fsp = false,   
               );
            
         case 1 :
            if(%obj.isAnimationDone){
               %obj.innerState=0;
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;      
            }
            
      }      
       
    case $AISTATES::IDLE : 
      //DO NOTHING
       
    case $AISTATES::TAKE_DAMMAGE :
      //TAKE DAMMAGE THEN RETURN TO LAST KNOWN EVENT      
      switch(%obj.innerState){
         case 0:
               %obj.innerState=1;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::TAKE_DAMMAGE], 
               false,//hold = false,  
               false//fsp = false,   
               );
            
         case 1 :
            if(%obj.isAnimationDone){
               %obj.innerState=0;
               %obj.AIState=$AISTATES::RETURN_TO_ORGIN;      
            }
            
      }      
      
    case $AISTATES::VICTORY :
      //TAKE DAMMAGE THEN RETURN TO LAST KNOWN EVENT      
      switch(%obj.innerState){
         case 0:
               %obj.innerState=1;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::VICTORY_STANCE], 
               false,//hold = false,  
               false//fsp = false,   
               );
            
         case 1 :
            
      }      
      
    case $AISTATES::LEVEL :
      //TAKE DAMMAGE THEN RETURN TO LAST KNOWN EVENT      
      switch(%obj.innerState){
         case 0:
               %obj.innerState=1;
               %obj.isAnimationDone=0;
               %obj.Avatar.setActionThread(%obj.Animations_Standard_Name[$ANIMATIONS::LEVEL_UP], 
               false,//hold = false,  
               false//fsp = false,   
               );
            
         case 1 :
            
      }      
      
    case $AISTATES::SHUTDOWN :
      //TAKE DAMMAGE THEN RETURN TO LAST KNOWN EVENT      
      
      return;
      
 }
 %obj.scheduleHandel=%obj.schedule(%obj.ThinkSpeed, "AIStateMachine", %obj);
}

InitializePlayers();

The Battle System Really consist of a gui Loader and a battle tick.
OnWake the battle system is setup. It will load the monster party selected into the global variable. then load the Monsters and Players Marked as inBattle=true into the scene under their selected drop point folders:

MonsterFormation
PartyFormation

Once the active player objects and monster objects are loaded and copied into the battle handle's the battle tick starts.

The battle ticks manages the life readings the attack que and the battle screen popup.

Life Monitor:
This check to see who has died as well as update the onscreen life meters for the players (Only player one for this code).

AttackQue monitors who's turn it is to attack. This solved an issue where every one was attacking at once and getting stuck on each other.

Once a monster dies their exp is added to the EXP pool. And their object is removed from the Monster Handle Array.

Same thing happens with the player when they die.

Who ever wins one of two things will happen. Either the game will quit, "you lose", or the victory screen will load.

The victory screen takes the total exp gathered and divided it among the living members.
Then the objects created for the battle scene are deleted.

The only thing tested for working is regular attacks. Using Healing items may work. This needs alot of work and ill re-upload the files whenever I finish them.


Enjoy.


Back To Blog:
RPG_Blog AKA New Resources

About the author

Riding Solo since 2005. Current Project: Fated World 2005-Present "... because Torque3D is not just for Tribes style First Person Shooters - but anything which you have the will to create" ~ Steve Acaster


#1
10/05/2009 (3:33 am)
Very impressive combo of resources, Kevin! Great work!
#2
10/05/2009 (8:10 am)
Wow Kevin these look great!

Will definitely be giving the inventory a look :)
#3
10/05/2009 (10:43 am)
So from looking at the video I am gathering the battle system is turn based correct?
#4
10/05/2009 (1:44 pm)
Turn base active battle
#5
10/05/2009 (3:35 pm)
What do you mean by turn based active? Basiclly I am assuming that I click attack. my character attacks then each other npc in the fight attacks then it comes back to me and waits for me to decide which attack I want to do again correct?
#6
10/05/2009 (3:50 pm)
thanks for your effort, you rock!!!.
#7
10/05/2009 (5:48 pm)
Turn base active battle mean while u decide what to do the AI can still kill u
#8
10/07/2009 (1:00 am)
Very nice set of resources!
#9
10/07/2009 (7:15 am)
Thank you good sir, please let me know if anyone is having problems. I'll see if I can help.
#10
10/07/2009 (11:56 am)
a loot function would be a great addition to this code.. as well as instead of moving it to a idle animation, it plays the Death animation. This would be awesome hooked into the AFX system.
#11
10/07/2009 (1:48 pm)
The death animation is there. Idle is called after death animation is complete, you should beable to like look as a aistate and mirror attack except just play the loot anomation and add the Gil desired
#12
10/07/2009 (2:29 pm)
yah i guess it would take a bit more to add in item and money loots..
#13
10/07/2009 (2:41 pm)
not alot just make it a special and add a isLoot in the special's section.
#14
10/15/2009 (3:58 pm)
Great resource Black Cat, and Thank you very much for your contribution to the community. With being a full time student in my senior year of game design I don’t get much of a chance to be here much anymore, but now that I am in the mists of some projects for school, which I made sure involved the new T3D engine I have been here more, and am continually astounded by the amount of time and energy people like you give to the community. Great work for helping keep it alive!
#15
10/08/2010 (4:29 pm)
Omm, download link is broken.

Thanks
#16
11/23/2011 (6:28 pm)
http://www.garagegames.com/community/resources/view/20583

New Links