Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Today's Posts

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 03-04-2007, 12:19 AM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Release: GBaddy V.1.0

PHP Code:
//GBaddy
//Version 1.0

//Features:
// Constantly moving about, not idle like most
// boring baddies you see on Graal. 
// When you step into the baddies vision radius,
// he will begin to chase after you, in attack mode.
// While in attack mode, the baddy has a total of
// 3 possible things that he can do, all of which
// are chosen randomly.
// The baddy can choose to swing his sword at
// you, heal himself, and/or cause an explosion
// under him.
// NOTE: I didn't add any damage checks besides
//       Was.Hit, so if Was.Hit only checks for
//       whether or not the baddy was hit by
//       a sword, then that's all that will
//       hurt it for now.
// NOTE #2: I know that it's NOT PERFECT,
//          but it's the first time I've actually,
//          worked with Artificial Intelligence,
//          excluding the current bot that I'm
//          making on Graal X, which is much
//          different. I figured it was a
//          nice learning experience, and I
//          figured some people could find it
//          useful since it's MUCH MORE challenging
//          than the default baddy NPCs.
// NOTE #3: I used some of the mathematical
//          calculations previously created by
//          Stefan in his baddy NPC (the default 
//          Graal baddy NPC).

//By: Gambet

enum 
{
 
WALK,
 
ATTACK,
 
DEAD
}

function 
onCreated()
{
  
showcharacter();
  
this.bodyimg "body2.png";
  
this.shieldimg "no-shield.png";
  
this.nick "GBaddy";
  
this.ap 0;
  for (
a=0a<5a++)
   {
    
this.colors[a] = "black";
   }
  if (
this.ani != "idle")
   {
     
setcharani("idle","");
   }
  
this.health = {10,10};
  
this.mov_speed 0.5;
  
this.count int(random(10,40));
  
this.mode WALK;
  
setTimer(0.1);
}

function 
onPlayerEnters()
{
  
onTimeOut(); //To Wake Up The NPC
  
this.headimg "head" int(random(0,1000)) @ ".png"//To Have A Different Head Each Time You Enter The Level
}

