• All, I am currently in the process of migrating domain registrations. During this time there may be some intermittent outages or slowdowns. Please contact staff if you have any questions.

How to Spawn a NPC anytime in a level/stage?

Bruce

Active member
What I am trying to do is to be able to spawn the NPC called Mikey anytime in the level/stage whenever there is enough SM.
I want to limit 1 NPC per player to be out in the level at a time. Is there a way for me to do so?

I am using SP meter script (Tech Demo) by msmalik681 for SM meter.
link: SP meter script (Tech Demo)

After Mikey is spawned in the level, I can execute the command d u a to have Mikey perform anim freespecial1


This is the script I have:
Code:
void spawn01(void vName, float fX, float fY, float fZ)
{

    void self = getlocalvar("self"); //Get calling entity.
    void vSpawn; //Spawn object.
    int  iDirection = getentityproperty(self, "direction");

    clearspawnentry(); //Clear current spawn entry.
      setspawnentry("name", vName); //Acquire spawn entity by name.

    if (iDirection == 0){ //Is entity facing left?               
          fX = -fX; //Reverse X direction to match facing.
    }

      fX = fX + getentityproperty(self, "x"); //Get X location and add adjustment.
      fY = fY + getentityproperty(self, "a"); //Get Y location and add adjustment.
      fZ = fZ + getentityproperty(self, "z"); //Get Z location and add adjustment.
  
    vSpawn = spawn(); //Spawn in entity.

    changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location.
    changeentityproperty(vSpawn, "direction", iDirection); //Set direction.
  
    return vSpawn; //Return spawn.
}

This is the Mikey text file:
Code:
name                Mikey
type                npc
subtype             follow
lifespan            60
remove                0
nolife              1
hostile             enemy
candamage           enemy obstacle
speed               20
running             40 1 1 5 1
turndelay           0    3
bounce              1
noquake             1
#shadow 3
gfxshadow 1 3
diesound            data/chars/players/Helpers/Ally/die1.wav
flash               flash
bflash              guard
dust                dust01
toflip              1
nodieblink          1
falldie             2

palette data/chars/players/Helpers/Ally/Mikey_Stand02.gif #1
animationscript        data/scripts/animatedscripts.c
ondrawscript        data/scripts/shadows.c

load                quake

com d u  a   freespecial1
   
       
anim    idle
    @script
    void self = getlocalvar("self");
            if(getentityproperty(self, "health")<=0)  {
                damageentity(self, self, 100, 1, 1);
             }
    @end_script
    loop    1
    offset    344 550
    bbox 0 0 0 0
    delay    5
    frame    data/chars/players/Helpers/Ally/Mikey_Stand01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Stand02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Stand01.gif
   
anim    idle1
    @script
    void self = getlocalvar("self");
            if(getentityproperty(self, "health")<=0)  {
                damageentity(self, self, 100, 1, 1);
             }
    @end_script
    loop    1
    offset    344 550
    bbox 0 0 0 0
    range 0 30
    delay    5
    frame    data/chars/players/Helpers/Ally/Mikey_Stand01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Stand02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Stand01.gif
   
anim    walk
    loop    1
    offset    344 550
    bbox    0 0 0 0
    range 30 90
    delay    5
    frame    data/chars/players/Helpers/Ally/Mikey_Walk01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk03.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk04.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk05.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk06.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk07.gif
   
anim    attack1  
    fastattack    1
    loop    0
    offset    344 550
    bbox 0 0 0 0
    range 0 29
    delay    4
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_03.gif
    attack1 378 359 146 163 10 0 0 0 20 15
    delay    8
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_04.gif
    attack  0 0 0 0 0 0 0 0 0 0
    delay    4
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_05.gif

anim  freespecial1
    @cmd costsm 5 "ANI_freespecial99"
    fastattack 1
    attackone 0
    hitfx data/sounds/beat3.wav
    loop 0
    offset    344 550
    bbox    0 0 0 0
    delay    5
    frame    data/chars/players/Helpers/Ally/special01.gif
    frame    data/chars/players/Helpers/Ally/special02.gif
    frame    data/chars/players/Helpers/Ally/special03.gif
    frame    data/chars/players/HelpersAlly//special04.gif
    attack2    156 179 112 121  5   0   10  0     20     20   
    frame    data/chars/players/Helpers/Ally/land01.gif 

