In Progress Night Stalkers by danno

The project is currently under development.
+1 to the anti-purest thing. To me it's just an excuse to be lazy about sprites.

"I am the weapon." What a crock of s***.

At risk of getting way pedantic, I used to teach self defense. Unless you're in some McDojo that watched too many anime movies, every last martial art on this planet acknowledges unarmed combat is a last resort, not the goal. Anything you can get your hands on is an advantage. Broomsticks, a rock, or even a bit of dirt. There are exactly two rules concerning real altercations:
  1. Don't fight.
  2. Don't fight fair.
Your body is indeed a weapon. It has binocular vision, abstract thought, and two dexterous hands, among other things. You are designed to use the environment and everything in it, and if you don't then you're a (probably dead) moron, not a martial artist.

Never been in a Zombie apocalypse though... so what do I know? o_O

DC
 
@DCurrent - 😁 yes - sprite laziness is something to be avoided, even if a character won't use a weapon at least something can be featured.

in the case of characters like Ortega tho, weapons are a sign of weakness, i don't know about the Roid female in @danno 's module...
but for Ortega creative animations of weapon disposal or one-time use and barrel dismisal are something i had considered..
the barrel being the only thing he might use for creative zombie takedowns.....

for Hong Hua tho, the best i can come up with - without relying on "player sensitive drops" and player specific weapons - is weapon transmutation for fire arms using the "Ofudas"

1671511118026.jpeg
The chainsaw could be turned into a "pochita" type demon, Machine gun could be a dragon, shotgun a fire frog, grenade demon wasps...


traditional weapons like the axe and bats are fine
 
Nekketsu Oyako is a game with player sensitive weapons. Only the bulk type character can grab the bazooka, but I interpret that as the weapon being too big and heavy for the other characters to grab and use it properly.
Ohh and in captain commando only the ninja can grab the shurikens.
 
Player sensitive weapons I understand, In this version of Night Slashers when Hong Hua uses a shot gun she moves back alil coz she's tiny, in Night Stalkers when she uses a bazooka she falls down completly and she won't be able to pick cars up or use massive metal spiked clubs like Ana Bolic can.

I guess this is why the overall vibe of a game is important, you literally smash through dead/non human flesh in the most disgusting ways, if Hong Hua never touched anything because she doesn't want to or can't get her hands dirty and just floated around shooting pretty pastel coloured magic I'd understand the no weapons thing tradtionally speaking BUT she stomps enemy's heads right through till it reaches their ass :ROFLMAO: she can punch a whole body into two pieces do you know how gruesome that is? is she really gonna then look at a gun and be like *No this is not the way* it's a horror beat em' up one of the most goriest out there, of course remember that weapons are optional, you don't have to use any of them.

in the case of characters like Ortega tho, weapons are a sign of weakness

c'mon man with this logic why would he fight weak ass zombie's in the first place surely fighting a Dog or even weaker still a Bat would have him questioning his own morality, (can he piledriver Bats too? that would be hilarious) he's not entering a tournament, he's not gonna win any belts suplexing Dogs.

Never been in a Zombie apocalypse though... so what do I know? o_O

My weapon of choice during a zombie apocalypse would be crying. (magic manly tears mind you)
 
Last edited:
  • Like
Reactions: NED
So much hype for both projects...
But particularly for Night Stalkers...

to get a bit away from this NSX... And go for something fresh !! <3
 
she won't be able to pick cars up or use massive metal spiked clubs like Ana Bolic can

See, I would never go the "can't" route with any universal weapon. I'd just make her suck at it. She probably doesn't know how to use such a thing and it's too heavy for her body size anyway, so all she can do is take really clumsy swings. Still hits hard, but with tons and tons of recoil. Or if you want to say she absolutely isn't strong enough to swing it, then have her treat it like a large object - she carries it around the way the others carry barrels and then throws it.

For actual barrels and similar things, if you want to say she can't lift those, then she could at least give them a shove like Double Dragon.

Picking up super sized objects like cars is a unique ability, so it's OK not everyone can do it, but common objects should be fair game for everyone to use on at least some level IMO.

Just my two cents.
DC
 
@danno ,
i am basing Ortega's personality on the little info that Lifeof Finale provides, it seems that on his version of things ortega takes the zombie apocalypse as a new challenge of sorts to "test his might" and his dialogues suggest that he thinks of himself as the unstoppable champion (in reality its the hardest character to beat 21C with)
my twisted sense of humor finds this very fitting.

it took me 12 file loads, 6 hours and 37 minutes to beat the game using Ortega, (not counting the base levels) with 21C, i am sure a skilled speedster might get that down to an hour and a half...

