CODE
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
const int bombchuflag = 98; //Flag the bombchu can pass through (even if solid)
//Sprite flips
const int FLIP_NO = 0; //No flip
const int FLIP_H = 1; //Horizontal flip
const int FLIP_V = 2; //Vertical flip
const int FLIP_B = 3; //Both (180 degree rotation)
bool bombchuattack;
bool isSolid(int x,int y){
if(x<0 || x>255 || y<0 || y>175) return false;
int mask=1111b;
if(x%16<8) mask&=0011b;
else mask&=1100b;
if(y%16<8) mask&=0101b;
else mask&=1010b;
return (!(Screen->ComboS[ComboAt(x,y)]&mask)==0);
}
bool bombchucheck(int x, int y){
if((isSolid(x,y) && Screen->ComboF[ComboAt(x,y)] != bombchuflag && Screen->ComboI
[ComboAt(x,y)] != bombchuflag)
|| (Screen->ComboF[ComboAt(x,y)] == 6 || Screen->ComboI[ComboAt(x,y)] == 6 ||
Screen->ComboF[ComboAt(x,y)] == 11 || Screen->ComboI[ComboAt(x,y)] == 11)) return
true;
}
void noaction(){
Link->InputR = false;
Link->InputL = false;
Link->InputA = false;
Link->InputB = false;
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
global script slot_2{
void run(){
//Bombchu variable setup, outside the while(true) loop
int bombchutile = 21780; // 21780;
int bombchuframes = 2; // 2;
int bombchuaspeed = 5;// 5;
int bombchucset = 8; // 8;
int bombchudmg = 3; // 3;
int bombchuspeed = 100; // 100;
int HP;
int bdir;
int bombchux; int bombchuy;
lweapon explosion;
while(true){
deflectArrows(); //Put this above your Waitframe()
spawnPartyMembers(); //Party member function, inside the while(true) loop
ExtendEnemies();
if(bombchuattack){ //Bombchu script, also inside the while(true) loop
if(Link->X > 15 && Link->X < 241 && Link->Y > 15 && Link->Y < 153){
lweapon bombchu = Screen->CreateLWeapon(31);
bdir = Link->Dir;
bombchu->OriginalTile = bombchutile+(bdir*bombchuframes);
bombchu->Tile = bombchutile+(bdir*bombchuframes);
bombchu->NumFrames = bombchuframes;
bombchu->ASpeed = bombchuaspeed;
bombchu->CSet = bombchucset;
bombchux = 0; bombchuy = 0;
if(bdir>1) bombchux = (((bdir-2)*2)-1)*16;
if(bdir<2) bombchuy = ((bdir*2)-1)*16;
bombchu->X = Link->X+bombchux;
bombchu->Y = Link->Y+bombchuy;
bombchu->Step = bombchuspeed;
Link->Action = LA_ATTACKING;
Game->Counter[6]--;
Waitframe();
while(bombchu->isValid()){
HP = Link->HP;
if(Link->InputUp) bdir = 0;
if(Link->InputDown) bdir = 1;
if(Link->InputLeft) bdir = 2;
if(Link->InputRight) bdir = 3;
if(bdir == 0 && bombchucheck(bombchu->X+8,bombchu->Y+4)
|| (bdir == 1 && bombchucheck(bombchu->X+8,bombchu->Y+12))
|| (bdir == 2 && bombchucheck(bombchu->X+4,bombchu->Y+8))
|| (bdir == 3 && bombchucheck(bombchu->X+12,bombchu->Y+8)))
bombchu->DeadState = 0;
bombchu->Dir = bdir;
bombchu->Tile = bombchutile+(bdir*bombchuframes);
bombchu->OriginalTile = bombchutile+(bdir*bombchuframes);
bombchux = bombchu->X;
bombchuy = bombchu->Y;
noaction();
Waitframe();
if(Link->HP < HP) bombchu->DeadState = 0;
}
explosion = Screen->CreateLWeapon(LW_SBOMB);
explosion->Damage = bombchudmg;
explosion->X = bombchux;
explosion->Y = bombchuy;
}else{
bdir = Link->Dir;
bombchux = 0; bombchuy = 0;
if(bdir>1) bombchux = (((bdir-2)*2)-1)*16;
if(bdir<2) bombchuy = ((bdir*2)-1)*16;
explosion = Screen->CreateLWeapon(LW_SBOMB);
explosion->X = Link->X+bombchux;
explosion->Y = Link->Y+bombchuy;
explosion->Damage = bombchudmg;
}
Link->Action = 0;
bombchuattack = false;
}
Waitframe();
}
}
}
global script slot_3{
void run(){
bombchuattack = false;
}
}
item script bombchu{
void run(){
if(Game->Counter[6] > 0) bombchuattack = true;
}
}
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;
}
}
}
void spawnPartyMembers(){
//Initialize party members
if ( Link->Item[I_MEMBER1] ){
ffc member = Screen->LoadFFC(FFC_MEMBER1);
if ( member->Script != FFCS_PARTYMEMBER ){
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;
}
}
if ( Link->Item[I_MEMBER2] ){
ffc member = Screen->LoadFFC(FFC_MEMBER2);
if ( member->Script != FFCS_PARTYMEMBER ){
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;
}
}
if ( Link->Item[I_MEMBER3] ){
ffc member = Screen->LoadFFC(FFC_MEMBER3);
if ( member->Script != FFCS_PARTYMEMBER ){
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;
}
}
}
//Put these at the bottom of your script file
//==== * Arrow deflect functions * ====
void deflectArrows(){
for ( int i = Screen->NumLWeapons(); i > 0; i-- ){
lweapon sword = Screen->LoadLWeapon(i);
if ( sword->ID != LW_SWORD )
continue;
for ( int j = Screen->NumEWeapons(); j > 0; j-- ){
eweapon arrow = Screen->LoadEWeapon(j);
if ( arrow->ID != EW_ARROW )
continue;
if ( Collision(sword, arrow) ){
lweapon rev = eWeapToLWeap(arrow);
rev->Dir = reverseDir(rev->Dir);
setFlip(rev);
Remove(arrow);
}
}
}
}
lweapon eWeapToLWeap(eweapon a) {
lweapon b = Screen->CreateLWeapon(EWtoLW(a->ID));
b->X = a->X;
b->Y = a->Y;
b->Z = a->Z;
b->Jump = a->Jump;
b->Extend = a->Extend;
b->TileWidth = a->TileWidth;
b->TileHeight = a->TileHeight;
b->HitWidth = a->HitWidth;
b->HitHeight = a->HitHeight;
b->HitZHeight = a->HitZHeight;
b->HitXOffset = a->HitXOffset;
b->HitYOffset = a->HitYOffset;
b->DrawXOffset = a->DrawXOffset;
b->DrawYOffset = a->DrawYOffset;
b->DrawZOffset = a->DrawZOffset;
b->Tile = a->Tile;
b->CSet = a->CSet;
b->DrawStyle = a->DrawStyle;
b->Dir = a->Dir;
b->OriginalTile = a->OriginalTile;
b->OriginalCSet = a->OriginalCSet;
b->FlashCSet = a->FlashCSet;
b->NumFrames = a->NumFrames;
b->Frame = a->Frame;
b->ASpeed = a->ASpeed;
b->Damage = a->Damage;
b->Step = a->Step;
b->Angle = a->Angle;
b->Angular = a->Angular;
b->CollDetection = a->CollDetection;
b->DeadState = a->DeadState;
b->Flash = a->Flash;
b->Flip = a->Flip;
for (int i = 0; i < 16; i++)
b->Misc[i] = a->Misc[i];
return b;
}
int EWtoLW ( int id ){
if ( id == EW_ARROW ) return LW_ARROW;
if ( id == EW_BRANG ) return LW_BRANG;
if ( id == EW_BEAM ) return LW_MAGIC;
if ( id == EW_ROCK ) return LW_ARROW;
if ( id == EW_MAGIC ) return LW_MAGIC;
if ( id == EW_FIREBALL || EW_FIREBALL2 ) return LW_MAGIC;
if ( id == EW_BOMB ) return LW_BOMB;
if ( id == EW_BOMBBLAST ) return LW_BOMBBLAST;
if ( id == EW_SBOMB ) return LW_SBOMB;
if ( id == EW_SBOMBBLAST ) return LW_SBOMBBLAST;
if ( id == EW_FIRETRAIL ) return LW_FIRE;
if ( id == EW_FIRE ) return LW_FIRE;
if ( id == EW_WIND ) return LW_MAGIC;
if ( id == EW_FIRE2 ) return LW_FIRE;
}
//Returns the opposite of a direction
int reverseDir(int dir){
if ( dir == DIR_UP ) return DIR_DOWN;
if ( dir == DIR_DOWN ) return DIR_UP;
if ( dir == DIR_LEFT ) return DIR_RIGHT;
if ( dir == DIR_RIGHT ) return DIR_LEFT;
if ( dir == DIR_LEFTUP ) return DIR_RIGHTDOWN;
if ( dir == DIR_RIGHTUP ) return DIR_LEFTDOWN;
if ( dir == DIR_LEFTDOWN ) return DIR_RIGHTUP;
if ( dir == DIR_RIGHTDOWN ) return DIR_LEFTUP;
return -1;
}
//Sets the correct directional flip for a weapon, assuming it already has the right tile.
void setFlip ( lweapon weap ){
if ( weap->Dir == DIR_DOWN )
weap->Flip = FLIP_V;
else if ( weap->Dir == DIR_LEFT )
weap->Flip = FLIP_H;
else
weap->Flip = FLIP_NO;
}
//====* End deflect arrows functions* ====