function 
onWas.Hit() //REMOVE THE . - GRAAL FORUMS FILTER IS ANNOYING >O
{
 if (
this.health[0]-(player.swordpower/2) > 0)
  {
    if (
this.ani != "hurt")
     {
       
setcharani("hurt","");
       
scheduleevent(1,"Counter","");
     }
    switch(
this.plyr.dir//Knockback
     
{
      case 
"2":
       if (!
onwall(this.x,this.y+3))
        {
         
this.y+=3;
        }
       break;
      case 
"0":
       if (!
onwall(this.x,this.y-3))
        {
         
this.y-=3;
        }
       break;
      case 
"1":
       if (!
onwall(this.x-3,this.y))
        {
         
this.x-=3;
        }
       break;
      case 
"3":
       if (!
onwall(this.x+3,this.y))
        {
         
this.x+=3;
        }
       break;
     }
     
this.health[0]-=player.swordpower/2;
     
chat this.health[0] @ "/" this.health[1];
     
scheduleevent(2,"HideChat","");
  } else
   {
    if (
this.mode != DEAD)
     {
       
this.mode DEAD;
       
this.health[0] = 0;
       
putexplosion2(3,3,this.x,this.y);
       
putexplosion2(3,3,this.x,this.y+0.5);
       
setcharani("dead","");
       
chat this.health[0] @ "/" this.health[1];
       
scheduleevent(8,"Respawn","");
     }
   }
}

function 
onHideChat()
{
 if (
params[0] == "idle")
  {
    
chat "";
    
setcharani("idle","");
  } else
   {
     
chat "";
   }
}

function 
onCounter()
{
 if (
this.health[0] > 0)
  {
    
setcharani("sword","");
  }
}

function 
onRespawn()
{
 if (
this.mode == DEAD)
  {
    
setcharani("idle","");
    
chat "";
    
this.health[0] = this.health[1];
    
this.mode WALK;
  }
}

function 
onTimeOut()
{
 if (
players.size() > 0
  {
   
setTimer(0.1);
  } else
   {
    
setTimer(0); //To Sleep In Case No Players Are In The Room - Saves CPU Time
   
}
 if (
this.mode != DEAD)
  {
   if (
this.to_check.x in |this.x-10,this.x+10| && this.to_check.y in |this.y-10,this.y+10|)
    {
     if (
this.mode != ATTACK)
      {
        
this.mode ATTACK;
      }
    } else
     {
       
this.mode WALK;
     }
  }
 if (
this.mode == WALK)
  {
    
this.to_check findnearestplayer(this.x,this.y);
    
this.new_x this.vecx(this.dir) * this.mov_speed;
    
this.new_y this.vecy(this.dir) * this.mov_speed;
    
this.count--;
   if (
this.count 0)
    {
      
this.to_add_x this.new_x 1.5 vecx(this.dir);
      
this.to_add_y this.new_y vecy(this.dir);
     if (
onwall(this.to_add_x,this.to_add_y)) 
      {
        
this.dir = (this.dir+2)%4;
      } else 
       {
         
setcharani("walk","");
         
this.new_x;
         
this.new_y;
       }
    } else
     {
       
this.count int(random(10,40));
       
this.dir = (this.dir+1+int(random(0,2))*2)%4;
     }
  }
  if (
this.mode == ATTACK)
   {
     
this.plyr this.to_check;
     
this.dist_x this.plyr.this.x;
     
this.dist_y this.plyr.this.y;
     
this.len = (this.dist_x*this.dist_x+this.dist_y*this.dist_y)^0.5;
     
this.add_x = (this.dist_x this.len);
     
this.add_y = (this.dist_y this.len);
     
this.check_x this.1.5;
     
this.check_y this.2;
     if (!
onwall(this.check_x this.add_x,this.check_y this.add_y))
      {
        
DamagePlayer();
        
Move();
      } else if (!
onwall(this.check_x this.add_x,this.check_y)) 
       {
         
this.+= this.add_x;
         
DamagePlayer();
       } else if (!
onwall(this.check_x,this.check_y this.add_y))
        {
          
this.+= this.add_y;
          
DamagePlayer();
        }
   }
 
setTimer(0.1); 
}

function 
DamagePlayer()
{
 
this.randomize int(random(0,101));
  if (
this.randomize in |0,82|) //Attack With Sword
   
{
     
setcharani("sword","");
   } else if (
this.randomize in |83,95|) //Cause Explosion
    
{
      
putexplosion2(3,3,this.x,this.y);
    } else if (
this.randomize in |95,101|) //Heal
     
{
      if (
this.health[0] < this.health[1])
       {
        if (
this.health[0]+this.health[1])
         {
           
this.temp_add int(random(0,6));
           
this.health[0]+=this.temp_add;
           
chat "*Healed for " this.temp_add "*";
         } else if (
this.health[0]+>= this.health[1])
          {
            
this.health[0] = this.health[1];
            
chat "*Fully Healed*";
          }
           
setcharani("lift","");
           
this.health[0] = this.health[1];
           
scheduleevent(1,"HideChat","idle");
       }
     }
}

function 
Move()
{
  
setcharani("walk","");
  
this.x+=this.add_x * (this.mov_speed 0.6);
  
this.y+=this.add_y * (this.mov_speed 0.6);
  if (
abs(this.dist_x) > abs(this.dist_y)) 
   {
    if (
this.dist_x 0
     {
       
this.dir 3
     } else 
      {
        
this.dir 1;
      }
   } else 
    {
     if (
this.dist_y 0
      {
        
this.dir 2
      } else 
       {
         
this.dir 0;
       }
    }





Last edited by Gambet; 03-04-2007 at 12:53 AM..
Reply With Quote
  #2  
Old 03-04-2007, 04:45 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
Quote:
Originally Posted by Gambet View Post
PHP Code:
//GBaddy
//Version 1.0

//Features:
// Constantly moving about, not idle like most
// boring baddies you see on Graal. 
// When you step into the baddies vision radius,
// he will begin to chase after you, in attack mode.
// While in attack mode, the baddy has a total of
// 3 possible things that he can do, all of which
// are chosen randomly.
// The baddy can choose to swing his sword at
// you, heal himself, and/or cause an explosion
// under him.
// NOTE: I didn't add any damage checks besides
//       Was.Hit, so if Was.Hit only checks for
//       whether or not the baddy was hit by
//       a sword, then that's all that will
//       hurt it for now.
// NOTE #2: I know that it's NOT PERFECT,
//          but it's the first time I've actually,
//          worked with Artificial Intelligence,
//          excluding the current bot that I'm
//          making on Graal X, which is much
//          different. I figured it was a
//          nice learning experience, and I
//          figured some people could find it
//          useful since it's MUCH MORE challenging
//          than the default baddy NPCs.
// NOTE #3: I used some of the mathematical
//          calculations previously created by
//          Stefan in his baddy NPC (the default 
//          Graal baddy NPC).

//By: Gambet

enum 
{
 
WALK,
 
ATTACK,
 
DEAD
}

function 
onCreated()
{
  
showcharacter();
  
this.bodyimg "body2.png";
  
this.shieldimg "no-shield.png";
  
this.nick "GBaddy";
  
this.ap 0;
  for (
a=0a<5a++)
   {
    
this.colors[a] = "black";
   }
  if (
this.ani != "idle")
   {
     
setcharani("idle","");
   }
  
this.health = {10,10};
  
this.mov_speed 0.5;
  
this.count int(random(10,40));
  
this.mode WALK;
  
setTimer(0.1);
}

function 
onPlayerEnters()
{
  
onTimeOut(); //To Wake Up The NPC
  
this.headimg "head" int(random(0,1000)) @ ".png"//To Have A Different Head Each Time You Enter The Level
}

function 
onWas.Hit() //REMOVE THE . - GRAAL FORUMS FILTER IS ANNOYING >O
{
 if (
this.health[0]-(player.swordpower/2) > 0)
  {
    if (
this.ani != "hurt")
     {
       
setcharani("hurt","");
       
scheduleevent(1,"Counter","");
     }
    switch(
this.plyr.dir//Knockback
     
{
      case 
"2":
       if (!
onwall(this.x,this.y+3))
        {
         
this.y+=3;
        }
       break;
      case 
"0":
       if (!
onwall(this.x,this.y-3))
        {
         
this.y-=3;
        }
       break;
      case 
"1":
       if (!
onwall(this.x-3,this.y))
        {
         
this.x-=3;
        }
       break;
      case 
"3":
       if (!
onwall(this.x+3,this.y))
        {
         
this.x+=3;
        }
       break;
     }
     
this.health[0]-=player.swordpower/2;
     
chat this.health[0] @ "/" this.health[1];
     
scheduleevent(2,"HideChat","");
  } else
   {
    if (
this.mode != DEAD)
     {
       
this.mode DEAD;
       
this.health[0] = 0;
       
putexplosion2(3,3,this.x,this.y);
       
putexplosion2(3,3,this.x,this.y+0.5);
       
setcharani("dead","");
       
chat this.health[0] @ "/" this.health[1];
       
scheduleevent(8,"Respawn","");
     }
   }
}

function 
onHideChat()
{
 if (
params[0] == "idle")
  {
    
chat "";
    
setcharani("idle","");
  } else
   {
     
chat "";
   }
}

function 
onCounter()
{
 if (
this.health[0] > 0)
  {
    
setcharani("sword","");
  }
}

function 
onRespawn()
{
 if (
this.mode == DEAD)
  {
    
setcharani("idle","");
    
chat "";
    
this.health[0] = this.health[1];
    
this.mode WALK;
  }
}

function 
onTimeOut()
{
 if (
players.size() > 0
  {
   
setTimer(0.1);
  } else
   {
    
setTimer(0); //To Sleep In Case No Players Are In The Room - Saves CPU Time
   
}
 if (
this.mode != DEAD)
  {
   if (
this.to_check.x in |this.x-10,this.x+10| && this.to_check.y in |this.y-10,this.y+10|)
    {
     if (
this.mode != ATTACK)
      {
        
this.mode ATTACK;
      }
    } else
     {
       
this.mode WALK;
     }
  }
 if (
this.mode == WALK)
  {
    
this.to_check findnearestplayer(this.x,this.y);
    
this.new_x this.vecx(this.dir) * this.mov_speed;
    
this.new_y this.vecy(this.dir) * this.mov_speed;
    
this.count--;
   if (
this.count 0)
    {
      
this.to_add_x this.new_x 1.5 vecx(this.dir);
      
this.to_add_y this.new_y vecy(this.dir);
     if (
onwall(this.to_add_x,this.to_add_y)) 
      {
        
this.dir = (this.dir+2)%4;
      } else 
       {
         
setcharani("walk","");
         
this.new_x;
         
this.new_y;
       }
    } else
     {
       
this.count int(random(10,40));
       
this.dir = (this.dir+1+int(random(0,2))*2)%4;
     }
  }
  if (
this.mode == ATTACK)
   {
     
this.plyr this.to_check;
     
this.dist_x this.plyr.this.x;
     
this.dist_y this.plyr.this.y;
     
this.len = (this.dist_x*this.dist_x+this.dist_y*this.dist_y)^0.5;
     
this.add_x = (this.dist_x this.len);
     
this.add_y = (this.dist_y this.len);
     
this.check_x this.1.5;
     
this.check_y this.2;
     if (!
onwall(this.check_x this.add_x,this.check_y this.add_y))
      {
        
DamagePlayer();
        
Move();
      } else if (!
onwall(this.check_x this.add_x,this.check_y)) 
       {
         
this.+= this.add_x;
         
DamagePlayer();
       } else if (!
onwall(this.check_x,this.check_y this.add_y))
        {
          
this.+= this.add_y;
          
DamagePlayer();
        }
   }
 
setTimer(0.1); 
}

function 
DamagePlayer()
{
 
this.randomize int(random(0,101));
  if (
this.randomize in |0,82|) //Attack With Sword
   
{
     
setcharani("sword","");
   } else if (
this.randomize in |83,95|) //Cause Explosion
    
{
      
putexplosion2(3,3,this.x,this.y);
    } else if (
this.randomize in |95,101|) //Heal
     
{
      if (
this.health[0] < this.health[1])
       {
        if (
this.health[0]+this.health[1])
         {
           
this.temp_add int(random(0,6));
           
this.health[0]+=this.temp_add;
           
chat "*Healed for " this.temp_add "*";
         } else if (
this.health[0]+>= this.health[1])
          {
            
this.health[0] = this.health[1];
            
chat "*Fully Healed*";
          }
           
setcharani("lift","");
           
this.health[0] = this.health[1];
           
scheduleevent(1,"HideChat","idle");
       }
     }
}

function 
Move()
{
  
setcharani("walk","");
  
this.x+=this.add_x * (this.mov_speed 0.6);
  
this.y+=this.add_y * (this.mov_speed 0.6);
  if (
abs(this.dist_x) > abs(this.dist_y)) 
   {
    if (
this.dist_x 0
     {
       
this.dir 3
     } else 
      {
        
this.dir 1;
      }
   } else 
    {
     if (
this.dist_y 0
      {
        
this.dir 2
      } else 
       {
         
this.dir 0;
       }
    }




Very nice, thanks Gambet! A lot of people have been waiting for someone to release baddies.
__________________
Reply With Quote
  #3  
Old 03-07-2007, 11:38 PM
Angel_Light Angel_Light is offline
Varia Developer
Angel_Light's Avatar
Join Date: Nov 2005
Location: Knoxville, TN
Posts: 1,684
Angel_Light is on a distinguished road
Send a message via AIM to Angel_Light Send a message via MSN to Angel_Light
Cool, I think I'll build off this Thanks much.
__________________
Deep into the Darkness peering...
Reply With Quote
  #4  
Old 03-08-2007, 12:04 AM
Chompy Chompy is offline
¯\(º_o)/¯
Chompy's Avatar
Join Date: Sep 2006
Location: Norway
Posts: 2,815
Chompy is just really niceChompy is just really niceChompy is just really nice
Send a message via MSN to Chompy
Hmm, you gave me some ideas, great job Gambet!
__________________
Reply With Quote
  #5  
Old 03-08-2007, 01:58 AM
JkWhoSaysNi JkWhoSaysNi is offline
Ruler of the graalaxy
Join Date: Feb 2005
Location: Great Britain
Posts: 488
JkWhoSaysNi is on a distinguished road
Send a message via ICQ to JkWhoSaysNi
Nice.
A while back I tried making a simple AI baddy NPC using a small backpropagation Neural Net but it was really beyond me. I have a very basic undertanding of Neural Networks but just couldn't get it to work as I wanted it to and gave up.

If I feel up to the challenge I might try again.
__________________

Coming soon (Hopefully:P)
Reply With Quote
  #6  
Old 03-08-2007, 02:42 AM
DustyPorViva DustyPorViva is offline
Will work for food. Maybe
DustyPorViva's Avatar
Join Date: Sep 2003
Location: Maryland, USA
Posts: 9,589
DustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond reputeDustyPorViva has a reputation beyond repute
Send a message via AIM to DustyPorViva Send a message via MSN to DustyPorViva
I was rescripting the original graal baddies a little while ago, but it was in GS1. Got pretty far, but just gave up after I got to their head directions and all, though could probably be done with showani... ah well. I did manage to remake the baddies into GANI's perfectly, which was fun. I'd say what you should do, which maybe I'll try one day, is once they catch the person in their line of sight, start recording perhaps the players last 20 steps. That way, if the player tries to run around obstacles or such you can revert from delta movement to the movement array. Smarter AI.
Reply With Quote
  #7  
Old 04-12-2007, 07:27 AM
shadowjones shadowjones is offline
**** Scripter xD
Join Date: Apr 2007
Posts: 24
shadowjones is on a distinguished road
[QUOTE=Gambet;1284203]
//GBaddy
//Version 1.0
......................
[QUOTE]

This NPC...pwns the hell out of me! I get him to 9.5 and he heals himself XD

Great idea builder!

Last edited by shadowjones; 04-12-2007 at 07:27 AM.. Reason: to long
Reply With Quote
  #8  
Old 04-12-2007, 04:57 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
[QUOTE=shadowjones;1299332][QUOTE=Gambet;1284203]
//GBaddy
//Version 1.0
......................
Quote:

This NPC...pwns the hell out of me! I get him to 9.5 and he heals himself XD

Great idea builder!

I've killed him a few times. It's fun


But, yes, he doesn't like the thought of dying too much.
Reply With Quote
  #9  
Old 04-15-2007, 06:59 AM
theHAWKER theHAWKER is offline
**FLIP OUT**
theHAWKER's Avatar
Join Date: Mar 2006
Location: canada, vancouver
Posts: 768
theHAWKER is an unknown quantity at this point
making v2?
__________________
**FLIP OUT**
Reply With Quote
  #10  
Old 04-15-2007, 10:10 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Quote:
Originally Posted by theHAWKER View Post
making v2?

If people give me worthwhile suggestions then I guess I can work on a v2.
Reply With Quote
  #11  
Old 04-16-2007, 02:07 AM
theHAWKER theHAWKER is offline
**FLIP OUT**
theHAWKER's Avatar
Join Date: Mar 2006
Location: canada, vancouver
Posts: 768
theHAWKER is an unknown quantity at this point
Quote:
Originally Posted by Gambet View Post
If people give me worthwhile suggestions then I guess I can work on a v2.
suggestion: make it so u can tell it what to do, like a robot
so like "/pk theHAWKER" then it would go kill me
__________________
**FLIP OUT**
Reply With Quote
  #12  
Old 04-16-2007, 02:11 AM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Quote:
Originally Posted by theHAWKER View Post
suggestion: make it so u can tell it what to do, like a robot
so like "/pk theHAWKER" then it would go kill me

That's not the purpose of this x-x
Reply With Quote
  #13  
Old 04-16-2007, 03:28 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
What would be cool is some sort of extremely basic AI that lets multiple baddies attack in a formation.
__________________
Reply With Quote
  #14  
Old 04-16-2007, 07:01 PM
xXziroXx xXziroXx is offline
Malorian
xXziroXx's Avatar
Join Date: May 2004
Posts: 5,289
xXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant future
How about you make a "friendly more" for it? Like.. it's an NPC that has to be rescued from a dungeon of evil beasts! Once you talk to him, he will follow you around and attack nearby enemies.
__________________
Follow my work on social media post-Graal:Updated august 2025.
Reply With Quote
  #15  
Old 04-16-2007, 09:00 PM
Gambet Gambet is offline
Registered User
Join Date: Oct 2003
Posts: 2,712
Gambet is on a distinguished road
Quote:
Originally Posted by xXziroXx View Post
How about you make a "friendly more" for it? Like.. it's an NPC that has to be rescued from a dungeon of evil beasts! Once you talk to him, he will follow you around and attack nearby enemies.

Now that's an idea!
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 09:24 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.