i did not test piledriving a bat, LOL - the only improvement i would make is to make a custom animation, perhaps even the most complex and spectacular at random times, that showcases absolute bat anihilation and unmatched fury.
 
Just a small update, I've added another weapon, the Barrel which means I only have 3 more weapons to do for Hong Hua which is the rifle gun, axe and chainsaw and then she'll be completely finished also I decided to bring back the classic arcade grab style as I feel it speeds up the action and grabbing feels more confirmed now.


EDIT: welp just realised the vomit hitflash at 1:55 needs antigravity
 
Last edited:
Just a small update, I've added another weapon, the Barrel which means I only have 3 more weapons to do for Hong Hua which is the rifle gun, axe and chainsaw and then she'll be completely finished also I decided to bring back the classic arcade grab style as I feel it speeds up the action and grabbing feels more confirmed now.


EDIT: welp just realised the vomit hitflash at 1:55 needs antigravity
Great!! Even "small" progress is good!
I like it! Very polished.
 
Just a small update, I've added another weapon, the Barrel which means I only have 3 more weapons to do for Hong Hua which is the rifle gun, axe and chainsaw and then she'll be completely finished also I decided to bring back the classic arcade grab style as I feel it speeds up the action and grabbing feels more confirmed now.


EDIT: welp just realised the vomit hitflash at 1:55 needs antigravity
Looks great overall. Just one thing... her back throw is the old towel sling. That's especially odd since she has an arsenal of nice looking slams.

Elsewise it's awesome. Keep it up @danno.

DC
 
It not the speed, it's that she's performing a shoulder throw animation, but they're just slung backward, so the reaction is mismatched.

She either needs to use a different animation or they need to get flipped over. It can still be quick.

DC
 
I really can't wait for this one
Neither can I 🤣

I've been working on cpu partners and interactive moves between players


as you can see at 0:35 into the video as I'm about to do a jumping slam as i'm techinally jumping the interaction move kicks in and the slam doesn't complete hence unbinding player to enemy isn't finished that's not really an issue for now my main issue is wanting to clean up this inline script of the player interaction and turn it into a @cmd I honest don't have the brain power for it at the mo so was wondering if I could get some help cleaning it up or improving it as a cmd

C:
@script
  void self = getlocalvar("self");
  int iMax = openborvariant("count_entities");
  int Dir = getentityproperty(self, "direction");
  int i;

  for(i=0; i<iMax; i++){
    void ally = getentity(i);
    char AName = getentityproperty(ally, "name");
    void AAni = getentityproperty(ally, "animationID");
    int ADir = getentityproperty(ally, "direction");

    if(AName=="Chris" || "Hong" && ADir==0 && AAni==openborconstant("ANI_FORWARDJUMP") || AAni==openborconstant("ANI_RUNJUMP")){
      int Disx = getRange(self, ally, "x", 0);
      int Disz = getRange(self, ally, "z", 0);
      int Ay = getentityproperty(ally, "y");
      
      if(Dir==1 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70){
        performattack(ally, openborconstant("ANI_FOLLOW20"));
        changeentityproperty(self, "direction", 1);
        performattack(self, openborconstant("ANI_FOLLOW6"));
        } else {
        if(Dir==0 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70){
        performattack(ally, openborconstant("ANI_FOLLOW20"));
        changeentityproperty(self, "direction", 1);       
        performattack(self, openborconstant("ANI_FOLLOW6"));
        break;
         }
        }
       }
      if(AName=="Chris" || "Hong" && ADir==1 && AAni==openborconstant("ANI_FORWARDJUMP") || AAni==openborconstant("ANI_RUNJUMP")){
      int Disx = getRange(self, ally, "x", 0);
      int Disz = getRange(self, ally, "z", 0);
      int Ay = getentityproperty(ally, "y");
      
      if(Dir==0 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70){
        changeentityproperty(self, "direction", 0);
        performattack(ally, openborconstant("ANI_FOLLOW20"));
        performattack(self, openborconstant("ANI_FOLLOW6"));
        } else {
        if(Dir==1 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70){
        performattack(ally, openborconstant("ANI_FOLLOW20"));
        changeentityproperty(self, "direction", 0);       
        performattack(self, openborconstant("ANI_FOLLOW6"));
        break;
            }
           }
          }
         }
@end_script
 
I think if you are going to make an animation script in its file instead of the inline code, you may need to call a local entity's name for certain allies. Not sure how this is gonna work, but this is my theory for an animation script file.

