In Progress Night Stalkers by danno

The project is currently under development.
negative captain, with the extra continue clause jack now doesn't interact at all.

C:
/*
* Caskey, Damon V.
* 2023-01-26 - Refactored from inline
* code by danno.
*
* Accept range and animation parameters.
*
* If an ally is within range, set both
* entities to accepted animations.
*/
void dc_team_attack(int range_x, int range_y, int range_z, int ally_position_y_min, int ally_position_y_max, int acting_animation, int ally_animation)
{
    void acting_entity = getlocalvar("self");
    void ally_entity = NULL();
    int ally_direction = openborconstant("DIRECTION_RIGHT");
    float ally_position_y = 0.0;
    int acting_direction = openborconstant("DIRECTION_RIGHT");
    int entity_count = 0;
    int cursor = 0;
    int ally_animation_old = 0;
    int ally_type = openborconstant("TYPE_NONE");
    int distance_x = 0;
    int distance_z = 0;
    char ally_model_name = "";
 
    /*
    * Get entity count and start looping.
    *
    */
    entity_count = openborvariant("count_entities");

    for (cursor = 0; cursor < entity_count; cursor++)
    {
        /*
        * Get entity from index curosr. Make sure
        * it is valid before moving on.
        */

        ally_entity = getentity(cursor);

        if (!ally_entity)
        {
            continue;
        }

        /*
        * The model text checks downstream are
        * slow. Let's optimize a bit by eliminating
        * entity types we don't care about first.
        */

        ally_type = getentityproperty(ally_entity, "type");

        if (!(ally_type & (openborconstant("TYPE_PLAYER") | openborconstant("TYPE_NPC"))))
        {
            continue;
        }

  
        ally_animation_old = getentityproperty(ally_entity, "animationID");
  

        /*
        * Compare animations. If entity is not
        * in one of the desired animations then
        * we move on.
        */

        ally_animation_old = getentityproperty(ally_entity, "animationID");

        if (ally_entity != openborconstant("ANI_FORWARDJUMP") && ally_entity != openborconstant("ANI_RUNJUMP"))
        {
            continue;
        }

        /*
        * Check models.
        */

        ally_model_name = getentityproperty(ally_entity, "name");

        if (ally_model_name != "Chris" && ally_model_name != "Hong")
        {
            continue;
        }

        /*
        * Check absolute positions.
        */

        ally_position_y = getentityproperty(ally_entity, "y");

        if (ally_position_y < ally_position_y_min && ally_position_y > ally_position_y_max)
        {
            continue;
        }

        /*
        * Check range.
        */

        distance_x = getRange(acting_entity, ally_entity, "x", 0);
        distance_z = getRange(acting_entity, ally_entity, "z", 0);
  
        if (distance_x > range_x || distance_z > range_z)
        {
            continue;
        }

        /*
        * Now we know we have a valid ally and it
        * can perform the team attack. Get direction
        * values and set up accordingly.
        */

        ally_direction = getentityproperty(ally_entity, "direction");
        acting_direction = getentityproperty(acting_entity, "direction");

        if (ally_direction == openborconstant("DIRECTION_RIGHT"))
        {
            if (acting_direction == openborconstant("DIRECTION_LEFT"))
            {
                performattack(ally_entity, ally_animation);
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_LEFT"));
                performattack(acting_entity, acting_animation);
            }
            else
            {
                performattack(ally_entity, ally_animation);
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_RIGHT"));
                performattack(acting_entity, acting_animation);                         
            }
        }
        else
        {
            if (acting_direction == openborconstant("DIRECTION_LEFT"))
            {
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_LEFT"));
                performattack(ally_entity, ally_animation);
                performattack(acting_entity, acting_animation);
            }
            else
            {         
                performattack(ally_entity, ally_animation);
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_RIGHT"));
                performattack(acting_entity, acting_animation);
            }
        }
    }
}

typo's fixed


Oh, I see the problem. Between deadlift sets right now, lol. Soon as I'm out of the gym ill post the fix.

DC
 
I'm confused right now about given entity directions. Wouldn't it be something like this?

C:
    void acting_entity = getlocalvar("self");
    void ally_entity = NULL();
    int ally_direction;
    float ally_position_y = 0.0;
    int acting_direction;
    int entity_count = 0;
    int cursor = 0;
    int ally_animation_old = 0;
    int ally_type = openborconstant("TYPE_NONE");
    int distance_x = 0;
    int distance_z = 0;
    char ally_model_name = "";

And then this after?

C:
        ally_direction = getentityproperty(ally_entity, "direction");
        acting_direction = getentityproperty(acting_entity, "direction");

