const int STATUS_GUM_SPEED_PENALTY = 0.75;//Speed penalty when affected by Gum status effect
const int STATUS_GUM_SWORD_POWER = 10;//Used to determine how fast failed attempts to use sword progress on getting rid of gum effect.
const int STATUS_GUM = 8;//ID of Gum status effect
const int CMB_GUM_ATTACH_GFX = 1000;//Comb used to render Gum attached to Link.
const int CSET_GUM_ATTACH_GFX = 10;//CSet used to render Gum attached to Link.
const int SFX_STATUS_GUM_STUCK = 42;//Sound to play, when Gum enemy attaches to Link.
const int NPC_DETACHED_GUM = 189;//ID of enemy to spawn when GUM detaches from Link (must be ID of GumZol itself)
const int SPR_GUM_DISSOLVE = 22;//Sprite to display, when Link washes off Gum with a potion or at fairy fountain.
const int I_NO_GUM = 100;//ID of item that prevents GumZols from attaching to Link.
//Gum Zol
//Moves like Zol, but faster. If it collides with Link, he attaches to him, redusing his movement speed and rendering him unable to use sword until Gum falls off or washed off. Repeatedly use sword to detach Gum faster or use a potion to wash it off entirely.
//Requires ghost.zh, LinkMovement.zh and status.zh set up already.
//1. Set up combo for rendering GumZol attached to Link, set CMB_GUM_ATTACH_GFX to ID of that combo.
//2. Set NPC_DETACHED_GUM to reserved ID for GumZol enemy.
//3. Check out other constants in script file.
//4. Global Script Combining: Put GumStatusUpdate() after StatusEffectsUpdate1() command that handles default status effects and UpdateStatusTimers() command that handles status effect timers.
//4. Compile the script.
//5. Set up enemy with ID equal to NPC_DETACHED_GUM from step 2.
ffc script GumZol{
void run(int enemyID){
npc ghost = Ghost_InitAutoGhost(this, enemyID);
int HF = ghost->Homing;
int HR = ghost->Haltrate;
int RR = ghost->Rate;
int HNG = ghost->Hunger;
int SPD = ghost->Step;
int WPND = ghost->WeaponDamage;
int sizex = Ghost_GetAttribute(ghost, 0, 1);//Enemy Size X
int sizey = Ghost_GetAttribute(ghost, 1, 1);//EnemySize Y;
int gumpower = Ghost_GetAttribute(ghost, 2, 600);//Duration of status effect, induced on collision
int cooldown = Ghost_GetAttribute(ghost, 3, 120);//Cooldown time right after spawn, during that enemy`s hitbox is inactive to prevent instant reattaches.
ghost->Extend=3;
Ghost_SetSize(this, ghost, sizex, sizey);
if (sizex>2 || sizey>2)Ghost_SetHitOffsets(ghost, 8, 8, 8, 8);
Ghost_SetFlag(GHF_NORMAL);
int OrigTile = ghost->OriginalTile;
int State = 0;
int statecounter = 0;
int haltcounter = -1;
int defs[18];
Ghost_StoreDefenses(ghost,defs);
ghost->CollDetection=false;
while(true){
haltcounter = Ghost_ConstantWalk4(haltcounter, SPD, RR, HF, HNG);
if (cooldown>0){
cooldown--;
if (cooldown<=0)ghost->CollDetection=true;
}
if (cooldown<=0&&LinkCollision(ghost)&&!IsActive(STATUS_GUM)&&!Link->Item[I_NO_GUM]){
InduceStatusEffect (STATUS_GUM, gumpower, I_NO_GUM, false);
ghost->ItemSet=0;
Ghost_HP=HP_SILENT;
}
Ghost_Waitframe(this, ghost);
}
}
}
//Status effect code to be put inside global script.
void GumStatusUpdate(){
if (STATUS_STATE[STATUS_GUM]>0){//A more advanced version of status effect template.
if (HasStarted(STATUS_GUM)){
Game->PlaySound(SFX_STATUS_GUM_STUCK);
Game->PlaySound(SFX_OUCH);
}
if (IsActive(STATUS_GUM)){
LinkMovement_SetLinkSpeedBoost(-STATUS_GUM_SPEED_PENALTY);
Link->SwordJinx=2;
int itm = GetEquipmentA();
itemdata it = Game->LoadItemData(itm);
if (it->Family==IC_SWORD && Link->PressA){
Game->PlaySound(SFX_STATUS_GUM_STUCK);
STATUSTIMERS[STATUS_GUM]-=STATUS_GUM_SWORD_POWER;
Link->InputA=false;
Link->PressA = false;
}
itm = GetEquipmentB();
it = Game->LoadItemData(itm);
if (it->Family==IC_SWORD && Link->PressB){
Game->PlaySound(SFX_STATUS_GUM_STUCK);
STATUSTIMERS[STATUS_GUM]-=STATUS_GUM_SWORD_POWER;
Link->InputB=false;
Link->PressB = false;
}
Screen->FastCombo(3,Link->X,Link->Y,CMB_GUM_ATTACH_GFX,CSET_GUM_ATTACH_GFX,OP_OPAQUE);
}
if (HasExpired(STATUS_GUM)){
if (NPC_DETACHED_GUM<=20) return;
npc gum = CreateNPCAt(NPC_DETACHED_GUM,Link->X,Link->Y);
gum->Jump=1.6;
int scr = Game->GetCurScreen();
Game->GuyCount[scr]++;
}
if (HasRemoved(STATUS_GUM)){
if (SPR_GUM_DISSOLVE<=0)return;
lweapon s = CreateLWeaponAt(LW_SPARKLE, Link->X, Link->Y);
s->UseSprite(SPR_GUM_DISSOLVE);
s->CollDetection=false;
}
}
}
// Init global script.
// global script Init {
// void run() {
// InitStatusEffects();
// }
// }
//example global script
global script GumZolActive{
void run(){
StartGhostZH();
Tango_Start();
__classic_zh_InitScreenUpdating();
LinkMovement_Init();
while(true) {
StatusEffectsUpdate1(); //Checks status effects and runs code for active ones.
GumStatusUpdate();
UpdateStatusTimers();
LinkMovement_Update1();
UpdateGhostZH1();
__classic_zh_UpdateScreenChange1();
Tango_Update1();
__classic_zh_do_z2_lantern();
if ( __classic_zc_internal[__classic_zh_SCREENCHANGED] )
{
__classic_zh_CompassBeep();
__classic_zh_ResetScreenChange();
}
Waitdraw();
// SolidObjects_Update2();
LinkMovement_Update2();
UpdateGhostZH2();
Tango_Update2();
Waitframe();
}
}
}
//Item that removes specific status effect when used/picked up.
//Can be used as "On Use" item script, like various antidotes,
//or "On Pickup", for item that prevents given status effect.
//D0: Status to remove.
//D1: Clear normally uncurable status effect. 0 - false, 1 - true.
//Temporarily fixed variant until library update would be submitted to PureZC database.
item script CureStatusEffectFixed{
void run (int status, int uncurableforceremove){
bool forceremove = false;
if (!IsActive(status)) Quit();
if (uncurableforceremove > 0) forceremove = true;
RemoveStatusEffect(status, forceremove);
}
}
//Step on FFC with this screen and all curable status effect will be removed instantly.
//Place FFC on the same place as Fairy Ring combo flags.
//D0: sound to play on curing status effects.
//Temporarily fixed variant until library update would be submitted to PureZC database.
ffc script FairyStatusRemoverFixed{
void run(int sound){
while(true){
if (LinkCollision(this)){
int numtimers = SizeOfArray(STATUSTIMERS);
for (int i=0; i<numtimers; i++){
if (IsActive(i))RemoveStatusEffect(i, false);
}
Waitframe();
Quit();
}
Waitframe();
}
}
}
//If GumZol attaches to Link on screen with Enemies->Secret screen flag is on, secrets will be triggered prematurely.
//Use this script instead of the flag to prevent this.
//Place FFC anywhere in that screen.
//D0 - ID of the Gum status effect.
ffc script AltEnemySecret{
void run(int status){
Waitframes(5);
if (Screen->State[ST_SECRET])Quit();
while (EnemiesAlive() || IsActive(status) || HasStarted(status)||HasExpired(status)) Waitframe();
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
}
}