diff --git a/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/units/Unit.groovy b/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/units/Unit.groovy index 0f452544..c627c6ce 100644 --- a/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/units/Unit.groovy +++ b/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/units/Unit.groovy @@ -54,6 +54,7 @@ class Unit extends Node implements FactionColours, Rotatable, Temporal { final PalettedSprite body final PalettedSprite turret + private PalettedSprite body2 private int stateIndex = 0 private long animationStartTime private SpriteSheet spriteSheet @@ -67,7 +68,7 @@ class Unit extends Node implements FactionColours, Rotatable, Temporal { body = new UnitBody(imagesFile.width, imagesFile.height, imagesFile.numImages, palette, { _ -> return CompletableFuture.completedFuture(spriteSheet) - }) + }, unitData) addChild(body) if (unitData.shpFile.parts.turret) { @@ -81,6 +82,20 @@ class Unit extends Node implements FactionColours, Rotatable, Temporal { } } + /** + * Adds a second body to this unit. Used for special cases like the weapons + * factory where the garage door is a separate sprite file. + */ + void addBody(ImagesFile imagesFile, Palette palette, UnitData unitData) { + + body2 = new UnitBody(imagesFile, palette, unitData).tap { + name = "UnitBody2" + } +// body2.transform.translate(0, 0, -1) +// addChildBefore(body2, body) + addChild(body2) + } + /** * Return the number of degrees it takes to rotate the unit left/right in * either direction for the current state of the unit. @@ -137,6 +152,7 @@ class Unit extends Node implements FactionColours, Rotatable, Temporal { FactionColours.super.faction = faction body.faction = faction + body2?.faction = faction turret?.faction = faction } @@ -167,8 +183,18 @@ class Unit extends Node implements FactionColours, Rotatable, Temporal { */ private class UnitBody extends PalettedSprite { - UnitBody(int width, int height, int numImages, Palette palette, SpriteSheetGenerator spriteSheetGenerator) { + private final UnitData unitData + + UnitBody(ImagesFile imagesFile, Palette palette, UnitData unitData) { + + super(imagesFile, palette) + this.unitData = unitData + } + + UnitBody(int width, int height, int numImages, Palette palette, SpriteSheetGenerator spriteSheetGenerator, UnitData unitData) { + super(width, height, numImages, palette, spriteSheetGenerator) + this.unitData = unitData } @Override diff --git a/redhorizon-explorer/source/nz/net/ultraq/redhorizon/explorer/objects/Map.groovy b/redhorizon-explorer/source/nz/net/ultraq/redhorizon/explorer/objects/Map.groovy index ee4a7a5c..898cf8f6 100644 --- a/redhorizon-explorer/source/nz/net/ultraq/redhorizon/explorer/objects/Map.groovy +++ b/redhorizon-explorer/source/nz/net/ultraq/redhorizon/explorer/objects/Map.groovy @@ -61,6 +61,8 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory import groovy.json.JsonSlurper +import groovy.transform.stc.ClosureParams +import groovy.transform.stc.FromString import java.nio.ByteBuffer import java.util.concurrent.CompletableFuture @@ -542,7 +544,9 @@ class Map extends Node { */ private abstract class FactionObjects extends Node { - Unit createObject(L objectLine) { + Unit createObject(L objectLine, + @ClosureParams(value = FromString, options = 'nz.net.ultraq.redhorizon.classic.units.Unit, nz.net.ultraq.redhorizon.classic.units.UnitData') + Closure configure) { var unitImages = resourceManager.loadFile("${objectLine.type}.shp", ShpFile) var unitJson = getResourceAsText("nz/net/ultraq/redhorizon/classic/units/data/${objectLine.type.toLowerCase()}.json") @@ -550,6 +554,8 @@ class Map extends Node { return new Unit(unitImages, palette, unitData).tap { + configure(it, unitData) + // TODO: Country to faction map faction = switch (objectLine.faction) { case "Greece" -> Faction.BLUE @@ -572,7 +578,10 @@ class Map extends Node { mapFile.unitsData.eachWithIndex { unitLine, index -> try { - addChild(createObject(unitLine)) + var unit = createObject(unitLine) { unit, unitData -> + unit.name = "Vehicle - ${unitLine.faction}, ${unitLine.type}" + } + addChild(unit) } catch (IllegalArgumentException ignored) { // Ignore unknown units @@ -591,12 +600,14 @@ class Map extends Node { mapFile.infantryData.eachWithIndex { infantryLine, index -> try { - var infantry = createObject(infantryLine) - switch (infantryLine.cellPos) { - case 1 -> infantry.transform.translate(-8, 8) - case 2 -> infantry.transform.translate(8, 8) - case 3 -> infantry.transform.translate(-8, -8) - case 4 -> infantry.transform.translate(8, -8) + var infantry = createObject(infantryLine) { infantry, infantryData -> + switch (infantryLine.cellPos) { + case 1 -> infantry.transform.translate(-8, 8) + case 2 -> infantry.transform.translate(8, 8) + case 3 -> infantry.transform.translate(-8, -8) + case 4 -> infantry.transform.translate(8, -8) + } + infantry.name = "Infantry - ${infantryLine.faction}, ${infantryLine.type}" } addChild(infantry) } @@ -617,7 +628,20 @@ class Map extends Node { mapFile.structuresData.eachWithIndex { structureLine, index -> try { - var structure = createObject(structureLine) + var structure = createObject(structureLine) { structure, structureData -> + structure.name = "Structure - ${structureLine.faction}, ${structureLine.type}" + + // Push down 1 cell to account for bib placement +// structure.transform.translate(0, -TILE_HEIGHT) + + var combineWith = structureData.shpFile.parts.body.combineWith + if (combineWith) { + var combinedImages = resourceManager.loadFile("${combineWith}.shp", ShpFile) + var combinedJson = getResourceAsText("nz/net/ultraq/redhorizon/classic/units/data/${combineWith.toLowerCase()}.json") + var combinedData = new JsonSlurper().parseText(combinedJson) as UnitData + structure.addBody(combinedImages, palette, combinedData) + } + } addChild(structure) } catch (IllegalArgumentException ignored) {