Help needed with scripting an NPC to walk back and forth

Started by Malcoladdin, Thu 21/10/2021 23:15:51

Previous topic - Next topic

Malcoladdin

I am very new to the world of scripting, and am having a bit of a hard time understanding the language. I have gone through the first few tutorials for Sammy's Quest, which have been very helpful in helping me with the first few steps, ie creating the 'world' of 12 walkable rooms, making the first few interactive objects and so on. I have also read the tutorials on scripting, but if I am being perfectly honest, a bit of it went over my head. I am sure that with practice I will get it, but it can be frustrating trying to work things out when you are a beginner.

Something I need advice on:

When the player, Clancy, enters the 'cave entrance' room where Samuel is, I have got Samuel to walk to him, say his speech, then walk back and forth... but this only works the first time the player enters the room. Ideally, I would like Samuel to walk back and forth between two spots when he enters the room. Samuel spawns at 219, 200. I have tried functions such as

Code: ags
function room_RepExec() {
  if (cSamuel.x==219)cSamuel.AddWaypoint(286, 183);


(before the below block of script)
but this seems to just freeze the character in place

Here is what I have at the moment.

Code: ags
function room_FirstLoad()
{
cSamuel.Walk(70, 197, eBlock, eWalkableAreas);
cSamuel.Say ("Stay out of the mine! It is dangerous!");
}

function room_RepExec() {
  if (cSamuel.x==70)cSamuel.AddWaypoint(286, 183);
  else if (cSamuel.x==286)cSamuel.AddWaypoint(161, 187);
  else if (cSamuel.x==161)cSamuel.AddWaypoint(286, 193);
}


If anyone could give me some guidance, that would be much appreciated. Thanks!

timid_dolphin

#1
Hi Malcoladdin!
let me see if I can help.

My first suggestion is to organise your code a little differently. The way you've laid it out is perfectly fine in terms of functionality, but you can make your code more readable by taking a 'function based' approach.

What I would do is break things down into functions, where each function does one thing, which is labelled very clearly and unambiguously, for example:

Code: ags

function samWarning()
{
  cSamuel.Walk(70, 197, eBlock, eWalkableAreas);
  cSamuel.Say ("Stay out of the mine! It is dangerous!");
}

function samWalk()
{
  if (cSamuel.x==70)
  {
  cSamuel.AddWaypoint(286, 183);
  } else if (cSamuel.x==286)
  {
  cSamuel.AddWaypoint(161, 187);
  } else if (cSamuel.x==161)
  {
  cSamuel.AddWaypoint(286, 193);
  }
}

function room_RepExec() 
{
  samWalk();
}

function room_FirstLoad()
{
  samWarning();
}



So now we have our two functions basically behaving how we want, it's easier to test their behaviour. I suspect that the problem is that we're calling samWarning() from room_FirstLoad(), but we want to call it every time the player enters the room. There's also a room_Load and a room_AfterFadeIn function, these are called every time the player enters the room. You can access these in the Room Events panel in the Room Edit window.

You should put samWalk() into room_AfterFadeIn, as you can't put blocking functions before the fade-in.

I hope this helps!


EDIT: I reread your code and I think I understand what you want a bit better. Do you only want Samuel's warning to happen the first time the room loads, and after this you want the walking back and forth behaviour?

If this is the case, you should keep samWarning() in room_FirstLoad(), and figure out the conditions for every other room load. For example in room_AfterFadeIn() you could check to see if this character is moving with cSamuel.Moving, eg:

Code: ags


function sendSamToLoop()
{
  if(!cSamuel.Moving)                     //checks if Samuel is not moving using the logical NOT operator !
 {
  cSamuel.AddWayPoint(70, 197);   //send him to the start of the loop you set up in samWalk()
 }
}

function room_AfterFadeIn()
{
  sendSamToLoop();
}




Also - as your code gets more complicated, you can call functions from your own functions to keep your code organised, eg:

Code: ags


function doOneThing()
{
  //bla bla bla code
}

function doSomeOtherThing()
{
  //etc etc etc
}

function complicatedFunction()
{
  doOneThing();
  doSomeOtherThing();
}



This way when you need to fix something you can focus on one thing at a time, and you can even reuse the same block of code somewhere else when it makes sense!

Malcoladdin

Thanks very much for your help Timid Dolphin! That really helped me to understand the scripting system of AGS a bit more clearly. It is really like learning a whole new language haha. Hopefully I can figure most of this out. With a bit of perseverance, I am sure I will get there

timid_dolphin

No worries, I'm happy to help!

I think AGS is really well designed, and as with any coding thing, the more you work with it, the more sense it'll make.
Soon enough, you'll be looking over your old code thinking - why did I do it that way? And you'll rewrite the whole thing in five minutes using half the lines.

Good luck with your project!

SMF spam blocked by CleanTalk