Skip to content

Commit

Permalink
Added SOM-based ranges and effect area to ranged weapons. Resolves #58
Browse files Browse the repository at this point in the history
  • Loading branch information
Bathtor committed Aug 12, 2018
1 parent 62d418d commit b733b20
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 44 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.3"
version in ThisBuild := "1.10.0"

scalaVersion in ThisBuild := "2.12.6"

Expand Down
12 changes: 12 additions & 0 deletions model/shared/src/main/scala/com/lkroll/ep/model/DamageType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,15 @@ object DamageType extends Enumeration {
def dynamicLabel(v: Value): String = s"${labelPrefix}-${v.toString()}";
def dynamicLabelShort(v: Value): String = s"${labelShortPrefix}-${v.toString()}";
}

object DamageArea extends Enumeration {
type DamageArea = Value;

val Point, Blast, UniformBlast, Cone = Value;

val labelPrefix = "damage-areaopt";
val labelShortPrefix = "damage-areaopt-short";

def dynamicLabel(v: Value): String = s"${labelPrefix}-${v.toString()}";
def dynamicLabelShort(v: Value): String = s"${labelShortPrefix}-${v.toString()}";
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,16 @@ object EPTranslation extends SheetI18N {
val burstFireDescription = text("burst-fire-description");
val fullAutomaticDescription = text("full-automatic-description");
val weaponRanges = text("weapon-ranges");
val thrown = text("thrown");
val shortRange = abbr("s-range", "short-range");
val mediumRange = abbr("m-range", "medium-range");
val longRange = abbr("l-range", "long-range");
val extremeRange = abbr("x-range", "extreme-range");
val magazine = text("magazine");
val size = text("size");
val ammoType = text("ammo-type");
val damageArea = text("damage-area");
val uniformRadius = text("uniform-radius");
val damageInflicts = text("damage-inflicts");
val damageValue = abbr("dv", "damage-value");
val concentrateFire = text("concentrate-fire");
Expand Down Expand Up @@ -381,6 +384,14 @@ object EPTranslation extends SheetI18N {
val opts = DamageType.values.map(v => (v -> v.toString)).toMap;
enum[DamageType.type](DamageType.labelShortPrefix, opts)
}
val dmgArea = {
val opts = DamageArea.values.map(v => (v -> v.toString)).toMap;
enum[DamageArea.type](DamageArea.labelPrefix, opts)
}
val dmgAreaShort = {
val opts = DamageArea.values.map(v => (v -> v.toString)).toMap;
enum[DamageArea.type](DamageArea.labelShortPrefix, opts)
}
val psiType = {
val opts = PsiType.values.map(v => (v -> v.toString)).toMap;
enum[PsiType.type](PsiType.labelPrefix, opts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,26 @@ object RangedWeaponSection extends RepeatingSection {
val semiAutomatic = "semi_automatic".default(false);
val burstFire = "burst_fire".default(false);
val fullAutomatic = "full_automatic".default(false);
val thrown = flag("thrown").default(false);
val rangeUnitSymbol = "range_unit_symbol".editable(false).default("m");
val shortRangeLower = "short_range_lower".default(2).editable(false);
val shortRangeUpper = "short_range_upper".default(0).validIn(0, 99999, 1);
val shortRangeUpperInput = "short_range_upper_input".default(0.0).validIn(0.0, 99999.0, 0.1);
val shortRangeUpper = "short_range_upper".default(0).editable(false);
val mediumRangeLower = "medium_range_lower".default(0).editable(false);
val mediumRangeUpper = "medium_range_upper".default(0).validIn(0, 99999, 1);
val mediumRangeUpperInput = "medium_range_upper_input".default(0.0).validIn(0.0, 99999.0, 0.1);
val mediumRangeUpper = "medium_range_upper".default(0).editable(false);
val longRangeLower = "long_range_lower".default(0).editable(false);
val longRangeUpper = "long_range_upper".default(0).validIn(0, 99999, 1);
val longRangeUpperInput = "long_range_upper_input".default(0.0).validIn(0.0, 99999.0, 0.1);
val longRangeUpper = "long_range_upper".default(0).editable(false);
val extremeRangeLower = "extreme_range_lower".default(0).editable(false);
val extremeRangeUpper = "extreme_range_upper".default(0).validIn(0, 99999, 1);
val extremeRangeUpperInput = "extreme_range_upper_input".default(0.0).validIn(0.0, 99999.0, 0.1);
val extremeRangeUpper = "extreme_range_upper".default(0).editable(false);
val magazineSize = "ammo_max".default(0).validIn(0, 999, 1);
val magazineCurrent = "ammo".default(0).validIn(0, 999, 1);
val magazineType = "ammo_type".default("standard");
val damageArea = "damage_area".options(DamageArea).default(DamageArea.Point);
val damageAreaShort = text("damage_area_short").editable(false).default(DamageArea.dynamicLabelShort(DamageArea.Point));
val uniformBlastArea = "uniform_blast_area".default(1).validIn(0, 99999, 1);
val showDescription = flag("show_description").default(false);
val description = text("description");
}
Expand Down
6 changes: 3 additions & 3 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.7"
version := "0.8.0"

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.3"
libraryDependencies += "com.lkroll.ep" %%% "epcompendium-core" % "3.0.1"
libraryDependencies += "com.lkroll.ep" %%% "ep-model" % "1.10.0"
libraryDependencies += "com.lihaoyi" %%% "fastparse" % "1.+"
libraryDependencies += "org.rogach" %%% "scallop" % "3.1.+"
libraryDependencies += "org.scalactic" %%% "scalactic" % "3.0.4" % "test"
Expand Down
116 changes: 92 additions & 24 deletions script/src/main/scala/com/lkroll/ep/api/compendium/WeaponImport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ package com.lkroll.ep.api.compendium
import com.lkroll.roll20.core._
import com.lkroll.roll20.api._
import com.lkroll.ep.compendium._
import com.lkroll.ep.model.{ EPCharModel => epmodel, MeleeWeaponSection, RangedWeaponSection, DamageType => ModelDamageType }
import com.lkroll.ep.model.{ EPCharModel => epmodel, MeleeWeaponSection, RangedWeaponSection, DamageType => ModelDamageType, DamageArea => ModelDamageArea }
import APIImplicits._;
//import scala.util.{ Try, Success, Failure }

object WeaponDamageTypeConverter {
def convert(dt: DamageType): Either[ModelDamageType.DamageType, String] = {
Expand All @@ -41,6 +42,17 @@ object WeaponDamageTypeConverter {
}
}

object WeaponDamageAreaConverter {
def convert(da: DamageArea): Either[ModelDamageArea.DamageArea, String] = {
da match {
case DamageArea.Point => Left(ModelDamageArea.Point)
case DamageArea.Blast => Left(ModelDamageArea.Blast)
case DamageArea.Cone => Left(ModelDamageArea.Cone)
case DamageArea.UniformBlast(_) => Left(ModelDamageArea.UniformBlast)
}
}
}

case class WeaponImport(weapon: Weapon) extends Importable {

override def updateLabel: String = s"weapon ${weapon.name}";
Expand All @@ -50,6 +62,10 @@ case class WeaponImport(weapon: Weapon) extends Importable {
case Left(dt) => dt
case Right(msg) => return Right(msg)
};
val damageArea = WeaponDamageAreaConverter.convert(weapon.area) match {
case Left(da) => da
case Right(msg) => return Right(msg)
}
weapon.`type` match {
case _: WeaponType.Melee => {
char.createRepeating(MeleeWeaponSection.weapon, rowId) <<= weapon.name;
Expand All @@ -75,7 +91,7 @@ case class WeaponImport(weapon: Weapon) extends Importable {
}
}
}
case _: WeaponType.Ranged => {
case _: WeaponType.Ranged | _: WeaponType.Thrown => {
char.createRepeating(RangedWeaponSection.weapon, rowId) <<= weapon.name;
char.createRepeating(RangedWeaponSection.skillSearch, rowId) <<= weapon.`type`.skill;
char.createRepeating(RangedWeaponSection.miscMod, rowId) <<= weapon.attackBonus;
Expand All @@ -88,19 +104,33 @@ case class WeaponImport(weapon: Weapon) extends Importable {
char.createRepeating(RangedWeaponSection.damageBonus, rowId) <<= weapon.damage.dmgConst;
char.createRepeating(RangedWeaponSection.damageType, rowId) <<= damageType.toString;
char.createRepeating(RangedWeaponSection.damageTypeShort, rowId) <<= ModelDamageType.dynamicLabelShort(damageType);
char.createRepeating(RangedWeaponSection.damageArea, rowId) <<= damageArea.toString;
char.createRepeating(RangedWeaponSection.damageAreaShort, rowId) <<= ModelDamageArea.dynamicLabelShort(damageArea);
weapon.area match {
case DamageArea.UniformBlast(r) => {
char.createRepeating(RangedWeaponSection.uniformBlastArea, rowId) <<= r;
}
case _ => () // leave default
}

val thrownField = char.createRepeating(RangedWeaponSection.thrown, rowId);
weapon.range match {
case Range.Melee => return Right("Ranged weapons should have range Ranged")
case _: Range.Thrown => return Right("Thrown weapons are currently not supported")
case Range.Melee => return Right("Ranged weapons should have range Ranged")
case r: Range.Thrown => {
char.createRepeating(RangedWeaponSection.shortRangeUpperInput, rowId) <<= r.shortFactor;
char.createRepeating(RangedWeaponSection.mediumRangeUpperInput, rowId) <<= r.mediumFactor;
char.createRepeating(RangedWeaponSection.longRangeUpperInput, rowId) <<= r.longFactor;
char.createRepeating(RangedWeaponSection.extremeRangeUpperInput, rowId) <<= r.extremeFactor;

thrownField.setWithWorker(true); // this will cause dependent ranged to be calculated
}
case Range.Ranged(s, m, l, x) => {
//char.createRepeating(RangedWeaponSection.shortRangeLower, rowId) <<= 2; // below this is point blank but don't write default value
char.createRepeating(RangedWeaponSection.shortRangeUpper, rowId) <<= s;
char.createRepeating(RangedWeaponSection.mediumRangeLower, rowId) <<= s + 1;
char.createRepeating(RangedWeaponSection.mediumRangeUpper, rowId) <<= m;
char.createRepeating(RangedWeaponSection.longRangeLower, rowId) <<= m + 1;
char.createRepeating(RangedWeaponSection.longRangeUpper, rowId) <<= l;
char.createRepeating(RangedWeaponSection.extremeRangeLower, rowId) <<= l + 1;
char.createRepeating(RangedWeaponSection.extremeRangeUpper, rowId) <<= x;
char.createRepeating(RangedWeaponSection.shortRangeUpperInput, rowId) <<= s;
char.createRepeating(RangedWeaponSection.mediumRangeUpperInput, rowId) <<= m;
char.createRepeating(RangedWeaponSection.longRangeUpperInput, rowId) <<= l;
char.createRepeating(RangedWeaponSection.extremeRangeUpperInput, rowId) <<= x;

thrownField.setWithWorker(false); // this will cause dependent ranged to be calculated
}
}

Expand All @@ -115,7 +145,17 @@ case class WeaponImport(weapon: Weapon) extends Importable {
magazine <<= magazineSize;
magazine.max = magazineSize.toString(); // TODO make max handling nicer
}
case None => APILogger.warn(s"Weapon ${weapon.name} does not seems to be gun, despite being of ranged type.")
case None => {
char.createRepeating(RangedWeaponSection.singleShot, rowId) <<= true;
char.createRepeating(RangedWeaponSection.semiAutomatic, rowId) <<= false;
char.createRepeating(RangedWeaponSection.burstFire, rowId) <<= false;
char.createRepeating(RangedWeaponSection.fullAutomatic, rowId) <<= false;

val magazine = char.createRepeating(RangedWeaponSection.magazineCurrent, rowId);
magazine <<= 1;
magazine.max = "1"; // TODO make max handling nicer
char.createRepeating(RangedWeaponSection.magazineType, rowId) <<= "NA";
}
}

char.createRepeating(RangedWeaponSection.description, rowId) <<= weapon.descr;
Expand Down Expand Up @@ -144,6 +184,10 @@ case class WeaponWithAmmoImport(weapon: WeaponWithAmmo) extends Importable {
case Left(dt) => dt
case Right(msg) => return Right(msg)
};
val damageArea = WeaponDamageAreaConverter.convert(weapon.area) match {
case Left(da) => da
case Right(msg) => return Right(msg)
}
weapon.weapon.`type` match {
case _: WeaponType.Melee => {
char.createRepeating(MeleeWeaponSection.weapon, rowId) <<= weapon.name;
Expand Down Expand Up @@ -182,19 +226,33 @@ case class WeaponWithAmmoImport(weapon: WeaponWithAmmo) extends Importable {
char.createRepeating(RangedWeaponSection.damageBonus, rowId) <<= weapon.damage.dmgConst;
char.createRepeating(RangedWeaponSection.damageType, rowId) <<= damageType.toString;
char.createRepeating(RangedWeaponSection.damageTypeShort, rowId) <<= ModelDamageType.dynamicLabelShort(damageType);
char.createRepeating(RangedWeaponSection.damageArea, rowId) <<= damageArea.toString;
char.createRepeating(RangedWeaponSection.damageAreaShort, rowId) <<= ModelDamageArea.dynamicLabelShort(damageArea);
weapon.area match {
case DamageArea.UniformBlast(r) => {
char.createRepeating(RangedWeaponSection.uniformBlastArea, rowId) <<= r;
}
case _ => () // leave default
}

val thrownField = char.createRepeating(RangedWeaponSection.thrown, rowId);
weapon.weapon.range match {
case Range.Melee => return Right("Ranged weapons should have range Ranged")
case _: Range.Thrown => return Right("Thrown weapons are currently not supported")
case Range.Melee => return Right("Ranged weapons should have range Ranged")
case r: Range.Thrown => {
char.createRepeating(RangedWeaponSection.shortRangeUpperInput, rowId) <<= r.shortFactor;
char.createRepeating(RangedWeaponSection.mediumRangeUpperInput, rowId) <<= r.mediumFactor;
char.createRepeating(RangedWeaponSection.longRangeUpperInput, rowId) <<= r.longFactor;
char.createRepeating(RangedWeaponSection.extremeRangeUpperInput, rowId) <<= r.extremeFactor;

thrownField.setWithWorker(true); // this will cause dependent ranged to be calculated
}
case Range.Ranged(s, m, l, x) => {
//char.createRepeating(RangedWeaponSection.shortRangeLower, rowId) <<= 2; // below this is point blank but don't write default value
char.createRepeating(RangedWeaponSection.shortRangeUpper, rowId) <<= s;
char.createRepeating(RangedWeaponSection.mediumRangeLower, rowId) <<= s + 1;
char.createRepeating(RangedWeaponSection.mediumRangeUpper, rowId) <<= m;
char.createRepeating(RangedWeaponSection.longRangeLower, rowId) <<= m + 1;
char.createRepeating(RangedWeaponSection.longRangeUpper, rowId) <<= l;
char.createRepeating(RangedWeaponSection.extremeRangeLower, rowId) <<= l + 1;
char.createRepeating(RangedWeaponSection.extremeRangeUpper, rowId) <<= x;
char.createRepeating(RangedWeaponSection.shortRangeUpperInput, rowId) <<= s;
char.createRepeating(RangedWeaponSection.mediumRangeUpperInput, rowId) <<= m;
char.createRepeating(RangedWeaponSection.longRangeUpperInput, rowId) <<= l;
char.createRepeating(RangedWeaponSection.extremeRangeUpperInput, rowId) <<= x;

thrownField.setWithWorker(false); // this will cause dependent ranged to be calculated
}
}

Expand All @@ -210,7 +268,17 @@ case class WeaponWithAmmoImport(weapon: WeaponWithAmmo) extends Importable {
magazine.max = magazineSize.toString(); // TODO make max handling nicer
char.createRepeating(RangedWeaponSection.magazineType, rowId) <<= weapon.ammo.name;
}
case None => APILogger.warn(s"Weapon ${weapon.name} does not seems to be gun, despite being of ranged type.")
case None => {
char.createRepeating(RangedWeaponSection.singleShot, rowId) <<= true;
char.createRepeating(RangedWeaponSection.semiAutomatic, rowId) <<= false;
char.createRepeating(RangedWeaponSection.burstFire, rowId) <<= false;
char.createRepeating(RangedWeaponSection.fullAutomatic, rowId) <<= false;

val magazine = char.createRepeating(RangedWeaponSection.magazineCurrent, rowId);
magazine <<= 1;
magazine.max = "1"; // TODO make max handling nicer
char.createRepeating(RangedWeaponSection.magazineType, rowId) <<= weapon.ammo.name;
}
}

char.createRepeating(RangedWeaponSection.description, rowId) <<= weapon.descr;
Expand Down
2 changes: 1 addition & 1 deletion sheet/epsheet.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name := "EP Sheet Root"

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

version in ThisBuild := "1.9.3"
version in ThisBuild := "1.10.0"

scalaVersion in ThisBuild := "2.12.6"

Expand Down
17 changes: 17 additions & 0 deletions sheet/js/src/main/scala/com/lkroll/ep/sheet/EPUpdates.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,21 @@ object EPUpdates extends MinorVersionUpdateManager {
val assignSMax = op(model.lucidity).update(luc => Seq(model.stressMax <<= luc));
List(speedUpdate, moaUpdate, assignSMax)
}
forVersion("1.9.0") {
val rangeUpdate = op(
RangedWeaponSection.shortRangeUpper,
RangedWeaponSection.mediumRangeUpper,
RangedWeaponSection.longRangeUpper,
RangedWeaponSection.extremeRangeUpper).update {
case (short, medium, long, extreme) => {
Seq(
RangedWeaponSection.shortRangeUpperInput <<= short.toDouble,
RangedWeaponSection.mediumRangeUpperInput <<= medium.toDouble,
RangedWeaponSection.longRangeUpperInput <<= long.toDouble,
RangedWeaponSection.extremeRangeUpperInput <<= extreme.toDouble)
}
};
val rangeUpdates = rangeUpdate.all(RangedWeaponSection);
List(rangeUpdates)
}
}
4 changes: 2 additions & 2 deletions sheet/js/src/main/scala/com/lkroll/ep/sheet/EPWorkers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,13 @@ object EPWorkers extends SheetWorkerRoot {

val savTotalCalc = bind(op(savBase, savTemp, savMorph, savMorphMax)) update (aptTotalCalc(savTotal), SkillWorkers.skillTotalCalc);

val somTotalCalc = bind(op(somBase, somTemp, somMorph, somMorphMax)) update (aptTotalCalc(somTotal), dbCalc.andThen(SkillWorkers.skillTotalCalc));
val somTotalCalc = bind(op(somBase, somTemp, somMorph, somMorphMax)) update (aptTotalCalc(somTotal), dbCalc.andThen(GearWorkers.weaponRangeLimits.all(RangedWeaponSection)).andThen(SkillWorkers.skillTotalCalc));

val wilTotalCalc = bind(op(wilBase, wilTemp, wilMorph, wilMorphMax)) update (aptTotalCalc(wilTotal), willStatsCalc.andThen(traumaThresholdCalc).andThen(SkillWorkers.skillTotalCalc));

val aptTotals = cogTotalCalc ++ List(cooTotalCalc, intTotalCalc, refTotalCalc, savTotalCalc, somTotalCalc, wilTotalCalc);

val aptTotalsAll = aptTotals ++ List(initCalc, dbCalc, willStatsCalc, traumaThresholdCalc, SkillWorkers.skillTotalCalc);
val aptTotalsAll = aptTotals ++ List(initCalc, dbCalc, willStatsCalc, traumaThresholdCalc, GearWorkers.weaponRangeLimits.all(RangedWeaponSection), SkillWorkers.skillTotalCalc);

val durStatsCalc = op(durabilityBonus, morphDurability, morphType) update {
case (bonus, morphDur, mt) => {
Expand Down
Loading

0 comments on commit b733b20

Please sign in to comment.