use of eidolons.entity.active.DC_ActiveObj in project Eidolons by IDemiurge.
the class InstantAttackRule method getInstantAttacks.
// could be a spell?..
public static List<DC_ActiveObj> getInstantAttacks(Unit unit) {
List<DC_ActiveObj> list = new ArrayList<>();
List<DC_UnitAction> attacks = new ArrayList<>(unit.getActionMap().get(ActionEnums.ACTION_TYPE.STANDARD_ATTACK));
if (unit.getActionMap().get(ActionEnums.ACTION_TYPE.SPECIAL_ATTACK) != null) {
attacks.addAll(unit.getActionMap().get(ActionEnums.ACTION_TYPE.SPECIAL_ATTACK));
}
for (DC_UnitAction attack : attacks) {
if (checkAttackCanBeInstant(attack)) // if (attack
// .checkProperty(G_PROPS.ACTION_TAGS,
// ACTION_TAGS.INSTANT_ATTACK.toString()))
{
list.add(attack);
}
}
return list;
}
use of eidolons.entity.active.DC_ActiveObj in project Eidolons by IDemiurge.
the class DamageDealer method dealPureDamage.
private static int dealPureDamage(BattleFieldObject attacked, Unit attacker, Integer endurance_dmg, Integer toughness_dmg, Ref ref) {
// apply Absorption here?
boolean enduranceOnly = false;
if (toughness_dmg == null) {
enduranceOnly = true;
toughness_dmg = 0;
}
if (isLogOn()) {
attacked.getGame().getLogManager().newLogEntryNode(true, ENTRY_TYPE.DAMAGE);
attacked.getGame().getLogManager().logDamageDealt(toughness_dmg, endurance_dmg, attacker, attacked);
}
LogMaster.log(1, toughness_dmg + " / " + endurance_dmg + " damage being dealt to " + attacked.toString());
ref.setTarget(attacked.getId());
ref.setSource(attacker.getId());
Event event;
boolean result;
int actual_t_damage = 0;
if (toughness_dmg > 0) {
if (!enduranceOnly) {
event = new Event(STANDARD_EVENT_TYPE.UNIT_IS_BEING_DEALT_TOUGHNESS_DAMAGE, ref);
ref.setAmount(toughness_dmg);
result = event.fire();
if (DC_GameManager.checkInterrupted(ref)) {
return 0;
}
// triggers may have changed the
toughness_dmg = ref.getAmount();
// amount!
actual_t_damage = Math.min(attacked.getIntParam(PARAMS.C_TOUGHNESS) * (100 + UnconsciousRule.getDeathBarrier(attacked)) / 100, toughness_dmg);
ref.setAmount(actual_t_damage);
// - attacked.getIntParam(PARAMS.C_TOUGHNESS);
if (result) {
attacked.modifyParameter(PARAMS.C_TOUGHNESS, -toughness_dmg);
}
event = new Event(STANDARD_EVENT_TYPE.UNIT_IS_DEALT_TOUGHNESS_DAMAGE, ref);
result = event.fire();
}
}
int actual_e_damage = 0;
if (endurance_dmg > 0) {
ref.setAmount(endurance_dmg);
event = new Event(STANDARD_EVENT_TYPE.UNIT_IS_BEING_DEALT_ENDURANCE_DAMAGE, ref);
result = event.fire();
if (DC_GameManager.checkInterrupted(ref)) {
attacked.getGame().getLogManager().doneLogEntryNode();
return 0;
}
endurance_dmg = ref.getAmount();
actual_e_damage = Math.min(attacked.getIntParam(PARAMS.C_ENDURANCE), endurance_dmg);
ref.setAmount(actual_e_damage);
if (result) {
attacked.modifyParameter(PARAMS.C_ENDURANCE, -endurance_dmg);
}
event = new Event(STANDARD_EVENT_TYPE.UNIT_IS_DEALT_ENDURANCE_DAMAGE, ref);
result = event.fire();
}
int damageDealt = Math.max(actual_e_damage, actual_t_damage);
boolean dead = DamageCalculator.isDead(attacked);
boolean annihilated = attacked instanceof Unit && attacked.getGame().getRules().getUnconsciousRule().checkUnitAnnihilated((Unit) attacked);
boolean unconscious = attacked instanceof Unit && attacked.getGame().getRules().getUnconsciousRule().checkStatusUpdate((Unit) attacked, (DC_ActiveObj) ref.getActive());
if (dead) {
// will start new entry... a good preCheck
try {
attacked.kill(attacker, !annihilated, false);
if (annihilated) {
attacked.getGame().getManager().getDeathMaster().unitAnnihilated(attacked, attacker);
}
} catch (Exception e) {
main.system.ExceptionMaster.printStackTrace(e);
}
ref.setAmount(damageDealt);
// if (DC_GameManager.checkInterrupted(ref))
// return 0; ???
} else {
if (unconscious) {
attacked.getGame().getRules().getUnconsciousRule().fallUnconscious((Unit) attacked);
}
}
if (toughness_dmg < 0 || endurance_dmg < 0) {
LogMaster.log(1, toughness_dmg + "rogue damage " + endurance_dmg);
} else
LogMaster.log(1, toughness_dmg + " / " + endurance_dmg + " damage has been dealt to " + attacked.toString());
if (isLogOn()) {
attacked.getGame().getLogManager().doneLogEntryNode(ENTRY_TYPE.DAMAGE, attacked, damageDealt);
}
processDamageEvent(null, ref, damageDealt, STANDARD_EVENT_TYPE.UNIT_HAS_BEEN_DEALT_PURE_DAMAGE);
return damageDealt;
}
use of eidolons.entity.active.DC_ActiveObj in project Eidolons by IDemiurge.
the class DC_AttackMaster method attackNow.
/**
* @return null if attack has been delayed by target's first strike; false if target is killed; true otherwise
*/
private Boolean attackNow(Attack attack, Ref ref, boolean free, boolean canCounter, Effect onHit, Effect onKill, boolean offhand, boolean isCounter) {
if (!(ref.getTargetObj() instanceof BattleFieldObject)) {
return true;
}
// PhaseAnimation animation =
// game.getAnimationManager().getAnimation(attack.getAction().getAnimationKey());
DC_ActiveObj action = (DC_ActiveObj) ref.getObj(KEYS.ACTIVE);
if (action.checkProperty(G_PROPS.ACTION_TAGS, "" + ActionEnums.ACTION_TAGS.OFF_HAND)) {
offhand = true;
}
if (!offhand) {
if (action.isRanged()) {
if (!action.isThrow()) {
if (getAttackWeapon(ref, true).isRanged()) {
offhand = true;
}
}
}
}
BattleFieldObject attacked = (BattleFieldObject) ref.getTargetObj();
Unit attacker = (Unit) ref.getSourceObj();
if (attack.isSneak()) {
if (attacked.checkPassive(UnitEnums.STANDARD_PASSIVES.SNEAK_IMMUNE)) {
attack.setSneak(false);
log(StringMaster.MESSAGE_PREFIX_INFO + attacked.getName() + " is immune to Sneak Attacks!");
} else {
log(StringMaster.MESSAGE_PREFIX_ALERT + attacker.getNameIfKnown() + " makes a Sneak Attack against " + attacked.getName());
}
}
if (canCounter) {
if (!attacked.canCounter(action, attack.isSneak())) {
canCounter = false;
}
}
LogMaster.log(LogMaster.ATTACKING_DEBUG, attacker.getNameIfKnown() + " attacks " + attacked.getName());
// } ====> Need a common messaging interface for actions/costs
String damage_mods = "";
// if (sneak)
// damage_mods+=DAMAGE_MODIFIER.SNEAK;
ref.setValue(KEYS.DAMAGE_MODS, damage_mods);
boolean countered = false;
if (canCounter) {
if (attacked.hasFirstStrike() && !attacker.hasFirstStrike()) {
if (!attacker.hasNoRetaliation()) {
// countered = tryCounter(attack);
return null;
}
}
}
if (attacker.isDead()) {
attack.getAnimation().addPhase(new AnimPhase(PHASE_TYPE.INTERRUPTED, ref));
return false;
}
// TODO revamp
DC_SoundMaster.playEffectSound(SOUNDS.ATTACK, attacker);
if (action.isRanged()) {
DC_SoundMaster.playRangedAttack(getAttackWeapon(ref, offhand));
}
int amount = attacker.getIntParam(PARAMS.BASE_DAMAGE);
ref.setAmount(amount);
Event event = new Event(STANDARD_EVENT_TYPE.UNIT_IS_BEING_ATTACKED, ref);
if (!event.fire()) {
attack.getAnimation().addPhase(new AnimPhase(PHASE_TYPE.INTERRUPTED, ref));
return false;
}
// initializeFullModifiers(attack.isSneak(), offhand, action, ref);
Boolean dodged = false;
if (ref.getEffect().isInterrupted()) {
event.getRef().getEffect().setInterrupted(false);
dodged = true;
}
if (!attacked.isDead())
if (!dodged) {
boolean parried = parryRule.tryParry(attack);
if (parried) {
attack.setParried(true);
// if (
// EventMaster.fireStandard(STANDARD_EVENT_TYPE.ATTACK_DODGED, ref)) {
attacked.applySpecialEffects(SPECIAL_EFFECTS_CASE.ON_PARRY, attacker, ref);
attacker.applySpecialEffects(SPECIAL_EFFECTS_CASE.ON_PARRY_SELF, attacked, ref);
// }
return true;
}
dodged = DefenseVsAttackRule.checkDodgedOrCrit(attack);
}
// BEFORE_HIT
if (!attacked.isDead())
if (dodged == null) {
if (!new Event(STANDARD_EVENT_TYPE.UNIT_HAS_BEEN_HIT, ref).fire()) {
return false;
}
if (attacker.isDead()) {
return true;
}
// if (attacked.isDead()) { // now in unit.kill()
// if (onKill != null) {
// onKill.apply(ref);
// }
// attacked.applySpecialEffects(SPECIAL_EFFECTS_CASE.ON_DEATH, attacker, ref);
// return true;
// }
} else {
if (dodged) {
attack.setDodged(true);
log(attacked.getName() + " has dodged an attack from " + attacker.getNameIfKnown());
DC_SoundMaster.playMissedSound(attacker, getAttackWeapon(ref, offhand));
StackingRule.actionMissed(action);
// ++ animation? *MISS* //TODO ++ true strike
action.setFailedLast(true);
if (checkEffectsInterrupt(attacked, attacker, SPECIAL_EFFECTS_CASE.ON_DODGE, ref, offhand)) {
return true;
}
if (canCounter) {
if ((!countered) || attacked.hasDoubleCounter()) {
// tryCounter(attack); TODO ?
return true;
}
}
} else {
if (attacked.checkPassive(UnitEnums.STANDARD_PASSIVES.CRITICAL_IMMUNE)) {
log(StringMaster.MESSAGE_PREFIX_INFO + attacked.getName() + " is immune to Critical Hits!");
} else {
log(StringMaster.MESSAGE_PREFIX_ALERT + attacker.getNameIfKnown() + " scores a critical hit on " + attacked.getName());
attack.setCritical(true);
}
}
}
attacked.applySpecialEffects(SPECIAL_EFFECTS_CASE.BEFORE_HIT, attacker, ref);
attacker.applySpecialEffects(SPECIAL_EFFECTS_CASE.BEFORE_ATTACK, attacked, ref);
Integer final_amount = attack.getDamage();
// TODO REAL CALC How to calc damage w/o crit (for parry)?
if (final_amount == Attack.DAMAGE_NOT_SET) {
AttackCalculator calculator = new AttackCalculator(attack, false);
final_amount = calculator.calculateFinalDamage();
}
// TODO different for multiDamageType
if (CoreEngine.isPhaseAnimsOn())
PhaseAnimator.getInstance().initAttackAnimRawDamage(attack);
ref.setAmount(final_amount);
if (final_amount < 0) {
return true;
}
ref.setAmount(final_amount);
DAMAGE_TYPE dmg_type = ref.getDamageType();
if (attack.isCritical()) {
if (attacker.checkPassive(UnitEnums.STANDARD_PASSIVES.CLEAVING_CRITICALS)) {
// TODO add default cleave?
CleaveRule.addCriticalCleave(attacker);
dmg_type = GenericEnums.DAMAGE_TYPE.SLASHING;
}
}
if (dmg_type == null) {
dmg_type = action.getDamageType();
}
if (dmg_type == null) {
if (!checkWeapon(ref)) {
dmg_type = attacker.getDamageType();
} else {
dmg_type = getAttackWeapon(ref, offhand).getDamageType();
}
}
attack.setDamageType(dmg_type);
if (attack.getDamage() == Attack.DAMAGE_NOT_SET) {
attack.setDamage(final_amount);
}
if (!new Event(STANDARD_EVENT_TYPE.UNIT_HAS_BEEN_ATTACKED, ref).fire()) {
return false;
}
if (!new Event(STANDARD_EVENT_TYPE.UNIT_HAS_BEEN_HIT, ref).fire()) {
return false;
}
Unit attackedUnit = null;
if (attacked instanceof Unit) {
attackedUnit = (Unit) attacked;
}
if (!attacked.isDead())
if (attackedUnit != null)
if (attackedUnit.getOffhandWeapon() != null) {
if (attackedUnit.getOffhandWeapon().isShield()) {
if (!attack.isSneak()) {
// && !isCounter) {
int blocked = game.getArmorMaster().getShieldDamageBlocked(final_amount, attackedUnit, attacker, action, getAttackWeapon(ref, attack.isOffhand()), attack.getDamageType());
final_amount -= blocked;
if (blocked > 0) {
Ref REF = ref.getCopy();
REF.setAmount(blocked);
if (checkEffectsInterrupt(attackedUnit, attacker, SPECIAL_EFFECTS_CASE.ON_SHIELD_BLOCK, REF, offhand)) {
return true;
}
if (checkEffectsInterrupt(attacker, attackedUnit, SPECIAL_EFFECTS_CASE.ON_SHIELD_BLOCK_SELF, REF, offhand)) {
return true;
}
}
}
}
}
// armor penetration?
attack.setDamage(final_amount);
if (checkAttackEventsInterrupt(attack, ref)) {
return true;
}
// ForceRule.addForceEffects(action); now in executor.resolve() for all actions
Damage damageObj = DamageFactory.getDamageForAttack(dmg_type, ref, final_amount);
int damageDealt = DamageDealer.dealDamage(damageObj);
attack.damageDealt(damageDealt);
attack.reset();
if (attacked.isDead()) {
if (!attack.isTriggered()) {
game.getRules().getCleaveRule().apply(ref, attack);
}
}
if (onHit != null) {
onHit.apply(ref);
}
if (!action.isRanged()) {
// e.g.
attacked.applySpecialEffects(SPECIAL_EFFECTS_CASE.ON_HIT, attacker, ref);
}
if (attackedUnit != null)
// e.g.
attacker.applySpecialEffects(SPECIAL_EFFECTS_CASE.ON_ATTACK, attackedUnit, ref, offhand);
try {
// map=
CoatingRule.unitIsHit(attacked, attacker, offhand, action, attack, attack.getWeapon());
} catch (Exception e) {
main.system.ExceptionMaster.printStackTrace(e);
}
if (attackedUnit != null) {
InjuryRule.applyInjuryRule(action);
if (attack.isCritical()) {
checkEffectsInterrupt(attackedUnit, attacker, SPECIAL_EFFECTS_CASE.ON_CRIT_SELF, ref, offhand);
checkEffectsInterrupt(attacker, attackedUnit, SPECIAL_EFFECTS_CASE.ON_CRIT, ref, offhand);
}
}
return true;
}
use of eidolons.entity.active.DC_ActiveObj in project Eidolons by IDemiurge.
the class AttackOfOpportunityRule method checkAttacksOfOpportunityInterrupt.
public static Boolean checkAttacksOfOpportunityInterrupt(DC_ActiveObj action) {
List<Unit> set = getPotentialAttackersOfOpportunity(action);
for (Unit unit : set) {
DC_ActiveObj attack = getAttackOfOpportunity(action, unit);
if (attack == null) {
continue;
}
Boolean before_after_none = RollMaster.makeReactionRoll(unit, action, attack);
if (before_after_none == null) {
action.addPendingAttackOpportunity(attack);
} else if (before_after_none) {
boolean result = triggerAttackOfOpportunityAttack(unit, action, attack);
if (result) {
return true;
}
}
}
return false;
}
use of eidolons.entity.active.DC_ActiveObj in project Eidolons by IDemiurge.
the class AttackOfOpportunityRule method getAttackOfOpportunity.
private static DC_ActiveObj getAttackOfOpportunity(DC_ActiveObj action, Unit unit) {
if (unit.getPreferredAttackOfOpportunity() != null) {
if (canMakeAttackOfOpportunityAgainst(action, unit.getPreferredAttackOfOpportunity(), unit)) {
return unit.getPreferredAttackOfOpportunity();
}
}
Unit target = action.getOwnerObj();
int distance = (PositionMaster.getDistance(target.getCoordinates(), unit.getCoordinates()));
for (DC_ActiveObj attack : getAttacksOfOpportunity(unit)) {
if (distance > getMaxAttackRange(attack)) {
continue;
}
if (!canMakeAttackOfOpportunityAgainst(action, attack, unit)) {
continue;
}
if (FacingMaster.getSingleFacing(unit, target) == UnitEnums.FACING_SINGLE.TO_THE_SIDE) {
if (!attack.checkPassive(UnitEnums.STANDARD_PASSIVES.BROAD_REACH)) {
continue;
}
}
if (FacingMaster.getSingleFacing(unit, target) == UnitEnums.FACING_SINGLE.BEHIND) {
if (!attack.checkPassive(UnitEnums.STANDARD_PASSIVES.HIND_REACH)) {
continue;
}
}
if (attack.canBeTargeted(target.getId())) {
if (attack.canBeActivatedAsAttackOfOpportunity(false, target)) // TODO PICK OPTIMAL? Consider roll's cost modifier...
{
return attack;
}
}
}
return null;
}
Aggregations