C:
void selfToAlly()
{
  void self = getlocalvar("self");
  int iMax = openborvariant("count_entities");
  int Dir = getentityproperty(self, "direction");
  int i;
  char Name;

  for(i=0; i<iMax; i++)
  {
    void ally = getentity(i);
    char AName = getentityproperty(ally, "name");
    void AAni = getentityproperty(ally, "animationID");
    int ADir = getentityproperty(ally, "direction");
    Name = getentityproperty(self, "name");

    if(Name == "Jake")
    {
      if(AName=="Chris" || AName == "Hong" && ADir==0 && AAni==openborconstant("ANI_FORWARDJUMP") || AAni==openborconstant("ANI_RUNJUMP"))
      {
        int Disx = getRange(self, ally, "x", 0);
        int Disz = getRange(self, ally, "z", 0);
        int Ay = getentityproperty(ally, "y");

        if(Dir==1 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70)
        {
          performattack(ally, openborconstant("ANI_FOLLOW20"));
          changeentityproperty(self, "direction", 1);
          performattack(self, openborconstant("ANI_FOLLOW6"));
        } else {
          if(Dir==0 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70){
            performattack(ally, openborconstant("ANI_FOLLOW20"));
            changeentityproperty(self, "direction", 1);       
            performattack(self, openborconstant("ANI_FOLLOW6"));
            break;
          }
        }

      } // End of ally facing left

      if(AName=="Chris" || AName =="Hong" && ADir==1 && AAni==openborconstant("ANI_FORWARDJUMP") || AAni==openborconstant("ANI_RUNJUMP"))
      {
        int Disx = getRange(self, ally, "x", 0);
        int Disz = getRange(self, ally, "z", 0);
        int Ay = getentityproperty(ally, "y");

        if(Dir==0 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70)
        {
          changeentityproperty(self, "direction", 0);
          performattack(ally, openborconstant("ANI_FOLLOW20"));
          performattack(self, openborconstant("ANI_FOLLOW6"));
        } else {
          if(Dir==1 && Disx <= 70 && Disz <= 10 && Ay > 20 && Ay < 70)
          {
            performattack(ally, openborconstant("ANI_FOLLOW20"));
            changeentityproperty(self, "direction", 0);       
            performattack(self, openborconstant("ANI_FOLLOW6"));
            break;
          }
        }

      } // End of ally facing right

    } // End of main Jake

  } // End of for loop statement

} // End of main animation code for calling allies
 
Neither can I 🤣

I've been working on cpu partners and interactive moves between players


as you can see at 0:35 into the video as I'm about to do a jumping slam as i'm techinally jumping the interaction move kicks in and the slam doesn't complete hence unbinding player to enemy isn't finished that's not really an issue for now my main issue is wanting to clean up this inline script of the player interaction and turn it into a @cmd I honest don't have the brain power for it at the mo so was wondering if I could get some help cleaning it up or improving it as a cmd

@danno,

Here is an example function. I wrote it freehand, so there might be typos, but I figure you can work out the skeleton and fix any issues. I did notice some ambiguity in the way you handled direction, so you might have to tweak that a bit as well. It's basically your logic in reverse. I try to eliminate entities in enumeration loops from the fastest checks possible to keep CPU load minimized.

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 = openboconstant("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, "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);
            }
        }
    }
}

The call would look something like this. The second parameter (Y range) does nothing because your code didn't check that, but I put the parameter in just in case you decide to add Y range later:

C:
frame data/chars/dude/cool_sprite_0.png

@cmd dc_team_attack 70 0 10 20 70 openborconstant("ANI_FOLLOW6") openborconstant("ANI_FOLLOW20")
frame data/chars/dude/cool_sprite_1.png
frame data/chars/dude/cool_sprite_2.png

HTH,
DC
 
@DCurrent Thanks for the base, it's really appriciated, the fact that you typed all that out freehand is impressive. for some reason ally animation state runjump forward jump is completely ignored and range is the only trigger but i'll sort it.


@maxman thanks for your input too as it's given me other idea's for player interactions.
 
for some reason ally animation state runjump forward jump is completely ignored and range is the only trigger but i'll sort it.

Here's the problem:

C:
if (ally_entity != openborconstant("ANI_FORWARDJUMP") && ally_entity != openborconstant("ANI_RUNJUMP")) /* * Check models. */

I forgot to add the continue clause to the if. It's just an empty if that does nothing... derp. 🤪

I'm updating my previous post to fix it. Copy again and see if it works better.

DC
 
Last edited:
see if it works better.
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
 
Back
Top Bottom