PDA

View Full Version : Release: GBaddy V.1.0


Gambet
03-04-2007, 12:19 AM
//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=0; a<5; a++)
{
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.x + vecx(this.dir) * this.mov_speed;
this.new_y = this.y + 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 + 2 + vecy(this.dir);
if (onwall(this.to_add_x,this.to_add_y))
{
this.dir = (this.dir+2)%4;
} else
{
setcharani("walk","");
x = this.new_x;
y = 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.x - this.x;
this.dist_y = this.plyr.y - 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.x + 1.5;
this.check_y = this.y + 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.x += this.add_x;
DamagePlayer();
} else if (!onwall(this.check_x,this.check_y + this.add_y))
{
this.y += 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]+5 < 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]+5 >= 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;
}
}
}





^^

cbk1994
03-04-2007, 04:45 AM
//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=0; a<5; a++)
{
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.x + vecx(this.dir) * this.mov_speed;
this.new_y = this.y + 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 + 2 + vecy(this.dir);
if (onwall(this.to_add_x,this.to_add_y))
{
this.dir = (this.dir+2)%4;
} else
{
setcharani("walk","");
x = this.new_x;
y = 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.x - this.x;
this.dist_y = this.plyr.y - 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.x + 1.5;
this.check_y = this.y + 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.x += this.add_x;
DamagePlayer();
} else if (!onwall(this.check_x,this.check_y + this.add_y))
{
this.y += 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]+5 < 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]+5 >= 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.

Angel_Light
03-07-2007, 11:38 PM
Cool, I think I'll build off this :D Thanks much.

Chompy
03-08-2007, 12:04 AM
Hmm, you gave me some ideas, great job Gambet!

JkWhoSaysNi
03-08-2007, 01:58 AM
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.

DustyPorViva
03-08-2007, 02:42 AM
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.

shadowjones
04-12-2007, 08:27 AM
[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!

Gambet
04-12-2007, 05:57 PM
[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. :)

theHAWKER
04-15-2007, 07:59 AM
making v2?

Gambet
04-15-2007, 11:10 PM
making v2?


If people give me worthwhile suggestions then I guess I can work on a v2.

theHAWKER
04-16-2007, 03:07 AM
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 :D
so like "/pk theHAWKER" then it would go kill me :D

Gambet
04-16-2007, 03:11 AM
suggestion: make it so u can tell it what to do, like a robot :D
so like "/pk theHAWKER" then it would go kill me :D


That's not the purpose of this x-x

cbk1994
04-16-2007, 04:28 AM
What would be cool is some sort of extremely basic AI that lets multiple baddies attack in a formation.

xXziroXx
04-16-2007, 08:01 PM
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.

Gambet
04-16-2007, 10:00 PM
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!

PrinceOfKenshin
06-16-2007, 06:14 AM
I know this is really old but how can use this for a custom body?

Gambet
06-16-2007, 08:48 AM
I know this is really old but how can use this for a custom body?



What do you mean by a custom body?



This is my own scripted custom baddy. You can make it look however you want, it will still function the same.

TheJames
06-16-2007, 08:50 AM
Haha, Mike! We have a baddy script. But if you wan't to use this one load it and i'll show you.

setcharani gani,legs,shirt,hat; :)

Gambet
06-16-2007, 09:16 AM
Yeah, last I remember this baddy kicks some serious ass. Might need some tweaking if it's going to be used on a server as a regular baddy. But, if it's to be used as a boss, then it's perfect. :)