Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change BEAM lights and sights to accept width instead of arc #4516

Merged
merged 4 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -399,16 +399,25 @@ private static Light parseLightJson(JsonObject lightDef, LightSource.Type lightS
lightDef.has("shape")
? ShapeType.valueOf(lightDef.get("shape").getAsString())
: ShapeType.CIRCLE;
// Cones permit the fields arc and offset, but no other shape accepts them.
// Beams permit the field "width", cones permit the field "arc", and both permit "offset".
// But no other shape permits these fields.
if (shape != ShapeType.BEAM) {
if (lightDef.has("width")) {
throw new ParserException(I18N.getText("Width provided but the shape is not a beam"));
}
}
if (shape != ShapeType.CONE) {
if (lightDef.has("arc")) {
throw new ParserException(I18N.getText("Arc provided but the shape is not a cone"));
}
}
if (shape != ShapeType.CONE && shape != ShapeType.BEAM) {
if (lightDef.has("offset")) {
throw new ParserException(
I18N.getText("Facing offset provided but the shape is not a cone"));
}
if (lightDef.has("arc")) {
throw new ParserException(I18N.getText("Arc provided but the shape is not a cone"));
}
}
final var width = lightDef.has("width") ? lightDef.get("width").getAsDouble() : 0;
final var offset = lightDef.has("offset") ? lightDef.get("offset").getAsDouble() : 0;
final var arc = lightDef.has("arc") ? lightDef.get("arc").getAsDouble() : 0;

Expand Down Expand Up @@ -444,7 +453,7 @@ private static Light parseLightJson(JsonObject lightDef, LightSource.Type lightS
throw new ParserException(I18N.getText("Lumens must be non-zero."));
}

return new Light(shape, offset, range, arc, colorPaint, lumens, gmOnly, ownerOnly);
return new Light(shape, offset, range, width, arc, colorPaint, lumens, gmOnly, ownerOnly);
}

