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 07-12-2007, 03:16 AM
_Z3phyr_ _Z3phyr_ is offline
Banned
Join Date: Sep 2003
Location: Louisiane
Posts: 390
_Z3phyr_ is an unknown quantity at this point
My "Realistic NPC", and an explanation of how to use

One of the things that I wanted to do was make NPCs that acted or behaved like the ones you see in those cool RPG games. You know, the ones that walk around like normal people and when you go up to them they say some message or whatever. My goal was to make a model of this so that it could be used everywhere and replace the normal default NPC script that just sits around like a douchebag facing the same direction for days on end and says the -exact- same thing every damn time you go up to it.

One semi-unrelated thing I discovered about player movement while working on this script was that players move at a speed of 1+(1/9) tiles per second in all 8 of the directions. What does that mean? It means that if you want to move X tiles to the right at player speed, that means you plug in the numbers so that the time is 1 second per 1.111... tile distance at which you move.

Here's the actual script of what I had so far. I was trying to make it into some kind of makeshift baddy or something after I made this model, but that didn't work out too well for me because I wasn't able to get the actual attack for dmg part of the script to work properly so I said "w/e it can just be a regular npc".

PHP Code:

//#CLIENTSIDE
function onCreated() {
  
init_Attr();
}
function 
onPlayerenters() {
  
this.setTimer(random(0,3));
}
function 
onPlayertouchsme() {
  
this.setTimer(0);
  
move(0,0,0.05,0);
  
dir getdir(player.x-x,player.y-y);
  
temp.var = int(random(0,this.messages.size()));
  if (
temp.var==0) { say2(this.messages[1]); }
  else { 
say2(this.messages[temp.var]); }
  
this.setTimer(5);
}
function 
onTimeout() {
  
doMove();
  
this.setTimer(int(random(2,5)));
}
function 
init_Attr() {//in honor of ace2896
  
showcharacter();
  
//  use this part if its a regular npc
  
player.head "head0.png";
  
player.body "body.png";
  
player.shield "no-shield.png";
  
colors[0] = "orange"colors[1] = "white"colors[2] = "blue"colors[3] = "red"colors[4] = "black";
  
  
//use this part if its a custom gani npc person
  //setcharani("delt_suo-kccutie","kc_kara2.png");
  
dir int(random(0,3));
  
this.messages = {null,"Where have you set the" NL "cabbage this time, Myra!?","My armpits smell like butter.","I wish daddy would stop hitting" NL "mommy.","C-C-C-C-C-COOCAAAINE","MMMMMM CIGARETTES","Well Gertrude, I tend to be more" NL "liberal-centrist on the issue.","Ware da hood @","kekekekekekeke ^_^","I am going to stab your" NL "babies with a sharpened banana.","I once set the internet on fire."};
  
this.distX = {null,0,-7,0,7,0};
  
this.distY = {null,0,-7,0,7,0};
  
this.dispT = {null,.4,.5,.65,.75,1};
}
function 
doMove() {
  
temp.array = {int(random(1,5)),int(random(1,5)),int(random(1,5))};
  
move(this.distX[temp.array[0]]*this.dispT[temp.array[2]],this.distY[temp.array[1]]*this.dispT[temp.array[2]],this.dispT[temp.array[2]],20);
  if (
this.distX[temp.array[0]]==this.distY[temp.array[1]]==0) {
    
dir int(random(0,3));
    
setcharani("idle",null);
    
sleep(this.dispT[temp.array[2]]);
  } 
  else { 
setcharani("walk",null); }

for the record, I made the first slot of my arrays null just out of habit -- it's my thing. sue me.

For those of you who do not know GS2 well but know the basics for reading it (i.e. know a thing or two about scripting in general), lemme spell out some of the variables:

this.messages is an array containing the things an npc says, which can be just one thing or a whole bunch of things.

As for movement, I didn't want to try to be fancy and make it longer than it could've been with onwall checks, so I just stuck with the default thing so it works the same as a player. If it aint broke, don't fix it, right? here's info on the movement vars:

this.distX, this.distY, and this.dispT are index arrays for the options you want to manually give the NPC for movement (a random distance looks weird because its usually small and insignificant) and allows 8-direction only movement. It's important to make the ends 0 and have that 0, #, 0, #, 0 pattern to keep the 8-direction movement.
They each stand for: Distance from X, distance from Y, and displacement of Time, respectively.
In order to move straight righ tin this script, distX must = 7 and distY must = 0. dispT gives the distance (or in my physics class as I originally learned the concept, displacement) that you travel and does not affect speed, which is constant at 1+(1/9) tiles per second aka player speed.

temp.array = { distXindex, distYindex, dispTindex };, which is declared in the doMove() function, is there to pick which values in the distX, distY, and dispT variables are used. This is the part of the script that decides where exactly the player is going and is used in the move command on the next line.
[important about temp.array]: I don't see a reason you'd ever need to alter temp.array — unless of course you are adding or erasing values in the distX, distY, and dispT arrays. The maximum values in the random() functions of temp.array need to match the .size() of each of the corresponding indecies.




With this model I'm sure you can create some interesting, very player-like NPC characters for your GS2 server. I really hope to see these NPCs around a lot. If they're not meant to move you can just erase the doMove() command in the model.

Last edited by _Z3phyr_; 07-13-2007 at 12:21 AM..
Reply With Quote
  #2  
Old 07-12-2007, 05:48 AM
LoneAngelIbesu LoneAngelIbesu is offline
master of infinite loops
LoneAngelIbesu's Avatar
Join Date: May 2007
Location: Toldeo, Ohio
Posts: 1,049
LoneAngelIbesu has a spectacular aura aboutLoneAngelIbesu has a spectacular aura about
Send a message via AIM to LoneAngelIbesu
It seems that when the NPC is moving, there's no animation (no steps, no sounds).
Reply With Quote
  #3  
Old 07-12-2007, 01:42 PM
_Z3phyr_ _Z3phyr_ is offline
Banned
Join Date: Sep 2003
Location: Louisiane
Posts: 390
_Z3phyr_ is an unknown quantity at this point
My apologies. The original script was made for a special gani NPC that floated around and didn't need any kind of separate walking or moving gani. I copy/pasted and overlooked that part. Thanks.

Fixed.
Reply With Quote
  #4  
Old 07-12-2007, 10:50 PM
LoneAngelIbesu LoneAngelIbesu is offline
master of infinite loops
LoneAngelIbesu's Avatar
Join Date: May 2007
Location: Toldeo, Ohio
Posts: 1,049
LoneAngelIbesu has a spectacular aura aboutLoneAngelIbesu has a spectacular aura about
Send a message via AIM to LoneAngelIbesu
Hm, I'm still not seeing the animation. Log on to "Val Dev" and you'll see what I'm seeing. The NPC either doesn't move, but has the animation, or moves without the animation. All I did was remove the setcharani() command and the comments around the basic NPC attributes.
Reply With Quote
  #5  
Old 07-12-2007, 11:52 PM
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
Just a note, player's speed is dependent on their shield level. First thing I noticed about movement on Delteria was how I moved at a .6 interval, which I thought was awkward.
As for the idea, I once thought of trying to make a 'smart' AI spar NPC, which would perform player-like moves, such as circling the player and such... but I never got around to it. Graal needs more interactive NPC's.
Reply With Quote
  #6  
Old 07-13-2007, 12:16 AM
_Z3phyr_ _Z3phyr_ is offline
Banned
Join Date: Sep 2003
Location: Louisiane
Posts: 390
_Z3phyr_ is an unknown quantity at this point
I had this problem with the animations when I first made the script — I guess the script that I have in this old hard drive is the incomplete one.

If I remember correctly, the way to fix it was just moving the setcharani() to another line in the script. Clearly I put it in the wrong place when I edited it. It's not made to constantly be moving around, and it's made to just stand still and face a random direction every so often (i.e. when distx and disty both = 0).

edit - i tried moving the setcharanis to after the move command and below the dir change.
Reply With Quote
  #7  
Old 09-09-2007, 01:26 AM
ShardIceFire ShardIceFire is offline
Dancing Pony Privateer
Join Date: Sep 2007
Location: The Desert
Posts: 31
ShardIceFire is on a distinguished road
Send a message via AIM to ShardIceFire
I really like this script alot, the walking/idle animations work but the synching is really odd. sometimes it'll show them perfectly, and other times it'll stay 'idle' while walking, or 'walk' in place. Do you know how to fix that?
__________________
Reply With Quote
  #8  
Old 09-09-2007, 03:24 PM
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
Quote:
Originally Posted by ShardIceFire View Post
I really like this script alot, the walking/idle animations work but the synching is really odd. sometimes it'll show them perfectly, and other times it'll stay 'idle' while walking, or 'walk' in place. Do you know how to fix that?
Check if the gani is already displayed instead of re-displaying it without a check if it already is displaying that ani..
__________________
Reply With Quote
  #9  
Old 09-13-2007, 05:50 AM
ShardIceFire ShardIceFire is offline
Dancing Pony Privateer
Join Date: Sep 2007
Location: The Desert
Posts: 31
ShardIceFire is on a distinguished road
Send a message via AIM to ShardIceFire
Quote:
Originally Posted by Chompy View Post
Check if the gani is already displayed instead of re-displaying it without a check if it already is displaying that ani..
well for someone who is unfamiliar with GS2, could you explain more in depth? or show the lines of code in his script that would need to be revised?
__________________
Reply With Quote
  #10  
Old 09-13-2007, 03:22 PM
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
PHP Code:
function doMove() {
  
temp.array = {int(random(1,5)),int(random(1,5)),int(random(1,5))};
  
move(this.distX[temp.array[0]]*this.dispT[temp.array[2]],this.distY[temp.array[1]]*this.dispT[temp.array[2]],this.dispT[temp.array[2]],20);
  if (
this.distX[temp.array[0]]==this.distY[temp.array[1]]==0) {
    
dir int(random(0,3));
    if (
this.ani != "idle") {
      
setcharani("idle",null);
    }
    
sleep(this.dispT[temp.array[2]]);
  }else{
    if (
this.ani != "walk") {
      
setcharani("walk",null);
    }
  }

for example ;o
__________________
Reply With Quote
  #11  
Old 11-02-2009, 05:30 AM
_Z3phyr_ _Z3phyr_ is offline
Banned
Join Date: Sep 2003
Location: Louisiane
Posts: 390
_Z3phyr_ is an unknown quantity at this point
unfortunately, i'm not able to edit my original post

so i'll just post the updated thing with the ap's edit:

PHP Code:
//#CLIENTSIDE
function onCreated() {
  
init_Attr();
}
function 
onPlayerenters() {
  
this.setTimer(random(0,3));
}
function 
onPlayertouchsme() {
  
this.setTimer(0);
  
move(0,0,0.05,0);
  
dir getdir(player.x-x,player.y-y);
  
temp.var = int(random(0,this.messages.size()));
  if (
temp.var==0) { say2(this.messages[1]); }
  else { 
say2(this.messages[temp.var]); }
  
this.setTimer(5);
}
function 
onTimeout() {
  
doMove();
  
this.setTimer(int(random(2,5)));
}
function 
init_Attr() {//in honor of ace2896
  
showcharacter();
  
//  use this part if its a regular npc
  
player.head "head0.png";
  
player.body "body.png";
  
player.shield "no-shield.png";
  
colors[0] = "orange"colors[1] = "white"colors[2] = "blue"colors[3] = "red"colors[4] = "black";
  
  
//use this part if its a custom gani npc person
  //setcharani("delt_suo-kccutie","kc_kara2.png");
  
dir int(random(0,3));
  
this.messages = {null,"Where have you set the" NL "cabbage this time, Myra!?","My armpits smell like butter.","I wish daddy would stop hitting" NL "mommy.","C-C-C-C-C-COOCAAAINE","MMMMMM CIGARETTES","Well Gertrude, I tend to be more" NL "liberal-centrist on the issue.","Ware da hood @","kekekekekekeke ^_^","I am going to stab your" NL "babies with a sharpened banana.","I once set the internet on fire."};
  
this.distX = {null,0,-7,0,7,0};
  
this.distY = {null,0,-7,0,7,0};
  
this.dispT = {null,.4,.5,.65,.75,1};
}
function 
doMove() {
  
temp.array = {int(random(1,5)),int(random(1,5)),int(random(1,5))};
  
move(this.distX[temp.array[0]]*this.dispT[temp.array[2]],this.distY[temp.array[1]]*this.dispT[temp.array[2]],this.dispT[temp.array[2]],20);
  if (
this.distX[temp.array[0]]==this.distY[temp.array[1]]==0) {
    
dir int(random(0,3));
    if (
this.ani != "idle") {
      
setcharani("idle",null);
    }
    
sleep(this.dispT[temp.array[2]]);
  }else{
    if (
this.ani != "walk") {
      
setcharani("walk",null);
    }
  }

i would have noticed thiat earlier but i've been banned from the forum for the past two years.
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 04:47 PM.


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