Jump to content

Photo

[2.55 Classic, LTTP and GB.zh) Chomp/Pincer Scripted Enemy Class


  • Please log in to reply
2 replies to this topic

#1 P-Tux7

P-Tux7

    💛

  • Members

Posted 19 September 2019 - 02:55 PM

LADX_Pincer_Sprite.png?version=f3e5b83d0

ALttP_Chain_Chomps.png?version=58558b5ea

 

This NPC script would be versatile due to the amount of Enemy Editor options for weaknesses, but also my ideas for whether one can harm the head, segments, or core, or combining the three booleans. It also has two movement styles for more versatility.

 

Graphics

8-dir (Movement Direction) 4-frame head

4-frame chain/segment

8-dir (Faces Link) 4-frame Core

8-dir (Faces Link) 4-frame Peeking Eyes (Pincer only)

 

Options and Details:

 

1. Movement Style (Pincer or Chain Chomp) (Boolean) - This determines if it rests on its combo and then lunges out like a Pincer, or if it casually hops around like a Chain Chomp before lunging. Pincers are invincible until they lunge and are exposed, but Chomps are always vulnerable. Pincers also have the "eye blink" animation before lunging, while Chomps briefly halt before lunging.

2. How many segments (Integer) How many segments, minus the head, there are. For example, Chain Chomps have 5 segments and Pincers have three. This also determines how far the Pincer or Chomp enemy can reach off of its center, and for Chomps how far away from its post it can bounce.

3. 8-Way or 360 (Boolean) - Chooses whether or not the enemy's movement is constrained to 8 directions, or if it can lunge at you the full 360. Note that Chomps, when hopping, will use 8-way movement either way - the 360 will only affect their lunge. The head also always uses 8-way animation.

4. Head is Vulnerable (Boolean) - 0 for Chomp, 1 for Pincer

5. Segments are Vulnerable (Boolean) - Enable this to have hitting the segments hurt the monster, a la Z1 Moldorm.

6. Core Is Vulnerable (Boolean) - If 1, this will cause attacks to the core to damage the monster. For instance, if you set the Chain Chomp on top of a hammer combo, pounding the post will both change the standard combo and instantly kill it. This allows for both Chain Chomps being defeated by hammering their post (a common Mario occurence), or reskin the Pincer/Chomp to a Boss Moldorm with invincible head and segments but a vulnerable tail. Note that the core is ALWAYS invulnerable while the head is in contact with it, to prevent one from hitting the core while the Pincer is "inside its hole" or displaying the "Peeking Eyes" animation.

 

Note that once non-harmful NPCs are implemented within ZC, this will also serve as a Bow Wow friendly NPC (how he acts after he is tied to the post and you lose his companionship).


  • Bagu likes this

#2 GrandLovania

GrandLovania

    Newbie

  • Members
  • Location:France

Posted 02 January 2020 - 05:00 AM

I know zephino ad once do a pincer and I have already see chomp on IOR but sadly none of them are public



#3 GrandLovania

GrandLovania

    Newbie

  • Members
  • Location:France

Posted 02 January 2020 - 05:35 AM

ah sorry I have at least found pincer :)

 

Hope it will be usefull

// Hole worm LA style - uses ghost.zh with AutoGhost
// Notes:
// - modify the hole/lava script in order to avoid enemies with  Misc[4] > 0  to fall
// - create an enemy with "other" type, set as tile the first of the set, in the order seen in the image file

// enemy attributes (can be left to 0 to set the default values - see below)
const int HOLE_ATTR_RADIUS = 1;
const int HOLE_ATTR_LENGHT = 2;
const int HOLE_ATTR_WAITTIME = 3;
// const int CT_HOLELAVA = 5;  // add this if you are not defining this variable in the hole/lava script

bool loc_is_busy[176];


const int NPCM_NOPUSH = 4; 
// if >0, the enemy cannot be pushed (by weapons and shield), and cannot fall into pits

bool isHole(int ct){
 return ct==CT_HOLELAVA; 
//I'm going to be arrogant and assume your using my Holelava script.
}

