CODE
//NPC Follower script by Joe123
//Modified for party members by MM
import "std.zh"
import "ffcscript.zh"
//Graphics: Up, Down, Left, Right for each row
//Row 1: Standing
//Row 2: Walking
//Row 3: Floating
//Row 4: Swimming
//Row 5: Jumping (NOT YET IMPLEMENTED)
const int FFCS_PARTYMEMBER = 6; //FFC script slot with party member script
const int M_NORMAL = 0;
const int M_MOVINGTOPOS = 1;
const int M_SOLIDATPOS = 2;
const int I_MEMBER1 = 211; //Item spawning first party member
const int I_MEMBER2 = 212; //Item spawning second party member
const int I_MEMBER3 = 213; //Item spawning third party member
const int CMB_MEMBER1 = 1708; //First of 20 combos for party member #1 (standing, facing up)
const int CMB_MEMBER2 = 1688; //Ditto #2
const int CMB_MEMBER3 = 1668; //Ditto #3
const int CSET_MEMBER1 = 6; //CSets of the party members
const int CSET_MEMBER2 = 6;
const int CSET_MEMBER3 = 6;
const int FFC_MEMBER1 = 30; //FFC taken by member #1
const int FFC_MEMBER2 = 31; //FFC taken by member #2
const int FFC_MEMBER3 = 32; //FFC taken by member #3
global script active{
void run(){
while(true){
spawnPartyMembers();
Waitframe();
}
}
}
ffc script FollowLink{
void run(int num){
int orig = this->Data;
int lastDir;
int MovementState;
int CurrentScreen;
int idle;
num++;
while(true){
int x = Link->X + InFrontX(Link->Dir, (num*16));
int y = Link->Y + InFrontY(Link->Dir, (num*16));
//int x = Link->X; int y = Link->Y;
//if(Link->Dir == DIR_UP||Link->Dir == DIR_DOWN) y -= Link->Dir*(16+16*num)-16;
//else x -= (Link->Dir-2)*(16+16*num)-16;
if(CurrentScreen != Game->GetCurScreen()) MovementState = NormalPlacement(this,x,y);
if(MovementState == M_NORMAL){
if(lastDir != Link->Dir) MovementState = MoveToPosition(this,x,y);
else MovementState = NormalPlacement(this,x,y);
}else if(MovementState == M_MOVINGTOPOS) MovementState = WhileMoving(this,x,y,idle);
else if(MovementState == M_SOLIDATPOS) MovementState = CheckPos(this,x,y);
SetGraphics(this,orig);
CurrentScreen = Game->GetCurScreen();
idle = (idle+1)%6;
lastDir = Link->Dir;
Waitframe();
}
}
int NormalPlacement(ffc this,int x,int y){
if(Solid(this,x,y)) return M_SOLIDATPOS;
this->X = x; this->Y = y;
return M_NORMAL;
}
int MoveToPosition(ffc this,int x,int y){
if(Solid(this,x,y)) return M_SOLIDATPOS;
int speed = Distance(x,y,this->X,this->Y)/8;
if(speed < 0.5) return M_NORMAL;
else if(speed < 1.2) speed *= 2;
FFCToPoint(this,x,y,speed);
return M_MOVINGTOPOS;
}
int WhileMoving(ffc this,int x,int y,int idle){
if(Abs(this->X-x) < 3 && Abs(this->Y-y) < 3){
this->Vx = 0; this->Vy = 0;
return M_NORMAL;
}
if(idle == 0) return MoveToPosition(this,x,y);
return M_MOVINGTOPOS;
}
int CheckPos(ffc this,int x,int y){
if(Solid(this,x,y)) return M_SOLIDATPOS;
return MoveToPosition(this,x,y);
}
bool Solid(ffc this,int x,int y){
if( Screen->isSolid(x+8,y+8) && !IsWater(ComboAt(x+8, y+8)) ){ //Modification: Not consered solid if water
this->Vx = 0; this->Vy = 0;
return true;
}
}
void SetGraphics(ffc this,int orig){
int moving;
int combo = ComboAt(CenterX(this), CenterY(this));
//Find the appropriate sprite row
if ( this->Misc[0] > 0 ) //In air
moving = 16;
else if ( IsWater(combo) && isMoving(this) ) //Swimming
moving = 12;
else if ( IsWater(combo) ) //Floating
moving = 8;
else if(isMoving(this)) //Walking
moving = 4;
this->Data = orig+moving+Link->Dir;
}
int FFCToPoint(ffc f,int x,int y,int speed){
if(speed == 0) return -1;
int dx = x-f->X; int dy = y-f->Y;
int dis = Abs(dx) + Abs(dy);
int d = dis/speed;
f->Vx = dx/d; f->Vy = dy/d;
return d;
}
bool isMoving(ffc this){
return (Link->InputUp || Link->InputDown || Link->InputLeft || Link->InputRight
|| this->Vx != 0 || this->Vy != 0);
}
}
//D0: Number of party members needed (not counting Link)
ffc script partySecret{
void run ( int count ){
if ( Screen->State[ST_SECRET] )
return;
while ( CountFFCsRunning(FFCS_PARTYMEMBER) < count )
Waitframe();
Screen->State[ST_SECRET] = true;
Screen->TriggerSecrets();
}
}
//Initializes a party member immediately, without waiting for a game restart
item script partyMember{
void run ( int num ){
if ( num == 1 ){
ffc member = Screen->LoadFFC(FFC_MEMBER1);
member->X = Link->X;
member->Y = Link->Y;
member->Data = CMB_MEMBER1;
member->CSet = CSET_MEMBER1;
member->Script = FFCS_PARTYMEMBER;
member->Flags[FFCF_CARRYOVER] = true;
member->InitD[0] = 1;
}
else if ( num == 2 ){
ffc member = Screen->LoadFFC(FFC_MEMBER2);
member->X = Link->X;
member->Y = Link->Y;
member->Data = CMB_MEMBER2;
member->CSet = CSET_MEMBER2;
member->Script = FFCS_PARTYMEMBER;
member->Flags[FFCF_CARRYOVER] = true;
member->InitD[0] = 2;
}
else if ( num == 3 ){
ffc member = Screen->LoadFFC(FFC_MEMBER3);
member->X = Link->X;
member->Y = Link->Y;
member->Data = CMB_MEMBER3;
member->CSet = CSET_MEMBER3;
member->Script = FFCS_PARTYMEMBER;
member->Flags[FFCF_CARRYOVER] = true;
member->InitD[0] = 3;
}
}
}