Code:
//this checks to see if we have a GCD to consume
if(bs.isGCD())
{
//this gets the timings for the time since the last time we cast those attacks.
lastGL = currEvent.eventTime() - bs.getLastGL();
lastTwin = currEvent.eventTime() - bs.getLastTwin();
lastDK = currEvent.eventTime() - myTarget.getLastDK();
//basically sets the last time we did demo to a million years ago if we're lacking demo (for PB)
lastDemo = (myTarget.demo()?currEvent.eventTime() - myTarget.getLastDEMO().eventTime():-100000);
//this gets our current GCD (modified by GL stacks)
currGCD = bs.getGCD();
//this just does PB at the start of the fight
if(currEvent.eventTime()==0 && !bs.pbCD())
{
bs.addAction(MNKEvent.EventType.PB, myTarget);
continue;
}
//this tells us what we do inside a PB
if(bs.pb())
{
//setup GL and buffs, first priority during PB
if(bs.gl() < 3)
{
//only Demo during PB only after buffs if we're starting with pb
if(!myTarget.demo() && (currEvent.eventTime() > 1000 || bs.bfb() && bs.ir()))
bs.addAction(MNKEvent.EventType.DEMO, myTarget);
else //otherwise SP
bs.addAction(MNKEvent.EventType.SP, myTarget);
}
else
{
//once we have GL3, setup other buffs, prioritizing DK before OPO form runs out
if(bs.getLastStance() == MNKSimulator.Stance.OPO && !myTarget.dk())
bs.addAction(MNKEvent.EventType.DK, myTarget);
else if(!bs.twin())
bs.addAction(MNKEvent.EventType.TWIN, myTarget);
else //if we have all buffs, just SP for max damage.
{
bs.addAction(MNKEvent.EventType.SP, myTarget);
}
}
}
else
{
//do different timings based on stance
switch(bs.getLastStance())
{
//we only have NONE stance if we just came out of PB or we had to leave target
case NONE:
//basically if we don't have DK, Twin or GL3, or demo, immediately start GL combo
if(!myTarget.dk() || lastDemo >= 1800 - currGCD * 2 || lastGL >= 1200 - currGCD*3 || lastTwin >= 1200 - currGCD * 2 || bs.gl() < 3)
bs.addAction(MNKEvent.EventType.DK, myTarget);
else if(!myTarget.tod()) //otherwise, we have time to ToD
bs.addAction(MNKEvent.EventType.TOD, myTarget);
else if(!myTarget.fr()) //otherwise, we have time to FR
bs.addAction(MNKEvent.EventType.FR, myTarget);
else //otherwise ID filler
bs.addAction(MNKEvent.EventType.ID, myTarget);
break;
case RAPTOR:
if(lastTwin >= 1200 - currGCD*3) //if twin will fall off within next combo
bs.addAction(MNKEvent.EventType.TWIN, myTarget);
//this tests timings to see whether we have time to filler
else if(lastGL < 1200 - currGCD*2 && lastDemo < 1800 - currGCD && lastTwin < 1200 - currGCD && lastDK < 1500 - currGCD*3)
{
//filler priority is ToD > FR > ID
if(!myTarget.tod())
bs.addAction(MNKEvent.EventType.TOD, myTarget);
else if(!myTarget.fr())
bs.addAction(MNKEvent.EventType.FR, myTarget);
else
bs.addAction(MNKEvent.EventType.ID, myTarget);
}
else
bs.addAction(MNKEvent.EventType.TRUE, myTarget);
break;
case COEURL:
//more timings, demo if it will expire in less than 3 seconds (arbitrary number here)
if(!myTarget.demo() || (lastDemo > 1500 && currEvent.numBuffs() > myTarget.getLastDEMO().numBuffs()))
bs.addAction(MNKEvent.EventType.DEMO, myTarget);
//otherwise SP if DK, GL, or Twin will fall off
else if(lastGL >= 1200 - currGCD || lastDK >= 1500 - currGCD*2 || lastTwin >= 1200 - currGCD*3)
bs.addAction(MNKEvent.EventType.SP, myTarget);
else
{
//otherwise filler
if(!myTarget.tod())
bs.addAction(MNKEvent.EventType.TOD, myTarget);
else if(!myTarget.fr())
bs.addAction(MNKEvent.EventType.FR, myTarget);
else
bs.addAction(MNKEvent.EventType.ID, myTarget);
}
break;
case OPO:
//dk if dk is going to fall off
if(!myTarget.dk() || lastDK > 1500 - currGCD*3)
bs.addAction(MNKEvent.EventType.DK, myTarget);
//if nothing's going to fall off we can filler
else if(lastGL < 1200 - currGCD*3 && lastDemo < 1800 - currGCD * 2 && lastTwin < 1200 - currGCD*2 && lastDK < 1500 - currGCD)
{
if(!myTarget.tod())
bs.addAction(MNKEvent.EventType.TOD, myTarget);
else if(!myTarget.fr())
bs.addAction(MNKEvent.EventType.FR, myTarget);
else
bs.addAction(MNKEvent.EventType.ID, myTarget);
}
//if somehow we get here (usually because i've disabled ID filler, we can BS if DK won't fall off
else if(myTarget.dk() && lastDK < 1500 - currGCD*3 && myTarget.canBackstab())
bs.addAction(MNKEvent.EventType.BS, myTarget);
else
//if we run out of stuff to do might as well DK to continue rotation
bs.addAction(MNKEvent.EventType.DK, myTarget);
break;
}
}
}
//this checks to see if there is an oGCD slot for an action
else if(bs.isOGCD())
{
//do all OGCD actions here
//PB if its up, and we are either missing GL stacks or the stance isn't COEURL (so we don't waste a coeurl)
if(!bs.pbCD() && (bs.gl() < 3 || bs.getLastStance() != MNKSimulator.Stance.COEURL))
{
bs.addAction(MNKEvent.EventType.PB, myTarget);
}
//do BfB > IR > HF > Peak > invig cooldowns, too lazy (and not much point) in saving to stack.
else if(!bs.bfbCD())
bs.addAction(MNKEvent.EventType.BFB, myTarget);
else if(!bs.irCD() && (!myTarget.demo() || lastDemo > 1200))
bs.addAction(MNKEvent.EventType.IR, myTarget);
else if(!bs.hfCD())
bs.addAction(MNKEvent.EventType.HF, myTarget);
else if(!bs.peakCD())
bs.addAction(MNKEvent.EventType.PEAK, myTarget);
else if(bs.getTPBalance() < 540)
bs.addAction(MNKEvent.EventType.INVIG, myTarget);
}