private static JsonObject lightSourceToJson(LightSource source) {
Expand All @@ -467,7 +476,7 @@ private static JsonObject lightToJson(LightSource source, Light light) {

if (light.getShape() == ShapeType.BEAM) {
lightDef.addProperty("offset", light.getFacingOffset());
lightDef.addProperty("arc", light.getArcAngle());
lightDef.addProperty("width", light.getWidth());
}

if (light.getShape() == ShapeType.CONE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import net.rptools.maptool.model.Light;
import net.rptools.maptool.model.LightSource;
import net.rptools.maptool.model.LookupTable;
import net.rptools.maptool.model.ShapeType;
import net.rptools.maptool.model.SightType;
import net.rptools.maptool.model.Token;
import net.rptools.maptool.model.Zone;
Expand Down Expand Up @@ -377,7 +378,7 @@ private JsonObject getCampaignInfo() throws ParserException {
JsonObject linfo = new JsonObject();
linfo.addProperty("name", ls.getName());
linfo.addProperty("max range", ls.getMaxRange());
linfo.addProperty("type", ls.getType().toString());
linfo.addProperty("type", ls.getType().name());
linfo.addProperty("scale", ls.isScaleWithToken());
// List<Light> lights = new ArrayList<Light>();
// for (Light light : ls.getLightList()) {
Expand Down Expand Up @@ -439,11 +440,28 @@ private JsonObject getCampaignInfo() throws ParserException {
JsonObject sightInfo = new JsonObject();
for (SightType sightType : c.getSightTypeMap().values()) {
JsonObject si = new JsonObject();
si.addProperty("arc", sightType.getArc());
si.addProperty("distance", sightType.getArc());
if (sightType.getShape() == ShapeType.BEAM) {
si.addProperty("width", sightType.getWidth());
si.addProperty("offset", sightType.getOffset());
}
if (sightType.getShape() == ShapeType.CONE) {
si.addProperty("arc", sightType.getArc());
si.addProperty("offset", sightType.getOffset());
}
si.addProperty("distance", sightType.getDistance());
si.addProperty("multiplier", sightType.getMultiplier());
si.addProperty("shape", sightType.getShape().toString());
si.addProperty("type", sightType.getOffset());
si.addProperty("shape", sightType.getShape().name());
si.addProperty("scale", sightType.isScaleWithToken());

JsonArray lightList = null;
if (sightType.getPersonalLightSource() != null) {
lightList = new JsonArray();
for (Light light : sightType.getPersonalLightSource().getLightList()) {
lightList.add(gson.toJsonTree(light));
}
}
si.add("personal lights", lightList);

sightInfo.add(sightType.getName(), si);
}
cinfo.add("sight", sightInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ private Illumination getIllumination(IlluminationKey illuminationKey) {
personalLights.addAll(calculateLitAreas(token, sight.getMultiplier()));
}

if (sight.hasPersonalLightSource()) {
if (sight.getPersonalLightSource() != null) {
// Calculate the personal light area here.
// Note that a personal light is affected by its own sight's magnification, but that's it.
// Since each token is only aware of its own personal light, of course we don't want a
Expand Down
60 changes: 26 additions & 34 deletions src/main/java/net/rptools/maptool/model/CampaignProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -297,44 +297,36 @@ public String getDefaultSightType() {
return defaultSightType;
}

// @formatter:off
private static final Object[][] starter =
new Object[][] {
// Sight Type Name Dist Mult Arc LtSrc Shape Scale
{"Normal", 0.0, 1.0, 0, null, null, false},
{"Lowlight", 0.0, 2.0, 0, null, null, false},
{"Grid Vision", 0.0, 1.0, 0, null, ShapeType.GRID, true},
{"Square Vision", 0.0, 1.0, 0, null, ShapeType.SQUARE, false},
{"Normal Vision - Short Range", 10.0, 1.0, 0, null, ShapeType.CIRCLE, true},
{"Conic Vision", 0.0, 1.0, 120, null, ShapeType.CONE, false},
{"Darkvision", 0.0, 1.0, 0, null, null, true},
};

// @formatter:on

private void initSightTypeMap() {
sightTypeMap.clear();
for (Object[] row : starter) {
SightType st =

final var types =
new SightType[] {
new SightType("Normal", 0, 1.0, ShapeType.CIRCLE, 0, 0, 0, false, null),
new SightType("Lowlight", 0, 2.0, ShapeType.CIRCLE, 0, 0, 0, false, null),
new SightType("Grid Vision", 0, 1, ShapeType.GRID, 0, 0, 0, true, null),
new SightType("Square Vision", 0, 1, ShapeType.SQUARE, 0, 0, 0, false, null),
new SightType(
(String) row[0],
(Double) row[2],
(LightSource) row[4],
(ShapeType) row[5],
(Integer) row[3],
(boolean) row[6]);
st.setDistance(((Double) row[1]).floatValue());
sightTypeMap.put((String) row[0], st);
}
SightType dv = sightTypeMap.get("Darkvision");
try {
dv.setPersonalLightSource(LightSource.getDefaultLightSources().get("Generic").get(5));
// sightTypeMap.put("Darkvision & Lowlight", new SightType("Darkvision", 2,
// LightSource.getDefaultLightSources().get("Generic").get(4)));
} catch (IOException e) {
MapTool.showError("CampaignProperties.error.noGenericLight", e);
"Normal Vision - Short Range", 10, 1.0, ShapeType.CIRCLE, 0, 0, 0, true, null),
new SightType("Conic Vision", 0, 1.0, ShapeType.CONE, 0, 120, 0, false, null),
new SightType(
"Darkvision",
0,
1.0,
ShapeType.CIRCLE,
0,
0,
0,
true,
LightSource.createPersonal(
true,
List.of(new Light(ShapeType.CIRCLE, 0, 60, 0, 0, null, 100, false, false)))),
};

for (SightType st : types) {
sightTypeMap.put(st.getName(), st);
}
defaultSightType = (String) starter[0][0];
defaultSightType = types[0].getName();
}

private void initTokenTypeMap() {
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/net/rptools/maptool/model/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ public Area getShapedArea(
ShapeType shape,
Token token,
double range,
double width,
double arcAngle,
int offsetAngle,
boolean scaleWithToken) {
Expand Down Expand Up @@ -400,12 +401,9 @@ public Area getShapedArea(
if (token.getFacing() == null) {
token.setFacing(0);
}
Shape lineShape =
new Rectangle2D.Double(
0,
getSize() / -2d * Math.sin(Math.toRadians(arcAngle / 2d)),
visionRange,
getSize() * Math.sin(Math.toRadians(arcAngle / 2d)));
// Make at least 1 pixel on each side, so it's at least visible at 100% zoom.
var pixelWidth = Math.max(2, width * getSize() / zone.getUnitsPerCell());
Shape lineShape = new Rectangle2D.Double(0, -pixelWidth / 2, visionRange, pixelWidth);
Shape visibleShape = new GeneralPath(lineShape);

visibleArea =
Expand Down
9 changes: 3 additions & 6 deletions src/main/java/net/rptools/maptool/model/IsometricGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ public Area getShapedArea(
ShapeType shape,
Token token,
double range,
double width,
double arcAngle,
int offsetAngle,
boolean scaleWithToken) {
Expand Down Expand Up @@ -349,12 +350,8 @@ public Area getShapedArea(
if (token.getFacing() == null) {
token.setFacing(0);
}
Shape visibleShape =
new Rectangle2D.Double(
0,
getSize() / -2d * Math.sin(Math.toRadians(arcAngle / 2.0)),
visionRange,
getSize() * Math.sin(Math.toRadians(arcAngle / 2.0)));
var pixelWidth = Math.max(2, width * getSize() / getZone().getUnitsPerCell());
Shape visibleShape = new Rectangle2D.Double(0, -pixelWidth / 2, visionRange, pixelWidth);

// new angle, corrected for isometric view
double theta = Math.toRadians(offsetAngle) + Math.toRadians(token.getFacing());
Expand Down
18 changes: 17 additions & 1 deletion src/main/java/net/rptools/maptool/model/Light.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public final class Light implements Serializable {
private final @Nonnull ShapeType shape;
private final double facingOffset;
private final double radius;
private final double width;
private final double arcAngle;
private final @Nullable DrawablePaint paint;
private final int lumens;
Expand All @@ -37,6 +38,7 @@ public Light(
@Nonnull ShapeType shape,
double facingOffset,
double radius,
double width,
double arcAngle,
@Nullable DrawablePaint paint,
int lumens,
Expand All @@ -45,6 +47,7 @@ public Light(
this.shape = shape;
this.facingOffset = facingOffset;
this.radius = radius;
this.width = width;
this.arcAngle = (arcAngle == 0) ? 90 : arcAngle;
this.paint = paint;
this.lumens = lumens;
Expand All @@ -61,6 +64,7 @@ public Light(
shape == null ? ShapeType.CIRCLE : shape,
facingOffset,
radius,
width,
arcAngle,
paint,
lumens == 0 ? 100 : lumens,
Expand All @@ -84,6 +88,10 @@ public double getRadius() {
return radius;
}

public double getWidth() {
return width;
}

public double getArcAngle() {
return arcAngle;
}
Expand All @@ -95,7 +103,13 @@ public double getArcAngle() {
public @Nonnull Area getArea(@Nonnull Token token, @Nonnull Zone zone, boolean scaleWithToken) {
return zone.getGrid()
.getShapedArea(
getShape(), token, getRadius(), getArcAngle(), (int) getFacingOffset(), scaleWithToken);
getShape(),
token,
getRadius(),
getWidth(),
getArcAngle(),
(int) getFacingOffset(),
scaleWithToken);
}

public boolean isGM() {
Expand All @@ -111,6 +125,7 @@ public boolean isOwnerOnly() {
ShapeType.valueOf(dto.getShape().name()),
dto.getFacingOffset(),
dto.getRadius(),
dto.getWidth(),
dto.getArcAngle(),
dto.hasPaint() ? DrawablePaint.fromDto(dto.getPaint()) : null,
dto.getLumens(),
Expand All @@ -125,6 +140,7 @@ public boolean isOwnerOnly() {
}
dto.setFacingOffset(facingOffset);
dto.setRadius(radius);
dto.setWidth(width);
dto.setArcAngle(arcAngle);
dto.setShape(ShapeTypeDto.valueOf(shape.name()));
dto.setIsGm(isGM);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/net/rptools/maptool/model/LightSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public Object writeReplace() {
light.getShape(),
light.getFacingOffset(),
light.getRadius(),
light.getWidth(),
light.getArcAngle(),
light.getPaint(),
lumens == 0 ? 100 : lumens,
Expand Down
Loading
Loading