Skip to content

Commit

Permalink
Roll damage through API and add apply buttons. Resolves #60
Browse files Browse the repository at this point in the history
  • Loading branch information
Bathtor committed Aug 12, 2018
1 parent 59a0765 commit 62d418d
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 135 deletions.
2 changes: 1 addition & 1 deletion model/epmodel.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name := "EP Model Root"

organization in ThisBuild := "com.lkroll.ep"

version in ThisBuild := "1.9.2"
version in ThisBuild := "1.9.3"

scalaVersion in ThisBuild := "2.12.6"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ object EPTranslation extends SheetI18N {
val rollAutoFailure = text("roll-auto-failure");
val mos = abbr("mos", "margin-of-success");
val mof = abbr("mof", "margin-of-failure");
val apiHead = text("api-head");
val applyDamage = text("apply-damage");
val applyCritDamage = text("apply-crit-damage");

val traitTypeOptions = {
val opts = TraitType.values.map(v => (v -> v.toString)).toMap;
Expand Down
4 changes: 2 additions & 2 deletions script/epapiscript.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ name := "EP API Script"

organization := "com.lkroll.ep"

version := "0.7.6"
version := "0.7.7"

scalaVersion := "2.12.6"

libraryDependencies += "com.lkroll.roll20" %%% "roll20-api-framework" % "0.8.+"
libraryDependencies += "com.lkroll.ep" %%% "epcompendium-core" % "3.0.0"
libraryDependencies += "com.lkroll.ep" %%% "ep-model" % "1.9.2"
libraryDependencies += "com.lkroll.ep" %%% "ep-model" % "1.9.3"
libraryDependencies += "com.lihaoyi" %%% "fastparse" % "1.+"
libraryDependencies += "org.rogach" %%% "scallop" % "3.1.+"
libraryDependencies += "org.scalactic" %%% "scalactic" % "3.0.4" % "test"
Expand Down
188 changes: 99 additions & 89 deletions script/src/main/scala/com/lkroll/ep/api/CharTools.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CharToolsConf(args: Seq[String]) extends ScallopAPIConf(args) {
val damage = opt[Int]("damage", descr = "Add damage to characters, calculating wounds as well.");
val stress = opt[Int]("stress", descr = "Add stress to characters, calculating traumas as well.");

val armourPenetration = opt[Int]("ap", descr = "Subtract Armour Penetration from selected armour.", default = Some(0));
val armourPenetration = opt[Int]("ap", descr = "Subtract Armour Penetration from selected armour. Will always be interpreted as a negative number.", default = Some(0)).map(i => Math.abs(i));
val armour = opt[String](
"armour",
descr = s"Reduce damage by character's armor value of the given type. Options are ${DamageType.values.mkString(", ")} or None").
Expand All @@ -39,6 +39,8 @@ class CharToolsConf(args: Seq[String]) extends ScallopAPIConf(args) {

object CharToolsCommand extends APICommand[CharToolsConf] {
import APIImplicits._;
lazy val minConf = new CharToolsConf(Seq("--damage", "0"));

override def command = "epchar";
override def options = (args) => new CharToolsConf(args);
override def apply(config: CharToolsConf, ctx: ChatContext): Unit = {
Expand Down Expand Up @@ -77,106 +79,114 @@ object CharToolsCommand extends APICommand[CharToolsConf] {

def applyStress(config: CharToolsConf, ctx: ChatContext, char: Roll20Char): String = {
var msg = "";
val stressField = char.attribute(epmodel.stress);
val stress = config.stress();
val curStress = stressField();
val luc = char.attribute(epmodel.lucidity)();
val ir = char.attribute(epmodel.insanityRating)();
val tt = char.attribute(epmodel.traumaThreshold)();
val stressTotal = stress + curStress;
stressField <<= stressTotal;
msg += s"<p>Took <em>$stress</em>SV.<p/>";

val (traumas, newTraumas) = if (stress >= tt) {
val newTraumas = stress / tt;
val traumaField = char.attribute(epmodel.trauma);
val curTraumas = traumaField();
val newCurTraumas = curTraumas + newTraumas;
traumaField.setWithWorker(newCurTraumas);
msg += s"<p>Took <em>$newTraumas</em> traumas.</p>";
(newCurTraumas, newTraumas)
} else (0, 0);

if (stressTotal >= ir) {
msg += s"<p>Is now permanently insane.</p>";
} else if (stressTotal >= luc) {
msg += s"<p>Is now catatonic until stress is reduced below <em>${luc}</em>.</p>";
} else {
if (newTraumas >= 1) {
msg += s"<p>Must ${char.rollButton("Resist Disorientation", "willx3-roll")} or be forced to expend a Complex Action to regain their wits.</p>";
if (traumas >= 4) {
msg += s"<p>Acquires <em>${newTraumas}</em> new minor derangements or upgrades an equivalent number of existing derangements, potentially to a disorder.</p>";
} else {
msg += s"<p>Acquires <em>${newTraumas}</em> new minor derangements or upgrades an equivalent number of existing derangements.</p>";
try {
val stressField = char.attribute(epmodel.stress);
val stress = config.stress();
val curStress = stressField.getOrDefault;
val luc = char.attribute(epmodel.lucidity).getOrDefault;
val ir = char.attribute(epmodel.insanityRating).getOrDefault;
val tt = char.attribute(epmodel.traumaThreshold).getOrDefault;
val stressTotal = stress + curStress;
stressField <<= stressTotal;
msg += s"<p>Took <em>$stress</em>SV.<p/>";

val (traumas, newTraumas) = if (stress >= tt) {
val newTraumas = stress / tt;
val traumaField = char.attribute(epmodel.trauma);
val curTraumas = traumaField.getOrDefault;
val newCurTraumas = curTraumas + newTraumas;
traumaField.setWithWorker(newCurTraumas);
msg += s"<p>Took <em>$newTraumas</em> traumas.</p>";
(newCurTraumas, newTraumas)
} else (0, 0);

if (stressTotal >= ir) {
msg += s"<p>Is now permanently insane.</p>";
} else if (stressTotal >= luc) {
msg += s"<p>Is now catatonic until stress is reduced below <em>${luc}</em>.</p>";
} else {
if (newTraumas >= 1) {
msg += s"<p>Must ${char.rollButton("Resist Disorientation", "willx3-roll")} or be forced to expend a Complex Action to regain their wits.</p>";
if (traumas >= 4) {
msg += s"<p>Acquires <em>${newTraumas}</em> new minor derangements or upgrades an equivalent number of existing derangements, potentially to a disorder.</p>";
} else {
msg += s"<p>Acquires <em>${newTraumas}</em> new minor derangements or upgrades an equivalent number of existing derangements.</p>";
}
}
}
} catch {
case e: java.util.NoSuchElementException => { error(e); msg += "An error occurred accessing a field." }
}
msg
}

def applyDamage(config: CharToolsConf, ctx: ChatContext, char: Roll20Char): String = {
var msg = "";
val damageField = char.attribute(epmodel.damage);
val incomingDamage = config.damage();
val curDamage = damageField();
val dur = char.attribute(epmodel.durability)();
val dr = char.attribute(epmodel.deathRating)();
val wt = char.attribute(epmodel.woundThreshold)();
val damageApplied: Int = if (config.armour.isSupplied) {
val ap = config.armourPenetration();
config.armour() match {
case Some(DamageType.Kinetic) => {
val kineticArmour = char.attribute(epmodel.armourKineticTotal)();
val armourApplied = Math.max(kineticArmour - ap, 0);
Math.max(0, incomingDamage - armourApplied)
}
case Some(DamageType.Energy) => {
val energyArmour = char.attribute(epmodel.armourEnergyTotal)();
val armourApplied = Math.max(energyArmour - ap, 0);
Math.max(0, incomingDamage - armourApplied)
try {
val damageField = char.attribute(epmodel.damage);
val incomingDamage = config.damage();
val curDamage = damageField.getOrDefault;
val dur = char.attribute(epmodel.durability).getOrDefault;
val dr = char.attribute(epmodel.deathRating).getOrDefault;
val wt = char.attribute(epmodel.woundThreshold).getOrDefault;
val damageApplied: Int = if (config.armour.isSupplied) {
val ap = config.armourPenetration();
config.armour() match {
case Some(DamageType.Kinetic) => {
val kineticArmour = char.attribute(epmodel.armourKineticTotal).getOrDefault;
val armourApplied = Math.max(kineticArmour - ap, 0);
Math.max(0, incomingDamage - armourApplied)
}
case Some(DamageType.Energy) => {
val energyArmour = char.attribute(epmodel.armourEnergyTotal).getOrDefault;
val armourApplied = Math.max(energyArmour - ap, 0);
Math.max(0, incomingDamage - armourApplied)
}
case Some(DamageType.Untyped) | None => incomingDamage
case _ => ??? // should be exhaustive
}
case Some(DamageType.Untyped) | None => incomingDamage
case _ => ??? // should be exhaustive
}
} else {
incomingDamage
};
val damageTotal = curDamage + damageApplied;
damageField <<= damageTotal;
msg += s"<p>Took <em>$damageApplied</em>DV.<p/>";
val (wounds, newWounds) = if (damageApplied >= wt) {
val newWounds = damageApplied / wt;
val woundsField = char.attribute(epmodel.wounds);
val curWounds = woundsField();
val newCurWounds = curWounds + newWounds;
woundsField.setWithWorker(newCurWounds);
msg += s"<p>Took <em>$newWounds</em> wounds.</p>";
(newCurWounds, newWounds)
} else (0, 0);
val isBiomorph = MorphType.withName(char.attribute(epmodel.morphType)()) match {
case MorphType.Biomorph | MorphType.Pod => true
case _ => false
};
if (damageTotal >= dr) {
if (isBiomorph) {
msg += s"<p>Morph is now beyond healing.</p>";
} else {
msg += s"<p>Morph is now beyond repair.</p>";
}
} else if (damageTotal >= dur && wounds > 0 && isBiomorph) {
msg += s"<p>Is now unconscious and bleeding out (1DV per Action Turn).</p>";
} else if (damageTotal >= dur) {
if (isBiomorph) {
msg += s"<p>Is now unconscious.</p>";
incomingDamage
};
val damageTotal = curDamage + damageApplied;
damageField <<= damageTotal;
msg += s"<p>Took <em>$damageApplied</em>DV.<p/>";
val (wounds, newWounds) = if (damageApplied >= wt) {
val newWounds = damageApplied / wt;
val woundsField = char.attribute(epmodel.wounds);
val curWounds = woundsField();
val newCurWounds = curWounds + newWounds;
woundsField.setWithWorker(newCurWounds);
msg += s"<p>Took <em>$newWounds</em> wounds.</p>";
(newCurWounds, newWounds)
} else (0, 0);
val isBiomorph = MorphType.withName(char.attribute(epmodel.morphType)()) match {
case MorphType.Biomorph | MorphType.Pod => true
case _ => false
};
if (damageTotal >= dr) {
if (isBiomorph) {
msg += s"<p>Morph is now beyond healing.</p>";
} else {
msg += s"<p>Morph is now beyond repair.</p>";
}
} else if (damageTotal >= dur && wounds > 0 && isBiomorph) {
msg += s"<p>Is now unconscious and bleeding out (1DV per Action Turn).</p>";
} else if (damageTotal >= dur) {
if (isBiomorph) {
msg += s"<p>Is now unconscious.</p>";
} else {
msg += s"<p>Is now incapacitated.</p>";
}
} else {
msg += s"<p>Is now incapacitated.</p>";
}
} else {
if (newWounds == 1) {
msg += s"<p>Must ${char.rollButton("Resist Knockdown", "somx3-roll")} or fall prone.</p>";
} else if (newWounds >= 2) {
msg += s"<p>Must ${char.rollButton("Resist Unconsciousness", "somx3-roll")} or pass out until awoken or healed.</p>";
if (newWounds == 1) {
msg += s"<p>Must ${char.rollButton("Resist Knockdown", "somx3-roll")} or fall prone.</p>";
} else if (newWounds >= 2) {
msg += s"<p>Must ${char.rollButton("Resist Unconsciousness", "somx3-roll")} or pass out until awoken or healed.</p>";
}
}
} catch {
case e: java.util.NoSuchElementException => { error(e); msg += "An error occurred accessing a field." }
}
msg
}
Expand Down
Loading

0 comments on commit 62d418d

Please sign in to comment.