Here's the script file from my questl:
CODE
import "std.zh"
import "string.zh"
import "ghost.zh"
bool NPC_Hastaken[99];
const int WSP_FALLING = 100; //Weapon/Misc. sprite for Link falling down a hole
const int WSP_LAVA = 101; //Weapon/Misc. sprite for Link drowning in lava
const int SFX_FALLING = 61; //SFX for falling down a hole
const int SFX_LAVA = 63; //SFX for drowning in lava
const int CMB_AUTOWARP = 7; //Combo ID of a transparent AutoWarp A combotype
const int CT_HOLELAVA = 143; //Combotype to give hole functionality to (default is Left Statue)
bool Falling;
bool usingLadder;
const int ClimbingFlag = 99;
const int SOUND_COMBO = 142;
const int SOUND_COMBO_SFX = 62;
bool soundCombos[176];
int scPrevScreen = -1;
int scPrevDMap = -1;
bool has_hover = false;
bool on_ladder = false;
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;
int ret = Screen->ComboS[ComboAt(x, y)] & mask;
return (ret!=0);
}
void ladder(int f) {
int lc;
lc = ComboAt(Link->X+8, Link->Y+15); //for speed
if(Screen->ComboF[lc] == f || Screen->ComboI[lc] == f) {
if(!on_ladder) {
on_ladder = true;
has_hover = Link->Item[I_HOVERBOOTS];
Link->Item[I_HOVERBOOTS] = false;
}
Link->Jump = 0;
Link->Z = 0;
Link->Dir = DIR_UP;
if(Link->InputDown) {
Link->InputDown = false;
Link->Action = LA_WALKING;
if(!isSolid(Link->X, Link->Y + 16)) Link->Y += 1;
}
if(Link->InputUp) {
Link->InputUp = false;
Link->Action = LA_WALKING;
if(!isSolid(Link->X, Link->Y - 1)) Link->Y -= 1;
}
if(Link->InputLeft) {
Link->InputLeft = false;
Link->Action = LA_WALKING;
if(!isSolid(Link->X - 1 , Link->Y)) Link->X -= 1;
}
if(Link->InputRight) {
Link->InputRight = false;
Link->Action = LA_WALKING;
if(!isSolid(Link->X + 16, Link->Y)) Link->X += 1;
}
} else {
if(on_ladder) {
Link->Item[I_HOVERBOOTS] = has_hover;
on_ladder = false;
}
}
}
void doSoundCombo()
{
if(Link->Action == LA_SCROLLING)
return;
bool playSound = false;
if(Game->GetCurDMap() != scPrevDMap || Game->GetCurDMapScreen() != scPrevScreen)
{
for(int i=0; i<176; i++)
soundCombos[i] = false;
}
scPrevDMap = Game->GetCurDMap();
scPrevScreen = Game->GetCurDMapScreen();
for(int i=0; i<176; i++)
{
if(Screen->ComboT[i] == SOUND_COMBO && !soundCombos[i])
playSound = true;
soundCombos[i] = Screen->ComboT[i] == SOUND_COMBO;
}
if(playSound)
Game->PlaySound(SOUND_COMBO_SFX);
}
global script soundCombo
{
void run()
{
while(true)
{
//Other Global functions called before Waitdraw(); go here...
//Climbing script functions...
if((Screen->ComboF[ComboAt(Link->X+8, Link->Y+9)] == ClimbingFlag || Screen->ComboI[ComboAt(Link->X+8, Link->Y+9)] == ClimbingFlag) && Link->Z == 0){
Link->InputA = false;
Link->InputB = false;
Link->InputL = false;
usingLadder=true;
}
else if(usingLadder)
usingLadder=false;
Waitdraw();
if(usingLadder)
Link->Dir = 0;
//Other Global Functions called after Waitdraw(); go here...
doSoundCombo();
ladder(98); // Change the number here to use a different flag
Waitframe();
}
}
}
ffc script Signpost{
void run(int m,int input){
int loc = ComboAt(this->X,this->Y);
while(true){
while(!AgainstComboBase(loc) || !SelectPressInput(input)) Waitframe();
SetInput(input,false);
Screen->Message(m);
Waitframe();
}
}
bool AgainstComboBase(int loc){
return Link->Z == 0 && (Link->Dir == DIR_UP && Link->Y == ComboY(loc)+8 && Abs(Link->X-ComboX(loc)) < 8);
}
}
ffc script RealNPC{
void run(int m, int sfx, int defdir, int d, int ffcnumber, int input){
ffc NPC = this;
if(ffcnumber != 0) Screen->LoadFFC(ffcnumber);
NPC->Misc[0] = NPC->Data;
if(d == 0) d = 40;
while(true){
SetGraphic(NPC,defdir,d);
if(CanTalk(NPC,input)){
SetInput(input,false);
if(sfx != 0) Game->PlaySound(sfx);
Screen->Message(m);
}
Waitframe();
}
}
bool CanTalk(ffc NPC,int input){
return (SelectPressInput(input) && Abs(NPC->X-Link->X) < 24 && Abs(NPC->Y-Link->Y) < 24 && Link->Z == 0);
}
void SetGraphic(ffc NPC, int defdir, int d){
int dx = NPC->X-Link->X; int ax = Abs(dx);
int dy = NPC->Y-Link->Y; int ay = Abs(dy);
if(defdir != 0){
if(ax < d && ay < d){
if(ax <= ay){
if(dy >= 0) NPC->Data = NPC->Misc[0]+DIR_UP;
else NPC->Data = NPC->Misc[0]+DIR_DOWN;
}else{
if(dx >= 0) NPC->Data = NPC->Misc[0]+DIR_LEFT;
else NPC->Data = NPC->Misc[0]+DIR_RIGHT;
}
}else NPC->Data = NPC->Misc[0]+(defdir-1);
}
}
}
item script Message{
void run(int m){
Screen->Message(m);
}
}
item script Message2{
void run(int filler, int m){
Screen->Message(m);
}
}
ffc script Shop{
void run(int itm, int price,int input){
while(true){
if(CanBuy(this,input)){
SetInput(input,false);
if(Game->Counter[CR_RUPEES] >= price){
ShopItemThanks(itm);
DeductRupees(price);
}else Screen->Message(S_NORUPEES);
}
Waitframe();
}
}
}
const int CMB_BLANK = 0; //Set this to the ID of a transparent combo
const int CMB_NULL = 0; //Leave this as 0!
ffc script ShopSingleSaleItem{
void run(int itm, int price, int perm, int input){
while(Screen->D[perm] == 0){
if(CanBuy(this,input)){
SetInput(input,false);
if(Game->Counter[CR_RUPEES] >= price){
ShopItemThanks(itm);
this->Data = CMB_BLANK;
DeductRupees(price);
Screen->D[perm]++;
}else Screen->Message(S_NORUPEES);
}
Waitframe();
}
this->Data = CMB_NULL;
}
}
const int S_NORUPEES = 72; //Message saying 'Not enough rupees'
const int S_THANKS = 73; //Message saying 'Thanks for buying'
bool CanBuy(ffc buy,int input){
return (Abs(Link->X-buy->X) < 8 && Abs(Link->Y-(buy->Y+8)) < 8 && SelectPressInput(input) && Link->Dir == DIR_UP);
}
void ShopItemThanks(int itm){
Screen->Message(S_THANKS);
Game->PlaySound(SFX_SCALE);
WaitNoAction();
CreatePickupItem(Link->X,Link->Y,itm);
Game->PlaySound(SFX_PICKUP);
WaitNoAction();
}
void CreatePickupItem(int x, int y, int itm){
item Spawn = Screen->CreateItem(itm);
Spawn->Pickup |= IP_TIMEOUT;
Spawn->HitWidth = 16; Spawn->HitHeight = 16;
Spawn->X = x; Spawn->Y = y;
}
void DeductRupees(int amount){
FreezeScreen();
for(int i=0;i<amount;i++){
Game->PlaySound(SFX_MSG);
Game->Counter[CR_RUPEES]--;
Waitframe();
}
UnFreeze();
}
int FreezeID;
void FreezeScreen(){
FreezeID = Screen->ComboT[0];
Screen->ComboT[0] = CT_SCREENFREEZE;
}
void UnFreeze(){
Screen->ComboT[0] = FreezeID;
}
bool SelectPressInput(int input){
if(input == 0) return Link->PressA;
else if(input == 1) return Link->PressB;
else if(input == 2) return Link->PressL;
else if(input == 3) return Link->PressR;
}
void SetInput(int input, bool state){
if(input == 0) Link->InputA = false;
else if(input == 1) Link->InputB = false;
else if(input == 2) Link->InputL = false;
else if(input == 3) Link->InputR = false;
}
ffc script FFCJumpCliff{
void run(int verticalmovement, int horizontalmovement, int directiontopress) {
int directiontopressmoreleft;
int directiontopressmoreright;
int LinkHmovementdone = 0;
bool ffcsentlinkjumping = false;
if (directiontopress==DIR_DOWN) {
directiontopressmoreleft = DIR_RIGHTDOWN;
directiontopressmoreright = DIR_LEFTDOWN;
}
else {
if (directiontopress==DIR_UP) {
directiontopressmoreleft = DIR_LEFTUP;
directiontopressmoreright = DIR_RIGHTUP;
}
else {
if (directiontopress==DIR_LEFT) {
directiontopressmoreleft = DIR_LEFTDOWN;
directiontopressmoreright = DIR_LEFTUP;
}
else {
if (directiontopress==DIR_RIGHT) {
directiontopressmoreleft = DIR_RIGHTUP;
directiontopressmoreright = DIR_RIGHTDOWN;
}
else {
if (directiontopress==DIR_LEFTDOWN) {
directiontopressmoreleft = DIR_DOWN;
directiontopressmoreright = DIR_LEFT;
}
else {
if (directiontopress==DIR_RIGHTDOWN) {
directiontopressmoreleft = DIR_RIGHT;
directiontopressmoreright = DIR_DOWN;
}
else {
if (directiontopress==DIR_LEFTUP) {
directiontopressmoreleft = DIR_LEFT;
directiontopressmoreright = DIR_UP;
}
else {
if (directiontopress==DIR_RIGHTUP) {
directiontopressmoreleft = DIR_UP;
directiontopressmoreright = DIR_RIGHT;
}
}
}
}
}
}
}
}
while (true){
if (Link->Z==0) {
LinkHmovementdone=0;
ffcsentlinkjumping = false;
}
if ( (ffcsentlinkjumping)&&(LinkHmovementdone<Abs(horizontalmovement)) ) {
if (horizontalmovement<0) {Link->X--;}
if (horizontalmovement>0) {Link->X++;}
LinkHmovementdone++;
}
if ( (LinkCollision(this))
&& ( (Link->Dir==directiontopress)
||(Link->Dir==directiontopressmoreleft)
||(Link->Dir==directiontopressmoreright) ) ) {
if (Link->Z==0){
Game->PlaySound(SFX_JUMP);
}
ffcsentlinkjumping=true;
Link->Y=Link->Y+verticalmovement;
Link->Z=Link->Z+verticalmovement;
}
Waitframe();
}
}
}
ffc script RealNPCtrade{
void run(int m, int sfx, int defdir, int itemid, int item2, int input, int npcid){
ffc NPC = this;
NPC->Misc[0] = NPC->Data;
while(true){
SetGraphic(NPC,defdir,40);
if(CanTalk(NPC,input)){
if(NPC_Hastaken[npcid]){
SetInput(input,false);
if(sfx != 0) Game->PlaySound(sfx);
Screen->Message(m);
}
else if(!NPC_Hastaken[npcid] && Link->Item[itemid]){
NPC_Hastaken[npcid] = true;
if(sfx!=0) Game->PlaySound(sfx);
SetInput(input,false);
Screen->Message(m+1);
Link->Item[itemid] = false;
Link->Item[item2] = true;
}
else if(!NPC_Hastaken[npcid] && !Link->Item[itemid]){
SetInput(input,false);
if(sfx!=0) Game->PlaySound(sfx);
Screen->Message(m+2);
}
}
Waitframe();
}
}
bool CanTalk(ffc NPC,int input){
return (SelectPressInput(input) && Abs(NPC->X-Link->X) < 24 && Abs(NPC->Y-Link->Y) < 24 && Link->Z == 0);
}
void SetGraphic(ffc NPC, int defdir, int d){
int dx = NPC->X-Link->X; int ax = Abs(dx);
int dy = NPC->Y-Link->Y; int ay = Abs(dy);
if(defdir != 0){
if(ax < d && ay < d){
if(ax <= ay){
if(dy >= 0) NPC->Data = NPC->Misc[0]+DIR_UP;
else NPC->Data = NPC->Misc[0]+DIR_DOWN;
}else{
if(dx >= 0) NPC->Data = NPC->Misc[0]+DIR_LEFT;
else NPC->Data = NPC->Misc[0]+DIR_RIGHT;
}
}else NPC->Data = NPC->Misc[0]+(defdir-1);
}
}
}
ffc script RealNPCtakemoney{
void run(int m, int sfx, int defdir, int increment, int decrement, int input, int npcid){
ffc NPC = this;
NPC->Misc[0] = NPC->Data;
while(true){
SetGraphic(NPC,defdir,40);
if(CanTalk(NPC,input)){
if(NPC_Hastaken[npcid]){
SetInput(input,false);
if(sfx != 0) Game->PlaySound(sfx);
Screen->Message(m);
}
else if(!NPC_Hastaken[npcid] && Game->Counter[CR_RUPEES] >= decrement){
Game->Counter[CR_RUPEES] -= decrement;
Game->Counter[CR_RUPEES] += increment;
NPC_Hastaken[npcid] = true;
if(sfx!=0) Game->PlaySound(sfx);
SetInput(input,false);
Screen->Message(m+1);
}
else if(!NPC_Hastaken[npcid] && Game->Counter[CR_RUPEES] < decrement){
SetInput(input,false);
if(sfx!=0) Game->PlaySound(sfx);
Screen->Message(m+2);
}
}
Waitframe();
}
}
bool CanTalk(ffc NPC,int input){
return (SelectPressInput(input) && Abs(NPC->X-Link->X) < 24 && Abs(NPC->Y-Link->Y) < 24 && Link->Z == 0);
}
void SetGraphic(ffc NPC, int defdir, int d){
int dx = NPC->X-Link->X; int ax = Abs(dx);
int dy = NPC->Y-Link->Y; int ay = Abs(dy);
if(defdir != 0){
if(ax < d && ay < d){
if(ax <= ay){
if(dy >= 0) NPC->Data = NPC->Misc[0]+DIR_UP;
else NPC->Data = NPC->Misc[0]+DIR_DOWN;
}else{
if(dx >= 0) NPC->Data = NPC->Misc[0]+DIR_LEFT;
else NPC->Data = NPC->Misc[0]+DIR_RIGHT;
}
}else NPC->Data = NPC->Misc[0]+(defdir-1);
}
}
}
ffc script HoleLava{
void run(int lava, int warpto, int warptype, int damage){
int graphic = WSP_FALLING; int sfx = SFX_FALLING;
if(lava){ graphic = WSP_LAVA; sfx = SFX_LAVA; }
if(this->X == 0 && this->Y == 0){
Waitframes(5);
this->X = Link->X; this->Y = Link->Y;
}
if(damage == 0) damage = 8;
while(true){
while(!OnPitCombo()) Waitframe();
int pitclk = 0;
while(OnPitCombo() && pitclk++ < 4) WaitCancelFeather();
if(pitclk >= 5) Fall(this,sfx,graphic,damage,warpto,warptype);
}
}
void Fall(ffc pos, int sfx, int graphic, int damage, int warpto, int warptype){
Falling = true;
Game->PlaySound(sfx);
for(int i=1;i<=Screen->NumLWeapons();i++){
lweapon l = Screen->LoadLWeapon(i);
if(l->ID == LW_SWORD) l->DeadState = WDS_DEAD;
}
int wait = CreateGraphic(graphic);
Link->CollDetection = false; Link->Invisible = true;
for(int i=0;i<30;i++) WaitNoAction();
Link->CollDetection = true; Link->Invisible = false;
if(warpto) PitWarp(pos, warptype);
Link->X = pos->X; Link->Y = pos->Y;
Link->HP -= damage;
Game->PlaySound(SFX_OUCH);
Falling = false;
}
void PitWarp(ffc Warp, int warptype){
int orig = Warp->Data;
Link->Z = Link->Y;
Warp->Data = CMB_AUTOWARP+warptype;
Waitframe();
Link->Z = Link->Y;
Quit();
}
bool OnPitCombo(){
return (Screen->ComboT[ComboAt(Link->X+8,Link->Y+8)] == CT_HOLELAVA && Link->Z <= 0 && Link->Action != LA_FROZEN);
}
int CreateGraphic(int sprite){
lweapon l = Screen->CreateLWeapon(LW_SCRIPT1);
l->HitXOffset = 500;
l->UseSprite(sprite);
l->DeadState = l->NumFrames*l->ASpeed;
l->X = Link->X; l->Y = Link->Y;
return l->DeadState;
}
void WaitCancelFeather(){
if(GetEquipmentA() == I_ROCSFEATHER && Link->InputA) Link->InputA = false;
if(GetEquipmentB() == I_ROCSFEATHER && Link->InputB) Link->InputB = false;
Waitframe();
}
}
ffc script Spawner
{
void run(int ID)
{
Waitframes(4);
npc n = CreateNPCAt(ID, this->X, this->Y);
n->Dir = DIR_DOWN;
}
}
But I'm not sure if I'll be able to merge all the global variables with this script from ghost.zh:
CODE
global script GhostZHActiveScript
{
void run()
{
StartClock();
while(true)
{
UpdateEWeapons();
UpdateClock();
CleanUpGhostFFCs();
Waitdraw();
AutoGhost();
Waitframe();
}
}
}