// 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;
}
}