anim    pain
    loop    0
    offset  344 550
    bbox    252 219 89 181
    delay    4
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  341 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  344 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  347 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  344 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  341 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  344 550
    delay    12
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif

anim    fall
@script
       void self = getlocalvar("self");
      
       if(frame==0){
         if(getentityproperty(self,"jugglepoints") <= 0){
                changeentityproperty(self, "animation", openborconstant("ANI_FALL3"));
         }
       }
        
    @end_script    
    landframe    2  
    loop    0
    offset  344 550
    delay    2
    bbox    252 219 89 181
    frame    data/chars/players/Helpers/Ally/Mikey_fall01.gif
    delay    999
    frame    data/chars/players/Helpers/Ally/Mikey_fall01.gif
    delay    1
    frame    data/chars/players/Helpers/Ally/Mikey_fall02.gif   

anim    rise
    loop    0
    offset  344 550
    delay    55
    frame    data/chars/players/Helpers/Ally/Mikey_fall02.gif
    delay    20
    frame    data/chars/players/Helpers/Ally/Mikey_rise01.gif
    delay    14
    frame    data/chars/players/Helpers/Ally/Mikey_fall02.gif
    delay    10
    frame    data/chars/players/Helpers/Ally/Mikey_rise01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_rise02.gif

This is how I spawn Mikey:

Code:
name      Ken
....
....
com d s   freespecial20
....
....

anim freespecial20
   @cmd costsm 10 "ANI_freespecial99"
   @cmd shadow 5 20 120 6 2 255 0 0 # Red
   fastattack 1
   attackone 0
   hitfx data/sounds/beat3.wav
   loop 0
   offset 303 400
   bbox 0 0 0 0
   delay 5
   sound data/chars/players/Ken/spawn01.wav
   @cmd spawn01 "Mikey" 0 0 0
   delay 10
   frame data/chars/players/Ken/01.gif
   frame data/chars/players/Ken/02.gif
   frame data/chars/players/Ken/03.gif
   frame data/chars/players/Ken/04.gif
   delay 10
   frame data/chars/players/Ken/02.gif
   frame data/chars/players/Ken/03.gif
   frame data/chars/players/Ken/04.gif
   delay 10
   @cmd projectile 1 "dust03" 0 0 0
   frame data/chars/players/Ken/land01.gif

This is all I have so far.
Whenever I spawn Mikey, sometimes I could only see Mikey for a blink of an eye.
Obviously, there is something wrong with the code.
Please notice that this is my first time ever coding about spawning a NPC Ally

Can someone please take a look at the code and see what I did wrong?
Thank you so much for your help
 
Solution
How do I make Mikey goes attacking enemies when they are within the range,
then comes back to the player whenever enemies are out of range or all killed?
Right now Mikey always stays at the player at all time.