After having both main and allied entities' directions set, you have this kind.

C:
if (ally_direction == openborconstant("DIRECTION_RIGHT"))
{
  if (acting_direction == openborconstant("DIRECTION_LEFT"))
  {
    // One particular argument.
  } 
  else
  {
    // Another argument.
  }
}

If it don't work, I let DC post his fix.
 
@danno,

Here's the fix for animations (I hope).

C:
/*
* Caskey, Damon V.
* 2023-01-26 - Refactored from inline
* code by danno.
*
* Accept range and animation parameters.
*
* If an ally is within range, set both
* entities to accepted animations.
*/
void dc_team_attack(int range_x, int range_y, int range_z, int ally_position_y_min, int ally_position_y_max, int acting_animation, int ally_animation)
{
    void acting_entity = getlocalvar("self");
    void ally_entity = NULL();
    int ally_direction = openborconstant("DIRECTION_RIGHT");
    float ally_position_y = 0.0;
    int acting_direction = openborconstant("DIRECTION_RIGHT");
    int entity_count = 0;
    int cursor = 0;
    int ally_animation_old = 0;
    int ally_type = openborconstant("TYPE_NONE");
    int distance_x = 0;
    int distance_z = 0;
    char ally_model_name = "";
 
    /*
    * Get entity count and start looping.
    *
    */
    entity_count = openborvariant("count_entities");

    for (cursor = 0; cursor < entity_count; cursor++)
    {
        /*
        * Get entity from index curosr. Make sure
        * it is valid before moving on.
        */

        ally_entity = getentity(cursor);

        if (!ally_entity)
        {
            continue;
        }

        /*
        * The model text checks downstream are
        * slow. Let's optimize a bit by eliminating
        * entity types we don't care about first.
        */

        ally_type = getentityproperty(ally_entity, "type");

        if (!(ally_type & (openborconstant("TYPE_PLAYER") | openborconstant("TYPE_NPC"))))
        {
            continue;
        }

        /*
        * Compare animations. If entity is not
        * in one of the desired animations then
        * we move on.
        */

        ally_animation_old = getentityproperty(ally_entity, "animationID");

        if (ally_animation_old != openborconstant("ANI_FORWARDJUMP") && ally_animation_old != openborconstant("ANI_RUNJUMP"))
        {
            continue;
        }

        /*
        * Check models.
        */

        ally_model_name = getentityproperty(ally_entity, "name");

        if (ally_model_name != "Chris" && ally_model_name != "Hong")
        {
            continue;
        }

        /*
        * Check absolute positions.
        */

        ally_position_y = getentityproperty(ally_entity, "y");

        if (ally_position_y < ally_position_y_min && ally_position_y > ally_position_y_max)
        {
            continue;
        }

        /*
        * Check range.
        */

        distance_x = getRange(acting_entity, ally_entity, "x", 0);
        distance_z = getRange(acting_entity, ally_entity, "z", 0);
    
        if (distance_x > range_x || distance_z > range_z)
        {
            continue;
        }

        /*
        * Now we know we have a valid ally and it
        * can perform the team attack. Get direction
        * values and set up accordingly.
        */

        ally_direction = getentityproperty(ally_entity, "direction");
        acting_direction = getentityproperty(acting_entity, "direction");

        if (ally_direction == openborconstant("DIRECTION_RIGHT"))
        {
            if (acting_direction == openborconstant("DIRECTION_LEFT"))
            {
                performattack(ally_entity, ally_animation);
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_LEFT"));
                performattack(acting_entity, acting_animation);
            }
            else
            {
                performattack(ally_entity, ally_animation);
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_RIGHT"));
                performattack(acting_entity, acting_animation);                           
            }
        }
        else
        {
            if (acting_direction == openborconstant("DIRECTION_LEFT"))
            {
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_LEFT"));
                performattack(ally_entity, ally_animation);
                performattack(acting_entity, acting_animation);
            }
            else
            {           
                performattack(ally_entity, ally_animation);
                changeentityproperty(acting_entity, "direction", openborconstant("DIRECTION_RIGHT"));
                performattack(acting_entity, acting_animation);
            }
        }
    }
}

The if clause was using wrong variable. It was comparing ally entity pointer to the animation constants when it was supposed to compare ally animation.

DC
 
works perfect.


If I remember correctly the original Night Slashers had co-op throws too so with this and a bit of binding I think it'll be good if the fella's could help Hong Hua out with some throws. I'll get on that towards the end, so I'm about 80% complete with everything now, all that's left is cleaning up the stages and redoing the alternate hospital route. I'll merge this thread with oldyz variants when I'm ready to release this version.
 
