Copy to Clipboard Test

Bari & Biri Code

// Bari's Link Shock Constants
const int BARI_SHOCK_TIME         = 30;
const int BARI_SFX_SHOCK          = 61;
const int BARI_WPS_SHOCK          = 88;

// npc->Attributes[] index
const int BARI_ATTR_SHOCK_CHANCE  = 5;
const int BARI_ATTR_SHOCK_TIME    = 7;

// ffc->Misc[] index
const int BARI_IDX_SHOCKING       = 0;

ffc script Bari
{
    void run(int enemyID)
    {
        //Init
        npc ghost = Ghost_InitAutoGhost(this, enemyID);
        int swordDefense = ghost->Defense[NPCD_SWORD]; //This is what is initially

        //Flags
        Ghost_SetFlag(GHF_FAKE_Z);
        Ghost_SetFlag(GHF_NO_FALL);
        Ghost_SetFlag(GHF_FLYING_ENEMY);

        //Combos
        int regularCombo = Ghost_Data;
        int shockCombo = Ghost_Data+1;

        //Movement Variables
        int counter = -1;
        int stepSpeed = ghost->Step;
        int randomRate = ghost->Rate;
        int homingFactor = ghost->Homing;
        int hunger = ghost->Hunger;
        int turnFrequency = ghost->Haltrate;
        bool alwaysMove;

        //Shock Variables

        int shockCounter;
        int shockChance = Ghost_GetAttribute(ghost, BARI_ATTR_SHOCK_CHANCE, 150);
        int shockTime = Ghost_GetAttribute(ghost, BARI_ATTR_SHOCK_TIME, 48);
        if(shockChance < 0)
        {
            shockChance *= -1;
            alwaysMove = true;
        }
        
        //Spawn Animation
        Ghost_SpawnAnimationPuff(this, ghost);

        //Behavior Loop
        do
        {
            if(ghost->Stun > 0 || ClockIsActive())
            {
                if(shockCounter > 0)
                {
                    shockCounter = 0;
                    Ghost_Data = regularCombo;
                }

                while(ghost->Stun > 0 || ClockIsActive())
                    Ghost_Waitframe(this, ghost, true, true);
            }

            //Using the shock attack? then decrement it's counter.
            if(shockCounter > 0)
            {
                shockCounter--;
                if(shockCounter==0)
                    Ghost_Data = regularCombo;
            }

            //Otherwise randomly start the shock attack.
            else if(Rand(shockChance)==0)
            {
                shockCounter = shockTime;
                Ghost_Data = shockCombo;
            }

            //Movement
            if(shockCounter==0 || alwaysMove)
            {
                counter = Ghost_VariableWalk8(counter, stepSpeed, randomRate, homingFactor, hunger, turnFrequency);
                Ghost_Z = 8; //maintain z position.
            }

        } while(BariWaitframe(this, ghost, shockCounter, swordDefense));
    }

    bool BariWaitframe(ffc this, npc ghost, int shockCounter, int swordDefense)
    {
        bool electrified;

        //Is the Bari electrified?
        if(shockCounter > 0)
        {
            electrified = true;
            ghost->Defense[NPCD_SWORD] = NPCDT_IGNORE;
        }
        else
        {
            electrified = false;
            ghost->Defense[NPCD_SWORD] = swordDefense;
        }

        //If stunned or a clock is active, set sword defense to normal and return.
        if(ghost->Stun > 0 || ClockIsActive())
        {
            ghost->Defense[NPCD_SWORD] = swordDefense;
            return Ghost_Waitframe(this, ghost, true, true);
        }
        //If not electrified just wait.
        else if(!electrified)
            return Ghost_Waitframe(this, ghost, true, true);
        //Same thing if another Bari is shocking Link.
        else if(AlreadyBeingShocked(this))
            return Ghost_Waitframe(this, ghost, true, true);

        //Otherwise check for sword collisions.
        else
        {
            lweapon sword;
            for(int i = Screen->NumLWeapons(); i > 0; i--)
            {
                sword = Screen->LoadLWeapon(i);

                if(sword->ID == LW_SWORD)
                {
                    // Hit by sword; create an eweapon to hurt Link
                    if(Collision(sword, ghost))
                    {
                        eweapon wpn;
                        int oldLinkX;
                        int oldLinkY;
                        bool oldLinkInvis;
                        bool oldLinkColl;
                        
                        // Set this so other Bari's don't activate
                        this->Misc[BARI_IDX_SHOCKING]=1;
                        
                        // Remember Link's data
                        oldLinkX=Link->X;
                        oldLinkY=Link->Y;
                        oldLinkInvis=Link->Invisible;
                        oldLinkColl=Link->CollDetection;
                        
                        // Hurt Link, hide him, draw the shock graphic, and play the sound
                        Link->HP-=4*ghost->WeaponDamage;
                        
                        Link->Invisible=true;
                        Link->CollDetection=false;
                        
                        lweapon graphic=Screen->CreateLWeapon(LW_SCRIPT1);
                        graphic->UseSprite(BARI_WPS_SHOCK);
                        graphic->X=Link->X;
                        graphic->Y=Link->Y;
                        graphic->CollDetection=false;
                        graphic->DeadState=BARI_SHOCK_TIME;
                        
                        Game->PlaySound(BARI_SFX_SHOCK);
                        Screen->Quake=Max(Screen->Quake, 30);
                        
                        for(int j=0; j<BARI_SHOCK_TIME; j++)
                        {
                            NoAction();
                            Link->X=oldLinkX;
                            Link->Y=oldLinkY;
                            Ghost_Waitframe(this, ghost, true, true);
                            
                            // Make Link visible again if he died
                            if(Link->HP<=0)
                                Link->Invisible=oldLinkInvis;
                        }
                        
                        // Unhide Link, stop flashing
                        Link->Invisible=oldLinkInvis;
                        Link->CollDetection=oldLinkColl;
                        this->Misc[BARI_IDX_SHOCKING]=0;
                    }
                    break;
                }
            }
        }
        return Ghost_Waitframe(this, ghost, true, true);
    }

    //Is another Bari already shocking Link?
    bool AlreadyBeingShocked(ffc this)
    {
        ffc f;
        
        // Check each other FFC
        for(int i = 1; i <= 32; i++)
        {
            f = Screen->LoadFFC(i);

            if(f==this)
                continue;

             //Same script and Misc[] index set? then It's shocking Link.
            if(f->Script == this->Script && f->Misc[BARI_IDX_SHOCKING] != 0)
                return true;
        }
        
        return false;
    }
}