import "std.zh"
import "ffcscript.zh"
const int LAYER_NPC = 2; //The layer NPCs use for solid combos
const int CMB_NPC_HIDDEN = 41; //Non-solid combo used for hidden NPCs
const int CMB_NPC_SOLID = 42; //Solid combo placed under visible NPCs
const int LAYER_NPC_CANTALK = 6; //The layer used for the speech bubble
const int CMB_NPC_CANTALK = 44; //The combo used for the speech bubble
const int CS_NPC_CANTALK = 8; //The CSet used for the speech bubble
const int NPCBT_NONE = 0; //Regular NPCs
const int NPCBT_FACELINK = 1; //NPCs that turn to face Link
const int NPCBT_GUARDH = 2; //NPCs that move along a horizontal path
const int NPCBT_GUARDV = 3; //NPCs that move along a vertical path
ffc script NPCScript{
void run(int String, int ItemCheck, int Type, int Arg1, int Arg2, int NoSolid, int Script, int ItemToGive){
//Stores the NPC's combo, hides it
int Combo = this->Data;
this->Data = CMB_NPC_HIDDEN;
//Waits until the NPC should appear and shows it
if(ItemCheck<0){
while(!Link->Item[Abs(ItemCheck)]){
Waitframe();
}
this->Data = Combo;
if(Type==NPCBT_FACELINK){
this->Data = Combo + Arg1;
}
}
else if(ItemCheck>0){
if(!Link->Item[Abs(ItemCheck)]){
this->Data = Combo;
if(Type==NPCBT_FACELINK){
this->Data = Combo + Arg1;
}
}
}
else if(ItemCheck==0){
this->Data = Combo;
if(Type==NPCBT_FACELINK){
this->Data = Combo + Arg1;
}
}
//Saves the width and height of the FFC for collision checks
int Width = 16;
int Height = 16;
if(this->EffectWidth!=16)
Width = this->EffectWidth;
else if(this->TileWidth>1)
Width = this->TileWidth*16;
if(this->EffectHeight!=16)
Height = this->EffectHeight;
else if(this->TileHeight>1)
Height = this->TileHeight*16;
//Wait until the screen is done scrolling to avoid a weird ZC crashing bug
Waitframe();
while(Link->Action==LA_SCROLLING){
Waitframe();
}
//Sets the space below the NPC or the space a guard NPC occupies to be solid
if(LAYER_NPC>-1&&NoSolid==0){
if(Type==NPCBT_GUARDH){
for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
}
}
}
else if(Type==NPCBT_GUARDV){
for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
}
}
}
else{
for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
}
}
}
}
while(true){
//Removes NPCs if Link has the required item
if(ItemCheck>0){
if(Link->Item[ItemCheck]){
this->Data = CMB_NPC_HIDDEN;
if(LAYER_NPC>-1&&NoSolid==0){
if(Type==NPCBT_GUARDH){
for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
}
}
}
else if(Type==NPCBT_GUARDV){
for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
}
}
}
else{
for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
}
}
}
}
Quit();
}
}
//Handles animation for turning NPCs
if(Type==NPCBT_FACELINK&&(Link->X>0&&Link->X<240&&Link->Y>0&&Link->Y<160)){
if(Distance(CenterLinkX(), CenterLinkY(), CenterX(this), CenterY(this))<Arg2)
this->Data = Combo + AngleDir4(Angle(CenterX(this), CenterY(this), CenterLinkX(), CenterLinkY()));
else
this->Data = Combo + Arg1;
}
//Handles movement for guard NPCs
else if(Type==NPCBT_GUARDH){
if(Link->X>16*Arg1-32&&Link->X<16*Arg2+32&&Link->Y>this->Y-32&&Link->Y<this->Y+32){
this->X = Clamp(this->X+(-this->X + Link->X)/4, 16*Arg1, 16*Arg2);
}
}
else if(Type==NPCBT_GUARDV){
if(Link->X>this->X-32&&Link->X<this->X+32&&Link->Y>16*Arg1-32&&Link->Y<16*Arg2+32){
this->Y = Clamp(this->Y+(-this->Y + Link->Y)/4, 16*Arg1, 16*Arg2);
}
}
//Facing Up
if(Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
if(CMB_NPC_CANTALK>0)
Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
if(Link->PressA){
Link->InputA = false;
Link->PressA = false;
Screen->Message(String);
Link->Item[ItemToGive] = true;
if(Script>0){
RunFFCScript(Script, 0);
}
}
}
//Facing Down
else if(Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
if(CMB_NPC_CANTALK>0)
Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
if(Link->PressA){
Link->InputA = false;
Link->PressA = false;
Screen->Message(String);
if(Script>0){
RunFFCScript(Script, 0);
}
}
}
//Facing Left
else if(Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
if(CMB_NPC_CANTALK>0)
Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
if(Link->PressA){
Link->InputA = false;
Link->PressA = false;
Screen->Message(String);
if(Script>0){
RunFFCScript(Script, 0);
}
}
}
//Facing Right
else if(Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
if(CMB_NPC_CANTALK>0)
Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
if(Link->PressA){
Link->InputA = false;
Link->PressA = false;
Screen->Message(String);
if(Script>0){
RunFFCScript(Script, 0);
}
}
}
Waitframe();
}
}
}
ffc script sign {
void run(int m, int ItemToGive) {
while(Link->X < this->X - 8 || Link->X > this->X + 24 || Link->Y < this->Y || Link->Y > this->Y + 24 || Link->Dir != DIR_UP || !Link->InputA) {
Waitframe();
}
Link->InputA = false;
Screen->Message(m);
Link->Item[ItemToGive] = true;
while(Link->X >= this->X - 8 && Link->X <= this->X + 24 && Link->Y >= this->Y && Link->Y <= this->Y + 24 && Link->Dir == DIR_UP) {
Waitframe();
}
Screen->Message(0);
}
}