Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
09fd11e
Add Unit::skillCharge and accessors
rayrobdod Mar 26, 2018
4611831
Display a unit's skillCharge in UnitInfo
rayrobdod Mar 26, 2018
c9f3e5e
Increase a unit's skillCharge when the unit is attacked
rayrobdod Mar 26, 2018
48bedda
Add a skill that uses skillCharge
rayrobdod Mar 26, 2018
e636534
Make the Rage skill only activate on enemy phase
rayrobdod Mar 26, 2018
a18e778
Add fieldSkill for using skillCharge on player phase
rayrobdod Mar 27, 2018
0c22d16
Solve skillCharge desynch from missed or zero-damage attacks
rayrobdod Mar 27, 2018
0c9ac20
Make Rage skills visible even if they do zero damage
rayrobdod Mar 27, 2018
c2d7686
Fix fieldskill.Rage's and fieldskill.Shove's equals methods
rayrobdod Mar 27, 2018
58dae35
Merge branch 'master' into skill-charge
rayrobdod Apr 7, 2018
bf6b172
Adjust skill charge numbers
rayrobdod Apr 7, 2018
e29d5c7
Make item-use functions return void
rayrobdod Apr 8, 2018
b88b88a
Remove functions that can use an item without destroying it
rayrobdod Apr 8, 2018
7484bcb
Add SkillChargingItem and the ability to use said item
rayrobdod Apr 8, 2018
5005806
Shove and Smite now increase a shoved enemy's skillCharge
rayrobdod Apr 8, 2018
f735823
Make units use their critical animation when performing a Rage attack
rayrobdod Apr 23, 2018
ac97743
Add start-of-phase weapon effects
rayrobdod Apr 23, 2018
81e6589
Deny StartOfPhaseEffects to dead or rescued units
rayrobdod Apr 23, 2018
7255fd2
Merge branch 'start-of-phase-effect' into skill-charge
rayrobdod Apr 23, 2018
0c1f767
Add a StartOfPhaseEffect to killer weapons that increments skillCharg…
rayrobdod Apr 23, 2018
1df7ce7
Merge branch 'master' into skill-charge
rayrobdod Jul 30, 2018
43ac07b
Merge branch 'master' into skill-charge
rayrobdod Nov 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions res/resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -4559,6 +4559,23 @@
}
]
},
{
"name": "hit_effect_rage",
"path": "res/battle_anim/hit_effect_critical.png",
"width": 240,
"height": 160,
"frames": 9,
"columns": 3,
"offsetX": 88,
"offsetY": 110,
"freeze": -1,
"soundMap": [
{
"frame": 0,
"sound":"hit_crit"
}
]
},
{
"name": "hit_effect_heal",
"path": "res/battle_anim/hit_effect_heal.png",
Expand Down
1 change: 1 addition & 0 deletions res/weapons.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Mend Staff 1 20 100 0 10 1000 - - -
Recover Staff 1 99 100 0 7 2250 - - -
Physic Staff 1-Mag/2 10 100 0 4 7500 - - -
# Debug items
Blessed Bow Bow 2 5 70 0 18 1550 Flier - -
Debug Sword Sword 1 10 100 200 20 1000 - - -
Debug Axe Axe 1 10 100 200 20 1000 - - -
Debug Bow Bow 1-3 10 100 0 1 1000 - - -
Expand Down
6 changes: 5 additions & 1 deletion src/net/fe/FEMultiplayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import net.fe.overworldStage.objective.Seize;
import net.fe.rng.SimpleRNG;
import net.fe.rng.TrueHitRNG;
import net.fe.unit.HealingItem;
import net.fe.unit.SkillChargingItem;
import net.fe.unit.Unit;
import net.fe.unit.UnitFactory;
import net.fe.unit.UnitIdentifier;
Expand Down Expand Up @@ -209,7 +211,7 @@ public void testFightStage(){

// ^------- put all pre-calc stuff here

CombatCalculator calc = new CombatCalculator(new UnitIdentifier(u1), new UnitIdentifier(u2), FEMultiplayer::getUnit, new TrueHitRNG(), new SimpleRNG(), new SimpleRNG());
CombatCalculator calc = new CombatCalculator(new UnitIdentifier(u1), new UnitIdentifier(u2), java.util.Collections.emptyList(), FEMultiplayer::getUnit, new TrueHitRNG(), new SimpleRNG(), new SimpleRNG());
System.out.println(calc.getAttackQueue());


Expand Down Expand Up @@ -239,6 +241,8 @@ public void testOverworldStage() {

Unit u1 = UnitFactory.getUnit("Natasha");
u1.addToInventory(WeaponFactory.getWeapon("Physic"));
u1.addToInventory(SkillChargingItem.INC10);
u1.addToInventory(HealingItem.VULNERARY);
u1.setHp(1);
localPlayer.getParty().addUnit(u1);

Expand Down
2 changes: 1 addition & 1 deletion src/net/fe/fightStage/Aether.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Aether(){
* @see net.fe.fightStage.CombatTrigger#attempt(net.fe.unit.Unit, int)
*/
@Override
public boolean attempt(Unit user, int range, Unit opponent, RNG rng) {
public boolean attempt(Unit user, boolean initiator, int range, Unit opponent, RNG rng) {
//return true;
return range == 1 && (rng.test(user.getStats().skl/2) || phase != SOL);
}
Expand Down
2 changes: 1 addition & 1 deletion src/net/fe/fightStage/Astra.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public Astra(){
* @see net.fe.fightStage.CombatTrigger#attempt(net.fe.unit.Unit, int)
*/
@Override
public boolean attempt(Unit user, int range, Unit opponent, RNG rng) {
public boolean attempt(Unit user, boolean initiator, int range, Unit opponent, RNG rng) {
//return true;
return range == 1 && rng.test(user.getStats().skl/2) || counter != 0;
}
Expand Down
13 changes: 11 additions & 2 deletions src/net/fe/fightStage/AttackRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public class AttackRecord implements Serializable {

/** The Constant serialVersionUID. */
private static final long serialVersionUID = 2227786706936956528L;
private static final long serialVersionUID = -203200690242377586L;

/** The animation. */
public String animation;
Expand All @@ -25,11 +25,20 @@ public class AttackRecord implements Serializable {
/** The drain. */
public int drain;

/** The skillCharge gained by the defender */
public int defenderSkillCharge;

/** The skillCharge gained by the attacker */
public int attackerSkillCharge;

/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString(){
return animation + ": " + attacker.name + ", " + defender.name + ", "
+ damage + ", " + drain + " (drain)";
+ damage + ", " + drain + " (drain), "
+ defenderSkillCharge + " (defenderSkillCharge), "
+ attackerSkillCharge + " (attackerSkillCharge), "
;
}
}
2 changes: 1 addition & 1 deletion src/net/fe/fightStage/Brave.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public Brave(){
* @see net.fe.fightStage.CombatTrigger#attempt(net.fe.unit.Unit, int)
*/
@Override
public boolean attempt(Unit user, int range, Unit opponent, RNG rng) {
public boolean attempt(Unit user, boolean initiator, int range, Unit opponent, RNG rng) {
return true;
}

Expand Down
55 changes: 55 additions & 0 deletions src/net/fe/fightStage/ChargeSkillConstant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package net.fe.fightStage;

import net.fe.rng.RNG;
import net.fe.unit.Unit;

/**
* Increase skill charge by a constant amount each round of combat
*
* Effect: Increments skillCharge when the user participates in a round of battle
* The amount incremented is .
* Trigger: Always
*/
public final class ChargeSkillConstant extends CombatTrigger {
private static final long serialVersionUID = 1L;

private static final int value = 5;

/**
*/
public ChargeSkillConstant() {
super(NO_NAME_MOD, 0);
}

@Override
public boolean attempt(Unit user, boolean initiator, int range, Unit opponent, RNG rng) {
return true;
}

@Override
public int runEnemyTurnSkillCharge(int damage) {
return value;
}

@Override
public int runYourTurnSkillCharge() {
return value;
}

@Override
public CombatTrigger getCopy(){
return new ChargeSkillConstant();
}

protected boolean canEquals(Object other) {
return other instanceof ChargeSkillConstant;
}
@Override
public boolean equals(Object other) {
return super.equals(other) &&
other instanceof ChargeSkillConstant &&
((ChargeSkillConstant) other).canEquals(this);
}
@Override public int hashCode() { return "ChargeSkillConstant".hashCode() + value; }
@Override public String toString() { return "ChargeSkillConstant[" + value + "]"; }
}
54 changes: 54 additions & 0 deletions src/net/fe/fightStage/ChargeSkillFromDamageRecieved.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package net.fe.fightStage;

import net.fe.rng.RNG;
import net.fe.unit.Unit;

/**
* Increase skill charge when the user takes damage
*
* Effect: Increments skillCharge when the user takes damage.
* The amount incremented is the damage received times a parameter.
* Trigger: Always
*/
public final class ChargeSkillFromDamageRecieved extends CombatTrigger {
private static final long serialVersionUID = 1L;

private final int multiplier;

/**
* @param multiplier the skill charge increment multiplier
*/
public ChargeSkillFromDamageRecieved(int multiplier) {
super(NO_NAME_MOD, 0);
this.multiplier = multiplier;
}

@Override
public boolean attempt(Unit user, boolean initiator, int range, Unit opponent, RNG rng) {
return true;
}

@Override
public int runEnemyTurnSkillCharge(int damage) {
return damage * multiplier;
}

@Override
public CombatTrigger getCopy(){
return new ChargeSkillFromDamageRecieved(multiplier);
}


protected boolean canEquals(Object other) {
return other instanceof ChargeSkillFromDamageRecieved;
}
@Override
public boolean equals(Object other) {
return super.equals(other) &&
other instanceof ChargeSkillFromDamageRecieved &&
((ChargeSkillFromDamageRecieved) other).canEquals(this) &&
((ChargeSkillFromDamageRecieved) other).multiplier == this.multiplier;
}
@Override public int hashCode() { return "ChargeSkillFromDamageRecieved".hashCode() + multiplier; }
@Override public String toString() { return "ChargeSkillFromDamageRecieved[" + multiplier + "]"; }
}
2 changes: 1 addition & 1 deletion src/net/fe/fightStage/Colossus.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public Colossus(){
* @see net.fe.fightStage.CombatTrigger#attempt(net.fe.unit.Unit, int)
*/
@Override
public boolean attempt(Unit user, int range, Unit opponent, RNG rng) {
public boolean attempt(Unit user, boolean initiator, int range, Unit opponent, RNG rng) {
return range == 1 && rng.test(user.getStats().skl/2);
}

Expand Down
51 changes: 42 additions & 9 deletions src/net/fe/fightStage/CombatCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public class CombatCalculator {
/** The attack triggers, weapon and unit skills */
private ArrayList<CombatTrigger> leftTriggers, rightTriggers;

/** the combat triggers added to left temporarily by a field skill activation */
private final Iterable<CombatTrigger> leftManualTriggers;

private RNG hitRNG;
private RNG critRNG;
private RNG skillRNG;
Expand All @@ -63,12 +66,19 @@ public class CombatCalculator {
* @param u1 the unit id of fighter 1
* @param u2 the unit id of fighter 2
* @param dereference A function that converts a UnitIdentifier into a Unit
* @param u1ManualTriggers the combat triggers added to u1 temporarily by a field skill activation
*/
public CombatCalculator(UnitIdentifier u1, UnitIdentifier u2, Function<UnitIdentifier, Unit> dereference, RNG hitRNG, RNG critRNG, RNG skillRNG){
public CombatCalculator(
UnitIdentifier u1, UnitIdentifier u2,
Iterable<CombatTrigger> u1ManualTriggers,
Function<UnitIdentifier, Unit> dereference,
RNG hitRNG, RNG critRNG, RNG skillRNG
){

this.hitRNG = hitRNG;
this.critRNG = critRNG;
this.skillRNG = skillRNG;
this.leftManualTriggers = u1ManualTriggers;

left = dereference.apply(u1);
right = dereference.apply(u2);
Expand Down Expand Up @@ -118,6 +128,9 @@ && shouldAttack(right,left,rightWeap,range)) {
for(CombatTrigger t: left.getTriggers()){
leftTriggers.add(t.getCopy());
}
for (CombatTrigger t: leftManualTriggers) {
leftTriggers.add(t.getCopy());
}

rightTriggers = new ArrayList<CombatTrigger>();
for(CombatTrigger t: right.getTriggers()){
Expand Down Expand Up @@ -195,6 +208,8 @@ private void attack(boolean leftAttacking, String currentEffect, Weapon leftWeap

int damage = 0;
int drain = 0;
int defenderSkillCharge = 0;
int attackerSkillCharge = 0;
String animation = "Attack";
boolean miss = false;
boolean use = false;
Expand All @@ -207,9 +222,9 @@ private void attack(boolean leftAttacking, String currentEffect, Weapon leftWeap
LinkedHashMap<CombatTrigger, Boolean> dSuccess = new LinkedHashMap<CombatTrigger, Boolean>();

for (CombatTrigger t : aTriggers)
aSuccess.put(t, t.attempt(a, range, d, skillRNG));
aSuccess.put(t, t.attempt(a, leftAttacking, range, d, skillRNG));
for (CombatTrigger t : dTriggers)
dSuccess.put(t, t.attempt(d, range, a, skillRNG));
dSuccess.put(t, t.attempt(d, !leftAttacking, range, a, skillRNG));



Expand Down Expand Up @@ -279,16 +294,30 @@ private void attack(boolean leftAttacking, String currentEffect, Weapon leftWeap
}
}

for (CombatTrigger t : aSuccess.keySet()) {
if(aSuccess.get(t)){
attackerSkillCharge += t.runYourTurnSkillCharge();
}
}

if(miss){
damage = 0;
drain = 0;
animation += " Miss";
}

for (CombatTrigger t : dSuccess.keySet()) {
if(dSuccess.get(t)){
defenderSkillCharge += t.runEnemyTurnSkillCharge(damage);
}
}

damage = Math.max(0, Math.min(damage, d.getHp()));
addToAttackQueue(a, d, animation, damage, drain);
addToAttackQueue(a, d, animation, damage, drain, defenderSkillCharge, attackerSkillCharge);
d.setHp(d.getHp() - damage);
a.setHp(a.getHp() + drain);
d.incrementSkillCharge(defenderSkillCharge);
a.incrementSkillCharge(attackerSkillCharge);
if(use)
a.use(a.getWeapon());
a.clearTempMods();
Expand All @@ -314,14 +343,18 @@ private void attack(boolean leftAttacking, String currentEffect, Weapon leftWeap
* @param animation the animation
* @param damage the damage
* @param drain the damage healed
* @param defenderSkillCharge the amount the defender's skillCharge increases by
* @param attackerSkillCharge the amount the attacker's skillCharge decreases by
*/
public void addToAttackQueue(Unit a, Unit d, String animation, int damage, int drain) {
public void addToAttackQueue(Unit a, Unit d, String animation, int damage, int drain, int defenderSkillCharge, int attackerSkillCharge) {
AttackRecord rec = new AttackRecord();
rec.attacker = new UnitIdentifier(a);
rec.defender = new UnitIdentifier(d);
rec.animation = animation;
rec.damage = damage;
rec.drain = drain;
rec.defenderSkillCharge = defenderSkillCharge;
rec.attackerSkillCharge = attackerSkillCharge;
attackQueue.add(rec);

logger.fine(rec.toString());
Expand Down Expand Up @@ -385,25 +418,25 @@ public static MainBattleStats calculatePreviewStats(Unit a, Unit d, boolean shou
// run preAttack triggers that are allowed to be shown in the preview
for (CombatTrigger t : a.getTriggers())
if (((t.turnToRun & CombatTrigger.SHOW_IN_PREVIEW) != 0) && ((t.turnToRun & CombatTrigger.YOUR_TURN_PRE) != 0))
if (t.attempt(a, -1, d, new net.fe.rng.NullRNG()))
if (t.attempt(a, true, -1, d, new net.fe.rng.NullRNG()))
t.runPreAttack(null, a, d);

for (CombatTrigger t : d.getTriggers())
if (((t.turnToRun & CombatTrigger.SHOW_IN_PREVIEW) != 0) && ((t.turnToRun & CombatTrigger.ENEMY_TURN_PRE) != 0))
if (t.attempt(a, -1, d, new net.fe.rng.NullRNG()))
if (t.attempt(a, false, -1, d, new net.fe.rng.NullRNG()))
t.runPreAttack(null, a, d);

int damage = CombatCalculator.calculateBaseDamage(a, d);

// Run combat mods that are allowed to occur in the preview
for (CombatTrigger t : a.getTriggers())
if (((t.turnToRun & CombatTrigger.SHOW_IN_PREVIEW) != 0) && ((t.turnToRun & CombatTrigger.YOUR_TURN_MOD) != 0))
if (t.attempt(a, -1, d, new net.fe.rng.NullRNG()))
if (t.attempt(a, true, -1, d, new net.fe.rng.NullRNG()))
damage = t.runDamageMod(a, d, damage);

for (CombatTrigger t : d.getTriggers())
if (((t.turnToRun & CombatTrigger.SHOW_IN_PREVIEW) != 0) && ((t.turnToRun & CombatTrigger.ENEMY_TURN_MOD) != 0))
if (t.attempt(a, -1, d, new net.fe.rng.NullRNG()))
if (t.attempt(a, false, -1, d, new net.fe.rng.NullRNG()))
damage = t.runDamageMod(a, d, damage);

damage = limit(0, 100, damage);
Expand Down
Loading