ffc script HoleWorm{
void run(int enemyID){
  npc enemy;
  float angle;
  int dir;
  float distance;
  int counter;
  int xstep;
  int ystep;
  int x0;
  int y0;
  int radius;
  int lenght;
  float speed;
  int waittime;
 
  // Initialize
  enemy=Ghost_InitAutoGhost(this, enemyID, GHF_NORMAL);
  Ghost_SpawnAnimationPuff(this, enemy);
  speed=enemy->Step/100;
  radius=enemy->Attributes[HOLE_ATTR_RADIUS];
  lenght=enemy->Attributes[HOLE_ATTR_LENGHT];
  waittime=enemy->Attributes[HOLE_ATTR_WAITTIME];
  // default inputs
  if(enemyID == 0) enemyID = 1;
  if(radius == 0) radius = 3*16;
  if(lenght == 0) lenght = 3*16;
  if(speed == 0) speed = 2;
  if(waittime == 0) waittime = 20;
  int loc = ComboAt(enemy->X+8,enemy->Y+8);
  int i = 0;
  while(!isHole(Screen->ComboT[loc]) || loc_is_busy[loc]){
   loc ++;
   if(i>=176) break;
   i ++;
   if(loc>=176) loc = 0;
  }
  if(i>=176){
   enemy->X = 200;
   Quit();
  }
  loc_is_busy[loc] = true;
  enemy->X = ComboX(loc);
  enemy->Y = ComboY(loc);
  Ghost_X = ComboX(loc);
  Ghost_Y = ComboY(loc);
  this->Data = INV_COMBO_ID;
  x0 = GridX(enemy->X);
  y0 = GridX(enemy->Y);
 
  int original_tile = enemy->OriginalTile;
  enemy->Misc[4] = 1;
  // main loop
  while(true){
   // initialize enemy and ffc
   enemy->X = x0;
   enemy->Y = y0;
   enemy->OriginalTile = INV_TILE_ID;
   enemy->Tile = INV_TILE_ID;
   enemy->CollDetection = false;
   // wait until Link is near
   counter = 0;
   while(counter < waittime){
    if(Distance(enemy->X,enemy->Y,Link->X,Link->Y)<radius){
     counter ++;
    }
    else counter = 0;
    Waitframe();
    loc_is_busy[loc] = false;
   }
   // start to show up
   enemy->OriginalTile = original_tile - 2;
   enemy->Tile = original_tile -2;
   Waitframes(20);
   enemy->Tile = INV_TILE_ID;
   Waitframes(20);
   enemy->CollDetection = true;
   angle = Angle(enemy->X,enemy->Y,Link->X,Link->Y);
   dir = AngleDir8(angle);
   enemy->OriginalTile = original_tile + dir;
   enemy->Tile = original_tile + dir;
   enemy->Dir = dir;
   Waitframes(20);
   // Jump outside
   distance = 0.0;
   if(dir == DIR_UP || dir == DIR_LEFTUP || dir == DIR_RIGHTUP) ystep = -speed;
   else if(dir == DIR_DOWN || dir == DIR_LEFTDOWN || dir == DIR_RIGHTDOWN) ystep = speed;
   else ystep = 0;
   if(dir == DIR_LEFT || dir == DIR_LEFTDOWN || dir == DIR_LEFTUP) xstep = -speed;
   else if(dir == DIR_RIGHT || dir == DIR_RIGHTDOWN || dir == DIR_RIGHTUP) xstep = speed;
   else xstep = 0;
   while(distance < lenght){
    enemy->X += xstep;
    enemy->Y += ystep;
    distance = Distance(enemy->X,enemy->Y,x0,y0);
    Screen->FastTile(0, (enemy->X+1.5*x0)/2.5, (enemy->Y+1.5*y0)/2.5, original_tile-1 , enemy->CSet, 128);
    Screen->FastTile(0, (2*enemy->X+x0)/3, (2*enemy->Y+y0)/3, original_tile-1 , enemy->CSet, 128);
    Waitframe();
    if(!enemy->isValid()) break;
   }
   for(int i=0;i<40;i++){
    Screen->FastTile(0, (enemy->X+1.5*x0)/2.5, (enemy->Y+1.5*y0)/2.5, original_tile-1 , enemy->CSet, 128);
    Screen->FastTile(0, (2*enemy->X+x0)/3, (2*enemy->Y+y0)/3, original_tile-1 , enemy->CSet, 128);
    Waitframe();
    if(!enemy->isValid()) break;
   }
   while(distance > 8){
    enemy->X -= xstep;
    enemy->Y -= ystep;
    distance = Distance(enemy->X,enemy->Y,x0,y0);
    Screen->FastTile(0, (enemy->X+2*x0)/3, (enemy->Y+2*y0)/3, original_tile-1 , enemy->CSet, 128);
    Screen->FastTile(0, (2*enemy->X+x0)/3, (2*enemy->Y+y0)/3, original_tile-1 , enemy->CSet, 128);
    Waitframe();
    if(!enemy->isValid()) break;
   }
   if(!enemy->isValid()) break;
  // end of main loop
  }
  Waitframe();
  Quit();
}
}

Edited by GrandLovania, 02 January 2020 - 05:36 AM.

  • SparksTheUnicorn likes this


1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users