Last edited:
I arrived back in England but forgot to bring a copy of what I've been working on with me so the most up to date version is on my computer back in Italy, I'm relying on my Italian mother in law to email me a copy 🤞


Any of you come across entity clipping before? I'm not sure how to go about fixing it.
 
I arrived back in England but forgot to bring a copy of what I've been working on with me so the most up to date version is on my computer back in Italy, I'm relying on my Italian mother in law to email me a copy 🤞


Any of you come across entity clipping before? I'm not sure how to go about fixing it.

You just touched on something that's a field of study in game development all by itself. It's right up there with collision optimization theory.

This happens when two objects overlap on the same drawing layer. It's very rare in gameplay because it requires two entities to end up in identical Z positions with the same layer settings, but it can happen. If it does, there's nothing left to determine drawing order other than update timing, which is affected by so many other factors it may as well be random. Since the last one drawn always "wins", you get what appears to be clipping on screen.

This is a problem that plagues every graphic engine in existence. There's no solution other than "don't ever put two things on the same drawing layer". Of course that's easier said than done when there's runtime entropy on the Z axis. There's no single solve, so it will depend on what caused it in the first place. I'm guessing it's leftover bodies, in which case we could look at some kind of shunting or layering routine.

DC
 
I was thinking on death if another entity is detected within range push said entity up or down 1 z pos
 
Just brainstoriming on the above, but I'm thinking of something like an entity enumeration that checks if entities are dead and on an identical Z axis. If they are, it moves one of them a tiny fraction, maybe -0.1 or something. The player wouldn't be able to tell, but it would ensure they're not on the same drawing layer.

Edit: Ninja'd. Although I wouldn't use range, because that's a lot of very expensive calculation.

DC
 
As far as I can see, they aren't clipping - they are blinking (switching the Z position)
Looks to be same issue I have here Flickering entites

In development terms, it's still called clipping. You are correct though, the underlying cause is the same. Two objects share screen position and drawing layer. I haven't had a chance to look at yours yet. All my OpenBOR time has gone to things I can answer fairly quickly and getting the next release prepared, but the solution would probably be similar to @danno's issue.

DC
 
hello,danno, I have played this game before, and I feel that the boss's AI is very weak. I wonder if you have strengthened it. .😶
 
@William999
what version did you play and with what version of the engine?

the 2019 bonus jz version has very good boss AI, but only if you play it with the old openbor version, but i found that if you use any other version after that, the AI would get messed up to the point that the latest openbor would make the bosses make almost no attacks at all...

the wide-screen transition made it even worse until Life of finale tweaked it a bit for his rebalanced edition....
for 21c i feature my own cheap tricks in combination with life of finale's stuff

but when it comes to "DX"
@danno is one of the best programmers here, so i have no doubt that he will be able to tweak the Ai to fit the version of the engine he is going to use
 
@William999
您玩的是哪个版本以及使用哪个版本的引擎?

2019年的奖金jz版本有非常好的boss AI,但前提是你用旧的openbor版本玩它,但我发现如果你之后使用任何其他版本,AI会变得混乱,以至于最新的openbor会让boss几乎不发动任何攻击...

宽屏过渡让情况变得更糟,直到《Life of Finale》对其重新平衡版本进行了一些调整......
对于 21c,我将自己的廉价技巧与 Finale 的生活相结合

但说到“DX”
@danno 是这里最好的程序员之一,所以我毫不怀疑他能够调整 Ai 以适应他将要使用的引擎版本
I don’t remember what version I’m playing, it should be the earliest version, the Android engine is 4161 🙂
The boss is so stupid, I can kill it with my eyes closed😄
 
hello,danno, I have played this game before, and I feel that the boss's AI is very weak. I wonder if you have strengthened it. .😶

You probably won't like this version, I've made it easier, over powered and fun, unfortunately all the things I'm working on are on hold at the moment, I'm going through some personal problems in life and I've lost my drive to do anything.
 
You probably won't like this version, I've made it easier, over powered and fun, unfortunately all the things I'm working on are on hold at the moment, I'm going through some personal problems in life and I've lost my drive to do anything.
OK, I totally understand you! All unhappy things in real life will pass.
Just do it when you have free time.🙂
 
Back to working on this, I've decided to remove even more to balance out the game better, How the game is played is really important to me so I've had to change even the weapons system so it works together with everything else. Even though most of the mechanics have changed it should feel more intuitive like how the arcade felt.
 
Back
Top Bottom