Problem(s) with scripting the behavior of... an angry bee.

Started by Fitz, Mon 25/04/2011 18:59:38

Previous topic - Next topic

Fitz

I'm trying to script a following scene:

1. After the character has acquired a certain object, he's passing through a meadow - where he attracts the attention of an angry bee - which starts to follow him around.
2. Wherever he goes, it follows. And when he stops, it flies up to him and sits on his forearm - which he's too afraid to move.
3. After he's been idle for 5-7 seconds, it finally stings him.

So, first, I put this:

Code: ags
cBee.FollowCharacter(cGray, 10, 0);


and it does the following around part beautifully. But a problem arises. I wanted him to always face the bee when he's not moving - for obvious reasons, and also because I want it to land on his arm, and it's the closest point to the bee only when he's facing it. The thing is, though, even though I put this:

Code: ags
 if (cGray.Moving ==false){
  cGray.FaceCharacter(cStrayBee2);}


in Repeat_Exec, he doesn't always turn around. And even if he does, he turns away again even if it's still there.

Also, how do I have the bee land on a specific part of his body? I'm guessing it involves specifying the main character's x and y (meaing where his feet are) plus/minus the distance from that point to the point where the bee should land. Keeping in mind that the x value will differ depending on which direction the character is facing (x - something if he's facing left, and x + something if facing right).

Allllso, I should mention that the character should be able to move around freely if the player wants to - not to make it explicit that they have to wait (be idle) for several seconds, because getting stung is the point of the puzzle, not something to avoid (by the way, is there some sort of a "HasBeenIdle(int how long)" command, and if not, how can I set a required period of idleness before he gets stung?).

I did try to set the bee's baseline to the character's baseline while it's usual flight altitute is at his shoulders' height, so that I could use the IsColidingWithCharacter option - but that only worked nice with cBee.Move and not so much with cBee.FollowCharacter, because that way, it simply bumped into the character and stopped there.

Since this one is quite a toughie, please let me know which script goes where - just to avoid confusion.

Icey

I think this might work.

is(player.moving == false) player.facecharacter(cbee, eBlock);

Fitz

Yeah, that's actually what I did, my mistake was that I copied only one line from that script into the code quote here (edited the post to include all of it - which looks pretty close to yours). Thanks for making me actually notice, though :)

Icey


Sephiroth

Hey,

If you'd like to check if the bee has been on him for a certain amount of time you could use a timer:

Code: ags


bool under_attack = false;
bool idle = false;
int sting = 0;

function repeatedly_execute()
{

  if(under_attack && sting == 1)
  {
    if(!player.Moving && !idle)
    {
      idle = true;
      SetTimer(1,  GetGameSpeed()*15);
    }
    else if(player.Moving && idle)
    {
      idle = false; 
    }

    if(IsTimerExpired(1) && idle)
    {
    //execute the sting part 
      sting = 2; 
      idle = false;
      under_attack = false;
    }
  }
  else if(under_attack && !sting && !player.Moving)
  {
    player.FaceCharacter(cBee, eNoBlock);
  }

}



When the bee attack sequence starts, you set under_attack = true;
When the bee is on the player set sting = 1;
If the bee flies again before it stings, sting = 0; idle = false;
Change the timer from 15 seconds to whatever you want.
And put your code for when it has to sting.

For the bee landing on player I thought moving it over the player would work fine, but maybe you can change the view of the player to have the bee drawn on the sprite instead.

I don't have AGS on this computer atm so tell me if there's any problem.

Fitz

Where exactly do I put the

Code: ags
bool under_attack = false;
bool idle = false;
int sting = 0;


part? Because right now, wherever I put it (my guesses were first BeforeFadeIn and then GlobalScript), it says it doesn't recognize/understand the under_attack part in the script. Sorry, I'm still confused sometimes about where things go, plus now I'm really really tired.

But the idea with the timer is great, I'm kicking myself for not having thought of that!

Sephiroth

Inside Global script this function should already be here. Just add the code inside, and the 3 lines just above:
Code: ags


bool under_attack = false;
bool idle = false;
int sting = 0;

function repeatedly_execute()
{

}



I just tried in AGS without a problem, is there an error? Can you write the error output pls?
I haven't tested but the code is supposed to work the exact same way inside room script I think.

If you use it in room script then all you have to do is copy paste the whole code I wrote previously, since there is no repeatedly_execute inside room script by default.

Fitz

Now the game started with no problem - except... nothing's happening ;) Might be that I still have my original, room-specific scripts active (if he steps onto a hotspot, the bee goes into FollowCharacter mode, and I think something else, too) - and I don't feel up to tinkering with those at the moment, I'm half asleep right now. The whole sequence is also dependent on a bunch of other factors, like HasInventory and a global variable for what time of the day it is, so I'd rather have a script that I could use within Room events rather than Global Script (which I have used very little so far). And I did use Repeatedly_Execute inside rooms before and it worked just fine.

But as I said, the idea with the timer itself gave me a bunch of ideas - even to refine the whole sequence a bit. Now if only I manage to fix the thing with him facing the bee when idle and get the bee to sit on him, it'll be all good.

Sephiroth

When the bee goes into FollowCharacter mode, put this line:

Code: ags

under_attack = true;


When the bee lands on player, put this:

Code: ags

sting = 1;


And put any additional code for when the bee stings inside the code where I put:
Code: ags

    //execute the sting part 


Setting under_attack to true is what launches the whole event.

Fitz

When I put the

Code: ags
under_attack = true;


in the Room events (Stand on hotspot, to be exact), it returns this error:

Failed to save room room2.crm; details below
room2.asc(141): Error (line 141): Undefined token 'under_attack'

Sephiroth

Make sure you have the 3 lines inside the room script but outside any function. It should work.

Code: ags

bool under_attack = false;
bool idle = false;
int sting = 0;


Or can you post the room code?
Also make sure these lines are written before/above the under_attack = true; code.

Fitz

Strange: when I copied the three lines into the room script, the game ran fine - but NOTHING happened. The character didn't face the bee but once, even. So I put the whole script again in the room's Repeatedly_Execute again - and still, nada.

I'm thinking this... If I set the bee's baseline to the same as the character's (his feet are at 215) and make cBee.Solid = false, it won't bump into the character. But when the timer expires, I could set to switch it to true, and voila, bumps into him right where I want it to, can't go any further. Then I use IsCollidingWithCharacter and ignite the function.

Except the FaceCharacter doesn't work properly. Darnation :-\ It actually failed me in another situation, too. I wanted the character to face the sun - and what he does is turn away from it, even though he's not even close to being in the same line vertically.

Edit: he actually turns to face the bee for half a second when it ventures as far as some 30-40 pixels away from him. But it seldom goes that far and turns around instantly, and he's turns away the second it does - long before it even get close to him, never mind pass him to reach the opposite end of its restricted area.

Sephiroth

Code: ags


bool under_attack = false;
bool idle = false;
int sting = 0;

function hHotspot1_WalkOn()
{
  under_attack = true;
  cBee.FollowCharacter(player, 10);
}

function room_RepExec()
{
  if(under_attack && sting == 1)
  {
    if(!player.Moving && !idle)
    {
      idle = true;
      SetTimer(1,  GetGameSpeed()*15);
    }
    else if(player.Moving && idle)
    {
      idle = false; 
    }

    if(IsTimerExpired(1) && idle)
    {
    //execute the sting part 
      Display("The bee attacked you!");
      sting = 2; 
      idle = false;
    }
  }
  else if(under_attack && !sting && !player.Moving)
  {
    player.FaceCharacter(cBee, eNoBlock);
    
  }

}




This is what the room script looks like, you would just need to use "sting = 1;" when the bee lands, then it will wait for player to be idle (not moving) for 15 sec and then display "The bee attacked you".

I just realised I had something wrong in the code, you need to use the event tab of the room to link Room_RepExec() properly. I edited the code.

Sorry I'm a bit tired too, hope this work like you expected.

Fitz

That's the thing - he doesn't. I checked and there's no other conflicting FaceCharacter command in use in Room script or elsewhere. I thought it was about the FollowCharacter command, but when I changed it to Move (with added waypoints, just to have the bee move from one end of the screen to another), there was absolutely no reaction from the main character. I even tried to work around it with

Code: ags
if (cBee.x > cGray.x + 5) {
  cGray.FaceLocation(320, 215) //the farthest point right in the room


and the opposite for him to look left, but that didn't work, either. I might've messed something up in that one, I'm pretty brain dead right now - but the whole FaceCharacter command not working/working weird is bugging the hell out of me.

Sephiroth

This is working fine with me , I created a room, a hotspot, a bee character, and put this code in the room script, but you need to link it in the room property panel for it to work (room repeatedly execute).

The hotspot must be linked the same way.
Also make sure you actually walk on the hotspot by adding a Display("test");

Btw I edited the code so pls paste it again.

Fitz

I *think* I followed all your instructions - and still nothing. I can tell when the hotspot is activated, because if he stands on it, the bee goes into FollowCharacter mode. But other than that, nothing happens. He just stands there, staring in one direction, the bee flies around him to and fro.

That's it for today, though, I need sleep. I'll try something tomorrow - but if I can't get that damn FaceCharacter command to work right, I'll have to figure something else out. And as I mentioned, this isn't the first time it does the exact opposite of what it's expcted to. Could it be that I'm experiencing some sort of a glitch here?

Sephiroth

Yeah strange, I can walk and have the bee follow me and whenever I stop it forces me to face it. Please post your room code, this is the easiest way to help you.

Fitz

Edit: deleted in order to avoid eternal shame ;)

Sephiroth

In the repeatedly_execute, try replacing the cstraybee1 line with:

Code: ags

cStrayBee1.Walk(walkx, walky, eNoBlock);


This may interfere with the rest of the code if the functions is blocking.
Does it work if you completely remove the random moving part with cstraybee1 from the rep_exec?
Was the Bee1 moving randomly as expected?

Fitz

I did. Nothing changed. First time I tried, Bee #2 froze after passing by Gray. The second time, everything went back to the original state. I removed Bee1 random movement. That didn't work, either. The only other things animating constantly are a beehive and a cig - but both are on eRepeat, eNoBlock, in AfterFadeIn/BefoteFadeIn

SMF spam blocked by CleanTalk