The quest file dropped in size by a notable amount, from the reduced ZASM, and the in-game performance is a bit better, too, from using internal function calls; and from overall compactness. The npc script sets an eweapon script onto the daira axe, as a weapon controller.
I was expecting the conversion on this to be a bit more painful, but it worked the first time out of the gate. My only revision thereafter, was to optimise some things from the original script, such as the call to this->LinkInRange; and to force visual Line of Sight, which the original enemy did not have.
///////////////////////////////////////////////////// /// Daira NPC Script for 2.55 /// /// v0.2 /// /// 7th March, 2019 /// /// /// /// Original Daira by: Tamamo, and NightmareJames /// /// This version, by: ZoriaRPG /// ///////////////////////////////////////////////////// npc script DairaNPC { void run() { //Original Tile int OTile = this->OriginalTile; //Movement Variables float counter = -1; int step = this->Step; int rate = this->Rate; int homing = this->Homing; int hunger = this->Hunger; //Weapon Variables eweapon wpn; int damage = this->WeaponDamage; int attackTimer; int attackWait; //Time between swings. bool throw = (this->BFlags[4]); //Behavioural FLag 4 //bool shielded = this->Attributes[0]&4; int wSprite = this->WeaponSprite; //Ghost_GetAttribute(ghost,1,-1); //Behavior while(this->isValid()) { //Attacking if(!attackTimer) //Attacks when Link is in Range, and within Line of Sight { if ( this->LinkInRange(80) ) { bool LoS = false; switch(this->Dir) { case DIR_UP: { if ( Link->Y > this->Y ) break; //Facing Link if ( Abs(Link->X - this->X) <= 16 ) LoS = true; break; } case DIR_DOWN: { if ( Link->Y < this->Y ) break; if ( Abs(Link->X - this->X) <= 16 ) LoS = true; break; } case DIR_LEFT: { if ( Link->X > this->X ) break; if ( Abs(Link->Y - this->Y) <= 16 ) LoS = true; break; } case DIR_RIGHT: { if ( Link->X < this->X ) break; if ( Abs(Link->Y - this->Y) <= 16 ) LoS = true; break; } default: break; } if ( LoS ) { attackWait--; if(attackWait<=0) { attackTimer = 21; attackWait = 60; } } } } if(attackTimer>0) //Attacking? { if(this->OriginalTile == OTile) { wpn=Screen->CreateEWeapon(EW_BEAM); wpn->Dir = Ghost_Dir; wpn->Step= 200; wpn->UseSprite(wSprite); wpn->Damage=damage; wpn->Angular=false; wpn->Script = 1; //daira axe wpn->CSet = this->CSet; } else if(!wpn->isValid()) { this->OriginalTile = OTile; Waitframe(); attackTimer = 0; continue; } this->OriginalTile = OTile + 20*Div(28-attackTimer, 7); wpn->Tile = this->OriginalTile+this->Dir+16; wpn->X = this->X; wpn->Y = this->Y; wpn->DeadState = WDS_ALIVE; if(attackTimer>14) { if((this->Dir == DIR_UP || this->Dir == DIR_DOWN)) wpn->Y -= 16; else wpn->X -= InFrontX(this->Dir, 0); } else if(attackTimer>7) { if(this->Dir == DIR_UP || this->Dir == DIR_DOWN) { if(this->Dir == DIR_UP ) wpn->Y -= 16; } else { wpn->X += InFrontX(this->Dir, 0); } } else { wpn->X += InFrontX(this->Dir,0); wpn->Y += InFrontY(this->Dir,0); } //the weapon hit boxes are small. SetWpnHitOffsets(wpn, Div(28-attackTimer, 7), this->Dir); attackTimer--; } else if(wpn->isValid()) { this->OriginalTile = OTile; if(throw) { wpn=Screen->CreateEWeapon(EW_BEAM); wpn->Dir = Ghost_Dir; wpn->Step= 200; wpn->UseSprite(wSprite); wpn->Damage=damage; wpn->Angular=false; wpn->Script = 1; //daira axe this->OriginalTile = this->OriginalTile + 80 + (this->Dir*4); } } if(this->HP <= 0) { wpn->DeadState = WDS_DEAD; Quit(); } Waitframe(); } } void SetWpnHitOffsets(eweapon wpn, int frame, int dir) { //Set Default Collision Properties wpn->CollDetection = true; wpn->HitXOffset = 0; wpn->HitYOffset = 0; wpn->HitWidth = 16; wpn->HitHeight = 16; //Modify it based off attack frame. switch(frame) { case 1: { if(dir == DIR_UP || dir == DIR_DOWN) { wpn->CollDetection = false; return; } else wpn->HitWidth = 8; if(dir == DIR_RIGHT) wpn->HitXOffset = 8; break; } case 2: { if(dir == DIR_UP || dir==DIR_DOWN) { wpn->HitHeight = 8; return; } else wpn->HitWidth = 8; if(dir == DIR_LEFT) wpn->HitXOffset = 8; break; } case 3: { wpn->HitXOffset = Cond(dir==DIR_LEFT, 8, 0); wpn->HitYOffset = Cond(dir==DIR_UP, 8, 0); wpn->HitWidth = Cond(dir==DIR_LEFT||dir==DIR_RIGHT, 8, 16); wpn->HitHeight = Cond(dir==DIR_UP||dir==DIR_DOWN, 8, 16); break; } default: //Out of range. { wpn->DeadState = WDS_DEAD; return; } } } }
Here also, is the old ghost.zh script, for comparison.