This question makes me thinking recently and I figured out a way to implement this, which is by using this thinkscript:
loyal1.c
C:
void main(){
  void self = getlocalvar("self");
  int En = openborvariant("count_enemies");
  void P1 = getplayerproperty(0, "entity");

  if(En > 0){
    changeentityproperty(self,"parent", NULL());
    changeentityproperty(self, "aimove", openborconstant("AIMOVE1_CHASE"));
  } else if(P1){
    changeentityproperty(self,"parent", P1);
  } else {
    changeentityproperty(self,"parent"...
Hmmm... it's hard to tell the actual cause so I'm going to ask couple things:
1. Can Mikey be spawned like any entity in level text?
2. Why are you using script in Mikey's IDLE?
3. Why is Mikey using 2 IDLEs (IDLE and IDLE1)?
 
Hmmm... it's hard to tell the actual cause so I'm going to ask couple things:
1. Can Mikey be spawned like any entity in level text?
2. Why are you using script in Mikey's IDLE?
3. Why is Mikey using 2 IDLEs (IDLE and IDLE1)?
I was reading the manual and I was thinking to make him do something else with idle1.
as far as the script in the idle, I copied it from the player character and forgot to delete it.
I removed the idle1 the script in the idle, the result is still the same.

---------------------------------------------------
I added Mikey to the level.txt as:
Code:
spawn  Mikey
    coords 150 440
    at  0

and in model.txt as:
Code:
load    Mikey        data/chars/players/Helpers/Ally/Mikey.txt

I can could see him falling down to the ground in the stage, but as soon as he hit the ground, he disappeared.
Furthermore, I added him as a player, I could control him in the stage just fine...
I just can't figure what I am doing wrong :-(


Thank you so much
 
I'm really puzzled with this. The last thing I need to ask is this:
ondrawscript data/scripts/shadows.c

Why do you use this?

Try spawning Mikey with this disabled to test. If that still doesn't work, you'd need to pack mikey and upload it for me to test him myself.
 
I'm really puzzled with this. The last thing I need to ask is this:


Why do you use this?

Try spawning Mikey with this disabled to test. If that still doesn't work, you'd need to pack mikey and upload it for me to test him myself.
There is no reason I would use shadows.c so I deleted it as it is supposed to be in Ken.txt for SM counter and display.

I double checked Mikey.txt and found out the 'turndelay' was missing. That's why it didn't work, sorry about that.
However, after adding turndelay to Mikey.txt,
only
Code:
anim  spawn
    spawnframe 1 0 0 0 0
    custentity Mikey
    ........
in Ken.txt would work and there seems to be a problem that Mikey only sticks to Ken and never leaves Ken at anytime.
When Ken gets close to the enemies, Mikey would attack them, but if Ken executes any attack, Mikey freezes
and does not attack enemies anymore and stuck with that last frame.

@cmd spawn01 "Mikey" 0 0 0 never works (maybe there is something wrong with the script? )

This is what I ended up with for Mikey.txt
Code:
name                Mikey
type                npc
subtype             follow
lifespan            60
nolife              1
hostile             enemy
candamage           enemy obstacle
speed               20
running             40 1 1 5 1
turndelay           0    3
bounce              1
noquake             1
#shadow             3
gfxshadow           1  3
diesound            data/chars/players/Helpers/Ally/die1.wav
flash               flash
bflash              guard
dust                dust01
toflip              1
nodieblink          1
falldie             2

palette data/chars/players/Helpers/Ally/Mikey_Stand02.gif #1
animationscript        data/scripts/animatedscripts.c

com d u  a   freespecial1
   
anim    idle
    loop    1
    offset    344 550
    bbox 0 0 0 0
    delay    5
    frame    data/chars/players/Helpers/Ally/Mikey_Idle01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Idle02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Idle01.gif
 
anim    walk
    loop    1
    offset    344 550
    bbox    0 0 0 0
    range 30 90
    delay    5
    frame    data/chars/players/Helpers/Ally/Mikey_Walk01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk03.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk04.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk05.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk06.gif
    frame    data/chars/players/Helpers/Ally/Mikey_Walk07.gif
 
anim    attack1
    fastattack    1
    loop    0
    offset    344 550
    bbox 0 0 0 0
    range 0 29
    delay    4
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_02.gif
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_03.gif
    attack1 378 359 146 163 10 0 0 0 20 15
    delay    8
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_04.gif
    attack  0 0 0 0 0 0 0 0 0 0
    delay    4
    frame    data/chars/players/Helpers/Ally/Mikey_SKill1_05.gif

anim  freespecial1
    @cmd costsm 5 "ANI_freespecial99"
    fastattack 1
    attackone 0
    hitfx data/sounds/beat3.wav
    loop 0
    offset    344 550
    bbox    0 0 0 0
    delay    5
    frame    data/chars/players/Helpers/Ally/special01.gif
    frame    data/chars/players/Helpers/Ally/special02.gif
    frame    data/chars/players/Helpers/Ally/special03.gif
    frame    data/chars/players/HelpersAlly//special04.gif
    attack2    156 179 112 121  5   0   10  0     20     20  
    frame    data/chars/players/Helpers/Ally/land01.gif

anim    pain
    loop    0
    offset  344 550
    bbox    252 219 89 181
    delay    4
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  341 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  344 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  347 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  344 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  341 550
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif
    offset  344 550
    delay    12
    frame    data/chars/players/Helpers/Ally/Mikey_pain01.gif

anim    fall  
    landframe    2
    loop    0
    offset  344 550
    delay    2
    bbox    252 219 89 181
    frame    data/chars/players/Helpers/Ally/Mikey_fall01.gif
    delay    999
    frame    data/chars/players/Helpers/Ally/Mikey_fall01.gif
    delay    1
    frame    data/chars/players/Helpers/Ally/Mikey_fall02.gif  

anim    rise
    loop    0
    offset  344 550
    delay    55
    frame    data/chars/players/Helpers/Ally/Mikey_fall02.gif
    delay    20
    frame    data/chars/players/Helpers/Ally/Mikey_rise01.gif
    delay    14
    frame    data/chars/players/Helpers/Ally/Mikey_fall02.gif
    delay    10
    frame    data/chars/players/Helpers/Ally/Mikey_rise01.gif
    frame    data/chars/players/Helpers/Ally/Mikey_rise02.gif

Thank you very much for helping

Edited:
1. How can I spawn the NPC Ally with a command whenever I want in the level?
2. How can I prevent my NPC Ally from sticking to my character at all time?

Thanks a lot
 
Last edited:
Glad you could get Mikey summoned :D

@cmd spawn01 "Mikey" 0 0 0 never works (maybe there is something wrong with the script? )

That functions always work here provided the to be spawned entity to be loaded first prior to spawning. If you have loaded Mikey in models.txt, it should work.

1. How can I spawn the NPC Ally with a command whenever I want in the level?

When you say command, is it :
a. by performing summon animation or FREESPECIAL?
or
b. by pressing a key?

Each option requires totally different approach so I need to get answer before answering the question.
2. How can I prevent my NPC Ally from sticking to my character at all time?

Hmmm... do you want Mikey to follow player or not to follow player at all? if it's the latter, you need to remove subtype follow from his header.txt.
 
I was messing around with the Mikey.txt and Ken.txt last night.
I ended up with the same problem as before: I was not able to summon Mikey at all.
It took me hours trying to figure out what's going on and it drove me nuts!

At the end, I changed relative from 0 to 1 just to test, somehow it worked.
Code:
spawnframe 1 0 0 0 1    #Relative has to be 1 in order for it to work, WHY ????
    custentity Mikey
Although now I am able to summon Mikey either by
anim spawn or FREESPECIAL in the level with spawnframe setup above,
I am still so lost and confused on how to set it up properly.

Regardless, @cmd spawn01 "Mikey" 0 0 0 STILL never works for me at all.
there got to be something wrong with my setup somehow.


When you say command, is it :
a. by performing summon animation or FREESPECIAL?
or
b. by pressing a key?
What I like to do is
after I summon Mikey, I would like to be able to execute FREESPECIAL command to have Mikey doing something.

I have FREESPECIAL1 with
com d u a freespecial1 in Mikey.txt

I have tried this d u a command, but it never worked.

Hmmm... do you want Mikey to follow player or not to follow player at all? if it's the latter, you need to remove subtype follow from his header.txt.
I do like Mikey to follow the player and goes attacking enemies when they are on the screen.
Then goes back to the player's side when there is no more enemy on the screen or out of range.
The problems that I am having right now is

1. Mikey always overlaps on top of the player regardless the enemies are close or far away.
2. Mikey only attacks the enemies when they are very close to the player.
3. If the player moves or attacks the enemies for a bit while Mikey is attacking them, he freezes.

I would like to learn how to setup the NPC Ally properly.
If you have examples on how to set it up, that would help me a lot.

I read the manual about idle1, 2, walk1, 2 but I can't understand the purpose of it.
I wish the manual had more examples....

Thank you very much
 
Regardless, @cmd spawn01 "Mikey" 0 0 0 STILL never works for me at all.

When you say never work, Mikey was never seen anywhere?
You have loaded Mikey before right?

I would like to be able to execute FREESPECIAL command to have Mikey doing something.

You can't declare com in NPC nor enemy text to force them to perform something. You have to use other way, one of these methods:
1. Generic order system
When the command is given, a certain global variable is set. Then NPC who can take the order will react to perform certain animation.
This method is stable cause NPC won't take the order when he/she/it isn't able to such as being in PAIN, FALLing or RISE. The tough part is that the variable needs to be resetted or IOW the order may need to be revoked to prevent NPC retaking the order after the first take. The revoking could be done by the player or by NPC.
2. Direct forcing
When the command is given, player directly changes NPC's animation to specified animation.
This method doesn't need revoking order cause the forcing is only done when command is given. However it is unstable cause NPC might be in improper state such as PAIN, FALLing or RISing.

Which method do you prefer?

I wish the manual had more examples....

Yeah, my wish too here.
 
Regardless, @cmd spawn01 "Mikey" 0 0 0 STILL never works for me at all.

When you say never work, Mikey was never seen anywhere?
You have loaded Mikey before right?
Yep Mike never spawns on the screen with @cmd spawn01 "Mikey" 0 0 0
This is what I have on the model.txt:
Code:
load    Mikey        data/chars/players/Helpers/Ally/Mikey.txt
I even loaded him on Ken.txt


After I spawn Mikey with
Code:
    spawnframe 1 0 0 0 0
    custentity Mikey
Do you know why Mikey freezes after I have Ken move around or do some attacks?

How do I make Mikey goes attacking enemies when they are within the range,
then comes back to the player whenever enemies are out of range or all killed?
Right now Mikey always stays at the player at all time.


I prefer method 2. Direct forcing
since the NPC's bbox will be 0 0 0 0, so they are always invisible to the enemies.
Haven't said that, I would like to see the examples for both methods 1 & 2 if that's possible.

Thanks a lot
 
Mike never spawns on the screen with @cmd spawn01 "Mikey" 0 0 0

That's really strange. Where did you get this function?

Do you know why Mikey freezes after I have Ken move around or do some attacks?

How do I make Mikey goes attacking enemies when they are within the range,
then comes back to the player whenever enemies are out of range or all killed?
Right now Mikey always stays at the player at all time.

Sadly, I don't know. I rarely use NPC helper which follows player. When I spawn NPC, the latter is not following any player IOW they are free to walk around, killing enemies or not.

I would like to see the examples for both methods 1 & 2 if that's possible.

I couldn't show example with method 2 if Mikey couldn't be spawned with spawn01 function. I need to use the function to link player with NPC for the player to control the NPC.
As for method 1, I'll make simple example for it.
 
Mike never spawns on the screen with @cmd spawn01 "Mikey" 0 0 0

That's really strange. Where did you get this function?
I got this function from the existing game that I've been modifying.
I saw this same code on this website somewhere too.
So I think this person probably copied this function from this website.
I can see alot of other functions in the animationscript and ondrawscript were copied cat from this website....
Code:
void spawn01(void vName, float fX, float fY, float fZ)
{

    void self = getlocalvar("self"); //Get calling entity.
    void vSpawn; //Spawn object.
    int  iDirection = getentityproperty(self, "direction");

    clearspawnentry(); //Clear current spawn entry.
      setspawnentry("name", vName); //Acquire spawn entity by name.

    if (iDirection == 0){ //Is entity facing left?              
          fX = -fX; //Reverse X direction to match facing.
    }

      fX = fX + getentityproperty(self, "x"); //Get X location and add adjustment.
      fY = fY + getentityproperty(self, "a"); //Get Y location and add adjustment.
      fZ = fZ + getentityproperty(self, "z"); //Get Z location and add adjustment.
 
    vSpawn = spawn(); //Spawn in entity.

    changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location.
    changeentityproperty(vSpawn, "direction", iDirection); //Set direction.
 
    return vSpawn; //Return spawn.
}

Hopefully someone else can help me on how to spawn a NPC with subtype follow and figures out why function
@cmd spawn01 "Mikey" 0 0 0
is not working and

why the NPC freezes with function
Code:
      spawnframe 1 0 0 0 1
      custentity Mikey

I actually made a mistake on my previous post that
the function below only works when relative is 1:
Code:
    spawnframe 1 0 0 0 1 <--- notice that this relative value has to be 1, it won't work when it is 0, WHY??????
    custentity Mikey
Thank you very much



Edit:
I added the range values to anim idle
and changed the range values on anim walk and anim attack1.
Now Mikey (NPC) goes attacking enemies and spawns back to the player whenever the player is out of range
or goes back to the player whenever all enemies are killed.
However, I found out that Mikey freezes whenever the player is out of range and he has to spawn back to the player while performing anim attack1.
Basically, if he is not performing anim attack1 and spawns back to the player, he does not freeze.

How can I fix this freezing problem?????
Thanks alot
 
Last edited:
I've done some tests on my lab module and managed to create method 1 to give control NPC. Here's how:
1. Player character needs this script to give the order:
C:
anim    freespecial2
@script
  if(frame == 2){
    setglobalvar("Order1", 1);
  }
  if(frame == 4){
    setglobalvar("Order1", 0);
  }
@end_script

This example sets the Order1 global variable to 1 in 3rd frame and sets it to 0 in 5th frame. The former is for giving the order and the latter is revoking order.

2. NPC needs this script to accept the order:
Code:
anim    idle
@script
  if(frame > 0){
    void self = getlocalvar("self");
    int Order = getglobalvar("Order1");

    if(Order==1){
      performattack(self, openborconstant("ANI_FOLLOW2"));
    }
  }
@end_script

The NPC will perform FOLLOW2 if Order1 global variable mentioned above is set to 1 aka order is given. This script is declared in IDLE. It could be declared in WALK but NPC must be stopped before performing the FOLLOW2.

3. Stabilizer
As I've mentioned before, global variable must be resetted aka order is revoked. There are multiple ways, one way is mentioned above. The other is by declaring this script in player's PAIN and FALL:
Code:
@script
  if(frame == 1){
    setglobalvar("Order1", 0);
  }
@end_script

This is in case player is attacked before revoking the order at 5th frame.
Another place to declare that script is in NPC's animation in FOLLOW2 that is.

I mentioned lab module above cause while coding this, I found 3rd way to control NPC which works like this: NPC checks parent's key check. If parent is holding certain key say attack key, NPC will perform certain animation.

Back to elephant in the room, I've tried spawning NPC in SPAWN animation with spawn01 function and it works as intended. I really can't figure out why the script doesn't work in your end.
 
I've done some tests on my lab module and managed to create method 1 to give control NPC. Here's how:
1. Player character needs this script to give the order:
C:
anim    freespecial2
@script
  if(frame == 2){
    setglobalvar("Order1", 1);
  }
  if(frame == 4){
    setglobalvar("Order1", 0);
  }
@end_script

This example sets the Order1 global variable to 1 in 3rd frame and sets it to 0 in 5th frame. The former is for giving the order and the latter is revoking order.

2. NPC needs this script to accept the order:
Code:
anim    idle
@script
  if(frame > 0){
    void self = getlocalvar("self");
    int Order = getglobalvar("Order1");

    if(Order==1){
      performattack(self, openborconstant("ANI_FOLLOW2"));
    }
  }
@end_script

The NPC will perform FOLLOW2 if Order1 global variable mentioned above is set to 1 aka order is given. This script is declared in IDLE. It could be declared in WALK but NPC must be stopped before performing the FOLLOW2.

3. Stabilizer
As I've mentioned before, global variable must be resetted aka order is revoked. There are multiple ways, one way is mentioned above. The other is by declaring this script in player's PAIN and FALL:
Code:
@script
  if(frame == 1){
    setglobalvar("Order1", 0);
  }
@end_script

This is in case player is attacked before revoking the order at 5th frame.
Another place to declare that script is in NPC's animation in FOLLOW2 that is.

I mentioned lab module above cause while coding this, I found 3rd way to control NPC which works like this: NPC checks parent's key check. If parent is holding certain key say attack key, NPC will perform certain animation.

Back to elephant in the room, I've tried spawning NPC in SPAWN animation with spawn01 function and it works as intended. I really can't figure out why the script doesn't work in your end.
I greatly appreciate for your time helping me out. However, due to the existing game that has 4 player mode, wouldn't there be a problem with this method 1?
For example, if the player 2 sets this global order to 1, the NPC Ally from any player can receive and execute this global order.
Also, if the player gives the global order while the NPC Ally is executing a long anim, this global order will be back to 0 once the player completes the 5th frame before the NPC Ally finishes this long anim.

The 3rd method sounds like something that I really want because I am planning to have multiple Freespecials.
Can you please help me understand how to set up for
parent's key check
and
NPC checks for parent's key

I've been messing around with the freezing problem,
but I can't still figure out why NPC freezes after it teleports back to the player while attacking the enemies whenever the player is out of range.
Is there a build-in system function that allows player to teleport the NPC Ally back to the player at anytime?
My Goal is to have the NPC Ally teleport back to the player first before it can receive and execute the attack order in a special situation.

Thank you so much


Edit:
I read the manual again and saw the anim respawn function.
I added this amin respawn and it has solved the freezing problem!
I still can not find the function that allows the player to teleport NPC anytime to the player anytime.
 
Last edited:
wouldn't there be a problem with this method 1?

Yep as I've mentioned before, each method has pros and cons. Since it's global, other NPCs could take order too. That's why it's great for giving order to multiple NPCs. It's also possible to include player's index in either global variable name or value so NPC could check who made the order before deciding to take the order or not.
And that's true also, the time to revoke the order needs proper balance so it requires trial and error to get it right and proper.

The 3rd method sounds like something that I really want because I am planning to have multiple Freespecials.

Okay, here's an example script in NPC's IDLE:
C:
anim    idle
@script
  if(frame > 0){
    void self = getlocalvar("self");
    void Par = getentityproperty(self,"parent");
    int PIndex = getentityproperty(Par,"playerindex");
    void iRKey = playerkeys(PIndex, 0, "attack");

    if(iRKey){
      performattack(self, openborconstant("ANI_FOLLOW1"));
    }
  }
@end_script
...

Similar script could be declared in WALK animation but speed and velocity must be grounded first for proper transition.
This script checks if parent is pressing attack key. If he/she is, perform FOLLOW1 animation.

BTW have you tried Map++ template yet? Arthur can summon NPCs with his summon NPC menu.
 
Yep as I've mentioned before, each method has pros and cons. Since it's global, other NPCs could take order too. That's why it's great for giving order to multiple NPCs. It's also possible to include player's index in either global variable name or value so NPC could check who made the order before deciding to take the order or not.
And that's true also, the time to revoke the order needs proper balance so it requires trial and error to get it right and proper.



Okay, here's an example script in NPC's IDLE:
C:
anim    idle
@script
  if(frame > 0){
    void self = getlocalvar("self");
    void Par = getentityproperty(self,"parent");
    int PIndex = getentityproperty(Par,"playerindex");
    void iRKey = playerkeys(PIndex, 0, "attack");

    if(iRKey){
      performattack(self, openborconstant("ANI_FOLLOW1"));
    }
  }
@end_script
...

Similar script could be declared in WALK animation but speed and velocity must be grounded first for proper transition.
This script checks if parent is pressing attack key. If he/she is, perform FOLLOW1 animation.

BTW have you tried Map++ template yet? Arthur can summon NPCs with his summon NPC menu.
I have not tried the Map++ template yet but I will.
I was trying to make the scripts such as "ParentOrder" , "ParentOrderOff" and "OberyParentOrder" for 4 players to send the orders to the NPC allies based on the player index.
However, I am stuck because I can not find a way to get the NPC Ally index.

Is there a way to get the NPC Ally index similar to player index (NPC Ally that player 1 summoned, will be 0, etc..)?

Can someone else please show me how to teleport the NPC Ally back to the player anytime?

void iRKey = playerkeys(PIndex, 0, "attack");
Is there anyway I can add Directions into the attack key such as D F attack, etc...


Thank you so much
 
How do I make Mikey goes attacking enemies when they are within the range,
then comes back to the player whenever enemies are out of range or all killed?
Right now Mikey always stays at the player at all time.

This question makes me thinking recently and I figured out a way to implement this, which is by using this thinkscript:
loyal1.c
C:
void main(){
  void self = getlocalvar("self");
  int En = openborvariant("count_enemies");
  void P1 = getplayerproperty(0, "entity");

  if(En > 0){
    changeentityproperty(self,"parent", NULL());
    changeentityproperty(self, "aimove", openborconstant("AIMOVE1_CHASE"));
  } else if(P1){
    changeentityproperty(self,"parent", P1);
  } else {
    changeentityproperty(self,"parent", NULL());
    changeentityproperty(self, "aimove", openborconstant("AIMOVE1_WANDER"));
  }
}

Save this in data/scripts folder and declare it in Mikey's header text with this line:
thinkscript data/scripts/loyal1.c

With this thinkscript, NPC will check number of enemies. If there are some enemies, NPC will not follow his/her parent and instead chase enemies until all of them are defeated. When there are no enemies, NPC will follow player 1. If there's no player 1, NPC will just wander around.

Is there a way to get the NPC Ally index similar to player index (NPC Ally that player 1 summoned, will be 0, etc..)?

NPCs aren't indexed so you'd need to index them manually. Or each player register summoned NPC in their entity variable. Doing that will also allows player to call NPCs back. Or do anything with the NPC actually.

Is there anyway I can add Directions into the attack key such as D F attack, etc...

Rather than doing that, I prefer NPC to check parent's animation instead. I'll code something for this, give me time.

[Next day]

Alright, here's script to check parent's animation instead of key press:
C:
anim    idle
@script
  if(frame > 0){
    void self = getlocalvar("self");
    void Par = getentityproperty(self,"parent");
    void PAniID = getentityproperty(Par,"animationID");

    if(Par && PAniID == openborconstant("ANI_FREESPECIAL2")){
      performattack(self, openborconstant("ANI_FOLLOW1"));
    }
  }
@end_script
...

anim    walk
@script
  if(frame > 0){
    void self = getlocalvar("self");
    void Par = getentityproperty(self,"parent");
    void PAniID = getentityproperty(Par,"animationID");

    if(Par && PAniID == openborconstant("ANI_FREESPECIAL2")){
      dasher(0, 0, 0);
      performattack(self, openborconstant("ANI_FOLLOW1"));
    }
  }
@end_script
...

This script makes NPC performs FOLLOW1 when parent is performing FREESPECIAL2.
 
Last edited:
Solution
C:
anim idle
@script
if(frame > 0){
void self = getlocalvar("self");
void Par = getentityproperty(self,"parent");
void PAniID = getentityproperty(Par,"animationID");

if(Par && PAniID == openborconstant("ANI_FREESPECIAL2")){
performattack(self, openborconstant("ANI_FOLLOW1"));
}
}
@end_script
...

anim walk
@script
if(frame > 0){
void self = getlocalvar("self");
void Par = getentityproperty(self,"parent");
void PAniID = getentityproperty(Par,"animationID");

if(Par && PAniID == openborconstant("ANI_FREESPECIAL2")){
dasher(0, 0, 0);
performattack(self, openborconstant("ANI_FOLLOW1"));
}
}
@end_script
...
This script makes NPC performs FOLLOW1 when parent is performing FREESPECIAL2.
OMG man, you are just seriously genious. I spent hours trying to code a bunch of different scripts, but none of them worked.
With your simply script, it has solved my problems: it even works for 4 player mode too!

I added this to teleport the NPC to the player:
Code:
          float fX = getentityproperty(Par, "x"); //X
          float fZ = getentityproperty(Par, "z"); //Z
          changeentityproperty(self, "position", fX, fZ);
I am not sure if anything is wrong for using this code, but it is working.

I very appreciate for all your time and help, god bless you!
 
Back
Top Bottom